From a5a4f737005258097fb46a7c746ac202575fd03e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 2 Apr 2012 22:10:00 +0200 Subject: Lua: Move module initialization code to C --- lib/mods/mods_aux.lua | 185 ---------------------------------------------- lib/mods/modules.lua | 5 -- lib/mods/theme/module.lua | 48 ------------ lib/module.lua | 36 --------- src/birth.c | 26 ++----- src/cmd4.c | 8 +- src/defines.h | 5 ++ src/dungeon.c | 16 ---- src/externs.h | 7 ++ src/init2.c | 25 ------- src/loadsave.c | 2 +- src/modules.c | 100 +++++++++++++++---------- src/skills.c | 2 +- src/tables.c | 43 +++++++++++ src/types.h | 62 ++++++++++++++++ src/variable.c | 5 ++ src/xtra2.c | 5 +- 17 files changed, 195 insertions(+), 385 deletions(-) delete mode 100644 lib/mods/mods_aux.lua delete mode 100644 lib/mods/modules.lua delete mode 100644 lib/mods/theme/module.lua delete mode 100644 lib/module.lua diff --git a/lib/mods/mods_aux.lua b/lib/mods/mods_aux.lua deleted file mode 100644 index 1562a566..00000000 --- a/lib/mods/mods_aux.lua +++ /dev/null @@ -1,185 +0,0 @@ --- Ok some functions that we dont need are dangerous ---[[ -execute = nil -getenv = nil -setlocale = nil -exit = nil -openfile = nil -writeto = nil -readfrom = nil -appendto = nil -remove = nil -rename = nil -tmpname = nil -]] -modules = {} - -current_module = nil - -function setup_module(mod) - -- For standart game, nothing needs to be done - if not mod.layout then return end - - for k, e in mod.layout do - module_reset_dir(k, e) - end -end - -function init_module(i) - setup_module(get_module(i)) -end - -function max_modules() - local i = 0 - for k, e in modules do - if type(k) == "number" and type(e) == "table" then - i = i + 1 - end - end - return i -end - -function get_module_name(j) - local i = 0 - for k, e in modules do - if type(k) == "number" and type(e) == "table" then - if i == j then return e.name end - i = i + 1 - end - end -end - -function get_module_desc(j) - local i = 0 - for k, e in modules do - if type(k) == "number" and type(e) == "table" then - if i == j then return e.desc end - i = i + 1 - end - end -end - -function get_module(j) - local i = 0 - for k, e in modules do - if type(k) == "number" and type(e) == "table" then - if i == j then return e end - i = i + 1 - end - end -end - -function find_module(name) - local i = 0 - for k, e in modules do - if type(k) == "number" and type(e) == "table" then - if name == e.name then return i end - i = i + 1 - end - end -end - -function assign_current_module(name) - current_module = get_module(find_module(name)) -end - -function get_module_info(type, subtype) - if subtype then - return current_module[type][subtype] - else - return current_module[type] - end -end - -function exec_module_info(type, ...) - return call(current_module[type], arg) -end - -function module_savefile_loadable(savefile_mod, savefile_death) - for _, e in current_module.mod_savefiles do - if e[1] == savefile_mod then - if e[2] == "all" then - return TRUE - elseif e[2] == "alive" and savefile_death == FALSE then - return TRUE - elseif e[2] == "dead" and savefile_death == TRUE then - return TRUE - end - end - end - return FALSE -end - -function scan_extra_modules() - scansubdir(ANGBAND_DIR_MODULES) - for i = 0, scansubdir_max - 1 do - if (scansubdir_result[i + 1] ~= ".") and (scansubdir_result[i + 1] ~= "..") then - local dir = path_build(ANGBAND_DIR_MODULES, scansubdir_result[i + 1]) - local file = path_build(dir, "module.lua") - if file_exist(file) == TRUE then - tome_dofile_anywhere(dir, "module.lua") - end - end - end -end - -function add_module(t) - assert(t.name, "No module name") - assert(type(t.version) == "table", "No module version") - assert(t.desc, "No module desc") - assert(t.author, "No module author") - assert(t.mod_savefiles, "No loadable savefiles module mark") - - for _, e in modules do - if type(e) == "table" and e.name == t.name then - error("Module name already defined: "..t.name) - end - end - - if type(t.author) == "string" then - t.author = { t.author, "unknown@unknown.net" } - end - - for k, e in t.mod_savefiles do - if type(e) == "string" then t.mod_savefiles[k] = { e, "all" } end - end - - if type(t.desc) == "table" then - local d = "" - for k, e in t.desc do - d = d .. e - if k < getn(t.desc) then - d = d .. "\n" - end - end - t.desc = d - end - - if not t.rand_quest then t.rand_quest = FALSE end - if not t.C_quest then t.C_quest = FALSE end - - if not t.base_dungeon then t.base_dungeon = 4 end - if not t.death_dungeon then t.death_dungeon = 28 end - - if not t.astral_dungeon then t.astral_dungeon = 8 end - if not t.astral_wild_x then t.astral_wild_x = 45 end - if not t.astral_wild_y then t.astral_wild_y = 19 end - - if not t.random_artifact_weapon_chance then - t.random_artifact_weapon_chance = 30 - end - if not t.random_artifact_armor_chance then - t.random_artifact_armor_chance = 20 - end - if not t.random_artifact_jewelry_chance then - t.random_artifact_jewelry_chance = 20 - end - - if not t.max_plev then t.max_plev = 50 end - if not t.max_skill_overage then t.max_skill_overage = 4 end - if not t.skill_per_level then t.skill_per_level = function() return 6 end end - - if not t.allow_birth then t.allow_birth = TRUE end - - tinsert(modules, t) -end diff --git a/lib/mods/modules.lua b/lib/mods/modules.lua deleted file mode 100644 index 5deddef7..00000000 --- a/lib/mods/modules.lua +++ /dev/null @@ -1,5 +0,0 @@ --- Load ToME -tome_dofile_anywhere(ANGBAND_DIR, "module.lua") - --- Look for more modules -scan_extra_modules() diff --git a/lib/mods/theme/module.lua b/lib/mods/theme/module.lua deleted file mode 100644 index cc0b6f08..00000000 --- a/lib/mods/theme/module.lua +++ /dev/null @@ -1,48 +0,0 @@ -add_module -{ - ["name"] = "Theme", - ["version"] = { 1, 2, 0 }, - ["author"] = { "furiosity", "furiosity@gmail.com" }, - ["desc"] = { - "A module that goes back to Tolkien roots, though by no means canonical.", - "A new wilderness map, new monsters, objects, artifacts, uniques, ego items,", - "terrain features, gods, races, subraces, and classes. Have fun. :-)", - }, - - ["rand_quest"] = TRUE, - ["C_quest"] = TRUE, - - ["base_dungeon"] = 4, - ["death_dungeon"] = 28, - - ["astral_dungeon"] = 8, - ["astral_wild_x"] = 45, - ["astral_wild_y"] = 19, - - ["random_artifact_weapon_chance"] = 30, - ["random_artifact_armor_chance"] = 30, - ["random_artifact_jewelry_chance"] = 30, - - ["max_plev"] = 50, - ["max_skill_overage"] = 5, - - ["mod_savefiles"]= - { - "Theme", - }, - ["layout"] = - { - ["apex"] = "theme", - ["core"] = "theme", - ["data"] = "theme", - ["dngn"] = "theme", - ["edit"] = "theme", - ["file"] = "theme", - ["help"] = "theme", - ["note"] = "theme", - ["save"] = "theme", - ["scpt"] = "theme", - ["user"] = "theme", - ["pref"] = "theme", - }, -} \ No newline at end of file diff --git a/lib/module.lua b/lib/module.lua deleted file mode 100644 index edbaa34b..00000000 --- a/lib/module.lua +++ /dev/null @@ -1,36 +0,0 @@ -add_module -{ - ["name"] = "ToME", - ["version"] = { 2, 3, 9 }, - ["author"] = { "DarkGod", "darkgod@t-o-m-e.net" }, - ["desc"] = { - "The Tales of Middle-earth, the standard and official game.", - "You are set on a quest to investigate the old tower of Dol Guldur.", - "But who knows what will happen...", - }, - - ["rand_quest"] = TRUE, - ["C_quest"] = TRUE, - - ["base_dungeon"] = 4, - ["death_dungeon"] = 28, - - ["astral_dungeon"] = 8, - ["astral_wild_x"] = 45, - ["astral_wild_y"] = 19, - - ["random_artifact_weapon_chance"] = 30, - ["random_artifact_armor_chance"] = 20, - ["random_artifact_jewelry_chance"] = 20, - - ["max_plev"] = 50, - ["max_skill_overage"] = 4, - ["skill_per_level"] = function() - return 6 - end, - - ["mod_savefiles"]= - { - "ToME", - }, -} diff --git a/src/birth.c b/src/birth.c index f073b2f6..cbe87512 100644 --- a/src/birth.c +++ b/src/birth.c @@ -1615,8 +1615,6 @@ static bool_ player_birth_aux_ask() { int i, k, n, v, sel; - s32b tmp; - int racem[100], max_racem = 0; u32b restrictions[2]; @@ -1632,8 +1630,6 @@ static bool_ player_birth_aux_ask() s16b *class_types; - s32b allow_quest; - /*** Intro ***/ /* Clear screen */ @@ -2354,23 +2350,16 @@ static bool_ player_birth_aux_ask() /* Set the recall dungeon accordingly */ - call_lua("get_module_info", "(s)", "d", "base_dungeon", &tmp); - dungeon_type = tmp; + dungeon_type = DUNGEON_BASE; p_ptr->recall_dungeon = dungeon_type; max_dlv[dungeon_type] = d_info[dungeon_type].mindepth; if (p_ptr->astral) { - s32b x, y, astral_dun; - - call_lua("get_module_info", "(s)", "d", "astral_dungeon", &astral_dun); - dungeon_type = astral_dun; - /* Somewhere in the misty mountains */ - call_lua("get_module_info", "(s)", "d", "astral_wild_x", &x); - call_lua("get_module_info", "(s)", "d", "astral_wild_y", &y); - p_ptr->wilderness_x = x; - p_ptr->wilderness_y = y; + dungeon_type = DUNGEON_ASTRAL; + p_ptr->wilderness_x = DUNGEON_ASTRAL_WILD_X; + p_ptr->wilderness_y = DUNGEON_ASTRAL_WILD_Y; } /* Clean up */ @@ -2379,8 +2368,7 @@ static bool_ player_birth_aux_ask() /*** User enters number of quests ***/ /* Heino Vander Sanden and Jimmy De Laet */ - call_lua("get_module_info", "(s)", "d", "rand_quest", &allow_quest); - if (!ironman_rooms && allow_quest) + if (!ironman_rooms) { if (do_quick_start) { @@ -2445,8 +2433,6 @@ static bool_ player_birth_aux_ask() p_ptr->inside_quest = 0; /* Init the plots */ - call_lua("get_module_info", "(s)", "d", "C_quest", &allow_quest); - if (allow_quest) { plots[PLOT_MAIN] = QUEST_NECRO; quest[plots[PLOT_MAIN]].status = QUEST_STATUS_TAKEN; @@ -3694,7 +3680,7 @@ savefile_try_again: { s32b can_use; - call_lua("module_savefile_loadable", "(s)", "d", savefile_module[k], &can_use); + can_use = module_savefile_loadable(savefile_module[k]); if (can_use) { savefile_idx[m++] = k; diff --git a/src/cmd4.c b/src/cmd4.c index c4440428..e9125d3d 100644 --- a/src/cmd4.c +++ b/src/cmd4.c @@ -2808,15 +2808,11 @@ void do_cmd_note(void) */ void do_cmd_version(void) { - cptr author, email; - - call_lua("get_module_info", "(s,d)", "s", "author", 1, &author); - call_lua("get_module_info", "(s,d)", "s", "author", 2, &email); - /* Silly message */ msg_format("You are playing %s made by %s (%s).", get_version_string(), - author, email); + modules[game_module_idx].meta.author.name, + modules[game_module_idx].meta.author.email); call_lua("patchs_display", "()", ""); } diff --git a/src/defines.h b/src/defines.h index bebe091c..344a171e 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4417,6 +4417,11 @@ #define PLOT_KHAZAD 6 #define MAX_PLOTS 7 +/* + * Modules + */ +#define MAX_MODULES 2 + /* * Hooks */ diff --git a/src/dungeon.c b/src/dungeon.c index 6d732f00..9b384dce 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -5296,22 +5296,6 @@ void play_game(bool_ new_game) /* Roll new character */ if (new_game) { - s32b ret; - - /* Are we authorized to create new chars? */ - call_lua("get_module_info", "(s)", "d", "allow_birth", &ret); - - if (!ret) - { - msg_box("Sorry, this module does not allow character creation.", -1, -1); - - /* Close stuff */ - close_game(); - - /* Quit */ - quit(NULL); - } - process_hooks(HOOK_INIT, "()"); /* The dungeon is not ready */ diff --git a/src/externs.h b/src/externs.h index 197c1c8a..c671693d 100644 --- a/src/externs.h +++ b/src/externs.h @@ -97,6 +97,7 @@ extern int cli_total; extern quest_type quest_init_tome[MAX_Q_IDX_INIT]; extern int max_body_part[BODY_MAX]; extern gf_name_type gf_names[]; +extern module_type modules[MAX_MODULES]; /* variable.c */ @@ -588,11 +589,16 @@ extern bool_ automatizer_enabled; extern s16b last_teleportation_y; extern s16b last_teleportation_x; extern cptr game_module; +extern s32b game_module_idx; extern s32b VERSION_MAJOR; extern s32b VERSION_MINOR; extern s32b VERSION_PATCH; extern s32b max_plev; +extern s32b DUNGEON_BASE; extern s32b DUNGEON_DEATH; +extern s32b DUNGEON_ASTRAL; +extern s32b DUNGEON_ASTRAL_WILD_X; +extern s32b DUNGEON_ASTRAL_WILD_Y; extern deity_type *deity_info; extern s32b max_gods; extern timer_type *gl_timers; @@ -1758,6 +1764,7 @@ extern bool_ get_lua_var(cptr name, char type, void *arg); extern void module_reset_dir(cptr dir, cptr new_path); extern cptr force_module; extern bool_ select_module(void); +extern bool_ module_savefile_loadable(cptr savefile_mod); /* lua_bind.c */ diff --git a/src/init2.c b/src/init2.c index 5239426c..222293c4 100644 --- a/src/init2.c +++ b/src/init2.c @@ -1933,15 +1933,6 @@ static void init_basic() } } -/* - * Pseudo, dummy quest initializer, to actualy disable them - */ -static bool_ quest_disable_init_hook(int q_idx) -{ - q_idx = q_idx; - return FALSE; -} - /* * Initialise misc. values @@ -1951,8 +1942,6 @@ static errr init_misc(void) int xstart = 0; int ystart = 0; int i; - s32b allow_quest; - s32b allow_rquest; /*** Prepare the various "bizarre" arrays ***/ @@ -1977,26 +1966,12 @@ static errr init_misc(void) C_COPY(powers_type, powers_type_init, POWER_MAX_INIT, power_type); /* Prepare quests */ - call_lua("get_module_info", "(s)", "d", "C_quest", &allow_quest); - call_lua("get_module_info", "(s)", "d", "rand_quest", &allow_rquest); - quest = NULL; max_q_idx = MAX_Q_IDX_INIT; reinit_quests(max_q_idx); C_COPY(quest, quest_init_tome, MAX_Q_IDX_INIT, quest_type); - /* If we dont allow C quests, we dont let them init */ - if (!allow_quest) - { - for (i = 0; i < MAX_Q_IDX_INIT; i++) - { - if (allow_rquest && (i == QUEST_RANDOM)) - continue; - quest[i].init = quest_disable_init_hook; - } - } - /* Prepare gods */ deity_info = NULL; max_gods = MAX_GODS_INIT; diff --git a/src/loadsave.c b/src/loadsave.c index 6799a502..5d43d79a 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -692,7 +692,7 @@ static bool_ do_extra(int flag) { s32b ok; - call_lua("module_savefile_loadable", "(s,d)", "d", loaded_game_module, death, &ok); + ok = module_savefile_loadable(loaded_game_module); /* Argh bad game module! */ if (!ok) diff --git a/src/modules.c b/src/modules.c index 39b41d20..5f582d92 100644 --- a/src/modules.c +++ b/src/modules.c @@ -88,7 +88,6 @@ static void dump_modules(int sel, int max) int i; char buf[40], pre = ' ', post = ')'; - cptr name; char ind; @@ -109,13 +108,11 @@ static void dump_modules(int sel, int max) post = ')'; } - call_lua("get_module_name", "(d)", "s", i, &name); - strnfmt(buf, 40, "%c%c%c %s", pre, ind, post, name); + strnfmt(buf, 40, "%c%c%c %s", pre, ind, post, modules[i].meta.name); if (sel == i) { - call_lua("get_module_desc", "(d)", "s", i, &name); - print_desc_aux(name, 5, 0); + print_desc_aux(modules[i].meta.desc, 5, 0); c_put_str(TERM_L_BLUE, buf, 10 + (i / 4), 20 * (i % 4)); } @@ -124,22 +121,23 @@ static void dump_modules(int sel, int max) } } -static void activate_module() +static void activate_module(int module_idx) { + module_type *module_ptr = &modules[module_idx]; + /* Initialize the module table */ - call_lua("assign_current_module", "(s)", "", game_module); + game_module_idx = module_idx; /* Do misc inits */ - call_lua("get_module_info", "(s)", "d", "max_plev", &max_plev); - call_lua("get_module_info", "(s)", "d", "death_dungeon", &DUNGEON_DEATH); + max_plev = module_ptr->max_plev; - call_lua("get_module_info", "(s)", "d", "random_artifact_weapon_chance", &RANDART_WEAPON); - call_lua("get_module_info", "(s)", "d", "random_artifact_armor_chance", &RANDART_ARMOR); - call_lua("get_module_info", "(s)", "d", "random_artifact_jewelry_chance", &RANDART_JEWEL); + RANDART_WEAPON = module_ptr->randarts.weapon_chance; + RANDART_ARMOR = module_ptr->randarts.armor_chance; + RANDART_JEWEL = module_ptr->randarts.jewelry_chance; - call_lua("get_module_info", "(s,d)", "d", "version", 1, &VERSION_MAJOR); - call_lua("get_module_info", "(s,d)", "d", "version", 2, &VERSION_MINOR); - call_lua("get_module_info", "(s,d)", "d", "version", 3, &VERSION_PATCH); + VERSION_MAJOR = module_ptr->meta.version.major; + VERSION_MINOR = module_ptr->meta.version.minor; + VERSION_PATCH = module_ptr->meta.version.patch; version_major = VERSION_MAJOR; version_minor = VERSION_MINOR; version_patch = VERSION_PATCH; @@ -155,6 +153,31 @@ static void activate_module() process_player_base(); } +static void init_module(module_type *module_ptr) +{ + /* Set up module directories? */ + cptr dir = module_ptr->meta.module_dir; + if (dir) { + module_reset_dir("apex", dir); + module_reset_dir("core", dir); + module_reset_dir("data", dir); + module_reset_dir("dngn", dir); + module_reset_dir("edit", dir); + module_reset_dir("file", dir); + module_reset_dir("help", dir); + module_reset_dir("note", dir); + module_reset_dir("save", dir); + module_reset_dir("scpt", dir); + module_reset_dir("user", dir); + module_reset_dir("pref", dir); + } +} + +bool_ module_savefile_loadable(cptr savefile_mod) +{ + return (strcmp(savefile_mod, modules[game_module_idx].meta.save_file_tag) == 0); +} + /* Did the player force a module on command line */ cptr force_module = NULL; @@ -166,32 +189,35 @@ bool_ select_module() /* Init some lua */ init_lua(); - /* Some ports need to separate the module scripts from the installed mods, - so we need to check for these in two different places */ - if(!tome_dofile_anywhere(ANGBAND_DIR_CORE, "mods_aux.lua", FALSE)) - tome_dofile_anywhere(ANGBAND_DIR_MODULES, "mods_aux.lua", TRUE); - if(!tome_dofile_anywhere(ANGBAND_DIR_CORE, "modules.lua", FALSE)) - tome_dofile_anywhere(ANGBAND_DIR_MODULES, "modules.lua", TRUE); - - /* Grab the savefiles */ - call_lua("max_modules", "()", "d", &max); + /* How many modules? */ + max = MAX_MODULES; /* No need to bother the player if there is only one module */ sel = -1; - if (force_module) - call_lua("find_module", "(s)", "d", force_module, &sel); - if (max == 1) + if (force_module) { + /* Find module by name */ + int i=0; + for (i=0; i= max)) continue; /* Process the module */ - call_lua("init_module", "(d)", "", x); - call_lua("get_module_name", "(d)", "s", x, &tmp); - game_module = string_make(tmp); + init_module(&modules[x]); + game_module = string_make(modules[x].meta.name); - activate_module(); + activate_module(x); return (FALSE); } diff --git a/src/skills.c b/src/skills.c index 36b4f585..9890e96d 100644 --- a/src/skills.c +++ b/src/skills.c @@ -31,7 +31,7 @@ void increase_skill(int i, s16b *invest) if (s_info[i].value >= SKILL_MAX) return; /* Cannot allocate more than player level + max_skill_overage levels */ - call_lua("get_module_info", "(s)", "d", "max_skill_overage", &max_skill_overage); + max_skill_overage = modules[game_module_idx].skills.max_skill_overage; if (((s_info[i].value + s_info[i].mod) / SKILL_STEP) >= (p_ptr->lev + max_skill_overage + 1)) { int hgt, wid; diff --git a/src/tables.c b/src/tables.c index e976e234..569acd93 100644 --- a/src/tables.c +++ b/src/tables.c @@ -4790,3 +4790,46 @@ gf_name_type gf_names[] = { GF_ATTACK, "projected melee attacks" }, { -1, NULL }, }; + +/** + * Modules + */ +module_type modules[MAX_MODULES] = +{ + { + { "ToME", + { 2, 3, 9 }, + { "DarkGod", "darkgod@t-o-m-e.net" }, + "The Tales of Middle-earth, the standard and official game.\n" + "You are set on a quest to investigate the old tower of Dol Guldur.\n" + "But who knows what will happen...", + "ToME", + NULL /* default dir */, + }, + /* Randarts: */ + { 30, 20, 20 }, + /* Max player level: */ + 50, + /* Skills: */ + { 6, 4, }, + }, + + { + { "Theme", + { 1, 2, 0 }, + { "furiosity", "furiosity@gmail.com" }, + "A module that goes back to Tolkien roots, though by no means canonical.\n" + "A new wilderness map, new monsters, objects, artifacts, uniques, ego items,\n" + "terrain features, gods, races, subraces, and classes. Have fun. :-)", + "Theme", + "theme", + }, + /* Randarts: */ + { 30, 30, 30 }, + /* Max player level: */ + 50, + /* Skill overage: */ + { 6, 5, }, + } + +}; diff --git a/src/types.h b/src/types.h index 49acb383..b5fab44e 100644 --- a/src/types.h +++ b/src/types.h @@ -2520,3 +2520,65 @@ struct ability_type s16b need_abilities[10]; /* List of prereq abilities(10 max) */ s16b forbid_abilities[10]; /* List of forbidden abilities(10 max) */ }; + +/** + * Module metadata + */ +typedef struct module_meta_type module_meta_type; +struct module_meta_type +{ + /* Module name */ + cptr name; + + /* Module version number */ + struct { + s32b major; + s32b minor; + s32b patch; + } version; + + /* Module author */ + struct { + cptr name; + cptr email; + } author; + + /* Module description */ + cptr desc; + + /* Save file tag */ + cptr save_file_tag; + + /* Module directory */ + cptr module_dir; +}; + +/** + * Modules + */ +typedef struct module_type module_type; +struct module_type +{ + /* Metadata about the module: author, description, etc. */ + module_meta_type meta; + + /* Random artifact generation chances */ + struct { + s32b weapon_chance; + s32b armor_chance; + s32b jewelry_chance; + } randarts; + + /* Max player level. */ + int max_plev; + + /* Skills */ + struct { + /* Skill points per level */ + s32b skill_per_level; + /* Maximum "overage" for skill points, i.e. how many skill + points you can go above your current level. */ + s32b max_skill_overage; + } skills; + +}; diff --git a/src/variable.c b/src/variable.c index 0eb0fadf..c00e1e42 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1564,6 +1564,7 @@ s16b last_teleportation_x = -1; * The current game module */ cptr game_module; +s32b game_module_idx; s32b VERSION_MAJOR; s32b VERSION_MINOR; s32b VERSION_PATCH; @@ -1572,7 +1573,11 @@ s32b VERSION_PATCH; * Some module info */ s32b max_plev = 50; +s32b DUNGEON_BASE = 4; s32b DUNGEON_DEATH = 28; +s32b DUNGEON_ASTRAL = 8; +s32b DUNGEON_ASTRAL_WILD_X = 45; +s32b DUNGEON_ASTRAL_WILD_Y = 19; /* * Gods diff --git a/src/xtra2.c b/src/xtra2.c index 70978e47..45a0caec 100644 --- a/src/xtra2.c +++ b/src/xtra2.c @@ -2037,11 +2037,8 @@ void check_experience(void) if (p_ptr->skill_last_level < p_ptr->lev) { - s32b pts; - call_lua("exec_module_info", "(s)", "d", "skill_per_level", &pts); - p_ptr->skill_last_level = p_ptr->lev; - p_ptr->skill_points += pts; + p_ptr->skill_points += modules[game_module_idx].skills.skill_per_level; cmsg_format(TERM_L_GREEN, "You can increase %d more skills.", p_ptr->skill_points); p_ptr->redraw |= PR_STUDY; } -- cgit v1.2.3 From 65a41a0ef06a606927a6b2866e0172f0d5c98e11 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 2 Apr 2012 22:10:00 +0200 Subject: Lua: Move "outfit player" code to C. --- lib/mods/theme/scpt/player.lua | 177 ----------------------------------------- lib/scpt/player.lua | 61 -------------- src/birth.c | 169 ++++++++++++++++++++++++++++++++++++--- src/cmd5.c | 2 +- src/defines.h | 2 + src/externs.h | 2 +- 6 files changed, 160 insertions(+), 253 deletions(-) diff --git a/lib/mods/theme/scpt/player.lua b/lib/mods/theme/scpt/player.lua index fd11ed9d..de04052d 100644 --- a/lib/mods/theme/scpt/player.lua +++ b/lib/mods/theme/scpt/player.lua @@ -6,88 +6,6 @@ function __birth_hook_objects() -- Grace delay for adding piety GRACE_DELAY = 0 - -- Provide a book of Geyser to Geomancers - if get_class_name() == "Geomancer" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Geyser") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - - -- Provide a book of prayer to priests - if get_class_name() == "Priest(Eru)" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("See the Music") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - if get_class_name() == "Priest(Manwe)" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Manwe's Blessing") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - if get_class_name() == "Druid" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Charm Animal") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - if get_class_name() == "Dark-Priest" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Curse") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - if get_class_name() == "Paladin" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Divine Aim") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - if get_class_name() == "Stonewright" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Firebrand") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - if get_class_name() == "Priest(Varda)" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Light of Valinor") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - if get_class_name() == "Priest(Ulmo)" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Song of Belegaer") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - if get_class_name() == "Priest(Mandos)" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Tears of Luthien") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - - if get_class_name() == "Mimic" then - local obj = create_object(TV_CLOAK, 100); - obj.pval2 = resolve_mimic_name("Mouse") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - -- Start the undeads, as undeads with the corruptions if get_subrace_name() == "Vampire" then player.corruption(CORRUPT_VAMPIRE_TEETH, TRUE) @@ -95,101 +13,6 @@ function __birth_hook_objects() player.corruption(CORRUPT_VAMPIRE_VAMPIRE, TRUE) end - -- Start the Red (Fire) dragons with a book of Light (Theme) - if get_subrace_name() == "Red" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Globe of Light") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - - -- Start the Black (Water) dragons with a book of Geyser (Theme) - if get_subrace_name() == "Black" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Geyser") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - - -- Start the Green (Air) dragons with a book of Noxious Cloud (Theme) - if get_subrace_name() == "Green" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Noxious Cloud") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - - -- Start the Blue (Earth) dragons with a book of Stone Skin (Theme) - if get_subrace_name() == "Blue" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Stone Skin") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - - -- Start the White dragons with a book of Sense Monsters (Theme) - if get_subrace_name() == "White" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Sense Monsters") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - - -- Start the Ethereal dragons with a book of Recharge (Theme) - if get_subrace_name() == "Ethereal" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Recharge") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - - -- Start the Aewroeg with a book of Charm (Theme) - if get_subrace_name() == "(Aewrog)" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Charm") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - - -- Start the Narroeg with a book of blink (Theme) - if get_subrace_name() == "(Narrog)" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Phase Door") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - - -- Start the Peace-mages with a book of blink (Theme) - if get_class_name() == "Peace-mage" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Phase Door") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - - -- Start the Wainriders with a book of Curse (Theme) - if get_class_name() == "Wainrider" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Curse") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - - -- Provide everyone with a scroll of WoR (Theme) - local obj = create_object(TV_SCROLL, SV_SCROLL_WORD_OF_RECALL); - inven_carry(obj, FALSE) - end_object(obj) - identify_pack_fully() end -- Register in the hook list diff --git a/lib/scpt/player.lua b/lib/scpt/player.lua index 2a617608..e8fb7e25 100644 --- a/lib/scpt/player.lua +++ b/lib/scpt/player.lua @@ -2,67 +2,6 @@ ----------------------- Hook to create birth objects ------------------------- ------------------------------------------------------------------------------ function __birth_hook_objects() - -- Provide a book of blink to rangers - if get_class_name() == "Ranger" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Phase Door") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - - -- Provide a book of Geyser to Geomancers - if get_class_name() == "Geomancer" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Geyser") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - - -- Provide a book of prayer to priests - if get_class_name() == "Priest(Eru)" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("See the Music") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - if get_class_name() == "Priest(Manwe)" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Manwe's Blessing") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - if get_class_name() == "Druid" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Charm Animal") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - if get_class_name() == "Dark-Priest" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Curse") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - if get_class_name() == "Paladin" then - local obj = create_object(TV_BOOK, 255); - obj.pval = find_spell("Divine Aim") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end - if get_class_name() == "Mimic" then - local obj = create_object(TV_CLOAK, 100); - obj.pval2 = resolve_mimic_name("Mouse") - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - end -- Start the undeads, as undeads with the corruptions if get_subrace_name() == "Vampire" then diff --git a/src/birth.c b/src/birth.c index cbe87512..263877fe 100644 --- a/src/birth.c +++ b/src/birth.c @@ -1082,6 +1082,35 @@ void outfit_obj(int tv, int sv, int pval, int dd, int ds) } +/* + * Give the player an object. + */ +static void player_outfit_object(int qty, int tval, int sval) +{ + object_type forge; + object_type *q_ptr = &forge; + object_prep(q_ptr, lookup_kind(tval, sval)); + q_ptr->number = qty; + object_aware(q_ptr); + object_known(q_ptr); + (void)inven_carry(q_ptr, FALSE); +} + + +/* + * Give player a spell book. + */ +static void player_outfit_spellbook(cptr spell_name) +{ + object_type forge; + object_type *q_ptr = &forge; + object_prep(q_ptr, lookup_kind(TV_BOOK, 255)); + q_ptr->pval = find_spell(spell_name); + q_ptr->ident |= IDENT_MENTAL | IDENT_KNOWN; + inven_carry(q_ptr, FALSE); +} + + /* * Init players with some belongings * @@ -1090,33 +1119,147 @@ void outfit_obj(int tv, int sv, int pval, int dd, int ds) static void player_outfit(void) { int i; + cptr class_name = spp_ptr->title + c_name; + cptr subrace_name = rmp_ptr->title + rmp_name; /* * Get an adventurer guide describing a bit of the * wilderness. */ { - object_type forge; - object_type *q_ptr = &forge; /* Hack -- Give the player an adventurer guide */ - object_prep(q_ptr, lookup_kind(TV_PARCHMENT, 20)); - q_ptr->number = 1; - object_aware(q_ptr); - object_known(q_ptr); - (void)inven_carry(q_ptr, FALSE); + player_outfit_object(1, TV_PARCHMENT, 20); } - process_hooks(HOOK_BIRTH_OBJECTS, "()"); + /* + * Provide spell books + */ + if (game_module_idx == MODULE_TOME) + { + if (streq(class_name, "Ranger")) + { + player_outfit_spellbook("Phase Door"); + } + } + if (streq(class_name, "Geomancer")) + { + player_outfit_spellbook("Geyser"); + } + if (streq(class_name, "Priest(Eru)")) + { + player_outfit_spellbook("See the Music"); + } + if (streq(class_name, "Priest(Manwe)")) + { + player_outfit_spellbook("Manwe's Blessing"); + } + if (streq(class_name, "Druid")) + { + player_outfit_spellbook("Charm Animal"); + } + if (streq(class_name, "Dark-Priest")) + { + player_outfit_spellbook("Curse"); + } + if (streq(class_name, "Paladin")) + { + player_outfit_spellbook("Divine Aim"); + } + if (game_module_idx == MODULE_THEME) + { + /* Priests */ + if (streq(class_name, "Stonewright")) + { + player_outfit_spellbook("Firebrand"); + } + if (streq(class_name, "Priest(Varda)")) + { + player_outfit_spellbook("Light of Valinor"); + } + if (streq(class_name, "Priest(Ulmo)")) + { + player_outfit_spellbook("Song of Belegaer"); + } + if (streq(class_name, "Priest(Mandos)")) + { + player_outfit_spellbook("Tears of Luthien"); + } + + /* Dragons */ + if (streq(subrace_name, "Red")) + { + player_outfit_spellbook("Globe of Light"); + } + if (streq(subrace_name, "Black")) + { + player_outfit_spellbook("Geyser"); + } + if (streq(subrace_name, "Green")) + { + player_outfit_spellbook("Noxious Cloud"); + } + if (streq(subrace_name, "Blue")) + { + player_outfit_spellbook("Stone Skin"); + } + if (streq(subrace_name, "White")) + { + player_outfit_spellbook("Sense Monsters"); + } + if (streq(subrace_name, "Ethereal")) + { + player_outfit_spellbook("Recharge"); + } + + /* Demons */ + if (streq(subrace_name, "(Aewrog)")) + { + player_outfit_spellbook("Charm"); + } + if (streq(subrace_name, "(Narrog)")) + { + player_outfit_spellbook("Phase Door"); + } + + /* Peace-mages */ + if (streq(class_name, "Peace-mage")) + { + player_outfit_spellbook("Phase Door"); + } + /* Wainriders */ + if (streq(class_name, "Wainrider")) + { + player_outfit_spellbook("Curse"); + } + } + + if (streq(class_name, "Mimic")) { object_type forge; object_type *q_ptr = &forge; + + object_prep(q_ptr, lookup_kind(TV_CLOAK, SV_MIMIC_CLOAK)); + q_ptr->pval2 = resolve_mimic_name("Mouse"); + q_ptr->ident |= IDENT_MENTAL | IDENT_KNOWN; + inven_carry(q_ptr, FALSE); + } + + if (game_module_idx == MODULE_THEME) + { + /* Give everyone a scroll of WoR. */ + player_outfit_object(1, TV_SCROLL, SV_SCROLL_WORD_OF_RECALL); + + /* Identify everything in pack. */ + identify_pack_fully(); + } + + process_hooks(HOOK_BIRTH_OBJECTS, "()"); + + { /* Hack -- Give the player some food */ - object_prep(q_ptr, lookup_kind(TV_FOOD, SV_FOOD_RATION)); - q_ptr->number = (byte)rand_range(3, 7); - object_aware(q_ptr); - object_known(q_ptr); - (void)inven_carry(q_ptr, FALSE); + int qty = (byte)rand_range(3, 7); + player_outfit_object(qty, TV_FOOD, SV_FOOD_RATION); } { diff --git a/src/cmd5.c b/src/cmd5.c index b415b166..847c279b 100644 --- a/src/cmd5.c +++ b/src/cmd5.c @@ -2538,7 +2538,7 @@ void do_cmd_copy_spell() /* * Finds a spell by name, optimized for speed */ -int find_spell(char *name) +int find_spell(const char *name) { int oldtop, spell; oldtop = lua_gettop(L); diff --git a/src/defines.h b/src/defines.h index 344a171e..a75df305 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4420,6 +4420,8 @@ /* * Modules */ +#define MODULE_TOME 0 +#define MODULE_THEME 1 #define MAX_MODULES 2 /* diff --git a/src/externs.h b/src/externs.h index c671693d..a9baa853 100644 --- a/src/externs.h +++ b/src/externs.h @@ -811,7 +811,7 @@ extern s32b get_school_spell(cptr do_what, cptr check_fct, s16b force_book); extern void do_cmd_copy_spell(void); extern void cast_school_spell(void); extern void browse_school_spell(int book, int pval, object_type *o_ptr); -extern int find_spell(char *name); +extern int find_spell(const char *name); extern bool_ is_school_book(object_type *o_ptr); /* cmd6.c */ -- cgit v1.2.3 From 3215bb6521aca21af4d48f0598e1322ef8d8773c Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 2 Apr 2012 22:10:00 +0200 Subject: Lua: Move Bounty Hunter quest to C --- lib/mods/theme/scpt/bounty.lua | 90 --------------------------------- lib/mods/theme/scpt/init.lua | 1 - lib/scpt/bounty.lua | 90 --------------------------------- lib/scpt/init.lua | 1 - src/bldg.c | 12 +++++ src/defines.h | 5 +- src/plots.c | 3 ++ src/plots.h | 6 +++ src/q_bounty.c | 111 +++++++++++++++++++++++++++++++++++++++++ src/quest.pkg | 9 ---- src/tables.c | 17 +++++++ src/variable.c | 2 +- 12 files changed, 154 insertions(+), 193 deletions(-) delete mode 100644 lib/mods/theme/scpt/bounty.lua delete mode 100644 lib/scpt/bounty.lua create mode 100644 src/q_bounty.c diff --git a/lib/mods/theme/scpt/bounty.lua b/lib/mods/theme/scpt/bounty.lua deleted file mode 100644 index 94c15598..00000000 --- a/lib/mods/theme/scpt/bounty.lua +++ /dev/null @@ -1,90 +0,0 @@ --- The bounty quest! bring back corpses to increase your monster lore skill - -add_quest -{ - ["global"] = "BOUNTY_QUEST", - ["name"] = "Bounty quest", - ["desc"] = function() - if quest(BOUNTY_QUEST).status == QUEST_STATUS_TAKEN then - print_hook("#####yBounty quest!\n") - print_hook("You must bring back "..monster_race_desc(bounty_quest_monster, 0).." corpse to the beastmaster.\n") - print_hook("\n") - end - end, - ["level"] = -1, - ["data"] = { - ["bounty_quest_monster"] = 0, - }, - ["hooks"] = { - -- Start the game without the quest, need to request it - [HOOK_BIRTH_OBJECTS] = function() - quest(BOUNTY_QUEST).status = QUEST_STATUS_UNTAKEN - end, - }, -} - -add_building_action -{ - -- Index is used in ba_info.txt to set the actions - ["index"] = 54, - ["action"] = function() - if quest(BOUNTY_QUEST).status == QUEST_STATUS_UNTAKEN then - quest(BOUNTY_QUEST).status = QUEST_STATUS_TAKEN - bounty_quest_monster = get_new_bounty_monster(3 + ((player.lev * 3) / 2)) - - msg_print("You must bring me back "..monster_race_desc(bounty_quest_monster, 0).." corpse.") - else - msg_print("You still must bring me back "..monster_race_desc(bounty_quest_monster, 0).." corpse.") - end - end -} - -add_building_action -{ - -- Index is used in ba_info.txt to set the actions - ["index"] = 55, - ["action"] = function() - if quest(BOUNTY_QUEST).status == QUEST_STATUS_TAKEN then - local ret, item - - -- Ask for an item - ret, item = get_item("What corpse to return?", - "You have no corpse to return.", - bor(USE_INVEN), - function (obj) - if (obj.tval == TV_CORPSE) and (obj.pval2 == bounty_quest_monster) then - return TRUE - end - return FALSE - end - ) - - -- Ok we got the corpse! - if ret == TRUE then - -- Take the corpse from the inventory - inven_item_increase(item, -1) - inven_item_optimize(item) - - msg_print("Ah well done adventurer!") - msg_print("As a reward I will teach you a bit of monster lore.") - - if skill(SKILL_LORE).mod == 0 then - skill(SKILL_LORE).mod = 900 - skill(SKILL_LORE).dev = TRUE - end - skill(SKILL_LORE).value = skill(SKILL_LORE).value + skill(SKILL_LORE).mod - if skill(SKILL_PRESERVATION).mod == 0 then - skill(SKILL_PRESERVATION).value = 800 - skill(SKILL_PRESERVATION).mod = 800 - skill(SKILL_PRESERVATION).dev = TRUE - msg_print("I see you don't know the corpse preservation skill, I shall teach you it too.") - end - - quest(BOUNTY_QUEST).status = QUEST_STATUS_UNTAKEN - bounty_quest_monster = 0 - end - else - msg_print("You do not have any bounty quest yet.") - end - end -} diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index 958d8f7d..19649da7 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -31,7 +31,6 @@ tome_dofile("gods_new.lua") tome_dofile("spells.lua") -- Add some quests -tome_dofile("bounty.lua") tome_dofile("god.lua") tome_dofile("fireprof.lua") tome_dofile("library.lua") diff --git a/lib/scpt/bounty.lua b/lib/scpt/bounty.lua deleted file mode 100644 index 94c15598..00000000 --- a/lib/scpt/bounty.lua +++ /dev/null @@ -1,90 +0,0 @@ --- The bounty quest! bring back corpses to increase your monster lore skill - -add_quest -{ - ["global"] = "BOUNTY_QUEST", - ["name"] = "Bounty quest", - ["desc"] = function() - if quest(BOUNTY_QUEST).status == QUEST_STATUS_TAKEN then - print_hook("#####yBounty quest!\n") - print_hook("You must bring back "..monster_race_desc(bounty_quest_monster, 0).." corpse to the beastmaster.\n") - print_hook("\n") - end - end, - ["level"] = -1, - ["data"] = { - ["bounty_quest_monster"] = 0, - }, - ["hooks"] = { - -- Start the game without the quest, need to request it - [HOOK_BIRTH_OBJECTS] = function() - quest(BOUNTY_QUEST).status = QUEST_STATUS_UNTAKEN - end, - }, -} - -add_building_action -{ - -- Index is used in ba_info.txt to set the actions - ["index"] = 54, - ["action"] = function() - if quest(BOUNTY_QUEST).status == QUEST_STATUS_UNTAKEN then - quest(BOUNTY_QUEST).status = QUEST_STATUS_TAKEN - bounty_quest_monster = get_new_bounty_monster(3 + ((player.lev * 3) / 2)) - - msg_print("You must bring me back "..monster_race_desc(bounty_quest_monster, 0).." corpse.") - else - msg_print("You still must bring me back "..monster_race_desc(bounty_quest_monster, 0).." corpse.") - end - end -} - -add_building_action -{ - -- Index is used in ba_info.txt to set the actions - ["index"] = 55, - ["action"] = function() - if quest(BOUNTY_QUEST).status == QUEST_STATUS_TAKEN then - local ret, item - - -- Ask for an item - ret, item = get_item("What corpse to return?", - "You have no corpse to return.", - bor(USE_INVEN), - function (obj) - if (obj.tval == TV_CORPSE) and (obj.pval2 == bounty_quest_monster) then - return TRUE - end - return FALSE - end - ) - - -- Ok we got the corpse! - if ret == TRUE then - -- Take the corpse from the inventory - inven_item_increase(item, -1) - inven_item_optimize(item) - - msg_print("Ah well done adventurer!") - msg_print("As a reward I will teach you a bit of monster lore.") - - if skill(SKILL_LORE).mod == 0 then - skill(SKILL_LORE).mod = 900 - skill(SKILL_LORE).dev = TRUE - end - skill(SKILL_LORE).value = skill(SKILL_LORE).value + skill(SKILL_LORE).mod - if skill(SKILL_PRESERVATION).mod == 0 then - skill(SKILL_PRESERVATION).value = 800 - skill(SKILL_PRESERVATION).mod = 800 - skill(SKILL_PRESERVATION).dev = TRUE - msg_print("I see you don't know the corpse preservation skill, I shall teach you it too.") - end - - quest(BOUNTY_QUEST).status = QUEST_STATUS_UNTAKEN - bounty_quest_monster = 0 - end - else - msg_print("You do not have any bounty quest yet.") - end - end -} diff --git a/lib/scpt/init.lua b/lib/scpt/init.lua index a6f3f8ab..8b288f17 100644 --- a/lib/scpt/init.lua +++ b/lib/scpt/init.lua @@ -30,7 +30,6 @@ tome_dofile("spells.lua") tome_dofile("gods.lua") -- Add some quests -tome_dofile("bounty.lua") tome_dofile("god.lua") tome_dofile("fireprof.lua") tome_dofile("library.lua") diff --git a/src/bldg.c b/src/bldg.c index 48e94e9f..1845e838 100644 --- a/src/bldg.c +++ b/src/bldg.c @@ -2030,6 +2030,18 @@ bool_ bldg_process_command(store_type *s_ptr, int i) break; } + case BACT_DROP_ITEM: + { + quest_bounty_drop_item(); + break; + } + + case BACT_GET_ITEM: + { + quest_bounty_get_item(); + break; + } + default: { if (process_hooks_ret(HOOK_BUILDING_ACTION, "dd", "(d)", bact)) diff --git a/src/defines.h b/src/defines.h index a75df305..1569012b 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4039,6 +4039,8 @@ #define BACT_REQUEST_ITEM 51 #define BACT_GET_LOAN 52 #define BACT_PAY_BACK_LOAN 53 +#define BACT_DROP_ITEM 54 +#define BACT_GET_ITEM 55 /* If one adds new BACT_ do NOT forget to increase max_bact in variables.c */ @@ -4406,7 +4408,8 @@ #define QUEST_DRAGONS 23 #define QUEST_HAUNTED 24 #define QUEST_EVIL 25 -#define MAX_Q_IDX_INIT 26 +#define QUEST_BOUNTY 26 +#define MAX_Q_IDX_INIT 27 #define PLOT_MAIN 0 #define PLOT_BREE 1 diff --git a/src/plots.c b/src/plots.c index 53d3e1bc..2fb1cbb1 100644 --- a/src/plots.c +++ b/src/plots.c @@ -471,3 +471,6 @@ bool_ quest_null_hook(int q) /*************************** Other plot ***************************/ #include "q_narsil.c" #include "q_thrain.c" + +/*************************** Bounty Quest *************************/ +#include "q_bounty.c" diff --git a/src/plots.h b/src/plots.h index a1a11e6c..903ffcef 100644 --- a/src/plots.h +++ b/src/plots.h @@ -46,3 +46,9 @@ extern bool_ quest_evil_init_hook(int q_idx); /******* Plot Other *********/ extern bool_ quest_narsil_init_hook(int q_idx); extern bool_ quest_thrain_init_hook(int q_idx); + +/******* Plot Bounty Quest ********/ +extern bool_ quest_bounty_init_hook(int q_idx); +extern bool_ quest_bounty_drop_item(); +extern bool_ quest_bounty_get_item(); +extern bool_ quest_bounty_describe(FILE *fff); diff --git a/src/q_bounty.c b/src/q_bounty.c new file mode 100644 index 00000000..01b119be --- /dev/null +++ b/src/q_bounty.c @@ -0,0 +1,111 @@ +#undef cquest +#define cquest (quest[QUEST_BOUNTY]) + +#define bounty_quest_monster (cquest.data[0]) + +static bool_ bounty_item_tester_hook(object_type *o_ptr) +{ + if ((o_ptr->tval == TV_CORPSE) && (o_ptr->pval2 == bounty_quest_monster)) + { + return TRUE; + } + else + { + return FALSE; + } +} + +bool_ quest_bounty_init_hook(int dummy) +{ + return FALSE; +} + +bool_ quest_bounty_drop_item() +{ + char mdesc[512]; + char msg[512]; + + if (cquest.status == QUEST_STATUS_UNTAKEN) + { + cquest.status = QUEST_STATUS_TAKEN; + bounty_quest_monster = lua_get_new_bounty_monster(3 + (p_ptr->lev * 3) / 2); + + monster_race_desc(mdesc, bounty_quest_monster, 0); + snprintf(msg, sizeof(msg), "You must bring me back %s corpse.", mdesc); + msg_print(msg); + } + else + { + monster_race_desc(mdesc, bounty_quest_monster, 0); + snprintf(msg, sizeof(msg), "You still must bring me back %s corpse.", mdesc); + msg_print(msg); + } + return FALSE; +} + +bool_ quest_bounty_get_item() +{ + if (cquest.status != QUEST_STATUS_TAKEN) + { + msg_print("You do not have any bounty quest yet."); + return FALSE; + } + + // Get the corpse. + item_tester_hook = bounty_item_tester_hook; + int item = -1; + bool_ ret = + get_item(&item, + "What corpse to return?", + "You have no corpse to return.", + USE_INVEN); + if (!ret) { + return FALSE; + } + + // Take the corpse from the inventory + inven_item_increase(item, -1); + inven_item_optimize(item); + + msg_print("Ah well done adventurer!"); + msg_print("As a reward I will teach you a bit of monster lore."); + + skill_type *lore = &s_info[SKILL_LORE]; + skill_type *preservation = &s_info[SKILL_PRESERVATION]; + + if (lore->mod == 0) { + lore->mod = 900; + lore->dev = TRUE; + } + lore->value += lore->mod; + + if (preservation->mod == 0) { + preservation->value = 800; + preservation->mod = 800; + preservation->dev = TRUE; + msg_print("I see you don't know the corpse preservation skill, I shall teach you it too."); + } + + // Need to ask for new quest. + cquest.status = QUEST_STATUS_UNTAKEN; + bounty_quest_monster = 0; + return FALSE; +} + +bool_ quest_bounty_describe(FILE *fff) +{ + char mdesc[512]; + + if (cquest.status == QUEST_STATUS_TAKEN) + { + monster_race_desc(mdesc, bounty_quest_monster, 0); + + fprintf(fff, "#####yBounty quest!\n"); + fprintf(fff, "You must bring back %s corpse to the beastmaster.\n", mdesc); + fprintf(fff, "\n"); + + return TRUE; + } + + return FALSE; +} diff --git a/src/quest.pkg b/src/quest.pkg index 4ba93b7a..487c62af 100644 --- a/src/quest.pkg +++ b/src/quest.pkg @@ -159,12 +159,3 @@ extern s16b add_new_quest @ new_quest(char *name); * @note (see file lua_bind.c) */ extern void desc_quest @ quest_desc(int q_idx, int d, char *desc); - -/** @fn get_new_bounty_monster(int lev); - * @brief Find a good random bounty monster.\n - * @param lev Number \n the level of the bounty monster. - * @brief Monster level - * @return Number \n The index of the monster in the r_info array. - * @note (see file lua_bind.c) - */ -extern int lua_get_new_bounty_monster@get_new_bounty_monster(int lev); diff --git a/src/tables.c b/src/tables.c index 569acd93..e7a81f11 100644 --- a/src/tables.c +++ b/src/tables.c @@ -4248,6 +4248,23 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] = {0, 0}, NULL, }, + /* Bounty */ + { + FALSE, + TRUE, + "Bounty quest", + { + "", /* dynamic desc */ + }, + QUEST_STATUS_UNTAKEN, + -1, + NULL, + HOOK_TYPE_C, + quest_bounty_init_hook, + {0, 0, 0, 0}, + quest_bounty_describe, + }, + }; diff --git a/src/variable.c b/src/variable.c index c00e1e42..c6a23758 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1537,7 +1537,7 @@ int cli_total = 0; /* * max_bact, only used so that lua scripts can add new bacts without worrying about the numbers */ -int max_bact = 54; +int max_bact = 56; /* * Max corruptions -- cgit v1.2.3 From 9ed872694d590996117dd936318e917f55ff6da0 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 2 Apr 2012 22:10:00 +0200 Subject: Lua: Move "Library" quest monster placement code to C --- lib/mods/theme/scpt/library.lua | 74 ++--------------------------------------- lib/scpt/library.lua | 74 ++--------------------------------------- src/plots.c | 3 ++ src/plots.h | 3 ++ src/q_library.c | 53 +++++++++++++++++++++++++++++ src/util.pkg | 2 ++ 6 files changed, 65 insertions(+), 144 deletions(-) create mode 100644 src/q_library.c diff --git a/lib/mods/theme/scpt/library.lua b/lib/mods/theme/scpt/library.lua index a16d37ef..4a8b03c4 100644 --- a/lib/mods/theme/scpt/library.lua +++ b/lib/mods/theme/scpt/library.lua @@ -4,13 +4,6 @@ library_quest = {} --- Map helper -library_quest.place_random = function(minY, minX, maxY, maxX, monster) - y = randint(maxY - minY + 1) + minY - x = randint(maxX - minX + 1) + minX - return place_monster_one(y, x, monster, 0, TRUE, MSTATUS_ENEMY) -end - -- Book creation helpers library_quest.bookable_spells = { @@ -278,71 +271,8 @@ add_quest load_map("library.map", 2, 2) level_flags2 = DF2_NO_GENO - -- generate the Liches 518 - liches = damroll(4, 2) -- plus one on the map - while(liches > 0) do - if 0 < library_quest.place_random(4, 4, 14, 37, 518) then - liches = liches - 1 - end - end - - -- generate the Monastic liches 611 - liches = damroll(1, 2) - while(liches > 0) do - if 0 < library_quest.place_random(14, 34, 37, 67, 611) then - liches = liches - 1 - end - end - - -- generate more Monastic liches 611 - liches = damroll(1, 2) - 1 - while(liches > 0) do - if 0 < library_quest.place_random(4, 34, 14, 67, 611) then - liches = liches - 1 - end - end - - -- generate even more Monastic liches 611 - liches = damroll(1, 2) - 1 - while(liches > 0) do - if 0 < library_quest.place_random(14, 4, 37, 34, 611) then - liches = liches - 1 - end - end - - -- Flesh golem 256 - golems = 2 - while(golems > 0) do - if 0 < library_quest.place_random(10, 10, 37, 67, 256) then - golems = golems - 1 - end - end - - -- Clay golem 261 - golems = 2 - while(golems > 0) do - if 0 < library_quest.place_random(10, 10, 37, 67, 261) then - golems = golems - 1 - end - end - - -- Iron golem 367 - golems = 2 - while(golems > 0) do - if 0 < library_quest.place_random(10, 10, 37, 67, 367) then - golems = golems - 1 - end - end - - -- Mithril Golem 464 - golems = 1 - while(golems > 0) do - if 0 < library_quest.place_random(10, 10, 37, 67, 464) then - golems = golems - 1 - end - end - - -- one Master lich is on the map + -- generate monsters + quest_library_gen_hook() return TRUE end, diff --git a/lib/scpt/library.lua b/lib/scpt/library.lua index 1433e47f..58e36556 100644 --- a/lib/scpt/library.lua +++ b/lib/scpt/library.lua @@ -4,13 +4,6 @@ library_quest = {} --- Map helper -library_quest.place_random = function(minY, minX, maxY, maxX, monster) - y = randint(maxY - minY + 1) + minY - x = randint(maxX - minX + 1) + minX - return place_monster_one(y, x, monster, 0, TRUE, MSTATUS_ENEMY) -end - -- Book creation helpers library_quest.bookable_spells = { @@ -275,71 +268,8 @@ add_quest load_map("library.map", 2, 2) level_flags2 = DF2_NO_GENO - -- generate the Liches 518 - liches = damroll(4, 2) -- plus one on the map - while(liches > 0) do - if 0 < library_quest.place_random(4, 4, 14, 37, 518) then - liches = liches - 1 - end - end - - -- generate the Monastic liches 611 - liches = damroll(1, 2) - while(liches > 0) do - if 0 < library_quest.place_random(14, 34, 37, 67, 611) then - liches = liches - 1 - end - end - - -- generate more Monastic liches 611 - liches = damroll(1, 2) - 1 - while(liches > 0) do - if 0 < library_quest.place_random(4, 34, 14, 67, 611) then - liches = liches - 1 - end - end - - -- generate even more Monastic liches 611 - liches = damroll(1, 2) - 1 - while(liches > 0) do - if 0 < library_quest.place_random(14, 4, 37, 34, 611) then - liches = liches - 1 - end - end - - -- Flesh golem 256 - golems = 2 - while(golems > 0) do - if 0 < library_quest.place_random(10, 10, 37, 67, 256) then - golems = golems - 1 - end - end - - -- Clay golem 261 - golems = 2 - while(golems > 0) do - if 0 < library_quest.place_random(10, 10, 37, 67, 261) then - golems = golems - 1 - end - end - - -- Iron golem 367 - golems = 2 - while(golems > 0) do - if 0 < library_quest.place_random(10, 10, 37, 67, 367) then - golems = golems - 1 - end - end - - -- Mithril Golem 464 - golems = 1 - while(golems > 0) do - if 0 < library_quest.place_random(10, 10, 37, 67, 464) then - golems = golems - 1 - end - end - - -- one Master lich is on the map + -- generate monsters + quest_library_gen_hook() return TRUE end, diff --git a/src/plots.c b/src/plots.c index 2fb1cbb1..b26d1e20 100644 --- a/src/plots.c +++ b/src/plots.c @@ -474,3 +474,6 @@ bool_ quest_null_hook(int q) /*************************** Bounty Quest *************************/ #include "q_bounty.c" + +/************************** Library Quest *************************/ +#include "q_library.c" diff --git a/src/plots.h b/src/plots.h index 903ffcef..2d78ee02 100644 --- a/src/plots.h +++ b/src/plots.h @@ -52,3 +52,6 @@ extern bool_ quest_bounty_init_hook(int q_idx); extern bool_ quest_bounty_drop_item(); extern bool_ quest_bounty_get_item(); extern bool_ quest_bounty_describe(FILE *fff); + +/******* Plot Library Quest *******/ +extern void quest_library_gen_hook(); diff --git a/src/q_library.c b/src/q_library.c new file mode 100644 index 00000000..edb1698f --- /dev/null +++ b/src/q_library.c @@ -0,0 +1,53 @@ +#undef cquest + +#define MONSTER_LICH 518 +#define MONSTER_MONASTIC_LICH 611 +#define MONSTER_FLESH_GOLEM 256 +#define MONSTER_CLAY_GOLEM 261 +#define MONSTER_IRON_GOLEM 367 +#define MONSTER_MITHRIL_GOLEM 464 + +static s16b library_quest_place_random(int minY, int minX, int maxY, int maxX, int r_idx) +{ + int y = randint(maxY - minY + 1) + minY; + int x = randint(maxX - minX + 1) + minX; + return place_monster_one(y, x, r_idx, 0, TRUE, MSTATUS_ENEMY); +} + +static void library_quest_place_nrandom(int minY, int minX, int maxY, int maxX, int r_idx, int n) +{ + while(n > 0) + { + if (0 < library_quest_place_random(minY, minX, maxY, maxX, r_idx)) + { + n--; + } + } +} + +void quest_library_gen_hook() +{ + library_quest_place_nrandom( + 4, 4, 14, 37, MONSTER_LICH, damroll(4,2)); + + library_quest_place_nrandom( + 14, 34, 37, 67, MONSTER_MONASTIC_LICH, damroll(1, 2)); + + library_quest_place_nrandom( + 4, 34, 14, 67, MONSTER_MONASTIC_LICH, damroll(1, 2) - 1); + + library_quest_place_nrandom( + 14, 4, 37, 34, MONSTER_MONASTIC_LICH, damroll(1, 2) - 1); + + library_quest_place_nrandom( + 10, 10, 37, 67, MONSTER_FLESH_GOLEM, 2); + + library_quest_place_nrandom( + 10, 10, 37, 67, MONSTER_CLAY_GOLEM, 2); + + library_quest_place_nrandom( + 10, 10, 37, 67, MONSTER_IRON_GOLEM, 2); + + library_quest_place_nrandom( + 10, 10, 37, 67, MONSTER_MITHRIL_GOLEM, 1); +} diff --git a/src/util.pkg b/src/util.pkg index 39f70b40..d13f74e6 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -2681,3 +2681,5 @@ extern void lite_spot(int y, int x); extern bool drop_text_left(byte c, cptr s, int y, int o); extern bool drop_text_right(byte c, cptr s, int y, int o); + +extern void quest_library_gen_hook(); -- cgit v1.2.3 From 7121520f1b7e564bd59287a11d4a8f89e999ea82 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 2 Apr 2012 22:10:00 +0200 Subject: Lua: Move "Library" quest functions to C --- lib/mods/theme/scpt/library.lua | 169 +---------------------------------- lib/scpt/library.lua | 169 +---------------------------------- src/externs.h | 4 + src/q_library.c | 189 ++++++++++++++++++++++++++++++++++++++++ src/quest.pkg | 6 ++ 5 files changed, 203 insertions(+), 334 deletions(-) diff --git a/lib/mods/theme/scpt/library.lua b/lib/mods/theme/scpt/library.lua index 4a8b03c4..38c26599 100644 --- a/lib/mods/theme/scpt/library.lua +++ b/lib/mods/theme/scpt/library.lua @@ -29,70 +29,6 @@ library_quest.bookable_spells = MANDOS_TEARS_LUTHIEN, MANDOS_TALE_DOOM } -library_quest.get_term_size = function() - local width = 0 - local height = 0 - ret, width, height = Term_get_size(width, height) - return width, height -end - -library_quest.book_slots_left = function() - if school_book[61][1] == -1 then - return 3 - elseif school_book[61][2] == -1 then - return 2 - elseif school_book[61][3] == -1 then - return 1 - else - return 0 - end -end - -library_quest.book_contains_spell = function(spell) - if school_book[61][1] == spell then - return TRUE - elseif school_book[61][2] == spell then - return TRUE - elseif school_book[61][3] == spell then - return TRUE - else - return FALSE - end -end - -library_quest.add_spell = function(spell) - if school_book[61][1] == -1 then - school_book[61][1] = spell - return TRUE - elseif school_book[61][2] == -1 then - school_book[61][2] = spell - return TRUE - elseif school_book[61][3] == -1 then - school_book[61][3] = spell - return TRUE - else - return FALSE - end -end - -library_quest.remove_spell = function(spell) - if school_book[61][1] == spell then - school_book[61][1] = school_book[61][2] - school_book[61][2] = school_book[61][3] - school_book[61][3] = -1 - return TRUE - elseif school_book[61][2] == spell then - school_book[61][2] = school_book[61][3] - school_book[61][3] = -1 - return TRUE - elseif school_book[61][3] == spell then - school_book[61][3] = -1 - return TRUE - else - return FALSE - end -end - -- Print a spell (taken from s_aux) function library_quest.print_spell(color, y, spl) local x, index, sch, size, s @@ -127,107 +63,6 @@ function library_quest.print_spell(color, y, spl) return y end --- spell selection routines inspired by skills.c -library_quest.print_spells = function(first, current) - Term_clear() - width, height = library_quest.get_term_size() - slots = library_quest.book_slots_left() - - c_prt(TERM_WHITE, "Book Creation Screen", 0, 0); - c_prt(TERM_WHITE, "Up/Down to move, Right/Left to modify, I to describe, Esc to Save/Cancel", 1, 0); - - if slots == 0 then - c_prt(TERM_L_RED, "The book can hold no more spells.", 2, 0); - elseif slots == 1 then - c_prt(TERM_L_BLUE, "The book can hold 1 more spell.", 2, 0); - else - c_prt(TERM_L_BLUE, "The book can hold "..slots.." more spells.", 2, 0); - end - - row = 3; - for index, spell in library_quest.bookable_spells do - if index >= first then - if index == current then - color = TERM_GREEN - elseif library_quest.book_contains_spell(spell) == TRUE then - color = TERM_WHITE - else - color = TERM_ORANGE - end - library_quest.print_spell(color, row, spell) - - if row == height - 1 then - return - end - row = row + 1 - end - end -end - -library_quest.fill_book = function() - -- Always start with a cleared book - school_book[61] = {-1, -1, -1} - - screen_save() - width, height = library_quest.get_term_size() - -- room for legend - margin = 3 - - first = 1 - current = 1 - done = FALSE - - while done == FALSE do - library_quest.print_spells(first, current) - - inkey_scan = FALSE - inkey_base = TRUE - char = inkey() - dir = get_keymap_dir(char) - if char == ESCAPE then - if library_quest.book_slots_left() == 0 then - flush() - done = get_check("Really create the book?") - else - done = TRUE - end - elseif char == strbyte('\r') then - -- TODO: make tree of schools - elseif char == strbyte('n') then - current = current + height - elseif char == strbyte('p') then - current = current - height - elseif char == strbyte('I') then - print_spell_desc(library_quest.bookable_spells[current], 0) - inkey() - elseif dir == 2 then - current = current + 1 - elseif dir == 8 then - current = current - 1 - elseif dir == 6 then - if library_quest.book_contains_spell(library_quest.bookable_spells[current]) == FALSE then - library_quest.add_spell(library_quest.bookable_spells[current]) - end - elseif dir == 4 then - library_quest.remove_spell(library_quest.bookable_spells[current]) - end - total = getn(library_quest.bookable_spells) - if current > total then - current = total - elseif current < 1 then - current = 1 - end - - if current > (first + height - margin - 1) then - first = current - height + margin + 1 - elseif first > current then - first = current - end - end - - screen_load() -end - -- Quest data and hooks add_quest { @@ -345,8 +180,8 @@ add_building_action elseif (quest(LIBRARY_QUEST).status == QUEST_STATUS_COMPLETED) then msg_print("Thank you! Let me make a special book for you.") msg_print("Tell me three spells and I will write them in the book.") - library_quest.fill_book() - if library_quest.book_slots_left() == 0 then + library_quest_fill_book() + if library_quest_book_slots_left() == 0 then quest(LIBRARY_QUEST).status = QUEST_STATUS_REWARDED book = create_object(TV_BOOK, 61) book.art_name = quark_add(player_name()) diff --git a/lib/scpt/library.lua b/lib/scpt/library.lua index 58e36556..5c98fe86 100644 --- a/lib/scpt/library.lua +++ b/lib/scpt/library.lua @@ -26,70 +26,6 @@ library_quest.bookable_spells = DRAIN } -library_quest.get_term_size = function() - local width = 0 - local height = 0 - ret, width, height = Term_get_size(width, height) - return width, height -end - -library_quest.book_slots_left = function() - if school_book[61][1] == -1 then - return 3 - elseif school_book[61][2] == -1 then - return 2 - elseif school_book[61][3] == -1 then - return 1 - else - return 0 - end -end - -library_quest.book_contains_spell = function(spell) - if school_book[61][1] == spell then - return TRUE - elseif school_book[61][2] == spell then - return TRUE - elseif school_book[61][3] == spell then - return TRUE - else - return FALSE - end -end - -library_quest.add_spell = function(spell) - if school_book[61][1] == -1 then - school_book[61][1] = spell - return TRUE - elseif school_book[61][2] == -1 then - school_book[61][2] = spell - return TRUE - elseif school_book[61][3] == -1 then - school_book[61][3] = spell - return TRUE - else - return FALSE - end -end - -library_quest.remove_spell = function(spell) - if school_book[61][1] == spell then - school_book[61][1] = school_book[61][2] - school_book[61][2] = school_book[61][3] - school_book[61][3] = -1 - return TRUE - elseif school_book[61][2] == spell then - school_book[61][2] = school_book[61][3] - school_book[61][3] = -1 - return TRUE - elseif school_book[61][3] == spell then - school_book[61][3] = -1 - return TRUE - else - return FALSE - end -end - -- Print a spell (taken from s_aux) function library_quest.print_spell(color, y, spl) local x, index, sch, size, s @@ -124,107 +60,6 @@ function library_quest.print_spell(color, y, spl) return y end --- spell selection routines inspired by skills.c -library_quest.print_spells = function(first, current) - Term_clear() - width, height = library_quest.get_term_size() - slots = library_quest.book_slots_left() - - c_prt(TERM_WHITE, "Book Creation Screen", 0, 0); - c_prt(TERM_WHITE, "Up/Down to move, Right/Left to modify, I to describe, Esc to Save/Cancel", 1, 0); - - if slots == 0 then - c_prt(TERM_L_RED, "The book can hold no more spells.", 2, 0); - elseif slots == 1 then - c_prt(TERM_L_BLUE, "The book can hold 1 more spell.", 2, 0); - else - c_prt(TERM_L_BLUE, "The book can hold "..slots.." more spells.", 2, 0); - end - - row = 3; - for index, spell in library_quest.bookable_spells do - if index >= first then - if index == current then - color = TERM_GREEN - elseif library_quest.book_contains_spell(spell) == TRUE then - color = TERM_WHITE - else - color = TERM_ORANGE - end - library_quest.print_spell(color, row, spell) - - if row == height - 1 then - return - end - row = row + 1 - end - end -end - -library_quest.fill_book = function() - -- Always start with a cleared book - school_book[61] = {-1, -1, -1} - - screen_save() - width, height = library_quest.get_term_size() - -- room for legend - margin = 3 - - first = 1 - current = 1 - done = FALSE - - while done == FALSE do - library_quest.print_spells(first, current) - - inkey_scan = FALSE - inkey_base = TRUE - char = inkey() - dir = get_keymap_dir(char) - if char == ESCAPE then - if library_quest.book_slots_left() == 0 then - flush() - done = get_check("Really create the book?") - else - done = TRUE - end - elseif char == strbyte('\r') then - -- TODO: make tree of schools - elseif char == strbyte('n') then - current = current + height - elseif char == strbyte('p') then - current = current - height - elseif char == strbyte('I') then - print_spell_desc(library_quest.bookable_spells[current], 0) - inkey() - elseif dir == 2 then - current = current + 1 - elseif dir == 8 then - current = current - 1 - elseif dir == 6 then - if library_quest.book_contains_spell(library_quest.bookable_spells[current]) == FALSE then - library_quest.add_spell(library_quest.bookable_spells[current]) - end - elseif dir == 4 then - library_quest.remove_spell(library_quest.bookable_spells[current]) - end - total = getn(library_quest.bookable_spells) - if current > total then - current = total - elseif current < 1 then - current = 1 - end - - if current > (first + height - margin - 1) then - first = current - height + margin + 1 - elseif first > current then - first = current - end - end - - screen_load() -end - -- Quest data and hooks add_quest { @@ -342,8 +177,8 @@ add_building_action elseif (quest(LIBRARY_QUEST).status == QUEST_STATUS_COMPLETED) then msg_print("Thank you! Let me make a special book for you.") msg_print("Tell me three spells and I will write them in the book.") - library_quest.fill_book() - if library_quest.book_slots_left() == 0 then + library_quest_fill_book() + if library_quest_book_slots_left() == 0 then quest(LIBRARY_QUEST).status = QUEST_STATUS_REWARDED book = create_object(TV_BOOK, 61) book.art_name = quark_add(player_name()) diff --git a/src/externs.h b/src/externs.h index a9baa853..0475a2b9 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1825,6 +1825,10 @@ extern cptr approximate_distance(int y, int x, int y2, int x2); extern bool_ drop_text_left(byte c, cptr s, int y, int o); extern bool_ drop_text_right(byte c, cptr s, int y, int o); +/* q_library.c */ +extern void library_quest_fill_book(); +extern int library_quest_book_slots_left(); + /* skills.c */ extern void dump_skills(FILE *fff); extern s16b find_skill(cptr name); diff --git a/src/q_library.c b/src/q_library.c index edb1698f..25f20717 100644 --- a/src/q_library.c +++ b/src/q_library.c @@ -25,6 +25,195 @@ static void library_quest_place_nrandom(int minY, int minX, int maxY, int maxX, } } +static int library_quest_book_get_slot(int slot) +{ + return exec_lua(format("return school_book[61][%d]", slot)); +} + +static int library_quest_book_set_slot(int slot, int spell) +{ + return exec_lua(format("school_book[61][%d] = %d", slot, spell)); +} + +int library_quest_book_slots_left() +{ + if (library_quest_book_get_slot(1) == -1) { + return 3; + } else if (library_quest_book_get_slot(2) == -1) { + return 2; + } else if (library_quest_book_get_slot(3) == -1) { + return 1; + } else { + return 0; + } +} + +static bool_ library_quest_book_contains_spell(int spell) +{ + return exec_lua(format("return spell_in_book(61, %d)", spell)); +} + +static int library_quest_bookable_spells_at(int i) { + return exec_lua(format("return library_quest.bookable_spells[%d]", i + 1)); +} + +static int library_quest_getn_bookable_spells() { + return exec_lua("return getn(library_quest.bookable_spells)"); +} + +static int library_quest_print_spell(int color, int row, int spell) { + return exec_lua(format("library_quest.print_spell(%d,%d,%d)", color, row, spell)); +} + +static int library_quest_print_spell_desc(int s, int y) { + return exec_lua(format("print_spell_desc(%d, %d)", s, y)); +} + +static void library_quest_add_spell(int spell) { + if (library_quest_book_get_slot(1) == -1) { + library_quest_book_set_slot(1, spell); + } else if (library_quest_book_get_slot(2) == -1) { + library_quest_book_set_slot(2, spell); + } else if (library_quest_book_get_slot(3) == -1) { + library_quest_book_set_slot(3, spell); + } +} + +static void library_quest_remove_spell(int spell) { + if (library_quest_book_get_slot(1) == spell) { + library_quest_book_set_slot(1, library_quest_book_get_slot(2)); + library_quest_book_set_slot(2, library_quest_book_get_slot(3)); + library_quest_book_set_slot(3, -1); + } else if (library_quest_book_get_slot(2) == spell) { + library_quest_book_set_slot(2, library_quest_book_get_slot(3)); + library_quest_book_set_slot(3, -1); + } else if (library_quest_book_get_slot(3) == spell) { + library_quest_book_set_slot(3, -1); + } +} + +/* spell selection routines inspired by skills.c */ +static void library_quest_print_spells(int first, int current) +{ + int width, height; + int slots, row; + int nspells, index; + + Term_clear(); + Term_get_size(&width, &height); + + slots = library_quest_book_slots_left(); + + c_prt(TERM_WHITE, "Book Creation Screen", 0, 0); + c_prt(TERM_WHITE, "Up/Down to move, Right/Left to modify, I to describe, Esc to Save/Cancel", 1, 0); + + if (slots == 0) { + c_prt(TERM_L_RED, "The book can hold no more spells.", 2, 0); + } else if (slots == 1) { + c_prt(TERM_L_BLUE, "The book can hold 1 more spell.", 2, 0); + } else { + c_prt(TERM_L_BLUE, format("The book can hold %d more spells.", slots), 2, 0); + } + + row = 3; + + nspells = library_quest_getn_bookable_spells(); + for (index = 0; index < nspells; index++) { + int spell = library_quest_bookable_spells_at(index); + if (index >= first) { + int color; + if (index == current) { + color = TERM_GREEN; + } else if (library_quest_book_contains_spell(spell)) { + color = TERM_WHITE; + } else { + color = TERM_ORANGE; + } + + library_quest_print_spell(color, row, spell); + + if (row == height - 1) { + return; + } + row = row + 1; + } + } +} + +void library_quest_fill_book() +{ + int width, height, margin, first, current; + bool_ done; + + /* Always start with a cleared book */ + exec_lua("school_book[61] = {-1, -1, -1}"); + + screen_save(); + Term_get_size(&width, &height); + + /* room for legend */ + margin = 3; + + first = 0; + current = 0; + done = FALSE; + + while (done == FALSE) + { + char ch; + int dir, total; + + library_quest_print_spells(first, current); + + inkey_scan = FALSE; + ch = inkey(); + dir = get_keymap_dir(ch); + + if (ch == ESCAPE) { + if (library_quest_book_slots_left() == 0) { + flush(); + done = get_check("Really create the book?"); + } else { + done = TRUE; + } + } else if (ch == '\r') { + /* TODO: make tree of schools */ + } else if (ch == 'n') { + current = current + height; + } else if (ch == 'p') { + current = current - height; + } else if (ch == 'I') { + library_quest_print_spell_desc(library_quest_bookable_spells_at(current), 0); + inkey(); + } else if (dir == 2) { + current = current + 1; + } else if (dir == 8) { + current = current - 1; + } else if (dir == 6) { + if (library_quest_book_contains_spell(library_quest_bookable_spells_at(current)) == FALSE) { + library_quest_add_spell(library_quest_bookable_spells_at(current)); + } + } else if (dir == 4) { + library_quest_remove_spell(library_quest_bookable_spells_at(current)); + } + + total = library_quest_getn_bookable_spells(); + if (current >= total) { + current = total - 1; + } else if (current < 0) { + current = 0; + } + + if (current > (first + height - margin - 1)) { + first = current - height + margin + 1; + } else if (first > current) { + first = current; + } + } + + screen_load(); +} + void quest_library_gen_hook() { library_quest_place_nrandom( diff --git a/src/quest.pkg b/src/quest.pkg index 487c62af..7476bc9b 100644 --- a/src/quest.pkg +++ b/src/quest.pkg @@ -159,3 +159,9 @@ extern s16b add_new_quest @ new_quest(char *name); * @note (see file lua_bind.c) */ extern void desc_quest @ quest_desc(int q_idx, int d, char *desc); + +/** + * Library Quest + */ +extern void library_quest_fill_book(); +extern int library_quest_book_slots_left(); -- cgit v1.2.3 From 6b85af588b8ef4d219bc011b7c31df07a314ba0c Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 2 Apr 2012 22:10:00 +0200 Subject: Lua: Move get_level_device() to C --- lib/core/s_aux.lua | 31 ++----------------------------- lib/mods/theme/core/s_aux.lua | 31 ++----------------------------- src/externs.h | 1 + src/lua_bind.c | 34 ++++++++++++++++++++++++++++++++++ src/spells.pkg | 3 +++ 5 files changed, 42 insertions(+), 58 deletions(-) diff --git a/lib/core/s_aux.lua b/lib/core/s_aux.lua index ec609b04..5e514081 100644 --- a/lib/core/s_aux.lua +++ b/lib/core/s_aux.lua @@ -200,35 +200,6 @@ function get_level_school(s, max, min) return lvl, nil end --- This is the function to use when casting through a stick -function get_level_device(s, max, min) - local lvl - - -- No max specified ? assume 50 - if not max then - max = 50 - end - - lvl = s_info[SKILL_DEVICE + 1].value - lvl = lvl + (get_level_use_stick * SKILL_STEP) - - -- Sticks are limited - if lvl - ((spell(s).skill_level + 1) * SKILL_STEP) >= get_level_max_stick * SKILL_STEP then - lvl = (get_level_max_stick + spell(s).skill_level - 1) * SKILL_STEP - end - - -- / 10 because otherwise we can overflow a s32b and we can use a u32b because the value can be negative - -- The loss of information should be negligible since 1 skill = 1000 internally - lvl = lvl / 10 - if not min then - lvl = lua_get_level(s, lvl, max, 1, 0) - else - lvl = lua_get_level(s, lvl, max, min, 0) - end - - return lvl -end - -- The real get_level, works for schooled magic and for innate powers get_level_use_stick = -1 get_level_max_stick = -1 @@ -236,6 +207,8 @@ function get_level(s, max, min) if type(s) == "number" then -- Ahah shall we use Magic device instead ? if get_level_use_stick > -1 then + if not max then max = 50 end + if not min then min = 1 end return get_level_device(s, max, min) else local lvl, na = get_level_school(s, max, min) diff --git a/lib/mods/theme/core/s_aux.lua b/lib/mods/theme/core/s_aux.lua index ec609b04..5e514081 100644 --- a/lib/mods/theme/core/s_aux.lua +++ b/lib/mods/theme/core/s_aux.lua @@ -200,35 +200,6 @@ function get_level_school(s, max, min) return lvl, nil end --- This is the function to use when casting through a stick -function get_level_device(s, max, min) - local lvl - - -- No max specified ? assume 50 - if not max then - max = 50 - end - - lvl = s_info[SKILL_DEVICE + 1].value - lvl = lvl + (get_level_use_stick * SKILL_STEP) - - -- Sticks are limited - if lvl - ((spell(s).skill_level + 1) * SKILL_STEP) >= get_level_max_stick * SKILL_STEP then - lvl = (get_level_max_stick + spell(s).skill_level - 1) * SKILL_STEP - end - - -- / 10 because otherwise we can overflow a s32b and we can use a u32b because the value can be negative - -- The loss of information should be negligible since 1 skill = 1000 internally - lvl = lvl / 10 - if not min then - lvl = lua_get_level(s, lvl, max, 1, 0) - else - lvl = lua_get_level(s, lvl, max, min, 0) - end - - return lvl -end - -- The real get_level, works for schooled magic and for innate powers get_level_use_stick = -1 get_level_max_stick = -1 @@ -236,6 +207,8 @@ function get_level(s, max, min) if type(s) == "number" then -- Ahah shall we use Magic device instead ? if get_level_use_stick > -1 then + if not max then max = 50 end + if not min then min = 1 end return get_level_device(s, max, min) else local lvl, na = get_level_school(s, max, min) diff --git a/src/externs.h b/src/externs.h index 0475a2b9..9ac54884 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1796,6 +1796,7 @@ extern s16b new_spell(int i, cptr name); extern spell_type *grab_spell_type(s16b num); extern school_type *grab_school_type(s16b num); extern s32b lua_get_level(s32b s, s32b lvl, s32b max, s32b min, s32b bonus); +extern s32b get_level_device(s32b s, s32b max, s32b min); extern s32b lua_spell_chance(s32b chance, int level, int skill_level, int mana, int cur_mana, int stat); extern s32b lua_spell_device_chance(s32b chance, int level, int base_level); diff --git a/src/lua_bind.c b/src/lua_bind.c index 67b75ee6..38e334ce 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -263,6 +263,40 @@ s32b lua_get_level(s32b s, s32b lvl, s32b max, s32b min, s32b bonus) return lvl; } +/** This is the function to use when casting through a stick */ +s32b get_level_device(s32b s, s32b max, s32b min) +{ + int lvl; + int get_level_use_stick = exec_lua("return get_level_use_stick"); + int get_level_max_stick = exec_lua("return get_level_max_stick"); + + /* No max specified ? assume 50 */ + if (max <= 0) { + max = 50; + } + /* No min specified ? */ + if (min <= 0) { + min = 1; + } + + lvl = s_info[SKILL_DEVICE].value; + lvl = lvl + (get_level_use_stick * SKILL_STEP); + + /* Sticks are limited */ + if (lvl - ((school_spells[s].skill_level + 1) * SKILL_STEP) >= get_level_max_stick * SKILL_STEP) + { + lvl = (get_level_max_stick + school_spells[s].skill_level - 1) * SKILL_STEP; + } + + /* / 10 because otherwise we can overflow a s32b and we can use a u32b because the value can be negative + -- The loss of information should be negligible since 1 skill = 1000 internally + */ + lvl = lvl / 10; + lvl = lua_get_level(s, lvl, max, min, 0); + + return lvl; +} + s32b lua_spell_chance(s32b chance, int level, int skill_level, int mana, int cur_mana, int stat) { int minfail; diff --git a/src/spells.pkg b/src/spells.pkg index e785de0d..9f8ddaaa 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2352,6 +2352,9 @@ extern school_type *grab_school_type @ school(s16b num); */ extern s32b lua_get_level(s32b s, s32b lvl, s32b max, s32b min, s32b bonus); +/** Get level of device */ +extern s32b get_level_device(s32b s, s32b max, s32b min); + /** @fn lua_spell_chance(s32b chance, int level, int skill_level, int mana, int cur_mana, int stat) * @dgonly * @brief Get the chance a spell will fail.\n -- cgit v1.2.3 From 2d8ba33e34c0cbab8b7db8bbd972f1b18b28b199 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 2 Apr 2012 22:10:00 +0200 Subject: Lua: Move spell_chance() to C --- lib/core/s_aux.lua | 17 ----------------- lib/mods/theme/core/s_aux.lua | 17 ----------------- src/cmd6.c | 4 ++-- src/externs.h | 1 + src/lua_bind.c | 32 ++++++++++++++++++++++++++++++++ src/spells.pkg | 4 ++++ 6 files changed, 39 insertions(+), 36 deletions(-) diff --git a/lib/core/s_aux.lua b/lib/core/s_aux.lua index 5e514081..8ae69749 100644 --- a/lib/core/s_aux.lua +++ b/lib/core/s_aux.lua @@ -401,23 +401,6 @@ function spell_in_book(book, spell) return FALSE end --- Returns spell chance of failure for spell -function spell_chance(s) - local chance, s_ptr - - s_ptr = spell(s) - - -- Extract the base spell failure rate - if get_level_use_stick > -1 then - chance = lua_spell_device_chance(s_ptr.fail, get_level(s, 50), s_ptr.skill_level) - else - chance = lua_spell_chance(s_ptr.fail, get_level(s, 50), s_ptr.skill_level, get_mana(s), get_power(s), get_spell_stat(s)) - end - - -- Return the chance - return chance -end - function check_affect(s, name, default) local s_ptr = __tmp_spells[s] local a diff --git a/lib/mods/theme/core/s_aux.lua b/lib/mods/theme/core/s_aux.lua index 5e514081..8ae69749 100644 --- a/lib/mods/theme/core/s_aux.lua +++ b/lib/mods/theme/core/s_aux.lua @@ -401,23 +401,6 @@ function spell_in_book(book, spell) return FALSE end --- Returns spell chance of failure for spell -function spell_chance(s) - local chance, s_ptr - - s_ptr = spell(s) - - -- Extract the base spell failure rate - if get_level_use_stick > -1 then - chance = lua_spell_device_chance(s_ptr.fail, get_level(s, 50), s_ptr.skill_level) - else - chance = lua_spell_chance(s_ptr.fail, get_level(s, 50), s_ptr.skill_level, get_mana(s), get_power(s), get_spell_stat(s)) - end - - -- Return the chance - return chance -end - function check_affect(s, name, default) local s_ptr = __tmp_spells[s] local a diff --git a/src/cmd6.c b/src/cmd6.c index db89c465..eaeee333 100644 --- a/src/cmd6.c +++ b/src/cmd6.c @@ -3683,7 +3683,7 @@ void do_cmd_use_staff(void) ident = FALSE; /* get the chance */ - chance = exec_lua(format("return spell_chance(%d)", o_ptr->pval2)); + chance = spell_chance(o_ptr->pval2); /* Extract object flags */ object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); @@ -3877,7 +3877,7 @@ void do_cmd_aim_wand(void) set_stick_mode(o_ptr); /* get the chance */ - chance = exec_lua(format("return spell_chance(%d)", o_ptr->pval2)); + chance = spell_chance(o_ptr->pval2); /* Extract object flags */ object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); diff --git a/src/externs.h b/src/externs.h index 9ac54884..e5d80c19 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1797,6 +1797,7 @@ extern spell_type *grab_spell_type(s16b num); extern school_type *grab_school_type(s16b num); extern s32b lua_get_level(s32b s, s32b lvl, s32b max, s32b min, s32b bonus); extern s32b get_level_device(s32b s, s32b max, s32b min); +extern s32b spell_chance(s32b s); extern s32b lua_spell_chance(s32b chance, int level, int skill_level, int mana, int cur_mana, int stat); extern s32b lua_spell_device_chance(s32b chance, int level, int base_level); diff --git a/src/lua_bind.c b/src/lua_bind.c index 38e334ce..05e1c743 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -297,6 +297,38 @@ s32b get_level_device(s32b s, s32b max, s32b min) return lvl; } +static int get_level(s32b s) { + return exec_lua(format("return get_level(%d, 50)", s)); +} + +static int get_mana(s32b s) { + return exec_lua(format("return get_mana(%d)", s)); +} + +static int get_power(s32b s) { + return exec_lua(format("return get_power(%d)", s)); +} + +static int get_spell_stat(s32b s) { + return exec_lua(format("return get_spell_stat(%d)", s)); +} + +/** Returns spell chance of failure for spell */ +s32b spell_chance(s32b s) +{ + int get_level_use_stick = exec_lua("return get_level_use_stick"); + spell_type *s_ptr = &school_spells[s]; + int level = get_level(s); + + /* Extract the base spell failure rate */ + if (get_level_use_stick > -1) { + return lua_spell_device_chance(s_ptr->fail, level, s_ptr->skill_level); + } else { + return lua_spell_chance(s_ptr->fail, level, s_ptr->skill_level, get_mana(s), get_power(s), get_spell_stat(s)); + } +} + + s32b lua_spell_chance(s32b chance, int level, int skill_level, int mana, int cur_mana, int stat) { int minfail; diff --git a/src/spells.pkg b/src/spells.pkg index 9f8ddaaa..2705737b 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2355,6 +2355,10 @@ extern s32b lua_get_level(s32b s, s32b lvl, s32b max, s32b min, s32b bonus); /** Get level of device */ extern s32b get_level_device(s32b s, s32b max, s32b min); +/** Get change of failure for spell. */ +extern s32b spell_chance(s32b s); + + /** @fn lua_spell_chance(s32b chance, int level, int skill_level, int mana, int cur_mana, int stat) * @dgonly * @brief Get the chance a spell will fail.\n -- cgit v1.2.3 From a77005060dac93cfdd5cdfdf7dc849e0f5207f60 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 2 Apr 2012 22:10:00 +0200 Subject: Lua: Move get_level_{use,max}_stick bits to C --- lib/core/s_aux.lua | 26 +++----------------------- lib/mods/theme/core/s_aux.lua | 26 +++----------------------- src/cmd6.c | 7 +++++-- src/externs.h | 5 ++++- src/lua_bind.c | 20 ++++++++++++-------- src/spells.pkg | 3 +++ src/util.c | 13 ------------- src/util.pkg | 15 --------------- src/variable.c | 2 ++ 9 files changed, 32 insertions(+), 85 deletions(-) diff --git a/lib/core/s_aux.lua b/lib/core/s_aux.lua index 8ae69749..29b22fd7 100644 --- a/lib/core/s_aux.lua +++ b/lib/core/s_aux.lua @@ -201,22 +201,10 @@ function get_level_school(s, max, min) end -- The real get_level, works for schooled magic and for innate powers -get_level_use_stick = -1 -get_level_max_stick = -1 function get_level(s, max, min) - if type(s) == "number" then - -- Ahah shall we use Magic device instead ? - if get_level_use_stick > -1 then - if not max then max = 50 end - if not min then min = 1 end - return get_level_device(s, max, min) - else - local lvl, na = get_level_school(s, max, min) - return lvl - end - else - return get_level_power(s, max, min) - end + if not max then max = 50 end + if not min then min = 1 end + return %get_level(s, max, min) end -- Can we cast the spell ? @@ -249,14 +237,6 @@ function get_power_name(s) end end --- Get the level of a power -function get_level_power(s, max, min) - if not max then max = 50 end - if not min then min = 1 end - - return value_scale(s.get_current_level(), 50, max, min) -end - -- Changes the amount of power(mana, piety, whatever) for the spell function adjust_power(s, x) if check_affect(s, "piety", FALSE) then diff --git a/lib/mods/theme/core/s_aux.lua b/lib/mods/theme/core/s_aux.lua index 8ae69749..29b22fd7 100644 --- a/lib/mods/theme/core/s_aux.lua +++ b/lib/mods/theme/core/s_aux.lua @@ -201,22 +201,10 @@ function get_level_school(s, max, min) end -- The real get_level, works for schooled magic and for innate powers -get_level_use_stick = -1 -get_level_max_stick = -1 function get_level(s, max, min) - if type(s) == "number" then - -- Ahah shall we use Magic device instead ? - if get_level_use_stick > -1 then - if not max then max = 50 end - if not min then min = 1 end - return get_level_device(s, max, min) - else - local lvl, na = get_level_school(s, max, min) - return lvl - end - else - return get_level_power(s, max, min) - end + if not max then max = 50 end + if not min then min = 1 end + return %get_level(s, max, min) end -- Can we cast the spell ? @@ -249,14 +237,6 @@ function get_power_name(s) end end --- Get the level of a power -function get_level_power(s, max, min) - if not max then max = 50 end - if not min then min = 1 end - - return value_scale(s.get_current_level(), 50, max, min) -end - -- Changes the amount of power(mana, piety, whatever) for the spell function adjust_power(s, x) if check_affect(s, "piety", FALSE) then diff --git a/src/cmd6.c b/src/cmd6.c index eaeee333..987315af 100644 --- a/src/cmd6.c +++ b/src/cmd6.c @@ -3616,12 +3616,15 @@ void set_stick_mode(object_type *o_ptr) s32b bonus = o_ptr->pval3 & 0xFFFF; s32b max = o_ptr->pval3 >> 16; - exec_lua(format("get_level_use_stick = %d; get_level_max_stick = %d", bonus, max)); + get_level_use_stick = bonus; + get_level_max_stick = max; } + /* Remove 'stick mode' */ void unset_stick_mode() { - exec_lua("get_level_use_stick = -1; get_level_max_stick = -1"); + get_level_use_stick = -1; + get_level_max_stick = -1; } diff --git a/src/externs.h b/src/externs.h index e5d80c19..dd305c07 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1431,7 +1431,6 @@ extern s32b rescale(s32b x, s32b max, s32b new_max); extern bool_ input_box(cptr text, int y, int x, char *buf, int max); extern void draw_box(int y, int x, int h, int w); extern void display_list(int y, int x, int h, int w, cptr title, cptr *list, int max, int begin, int sel, byte sel_color); -extern s32b value_scale(int value, int vmax, int max, int min); extern int ask_menu(cptr ask, char **items, int max); extern cptr get_player_race_name(int pr, int ps); extern cptr get_month_name(int month, bool_ full, bool_ compact); @@ -1798,9 +1797,13 @@ extern school_type *grab_school_type(s16b num); extern s32b lua_get_level(s32b s, s32b lvl, s32b max, s32b min, s32b bonus); extern s32b get_level_device(s32b s, s32b max, s32b min); extern s32b spell_chance(s32b s); +extern s32b get_level(s32b s, s32b max, s32b min); extern s32b lua_spell_chance(s32b chance, int level, int skill_level, int mana, int cur_mana, int stat); extern s32b lua_spell_device_chance(s32b chance, int level, int base_level); +extern s32b get_level_max_stick; +extern s32b get_level_use_stick; + extern cave_type *lua_get_cave(int y, int x); extern void set_target(int y, int x); extern void get_target(int dir, int *y, int *x); diff --git a/src/lua_bind.c b/src/lua_bind.c index 05e1c743..82b802f2 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -267,8 +267,6 @@ s32b lua_get_level(s32b s, s32b lvl, s32b max, s32b min, s32b bonus) s32b get_level_device(s32b s, s32b max, s32b min) { int lvl; - int get_level_use_stick = exec_lua("return get_level_use_stick"); - int get_level_max_stick = exec_lua("return get_level_max_stick"); /* No max specified ? assume 50 */ if (max <= 0) { @@ -297,10 +295,6 @@ s32b get_level_device(s32b s, s32b max, s32b min) return lvl; } -static int get_level(s32b s) { - return exec_lua(format("return get_level(%d, 50)", s)); -} - static int get_mana(s32b s) { return exec_lua(format("return get_mana(%d)", s)); } @@ -316,9 +310,8 @@ static int get_spell_stat(s32b s) { /** Returns spell chance of failure for spell */ s32b spell_chance(s32b s) { - int get_level_use_stick = exec_lua("return get_level_use_stick"); spell_type *s_ptr = &school_spells[s]; - int level = get_level(s); + int level = get_level(s, 50, 1); /* Extract the base spell failure rate */ if (get_level_use_stick > -1) { @@ -328,6 +321,17 @@ s32b spell_chance(s32b s) } } +s32b get_level(s32b s, s32b max, s32b min) +{ + /** Ahah shall we use Magic device instead ? */ + if (get_level_use_stick > -1) { + return get_level_device(s, max, min); + } else { + int level = exec_lua(format("local lvl, na = get_level_school(%d, %d, %d); return lvl", s, max, min)); + return level; + } +} + s32b lua_spell_chance(s32b chance, int level, int skill_level, int mana, int cur_mana, int stat) { diff --git a/src/spells.pkg b/src/spells.pkg index 2705737b..cbbc2dc5 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2358,6 +2358,9 @@ extern s32b get_level_device(s32b s, s32b max, s32b min); /** Get change of failure for spell. */ extern s32b spell_chance(s32b s); +/** Get level of spell */ +extern s32b get_level(s32b s, s32b max, s32b min); + /** @fn lua_spell_chance(s32b chance, int level, int skill_level, int mana, int cur_mana, int stat) * @dgonly diff --git a/src/util.c b/src/util.c index 93e38e4a..f1b0710e 100644 --- a/src/util.c +++ b/src/util.c @@ -4317,19 +4317,6 @@ bool_ prefix(cptr s, cptr t) return (TRUE); } -/* - * Rescale a value - */ -s32b value_scale(int value, int vmax, int max, int min) -{ - s32b full_max = max - min; - - value = (value * full_max) / vmax; - value += min; - - return value; -} - /* * Displays a box */ diff --git a/src/util.pkg b/src/util.pkg index d13f74e6..183a28f2 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -1499,21 +1499,6 @@ extern cptr get_player_race_name(int pr, int ps); */ extern void quit(cptr str); -/** @fn value_scale(int value, int vmax, int max, int min) - * @brief Rescale a value - * @param value Number \n the original value - * @brief Original value - * @param vmax Number \n the maximum the original value can be - * @brief Original maximum - * @param max Number \n the maximum new value - * @brief New maximum - * @param min Number \n the minimum new value - * @brief New minimum - * @return Number \n The rescaled value - * @note (see file util.c) - */ -extern s32b value_scale(int value, int vmax, int max, int min); - /* * compass, approximate_distance */ diff --git a/src/variable.c b/src/variable.c index c6a23758..9ed084b4 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1170,6 +1170,8 @@ bool_ easy_open = TRUE; bool_ easy_disarm = TRUE; bool_ easy_tunnel = FALSE; +s32b get_level_max_stick = -1; +s32b get_level_use_stick = -1; /* * Maximum size of the wilderness map -- cgit v1.2.3 From bfa8fa32382c89259dbf4f9301b316b7e0239344 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 5 Apr 2012 21:03:05 +0200 Subject: Lua: Add functions to get GOD_* Lua variables from C code --- src/externs.h | 4 ++++ src/lua_bind.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/externs.h b/src/externs.h index dd305c07..e232f69d 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1787,6 +1787,10 @@ extern void desc_quest(int q_idx, int d, char *desc); extern s16b add_new_gods(char *name); extern void desc_god(int g_idx, int d, char *desc); +extern s16b get_god_AULE(); +extern s16b get_god_VARDA(); +extern s16b get_god_ULMO(); +extern s16b get_god_MANDOS(); extern bool_ get_com_lua(cptr promtp, int *com); diff --git a/src/lua_bind.c b/src/lua_bind.c index 82b802f2..00a0e25b 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -608,6 +608,38 @@ void desc_god(int g_idx, int d, char *desc) strncpy(deity_info[g_idx].desc[d], desc, 79); } +static int get_god_theme(cptr name) +{ + if (game_module_idx == MODULE_THEME) + { + return exec_lua(format("return GOD_%s", name)); + } + else + { + return -1; + } +} + +s16b get_god_AULE() +{ + return get_god_theme("AULE"); +} + +s16b get_god_MANDOS() +{ + return get_god_theme("MANDOS"); +} + +s16b get_god_VARDA() +{ + return get_god_theme("VARDA"); +} + +s16b get_god_ULMO() +{ + return get_god_theme("ULMO"); +} + /* * Returns the direction of the compass that y2, x2 is from y, x * the return value will be one of the following: north, south, -- cgit v1.2.3 From c92f7bf932d6e36c1aecd704a2a69d742ef7748d Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 5 Apr 2012 20:55:25 +0200 Subject: Lua: Remove HOOK_GF_EXEC and HOOK_GF_COLOR --- lib/core/s_aux.lua | 29 -------- lib/mods/theme/core/s_aux.lua | 29 -------- lib/mods/theme/scpt/gods_new.lua | 16 ---- lib/mods/theme/scpt/mkeys.lua | 16 ---- lib/mods/theme/scpt/s_geom.lua | 20 ----- lib/scpt/mkeys.lua | 16 ---- lib/scpt/s_geom.lua | 20 ----- src/defines.h | 7 +- src/spells.pkg | 11 ++- src/spells1.c | 149 +++++++++++++++++++++---------------- src/util.pkg | 156 --------------------------------------- 11 files changed, 98 insertions(+), 371 deletions(-) diff --git a/lib/core/s_aux.lua b/lib/core/s_aux.lua index 29b22fd7..97643626 100644 --- a/lib/core/s_aux.lua +++ b/lib/core/s_aux.lua @@ -621,32 +621,3 @@ end function activate_activation(spl, item) __spell_spell[spl](item) end - - -------- Add new GF type ---------- -max_gf = MAX_GF -function add_spell_type(t) - t.index = max_gf - max_gf = max_gf + 1 - assert(t.color, "No GF color") - if not t.monster then t.monster = function() end end - if not t.angry then t.angry = function() end end - if not t.object then t.object = function() end end - if not t.player then t.player = function() end end - if not t.grid then t.grid = function() end end - - add_hooks - { - [HOOK_GF_COLOR] = function (gf, new_gfx) - local t = %t - if gf == t.index then return TRUE, t.color[new_gfx + 1] end - end, - [HOOK_GF_EXEC] = function (action, who, gf, dam, rad, y, x, extra) - local t = %t - if t.index == gf then - return t[action](who, dam, rad, y, x, extra) - end - end, - } - return t.index -end diff --git a/lib/mods/theme/core/s_aux.lua b/lib/mods/theme/core/s_aux.lua index 29b22fd7..97643626 100644 --- a/lib/mods/theme/core/s_aux.lua +++ b/lib/mods/theme/core/s_aux.lua @@ -621,32 +621,3 @@ end function activate_activation(spl, item) __spell_spell[spl](item) end - - -------- Add new GF type ---------- -max_gf = MAX_GF -function add_spell_type(t) - t.index = max_gf - max_gf = max_gf + 1 - assert(t.color, "No GF color") - if not t.monster then t.monster = function() end end - if not t.angry then t.angry = function() end end - if not t.object then t.object = function() end end - if not t.player then t.player = function() end end - if not t.grid then t.grid = function() end end - - add_hooks - { - [HOOK_GF_COLOR] = function (gf, new_gfx) - local t = %t - if gf == t.index then return TRUE, t.color[new_gfx + 1] end - end, - [HOOK_GF_EXEC] = function (action, who, gf, dam, rad, y, x, extra) - local t = %t - if t.index == gf then - return t[action](who, dam, rad, y, x, extra) - end - end, - } - return t.index -end diff --git a/lib/mods/theme/scpt/gods_new.lua b/lib/mods/theme/scpt/gods_new.lua index 8153d453..9a020915 100644 --- a/lib/mods/theme/scpt/gods_new.lua +++ b/lib/mods/theme/scpt/gods_new.lua @@ -192,14 +192,6 @@ GOD_VARDA = add_god player.cur_lite = player.cur_lite + 1 end end, - [HOOK_GF_EXEC] = function (target, who, type, dam, r, y, x, m_ptr) - if (player.pgod == GOD_VARDA) then - if ((type == GF_LITE) or (type == GF_LITE_WEAK)) then - -- Raise piety for using lite - set_grace(player.grace + 1) - end - end - end, }, } @@ -276,14 +268,6 @@ GOD_ULMO = add_god end end end, - [HOOK_GF_EXEC] = function (target, who, type, dam, r, y, x, m_ptr) - if (player.pgod == GOD_ULMO) then - if ((type == GF_FIRE) or (type == GF_HELL_FIRE) or (type == GF_HOLY_FIRE) or (type == GF_LAVA_FLOW) or (type == GF_METEOR) or (type == GF_NUKE) or (type == GF_PLASMA)) then - -- Reduce piety for using any kind of fire magic - set_grace(player.grace - 5) - end - end - end, [HOOK_PROCESS_WORLD] = function() if (player.pgod == GOD_ULMO) then GRACE_DELAY = GRACE_DELAY + 1 diff --git a/lib/mods/theme/scpt/mkeys.lua b/lib/mods/theme/scpt/mkeys.lua index 07105c64..96fc2934 100644 --- a/lib/mods/theme/scpt/mkeys.lua +++ b/lib/mods/theme/scpt/mkeys.lua @@ -1,21 +1,5 @@ -- Mkeys for skills & abilities -GF_INSTA_DEATH = add_spell_type -{ - ["color"] = { TERM_DARK, 0 }, - ["angry"] = function() return TRUE, TRUE end, - ["monster"] = function(who, dam, rad, y, x, monst) - local race = race_info_idx(monst.r_idx, monst.ego) - if magik(5) == FALSE or band(race.flags1, RF1_UNIQUE) ~= FALSE or band(race.flags3, RF3_UNDEAD) ~= FALSE or band(race.flags3, RF3_NONLIVING) ~= FALSE then - return TRUE, FALSE - else - -- Reduce the exp gained this way - monst.level = monst.level / 3 - return TRUE, FALSE, 32535, 0, 0, 0, 0, 0, 0, 0, " faints.", " is sucked out of life." - end - end, -} - -- Death touch ability add_mkey { diff --git a/lib/mods/theme/scpt/s_geom.lua b/lib/mods/theme/scpt/s_geom.lua index b9730318..52ebd49a 100644 --- a/lib/mods/theme/scpt/s_geom.lua +++ b/lib/mods/theme/scpt/s_geom.lua @@ -31,17 +31,6 @@ function geomancy_random_wall(y, x) end -GF_ELEMENTAL_WALL = add_spell_type -{ - ["color"] = { TERM_GREEN, 0 }, - ["angry"] = function() return TRUE, FALSE end, - ["grid"] = function(who, dam, rad, y, x) - if player.py ~= y or player.px ~= x then - geomancy_random_wall(y, x) - end - end, -} - function geomancy_random_floor(y, x, kill_wall) local c_ptr = cave(y, x) @@ -81,15 +70,6 @@ function geomancy_random_floor(y, x, kill_wall) end -GF_ELEMENTAL_GROWTH = add_spell_type -{ - ["color"] = { TERM_GREEN, 0 }, - ["angry"] = function() return TRUE, FALSE end, - ["grid"] = function(who, dam, rad, y, x) - geomancy_random_floor(y, x) - end, -} - CALL_THE_ELEMENTS = add_spell { ["name"] = "Call the Elements", diff --git a/lib/scpt/mkeys.lua b/lib/scpt/mkeys.lua index 07105c64..96fc2934 100644 --- a/lib/scpt/mkeys.lua +++ b/lib/scpt/mkeys.lua @@ -1,21 +1,5 @@ -- Mkeys for skills & abilities -GF_INSTA_DEATH = add_spell_type -{ - ["color"] = { TERM_DARK, 0 }, - ["angry"] = function() return TRUE, TRUE end, - ["monster"] = function(who, dam, rad, y, x, monst) - local race = race_info_idx(monst.r_idx, monst.ego) - if magik(5) == FALSE or band(race.flags1, RF1_UNIQUE) ~= FALSE or band(race.flags3, RF3_UNDEAD) ~= FALSE or band(race.flags3, RF3_NONLIVING) ~= FALSE then - return TRUE, FALSE - else - -- Reduce the exp gained this way - monst.level = monst.level / 3 - return TRUE, FALSE, 32535, 0, 0, 0, 0, 0, 0, 0, " faints.", " is sucked out of life." - end - end, -} - -- Death touch ability add_mkey { diff --git a/lib/scpt/s_geom.lua b/lib/scpt/s_geom.lua index b9730318..52ebd49a 100644 --- a/lib/scpt/s_geom.lua +++ b/lib/scpt/s_geom.lua @@ -31,17 +31,6 @@ function geomancy_random_wall(y, x) end -GF_ELEMENTAL_WALL = add_spell_type -{ - ["color"] = { TERM_GREEN, 0 }, - ["angry"] = function() return TRUE, FALSE end, - ["grid"] = function(who, dam, rad, y, x) - if player.py ~= y or player.px ~= x then - geomancy_random_wall(y, x) - end - end, -} - function geomancy_random_floor(y, x, kill_wall) local c_ptr = cave(y, x) @@ -81,15 +70,6 @@ function geomancy_random_floor(y, x, kill_wall) end -GF_ELEMENTAL_GROWTH = add_spell_type -{ - ["color"] = { TERM_GREEN, 0 }, - ["angry"] = function() return TRUE, FALSE end, - ["grid"] = function(who, dam, rad, y, x) - geomancy_random_floor(y, x) - end, -} - CALL_THE_ELEMENTS = add_spell { ["name"] = "Call the Elements", diff --git a/src/defines.h b/src/defines.h index 1569012b..e0851fd4 100644 --- a/src/defines.h +++ b/src/defines.h @@ -2674,7 +2674,10 @@ #define GF_TRAP_DEMONSOUL 108 #define GF_ATTACK 109 #define GF_CHARM_UNMOVING 110 -#define MAX_GF 111 +#define GF_INSTA_DEATH 111 +#define GF_ELEMENTAL_WALL 112 +#define GF_ELEMENTAL_GROWTH 113 +#define MAX_GF 114 /* * Some things which induce learning @@ -4488,8 +4491,6 @@ #define HOOK_EAT 55 #define HOOK_DIE 56 #define HOOK_CALC_HP 57 -#define HOOK_GF_COLOR 58 -#define HOOK_GF_EXEC 59 #define HOOK_CALC_MANA 60 #define HOOK_LOAD_END 61 #define HOOK_RECALL 62 diff --git a/src/spells.pkg b/src/spells.pkg index cbbc2dc5..5575d0f4 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -340,8 +340,17 @@ typedef unsigned int u32b; /** @def GF_CHARM_UNMOVING */ #define GF_CHARM_UNMOVING 110 +/** @def GF_INSTA_DEATH */ +#define GF_INSTA_DEATH 111 + +/** @def GF_ELEMENTAL_WALL */ +#define GF_ELEMENTAL_WALL 112 + +/** @def GF_ELEMENTAL_GROWTH */ +#define GF_ELEMENTAL_GROWTH 113 + /** @def MAX_GF */ -#define MAX_GF 111 +#define MAX_GF 114 /** @} */ /** @name Spell Projection Flags diff --git a/src/spells1.c b/src/spells1.c index 9bfc6fe2..e99bbc23 100644 --- a/src/spells1.c +++ b/src/spells1.c @@ -939,6 +939,36 @@ void recall_player(int d, int f) } +/* + * Check the gods + */ +static void project_check_gods(int typ) +{ + if (p_ptr->pgod == get_god_VARDA()) + { + if ((typ == GF_LITE) || (typ == GF_LITE_WEAK)) + { + /* Raise piety for using lite */ + set_grace(p_ptr->grace + 1); + } + } + + if (p_ptr->pgod == get_god_ULMO()) + { + if ((typ == GF_FIRE) || + (typ == GF_HELL_FIRE) || + (typ == GF_HOLY_FIRE) || + (typ == GF_LAVA_FLOW) || + (typ == GF_METEOR) || + (typ == GF_NUKE) || + (typ == GF_PLASMA)) + { + /* Reduce piety for using any kind of fire magic */ + set_grace(p_ptr->grace - 5); + } + } +} + /* * Get a legal "multi-hued" color for drawing "spells" @@ -988,12 +1018,6 @@ static byte mh_attr(int max) */ byte spell_color(int type) { - /* Hooks! */ - if (process_hooks_ret(HOOK_GF_COLOR, "d", "(d,d)", type, streq(ANGBAND_GRAF, "new"))) - { - return process_hooks_return[0].num; - } - /* Check if A.B.'s new graphics should be used (rr9) */ if (streq(ANGBAND_GRAF, "new")) { @@ -1075,6 +1099,11 @@ byte spell_color(int type) case GF_TELEKINESIS: case GF_DOMINATION: return (0x09); + case GF_INSTA_DEATH: + return 0; + case GF_ELEMENTAL_WALL: + case GF_ELEMENTAL_GROWTH: + return 0; } } @@ -1161,6 +1190,11 @@ byte spell_color(int type) case GF_TELEKINESIS: case GF_DOMINATION: return (randint(3) != 1 ? TERM_L_BLUE : TERM_WHITE); + case GF_INSTA_DEATH: + return TERM_DARK; + case GF_ELEMENTAL_WALL: + case GF_ELEMENTAL_GROWTH: + return TERM_GREEN; } } @@ -2975,6 +3009,9 @@ static bool_ project_f(int who, int r, int y, int x, int dam, int typ) /* Remember if the grid is with the LoS of player */ seen = player_can_see_bold(y, x); + /* Check gods */ + project_check_gods(typ); + /* Analyze the type */ switch (typ) { @@ -3793,14 +3830,19 @@ static bool_ project_f(int who, int r, int y, int x, int dam, int typ) obvious = TRUE; break; } - default: + + case GF_ELEMENTAL_WALL: { - /* Hooks! */ - if (process_hooks_ret(HOOK_GF_EXEC, "dd", "(s,d,d,d,d,d,d)", "grid", who, typ, dam, r, y, x)) - { - obvious = process_hooks_return[0].num; - flag = process_hooks_return[1].num; + if ((p_ptr->py != y) || (p_ptr->px != x)) { + exec_lua(format("geomancy_random_wall(%d,%d);", y, x)); } + + break; + } + + case GF_ELEMENTAL_GROWTH: + { + exec_lua(format("geomancy_random_floor(%d, %d)", y, x)); break; } } @@ -3879,6 +3921,8 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ) /* Reduce damage by distance */ dam = (dam + r) / (r + 1); + /* Check new gods. */ + project_check_gods(typ); /* Scan all objects in the grid */ for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) @@ -4173,15 +4217,7 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ) break; } default: - { - /* Hooks! */ - if (process_hooks_ret(HOOK_GF_EXEC, "dd", "(s,d,d,d,d,d,d,O)", "object", who, typ, dam, r, y, x, o_ptr)) - { - obvious = process_hooks_return[0].num; - do_kill = process_hooks_return[1].num; - } - break; - } + break; } @@ -4385,6 +4421,9 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ) dam = (dam + r) / (r + 1); + /* Check gods */ + project_check_gods(typ); + /* Get the monster name (BEFORE polymorphing) */ monster_desc(m_name, m_ptr, 0); @@ -4484,14 +4523,13 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ) if (r_ptr->flags3 & RF3_HURT_LITE) get_angry = TRUE; break; - default: - /* Hooks! */ - if (process_hooks_ret(HOOK_GF_EXEC, "d", "(s,d,d,d,d,d,d,M)", "angry", who, typ, dam, r, y, x, m_ptr)) - { - get_angry = process_hooks_return[0].num; - } - else - get_angry = TRUE; + case GF_INSTA_DEATH: + get_angry = TRUE; + break; + case GF_ELEMENTAL_GROWTH: + case GF_ELEMENTAL_WALL: + get_angry = FALSE; + break; } /* Now anger it if appropriate */ @@ -6746,36 +6784,25 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ) break; } - /* Default */ - default: + case GF_INSTA_DEATH: { - /* Hooks! */ - if (process_hooks_ret(HOOK_GF_EXEC, "dddddddddss", "(s,d,d,d,d,d,d,M)", "monster", who, typ, dam, r, y, x, m_ptr)) - { - obvious = process_hooks_return[0].num; - dam = process_hooks_return[1].num; - do_stun = process_hooks_return[2].num; - do_fear = process_hooks_return[3].num; - do_conf = process_hooks_return[4].num; - do_dist = process_hooks_return[5].num; - do_pois = process_hooks_return[6].num; - do_cut = process_hooks_return[7].num; - do_poly = process_hooks_return[8].num; - if (process_hooks_return[9].str != NULL) - note = process_hooks_return[9].str; - if (process_hooks_return[10].str != NULL) - note_dies = process_hooks_return[10].str; - } - else - { - /* Irrelevant */ + if (magik(95) && !(r_ptr->flags1 & RF1_UNIQUE) && !(r_ptr->flags3 & RF3_UNDEAD) && !(r_ptr->flags3 & RF3_NONLIVING)) { + /* Kill outright, but reduce exp. */ + m_ptr->level = m_ptr->level / 3; + dam = 32535; /* Should be enough */ + note = " faints."; + note_dies = " is sucked out of life."; + } else { + /* No effect */ skipped = TRUE; - - /* No damage */ - dam = 0; } + break; } + + default: + skipped = TRUE; + break; } @@ -8018,17 +8045,9 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad /* Default */ default: { - /* Hooks! */ - if (process_hooks_ret(HOOK_GF_EXEC, "dd", "(s,d,d,d,d,d,d)", "player", who, typ, dam, r, y, x)) - { - obvious = process_hooks_return[0].num; - dam = process_hooks_return[1].num; - } - else - { - /* No damage */ - dam = 0; - } + /* No damage */ + dam = 0; + break; } } diff --git a/src/util.pkg b/src/util.pkg index 183a28f2..50f69e79 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -713,162 +713,6 @@ typedef unsigned int u32b; */ #define HOOK_CALC_HP 57 -/** @def HOOK_GF_COLOR - * @brief Set color for spell. - * @param Number type \n type of spell. - * @brief Type - * @param Number file \n if this is 0 use ANGBAND_GRAF, otherwise use "new". - * @brief File - * @return Boolean \n TRUE if hook sets a color, otherwise FALSE. - * @return Number color \n The color for the spell. - * @note - * If the hook returns TRUE, spell_color() returns the hook's color, otherwise - * the function continues. - * @note (see file spells1.c) - */ -#define HOOK_GF_COLOR 58 - -/** @def HOOK_GF_EXEC - * @brief A spell to damage terrain features.\n - * @param String target \n "grid" to indicate spell damages terrain. - * @brief Target - * @param Number who \n the source of the spell. - * @brief Source - * @param Number type \n the type of spell. - * @brief Type - * @param Number dam \n the number of hit points of damage. - * @brief Damage - * @param Number r \n the radius of the spell. - * @brief Radius - * @param Number y \n the y-coordinate of the target. - * @brief Y-coordinate - * @param Number x \n the x-coordinate of the target. - * @brief X-coordinate - * @return Boolean \n TRUE if spell was cast, otherwise FALSE. - * @return Number obvious \n TRUE if the player notices the spell, otherwise - * FALSE. - * @return Number flag \n TRUE if the player is affected, otherwise FALSE. - * @note - * If the hook returns TRUE, the hook sets the "obvious" and "flag" fields. - * @note (see file spells1.c) - */ -/** @def HOOK_GF_EXEC - * @brief A spell to damage objects.\n - * @param String target \n "object" to indicate spell damages objects. - * @brief Target - * @param Number who \n the source of the spell. - * @brief Source - * @param Number type \n the type of spell. - * @brief Type - * @param Number dam \n the number of hit points of damage. - * @brief Damage - * @param Number r \n the radius of the spell. - * @brief Radius - * @param Number y \n the y-coordinate of the target. - * @brief Y-coordinate - * @param Number x \n the x-coordinate of the target. - * @brief X-coordinate - * @param Object o_ptr \n the object which is the target of the spell. - * @brief Object - * @return Boolean \n TRUE if spell was cast, otherwise FALSE. - * @return Number obvious \n TRUE if the player notices the spell, otherwise - * FALSE. - * @return Number flag \n TRUE if the player is affected, otherwise FALSE. - * @note - * If the hook returns TRUE, the hook sets the "obvious" and "do_kill" fields. - * @note (see file spells1.c) - */ -/** @def HOOK_GF_EXEC - * @brief A spell to damage monsters.\n - * @param String target \n "angry" to indicate spell angers a friend. - * @brief Target - * @param Number who \n the source of the spell. - * @brief Source - * @param Number type \n the type of spell. - * @brief Type - * @param Number dam \n the number of hit points of damage. - * @brief Damage - * @param Number r \n the radius of the spell. - * @brief Radius - * @param Number y \n the y-coordinate of the target. - * @brief Y-coordinate - * @param Number x \n the x-coordinate of the target. - * @brief X-coordinate - * @param Monster m_ptr \n the monster which is the target of the spell. - * @brief Monster - * @return Boolean \n TRUE if spell was cast, otherwise FALSE. - * @return Number get_angry \n TRUE if the monster gets angry, otherwise FALSE. - * @note - * If the hook returns TRUE, the hook sets the "get_angry" field. - * @note (see file spells1.c) - */ -/** @def HOOK_GF_EXEC - * @brief A spell to damage monsters.\n - * @param String target \n "monster" to indicate spell damages monsters. - * @brief Target - * @param Number who \n the source of the spell. - * @brief Source - * @param Number type \n the type of spell. - * @brief Type - * @param Number dam \n the number of hit points of damage. - * @brief Damage - * @param Number r \n the radius of the spell. - * @brief Radius - * @param Number y \n the y-coordinate of the target. - * @brief Y-coordinate - * @param Number x \n the x-coordinate of the target. - * @brief X-coordinate - * @param Monster m_ptr \n the monster which is the target of the spell. - * @brief Monster - * @return Boolean \n TRUE if spell was cast, otherwise FALSE. - * @return Number obvious \n TRUE if the player notices the spell, otherwise - * FALSE. - * @return Number dam \n The damage the monster takes. - * @return Number do_stun \n TRUE if the monster is stunned, otherwise FALSE. - * @return Number do_fear \n TRUE if the monster is frightened, otherwise - * FALSE. - * @return Number do_conf \n TRUE if the monster is confused, otherwise FALSE. - * @return Number do_dist \n TRUE if the monster is disturbed, otherwise FALSE. - * @return Number do_pois \n TRUE if the monster is poisoned, otherwise FALSE. - * @return Number do_cut \n TRUE if the monster is wounded, otherwise FALSE. - * @return Number do_poly \n TRUE if the monster is polymorphed, otherwise - * FALSE. - * @return String note \n The message displayed if the monster if affected. - * @return String note_dies \n The message displayed if the monster dies. - * @note - * If the hook returns TRUE, the hook sets the "obvious", "dam", "do_stun", - * "do_fear", "do_conf", "do_dist", "do_pois", "do_cut", "do_poly", "note", - * and "note dies" fields, otherwise the spell has no effect and does no - * damage. - * @note (see file spells1.c) - */ -/** @def HOOK_GF_EXEC - * @brief A spell to damage the player.\n - * @param String target \n "player" to indicate spell damages the player. - * @brief Target - * @param Number who \n the source of the spell. - * @brief Source - * @param Number type \n the type of spell. - * @brief Type - * @param Number dam \n the number of hit points of damage. - * @brief Damage - * @param Number r \n the radius of the spell. - * @brief Radius - * @param Number y \n the y-coordinate of the target. - * @brief Y-coordinate - * @param Number x \n the x-coordinate of the target. - * @brief X-coordinate - * @return Boolean \n TRUE if spell was cast, otherwise FALSE. - * @return Number obvious \n TRUE if the player notices the spell, otherwise - * FALSE. - * @return Number dam \n The damage the player takes. - * @note - * If the hook returns TRUE, the hook sets the "obvious" and "dam" fields, - * otherwise there is no damage. - * @note (see file spells1.c) - */ -#define HOOK_GF_EXEC 59 - /** @def HOOK_CALC_MANA * @brief Recalculate player SP (spell points).\n * @param Number msp \n the player's new maximum spell points. -- cgit v1.2.3 From 46498dfaab2cb0698822397b43039e3ecf605a1e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 5 Apr 2012 21:03:18 +0200 Subject: Lua: Move geomancy spell effects to C --- lib/core/dungeon.lua | 26 --- lib/mods/theme/core/dungeon.lua | 26 --- lib/mods/theme/scpt/s_geom.lua | 252 +---------------------------- lib/scpt/s_geom.lua | 252 +---------------------------- src/externs.h | 5 + src/lua_bind.c | 5 + src/spells.pkg | 7 + src/spells1.c | 5 +- src/spells2.c | 347 ++++++++++++++++++++++++++++++++++++++++ 9 files changed, 370 insertions(+), 555 deletions(-) diff --git a/lib/core/dungeon.lua b/lib/core/dungeon.lua index d91d785b..ba4fd38a 100644 --- a/lib/core/dungeon.lua +++ b/lib/core/dungeon.lua @@ -20,32 +20,6 @@ function explode_dir(dir) return ddy[dir + 1], ddx[dir + 1] end -function rotate_dir(dir, mov) - if mov > 0 then - if dir == 7 then dir = 8 - elseif dir == 8 then dir = 9 - elseif dir == 9 then dir = 6 - elseif dir == 6 then dir = 3 - elseif dir == 3 then dir = 2 - elseif dir == 2 then dir = 1 - elseif dir == 1 then dir = 4 - elseif dir == 4 then dir = 7 - end - elseif mov < 0 then - if dir == 7 then dir = 4 - elseif dir == 4 then dir = 1 - elseif dir == 1 then dir = 2 - elseif dir == 2 then dir = 3 - elseif dir == 3 then dir = 6 - elseif dir == 6 then dir = 9 - elseif dir == 9 then dir = 8 - elseif dir == 8 then dir = 7 - end - end - - return dir -end - -- Place a trap for a specific level function place_trap(y, x, level) local old_dun = dun_level diff --git a/lib/mods/theme/core/dungeon.lua b/lib/mods/theme/core/dungeon.lua index d91d785b..ba4fd38a 100644 --- a/lib/mods/theme/core/dungeon.lua +++ b/lib/mods/theme/core/dungeon.lua @@ -20,32 +20,6 @@ function explode_dir(dir) return ddy[dir + 1], ddx[dir + 1] end -function rotate_dir(dir, mov) - if mov > 0 then - if dir == 7 then dir = 8 - elseif dir == 8 then dir = 9 - elseif dir == 9 then dir = 6 - elseif dir == 6 then dir = 3 - elseif dir == 3 then dir = 2 - elseif dir == 2 then dir = 1 - elseif dir == 1 then dir = 4 - elseif dir == 4 then dir = 7 - end - elseif mov < 0 then - if dir == 7 then dir = 4 - elseif dir == 4 then dir = 1 - elseif dir == 1 then dir = 2 - elseif dir == 2 then dir = 3 - elseif dir == 3 then dir = 6 - elseif dir == 6 then dir = 9 - elseif dir == 9 then dir = 8 - elseif dir == 8 then dir = 7 - end - end - - return dir -end - -- Place a trap for a specific level function place_trap(y, x, level) local old_dun = dun_level diff --git a/lib/mods/theme/scpt/s_geom.lua b/lib/mods/theme/scpt/s_geom.lua index 52ebd49a..d152bc25 100644 --- a/lib/mods/theme/scpt/s_geom.lua +++ b/lib/mods/theme/scpt/s_geom.lua @@ -1,75 +1,5 @@ -- Geomancy school -function geomancy_random_wall(y, x) - local c_ptr = cave(y, x) - - -- Do not destroy permanent things - if cave_is(c_ptr, FF1_PERMANENT) ~= FALSE then return end - - local feat = nil - local table = - { - [1] = { SKILL_FIRE, FEAT_SANDWALL, 1}, - - [2] = { SKILL_WATER, FEAT_TREES, 1}, - [3] = { SKILL_WATER, FEAT_ICE_WALL, 12}, - - [4] = { SKILL_EARTH, FEAT_WALL_EXTRA, 1}, - } - - while feat == nil do - local t = table[randint(getn(table))] - - -- Do we meet the requirements ? - -- And then select the features based on skill proportions - if get_skill(t[1]) >= t[3] and magik(get_skill_scale(t[1], 100)) == TRUE then - feat = t[2] - end - end - - cave_set_feat(y, x, feat) -end - - -function geomancy_random_floor(y, x, kill_wall) - local c_ptr = cave(y, x) - - -- Do not destroy permanent things - if cave_is(c_ptr, FF1_PERMANENT) ~= FALSE then return end - if not kill_wall then - if cave_is(c_ptr, FF1_FLOOR) ~= TRUE then return end - end - - local feat = nil - local table = - { - [1] = { SKILL_FIRE, FEAT_SAND, 1}, - [2] = { SKILL_FIRE, FEAT_SHAL_LAVA, 8}, - [3] = { SKILL_FIRE, FEAT_DEEP_LAVA, 18}, - - [4] = { SKILL_WATER, FEAT_SHAL_WATER, 1}, - [5] = { SKILL_WATER, FEAT_DEEP_WATER, 8}, - [6] = { SKILL_WATER, FEAT_ICE, 18}, - - [7] = { SKILL_EARTH, FEAT_GRASS, 1}, - [8] = { SKILL_EARTH, FEAT_FLOWER, 8}, - [9] = { SKILL_EARTH, FEAT_DARK_PIT, 18}, - } - - while feat == nil do - local t = table[randint(getn(table))] - - -- Do we meet the requirements ? - -- And then select the features based on skill proportions - if get_skill(t[1]) >= t[3] and magik(get_skill_scale(t[1], 100)) == TRUE then - feat = t[2] - end - end - - cave_set_feat(y, x, feat) -end - - CALL_THE_ELEMENTS = add_spell { ["name"] = "Call the Elements", @@ -103,114 +33,6 @@ CALL_THE_ELEMENTS = add_spell } } --- Seperate function because an other spell needs it -function channel_the_elements(y, x, level, silent) - local t = - { - -- Earth stuff - [FEAT_GRASS] = function() - hp_player(player.mhp * (5 + get_skill_scale(SKILL_EARTH, 20)) / 100) - end, - [FEAT_FLOWER] = function() - hp_player(player.mhp * (5 + get_skill_scale(SKILL_EARTH, 30)) / 100) - end, - [FEAT_DARK_PIT] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - local type = GF_DARK - if get_skill(SKILL_EARTH) >= 18 then type = GF_NETHER end - fire_bolt(type, dir, damroll(10, get_skill(SKILL_EARTH))) - end, - - -- Water stuff - [FEAT_SHAL_WATER] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - local type = GF_WATER - if get_skill(SKILL_WATER) >= 18 then type = GF_WAVE end - - if get_skill(SKILL_WATER) >= 8 then - fire_beam(type, dir, damroll(3, get_skill(SKILL_WATER))) - else - fire_bolt(type, dir, damroll(3, get_skill(SKILL_WATER))) - end - end, - [FEAT_DEEP_WATER] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - local type = GF_WATER - if get_skill(SKILL_WATER) >= 18 then type = GF_WAVE end - - if get_skill(SKILL_WATER) >= 8 then - fire_beam(type, dir, damroll(5, get_skill(SKILL_WATER))) - else - fire_bolt(type, dir, damroll(5, get_skill(SKILL_WATER))) - end - end, - [FEAT_ICE] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - if get_skill(SKILL_WATER) >= 12 then - fire_ball(GF_ICE, dir, get_skill_scale(SKILL_WATER, 340), 3) - else - fire_bolt(GF_ICE, dir, damroll(3, get_skill(SKILL_WATER))) - end - end, - - -- Fire stuff - [FEAT_SAND] = function() - local type - if (get_level(FIERYAURA, 50) >= 8) then - type = SHIELD_GREAT_FIRE - else - type = SHIELD_FIRE - end - local dur = randint(20) + %level + get_skill(SKILL_AIR) - set_shield(dur, 0, type, 5 + get_skill_scale(SKILL_FIRE, 20), 5 + get_skill_scale(SKILL_FIRE, 14)) - set_blind(dur) - end, - [FEAT_SHAL_LAVA] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - if get_skill(SKILL_FIRE) >= 15 then - fire_bolt(GF_HELL_FIRE, dir, damroll(get_skill_scale(SKILL_FIRE, 30), 15)) - else - fire_bolt(GF_FIRE, dir, damroll(get_skill_scale(SKILL_FIRE, 30), 15)) - end - end, - [FEAT_DEEP_LAVA] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - if get_skill(SKILL_FIRE) >= 15 then - fire_ball(GF_HELL_FIRE, dir, damroll(get_skill_scale(SKILL_FIRE, 30), 15), 3) - else - fire_ball(GF_FIRE, dir, damroll(get_skill_scale(SKILL_FIRE, 30), 15), 3) - end - end, - } - - if t[cave(y, x).feat] then - t[cave(y, x).feat]() - - if magik(100 - level) == TRUE then - if cave(y, x).feat == FEAT_FLOWER then - cave_set_feat(y, x, FEAT_GRASS) - else - cave_set_feat(y, x, FEAT_FLOOR) - end - msg_print("The area is drained.") - end - elseif not silent then - msg_print("You cannot channel this area.") - end -end - CHANNEL_ELEMENTS = add_spell { ["name"] = "Channel Elements", @@ -223,7 +45,7 @@ CHANNEL_ELEMENTS = add_spell ["blind"] = FALSE, ["random"] = 0, ["spell"] = function() - channel_the_elements(player.py, player.px, get_level(CHANNEL_ELEMENTS), nil) + channel_the_elements(player.py, player.px, get_level(CHANNEL_ELEMENTS)) return TRUE end, ["info"] = function() @@ -364,76 +186,6 @@ VAPORIZE = add_spell } } -geomancy_can_tunnel = -{ - [FEAT_WALL_EXTRA] = TRUE, - [FEAT_WALL_OUTER] = TRUE, - [FEAT_WALL_INNER] = TRUE, - [FEAT_WALL_SOLID] = TRUE, - - [FEAT_MAGMA] = TRUE, - [FEAT_QUARTZ] = TRUE, - [FEAT_MAGMA_H] = TRUE, - [FEAT_QUARTZ_H] = TRUE, - [FEAT_MAGMA_K] = TRUE, - [FEAT_QUARTZ_K] = TRUE, - - [FEAT_TREES] = TRUE, - [FEAT_DEAD_TREE] = TRUE, - - [FEAT_SANDWALL] = TRUE, - [FEAT_SANDWALL_H] = TRUE, - [FEAT_SANDWALL_K] = TRUE, - - [FEAT_ICE_WALL] = TRUE, -} - --- Dig & sprew -function geomancy_dig(oy, ox, dir, length) - local dy, dx = explode_dir(dir) - local y = dy + oy - local x = dx + ox - - for i = 1, length do - local c_ptr = cave(y, x) - local ox = x - dx - local oy = y - dy - - -- stop at the end of tunnelable things - if not geomancy_can_tunnel[c_ptr.feat] then break end - - if geomancy_can_tunnel[cave(y - 1, x - 1).feat] then geomancy_random_wall(y - 1, x - 1) end - if geomancy_can_tunnel[cave(y - 1, x).feat] then geomancy_random_wall(y - 1, x) end - if geomancy_can_tunnel[cave(y - 1, x + 1).feat] then geomancy_random_wall(y - 1, x + 1) end - - if geomancy_can_tunnel[cave(y, x - 1).feat] then geomancy_random_wall(y, x - 1) end - if geomancy_can_tunnel[cave(y, x + 1).feat] then geomancy_random_wall(y, x + 1) end - - if geomancy_can_tunnel[cave(y + 1, x - 1).feat] then geomancy_random_wall(y + 1, x - 1) end - if geomancy_can_tunnel[cave(y + 1, x).feat] then geomancy_random_wall(y + 1, x) end - if geomancy_can_tunnel[cave(y + 1, x + 1).feat] then geomancy_random_wall(y + 1, x + 1) end - - y = y + dy - x = x + dx - end - - y = y - dy - x = x - dx - while (y ~= oy) or (x ~= ox) do - geomancy_random_floor(y, x, TRUE) - - -- Should we branch ? - if magik(20) == TRUE then - local rot = 1 - if magik(50) == TRUE then rot = -1 end - geomancy_dig(y, x, rotate_dir(dir, rot), length / 3) - end - - y = y - dy - x = x - dx - end -end - GEOLYSIS = add_spell { ["name"] = "Geolysis", @@ -473,7 +225,7 @@ add_hooks { [HOOK_MOVED] = function(oy, ox) if player.dripping_tread > 0 then - geomancy_random_floor(oy, ox) + geomancy_random_floor(oy, ox, FALSE) player.dripping_tread = player.dripping_tread - 1 if player.dripping_tread == 0 then msg_print("You stop dripping raw elemental energies.") diff --git a/lib/scpt/s_geom.lua b/lib/scpt/s_geom.lua index 52ebd49a..d152bc25 100644 --- a/lib/scpt/s_geom.lua +++ b/lib/scpt/s_geom.lua @@ -1,75 +1,5 @@ -- Geomancy school -function geomancy_random_wall(y, x) - local c_ptr = cave(y, x) - - -- Do not destroy permanent things - if cave_is(c_ptr, FF1_PERMANENT) ~= FALSE then return end - - local feat = nil - local table = - { - [1] = { SKILL_FIRE, FEAT_SANDWALL, 1}, - - [2] = { SKILL_WATER, FEAT_TREES, 1}, - [3] = { SKILL_WATER, FEAT_ICE_WALL, 12}, - - [4] = { SKILL_EARTH, FEAT_WALL_EXTRA, 1}, - } - - while feat == nil do - local t = table[randint(getn(table))] - - -- Do we meet the requirements ? - -- And then select the features based on skill proportions - if get_skill(t[1]) >= t[3] and magik(get_skill_scale(t[1], 100)) == TRUE then - feat = t[2] - end - end - - cave_set_feat(y, x, feat) -end - - -function geomancy_random_floor(y, x, kill_wall) - local c_ptr = cave(y, x) - - -- Do not destroy permanent things - if cave_is(c_ptr, FF1_PERMANENT) ~= FALSE then return end - if not kill_wall then - if cave_is(c_ptr, FF1_FLOOR) ~= TRUE then return end - end - - local feat = nil - local table = - { - [1] = { SKILL_FIRE, FEAT_SAND, 1}, - [2] = { SKILL_FIRE, FEAT_SHAL_LAVA, 8}, - [3] = { SKILL_FIRE, FEAT_DEEP_LAVA, 18}, - - [4] = { SKILL_WATER, FEAT_SHAL_WATER, 1}, - [5] = { SKILL_WATER, FEAT_DEEP_WATER, 8}, - [6] = { SKILL_WATER, FEAT_ICE, 18}, - - [7] = { SKILL_EARTH, FEAT_GRASS, 1}, - [8] = { SKILL_EARTH, FEAT_FLOWER, 8}, - [9] = { SKILL_EARTH, FEAT_DARK_PIT, 18}, - } - - while feat == nil do - local t = table[randint(getn(table))] - - -- Do we meet the requirements ? - -- And then select the features based on skill proportions - if get_skill(t[1]) >= t[3] and magik(get_skill_scale(t[1], 100)) == TRUE then - feat = t[2] - end - end - - cave_set_feat(y, x, feat) -end - - CALL_THE_ELEMENTS = add_spell { ["name"] = "Call the Elements", @@ -103,114 +33,6 @@ CALL_THE_ELEMENTS = add_spell } } --- Seperate function because an other spell needs it -function channel_the_elements(y, x, level, silent) - local t = - { - -- Earth stuff - [FEAT_GRASS] = function() - hp_player(player.mhp * (5 + get_skill_scale(SKILL_EARTH, 20)) / 100) - end, - [FEAT_FLOWER] = function() - hp_player(player.mhp * (5 + get_skill_scale(SKILL_EARTH, 30)) / 100) - end, - [FEAT_DARK_PIT] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - local type = GF_DARK - if get_skill(SKILL_EARTH) >= 18 then type = GF_NETHER end - fire_bolt(type, dir, damroll(10, get_skill(SKILL_EARTH))) - end, - - -- Water stuff - [FEAT_SHAL_WATER] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - local type = GF_WATER - if get_skill(SKILL_WATER) >= 18 then type = GF_WAVE end - - if get_skill(SKILL_WATER) >= 8 then - fire_beam(type, dir, damroll(3, get_skill(SKILL_WATER))) - else - fire_bolt(type, dir, damroll(3, get_skill(SKILL_WATER))) - end - end, - [FEAT_DEEP_WATER] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - local type = GF_WATER - if get_skill(SKILL_WATER) >= 18 then type = GF_WAVE end - - if get_skill(SKILL_WATER) >= 8 then - fire_beam(type, dir, damroll(5, get_skill(SKILL_WATER))) - else - fire_bolt(type, dir, damroll(5, get_skill(SKILL_WATER))) - end - end, - [FEAT_ICE] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - if get_skill(SKILL_WATER) >= 12 then - fire_ball(GF_ICE, dir, get_skill_scale(SKILL_WATER, 340), 3) - else - fire_bolt(GF_ICE, dir, damroll(3, get_skill(SKILL_WATER))) - end - end, - - -- Fire stuff - [FEAT_SAND] = function() - local type - if (get_level(FIERYAURA, 50) >= 8) then - type = SHIELD_GREAT_FIRE - else - type = SHIELD_FIRE - end - local dur = randint(20) + %level + get_skill(SKILL_AIR) - set_shield(dur, 0, type, 5 + get_skill_scale(SKILL_FIRE, 20), 5 + get_skill_scale(SKILL_FIRE, 14)) - set_blind(dur) - end, - [FEAT_SHAL_LAVA] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - if get_skill(SKILL_FIRE) >= 15 then - fire_bolt(GF_HELL_FIRE, dir, damroll(get_skill_scale(SKILL_FIRE, 30), 15)) - else - fire_bolt(GF_FIRE, dir, damroll(get_skill_scale(SKILL_FIRE, 30), 15)) - end - end, - [FEAT_DEEP_LAVA] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - if get_skill(SKILL_FIRE) >= 15 then - fire_ball(GF_HELL_FIRE, dir, damroll(get_skill_scale(SKILL_FIRE, 30), 15), 3) - else - fire_ball(GF_FIRE, dir, damroll(get_skill_scale(SKILL_FIRE, 30), 15), 3) - end - end, - } - - if t[cave(y, x).feat] then - t[cave(y, x).feat]() - - if magik(100 - level) == TRUE then - if cave(y, x).feat == FEAT_FLOWER then - cave_set_feat(y, x, FEAT_GRASS) - else - cave_set_feat(y, x, FEAT_FLOOR) - end - msg_print("The area is drained.") - end - elseif not silent then - msg_print("You cannot channel this area.") - end -end - CHANNEL_ELEMENTS = add_spell { ["name"] = "Channel Elements", @@ -223,7 +45,7 @@ CHANNEL_ELEMENTS = add_spell ["blind"] = FALSE, ["random"] = 0, ["spell"] = function() - channel_the_elements(player.py, player.px, get_level(CHANNEL_ELEMENTS), nil) + channel_the_elements(player.py, player.px, get_level(CHANNEL_ELEMENTS)) return TRUE end, ["info"] = function() @@ -364,76 +186,6 @@ VAPORIZE = add_spell } } -geomancy_can_tunnel = -{ - [FEAT_WALL_EXTRA] = TRUE, - [FEAT_WALL_OUTER] = TRUE, - [FEAT_WALL_INNER] = TRUE, - [FEAT_WALL_SOLID] = TRUE, - - [FEAT_MAGMA] = TRUE, - [FEAT_QUARTZ] = TRUE, - [FEAT_MAGMA_H] = TRUE, - [FEAT_QUARTZ_H] = TRUE, - [FEAT_MAGMA_K] = TRUE, - [FEAT_QUARTZ_K] = TRUE, - - [FEAT_TREES] = TRUE, - [FEAT_DEAD_TREE] = TRUE, - - [FEAT_SANDWALL] = TRUE, - [FEAT_SANDWALL_H] = TRUE, - [FEAT_SANDWALL_K] = TRUE, - - [FEAT_ICE_WALL] = TRUE, -} - --- Dig & sprew -function geomancy_dig(oy, ox, dir, length) - local dy, dx = explode_dir(dir) - local y = dy + oy - local x = dx + ox - - for i = 1, length do - local c_ptr = cave(y, x) - local ox = x - dx - local oy = y - dy - - -- stop at the end of tunnelable things - if not geomancy_can_tunnel[c_ptr.feat] then break end - - if geomancy_can_tunnel[cave(y - 1, x - 1).feat] then geomancy_random_wall(y - 1, x - 1) end - if geomancy_can_tunnel[cave(y - 1, x).feat] then geomancy_random_wall(y - 1, x) end - if geomancy_can_tunnel[cave(y - 1, x + 1).feat] then geomancy_random_wall(y - 1, x + 1) end - - if geomancy_can_tunnel[cave(y, x - 1).feat] then geomancy_random_wall(y, x - 1) end - if geomancy_can_tunnel[cave(y, x + 1).feat] then geomancy_random_wall(y, x + 1) end - - if geomancy_can_tunnel[cave(y + 1, x - 1).feat] then geomancy_random_wall(y + 1, x - 1) end - if geomancy_can_tunnel[cave(y + 1, x).feat] then geomancy_random_wall(y + 1, x) end - if geomancy_can_tunnel[cave(y + 1, x + 1).feat] then geomancy_random_wall(y + 1, x + 1) end - - y = y + dy - x = x + dx - end - - y = y - dy - x = x - dx - while (y ~= oy) or (x ~= ox) do - geomancy_random_floor(y, x, TRUE) - - -- Should we branch ? - if magik(20) == TRUE then - local rot = 1 - if magik(50) == TRUE then rot = -1 end - geomancy_dig(y, x, rotate_dir(dir, rot), length / 3) - end - - y = y - dy - x = x - dx - end -end - GEOLYSIS = add_spell { ["name"] = "Geolysis", @@ -473,7 +225,7 @@ add_hooks { [HOOK_MOVED] = function(oy, ox) if player.dripping_tread > 0 then - geomancy_random_floor(oy, ox) + geomancy_random_floor(oy, ox, FALSE) player.dripping_tread = player.dripping_tread - 1 if player.dripping_tread == 0 then msg_print("You stop dripping raw elemental energies.") diff --git a/src/externs.h b/src/externs.h index e232f69d..4f8def3a 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1394,6 +1394,10 @@ extern void random_misc (object_type * o_ptr, bool_ is_scroll); extern void random_plus(object_type * o_ptr, bool_ is_scroll); extern bool_ reset_recall(bool_ no_trepas_max_depth); extern void remove_dg_curse(void); +extern void geomancy_random_wall(int y, int x); +extern void geomancy_random_floor(int y, int x, bool_ kill_wall); +extern void geomancy_dig(int oy, int ox, int dir, int length); +extern void channel_the_elements(int y, int x, int level); /* randart.c */ extern int get_activation_power(void); @@ -1787,6 +1791,7 @@ extern void desc_quest(int q_idx, int d, char *desc); extern s16b add_new_gods(char *name); extern void desc_god(int g_idx, int d, char *desc); +extern int get_lua_int(cptr name); extern s16b get_god_AULE(); extern s16b get_god_VARDA(); extern s16b get_god_ULMO(); diff --git a/src/lua_bind.c b/src/lua_bind.c index 00a0e25b..765b8072 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -608,6 +608,11 @@ void desc_god(int g_idx, int d, char *desc) strncpy(deity_info[g_idx].desc[d], desc, 79); } +int get_lua_int(cptr name) +{ + return exec_lua(format("return %s", name)); +} + static int get_god_theme(cptr name) { if (game_module_idx == MODULE_THEME) diff --git a/src/spells.pkg b/src/spells.pkg index 5575d0f4..77a1794e 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2465,3 +2465,10 @@ extern s16b last_teleportation_x; * @note (see file spells1.c) */ extern void get_pos_player(int dis, int *ny=0, int *nx=0); + +/** + * Geomancy + */ +extern void geomancy_random_floor(int y, int x, bool kill_wall); +extern void geomancy_dig(int y, int x, int dir, int length); +extern void channel_the_elements(int y, int x, int level); diff --git a/src/spells1.c b/src/spells1.c index e99bbc23..8350a4ff 100644 --- a/src/spells1.c +++ b/src/spells1.c @@ -3834,15 +3834,14 @@ static bool_ project_f(int who, int r, int y, int x, int dam, int typ) case GF_ELEMENTAL_WALL: { if ((p_ptr->py != y) || (p_ptr->px != x)) { - exec_lua(format("geomancy_random_wall(%d,%d);", y, x)); + geomancy_random_wall(y, x); } - break; } case GF_ELEMENTAL_GROWTH: { - exec_lua(format("geomancy_random_floor(%d, %d)", y, x)); + geomancy_random_floor(y, x, FALSE); break; } } diff --git a/src/spells2.c b/src/spells2.c index 5467499c..6fb1b1b9 100644 --- a/src/spells2.c +++ b/src/spells2.c @@ -8074,3 +8074,350 @@ void create_between_gate(int dist, int y, int x) cave[ij][ii].special = p_ptr->px + (p_ptr->py << 8); } } + +/** + * Geomancy + */ +typedef struct geomancy_entry { + int skill; + int feat; + int min_skill_level; +} geomancy_entry; + +static int choose_geomancy_feature(int n, geomancy_entry *table) +{ + int feat = -1; + /* choose feature */ + while (feat < 0) { + geomancy_entry *t = &table[rand_int(n)]; + + /* Do we meet the requirements ? + And then select the features based on skill proportions */ + if ((get_skill(t->skill) >= t->min_skill_level) && magik(get_skill_scale(t->skill, 100))) + { + feat = t->feat; + } + } + /* return */ + return feat; +} + +static int rotate_dir(int dir, int mov) +{ + if (mov > 0) + { + switch (dir) { + case 7: return 8; + case 8: return 9; + case 9: return 6; + case 6: return 3; + case 3: return 2; + case 2: return 1; + case 1: return 4; + case 4: return 7; + } + } + else if (mov < 0) + { + switch (dir) { + case 7: return 4; + case 4: return 1; + case 1: return 2; + case 2: return 3; + case 3: return 6; + case 6: return 9; + case 9: return 8; + case 8: return 7; + } + } + + return dir; +} + +void geomancy_random_wall(int y, int x) +{ +#define TABLE_SIZE 4 + cave_type *c_ptr = &cave[y][x]; + int feat = -1; + geomancy_entry table[TABLE_SIZE] = { + /* Fire element */ + { SKILL_FIRE, FEAT_SANDWALL, 1}, + /* Water element */ + { SKILL_WATER, FEAT_TREES, 1}, + { SKILL_WATER, FEAT_ICE_WALL, 12}, + /* Earth element */ + { SKILL_EARTH, FEAT_WALL_EXTRA, 1} + }; + + /* Do not destroy permanent things */ + if (f_info[c_ptr->feat].flags1 & FF1_PERMANENT) { + return; + } + + /* Choose feature */ + feat = choose_geomancy_feature(TABLE_SIZE, table); + if (feat >= 0) + { + cave_set_feat(y, x, feat); + } +#undef TABLE_SIZE +} + +void geomancy_random_floor(int y, int x, bool_ kill_wall) +{ +#define TABLE_SIZE 9 + cave_type *c_ptr = &cave[y][x]; + int feat = -1; + geomancy_entry table[TABLE_SIZE] = { + /* Fire element */ + { SKILL_FIRE, FEAT_SAND, 1}, + { SKILL_FIRE, FEAT_SHAL_LAVA, 8}, + { SKILL_FIRE, FEAT_DEEP_LAVA, 18}, + /* Water element */ + { SKILL_WATER, FEAT_SHAL_WATER, 1}, + { SKILL_WATER, FEAT_DEEP_WATER, 8}, + { SKILL_WATER, FEAT_ICE, 18}, + /* Earth element */ + { SKILL_EARTH, FEAT_GRASS, 1}, + { SKILL_EARTH, FEAT_FLOWER, 8}, + { SKILL_EARTH, FEAT_DARK_PIT, 18} + }; + + /* Do not destroy permanent things */ + if (f_info[c_ptr->feat].flags1 & FF1_PERMANENT) { + return; + } + if (!(kill_wall || (f_info[c_ptr->feat].flags1 & FF1_FLOOR))) { + return; + } + + /* Choose feature */ + feat = choose_geomancy_feature(TABLE_SIZE, table); + if (feat >= 0) + { + cave_set_feat(y, x, feat); + } +#undef TABLE_SIZE +} + +static bool_ geomancy_can_tunnel(int y, int x) +{ + switch (cave[y][x].feat) + { + case FEAT_WALL_EXTRA: + case FEAT_WALL_OUTER: + case FEAT_WALL_INNER: + case FEAT_WALL_SOLID: + case FEAT_MAGMA: + case FEAT_QUARTZ: + case FEAT_MAGMA_H: + case FEAT_QUARTZ_H: + case FEAT_MAGMA_K: + case FEAT_QUARTZ_K: + case FEAT_TREES: + case FEAT_DEAD_TREE: + case FEAT_SANDWALL: + case FEAT_SANDWALL_H: + case FEAT_SANDWALL_K: + case FEAT_ICE_WALL: + return TRUE; + default: + return FALSE; + } +} + +void geomancy_dig(int oy, int ox, int dir, int length) +{ + int dy = ddy[dir]; + int dx = ddx[dir]; + int y = dy + oy; + int x = dx + ox; + int i; + + for (i=0; imhp * (5 + get_skill_scale(SKILL_EARTH, 20)) / 100); + break; + + case FEAT_FLOWER: + hp_player(p_ptr->mhp * (5 + get_skill_scale(SKILL_EARTH, 30)) / 100); + break; + + case FEAT_DARK_PIT: + { + int dir, type; + if (!get_aim_dir(&dir)) break; + + type = (get_skill(SKILL_EARTH) >= 18) ? GF_NETHER : GF_DARK; + + fire_bolt(type, dir, damroll(10, get_skill(SKILL_EARTH))); + + break; + } + + case FEAT_SHAL_WATER: + { + int dir, type; + if (!get_aim_dir(&dir)) break; + + type = (get_skill(SKILL_WATER) >= 18) ? GF_WAVE : GF_WATER; + + if (get_skill(SKILL_WATER) >= 8) + { + fire_beam(type, dir, damroll(3, get_skill(SKILL_WATER))); + } + else + { + fire_bolt(type, dir, damroll(3, get_skill(SKILL_WATER))); + } + + break; + } + + case FEAT_DEEP_WATER: + { + int dir, type; + if (!get_aim_dir(&dir)) break; + + type = (get_skill(SKILL_WATER) >= 18) ? GF_WAVE : GF_WATER; + + if (get_skill(SKILL_WATER) >= 8) + { + fire_beam(type, dir, damroll(5, get_skill(SKILL_WATER))); + } + else + { + fire_bolt(type, dir, damroll(5, get_skill(SKILL_WATER))); + } + + break; + } + + case FEAT_ICE: + { + int dir; + if (!get_aim_dir(&dir)) break; + + if (get_skill(SKILL_WATER) >= 12) + { + fire_ball(GF_ICE, dir, get_skill_scale(SKILL_WATER, 340), 3); + } + else + { + fire_bolt(GF_ICE, dir, damroll(3, get_skill(SKILL_WATER))); + } + + break; + } + + case FEAT_SAND: + { + int type, dur, FIERYAURA; + + FIERYAURA = get_lua_int("FIERYAURA"); + type = (get_level(FIERYAURA, 50, 1) >= 8) ? SHIELD_GREAT_FIRE : SHIELD_FIRE; + + dur = randint(20) + level + get_skill(SKILL_AIR); + set_shield(dur, 0, type, 5 + get_skill_scale(SKILL_FIRE, 20), 5 + get_skill_scale(SKILL_FIRE, 14)); + set_blind(dur); + + break; + } + + case FEAT_SHAL_LAVA: + { + int dir; + if (!get_aim_dir(&dir)) break; + + if (get_skill(SKILL_FIRE) >= 15) + { + fire_bolt(GF_HELL_FIRE, dir, damroll(get_skill_scale(SKILL_FIRE, 30), 15)); + } + else + { + fire_bolt(GF_FIRE, dir, damroll(get_skill_scale(SKILL_FIRE, 30), 15)); + } + + break; + } + + case FEAT_DEEP_LAVA: + { + int dir; + if (!get_aim_dir(&dir)) break; + + if (get_skill(SKILL_FIRE) >= 15) + { + fire_ball(GF_HELL_FIRE, dir, damroll(get_skill_scale(SKILL_FIRE, 30), 15), 3); + } + else + { + fire_ball(GF_FIRE, dir, damroll(get_skill_scale(SKILL_FIRE, 30), 15), 3); + } + + break; + } + + default: + msg_print("You cannot channel this area."); + return; + } + + /* Drain area? */ + if (magik(100 - level)) + { + if (cave[y][x].feat == FEAT_FLOWER) + { + cave_set_feat(y, x, FEAT_GRASS); + } + else + { + cave_set_feat(y, x, FEAT_FLOOR); + } + msg_print("The area is drained."); + } +} -- cgit v1.2.3 From 6548c6fb76232f4502d0856e04f169394deb6093 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 5 Apr 2012 19:50:12 +0200 Subject: Lua: Remove unused HOOK_CALC_BONUS_END --- src/defines.h | 3 +-- src/util.pkg | 6 ------ src/xtra1.c | 3 --- 3 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/defines.h b/src/defines.h index e0851fd4..3b17211b 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4508,8 +4508,7 @@ #define HOOK_CALC_WEIGHT 74 #define HOOK_FORBID_TRAVEL 75 #define HOOK_DEBUG_COMMAND 76 -#define HOOK_CALC_BONUS_END 77 -#define MAX_HOOKS 78 +#define MAX_HOOKS 77 #define HOOK_TYPE_C 0 #define HOOK_TYPE_LUA 1 diff --git a/src/util.pkg b/src/util.pkg index 50f69e79..d3d1f041 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -421,12 +421,6 @@ typedef unsigned int u32b; */ #define HOOK_CALC_BONUS 29 -/** @def HOOK_CALC_BONUS - * @brief Calculate player "state" bonuses, after all calcs are done. - * @note (see xtra1.c) - */ -#define HOOK_CALC_BONUS_END 77 - /** @def HOOK_CALC_POWERS * @brief Calculate player powers. * @note (see xtra1.c) diff --git a/src/xtra1.c b/src/xtra1.c index 933bc265..c708f3f9 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -3956,9 +3956,6 @@ void calc_bonuses(bool_ silent) p_ptr->skill_sav = 10; else p_ptr->skill_sav += 10; - - /* Let the scripts do what they need */ - process_hooks(HOOK_CALC_BONUS_END, "(d)", silent); } -- cgit v1.2.3 From 2bd0f18da7dbccd650d8a83aa457d5190f4ce1bc Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 5 Apr 2012 20:12:21 +0200 Subject: Lua: Move HOOK_CALC_BONUS code for gods to C --- lib/mods/theme/scpt/gods_new.lua | 56 -------------------------------- lib/mods/theme/scpt/s_mandos.lua | 9 ------ src/externs.h | 1 + src/loadsave.c | 1 + src/player.pkg | 5 +++ src/variable.c | 5 +++ src/xtra1.c | 69 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 81 insertions(+), 65 deletions(-) diff --git a/lib/mods/theme/scpt/gods_new.lua b/lib/mods/theme/scpt/gods_new.lua index 9a020915..0a3b7283 100644 --- a/lib/mods/theme/scpt/gods_new.lua +++ b/lib/mods/theme/scpt/gods_new.lua @@ -22,24 +22,6 @@ GOD_AULE = add_god }, ["hooks"] = { - [HOOK_CALC_BONUS] = function() - if (player.pgod == GOD_AULE) and (player.grace > 0) then - -- Resist fire, not shown on the character screen (?) - if (player.grace > 5000) then - player.resist_fire = TRUE - end - - local bonus = player.grace / 5000 - if bonus > 5 then - bonus = 5 - end - player.to_h = player.to_h + bonus - player.dis_to_h = player.dis_to_h + bonus - player.to_d = player.to_d + bonus - player.dis_to_d = player.dis_to_d + bonus - - end - end, [HOOK_PROCESS_WORLD] = function() if (player.pgod == GOD_AULE) then GRACE_DELAY = GRACE_DELAY + 1 @@ -204,25 +186,6 @@ GOD_ULMO = add_god }, ["hooks"] = { - [HOOK_CALC_BONUS] = function() - if (player.pgod == GOD_ULMO) then - player.water_breath = TRUE - end - if (player.pgod == GOD_ULMO) and (player.grace > 0) then - local bonus = player.grace / 5000 - if bonus > 5 then - bonus = 5 - end - - if ((player.grace > 1000) and (player.praying == TRUE)) then - player.resist_pois = TRUE - end - if ((player.grace > 15000) and (player.praying == TRUE)) then - player.magic_breath = TRUE - end - end - end, - [HOOK_MONSTER_DEATH] = function(m_idx) if (player.pgod == GOD_ULMO) then m_ptr = monster(m_idx) @@ -319,25 +282,6 @@ GOD_MANDOS = add_god }, ["hooks"] = { - [HOOK_CALC_BONUS] = function() - if (player.pgod == GOD_MANDOS) then - player.resist_neth = TRUE - end - if (player.pgod == GOD_MANDOS) and (player.grace > 0) then - local bonus = player.grace / 5000 - if bonus > 5 then - bonus = 5 - end - - if ((player.grace > 10000) and (player.praying == TRUE)) then - player.resist_continuum = TRUE - end - - if ((player.grace > 20000) and (player.praying == TRUE)) then - player.immune_neth = TRUE - end - end - end, [HOOK_PROCESS_WORLD] = function() if (player.pgod == GOD_MANDOS) then GRACE_DELAY = GRACE_DELAY + 1 diff --git a/lib/mods/theme/scpt/s_mandos.lua b/lib/mods/theme/scpt/s_mandos.lua index cc7e346a..90876930 100644 --- a/lib/mods/theme/scpt/s_mandos.lua +++ b/lib/mods/theme/scpt/s_mandos.lua @@ -4,8 +4,6 @@ BOOK_MANDOS = 66 -- precognition timer for high-level spell [from T-Plus by Ingeborg S. Norden] -add_loadsave("tim_precognition",0) - function set_precognition(v) local notice = FALSE if (v < 0) then v = 0 end @@ -33,13 +31,6 @@ end -- related hooks add_hooks{ - [HOOK_CALC_BONUS] = function() - if (tim_precognition > 0) then - --player.precognition = TRUE - apply_flags(0, 0, 0, TR4_PRECOGNITION, 0, 0, 0, 0, 0, 0, 0) - end - end, - [HOOK_PROCESS_WORLD] = function() if (tim_precognition > 0) then set_precognition(tim_precognition - 1) diff --git a/src/externs.h b/src/externs.h index 4f8def3a..6821fd30 100644 --- a/src/externs.h +++ b/src/externs.h @@ -602,6 +602,7 @@ extern s32b DUNGEON_ASTRAL_WILD_Y; extern deity_type *deity_info; extern s32b max_gods; extern timer_type *gl_timers; +extern s16b tim_precognition; extern const char *get_version_string(); /* plots.c */ diff --git a/src/loadsave.c b/src/loadsave.c index 5d43d79a..58a0931b 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -512,6 +512,7 @@ static bool_ do_extra(int flag) do_s16b(&p_ptr->blessed, flag); do_s16b(&p_ptr->control, flag); do_byte(&p_ptr->control_dir, flag); + do_s16b(&tim_precognition, flag); do_s16b(&p_ptr->tim_thunder, flag); do_s16b(&p_ptr->tim_thunder_p1, flag); do_s16b(&p_ptr->tim_thunder_p2, flag); diff --git a/src/player.pkg b/src/player.pkg index dfdced26..b2f46506 100644 --- a/src/player.pkg +++ b/src/player.pkg @@ -2622,6 +2622,11 @@ extern void apply_flags(u32b f1, u32b f2, u32b f3, u32b f4, u32b f5, u32b esp, s #define SHIELD_FEAR 0x0008 /** @} */ +/** + * Timered precognition + */ +extern s16b tim_precognition; + /** @fn set_tim_thunder(int v, int p1, int p2) * @brief Player has timed thunderstorm.\n diff --git a/src/variable.c b/src/variable.c index 9ed084b4..5b1afc3b 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1592,6 +1592,11 @@ s32b max_gods = MAX_GODS_INIT; */ timer_type *gl_timers = NULL; +/* + * Timered precognition. + */ +s16b tim_precognition = 0; + /** * Get the version string. */ diff --git a/src/xtra1.c b/src/xtra1.c index c708f3f9..e39c2fad 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -2424,6 +2424,69 @@ void calc_gods() if (p_ptr->grace > 15000) p_ptr->stat_add[A_STR] += 1; if (p_ptr->grace > 20000) p_ptr->stat_add[A_STR] += 1; } + + /* Aule provides to-hit/damage bonuses and fire resistance */ + GOD(get_god_AULE()) + { + if (p_ptr->grace > 0) + { + int bonus; + /* Resist fire, not shown on the character screen (?) */ + if (p_ptr->grace > 5000) + { + p_ptr->resist_fire = TRUE; + } + + bonus = p_ptr->grace / 5000; + if (bonus > 5) + { + bonus = 5; + } + + p_ptr->to_h = p_ptr->to_h + bonus; + p_ptr->dis_to_h = p_ptr->dis_to_h + bonus; + p_ptr->to_d = p_ptr->to_d + bonus; + p_ptr->dis_to_d = p_ptr->dis_to_d + bonus; + } + } + + /* Mandos provides nether resistance and, while praying, + nether immunity and prevents teleportation. */ + GOD(get_god_MANDOS()) + { + p_ptr->resist_neth = TRUE; + + if ((p_ptr->grace > 10000) && + (p_ptr->praying == TRUE)) + { + p_ptr->resist_continuum = TRUE; + } + + if ((p_ptr->grace > 20000) && + (p_ptr->praying == TRUE)) + { + p_ptr->immune_neth = TRUE; + } + } + + /* Ulmo provides water breath and, while praying can + provide poison resistance and magic breath. */ + GOD(get_god_ULMO()) + { + p_ptr->water_breath = TRUE; + + if ((p_ptr->grace > 1000) && + (p_ptr->praying == TRUE)) + { + p_ptr->resist_pois = TRUE; + } + + if ((p_ptr->grace > 15000) && + (p_ptr->praying == TRUE)) + { + p_ptr->magical_breath = TRUE; + } + } } /* Apply flags */ @@ -3151,6 +3214,12 @@ void calc_bonuses(bool_ silent) p_ptr->dis_to_a += 100; } + /* Temporary precognition */ + if (tim_precognition > 0) + { + apply_flags(0, 0, 0, TR4_PRECOGNITION, 0, 0, 0, 0, 0, 0, 0); + } + /* Breath */ if (p_ptr->tim_water_breath) { -- cgit v1.2.3 From 1a5636844a5ac885821a1562e38e8f97631fe9d2 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 5 Apr 2012 21:15:43 +0200 Subject: Lua: Add 'static' modifier to calc_gods() --- src/xtra1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xtra1.c b/src/xtra1.c index e39c2fad..4d3a4519 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -2351,7 +2351,7 @@ int get_archery_skill() } /* Apply gods */ -void calc_gods() +static void calc_gods() { /* Boost WIS if the player follows Eru */ GOD(GOD_ERU) -- cgit v1.2.3 From 6cefca4c3f1ded484c4e00aeb9a660f131a48b16 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 5 Apr 2012 21:25:42 +0200 Subject: Lua: Move spell school usages of HOOK_CALC_BONUS to C --- lib/mods/theme/scpt/spells.lua | 14 -------------- lib/scpt/spells.lua | 16 ---------------- src/xtra1.c | 17 +++++++++++++++++ 3 files changed, 17 insertions(+), 30 deletions(-) diff --git a/lib/mods/theme/scpt/spells.lua b/lib/mods/theme/scpt/spells.lua index 838240a3..9f18ee3a 100644 --- a/lib/mods/theme/scpt/spells.lua +++ b/lib/mods/theme/scpt/spells.lua @@ -44,10 +44,6 @@ SCHOOL_FIRE = add_school ["sorcery"] = TRUE, ["hooks"] = { - [HOOK_CALC_BONUS] = function() - if get_skill(SKILL_FIRE) >= 35 then - end - end, [HOOK_CALC_POWERS] = function() if get_skill(SKILL_FIRE) >= 50 then -- player.add_power(PWR_FIRE_SHAPE) @@ -73,11 +69,6 @@ SCHOOL_AIR = add_school ["sorcery"] = TRUE, ["hooks"] = { - [HOOK_CALC_BONUS] = function() - if get_skill(SKILL_AIR) >= 50 then - player.magical_breath = TRUE - end - end, [HOOK_CALC_POWERS] = function() if get_skill(SKILL_AIR) >= 50 then -- player.add_powe(PWR_AIR_SHAPE) @@ -103,11 +94,6 @@ SCHOOL_WATER = add_school ["sorcery"] = TRUE, ["hooks"] = { - [HOOK_CALC_BONUS] = function() - if get_skill(SKILL_WATER) >= 30 then - player.water_breath = TRUE - end - end, [HOOK_CALC_POWERS] = function() if get_skill(SKILL_WATER) >= 50 then -- player.add_powe(PWR_WATER_SHAPE) diff --git a/lib/scpt/spells.lua b/lib/scpt/spells.lua index 2f90c10b..24b4f02b 100644 --- a/lib/scpt/spells.lua +++ b/lib/scpt/spells.lua @@ -42,14 +42,6 @@ SCHOOL_AIR = add_school ["skill"] = SKILL_AIR, ["spell_power"] = TRUE, ["sorcery"] = TRUE, - ["hooks"] = - { - [HOOK_CALC_BONUS] = function() - if get_skill(SKILL_AIR) >= 50 then - player.magical_breath = TRUE - end - end, - }, ["gods"] = { -- Manwe Sulimo provides the Air school at 2/3 the prayer skill @@ -67,14 +59,6 @@ SCHOOL_WATER = add_school ["skill"] = SKILL_WATER, ["spell_power"] = TRUE, ["sorcery"] = TRUE, - ["hooks"] = - { - [HOOK_CALC_BONUS] = function() - if get_skill(SKILL_WATER) >= 30 then - player.water_breath = TRUE - end - end, - }, ["gods"] = { -- Yavanna Kementari provides the Water school at 1/2 the prayer skill diff --git a/src/xtra1.c b/src/xtra1.c index 4d3a4519..1d2d8ba0 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -2489,6 +2489,20 @@ static void calc_gods() } } +/* Apply spell schools */ +static void calc_schools() +{ + if (get_skill(SKILL_AIR) >= 50) + { + p_ptr->magical_breath = TRUE; + } + + if (get_skill(SKILL_WATER) >= 30) + { + p_ptr->water_breath = TRUE; + } +} + /* Apply flags */ static int extra_blows; static int extra_shots; @@ -2903,6 +2917,9 @@ void calc_bonuses(bool_ silent) /* Let the scripts do what they need */ process_hooks(HOOK_CALC_BONUS, "()"); + /* Take care of spell schools */ + calc_schools(); + /* The powers gived by the wielded monster */ calc_wield_monster(); -- cgit v1.2.3 From a222834aca2090772fec130ded728424a5e790d6 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 5 Apr 2012 21:36:53 +0200 Subject: Lua: Remove dead code from Theme spells.lua --- lib/mods/theme/scpt/spells.lua | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/lib/mods/theme/scpt/spells.lua b/lib/mods/theme/scpt/spells.lua index 9f18ee3a..36829356 100644 --- a/lib/mods/theme/scpt/spells.lua +++ b/lib/mods/theme/scpt/spells.lua @@ -42,14 +42,6 @@ SCHOOL_FIRE = add_school ["skill"] = SKILL_FIRE, ["spell_power"] = TRUE, ["sorcery"] = TRUE, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - if get_skill(SKILL_FIRE) >= 50 then --- player.add_power(PWR_FIRE_SHAPE) - end - end, - }, ["gods"] = { -- Aule provides the Fire school at 3/5 the prayer skill @@ -67,14 +59,6 @@ SCHOOL_AIR = add_school ["skill"] = SKILL_AIR, ["spell_power"] = TRUE, ["sorcery"] = TRUE, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - if get_skill(SKILL_AIR) >= 50 then --- player.add_powe(PWR_AIR_SHAPE) - end - end, - }, ["gods"] = { -- Manwe Sulimo provides the Air school at 2/3 the prayer skill @@ -92,14 +76,6 @@ SCHOOL_WATER = add_school ["skill"] = SKILL_WATER, ["spell_power"] = TRUE, ["sorcery"] = TRUE, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - if get_skill(SKILL_WATER) >= 50 then --- player.add_powe(PWR_WATER_SHAPE) - end - end, - }, ["gods"] = { -- Yavanna Kementari provides the Water school at 1/2 the prayer skill @@ -124,14 +100,6 @@ SCHOOL_EARTH = add_school ["skill"] = SKILL_EARTH, ["spell_power"] = TRUE, ["sorcery"] = TRUE, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - if get_skill(SKILL_EARTH) >= 50 then --- player.add_powe(PWR_EARTH_SHAPE) - end - end, - }, ["gods"] = { -- Tulkas provides the Earth school at 4/5 the prayer skill -- cgit v1.2.3 From a9b597979d99a53c56d2fa5b8498834364fef7a9 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 5 Apr 2012 23:03:27 +0200 Subject: Lua: Move player.corrupt_anti_teleport_stopped variable to C --- lib/mods/theme/scpt/powers.lua | 2 -- lib/scpt/powers.lua | 2 -- src/loadsave.c | 2 ++ src/player.pkg | 1 + src/types.h | 1 + 5 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/mods/theme/scpt/powers.lua b/lib/mods/theme/scpt/powers.lua index ff4c62c5..90d69ac7 100644 --- a/lib/mods/theme/scpt/powers.lua +++ b/lib/mods/theme/scpt/powers.lua @@ -35,8 +35,6 @@ POWER_WEB = add_power -- Activating/stopping space-continuum -- When stopped it will induce constant mana loss -player.corrupt_anti_teleport_stopped = FALSE -add_loadsave("player.corrupt_anti_teleport_stopped", FALSE) POWER_COR_SPACE_TIME = add_power { ["name"] = "control space/time continuum", diff --git a/lib/scpt/powers.lua b/lib/scpt/powers.lua index ff4c62c5..90d69ac7 100644 --- a/lib/scpt/powers.lua +++ b/lib/scpt/powers.lua @@ -35,8 +35,6 @@ POWER_WEB = add_power -- Activating/stopping space-continuum -- When stopped it will induce constant mana loss -player.corrupt_anti_teleport_stopped = FALSE -add_loadsave("player.corrupt_anti_teleport_stopped", FALSE) POWER_COR_SPACE_TIME = add_power { ["name"] = "control space/time continuum", diff --git a/src/loadsave.c b/src/loadsave.c index 58a0931b..287eabd8 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -591,6 +591,8 @@ static bool_ do_extra(int flag) p_ptr->corruptions[i] = tmp8u; } + do_byte((byte*)&p_ptr->corrupt_anti_teleport_stopped, flag); + do_byte(&p_ptr->confusing, flag); do_byte((byte*)&p_ptr->black_breath, flag); do_byte((byte*)&fate_flag, flag); diff --git a/src/player.pkg b/src/player.pkg index b2f46506..ef85926a 100644 --- a/src/player.pkg +++ b/src/player.pkg @@ -1797,6 +1797,7 @@ struct player_type * @brief Boolean */ bool corruptions[max_corruptions] @ corruptions_aux; + bool corrupt_anti_teleport_stopped; /* Astral */ /** @structvar astral diff --git a/src/types.h b/src/types.h index b5fab44e..de90a019 100644 --- a/src/types.h +++ b/src/types.h @@ -1808,6 +1808,7 @@ struct player_type /* Corruptions */ bool_ *corruptions; + bool_ corrupt_anti_teleport_stopped; /*** Pet commands ***/ byte pet_follow_distance; /* Length of the imaginary "leash" for pets */ -- cgit v1.2.3 From 62e385cb769000cfefa052b1ab3e155314e7ac37 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 5 Apr 2012 23:42:13 +0200 Subject: Lua: Move HOOK_CALC_BONUS corruption code to C --- lib/core/crpt_aux.lua | 21 +++++------ lib/mods/theme/core/crpt_aux.lua | 21 +++++------ lib/mods/theme/scpt/corrupt.lua | 63 --------------------------------- lib/scpt/corrupt.lua | 63 --------------------------------- src/externs.h | 16 +++++++++ src/lua_bind.c | 13 +++++++ src/player.pkg | 19 ++++++++++ src/variable.c | 18 ++++++++++ src/xtra1.c | 75 ++++++++++++++++++++++++++++++++++++++++ 9 files changed, 163 insertions(+), 146 deletions(-) diff --git a/lib/core/crpt_aux.lua b/lib/core/crpt_aux.lua index 97f8d4b6..c1772c04 100644 --- a/lib/core/crpt_aux.lua +++ b/lib/core/crpt_aux.lua @@ -140,7 +140,6 @@ function add_corruption(c) assert(c.get_text, "No corruption get_text") assert(c.lose_text, "No corruption lose_text") assert(c.desc, "No corruption desc") - assert(c.hooks, "Nothing to do for corruption") if not c.random then c.random = TRUE end if not c.removable then c.removable = TRUE end if not c.allow then c.allow = function() return not nil end end @@ -155,16 +154,18 @@ function add_corruption(c) end local index, h - for index, h in c.hooks do - add_hook_script(index, "__lua__corrupt_callback"..__corruptions_callbacks_max, "__lua__corrupt_callback"..__corruptions_callbacks_max) - setglobal("__lua__corrupt_callback"..__corruptions_callbacks_max, - function (...) - if test_depend_corrupt(%__corruptions_max) == TRUE then - return call(%h, arg) + if type(c.hooks) == "table" then + for index, h in c.hooks do + add_hook_script(index, "__lua__corrupt_callback"..__corruptions_callbacks_max, "__lua__corrupt_callback"..__corruptions_callbacks_max) + setglobal("__lua__corrupt_callback"..__corruptions_callbacks_max, + function (...) + if test_depend_corrupt(%__corruptions_max) == TRUE then + return call(%h, arg) + end end - end - ) - __corruptions_callbacks_max = __corruptions_callbacks_max + 1 + ) + __corruptions_callbacks_max = __corruptions_callbacks_max + 1 + end end if type(c.desc) == "table" then diff --git a/lib/mods/theme/core/crpt_aux.lua b/lib/mods/theme/core/crpt_aux.lua index 97f8d4b6..c1772c04 100644 --- a/lib/mods/theme/core/crpt_aux.lua +++ b/lib/mods/theme/core/crpt_aux.lua @@ -140,7 +140,6 @@ function add_corruption(c) assert(c.get_text, "No corruption get_text") assert(c.lose_text, "No corruption lose_text") assert(c.desc, "No corruption desc") - assert(c.hooks, "Nothing to do for corruption") if not c.random then c.random = TRUE end if not c.removable then c.removable = TRUE end if not c.allow then c.allow = function() return not nil end end @@ -155,16 +154,18 @@ function add_corruption(c) end local index, h - for index, h in c.hooks do - add_hook_script(index, "__lua__corrupt_callback"..__corruptions_callbacks_max, "__lua__corrupt_callback"..__corruptions_callbacks_max) - setglobal("__lua__corrupt_callback"..__corruptions_callbacks_max, - function (...) - if test_depend_corrupt(%__corruptions_max) == TRUE then - return call(%h, arg) + if type(c.hooks) == "table" then + for index, h in c.hooks do + add_hook_script(index, "__lua__corrupt_callback"..__corruptions_callbacks_max, "__lua__corrupt_callback"..__corruptions_callbacks_max) + setglobal("__lua__corrupt_callback"..__corruptions_callbacks_max, + function (...) + if test_depend_corrupt(%__corruptions_max) == TRUE then + return call(%h, arg) + end end - end - ) - __corruptions_callbacks_max = __corruptions_callbacks_max + 1 + ) + __corruptions_callbacks_max = __corruptions_callbacks_max + 1 + end end if type(c.desc) == "table" then diff --git a/lib/mods/theme/scpt/corrupt.lua b/lib/mods/theme/scpt/corrupt.lua index f402add3..51d7233b 100644 --- a/lib/mods/theme/scpt/corrupt.lua +++ b/lib/mods/theme/scpt/corrupt.lua @@ -15,10 +15,6 @@ CORRUPT_BALROG_AURA = add_corruption }, ["hooks"] = { - [HOOK_CALC_BONUS] = function() - player.xtra_f3 = bor(player.xtra_f3, TR3_SH_FIRE) - player.xtra_f3 = bor(player.xtra_f3, TR3_LITE1) - end, [HOOK_READ] = function(obj) if magik(5) == TRUE then msg_print("Your demon aura burns the scroll before you read it!") @@ -41,14 +37,6 @@ CORRUPT_BALROG_WINGS = add_corruption " Creates ugly, but working, wings allowing you to fly", " But it reduces charisma by 4 and dexterity by 2" }, - ["hooks"] = - { - [HOOK_CALC_BONUS] = function() - player.xtra_f4 = bor(player.xtra_f4, TR4_FLY) - player.modify_stat(A_CHR, -4) - player.modify_stat(A_DEX, -2) - end, - }, } CORRUPT_BALROG_STRENGTH = add_corruption @@ -62,15 +50,6 @@ CORRUPT_BALROG_STRENGTH = add_corruption " Provides 3 strength and 1 constitution", " But it reduces charisma by 1 and dexterity by 3" }, - ["hooks"] = - { - [HOOK_CALC_BONUS] = function() - player.modify_stat(A_STR, 3) - player.modify_stat(A_CON, 1) - player.modify_stat(A_DEX, -3) - player.modify_stat(A_CHR, -1) - end, - }, } CORRUPT_BALROG_FORM = add_corruption @@ -120,13 +99,6 @@ CORRUPT_DEMON_SPIRIT = add_corruption return not nil end end, - ["hooks"] = - { - [HOOK_CALC_BONUS] = function() - player.modify_stat(A_INT, 1) - player.modify_stat(A_CHR, -2) - end, - }, } CORRUPT_DEMON_HIDE = add_corruption @@ -150,15 +122,6 @@ CORRUPT_DEMON_HIDE = add_corruption return not nil end end, - ["hooks"] = - { - [HOOK_CALC_BONUS] = function() - player.to_a = player.to_a + player.lev - player.dis_to_a = player.dis_to_a + player.lev - player.pspeed = player.pspeed - (player.lev / 7) - if player.lev >= 40 then player.xtra_f2 = bor(player.xtra_f2, TR2_IM_FIRE) end - end, - }, } CORRUPT_DEMON_BREATH = add_corruption @@ -214,15 +177,6 @@ CORRUPT_DEMON_REALM = add_corruption return not nil end end, - ["hooks"] = - { - [HOOK_CALC_BONUS] = function() - -- 1500 may seem a lot, but people are rather unlikely to get the corruption very soon - -- due to the dependencies - if s_info[SKILL_DAEMON + 1].mod == 0 then s_info[SKILL_DAEMON + 1].mod = 1500 end - s_info[SKILL_DAEMON + 1].hidden = FALSE; - end, - }, } @@ -252,9 +206,6 @@ CORRUPT_RANDOM_TELEPORT = add_corruption -- No oppose field, it will be automatically set when we declare the anti-telep corruption to oppose us ["hooks"] = { - [HOOK_CALC_BONUS] = function() - player.xtra_f3 = bor(player.xtra_f3, TR3_TELEPORT) - end, [HOOK_PROCESS_WORLD] = function() if rand_int(300) == 1 then if magik(70) == TRUE then @@ -303,11 +254,6 @@ CORRUPT_ANTI_TELEPORT = add_corruption [HOOK_CALC_POWERS] = function() player.add_power(POWER_COR_SPACE_TIME) end, - [HOOK_CALC_BONUS] = function() - if player.corrupt_anti_teleport_stopped == FALSE then - player.resist_continuum = TRUE - end - end, [HOOK_PROCESS_WORLD] = function() if player.corrupt_anti_teleport_stopped == TRUE then local amt = player.msp + player.csp @@ -347,13 +293,6 @@ CORRUPT_TROLL_BLOOD = add_corruption return not nil end end, - ["hooks"] = - { - [HOOK_CALC_BONUS] = function() - player.xtra_f3 = bor(player.xtra_f3, TR3_REGEN, TR3_AGGRAVATE) - player.xtra_esp = bor(player.xtra_esp, ESP_TROLL) - end, - }, } -- The vampire corruption set @@ -1082,8 +1021,6 @@ CORRUPT_ = add_corruption }, ["hooks"] = { - [HOOK_CALC_BONUS] = function() - end, }, } ]] diff --git a/lib/scpt/corrupt.lua b/lib/scpt/corrupt.lua index 550f8bc0..1435df6e 100644 --- a/lib/scpt/corrupt.lua +++ b/lib/scpt/corrupt.lua @@ -14,10 +14,6 @@ CORRUPT_BALROG_AURA = add_corruption }, ["hooks"] = { - [HOOK_CALC_BONUS] = function() - player.xtra_f3 = bor(player.xtra_f3, TR3_SH_FIRE) - player.xtra_f3 = bor(player.xtra_f3, TR3_LITE1) - end, [HOOK_READ] = function(obj) if magik(5) == TRUE then msg_print("Your demon aura burns the scroll before you read it!") @@ -40,14 +36,6 @@ CORRUPT_BALROG_WINGS = add_corruption " Creates ugly, but working, wings allowing you to fly", " But it reduces charisma by 4 and dexterity by 2" }, - ["hooks"] = - { - [HOOK_CALC_BONUS] = function() - player.xtra_f4 = bor(player.xtra_f4, TR4_FLY) - player.modify_stat(A_CHR, -4) - player.modify_stat(A_DEX, -2) - end, - }, } CORRUPT_BALROG_STRENGTH = add_corruption @@ -61,15 +49,6 @@ CORRUPT_BALROG_STRENGTH = add_corruption " Provides 3 strength and 1 constitution", " But it reduces charisma by 1 and dexterity by 3" }, - ["hooks"] = - { - [HOOK_CALC_BONUS] = function() - player.modify_stat(A_STR, 3) - player.modify_stat(A_CON, 1) - player.modify_stat(A_DEX, -3) - player.modify_stat(A_CHR, -1) - end, - }, } CORRUPT_BALROG_FORM = add_corruption @@ -110,13 +89,6 @@ CORRUPT_DEMON_SPIRIT = add_corruption " Increases your intelligence by 1", " But reduce your charisma by 2", }, - ["hooks"] = - { - [HOOK_CALC_BONUS] = function() - player.modify_stat(A_INT, 1) - player.modify_stat(A_CHR, -2) - end, - }, } CORRUPT_DEMON_HIDE = add_corruption @@ -131,15 +103,6 @@ CORRUPT_DEMON_HIDE = add_corruption " Provides immunity to fire at level 40", " But reduces speed by your level / 7", }, - ["hooks"] = - { - [HOOK_CALC_BONUS] = function() - player.to_a = player.to_a + player.lev - player.dis_to_a = player.dis_to_a + player.lev - player.pspeed = player.pspeed - (player.lev / 7) - if player.lev >= 40 then player.xtra_f2 = bor(player.xtra_f2, TR2_IM_FIRE) end - end, - }, } CORRUPT_DEMON_BREATH = add_corruption @@ -186,15 +149,6 @@ CORRUPT_DEMON_REALM = add_corruption [CORRUPT_DEMON_HIDE] = TRUE, [CORRUPT_DEMON_BREATH] = TRUE }, - ["hooks"] = - { - [HOOK_CALC_BONUS] = function() - -- 1500 may seem a lot, but people are rather unlikely to get the corruption very soon - -- due to the dependencies - if s_info[SKILL_DAEMON + 1].mod == 0 then s_info[SKILL_DAEMON + 1].mod = 1500 end - s_info[SKILL_DAEMON + 1].hidden = FALSE; - end, - }, } @@ -215,9 +169,6 @@ CORRUPT_RANDOM_TELEPORT = add_corruption -- No oppose field, it will be automatically set when we declare the anti-telep corruption to oppose us ["hooks"] = { - [HOOK_CALC_BONUS] = function() - player.xtra_f3 = bor(player.xtra_f3, TR3_TELEPORT) - end, [HOOK_PROCESS_WORLD] = function() if rand_int(300) == 1 then if magik(70) == TRUE then @@ -257,11 +208,6 @@ CORRUPT_ANTI_TELEPORT = add_corruption [HOOK_CALC_POWERS] = function() player.add_power(POWER_COR_SPACE_TIME) end, - [HOOK_CALC_BONUS] = function() - if player.corrupt_anti_teleport_stopped == FALSE then - player.resist_continuum = TRUE - end - end, [HOOK_PROCESS_WORLD] = function() if player.corrupt_anti_teleport_stopped == TRUE then local amt = player.msp + player.csp @@ -300,13 +246,6 @@ CORRUPT_TROLL_BLOOD = add_corruption return not nil end end, - ["hooks"] = - { - [HOOK_CALC_BONUS] = function() - player.xtra_f3 = bor(player.xtra_f3, TR3_REGEN, TR3_AGGRAVATE) - player.xtra_esp = bor(player.xtra_esp, ESP_TROLL) - end, - }, } -- The vampire corruption set @@ -426,8 +365,6 @@ CORRUPT_ = add_corruption }, ["hooks"] = { - [HOOK_CALC_BONUS] = function() - end, }, } ]] diff --git a/src/externs.h b/src/externs.h index 6821fd30..c8e34c84 100644 --- a/src/externs.h +++ b/src/externs.h @@ -604,6 +604,20 @@ extern s32b max_gods; extern timer_type *gl_timers; extern s16b tim_precognition; extern const char *get_version_string(); +extern s16b CORRUPT_BALROG_AURA; +extern s16b CORRUPT_BALROG_WINGS; +extern s16b CORRUPT_BALROG_STRENGTH; +extern s16b CORRUPT_BALROG_FORM; +extern s16b CORRUPT_DEMON_SPIRIT; +extern s16b CORRUPT_DEMON_HIDE; +extern s16b CORRUPT_DEMON_BREATH; +extern s16b CORRUPT_DEMON_REALM; +extern s16b CORRUPT_RANDOM_TELEPORT; +extern s16b CORRUPT_ANTI_TELEPORT; +extern s16b CORRUPT_TROLL_BLOOD; +extern s16b CORRUPT_VAMPIRE_TEETH; +extern s16b CORRUPT_VAMPIRE_STRENGTH; +extern s16b CORRUPT_VAMPIRE_VAMPIRE; /* plots.c */ extern FILE *hook_file; @@ -1834,6 +1848,8 @@ extern void lua_delete_list(list_type *, int size); extern void lua_add_to_list(list_type *, int idx, cptr str); extern void lua_display_list(int y, int x, int h, int w, cptr title, list_type *list, int max, int begin, int sel, byte sel_color); +extern bool_ player_has_corruption(int corruption_idx); + extern cptr compass(int y, int x, int y2, int x2); extern cptr approximate_distance(int y, int x, int y2, int x2); diff --git a/src/lua_bind.c b/src/lua_bind.c index 765b8072..424d1f74 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -585,6 +585,19 @@ void lua_display_list(int y, int x, int h, int w, cptr title, list_type* list, i display_list(y, x, h, w, title, list->list, max, begin, sel, sel_color); } +/* + * Corruptions + */ +bool_ player_has_corruption(int corruption_idx) +{ + if (corruption_idx < 0) + { + return FALSE; + } + + return (p_ptr->corruptions[corruption_idx]); +} + /* * Gods */ diff --git a/src/player.pkg b/src/player.pkg index ef85926a..16370b0a 100644 --- a/src/player.pkg +++ b/src/player.pkg @@ -1815,6 +1815,25 @@ struct player_type bool leaving; }; +/** + * Corruptions + */ +extern s16b CORRUPT_BALROG_AURA; +extern s16b CORRUPT_BALROG_WINGS; +extern s16b CORRUPT_BALROG_STRENGTH; +extern s16b CORRUPT_BALROG_FORM; +extern s16b CORRUPT_DEMON_SPIRIT; +extern s16b CORRUPT_DEMON_HIDE; +extern s16b CORRUPT_DEMON_BREATH; +extern s16b CORRUPT_DEMON_REALM; +extern s16b CORRUPT_RANDOM_TELEPORT; +extern s16b CORRUPT_ANTI_TELEPORT; +extern s16b CORRUPT_TROLL_BLOOD; +extern s16b CORRUPT_VAMPIRE_TEETH; +extern s16b CORRUPT_VAMPIRE_STRENGTH; +extern s16b CORRUPT_VAMPIRE_VAMPIRE; + + /** @name Spellbinder triggers * @{ */ /** @def SPELLBINDER_HP75 diff --git a/src/variable.c b/src/variable.c index 5b1afc3b..3c2295b1 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1597,6 +1597,24 @@ timer_type *gl_timers = NULL; */ s16b tim_precognition = 0; +/** + * Corruptions + */ +s16b CORRUPT_BALROG_AURA = -1; +s16b CORRUPT_BALROG_WINGS = -1; +s16b CORRUPT_BALROG_STRENGTH = -1; +s16b CORRUPT_BALROG_FORM = -1; +s16b CORRUPT_DEMON_SPIRIT = -1; +s16b CORRUPT_DEMON_HIDE = -1; +s16b CORRUPT_DEMON_BREATH = -1; +s16b CORRUPT_DEMON_REALM = -1; +s16b CORRUPT_RANDOM_TELEPORT = -1; +s16b CORRUPT_ANTI_TELEPORT = -1; +s16b CORRUPT_TROLL_BLOOD = -1; +s16b CORRUPT_VAMPIRE_TEETH = -1; +s16b CORRUPT_VAMPIRE_STRENGTH = -1; +s16b CORRUPT_VAMPIRE_VAMPIRE = -1; + /** * Get the version string. */ diff --git a/src/xtra1.c b/src/xtra1.c index 1d2d8ba0..c30d6e4d 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -2503,6 +2503,78 @@ static void calc_schools() } } +/* Apply corruptions */ +static void calc_corruptions() +{ + if (player_has_corruption(CORRUPT_BALROG_AURA)) + { + p_ptr->xtra_f3 |= TR3_SH_FIRE; + p_ptr->xtra_f3 |= TR3_LITE1; + } + + if (player_has_corruption(CORRUPT_BALROG_WINGS)) + { + p_ptr->xtra_f4 |= TR4_FLY; + p_ptr->stat_add[A_CHR] -= 4; + p_ptr->stat_add[A_DEX] -= 2; + } + + if (player_has_corruption(CORRUPT_BALROG_STRENGTH)) + { + p_ptr->stat_add[A_STR] += 3; + p_ptr->stat_add[A_CON] += 1; + p_ptr->stat_add[A_DEX] -= 3; + p_ptr->stat_add[A_CHR] -= 1; + } + + if (player_has_corruption(CORRUPT_DEMON_SPIRIT)) + { + p_ptr->stat_add[A_INT] += 1; + p_ptr->stat_add[A_CHR] -= 2; + } + + if (player_has_corruption(CORRUPT_DEMON_HIDE)) + { + p_ptr->to_a = p_ptr->to_a + p_ptr->lev; + p_ptr->dis_to_a = p_ptr->dis_to_a + p_ptr->lev; + p_ptr->pspeed = p_ptr->pspeed - (p_ptr->lev / 7); + if (p_ptr->lev >= 40) + { + p_ptr->xtra_f2 |= TR2_IM_FIRE; + } + } + + if (player_has_corruption(CORRUPT_DEMON_REALM)) + { + /* 1500 may seem a lot, but people are rather unlikely to + get the corruption very soon due to the dependencies. */ + if (s_info[SKILL_DAEMON].mod == 0) + { + s_info[SKILL_DAEMON].mod = 1500; + } + s_info[SKILL_DAEMON].hidden = FALSE; + } + + if (player_has_corruption(CORRUPT_RANDOM_TELEPORT)) + { + p_ptr->xtra_f3 |= TR3_TELEPORT; + } + + if (player_has_corruption(CORRUPT_ANTI_TELEPORT)) + { + if (p_ptr->corrupt_anti_teleport_stopped == FALSE) + { + p_ptr->resist_continuum = TRUE; + } + } + + if (player_has_corruption(CORRUPT_TROLL_BLOOD)) + { + p_ptr->xtra_f3 |= (TR3_REGEN | TR3_AGGRAVATE); + p_ptr->xtra_esp |= ESP_TROLL; + } +} + /* Apply flags */ static int extra_blows; static int extra_shots; @@ -2920,6 +2992,9 @@ void calc_bonuses(bool_ silent) /* Take care of spell schools */ calc_schools(); + /* Take care of corruptions */ + calc_corruptions(); + /* The powers gived by the wielded monster */ calc_wield_monster(); -- cgit v1.2.3 From 0b42d7ebfc1abd8b8620109bb996e2cee18e9f79 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 5 Apr 2012 23:43:10 +0200 Subject: Lua: Remove last bits of HOOK_CALC_BONUS --- src/defines.h | 1 - src/util.pkg | 6 ------ src/xtra1.c | 3 --- 3 files changed, 10 deletions(-) diff --git a/src/defines.h b/src/defines.h index 3b17211b..2677008a 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4462,7 +4462,6 @@ #define HOOK_ACTIVATE 26 #define HOOK_ZAP 27 #define HOOK_READ 28 -#define HOOK_CALC_BONUS 29 #define HOOK_CALC_POWERS 30 #define HOOK_KEYPRESS 31 #define HOOK_CHAT 32 diff --git a/src/util.pkg b/src/util.pkg index d3d1f041..ab2b6ce2 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -415,12 +415,6 @@ typedef unsigned int u32b; */ #define HOOK_READ 28 -/** @def HOOK_CALC_BONUS - * @brief Calculate player "state" bonuses. - * @note (see xtra1.c) - */ -#define HOOK_CALC_BONUS 29 - /** @def HOOK_CALC_POWERS * @brief Calculate player powers. * @note (see xtra1.c) diff --git a/src/xtra1.c b/src/xtra1.c index c30d6e4d..9a2c2d42 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -2986,9 +2986,6 @@ void calc_bonuses(bool_ silent) calc_body_bonus(); } - /* Let the scripts do what they need */ - process_hooks(HOOK_CALC_BONUS, "()"); - /* Take care of spell schools */ calc_schools(); -- cgit v1.2.3 From 05fedc33f23a2459c4149f2a0970f01ae2602a62 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 6 Apr 2012 10:52:15 +0200 Subject: Lua: Move uses of HOOK_READ to C --- lib/mods/theme/scpt/corrupt.lua | 11 ----------- lib/mods/theme/scpt/misc.lua | 11 ----------- lib/scpt/corrupt.lua | 11 ----------- src/cmd6.c | 18 +++++++++++++++++- src/defines.h | 1 + 5 files changed, 18 insertions(+), 34 deletions(-) diff --git a/lib/mods/theme/scpt/corrupt.lua b/lib/mods/theme/scpt/corrupt.lua index 51d7233b..f3ae60eb 100644 --- a/lib/mods/theme/scpt/corrupt.lua +++ b/lib/mods/theme/scpt/corrupt.lua @@ -13,17 +13,6 @@ CORRUPT_BALROG_AURA = add_corruption " Surrounds you with a fiery aura", " But it can burn scrolls when you read them" }, - ["hooks"] = - { - [HOOK_READ] = function(obj) - if magik(5) == TRUE then - msg_print("Your demon aura burns the scroll before you read it!") - return TRUE, TRUE, FALSE - else - return FALSE - end - end, - }, } CORRUPT_BALROG_WINGS = add_corruption diff --git a/lib/mods/theme/scpt/misc.lua b/lib/mods/theme/scpt/misc.lua index acb45f3c..6738b8f3 100644 --- a/lib/mods/theme/scpt/misc.lua +++ b/lib/mods/theme/scpt/misc.lua @@ -1,14 +1,3 @@ --- New scrolls -function sterilize_scroll(tval, sval) - if tval == 70 and sval == 54 then - msg_print("A neutralising wave radiates from you!") - set_no_breeders(randint(100) + 100) - return TRUE - end -end - -add_hook_script(HOOK_READ, "sterilize_scroll", "sterilize_scroll") - -- Neil's automagic statgain script player.last_rewarded_level = 1 diff --git a/lib/scpt/corrupt.lua b/lib/scpt/corrupt.lua index 1435df6e..ff2b6541 100644 --- a/lib/scpt/corrupt.lua +++ b/lib/scpt/corrupt.lua @@ -12,17 +12,6 @@ CORRUPT_BALROG_AURA = add_corruption " Surrounds you with a fiery aura", " But it can burn scrolls when you read them" }, - ["hooks"] = - { - [HOOK_READ] = function(obj) - if magik(5) == TRUE then - msg_print("Your demon aura burns the scroll before you read it!") - return TRUE, TRUE, FALSE - else - return FALSE - end - end, - }, } CORRUPT_BALROG_WINGS = add_corruption diff --git a/src/cmd6.c b/src/cmd6.c index 987315af..869ad707 100644 --- a/src/cmd6.c +++ b/src/cmd6.c @@ -2899,8 +2899,16 @@ void do_cmd_read_scroll(void) /* Assume the scroll will get used up */ used_up = TRUE; + /* Corruption */ + if (player_has_corruption(CORRUPT_BALROG_AURA) && magik(5)) + { + msg_print("Your demon aura burns the scroll before you read it!"); + used_up = TRUE; + ident = FALSE; + } + /* New scripts, can override the ingame code */ - if (process_hooks_ret(HOOK_READ, "dd", "(O)", o_ptr)) + else if (process_hooks_ret(HOOK_READ, "dd", "(O)", o_ptr)) { used_up = process_hooks_return[0].num; ident = process_hooks_return[1].num; @@ -3509,6 +3517,14 @@ void do_cmd_read_scroll(void) break; } + case SV_SCROLL_STERILIZATION: + { + msg_print("A neutralising wave radiates from you!"); + set_no_breeders(randint(100) + 100); + + break; + } + default: { break; diff --git a/src/defines.h b/src/defines.h index 2677008a..3d258caf 100644 --- a/src/defines.h +++ b/src/defines.h @@ -1938,6 +1938,7 @@ #define SV_SCROLL_RUMOR 51 #define SV_SCROLL_ARTIFACT 52 #define SV_SCROLL_NOTHING 53 +#define SV_SCROLL_STERILIZATION 54 /* The "sval" codes for TV_POTION */ #define SV_POTION_WATER 0 -- cgit v1.2.3 From 5a91c8e154a9b55fa6ccba342f26d8bd03af140d Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 6 Apr 2012 10:52:28 +0200 Subject: Lua: Remove HOOK_READ completely --- src/cmd6.c | 8 +------- src/defines.h | 1 - src/util.pkg | 14 -------------- 3 files changed, 1 insertion(+), 22 deletions(-) diff --git a/src/cmd6.c b/src/cmd6.c index 869ad707..63137a69 100644 --- a/src/cmd6.c +++ b/src/cmd6.c @@ -2907,13 +2907,7 @@ void do_cmd_read_scroll(void) ident = FALSE; } - /* New scripts, can override the ingame code */ - else if (process_hooks_ret(HOOK_READ, "dd", "(O)", o_ptr)) - { - used_up = process_hooks_return[0].num; - ident = process_hooks_return[1].num; - } - /* Traditional scrolls */ + /* Scrolls */ else if (o_ptr->tval == TV_SCROLL) { /* Analyze the scroll */ diff --git a/src/defines.h b/src/defines.h index 3d258caf..605a8c24 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4462,7 +4462,6 @@ #define HOOK_USE 25 #define HOOK_ACTIVATE 26 #define HOOK_ZAP 27 -#define HOOK_READ 28 #define HOOK_CALC_POWERS 30 #define HOOK_KEYPRESS 31 #define HOOK_CHAT 32 diff --git a/src/util.pkg b/src/util.pkg index ab2b6ce2..e988b62e 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -401,20 +401,6 @@ typedef unsigned int u32b; */ #define HOOK_ZAP 27 -/** @def HOOK_READ - * @brief Player reads a scroll.\n - * @param Object o_ptr \n the scroll to read. - * @brief Scroll - * @return Boolean \n TRUE if scroll was read, otherwise FALSE. - * @return Number used_up \n TRUE if the scroll was used up, otherwise FALSE. - * @return Number ident \n TRUE if the scroll was identifed, otherwise FALSE. - * @note - * If the hook returns TRUE, the hook sets the "scroll used up" and - * "scroll identified" flags. - * @note (see file cmd6.c) - */ -#define HOOK_READ 28 - /** @def HOOK_CALC_POWERS * @brief Calculate player powers. * @note (see xtra1.c) -- cgit v1.2.3 From 92e717a03262c95983d7a6bcaaa7da4923ce850f Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 6 Apr 2012 11:09:30 +0200 Subject: Lua: Remove Lua use of HOOK_QUAFF. --- lib/mods/theme/scpt/corrupt.lua | 8 -------- lib/mods/theme/scpt/misc.lua | 12 ------------ lib/scpt/corrupt.lua | 8 -------- src/cmd6.c | 20 +++++++++++++++++++- 4 files changed, 19 insertions(+), 29 deletions(-) diff --git a/lib/mods/theme/scpt/corrupt.lua b/lib/mods/theme/scpt/corrupt.lua index f3ae60eb..5cacd2b7 100644 --- a/lib/mods/theme/scpt/corrupt.lua +++ b/lib/mods/theme/scpt/corrupt.lua @@ -129,14 +129,6 @@ CORRUPT_DEMON_BREATH = add_corruption [HOOK_CALC_POWERS] = function() player.add_power(PWR_BR_FIRE) end, - [HOOK_QUAFF] = function(obj) - if magik(9) == TRUE then - msg_print("Your demon breath spoils the potion!") - return TRUE, FALSE - else - return FALSE - end - end, }, } diff --git a/lib/mods/theme/scpt/misc.lua b/lib/mods/theme/scpt/misc.lua index 6738b8f3..17eba40f 100644 --- a/lib/mods/theme/scpt/misc.lua +++ b/lib/mods/theme/scpt/misc.lua @@ -164,18 +164,6 @@ add_building_action end } --- function to make Melkor like it if a player quaffs potions of corruption -function melkor_potion_corruption(object) - if (player.pgod == GOD_MELKOR) then - if (object.tval == TV_POTION) and (object.sval == SV_POTION_MUTATION) then - msg_print("Your quaffing of this potion pleases Melkor!") - set_grace(player.grace + 2) - return FALSE - end - end -end -add_hook_script(HOOK_QUAFF, "melkor_potion_corruption", "melkor_potion_corruption") - -- function to check for Key of Orthanc before proceeding to the final level in Isengard add_hooks { diff --git a/lib/scpt/corrupt.lua b/lib/scpt/corrupt.lua index ff2b6541..ae9eff8c 100644 --- a/lib/scpt/corrupt.lua +++ b/lib/scpt/corrupt.lua @@ -110,14 +110,6 @@ CORRUPT_DEMON_BREATH = add_corruption [HOOK_CALC_POWERS] = function() player.add_power(PWR_BR_FIRE) end, - [HOOK_QUAFF] = function(obj) - if magik(9) == TRUE then - msg_print("Your demon breath spoils the potion!") - return TRUE, FALSE - else - return FALSE - end - end, }, } diff --git a/src/cmd6.c b/src/cmd6.c index 63137a69..b70654a9 100644 --- a/src/cmd6.c +++ b/src/cmd6.c @@ -2335,6 +2335,17 @@ static bool_ quaff_potion(int tval, int sval, int pval, int pval2) case SV_POTION_MUTATION: { + /* In Theme, Melkor likes players who quaff + potions of corruption. */ + if (game_module_idx == MODULE_THEME) + { + GOD(GOD_MELKOR) + { + msg_print("Your quaffing of this potion pleases Melkor!"); + set_grace(p_ptr->grace + 2); + } + } + msg_print("You feel the dark corruptions of Morgoth coming over you!"); gain_random_corruption(0); ident = TRUE; @@ -2478,8 +2489,15 @@ void do_cmd_quaff_potion(void) /* Object level */ lev = k_info[o_ptr->k_idx].level; + /* Demon Breath corruption can spoil potions. */ + if (player_has_corruption(CORRUPT_DEMON_BREATH) && magik(9)) + { + msg_print("Your demon breath spoils the potion!"); + ident = FALSE; + } + /* Analyze the potion */ - if (process_hooks_ret(HOOK_QUAFF, "d", "(O)", o_ptr)) + else if (process_hooks_ret(HOOK_QUAFF, "d", "(O)", o_ptr)) { ident = process_hooks_return[0].num; } -- cgit v1.2.3 From 8ffbaea87b5ca17e7baa77cf17986a5b9dfc585e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 6 Apr 2012 11:10:49 +0200 Subject: Lua: Remove HOOK_QUAFF completely --- src/cmd6.c | 7 +------ src/defines.h | 1 - src/util.pkg | 12 ------------ 3 files changed, 1 insertion(+), 19 deletions(-) diff --git a/src/cmd6.c b/src/cmd6.c index b70654a9..48d56125 100644 --- a/src/cmd6.c +++ b/src/cmd6.c @@ -2495,14 +2495,9 @@ void do_cmd_quaff_potion(void) msg_print("Your demon breath spoils the potion!"); ident = FALSE; } - - /* Analyze the potion */ - else if (process_hooks_ret(HOOK_QUAFF, "d", "(O)", o_ptr)) - { - ident = process_hooks_return[0].num; - } else { + /* Normal potion handling */ ident = quaff_potion(o_ptr->tval, o_ptr->sval, o_ptr->pval, o_ptr->pval2); } diff --git a/src/defines.h b/src/defines.h index 605a8c24..d40e3b90 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4457,7 +4457,6 @@ #define HOOK_PLAYER_LEVEL 20 #define HOOK_WIELD 21 #define HOOK_INIT 22 -#define HOOK_QUAFF 23 #define HOOK_AIM 24 #define HOOK_USE 25 #define HOOK_ACTIVATE 26 diff --git a/src/util.pkg b/src/util.pkg index e988b62e..d00dcb76 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -361,18 +361,6 @@ typedef unsigned int u32b; */ #define HOOK_INIT 22 -/** @def HOOK_QUAFF - * @brief Player quaffs a potion.\n - * @param Object o_ptr \n the potion to quaff. - * @brief Potion - * @return Boolean \n TRUE if potion was quaffed, otherwise FALSE. - * @return Number ident \n TRUE if the potion was identifed, otherwise FALSE. - * @note - * If the hook returns TRUE, the hook sets the "potion identified" flag. - * @note (see file cmd6.c) - */ -#define HOOK_QUAFF 23 - /** @def HOOK_AIM */ #define HOOK_AIM 24 -- cgit v1.2.3 From 6a860ab9022123d9fc5387424ef49eb3a814c64b Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 6 Apr 2012 11:54:47 +0200 Subject: Lua: Add C identifiers for Theme corruptions --- src/externs.h | 20 ++++++++++++++++++++ src/player.pkg | 20 ++++++++++++++++++++ src/variable.c | 20 ++++++++++++++++++++ 3 files changed, 60 insertions(+) diff --git a/src/externs.h b/src/externs.h index c8e34c84..97569fc0 100644 --- a/src/externs.h +++ b/src/externs.h @@ -618,6 +618,26 @@ extern s16b CORRUPT_TROLL_BLOOD; extern s16b CORRUPT_VAMPIRE_TEETH; extern s16b CORRUPT_VAMPIRE_STRENGTH; extern s16b CORRUPT_VAMPIRE_VAMPIRE; +extern s16b MUT1_SPIT_ACID; +extern s16b MUT1_BR_FIRE; +extern s16b MUT1_HYPN_GAZE; +extern s16b MUT1_TELEKINES; +extern s16b MUT1_VTELEPORT; +extern s16b MUT1_MIND_BLST; +extern s16b MUT1_VAMPIRISM; +extern s16b MUT1_SMELL_MET; +extern s16b MUT1_SMELL_MON; +extern s16b MUT1_BLINK; +extern s16b MUT1_EAT_ROCK; +extern s16b MUT1_SWAP_POS; +extern s16b MUT1_SHRIEK; +extern s16b MUT1_ILLUMINE; +extern s16b MUT1_DET_CURSE; +extern s16b MUT1_BERSERK; +extern s16b MUT1_MIDAS_TCH; +extern s16b MUT1_GROW_MOLD; +extern s16b MUT1_RESIST; +extern s16b MUT1_EARTHQUAKE; /* plots.c */ extern FILE *hook_file; diff --git a/src/player.pkg b/src/player.pkg index 16370b0a..f34d108b 100644 --- a/src/player.pkg +++ b/src/player.pkg @@ -1832,6 +1832,26 @@ extern s16b CORRUPT_TROLL_BLOOD; extern s16b CORRUPT_VAMPIRE_TEETH; extern s16b CORRUPT_VAMPIRE_STRENGTH; extern s16b CORRUPT_VAMPIRE_VAMPIRE; +extern s16b MUT1_SPIT_ACID; +extern s16b MUT1_BR_FIRE; +extern s16b MUT1_HYPN_GAZE; +extern s16b MUT1_TELEKINES; +extern s16b MUT1_VTELEPORT; +extern s16b MUT1_MIND_BLST; +extern s16b MUT1_VAMPIRISM; +extern s16b MUT1_SMELL_MET; +extern s16b MUT1_SMELL_MON; +extern s16b MUT1_BLINK; +extern s16b MUT1_EAT_ROCK; +extern s16b MUT1_SWAP_POS; +extern s16b MUT1_SHRIEK; +extern s16b MUT1_ILLUMINE; +extern s16b MUT1_DET_CURSE; +extern s16b MUT1_BERSERK; +extern s16b MUT1_MIDAS_TCH; +extern s16b MUT1_GROW_MOLD; +extern s16b MUT1_RESIST; +extern s16b MUT1_EARTHQUAKE; /** @name Spellbinder triggers diff --git a/src/variable.c b/src/variable.c index 3c2295b1..33c2dbac 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1614,6 +1614,26 @@ s16b CORRUPT_TROLL_BLOOD = -1; s16b CORRUPT_VAMPIRE_TEETH = -1; s16b CORRUPT_VAMPIRE_STRENGTH = -1; s16b CORRUPT_VAMPIRE_VAMPIRE = -1; +s16b MUT1_SPIT_ACID = -1; +s16b MUT1_BR_FIRE = -1; +s16b MUT1_HYPN_GAZE = -1; +s16b MUT1_TELEKINES = -1; +s16b MUT1_VTELEPORT = -1; +s16b MUT1_MIND_BLST = -1; +s16b MUT1_VAMPIRISM = -1; +s16b MUT1_SMELL_MET = -1; +s16b MUT1_SMELL_MON = -1; +s16b MUT1_BLINK = -1; +s16b MUT1_EAT_ROCK = -1; +s16b MUT1_SWAP_POS = -1; +s16b MUT1_SHRIEK = -1; +s16b MUT1_ILLUMINE = -1; +s16b MUT1_DET_CURSE = -1; +s16b MUT1_BERSERK = -1; +s16b MUT1_MIDAS_TCH = -1; +s16b MUT1_GROW_MOLD = -1; +s16b MUT1_RESIST = -1; +s16b MUT1_EARTHQUAKE = -1; /** * Get the version string. -- cgit v1.2.3 From 3f819c170739b098f9f7951fc9c2ff407f3bbf03 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 6 Apr 2012 11:40:03 +0200 Subject: Lua: Moved corruption "can_gain" checks to C --- lib/core/crpt_aux.lua | 6 +- lib/mods/theme/core/crpt_aux.lua | 6 +- lib/mods/theme/scpt/corrupt.lua | 261 --------------------------------------- lib/scpt/corrupt.lua | 8 -- src/externs.h | 1 + src/lua_bind.c | 45 +++++++ src/player.pkg | 1 + 7 files changed, 49 insertions(+), 279 deletions(-) diff --git a/lib/core/crpt_aux.lua b/lib/core/crpt_aux.lua index c1772c04..85cddbf3 100644 --- a/lib/core/crpt_aux.lua +++ b/lib/core/crpt_aux.lua @@ -55,11 +55,7 @@ function test_depend_corrupt(corrupt, can_gain) end -- are we even allowed to get it? - if __corruptions[corrupt].can_gain and (not __corruptions[corrupt].can_gain()) then - return FALSE - end - - return TRUE + return player_can_gain_corruption(corrupt) end -- Gain a new corruption diff --git a/lib/mods/theme/core/crpt_aux.lua b/lib/mods/theme/core/crpt_aux.lua index c1772c04..85cddbf3 100644 --- a/lib/mods/theme/core/crpt_aux.lua +++ b/lib/mods/theme/core/crpt_aux.lua @@ -55,11 +55,7 @@ function test_depend_corrupt(corrupt, can_gain) end -- are we even allowed to get it? - if __corruptions[corrupt].can_gain and (not __corruptions[corrupt].can_gain()) then - return FALSE - end - - return TRUE + return player_can_gain_corruption(corrupt) end -- Gain a new corruption diff --git a/lib/mods/theme/scpt/corrupt.lua b/lib/mods/theme/scpt/corrupt.lua index 5cacd2b7..440a1d81 100644 --- a/lib/mods/theme/scpt/corrupt.lua +++ b/lib/mods/theme/scpt/corrupt.lua @@ -79,15 +79,6 @@ CORRUPT_DEMON_SPIRIT = add_corruption " Increases your intelligence by 1", " But reduce your charisma by 2", }, -["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, } CORRUPT_DEMON_HIDE = add_corruption @@ -102,15 +93,6 @@ CORRUPT_DEMON_HIDE = add_corruption " Provides immunity to fire at level 40", " But reduces speed by your level / 7", }, -["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, } CORRUPT_DEMON_BREATH = add_corruption @@ -149,15 +131,6 @@ CORRUPT_DEMON_REALM = add_corruption [CORRUPT_DEMON_HIDE] = TRUE, [CORRUPT_DEMON_BREATH] = TRUE }, -["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, } @@ -175,15 +148,6 @@ CORRUPT_RANDOM_TELEPORT = add_corruption { " Randomly teleports you around", }, -["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, -- No oppose field, it will be automatically set when we declare the anti-telep corruption to oppose us ["hooks"] = { @@ -218,15 +182,6 @@ CORRUPT_ANTI_TELEPORT = add_corruption { [CORRUPT_RANDOM_TELEPORT] = TRUE }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_BIRTH_OBJECTS] = function() @@ -265,15 +220,6 @@ CORRUPT_TROLL_BLOOD = add_corruption " It also enables you to feel the presence of other troll beings", " But it will make your presence more noticeable and aggravating", }, - ["can_gain"] = function() - -- Ok trolls should not get this one. never. - local str = get_race_name() - if (str == "Maia") or (str == "Troll") then - return nil - else - return not nil - end - end, } -- The vampire corruption set @@ -290,15 +236,6 @@ CORRUPT_VAMPIRE_TEETH = add_corruption " Your teeth allow you to drain blood to feed yourself", " However your stomach now only accepts blood.", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["allow"] = function() if test_race_flags(1, PR1_NO_SUBRACE_CHANGE) == FALSE then return not nil else return nil end end, @@ -330,15 +267,6 @@ CORRUPT_VAMPIRE_STRENGTH = add_corruption { [CORRUPT_VAMPIRE_TEETH] = TRUE, }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["gain"] = function() -- Apply the bonuses/penalities subrace(SUBRACE_SAVE).r_mhp = subrace(SUBRACE_SAVE).r_mhp + 1 @@ -376,15 +304,6 @@ CORRUPT_VAMPIRE_VAMPIRE = add_corruption { [CORRUPT_VAMPIRE_STRENGTH] = TRUE, }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["gain"] = function() -- Be a Vampire and be proud of it local title = get_subrace_title(SUBRACE_SAVE) @@ -420,15 +339,6 @@ MUT1_SPIT_ACID = add_corruption " Damage=level Radius 1+(level/30)", " Level=9, Cost=9, Stat=DEX, Difficulty=15", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() @@ -449,15 +359,6 @@ MUT1_BR_FIRE = add_corruption " Damage=2*level Radius 1+(level/20)", " Level=20, Cost=10, Stat=CON, Difficulty=18", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() @@ -478,15 +379,6 @@ MUT1_HYPN_GAZE = add_corruption " Power=level", " Level=12, Cost=12, Stat=CHR, Difficulty=18", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() @@ -507,15 +399,6 @@ MUT1_TELEKINES = add_corruption " Max weight equal to (level) pounds", " Level=9, Cost=9, Stat=WIS, Difficulty=14", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() @@ -536,15 +419,6 @@ MUT1_VTELEPORT = add_corruption " Distance 10+4*level squares", " Level=7, Cost=7, Stat=WIS, Difficulty=15", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() @@ -565,15 +439,6 @@ MUT1_MIND_BLST = add_corruption " Psi Damage (3+(level-1)/5)d3", " Level=5, Cost=3, Stat=WIS, Difficulty=15", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() @@ -595,15 +460,6 @@ MUT1_VAMPIRISM = add_corruption " heals you and satiates you. Doesn't work on all monsters", " Level=4, Cost=5, Stat=CON, Difficulty=9", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() @@ -624,15 +480,6 @@ MUT1_SMELL_MET = add_corruption " Radius 25", " Level=3, Cost=2, Stat=INT, Difficulty=12", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() @@ -653,15 +500,6 @@ MUT1_SMELL_MON = add_corruption " Radius 25", " Level=5, Cost=4, Stat=INT, Difficulty=15", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() @@ -681,15 +519,6 @@ MUT1_BLINK = add_corruption " You can teleport yourself short distances (10 squares).", " Level=3, Cost=3, Stat=WIS, Difficulty=12", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() @@ -710,15 +539,6 @@ MUT1_EAT_ROCK = add_corruption " leaving an empty space behind.", " Level=8, Cost=12, Stat=CON, Difficulty=18", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() @@ -739,15 +559,6 @@ MUT1_SWAP_POS = add_corruption " unless it resists teleportation.", " Level=15, Cost=12, Stat=DEX, Difficulty=16", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() @@ -768,15 +579,6 @@ MUT1_SHRIEK = add_corruption " Damage=level*4, Radius=8, centered on player", " Level=4, Cost=4, Stat=CON, Difficulty=6", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() @@ -797,15 +599,6 @@ MUT1_ILLUMINE = add_corruption " Damage=2d(level/2) Radius=(level/10)+1", " Level=3, Cost=2, Stat=INT, Difficulty=10", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() @@ -826,15 +619,6 @@ MUT1_DET_CURSE = add_corruption " It detects cursed items in the inventory", " Level=7, Cost=14, Stat=WIS, Difficulty=14", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() @@ -855,15 +639,6 @@ MUT1_BERSERK = add_corruption " It grants super-heroism. Duration=10+1d(level)", " Level=8, Cost=8, Stat=STR, Difficulty=14", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() @@ -885,15 +660,6 @@ MUT1_MIDAS_TCH = add_corruption " Turns a non-artifact object into 1/3 its value in gold", " Level=10, Cost=5, Stat=INT, Difficulty=12", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() @@ -914,15 +680,6 @@ MUT1_GROW_MOLD = add_corruption " Summons up to 8 molds around the player", " Level=1, Cost=6, Stat=CON, Difficulty=14", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() @@ -944,15 +701,6 @@ MUT1_RESIST = add_corruption " elements and poison. Duration=20 + d20", " Level=10, Cost=12, Stat=CON, Difficulty=12", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() @@ -973,15 +721,6 @@ MUT1_EARTHQUAKE = add_corruption " Radius=10, center on the player", " Level=12, Cost=12, Stat=STR, Difficulty=16", }, - ["can_gain"] = function() - -- Maiar can't get this one! - local str = get_race_name() - if str == "Maia" then - return nil - else - return not nil - end - end, ["hooks"] = { [HOOK_CALC_POWERS] = function() diff --git a/lib/scpt/corrupt.lua b/lib/scpt/corrupt.lua index ae9eff8c..f72ddf2d 100644 --- a/lib/scpt/corrupt.lua +++ b/lib/scpt/corrupt.lua @@ -219,14 +219,6 @@ CORRUPT_TROLL_BLOOD = add_corruption " It also enables you to feel the presence of other troll beings", " But it will make your presence more noticeable and aggravating", }, - ["can_gain"] = function() - -- Ok trolls should not get this one. never. - if get_race_name() == "Troll" then - return nil - else - return not nil - end - end, } -- The vampire corruption set diff --git a/src/externs.h b/src/externs.h index 97569fc0..469f9633 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1869,6 +1869,7 @@ extern void lua_add_to_list(list_type *, int idx, cptr str); extern void lua_display_list(int y, int x, int h, int w, cptr title, list_type *list, int max, int begin, int sel, byte sel_color); extern bool_ player_has_corruption(int corruption_idx); +extern bool_ player_can_gain_corruption(int corruption_idx); extern cptr compass(int y, int x, int y2, int x2); extern cptr approximate_distance(int y, int x, int y2, int x2); diff --git a/src/lua_bind.c b/src/lua_bind.c index 424d1f74..e9eb95a0 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -11,6 +11,7 @@ */ #include "angband.h" +#include #include "lua.h" #include "tolua.h" @@ -595,9 +596,53 @@ bool_ player_has_corruption(int corruption_idx) return FALSE; } + + return (p_ptr->corruptions[corruption_idx]); } +bool_ player_can_gain_corruption(int corruption_idx) +{ + cptr r_name = rp_ptr->title + rp_name; + bool_ allowed = TRUE; /* Allowed by default */ + + assert(corruption_idx >= 0); + + if (corruption_idx == CORRUPT_TROLL_BLOOD) + { + /* Ok trolls should not get this one. never. */ + if (streq(r_name, "Troll")) + { + allowed = FALSE; + } + } + + /* Theme module adds additional restrictions for Maiar */ + + if (game_module_idx == MODULE_THEME) + { + if (streq(r_name, "Maia")) + { + /* We use a whitelist of corruptions for Maiar */ + bool_ allow = FALSE; + if ((corruption_idx == CORRUPT_BALROG_AURA) || + (corruption_idx == CORRUPT_BALROG_WINGS) || + (corruption_idx == CORRUPT_BALROG_STRENGTH) || + (corruption_idx == CORRUPT_BALROG_FORM) || + (corruption_idx == CORRUPT_DEMON_BREATH)) + { + allow = TRUE; + }; + + /* Mix result into 'allowed' flag */ + allowed = allowed & allow; + } + } + + /* Result */ + return allowed; +} + /* * Gods */ diff --git a/src/player.pkg b/src/player.pkg index f34d108b..16b280c9 100644 --- a/src/player.pkg +++ b/src/player.pkg @@ -1853,6 +1853,7 @@ extern s16b MUT1_GROW_MOLD; extern s16b MUT1_RESIST; extern s16b MUT1_EARTHQUAKE; +extern bool player_can_gain_corruption(int corruption_idx); /** @name Spellbinder triggers * @{ */ -- cgit v1.2.3 From 09c56bf058a10fcaaff2e88e3259477557f00cc9 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 6 Apr 2012 13:23:02 +0200 Subject: Lua: Add "bindings" for accessing POWER_* from C code --- src/externs.h | 3 +++ src/player.pkg | 5 +++++ src/variable.c | 9 +++++++++ 3 files changed, 17 insertions(+) diff --git a/src/externs.h b/src/externs.h index 469f9633..3a0d8191 100644 --- a/src/externs.h +++ b/src/externs.h @@ -638,6 +638,9 @@ extern s16b MUT1_MIDAS_TCH; extern s16b MUT1_GROW_MOLD; extern s16b MUT1_RESIST; extern s16b MUT1_EARTHQUAKE; +extern s16b POWER_INVISIBILITY; +extern s16b POWER_WEB; +extern s16b POWER_COR_SPACE_TIME; /* plots.c */ extern FILE *hook_file; diff --git a/src/player.pkg b/src/player.pkg index 16b280c9..080d40a9 100644 --- a/src/player.pkg +++ b/src/player.pkg @@ -3429,6 +3429,11 @@ extern void desc_god(int g_idx, int d, char *desc); #define PWR_BALROG 61 /** @} */ +extern s16b POWER_INVISIBILITY; +extern s16b POWER_WEB; +extern s16b POWER_COR_SPACE_TIME; + + /* Misc */ /** @fn do_cmd_throw(void) * @brief Throw an object from the pack or floor. diff --git a/src/variable.c b/src/variable.c index 33c2dbac..b73a1edf 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1635,6 +1635,15 @@ s16b MUT1_GROW_MOLD = -1; s16b MUT1_RESIST = -1; s16b MUT1_EARTHQUAKE = -1; + +/* + * Powers + */ +s16b POWER_INVISIBILITY = -1; +s16b POWER_WEB = -1; +s16b POWER_COR_SPACE_TIME = -1; + + /** * Get the version string. */ -- cgit v1.2.3 From d5712602c95caccc32dd73fa54592370b91cc398 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 6 Apr 2012 13:23:52 +0200 Subject: Lua: Move "powers granted by corruptions" calculation from Lua to C. --- lib/mods/theme/scpt/corrupt.lua | 135 ---------------------------------------- lib/scpt/corrupt.lua | 15 ----- src/xtra1.c | 49 +++++++++++++++ 3 files changed, 49 insertions(+), 150 deletions(-) diff --git a/lib/mods/theme/scpt/corrupt.lua b/lib/mods/theme/scpt/corrupt.lua index 440a1d81..81b87847 100644 --- a/lib/mods/theme/scpt/corrupt.lua +++ b/lib/mods/theme/scpt/corrupt.lua @@ -58,12 +58,6 @@ CORRUPT_BALROG_FORM = add_corruption [CORRUPT_BALROG_WINGS] = TRUE, [CORRUPT_BALROG_STRENGTH] = TRUE }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_BALROG) - end, - }, } @@ -106,12 +100,6 @@ CORRUPT_DEMON_BREATH = add_corruption " Provides fire breath", " But gives a small chance to spoil potions when you quaff them", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_BR_FIRE) - end, - }, } CORRUPT_DEMON_REALM = add_corruption @@ -187,9 +175,6 @@ CORRUPT_ANTI_TELEPORT = add_corruption [HOOK_BIRTH_OBJECTS] = function() player.corrupt_anti_teleport_stopped = FALSE end, - [HOOK_CALC_POWERS] = function() - player.add_power(POWER_COR_SPACE_TIME) - end, [HOOK_PROCESS_WORLD] = function() if player.corrupt_anti_teleport_stopped == TRUE then local amt = player.msp + player.csp @@ -339,12 +324,6 @@ MUT1_SPIT_ACID = add_corruption " Damage=level Radius 1+(level/30)", " Level=9, Cost=9, Stat=DEX, Difficulty=15", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_SPIT_ACID) - end, - }, } MUT1_BR_FIRE = add_corruption @@ -359,12 +338,6 @@ MUT1_BR_FIRE = add_corruption " Damage=2*level Radius 1+(level/20)", " Level=20, Cost=10, Stat=CON, Difficulty=18", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_BR_FIRE) - end, - }, } MUT1_HYPN_GAZE = add_corruption @@ -379,12 +352,6 @@ MUT1_HYPN_GAZE = add_corruption " Power=level", " Level=12, Cost=12, Stat=CHR, Difficulty=18", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_HYPN_GAZE) - end, - }, } MUT1_TELEKINES = add_corruption @@ -399,12 +366,6 @@ MUT1_TELEKINES = add_corruption " Max weight equal to (level) pounds", " Level=9, Cost=9, Stat=WIS, Difficulty=14", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_TELEKINES) - end, - }, } MUT1_VTELEPORT = add_corruption @@ -419,12 +380,6 @@ MUT1_VTELEPORT = add_corruption " Distance 10+4*level squares", " Level=7, Cost=7, Stat=WIS, Difficulty=15", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_VTELEPORT) - end, - }, } MUT1_MIND_BLST = add_corruption @@ -439,12 +394,6 @@ MUT1_MIND_BLST = add_corruption " Psi Damage (3+(level-1)/5)d3", " Level=5, Cost=3, Stat=WIS, Difficulty=15", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_MIND_BLST) - end, - }, } MUT1_VAMPIRISM = add_corruption @@ -460,12 +409,6 @@ MUT1_VAMPIRISM = add_corruption " heals you and satiates you. Doesn't work on all monsters", " Level=4, Cost=5, Stat=CON, Difficulty=9", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_VAMPIRISM) - end, - }, } MUT1_SMELL_MET = add_corruption @@ -480,12 +423,6 @@ MUT1_SMELL_MET = add_corruption " Radius 25", " Level=3, Cost=2, Stat=INT, Difficulty=12", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_SMELL_MET) - end, - }, } MUT1_SMELL_MON = add_corruption @@ -500,12 +437,6 @@ MUT1_SMELL_MON = add_corruption " Radius 25", " Level=5, Cost=4, Stat=INT, Difficulty=15", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_SMELL_MON) - end, - }, } MUT1_BLINK = add_corruption @@ -519,12 +450,6 @@ MUT1_BLINK = add_corruption " You can teleport yourself short distances (10 squares).", " Level=3, Cost=3, Stat=WIS, Difficulty=12", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_BLINK) - end, - }, } MUT1_EAT_ROCK = add_corruption @@ -539,12 +464,6 @@ MUT1_EAT_ROCK = add_corruption " leaving an empty space behind.", " Level=8, Cost=12, Stat=CON, Difficulty=18", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_EAT_ROCK) - end, - }, } MUT1_SWAP_POS = add_corruption @@ -559,12 +478,6 @@ MUT1_SWAP_POS = add_corruption " unless it resists teleportation.", " Level=15, Cost=12, Stat=DEX, Difficulty=16", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_SWAP_POS) - end, - }, } MUT1_SHRIEK = add_corruption @@ -579,12 +492,6 @@ MUT1_SHRIEK = add_corruption " Damage=level*4, Radius=8, centered on player", " Level=4, Cost=4, Stat=CON, Difficulty=6", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_SHRIEK) - end, - }, } MUT1_ILLUMINE = add_corruption @@ -599,12 +506,6 @@ MUT1_ILLUMINE = add_corruption " Damage=2d(level/2) Radius=(level/10)+1", " Level=3, Cost=2, Stat=INT, Difficulty=10", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_ILLUMINE) - end, - }, } MUT1_DET_CURSE = add_corruption @@ -619,12 +520,6 @@ MUT1_DET_CURSE = add_corruption " It detects cursed items in the inventory", " Level=7, Cost=14, Stat=WIS, Difficulty=14", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_DET_CURSE) - end, - }, } MUT1_BERSERK = add_corruption @@ -639,12 +534,6 @@ MUT1_BERSERK = add_corruption " It grants super-heroism. Duration=10+1d(level)", " Level=8, Cost=8, Stat=STR, Difficulty=14", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_BERSERK) - end, - }, } @@ -660,12 +549,6 @@ MUT1_MIDAS_TCH = add_corruption " Turns a non-artifact object into 1/3 its value in gold", " Level=10, Cost=5, Stat=INT, Difficulty=12", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_MIDAS_TCH) - end, - }, } MUT1_GROW_MOLD = add_corruption @@ -680,12 +563,6 @@ MUT1_GROW_MOLD = add_corruption " Summons up to 8 molds around the player", " Level=1, Cost=6, Stat=CON, Difficulty=14", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_GROW_MOLD) - end, - }, } MUT1_RESIST = add_corruption @@ -701,12 +578,6 @@ MUT1_RESIST = add_corruption " elements and poison. Duration=20 + d20", " Level=10, Cost=12, Stat=CON, Difficulty=12", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_RESIST) - end, - }, } MUT1_EARTHQUAKE = add_corruption @@ -721,12 +592,6 @@ MUT1_EARTHQUAKE = add_corruption " Radius=10, center on the player", " Level=12, Cost=12, Stat=STR, Difficulty=16", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_EARTHQUAKE) - end, - }, } --[[ CORRUPT_ = add_corruption diff --git a/lib/scpt/corrupt.lua b/lib/scpt/corrupt.lua index f72ddf2d..c58c8414 100644 --- a/lib/scpt/corrupt.lua +++ b/lib/scpt/corrupt.lua @@ -57,12 +57,6 @@ CORRUPT_BALROG_FORM = add_corruption [CORRUPT_BALROG_WINGS] = TRUE, [CORRUPT_BALROG_STRENGTH] = TRUE }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_BALROG) - end, - }, } @@ -105,12 +99,6 @@ CORRUPT_DEMON_BREATH = add_corruption " Provides fire breath", " But gives a small chance to spoil potions when you quaff them", }, - ["hooks"] = - { - [HOOK_CALC_POWERS] = function() - player.add_power(PWR_BR_FIRE) - end, - }, } CORRUPT_DEMON_REALM = add_corruption @@ -186,9 +174,6 @@ CORRUPT_ANTI_TELEPORT = add_corruption [HOOK_BIRTH_OBJECTS] = function() player.corrupt_anti_teleport_stopped = FALSE end, - [HOOK_CALC_POWERS] = function() - player.add_power(POWER_COR_SPACE_TIME) - end, [HOOK_PROCESS_WORLD] = function() if player.corrupt_anti_teleport_stopped == TRUE then local amt = player.msp + player.csp diff --git a/src/xtra1.c b/src/xtra1.c index 9a2c2d42..54c079b8 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -1516,6 +1516,52 @@ static void calc_spells(void) p_ptr->new_spells = 0; } + +/* + * Calculate powers of player given the current set of corruptions. + */ +static void calc_powers_corruption() +{ + /* Map of corruptions to a power */ + s16b power_by_corruption[][2] = + { { CORRUPT_BALROG_FORM , PWR_BALROG }, + { CORRUPT_DEMON_BREATH , PWR_BR_FIRE }, + { CORRUPT_ANTI_TELEPORT , POWER_COR_SPACE_TIME }, + { MUT1_SPIT_ACID , PWR_SPIT_ACID }, + { MUT1_BR_FIRE , PWR_BR_FIRE }, + { MUT1_HYPN_GAZE , PWR_HYPN_GAZE }, + { MUT1_TELEKINES , PWR_TELEKINES }, + { MUT1_VTELEPORT , PWR_VTELEPORT }, + { MUT1_MIND_BLST , PWR_MIND_BLST }, + { MUT1_VAMPIRISM , PWR_VAMPIRISM }, + { MUT1_SMELL_MET , PWR_SMELL_MET }, + { MUT1_SMELL_MON , PWR_SMELL_MON }, + { MUT1_BLINK , PWR_BLINK }, + { MUT1_EAT_ROCK , PWR_EAT_ROCK }, + { MUT1_SWAP_POS , PWR_SWAP_POS }, + { MUT1_SHRIEK , PWR_SHRIEK }, + { MUT1_ILLUMINE , PWR_ILLUMINE }, + { MUT1_DET_CURSE , PWR_DET_CURSE }, + { MUT1_BERSERK , PWR_BERSERK }, + { MUT1_MIDAS_TCH , PWR_MIDAS_TCH }, + { MUT1_GROW_MOLD , PWR_GROW_MOLD }, + { MUT1_RESIST , PWR_RESIST }, + { MUT1_EARTHQUAKE , PWR_EARTHQUAKE }, + { -1 , -1 }, + }; + int i; + + /* Grant powers according to whatever corruptions the player has */ + for (i = 0; power_by_corruption[i][0] >= 0; i++) + { + if (player_has_corruption(power_by_corruption[i][0])) + { + p_ptr->powers[power_by_corruption[i][1]] = TRUE; + } + } +} + + /* Ugly hack */ bool_ calc_powers_silent = FALSE; @@ -1540,6 +1586,9 @@ static void calc_powers(void) for (i = 0; i < POWER_MAX_INIT; i++) p_ptr->powers[i] = p_ptr->powers_mod[i]; for (; i < power_max; i++) p_ptr->powers[i] = 0; + /* Calculate powers granted by corruptions */ + calc_powers_corruption(); + /* Hooked powers */ process_hooks(HOOK_CALC_POWERS, "()"); -- cgit v1.2.3 From 8a0cd497bc0848adaefa56321321df7d0b19dd22 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 6 Apr 2012 15:01:52 +0200 Subject: Lua: Remove unneeded init of corrupt_anti_teleport_stopped --- lib/mods/theme/scpt/corrupt.lua | 3 --- lib/scpt/corrupt.lua | 3 --- 2 files changed, 6 deletions(-) diff --git a/lib/mods/theme/scpt/corrupt.lua b/lib/mods/theme/scpt/corrupt.lua index 81b87847..dc750f0f 100644 --- a/lib/mods/theme/scpt/corrupt.lua +++ b/lib/mods/theme/scpt/corrupt.lua @@ -172,9 +172,6 @@ CORRUPT_ANTI_TELEPORT = add_corruption }, ["hooks"] = { - [HOOK_BIRTH_OBJECTS] = function() - player.corrupt_anti_teleport_stopped = FALSE - end, [HOOK_PROCESS_WORLD] = function() if player.corrupt_anti_teleport_stopped == TRUE then local amt = player.msp + player.csp diff --git a/lib/scpt/corrupt.lua b/lib/scpt/corrupt.lua index c58c8414..b9cae0b1 100644 --- a/lib/scpt/corrupt.lua +++ b/lib/scpt/corrupt.lua @@ -171,9 +171,6 @@ CORRUPT_ANTI_TELEPORT = add_corruption }, ["hooks"] = { - [HOOK_BIRTH_OBJECTS] = function() - player.corrupt_anti_teleport_stopped = FALSE - end, [HOOK_PROCESS_WORLD] = function() if player.corrupt_anti_teleport_stopped == TRUE then local amt = player.msp + player.csp -- cgit v1.2.3 From e620b7e9e0b6a70f4c350c84a7c18ea2b523eab4 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 6 Apr 2012 15:11:18 +0200 Subject: Lua: Refactor HOOK_PROCESS_WORLD code from corrupt.lua to C --- lib/mods/theme/scpt/corrupt.lua | 32 --------------------------- lib/scpt/corrupt.lua | 32 --------------------------- src/dungeon.c | 49 +++++++++++++++++++++++++++++++++++++++++ src/externs.h | 2 ++ src/lua_bind.c | 7 ++++++ 5 files changed, 58 insertions(+), 64 deletions(-) diff --git a/lib/mods/theme/scpt/corrupt.lua b/lib/mods/theme/scpt/corrupt.lua index dc750f0f..2f3d30ce 100644 --- a/lib/mods/theme/scpt/corrupt.lua +++ b/lib/mods/theme/scpt/corrupt.lua @@ -137,22 +137,6 @@ CORRUPT_RANDOM_TELEPORT = add_corruption " Randomly teleports you around", }, -- No oppose field, it will be automatically set when we declare the anti-telep corruption to oppose us - ["hooks"] = - { - [HOOK_PROCESS_WORLD] = function() - if rand_int(300) == 1 then - if magik(70) == TRUE then - if get_check("Teleport?") == TRUE then - teleport_player(50) - end - else - disturb(0, 0) - msg_print("Your corruption takes over you, you teleport!") - teleport_player(50) - end - end - end, - }, } -- Anti-teleportation corruption, can be stopped with this power @@ -170,22 +154,6 @@ CORRUPT_ANTI_TELEPORT = add_corruption { [CORRUPT_RANDOM_TELEPORT] = TRUE }, - ["hooks"] = - { - [HOOK_PROCESS_WORLD] = function() - if player.corrupt_anti_teleport_stopped == TRUE then - local amt = player.msp + player.csp - amt = amt / 100 - if (amt < 1) then amt = 1 end - increase_mana(-amt) - if player.csp == 0 then - player.corrupt_anti_teleport_stopped = FALSE - msg_print("You stop controlling your corruption.") - player.update = bor(player.update, PU_BONUS) - end - end - end, - }, } diff --git a/lib/scpt/corrupt.lua b/lib/scpt/corrupt.lua index b9cae0b1..81690879 100644 --- a/lib/scpt/corrupt.lua +++ b/lib/scpt/corrupt.lua @@ -136,22 +136,6 @@ CORRUPT_RANDOM_TELEPORT = add_corruption " Randomly teleports you around", }, -- No oppose field, it will be automatically set when we declare the anti-telep corruption to oppose us - ["hooks"] = - { - [HOOK_PROCESS_WORLD] = function() - if rand_int(300) == 1 then - if magik(70) == TRUE then - if get_check("Teleport?") == TRUE then - teleport_player(50) - end - else - disturb(0, 0) - msg_print("Your corruption takes over you, you teleport!") - teleport_player(50) - end - end - end, - }, } -- Anti-teleportation corruption, can be stopped with this power @@ -169,22 +153,6 @@ CORRUPT_ANTI_TELEPORT = add_corruption { [CORRUPT_RANDOM_TELEPORT] = TRUE }, - ["hooks"] = - { - [HOOK_PROCESS_WORLD] = function() - if player.corrupt_anti_teleport_stopped == TRUE then - local amt = player.msp + player.csp - amt = amt / 100 - if (amt < 1) then amt = 1 end - increase_mana(-amt) - if player.csp == 0 then - player.corrupt_anti_teleport_stopped = FALSE - msg_print("You stop controlling your corruption.") - player.update = bor(player.update, PU_BONUS) - end - end - end, - }, } diff --git a/src/dungeon.c b/src/dungeon.c index 9b384dce..bcd727ca 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -1015,6 +1015,52 @@ void apply_effect(int y, int x) bool_ is_recall = FALSE; +/* + * Hook for corruptions + */ +static void process_world_corruptions() +{ + if (player_has_corruption(CORRUPT_RANDOM_TELEPORT)) + { + if (rand_int(300) == 1) + { + if (magik(70)) + { + if (get_check("Teleport?")) + { + teleport_player(50); + } + else + { + disturb(0, 0); + msg_print("Your corruption takes over you, you teleport!"); + teleport_player(50); + } + } + } + } + + if (player_has_corruption(CORRUPT_ANTI_TELEPORT)) + { + if (p_ptr->corrupt_anti_teleport_stopped) + { + int amt = p_ptr->msp + p_ptr->csp; + amt = amt / 100; + if (amt < 1) { + amt = 1; + } + increase_mana(-amt); + if (p_ptr->csp == 0) + { + p_ptr->corrupt_anti_teleport_stopped = FALSE; + msg_print("You stop controlling your corruption."); + p_ptr->update = p_ptr->update | PU_BONUS; + } + } + } +} + + /* * Handle certain things once every 10 game turns * @@ -1061,6 +1107,9 @@ static void process_world(void) /* Let the script live! */ process_hooks(HOOK_PROCESS_WORLD, "()"); + /* Handle corruptions */ + process_world_corruptions(); + /* Handle the player song */ check_music(); } diff --git a/src/externs.h b/src/externs.h index 3a0d8191..28386ef7 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1880,6 +1880,8 @@ extern cptr approximate_distance(int y, int x, int y2, int x2); extern bool_ drop_text_left(byte c, cptr s, int y, int o); extern bool_ drop_text_right(byte c, cptr s, int y, int o); +extern void increase_mana(int delta); + /* q_library.c */ extern void library_quest_fill_book(); extern int library_quest_book_slots_left(); diff --git a/src/lua_bind.c b/src/lua_bind.c index e9eb95a0..b83fc190 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -854,3 +854,10 @@ bool_ drop_text_right(byte c, cptr str, int y, int o) } return FALSE; } + +void increase_mana(int delta) +{ + char buf[256]; + sprintf(buf, "increase_mana(%d)", delta); + exec_lua(buf); +} -- cgit v1.2.3 From bf358f4520ea47059e02237892955edaa24c8be9 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 6 Apr 2012 16:28:21 +0200 Subject: Lua: Remove unused switch_class and switch_subclass --- src/externs.h | 2 -- src/player.pkg | 16 ---------------- src/xtra2.c | 18 ------------------ 3 files changed, 36 deletions(-) diff --git a/src/externs.h b/src/externs.h index 28386ef7..0a66e6a5 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1583,8 +1583,6 @@ extern void do_rebirth(void); extern cptr get_subrace_title(int racem); extern void set_subrace_title(int racem, cptr name); extern void switch_subrace(int racem, bool_ copy_old); -extern void switch_class(int sclass); -extern void switch_subclass(int sclass); extern void drop_from_wild(void); extern void clean_wish_name(char *buf, char *name); extern bool_ test_object_wish(char *name, object_type *o_ptr, object_type *forge, char *what); diff --git a/src/player.pkg b/src/player.pkg index 080d40a9..fad6d129 100644 --- a/src/player.pkg +++ b/src/player.pkg @@ -3461,22 +3461,6 @@ extern void do_cmd_throw(void); */ extern void change_wild_mode(); -/** @fn switch_class(int sclass) - * @brief Change to an other class.\n - * @param sclass Number \n the inex of the new class in the class array - * @brief Class index - * @note (see file xtra2.c) - */ -extern void switch_class(int sclass); - -/** @fn switch_subclass(int sclass) - * @brief Change to an other subclass.\n - * @param sclass Number \n the new subclass - * @brief Subclass - * @note (see file xtra2.c) - */ -extern void switch_subclass(int sclass); - /** @fn switch_subrace(int racem, bool copy_old) * @brief Change to an other subrace.\n * @param racem Number \n index of subrace in subrace array diff --git a/src/xtra2.c b/src/xtra2.c index 45a0caec..34a2a283 100644 --- a/src/xtra2.c +++ b/src/xtra2.c @@ -6065,24 +6065,6 @@ void corrupt_corrupted(void) return; } -/* - * Change to an other class - */ -void switch_class(int sclass) -{ - p_ptr->pclass = sclass; - cp_ptr = &class_info[p_ptr->pclass]; -} - -/* - * Change to an other subclass - */ -void switch_subclass(int sclass) -{ - p_ptr->pspec = sclass; - spp_ptr = &class_info[p_ptr->pclass].spec[p_ptr->pspec]; -} - /* * Change to an other subrace */ -- cgit v1.2.3 From 893ab1125bb3d25c184750aa146d3d6f5d82aa10 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 6 Apr 2012 16:00:55 +0200 Subject: Lua: Refactor vampire corruption logic to C --- lib/core/player.lua | 10 ------ lib/mods/theme/core/player.lua | 10 ------ lib/mods/theme/scpt/corrupt.lua | 50 ++------------------------ lib/scpt/corrupt.lua | 50 ++------------------------ src/externs.h | 3 ++ src/lua_bind.c | 78 +++++++++++++++++++++++++++++++++++++++++ src/player.pkg | 42 ++-------------------- 7 files changed, 90 insertions(+), 153 deletions(-) diff --git a/lib/core/player.lua b/lib/core/player.lua index 16878228..03e9824f 100644 --- a/lib/core/player.lua +++ b/lib/core/player.lua @@ -123,13 +123,3 @@ add_hook_script(HOOK_MKEY, "__mkey_fct_activate", "__mkey_fct_activate") function subrace(racem) return race_mod_info[racem + 1] end - -function subrace_add_power(subrace, power) - for i = 1, 4 do - if subrace.powers[i] == -1 then - subrace.powers[i] = power - return not nil - end - end - return nil -end diff --git a/lib/mods/theme/core/player.lua b/lib/mods/theme/core/player.lua index 16878228..03e9824f 100644 --- a/lib/mods/theme/core/player.lua +++ b/lib/mods/theme/core/player.lua @@ -123,13 +123,3 @@ add_hook_script(HOOK_MKEY, "__mkey_fct_activate", "__mkey_fct_activate") function subrace(racem) return race_mod_info[racem + 1] end - -function subrace_add_power(subrace, power) - for i = 1, 4 do - if subrace.powers[i] == -1 then - subrace.powers[i] = power - return not nil - end - end - return nil -end diff --git a/lib/mods/theme/scpt/corrupt.lua b/lib/mods/theme/scpt/corrupt.lua index 2f3d30ce..1bb976df 100644 --- a/lib/mods/theme/scpt/corrupt.lua +++ b/lib/mods/theme/scpt/corrupt.lua @@ -189,15 +189,7 @@ CORRUPT_VAMPIRE_TEETH = add_corruption ["allow"] = function() if test_race_flags(1, PR1_NO_SUBRACE_CHANGE) == FALSE then return not nil else return nil end end, - ["gain"] = function() - switch_subrace(SUBRACE_SAVE, TRUE); - - subrace_add_power(subrace(SUBRACE_SAVE), PWR_VAMPIRISM) - subrace(SUBRACE_SAVE).flags1 = bor(subrace(SUBRACE_SAVE).flags1, PR1_VAMPIRE, PR1_UNDEAD, PR1_NO_SUBRACE_CHANGE) - end, - ["hooks"] = - { - }, + ["gain"] = function() player_gain_vampire_teeth() end, } CORRUPT_VAMPIRE_STRENGTH = add_corruption { @@ -217,25 +209,7 @@ CORRUPT_VAMPIRE_STRENGTH = add_corruption { [CORRUPT_VAMPIRE_TEETH] = TRUE, }, - ["gain"] = function() - -- Apply the bonuses/penalities - subrace(SUBRACE_SAVE).r_mhp = subrace(SUBRACE_SAVE).r_mhp + 1 - subrace(SUBRACE_SAVE).r_exp = subrace(SUBRACE_SAVE).r_exp + 100 - - subrace(SUBRACE_SAVE).r_adj[A_STR + 1] = subrace(SUBRACE_SAVE).r_adj[A_STR + 1] + 3 - subrace(SUBRACE_SAVE).r_adj[A_INT + 1] = subrace(SUBRACE_SAVE).r_adj[A_INT + 1] + 2 - subrace(SUBRACE_SAVE).r_adj[A_WIS + 1] = subrace(SUBRACE_SAVE).r_adj[A_WIS + 1] - 3 - subrace(SUBRACE_SAVE).r_adj[A_DEX + 1] = subrace(SUBRACE_SAVE).r_adj[A_DEX + 1] - 2 - subrace(SUBRACE_SAVE).r_adj[A_CON + 1] = subrace(SUBRACE_SAVE).r_adj[A_CON + 1] + 1 - subrace(SUBRACE_SAVE).r_adj[A_CHR + 1] = subrace(SUBRACE_SAVE).r_adj[A_CHR + 1] - 4 - - -- be reborn! - do_rebirth() - cmsg_print(TERM_L_DARK, "You feel death slipping inside.") - end, - ["hooks"] = - { - }, + ["gain"] = function() player_gain_vampire_strength() end, } CORRUPT_VAMPIRE_VAMPIRE = add_corruption { @@ -254,25 +228,7 @@ CORRUPT_VAMPIRE_VAMPIRE = add_corruption { [CORRUPT_VAMPIRE_STRENGTH] = TRUE, }, - ["gain"] = function() - -- Be a Vampire and be proud of it - local title = get_subrace_title(SUBRACE_SAVE) - if title == " " or title == "Vampire" then - title = "Vampire" - subrace(SUBRACE_SAVE).place = FALSE - else - title = "Vampire "..title - end - set_subrace_title(SUBRACE_SAVE, title) - - -- Bonus/and .. not bonus :) - subrace(SUBRACE_SAVE).flags1 = bor(subrace(SUBRACE_SAVE).flags1, PR1_HURT_LITE) - subrace(SUBRACE_SAVE).oflags2[2] = bor(subrace(SUBRACE_SAVE).oflags2[2], TR2_RES_POIS, TR2_RES_NETHER, TR2_RES_COLD, TR2_RES_DARK, TR2_HOLD_LIFE) - subrace(SUBRACE_SAVE).oflags3[2] = bor(subrace(SUBRACE_SAVE).oflags3[2], TR3_LITE1) - end, - ["hooks"] = - { - }, + ["gain"] = function() player_gain_vampire() end, } -- The old activable corruptions / mutations diff --git a/lib/scpt/corrupt.lua b/lib/scpt/corrupt.lua index 81690879..27746cc9 100644 --- a/lib/scpt/corrupt.lua +++ b/lib/scpt/corrupt.lua @@ -188,15 +188,7 @@ CORRUPT_VAMPIRE_TEETH = add_corruption ["allow"] = function() if test_race_flags(1, PR1_NO_SUBRACE_CHANGE) == FALSE then return not nil else return nil end end, - ["gain"] = function() - switch_subrace(SUBRACE_SAVE, TRUE); - - subrace_add_power(subrace(SUBRACE_SAVE), PWR_VAMPIRISM) - subrace(SUBRACE_SAVE).flags1 = bor(subrace(SUBRACE_SAVE).flags1, PR1_VAMPIRE, PR1_UNDEAD, PR1_NO_SUBRACE_CHANGE) - end, - ["hooks"] = - { - }, + ["gain"] = function() player_gain_vampire_teeth() end, } CORRUPT_VAMPIRE_STRENGTH = add_corruption { @@ -216,25 +208,7 @@ CORRUPT_VAMPIRE_STRENGTH = add_corruption { [CORRUPT_VAMPIRE_TEETH] = TRUE, }, - ["gain"] = function() - -- Apply the bonuses/penalities - subrace(SUBRACE_SAVE).r_mhp = subrace(SUBRACE_SAVE).r_mhp + 1 - subrace(SUBRACE_SAVE).r_exp = subrace(SUBRACE_SAVE).r_exp + 100 - - subrace(SUBRACE_SAVE).r_adj[A_STR + 1] = subrace(SUBRACE_SAVE).r_adj[A_STR + 1] + 3 - subrace(SUBRACE_SAVE).r_adj[A_INT + 1] = subrace(SUBRACE_SAVE).r_adj[A_INT + 1] + 2 - subrace(SUBRACE_SAVE).r_adj[A_WIS + 1] = subrace(SUBRACE_SAVE).r_adj[A_WIS + 1] - 3 - subrace(SUBRACE_SAVE).r_adj[A_DEX + 1] = subrace(SUBRACE_SAVE).r_adj[A_DEX + 1] - 2 - subrace(SUBRACE_SAVE).r_adj[A_CON + 1] = subrace(SUBRACE_SAVE).r_adj[A_CON + 1] + 1 - subrace(SUBRACE_SAVE).r_adj[A_CHR + 1] = subrace(SUBRACE_SAVE).r_adj[A_CHR + 1] - 4 - - -- be reborn! - do_rebirth() - cmsg_print(TERM_L_DARK, "You feel death slipping inside.") - end, - ["hooks"] = - { - }, + ["gain"] = function() player_gain_vampire_strength() end, } CORRUPT_VAMPIRE_VAMPIRE = add_corruption { @@ -253,25 +227,7 @@ CORRUPT_VAMPIRE_VAMPIRE = add_corruption { [CORRUPT_VAMPIRE_STRENGTH] = TRUE, }, - ["gain"] = function() - -- Be a Vampire and be proud of it - local title = get_subrace_title(SUBRACE_SAVE) - if title == " " or title == "Vampire" then - title = "Vampire" - subrace(SUBRACE_SAVE).place = FALSE - else - title = "Vampire "..title - end - set_subrace_title(SUBRACE_SAVE, title) - - -- Bonus/and .. not bonus :) - subrace(SUBRACE_SAVE).flags1 = bor(subrace(SUBRACE_SAVE).flags1, PR1_HURT_LITE) - subrace(SUBRACE_SAVE).oflags2[2] = bor(subrace(SUBRACE_SAVE).oflags2[2], TR2_RES_POIS, TR2_RES_NETHER, TR2_RES_COLD, TR2_RES_DARK, TR2_HOLD_LIFE) - subrace(SUBRACE_SAVE).oflags3[2] = bor(subrace(SUBRACE_SAVE).oflags3[2], TR3_LITE1) - end, - ["hooks"] = - { - }, + ["gain"] = function() player_gain_vampire() end, } diff --git a/src/externs.h b/src/externs.h index 0a66e6a5..38a91d9e 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1871,6 +1871,9 @@ extern void lua_display_list(int y, int x, int h, int w, cptr title, list_type * extern bool_ player_has_corruption(int corruption_idx); extern bool_ player_can_gain_corruption(int corruption_idx); +extern void player_gain_vampire_teeth(); +extern void player_gain_vampire_strength(); +extern void player_gain_vampire(); extern cptr compass(int y, int x, int y2, int x2); extern cptr approximate_distance(int y, int x, int y2, int x2); diff --git a/src/lua_bind.c b/src/lua_bind.c index b83fc190..ded66b21 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -643,6 +643,84 @@ bool_ player_can_gain_corruption(int corruption_idx) return allowed; } +static void subrace_add_power(player_race_mod *rmp_ptr, int power) +{ + int i; + + for (i=0; i<4; i++) + { + if (rmp_ptr->powers[i] == -1) + { + rmp_ptr->powers[i] = power; + return; + } + } +} + +void player_gain_vampire_teeth() +{ + player_race_mod *rmp_ptr = NULL; + + switch_subrace(SUBRACE_SAVE, TRUE); + + rmp_ptr = &race_mod_info[SUBRACE_SAVE]; + subrace_add_power(rmp_ptr, PWR_VAMPIRISM); + rmp_ptr->flags1 = rmp_ptr->flags1 + | PR1_VAMPIRE + | PR1_UNDEAD + | PR1_NO_SUBRACE_CHANGE; +} + +void player_gain_vampire_strength() +{ + player_race_mod *rmp_ptr = &race_mod_info[SUBRACE_SAVE]; + /* Apply the bonuses/penalities */ + rmp_ptr->r_mhp = rmp_ptr->r_mhp + 1; + rmp_ptr->r_exp = rmp_ptr->r_exp + 100; + + rmp_ptr->r_adj[A_STR + 1] = rmp_ptr->r_adj[A_STR + 1] + 3; + rmp_ptr->r_adj[A_INT + 1] = rmp_ptr->r_adj[A_INT + 1] + 2; + rmp_ptr->r_adj[A_WIS + 1] = rmp_ptr->r_adj[A_WIS + 1] - 3; + rmp_ptr->r_adj[A_DEX + 1] = rmp_ptr->r_adj[A_DEX + 1] - 2; + rmp_ptr->r_adj[A_CON + 1] = rmp_ptr->r_adj[A_CON + 1] + 1; + rmp_ptr->r_adj[A_CHR + 1] = rmp_ptr->r_adj[A_CHR + 1] - 4; + + /* be reborn! */ + do_rebirth(); + cmsg_print(TERM_L_DARK, "You feel death slipping inside."); +} + +void player_gain_vampire() +{ + player_race_mod *rmp_ptr = &race_mod_info[SUBRACE_SAVE]; + + /* Be a Vampire and be proud of it */ + cptr title = get_subrace_title(SUBRACE_SAVE); + if (streq(title, " ") || streq(title, "Vampire")) + { + title = "Vampire"; + rmp_ptr->place = FALSE; + set_subrace_title(SUBRACE_SAVE, title); + } + else + { + char buf[512]; + sprintf(buf, "Vampire %s", title); + set_subrace_title(SUBRACE_SAVE, buf); + } + + /* Bonus/and .. not bonus :) */ + rmp_ptr->flags1 = rmp_ptr->flags1 | PR1_HURT_LITE; + rmp_ptr->oflags2[2] = rmp_ptr->oflags2[2] + | TR2_RES_POIS + | TR2_RES_NETHER + | TR2_RES_COLD + | TR2_RES_DARK + | TR2_HOLD_LIFE; + rmp_ptr->oflags3[2] = rmp_ptr->oflags3[2] + | TR3_LITE1; +} + /* * Gods */ diff --git a/src/player.pkg b/src/player.pkg index fad6d129..5e693c9b 100644 --- a/src/player.pkg +++ b/src/player.pkg @@ -1854,6 +1854,9 @@ extern s16b MUT1_RESIST; extern s16b MUT1_EARTHQUAKE; extern bool player_can_gain_corruption(int corruption_idx); +extern void player_gain_vampire_teeth(); +extern void player_gain_vampire_strength(); +extern void player_gain_vampire(); /** @name Spellbinder triggers * @{ */ @@ -3461,45 +3464,6 @@ extern void do_cmd_throw(void); */ extern void change_wild_mode(); -/** @fn switch_subrace(int racem, bool copy_old) - * @brief Change to an other subrace.\n - * @param racem Number \n index of subrace in subrace array - * @brief Subrace index - * @param copy_old Boolean \n TRUE if the new subrace is to be saved, - * otherwise FALSE. - * @brief Copy old subrace? - * @note (see file xtra2.c) - */ -extern void switch_subrace(int racem, bool copy_old); - -/** @fn get_subrace_title(int racem) - * @brief Return the subrace title.\n - * @param racem Number \n index of subrace in subrace array - * @brief Subrace index - * @return String \n Title of subrace. - * @note (see file xtra2.c) - */ -extern cptr get_subrace_title(int racem); - -/** @fn set_subrace_title(int racem, cptr name) - * @brief Set the subrace title.\n - * @param racem Number \n index of subrace in subrace array - * @brief Subrace index - * @param name String \n new title of subrace - * @brief New title - * @note (see file xtra2.c) - */ -extern void set_subrace_title(int racem, cptr name); - -/** @fn do_rebirth() - * @brief The player is reborn after a class, race, or subrace change. - * @note - * The experience factor is recalculated. The hit dice are reset and new HP - * are calculated. There may be a level change involved. - * @note (see file xtra2.c) - */ -extern void do_rebirth(); - /* Player race flags */ $static bool lua_test_race_flags(int slot, u32b flags) { if (slot == 1) return (PRACE_FLAG(flags)) ? TRUE : FALSE; else return (PRACE_FLAG2(flags)) ? TRUE : FALSE; } /** @fn test_race_flags(int slot, u32b flags); -- cgit v1.2.3 From 818696e7d00a0f504f9e147ee691164ae391e0bb Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 6 Apr 2012 18:31:10 +0200 Subject: Lua: Remove dead Lua code dealing with corruption hooks --- lib/core/crpt_aux.lua | 16 +--------------- lib/mods/theme/core/crpt_aux.lua | 16 +--------------- lib/mods/theme/scpt/corrupt.lua | 3 --- lib/scpt/corrupt.lua | 3 --- 4 files changed, 2 insertions(+), 36 deletions(-) diff --git a/lib/core/crpt_aux.lua b/lib/core/crpt_aux.lua index 85cddbf3..7703a815 100644 --- a/lib/core/crpt_aux.lua +++ b/lib/core/crpt_aux.lua @@ -149,23 +149,9 @@ function add_corruption(c) __corruptions[o].oppose[__corruptions_max] = TRUE end - local index, h - if type(c.hooks) == "table" then - for index, h in c.hooks do - add_hook_script(index, "__lua__corrupt_callback"..__corruptions_callbacks_max, "__lua__corrupt_callback"..__corruptions_callbacks_max) - setglobal("__lua__corrupt_callback"..__corruptions_callbacks_max, - function (...) - if test_depend_corrupt(%__corruptions_max) == TRUE then - return call(%h, arg) - end - end - ) - __corruptions_callbacks_max = __corruptions_callbacks_max + 1 - end - end - if type(c.desc) == "table" then local new_desc = "" + local index, h for index, h in c.desc do new_desc = new_desc..h.."\n" end diff --git a/lib/mods/theme/core/crpt_aux.lua b/lib/mods/theme/core/crpt_aux.lua index 85cddbf3..7703a815 100644 --- a/lib/mods/theme/core/crpt_aux.lua +++ b/lib/mods/theme/core/crpt_aux.lua @@ -149,23 +149,9 @@ function add_corruption(c) __corruptions[o].oppose[__corruptions_max] = TRUE end - local index, h - if type(c.hooks) == "table" then - for index, h in c.hooks do - add_hook_script(index, "__lua__corrupt_callback"..__corruptions_callbacks_max, "__lua__corrupt_callback"..__corruptions_callbacks_max) - setglobal("__lua__corrupt_callback"..__corruptions_callbacks_max, - function (...) - if test_depend_corrupt(%__corruptions_max) == TRUE then - return call(%h, arg) - end - end - ) - __corruptions_callbacks_max = __corruptions_callbacks_max + 1 - end - end - if type(c.desc) == "table" then local new_desc = "" + local index, h for index, h in c.desc do new_desc = new_desc..h.."\n" end diff --git a/lib/mods/theme/scpt/corrupt.lua b/lib/mods/theme/scpt/corrupt.lua index 1bb976df..f1d83c26 100644 --- a/lib/mods/theme/scpt/corrupt.lua +++ b/lib/mods/theme/scpt/corrupt.lua @@ -525,8 +525,5 @@ CORRUPT_ = add_corruption { " ", }, - ["hooks"] = - { - }, } ]] diff --git a/lib/scpt/corrupt.lua b/lib/scpt/corrupt.lua index 27746cc9..a1bc98a4 100644 --- a/lib/scpt/corrupt.lua +++ b/lib/scpt/corrupt.lua @@ -242,8 +242,5 @@ CORRUPT_ = add_corruption { " ", }, - ["hooks"] = - { - }, } ]] -- cgit v1.2.3 From 1de4221b9e906ce8324237943165c161f78b5e07 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 6 Apr 2012 18:34:59 +0200 Subject: Lua: Remove unused lose_all_corruptions() --- lib/core/crpt_aux.lua | 9 --------- lib/mods/theme/core/crpt_aux.lua | 9 --------- src/externs.h | 1 - src/xtra2.c | 6 ------ 4 files changed, 25 deletions(-) diff --git a/lib/core/crpt_aux.lua b/lib/core/crpt_aux.lua index 7703a815..369cf5d1 100644 --- a/lib/core/crpt_aux.lua +++ b/lib/core/crpt_aux.lua @@ -120,15 +120,6 @@ function lose_corruption() end end --- Lose all corruptions (for e.g. Potion of New Life) -function lose_all_corruptions() - local i; - for i = 0, __corruptions_max - 1 do - lose_corruption() - end - return -1 -end - -- Creates a new corruption function add_corruption(c) assert(c.color, "No corruption color") diff --git a/lib/mods/theme/core/crpt_aux.lua b/lib/mods/theme/core/crpt_aux.lua index 7703a815..369cf5d1 100644 --- a/lib/mods/theme/core/crpt_aux.lua +++ b/lib/mods/theme/core/crpt_aux.lua @@ -120,15 +120,6 @@ function lose_corruption() end end --- Lose all corruptions (for e.g. Potion of New Life) -function lose_all_corruptions() - local i; - for i = 0, __corruptions_max - 1 do - lose_corruption() - end - return -1 -end - -- Creates a new corruption function add_corruption(c) assert(c.color, "No corruption color") diff --git a/src/externs.h b/src/externs.h index 38a91d9e..579ed463 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1679,7 +1679,6 @@ extern bool_ curse_weapon(void); extern bool_ curse_armor(void); extern void random_resistance(object_type * q_ptr, bool_ is_scroll, int specific); extern bool_ lose_corruption(int choose_mut); -extern bool_ lose_all_corruptions(void); extern void great_side_effect(void); extern void nasty_side_effect(void); extern void deadly_side_effect(bool_ god); diff --git a/src/xtra2.c b/src/xtra2.c index 34a2a283..1a6ec3a0 100644 --- a/src/xtra2.c +++ b/src/xtra2.c @@ -5613,12 +5613,6 @@ bool_ lose_corruption(int choose_mut) return (FALSE); } -bool_ lose_all_corruptions(void) -{ - exec_lua("lose_all_corruptions()"); - return (FALSE); -} - bool_ get_hack_dir(int *dp) { int dir; -- cgit v1.2.3 From 41b6617e992d3fedda4c0a93ddd0fa4ad834a2ae Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 6 Apr 2012 19:24:21 +0200 Subject: Lua: Refactor the "set" part of player.corruption() to C --- lib/core/crpt_aux.lua | 22 +++++----------------- lib/mods/theme/core/crpt_aux.lua | 22 +++++----------------- lib/mods/theme/scpt/corrupt.lua | 3 --- lib/mods/theme/scpt/player.lua | 6 +++--- lib/scpt/corrupt.lua | 3 --- lib/scpt/player.lua | 6 +++--- src/externs.h | 5 ++--- src/lua_bind.c | 39 ++++++++++++++++++++++++++++++++++++--- src/player.pkg | 5 ++--- 9 files changed, 56 insertions(+), 55 deletions(-) diff --git a/lib/core/crpt_aux.lua b/lib/core/crpt_aux.lua index 369cf5d1..24b71860 100644 --- a/lib/core/crpt_aux.lua +++ b/lib/core/crpt_aux.lua @@ -5,20 +5,8 @@ __corruptions_max = 0 __corruptions_callbacks_max = 0 -- Get the corruption -function player.corruption(c, set) - if set then - player.corruptions_aux[c + 1] = set - player.redraw = bor(player.redraw, PR_BASIC) - player.update = bor(player.update, PU_BONUS, PU_TORCH, PU_BODY, PU_POWERS) - if (set == TRUE) and (__corruptions[c].gain) then - __corruptions[c].gain() - end - if (set == FALSE) and (__corruptions[c].lose) then - __corruptions[c].lose() - end - else - return player.corruptions_aux[c + 1] - end +function player.corruption(c) + return player.corruptions_aux[c + 1] end -- Test if we have that corruption @@ -76,7 +64,7 @@ function gain_corruption(group) if (max > 0) then local ret = rand_int(max) - player.corruption(pos[ret], TRUE) + player_gain_corruption(pos[ret]) cmsg_print(TERM_L_RED, __corruptions[pos[ret]].get_text) return pos[ret] @@ -103,13 +91,13 @@ function lose_corruption() if (max > 0) then local ret = rand_int(max) - player.corruption(pos[ret], FALSE) + player_lose_corruption(pos[ret]) cmsg_print(TERM_L_RED, __corruptions[pos[ret]].lose_text) -- Ok now lets see if it broke some dependancies for i = 0, max - 1 do if player.corruption(pos[i]) ~= test_depend_corrupt(pos[i]) then - player.corruption(pos[i], FALSE) + player_lose_corruption(pos[i]) cmsg_print(TERM_L_RED, __corruptions[pos[i]].lose_text) end end diff --git a/lib/mods/theme/core/crpt_aux.lua b/lib/mods/theme/core/crpt_aux.lua index 369cf5d1..24b71860 100644 --- a/lib/mods/theme/core/crpt_aux.lua +++ b/lib/mods/theme/core/crpt_aux.lua @@ -5,20 +5,8 @@ __corruptions_max = 0 __corruptions_callbacks_max = 0 -- Get the corruption -function player.corruption(c, set) - if set then - player.corruptions_aux[c + 1] = set - player.redraw = bor(player.redraw, PR_BASIC) - player.update = bor(player.update, PU_BONUS, PU_TORCH, PU_BODY, PU_POWERS) - if (set == TRUE) and (__corruptions[c].gain) then - __corruptions[c].gain() - end - if (set == FALSE) and (__corruptions[c].lose) then - __corruptions[c].lose() - end - else - return player.corruptions_aux[c + 1] - end +function player.corruption(c) + return player.corruptions_aux[c + 1] end -- Test if we have that corruption @@ -76,7 +64,7 @@ function gain_corruption(group) if (max > 0) then local ret = rand_int(max) - player.corruption(pos[ret], TRUE) + player_gain_corruption(pos[ret]) cmsg_print(TERM_L_RED, __corruptions[pos[ret]].get_text) return pos[ret] @@ -103,13 +91,13 @@ function lose_corruption() if (max > 0) then local ret = rand_int(max) - player.corruption(pos[ret], FALSE) + player_lose_corruption(pos[ret]) cmsg_print(TERM_L_RED, __corruptions[pos[ret]].lose_text) -- Ok now lets see if it broke some dependancies for i = 0, max - 1 do if player.corruption(pos[i]) ~= test_depend_corrupt(pos[i]) then - player.corruption(pos[i], FALSE) + player_lose_corruption(pos[i]) cmsg_print(TERM_L_RED, __corruptions[pos[i]].lose_text) end end diff --git a/lib/mods/theme/scpt/corrupt.lua b/lib/mods/theme/scpt/corrupt.lua index f1d83c26..e303803b 100644 --- a/lib/mods/theme/scpt/corrupt.lua +++ b/lib/mods/theme/scpt/corrupt.lua @@ -189,7 +189,6 @@ CORRUPT_VAMPIRE_TEETH = add_corruption ["allow"] = function() if test_race_flags(1, PR1_NO_SUBRACE_CHANGE) == FALSE then return not nil else return nil end end, - ["gain"] = function() player_gain_vampire_teeth() end, } CORRUPT_VAMPIRE_STRENGTH = add_corruption { @@ -209,7 +208,6 @@ CORRUPT_VAMPIRE_STRENGTH = add_corruption { [CORRUPT_VAMPIRE_TEETH] = TRUE, }, - ["gain"] = function() player_gain_vampire_strength() end, } CORRUPT_VAMPIRE_VAMPIRE = add_corruption { @@ -228,7 +226,6 @@ CORRUPT_VAMPIRE_VAMPIRE = add_corruption { [CORRUPT_VAMPIRE_STRENGTH] = TRUE, }, - ["gain"] = function() player_gain_vampire() end, } -- The old activable corruptions / mutations diff --git a/lib/mods/theme/scpt/player.lua b/lib/mods/theme/scpt/player.lua index de04052d..0e9faff6 100644 --- a/lib/mods/theme/scpt/player.lua +++ b/lib/mods/theme/scpt/player.lua @@ -8,9 +8,9 @@ function __birth_hook_objects() -- Start the undeads, as undeads with the corruptions if get_subrace_name() == "Vampire" then - player.corruption(CORRUPT_VAMPIRE_TEETH, TRUE) - player.corruption(CORRUPT_VAMPIRE_STRENGTH, TRUE) - player.corruption(CORRUPT_VAMPIRE_VAMPIRE, TRUE) + player_gain_corruption(CORRUPT_VAMPIRE_TEETH) + player_gain_corruption(CORRUPT_VAMPIRE_STRENGTH) + player_gain_corruption(CORRUPT_VAMPIRE_VAMPIRE) end end diff --git a/lib/scpt/corrupt.lua b/lib/scpt/corrupt.lua index a1bc98a4..19957668 100644 --- a/lib/scpt/corrupt.lua +++ b/lib/scpt/corrupt.lua @@ -188,7 +188,6 @@ CORRUPT_VAMPIRE_TEETH = add_corruption ["allow"] = function() if test_race_flags(1, PR1_NO_SUBRACE_CHANGE) == FALSE then return not nil else return nil end end, - ["gain"] = function() player_gain_vampire_teeth() end, } CORRUPT_VAMPIRE_STRENGTH = add_corruption { @@ -208,7 +207,6 @@ CORRUPT_VAMPIRE_STRENGTH = add_corruption { [CORRUPT_VAMPIRE_TEETH] = TRUE, }, - ["gain"] = function() player_gain_vampire_strength() end, } CORRUPT_VAMPIRE_VAMPIRE = add_corruption { @@ -227,7 +225,6 @@ CORRUPT_VAMPIRE_VAMPIRE = add_corruption { [CORRUPT_VAMPIRE_STRENGTH] = TRUE, }, - ["gain"] = function() player_gain_vampire() end, } diff --git a/lib/scpt/player.lua b/lib/scpt/player.lua index e8fb7e25..1c8da791 100644 --- a/lib/scpt/player.lua +++ b/lib/scpt/player.lua @@ -5,9 +5,9 @@ function __birth_hook_objects() -- Start the undeads, as undeads with the corruptions if get_subrace_name() == "Vampire" then - player.corruption(CORRUPT_VAMPIRE_TEETH, TRUE) - player.corruption(CORRUPT_VAMPIRE_STRENGTH, TRUE) - player.corruption(CORRUPT_VAMPIRE_VAMPIRE, TRUE) + player_gain_corruption(CORRUPT_VAMPIRE_TEETH) + player_gain_corruption(CORRUPT_VAMPIRE_STRENGTH) + player_gain_corruption(CORRUPT_VAMPIRE_VAMPIRE) end end diff --git a/src/externs.h b/src/externs.h index 579ed463..3f48098c 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1870,9 +1870,8 @@ extern void lua_display_list(int y, int x, int h, int w, cptr title, list_type * extern bool_ player_has_corruption(int corruption_idx); extern bool_ player_can_gain_corruption(int corruption_idx); -extern void player_gain_vampire_teeth(); -extern void player_gain_vampire_strength(); -extern void player_gain_vampire(); +extern void player_gain_corruption(int corruption_idx); +extern void player_lose_corruption(int corruption_idx); extern cptr compass(int y, int x, int y2, int x2); extern cptr approximate_distance(int y, int x, int y2, int x2); diff --git a/src/lua_bind.c b/src/lua_bind.c index ded66b21..1add61e3 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -657,7 +657,7 @@ static void subrace_add_power(player_race_mod *rmp_ptr, int power) } } -void player_gain_vampire_teeth() +static void player_gain_vampire_teeth() { player_race_mod *rmp_ptr = NULL; @@ -671,7 +671,7 @@ void player_gain_vampire_teeth() | PR1_NO_SUBRACE_CHANGE; } -void player_gain_vampire_strength() +static void player_gain_vampire_strength() { player_race_mod *rmp_ptr = &race_mod_info[SUBRACE_SAVE]; /* Apply the bonuses/penalities */ @@ -690,7 +690,7 @@ void player_gain_vampire_strength() cmsg_print(TERM_L_DARK, "You feel death slipping inside."); } -void player_gain_vampire() +static void player_gain_vampire() { player_race_mod *rmp_ptr = &race_mod_info[SUBRACE_SAVE]; @@ -721,6 +721,39 @@ void player_gain_vampire() | TR3_LITE1; } +static void player_set_corruption(int c, bool_ set) +{ + p_ptr->corruptions[c] = set; + p_ptr->redraw = p_ptr->redraw | PR_BASIC; + p_ptr->update = p_ptr->update | PU_BONUS | PU_TORCH | PU_BODY | PU_POWERS; + +} + +void player_gain_corruption(int corruption_idx) +{ + player_set_corruption(corruption_idx, TRUE); + + if (corruption_idx == CORRUPT_VAMPIRE_TEETH) + { + player_gain_vampire_teeth(); + } + else if (corruption_idx == CORRUPT_VAMPIRE_STRENGTH) + { + player_gain_vampire_strength(); + } + else if (corruption_idx == CORRUPT_VAMPIRE_VAMPIRE) + { + player_gain_vampire(); + } +} + +void player_lose_corruption(int corruption_idx) +{ + player_set_corruption(corruption_idx, FALSE); + /* Currently no corruptions need + any special handling when lost */ +} + /* * Gods */ diff --git a/src/player.pkg b/src/player.pkg index 5e693c9b..ad01e9eb 100644 --- a/src/player.pkg +++ b/src/player.pkg @@ -1854,9 +1854,8 @@ extern s16b MUT1_RESIST; extern s16b MUT1_EARTHQUAKE; extern bool player_can_gain_corruption(int corruption_idx); -extern void player_gain_vampire_teeth(); -extern void player_gain_vampire_strength(); -extern void player_gain_vampire(); +extern void player_gain_corruption(int corruption_idx); +extern void player_lose_corruption(int corruption_idx); /** @name Spellbinder triggers * @{ */ -- cgit v1.2.3 From a01f15e08da3b2e0e326b2a94100e17962136741 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 7 Apr 2012 14:50:36 +0200 Subject: Lua: Refactor all the corruption code into C --- lib/core/crpt_aux.lua | 144 ------ lib/core/init.lua | 1 - lib/mods/theme/core/crpt_aux.lua | 144 ------ lib/mods/theme/core/init.lua | 1 - lib/mods/theme/scpt/corrupt.lua | 526 ---------------------- lib/mods/theme/scpt/init.lua | 3 - lib/mods/theme/scpt/monsters.lua | 8 +- lib/scpt/corrupt.lua | 243 ----------- lib/scpt/init.lua | 3 - src/CMakeLists.txt | 2 +- src/birth.c | 6 - src/cmd4.c | 5 +- src/cmd5.c | 2 +- src/cmd6.c | 4 +- src/corrupt.c | 916 +++++++++++++++++++++++++++++++++++++++ src/defines.h | 39 ++ src/externs.h | 53 +-- src/files.c | 6 +- src/init2.c | 8 +- src/loadsave.c | 9 +- src/lua_bind.c | 166 ------- src/melee1.c | 2 +- src/player.pkg | 78 ++-- src/script.c | 3 +- src/tables.c | 1 + src/types.h | 20 +- src/variable.c | 43 -- src/wizard2.c | 2 +- src/xtra2.c | 65 +-- 29 files changed, 1047 insertions(+), 1456 deletions(-) delete mode 100644 lib/core/crpt_aux.lua delete mode 100644 lib/mods/theme/core/crpt_aux.lua delete mode 100644 lib/mods/theme/scpt/corrupt.lua delete mode 100644 lib/scpt/corrupt.lua create mode 100644 src/corrupt.c diff --git a/lib/core/crpt_aux.lua b/lib/core/crpt_aux.lua deleted file mode 100644 index 24b71860..00000000 --- a/lib/core/crpt_aux.lua +++ /dev/null @@ -1,144 +0,0 @@ --- Core functions for corruptions - -__corruptions = {} -__corruptions_max = 0 -__corruptions_callbacks_max = 0 - --- Get the corruption -function player.corruption(c) - return player.corruptions_aux[c + 1] -end - --- Test if we have that corruption --- We must: --- 1) have it or be willing to get it --- 2) have all its dependancies --- 3) have none of its opposing corruptions --- 4) pass the possible tests -function test_depend_corrupt(corrupt, can_gain) - local i, c - - if not can_gain then can_gain = FALSE end - - if can_gain == TRUE then - if (player.corruption(corrupt) ~= FALSE) then - return FALSE - end - else - if (player.corruption(corrupt) ~= TRUE) then - return FALSE - end - end - - for c, i in __corruptions[corrupt].depends do - if test_depend_corrupt(c) ~= TRUE then - return FALSE - end - end - - for c, i in __corruptions[corrupt].oppose do - if test_depend_corrupt(c) ~= FALSE then - return FALSE - end - end - - -- are we even allowed to get it? - return player_can_gain_corruption(corrupt) -end - --- Gain a new corruption -function gain_corruption(group) - local i, max - local pos = {} - - -- Get the list of all possible ones - max = 0 - for i = 0, __corruptions_max - 1 do - if __corruptions[i].group == group and test_depend_corrupt(i, TRUE) == TRUE and __corruptions[i].random == TRUE and __corruptions[i].allow() then - pos[max] = i - max = max + 1 - end - end - - -- Ok now get one of them - if (max > 0) then - local ret = rand_int(max) - - player_gain_corruption(pos[ret]) - cmsg_print(TERM_L_RED, __corruptions[pos[ret]].get_text) - - return pos[ret] - else - return -1 - end -end - --- Lose an existing corruption -function lose_corruption() - local i, max - local pos = {} - - -- Get the list of all possible ones - max = 0 - for i = 0, __corruptions_max - 1 do - if test_depend_corrupt(i) == TRUE and __corruptions[i].removable == TRUE then - pos[max] = i - max = max + 1 - end - end - - -- Ok now get one of them - if (max > 0) then - local ret = rand_int(max) - - player_lose_corruption(pos[ret]) - cmsg_print(TERM_L_RED, __corruptions[pos[ret]].lose_text) - - -- Ok now lets see if it broke some dependancies - for i = 0, max - 1 do - if player.corruption(pos[i]) ~= test_depend_corrupt(pos[i]) then - player_lose_corruption(pos[i]) - cmsg_print(TERM_L_RED, __corruptions[pos[i]].lose_text) - end - end - - return pos[ret] - else - return -1 - end -end - --- Creates a new corruption -function add_corruption(c) - assert(c.color, "No corruption color") - assert(c.name, "No corruption name") - assert(c.get_text, "No corruption get_text") - assert(c.lose_text, "No corruption lose_text") - assert(c.desc, "No corruption desc") - if not c.random then c.random = TRUE end - if not c.removable then c.removable = TRUE end - if not c.allow then c.allow = function() return not nil end end - - if c.depends == nil then c.depends = {} end - if c.oppose == nil then c.oppose = {} end - - -- We must make sure the other ones opposes too - local o, i - for o, i in c.oppose do - __corruptions[o].oppose[__corruptions_max] = TRUE - end - - if type(c.desc) == "table" then - local new_desc = "" - local index, h - for index, h in c.desc do - new_desc = new_desc..h.."\n" - end - c.desc = new_desc - end - - __corruptions[__corruptions_max] = c - __corruptions_max = __corruptions_max + 1 - return (__corruptions_max - 1) -end - diff --git a/lib/core/init.lua b/lib/core/init.lua index 11b812d5..3db34076 100644 --- a/lib/core/init.lua +++ b/lib/core/init.lua @@ -17,7 +17,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "building.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "s_aux.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "crpt_aux.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "mimc_aux.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "quests.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "gods.lua") diff --git a/lib/mods/theme/core/crpt_aux.lua b/lib/mods/theme/core/crpt_aux.lua deleted file mode 100644 index 24b71860..00000000 --- a/lib/mods/theme/core/crpt_aux.lua +++ /dev/null @@ -1,144 +0,0 @@ --- Core functions for corruptions - -__corruptions = {} -__corruptions_max = 0 -__corruptions_callbacks_max = 0 - --- Get the corruption -function player.corruption(c) - return player.corruptions_aux[c + 1] -end - --- Test if we have that corruption --- We must: --- 1) have it or be willing to get it --- 2) have all its dependancies --- 3) have none of its opposing corruptions --- 4) pass the possible tests -function test_depend_corrupt(corrupt, can_gain) - local i, c - - if not can_gain then can_gain = FALSE end - - if can_gain == TRUE then - if (player.corruption(corrupt) ~= FALSE) then - return FALSE - end - else - if (player.corruption(corrupt) ~= TRUE) then - return FALSE - end - end - - for c, i in __corruptions[corrupt].depends do - if test_depend_corrupt(c) ~= TRUE then - return FALSE - end - end - - for c, i in __corruptions[corrupt].oppose do - if test_depend_corrupt(c) ~= FALSE then - return FALSE - end - end - - -- are we even allowed to get it? - return player_can_gain_corruption(corrupt) -end - --- Gain a new corruption -function gain_corruption(group) - local i, max - local pos = {} - - -- Get the list of all possible ones - max = 0 - for i = 0, __corruptions_max - 1 do - if __corruptions[i].group == group and test_depend_corrupt(i, TRUE) == TRUE and __corruptions[i].random == TRUE and __corruptions[i].allow() then - pos[max] = i - max = max + 1 - end - end - - -- Ok now get one of them - if (max > 0) then - local ret = rand_int(max) - - player_gain_corruption(pos[ret]) - cmsg_print(TERM_L_RED, __corruptions[pos[ret]].get_text) - - return pos[ret] - else - return -1 - end -end - --- Lose an existing corruption -function lose_corruption() - local i, max - local pos = {} - - -- Get the list of all possible ones - max = 0 - for i = 0, __corruptions_max - 1 do - if test_depend_corrupt(i) == TRUE and __corruptions[i].removable == TRUE then - pos[max] = i - max = max + 1 - end - end - - -- Ok now get one of them - if (max > 0) then - local ret = rand_int(max) - - player_lose_corruption(pos[ret]) - cmsg_print(TERM_L_RED, __corruptions[pos[ret]].lose_text) - - -- Ok now lets see if it broke some dependancies - for i = 0, max - 1 do - if player.corruption(pos[i]) ~= test_depend_corrupt(pos[i]) then - player_lose_corruption(pos[i]) - cmsg_print(TERM_L_RED, __corruptions[pos[i]].lose_text) - end - end - - return pos[ret] - else - return -1 - end -end - --- Creates a new corruption -function add_corruption(c) - assert(c.color, "No corruption color") - assert(c.name, "No corruption name") - assert(c.get_text, "No corruption get_text") - assert(c.lose_text, "No corruption lose_text") - assert(c.desc, "No corruption desc") - if not c.random then c.random = TRUE end - if not c.removable then c.removable = TRUE end - if not c.allow then c.allow = function() return not nil end end - - if c.depends == nil then c.depends = {} end - if c.oppose == nil then c.oppose = {} end - - -- We must make sure the other ones opposes too - local o, i - for o, i in c.oppose do - __corruptions[o].oppose[__corruptions_max] = TRUE - end - - if type(c.desc) == "table" then - local new_desc = "" - local index, h - for index, h in c.desc do - new_desc = new_desc..h.."\n" - end - c.desc = new_desc - end - - __corruptions[__corruptions_max] = c - __corruptions_max = __corruptions_max + 1 - return (__corruptions_max - 1) -end - diff --git a/lib/mods/theme/core/init.lua b/lib/mods/theme/core/init.lua index 11b812d5..3db34076 100644 --- a/lib/mods/theme/core/init.lua +++ b/lib/mods/theme/core/init.lua @@ -17,7 +17,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "building.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "s_aux.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "crpt_aux.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "mimc_aux.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "quests.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "gods.lua") diff --git a/lib/mods/theme/scpt/corrupt.lua b/lib/mods/theme/scpt/corrupt.lua deleted file mode 100644 index e303803b..00000000 --- a/lib/mods/theme/scpt/corrupt.lua +++ /dev/null @@ -1,526 +0,0 @@ --- Definition of the corruptions --- Theme adds the restriction T-Plus has for Maiar: they may only gain the Balrog corruptions. - --- The Balrog corruptions -CORRUPT_BALROG_AURA = add_corruption -{ - ["color"] = TERM_ORANGE, - ["name"] = "Balrog Aura", - ["get_text"] = "A corrupted wall of flames surrounds you.", - ["lose_text"] = "The wall of corrupted flames abandons you.", - ["desc"] = - { - " Surrounds you with a fiery aura", - " But it can burn scrolls when you read them" - }, -} - -CORRUPT_BALROG_WINGS = add_corruption -{ - ["color"] = TERM_ORANGE, - ["name"] = "Balrog Wings", - ["get_text"] = "Wings of shadow grow in your back.", - ["lose_text"] = "The wings in your back fall apart.", - ["desc"] = - { - " Creates ugly, but working, wings allowing you to fly", - " But it reduces charisma by 4 and dexterity by 2" - }, -} - -CORRUPT_BALROG_STRENGTH = add_corruption -{ - ["color"] = TERM_ORANGE, - ["name"] = "Balrog Strength", - ["get_text"] = "Your muscles get unnatural strength.", - ["lose_text"] = "Your muscles get weaker again.", - ["desc"] = - { - " Provides 3 strength and 1 constitution", - " But it reduces charisma by 1 and dexterity by 3" - }, -} - -CORRUPT_BALROG_FORM = add_corruption -{ - ["color"] = TERM_YELLOW, - ["name"] = "Balrog Form", - ["get_text"] = "You feel the might of a Balrog inside you.", - ["lose_text"] = "The presence of the Balrog seems to abandon you.", - ["desc"] = - { - " Allows you to turn into a Balrog at will", - " You need Balrog Wings, Balrog Aura and Balrog Strength to activate it" - }, - ["depends"] = - { - [CORRUPT_BALROG_AURA] = TRUE, - [CORRUPT_BALROG_WINGS] = TRUE, - [CORRUPT_BALROG_STRENGTH] = TRUE - }, -} - - --- The Demon corruptions -CORRUPT_DEMON_SPIRIT = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Demon Spirit", - ["get_text"] = "Your spirit opens to corrupted thoughts.", - ["lose_text"] = "Your spirit closes again to the corrupted thoughts.", - ["desc"] = - { - " Increases your intelligence by 1", - " But reduce your charisma by 2", - }, -} - -CORRUPT_DEMON_HIDE = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Demon Hide", - ["get_text"] = "Your skin grows into a thick hide.", - ["lose_text"] = "Your skin returns to a natural state.", - ["desc"] = - { - " Increases your armour class by your level", - " Provides immunity to fire at level 40", - " But reduces speed by your level / 7", - }, -} - -CORRUPT_DEMON_BREATH = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Demon Breath", - ["get_text"] = "Your breath becomes mephitic.", - ["lose_text"] = "Your breath is once again normal.", - ["desc"] = - { - " Provides fire breath", - " But gives a small chance to spoil potions when you quaff them", - }, -} - -CORRUPT_DEMON_REALM = add_corruption -{ - ["color"] = TERM_L_RED, - ["name"] = "Demon Realm", - ["get_text"] = "You feel more attuned to the demon realm.", - ["lose_text"] = "You lose your attunement to the demon realm.", - ["desc"] = - { - " Provides access to the demon school skill and the use of demonic equipment", - " You need Demon Spirit, Demon Hide and Demon Breath to activate it" - }, - ["depends"] = - { - [CORRUPT_DEMON_SPIRIT] = TRUE, - [CORRUPT_DEMON_HIDE] = TRUE, - [CORRUPT_DEMON_BREATH] = TRUE - }, -} - - --- Teleportation corruptions - --- Random teleportation will ask for confirmation 70% of the time --- But 30% of the time it will teleport, without asking -CORRUPT_RANDOM_TELEPORT = add_corruption -{ - ["color"] = TERM_GREEN, - ["name"] = "Random teleportation", - ["get_text"] = "Space seems to fizzle around you.", - ["lose_text"] = "Space solidify again around you.", - ["desc"] = - { - " Randomly teleports you around", - }, - -- No oppose field, it will be automatically set when we declare the anti-telep corruption to oppose us -} - --- Anti-teleportation corruption, can be stopped with this power -CORRUPT_ANTI_TELEPORT = add_corruption -{ - ["color"] = TERM_GREEN, - ["name"] = "Anti-teleportation", - ["get_text"] = "Space continuum freezes around you.", - ["lose_text"] = "Space continuum can once more be altered around you.", - ["desc"] = - { - " Prevents all teleportations, be it of you or monsters", - }, - ["oppose"] = - { - [CORRUPT_RANDOM_TELEPORT] = TRUE - }, -} - - --- Troll blood -CORRUPT_TROLL_BLOOD = add_corruption -{ - ["color"] = TERM_GREEN, - ["name"] = "Troll Blood", - ["get_text"] = "Your blood thickens, you sense corruption in it.", - ["lose_text"] = "Your blood returns to a normal state.", - ["desc"] = - { - " Troll blood flows in your veins, granting increased regeneration", - " It also enables you to feel the presence of other troll beings", - " But it will make your presence more noticeable and aggravating", - }, -} - --- The vampire corruption set -CORRUPT_VAMPIRE_TEETH = add_corruption -{ - ["group"] = "Vampire", - ["removable"] = FALSE, - ["color"] = TERM_L_DARK, - ["name"] = "Vampiric Teeth", - ["get_text"] = "You grow vampiric teeth!", - ["lose_text"] = "BUG! this should not happen", - ["desc"] = - { - " Your teeth allow you to drain blood to feed yourself", - " However your stomach now only accepts blood.", - }, - ["allow"] = function() - if test_race_flags(1, PR1_NO_SUBRACE_CHANGE) == FALSE then return not nil else return nil end - end, -} -CORRUPT_VAMPIRE_STRENGTH = add_corruption -{ - ["group"] = "Vampire", - ["removable"] = FALSE, - ["color"] = TERM_L_DARK, - ["name"] = "Vampiric Strength", - ["get_text"] = "Your body seems more dead than alive.", - ["lose_text"] = "BUG! this should not happen", - ["desc"] = - { - " Your body seems somewhat dead", - " In this near undead state it has improved strength, constitution and intelligence", - " But reduced dexterity, wisdom and charisma.", - }, - ["depends"] = - { - [CORRUPT_VAMPIRE_TEETH] = TRUE, - }, -} -CORRUPT_VAMPIRE_VAMPIRE = add_corruption -{ - ["group"] = "Vampire", - ["removable"] = FALSE, - ["color"] = TERM_L_DARK, - ["name"] = "Vampire", - ["get_text"] = "You die to be reborn in a Vampire form.", - ["lose_text"] = "BUG! this should not happen", - ["desc"] = - { - " You are a Vampire. As such you resist cold, poison, darkness and nether.", - " Your life is sustained, but you cannot stand the light of the sun." - }, - ["depends"] = - { - [CORRUPT_VAMPIRE_STRENGTH] = TRUE, - }, -} - --- The old activable corruptions / mutations - -MUT1_SPIT_ACID = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Ancalagon's Breath", - ["get_text"] = "You gain the ability to spit acid.", - ["lose_text"] = "You lose the ability to spit acid.", - ["desc"] = - { - " Fires an acid ball.", - " Damage=level Radius 1+(level/30)", - " Level=9, Cost=9, Stat=DEX, Difficulty=15", - }, -} - -MUT1_BR_FIRE = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Smaug's Breath", - ["get_text"] = "You gain the ability to breathe fire.", - ["lose_text"] = "You lose the ability to breathe fire.", - ["desc"] = - { - " Fires a fire ball.", - " Damage=2*level Radius 1+(level/20)", - " Level=20, Cost=10, Stat=CON, Difficulty=18", - }, -} - -MUT1_HYPN_GAZE = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Glaurung's Gaze", - ["get_text"] = "Your eyes look mesmerizing...", - ["lose_text"] = "Your eyes look uninteresting.", - ["desc"] = - { - " Tries to make a monster your pet.", - " Power=level", - " Level=12, Cost=12, Stat=CHR, Difficulty=18", - }, -} - -MUT1_TELEKINES = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Saruman's Power", - ["get_text"] = "You gain the ability to move objects telekinetically.", - ["lose_text"] = "You lose the ability to move objects telekinetically.", - ["desc"] = - { - " Move an object in line of sight to you.", - " Max weight equal to (level) pounds", - " Level=9, Cost=9, Stat=WIS, Difficulty=14", - }, -} - -MUT1_VTELEPORT = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Teleport", - ["get_text"] = "You gain the power of teleportation at will.", - ["lose_text"] = "You lose the power of teleportation at will.", - ["desc"] = - { - " Teleports the player at will.", - " Distance 10+4*level squares", - " Level=7, Cost=7, Stat=WIS, Difficulty=15", - }, -} - -MUT1_MIND_BLST = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Glaurung's Spell", - ["get_text"] = "You gain the power of Mind Blast.", - ["lose_text"] = "You lose the power of Mind Blast.", - ["desc"] = - { - " Fires a mind blasting bolt (psi damage).", - " Psi Damage (3+(level-1)/5)d3", - " Level=5, Cost=3, Stat=WIS, Difficulty=15", - }, -} - -MUT1_VAMPIRISM = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Vampiric Drain", - ["get_text"] = "You become vampiric.", - ["lose_text"] = "You are no longer vampiric.", - ["desc"] = - { - " You can drain life from a foe like a vampire.", - " Drains (level+1d(level))*(level/10) hitpoints,", - " heals you and satiates you. Doesn't work on all monsters", - " Level=4, Cost=5, Stat=CON, Difficulty=9", - }, -} - -MUT1_SMELL_MET = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Carcharoth's Nose", - ["get_text"] = "You smell a metallic odour.", - ["lose_text"] = "You no longer smell a metallic odour.", - ["desc"] = - { - " You can detect nearby precious metal (treasure).", - " Radius 25", - " Level=3, Cost=2, Stat=INT, Difficulty=12", - }, -} - -MUT1_SMELL_MON = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Huan's Nose", - ["get_text"] = "You smell filthy monsters.", - ["lose_text"] = "You no longer smell filthy monsters.", - ["desc"] = - { - " You can detect nearby monsters.", - " Radius 25", - " Level=5, Cost=4, Stat=INT, Difficulty=15", - }, -} - -MUT1_BLINK = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Blink", - ["get_text"] = "You gain the power of minor teleportation.", - ["lose_text"] = "You lose the power of minor teleportation.", - ["desc"] = - { - " You can teleport yourself short distances (10 squares).", - " Level=3, Cost=3, Stat=WIS, Difficulty=12", - }, -} - -MUT1_EAT_ROCK = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Eat Rock", - ["get_text"] = "The walls look delicious.", - ["lose_text"] = "The walls look unappetizing.", - ["desc"] = - { - " You can consume solid rock with food benefit,", - " leaving an empty space behind.", - " Level=8, Cost=12, Stat=CON, Difficulty=18", - }, -} - -MUT1_SWAP_POS = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Swap Position", - ["get_text"] = "You feel like walking a mile in someone else's shoes.", - ["lose_text"] = "You feel like staying in your own shoes.", - ["desc"] = - { - " You can switch locations with another being,", - " unless it resists teleportation.", - " Level=15, Cost=12, Stat=DEX, Difficulty=16", - }, -} - -MUT1_SHRIEK = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Shriek", - ["get_text"] = "Your vocal cords get much tougher.", - ["lose_text"] = "Your vocal cords get much weaker.", - ["desc"] = - { - " Fires a sound ball and aggravates monsters.", - " Damage=level*4, Radius=8, centered on player", - " Level=4, Cost=4, Stat=CON, Difficulty=6", - }, -} - -MUT1_ILLUMINE = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Illuminate", - ["get_text"] = "You can light up rooms with your presence.", - ["lose_text"] = "You can no longer light up rooms with your presence.", - ["desc"] = - { - " You can emit bright light that illuminates an area.", - " Damage=2d(level/2) Radius=(level/10)+1", - " Level=3, Cost=2, Stat=INT, Difficulty=10", - }, -} - -MUT1_DET_CURSE = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Detect Curses", - ["get_text"] = "You can feel evil magics.", - ["lose_text"] = "You can no longer feel evil magics.", - ["desc"] = - { - " You can feel the danger of evil magic.", - " It detects cursed items in the inventory", - " Level=7, Cost=14, Stat=WIS, Difficulty=14", - }, -} - -MUT1_BERSERK = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Berserk", - ["get_text"] = "You feel a controlled rage.", - ["lose_text"] = "You no longer feel a controlled rage.", - ["desc"] = - { - " You can drive yourself into a berserk frenzy.", - " It grants super-heroism. Duration=10+1d(level)", - " Level=8, Cost=8, Stat=STR, Difficulty=14", - }, -} - - -MUT1_MIDAS_TCH = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Midas touch", - ["get_text"] = "You gain the Midas touch.", - ["lose_text"] = "You lose the Midas touch.", - ["desc"] = - { - " You can turn ordinary items to gold.", - " Turns a non-artifact object into 1/3 its value in gold", - " Level=10, Cost=5, Stat=INT, Difficulty=12", - }, -} - -MUT1_GROW_MOLD = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Grow Mold", - ["get_text"] = "You feel a sudden affinity for mold.", - ["lose_text"] = "You feel a sudden dislike for mold.", - ["desc"] = - { - " You can cause mold to grow near you.", - " Summons up to 8 molds around the player", - " Level=1, Cost=6, Stat=CON, Difficulty=14", - }, -} - -MUT1_RESIST = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Resist Elements", - ["get_text"] = "You feel like you can protect yourself.", - ["lose_text"] = "You feel like you might be vulnerable.", - ["desc"] = - { - " You can harden yourself to the ravages of the elements.", - " Level-dependent chance of gaining resistances to the four ", - " elements and poison. Duration=20 + d20", - " Level=10, Cost=12, Stat=CON, Difficulty=12", - }, -} - -MUT1_EARTHQUAKE = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Earthquake", - ["get_text"] = "You gain the ability to wreck the dungeon.", - ["lose_text"] = "You lose the ability to wreck the dungeon.", - ["desc"] = - { - " You can bring down the dungeon around your ears.", - " Radius=10, center on the player", - " Level=12, Cost=12, Stat=STR, Difficulty=16", - }, -} ---[[ -CORRUPT_ = add_corruption -{ - ["color"] = TERM_GREEN, - ["name"] = "", - ["get_text"] = "", - ["lose_text"] = "", - ["desc"] = - { - " ", - }, -} -]] diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index 19649da7..b70fb773 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -17,9 +17,6 @@ tome_dofile("powers.lua") -- Add the mimic shapes tome_dofile("mimic.lua") --- Add the corruptions -tome_dofile("corrupt.lua") - -- Add the mkey activations tome_dofile("mkeys.lua") diff --git a/lib/mods/theme/scpt/monsters.lua b/lib/mods/theme/scpt/monsters.lua index ad3a5628..cbadf1d6 100644 --- a/lib/mods/theme/scpt/monsters.lua +++ b/lib/mods/theme/scpt/monsters.lua @@ -75,10 +75,10 @@ add_hooks{ [HOOK_GAME_START] = function() if ((get_race_name() == "Maia") and - (player.corruption(CORRUPT_BALROG_AURA) ~= TRUE) and - (player.corruption(CORRUPT_BALROG_WINGS) ~= TRUE) and - (player.corruption(CORRUPT_BALROG_STRENGTH) ~= TRUE) and - (player.corruption(CORRUPT_BALROG_FORM) ~= TRUE)) then + (player_has_corruption(CORRUPT_BALROG_AURA) ~= TRUE) and + (player_has_corruption(CORRUPT_BALROG_WINGS) ~= TRUE) and + (player_has_corruption(CORRUPT_BALROG_STRENGTH) ~= TRUE) and + (player_has_corruption(CORRUPT_BALROG_FORM) ~= TRUE)) then -- "Proper" Maiar aggravate evil beings TIMER_AGGRAVATE_EVIL.enabled = TRUE -- Good beings (except swans, GWoPs, Wyrm Spirits, and some joke uniques) are coaligned with Maiar diff --git a/lib/scpt/corrupt.lua b/lib/scpt/corrupt.lua deleted file mode 100644 index 19957668..00000000 --- a/lib/scpt/corrupt.lua +++ /dev/null @@ -1,243 +0,0 @@ --- Definition of the corruptions - --- The Balrog corruptions -CORRUPT_BALROG_AURA = add_corruption -{ - ["color"] = TERM_ORANGE, - ["name"] = "Balrog Aura", - ["get_text"] = "A corrupted wall of flames surrounds you.", - ["lose_text"] = "The wall of corrupted flames abandons you.", - ["desc"] = - { - " Surrounds you with a fiery aura", - " But it can burn scrolls when you read them" - }, -} - -CORRUPT_BALROG_WINGS = add_corruption -{ - ["color"] = TERM_ORANGE, - ["name"] = "Balrog Wings", - ["get_text"] = "Wings of shadow grow in your back.", - ["lose_text"] = "The wings in your back fall apart.", - ["desc"] = - { - " Creates ugly, but working, wings allowing you to fly", - " But it reduces charisma by 4 and dexterity by 2" - }, -} - -CORRUPT_BALROG_STRENGTH = add_corruption -{ - ["color"] = TERM_ORANGE, - ["name"] = "Balrog Strength", - ["get_text"] = "Your muscles get unnatural strength.", - ["lose_text"] = "Your muscles get weaker again.", - ["desc"] = - { - " Provides 3 strength and 1 constitution", - " But it reduces charisma by 1 and dexterity by 3" - }, -} - -CORRUPT_BALROG_FORM = add_corruption -{ - ["color"] = TERM_YELLOW, - ["name"] = "Balrog Form", - ["get_text"] = "You feel the might of a Balrog inside you.", - ["lose_text"] = "The presence of the Balrog seems to abandon you.", - ["desc"] = - { - " Allows you to turn into a Balrog at will", - " You need Balrog Wings, Balrog Aura and Balrog Strength to activate it" - }, - ["depends"] = - { - [CORRUPT_BALROG_AURA] = TRUE, - [CORRUPT_BALROG_WINGS] = TRUE, - [CORRUPT_BALROG_STRENGTH] = TRUE - }, -} - - --- The Demon corruptions -CORRUPT_DEMON_SPIRIT = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Demon Spirit", - ["get_text"] = "Your spirit opens to corrupted thoughts.", - ["lose_text"] = "Your spirit closes again to the corrupted thoughts.", - ["desc"] = - { - " Increases your intelligence by 1", - " But reduce your charisma by 2", - }, -} - -CORRUPT_DEMON_HIDE = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Demon Hide", - ["get_text"] = "Your skin grows into a thick hide.", - ["lose_text"] = "Your skin returns to a natural state.", - ["desc"] = - { - " Increases your armour class by your level", - " Provides immunity to fire at level 40", - " But reduces speed by your level / 7", - }, -} - -CORRUPT_DEMON_BREATH = add_corruption -{ - ["color"] = TERM_RED, - ["name"] = "Demon Breath", - ["get_text"] = "Your breath becomes mephitic.", - ["lose_text"] = "Your breath is once again normal.", - ["desc"] = - { - " Provides fire breath", - " But gives a small chance to spoil potions when you quaff them", - }, -} - -CORRUPT_DEMON_REALM = add_corruption -{ - ["color"] = TERM_L_RED, - ["name"] = "Demon Realm", - ["get_text"] = "You feel more attuned to the demon realm.", - ["lose_text"] = "You lose your attunement to the demon realm.", - ["desc"] = - { - " Provides access to the demon school skill and the use of demonic equipment", - " You need Demon Spirit, Demon Hide and Demon Breath to activate it" - }, - ["depends"] = - { - [CORRUPT_DEMON_SPIRIT] = TRUE, - [CORRUPT_DEMON_HIDE] = TRUE, - [CORRUPT_DEMON_BREATH] = TRUE - }, -} - - --- Teleportation corruptions - --- Random teleportation will ask for confirmation 70% of the time --- But 30% of the time it will teleport, without asking -CORRUPT_RANDOM_TELEPORT = add_corruption -{ - ["color"] = TERM_GREEN, - ["name"] = "Random teleportation", - ["get_text"] = "Space seems to fizzle around you.", - ["lose_text"] = "Space solidify again around you.", - ["desc"] = - { - " Randomly teleports you around", - }, - -- No oppose field, it will be automatically set when we declare the anti-telep corruption to oppose us -} - --- Anti-teleportation corruption, can be stopped with this power -CORRUPT_ANTI_TELEPORT = add_corruption -{ - ["color"] = TERM_GREEN, - ["name"] = "Anti-teleportation", - ["get_text"] = "Space continuum freezes around you.", - ["lose_text"] = "Space continuum can once more be altered around you.", - ["desc"] = - { - " Prevents all teleportations, be it of you or monsters", - }, - ["oppose"] = - { - [CORRUPT_RANDOM_TELEPORT] = TRUE - }, -} - - --- Troll blood -CORRUPT_TROLL_BLOOD = add_corruption -{ - ["color"] = TERM_GREEN, - ["name"] = "Troll Blood", - ["get_text"] = "Your blood thickens, you sense corruption in it.", - ["lose_text"] = "Your blood returns to a normal state.", - ["desc"] = - { - " Troll blood flows in your veins, granting increased regeneration", - " It also enables you to feel the presence of other troll beings", - " But it will make your presence more noticeable and aggravating", - }, -} - --- The vampire corruption set -CORRUPT_VAMPIRE_TEETH = add_corruption -{ - ["group"] = "Vampire", - ["removable"] = FALSE, - ["color"] = TERM_L_DARK, - ["name"] = "Vampiric Teeth", - ["get_text"] = "You grow vampiric teeth!", - ["lose_text"] = "BUG! this should not happen", - ["desc"] = - { - " Your teeth allow you to drain blood to feed yourself", - " However your stomach now only accepts blood.", - }, - ["allow"] = function() - if test_race_flags(1, PR1_NO_SUBRACE_CHANGE) == FALSE then return not nil else return nil end - end, -} -CORRUPT_VAMPIRE_STRENGTH = add_corruption -{ - ["group"] = "Vampire", - ["removable"] = FALSE, - ["color"] = TERM_L_DARK, - ["name"] = "Vampiric Strength", - ["get_text"] = "Your body seems more dead than alive.", - ["lose_text"] = "BUG! this should not happen", - ["desc"] = - { - " Your body seems somewhat dead", - " In this near undead state it has improved strength, constitution and intelligence", - " But reduced dexterity, wisdom and charisma.", - }, - ["depends"] = - { - [CORRUPT_VAMPIRE_TEETH] = TRUE, - }, -} -CORRUPT_VAMPIRE_VAMPIRE = add_corruption -{ - ["group"] = "Vampire", - ["removable"] = FALSE, - ["color"] = TERM_L_DARK, - ["name"] = "Vampire", - ["get_text"] = "You die to be reborn in a Vampire form.", - ["lose_text"] = "BUG! this should not happen", - ["desc"] = - { - " You are a Vampire. As such you resist cold, poison, darkness and nether.", - " Your life is sustained, but you cannot stand the light of the sun." - }, - ["depends"] = - { - [CORRUPT_VAMPIRE_STRENGTH] = TRUE, - }, -} - - ---[[ -CORRUPT_ = add_corruption -{ - ["color"] = TERM_GREEN, - ["name"] = "", - ["get_text"] = "", - ["lose_text"] = "", - ["desc"] = - { - " ", - }, -} -]] diff --git a/lib/scpt/init.lua b/lib/scpt/init.lua index 8b288f17..ea42f927 100644 --- a/lib/scpt/init.lua +++ b/lib/scpt/init.lua @@ -17,9 +17,6 @@ tome_dofile("powers.lua") -- Add the mimic shapes tome_dofile("mimic.lua") --- Add the corruptions -tome_dofile("corrupt.lua") - -- Add the mkey activations tome_dofile("mkeys.lua") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e2e62644..d610e193 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,7 +9,7 @@ SET(SRCS object1.c object2.c randart.c squeltch.c traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c - spells1.c spells2.c + spells1.c spells2.c corrupt.c status.c files.c notes.c loadsave.c cmd1.c cmd2.c cmd3.c cmd4.c cmd5.c cmd6.c cmd7.c help.c diff --git a/src/birth.c b/src/birth.c index 263877fe..f050f9d1 100644 --- a/src/birth.c +++ b/src/birth.c @@ -823,7 +823,6 @@ static void player_wipe(void) int i, j; bool_ *powers; - bool_ *corruptions; /* Wipe special levels */ @@ -831,21 +830,16 @@ static void player_wipe(void) /* Save the powers & corruptions */ powers = p_ptr->powers; - corruptions = p_ptr->corruptions; /* Hack -- zero the struct */ p_ptr = WIPE(p_ptr, player_type); /* Restore the powers & corruptions */ p_ptr->powers = powers; - p_ptr->corruptions = corruptions; /* Not dead yet */ p_ptr->lives = 0; - /* Wipe the corruptions */ - (void)C_WIPE(p_ptr->corruptions, max_corruptions, bool_); - /* Wipe the history */ for (i = 0; i < 4; i++) { diff --git a/src/cmd4.c b/src/cmd4.c index e9125d3d..29d01c73 100644 --- a/src/cmd4.c +++ b/src/cmd4.c @@ -4069,7 +4069,10 @@ void do_cmd_knowledge_corruptions(void) fff = my_fopen(file_name, "w"); /* Dump the corruptions to file */ - if (fff) dump_corruptions(fff, TRUE); + if (fff) + { + dump_corruptions(fff, TRUE, FALSE); + } /* Close the file */ my_fclose(fff); diff --git a/src/cmd5.c b/src/cmd5.c index 847c279b..57746ca0 100644 --- a/src/cmd5.c +++ b/src/cmd5.c @@ -236,7 +236,7 @@ void do_poly_self(void) /* Polymorph into a less corrupted form */ power -= 10; - lose_corruption(0); + lose_corruption(); } /* diff --git a/src/cmd6.c b/src/cmd6.c index 48d56125..67fad8e2 100644 --- a/src/cmd6.c +++ b/src/cmd6.c @@ -2347,7 +2347,7 @@ static bool_ quaff_potion(int tval, int sval, int pval, int pval2) } msg_print("You feel the dark corruptions of Morgoth coming over you!"); - gain_random_corruption(0); + gain_random_corruption(); ident = TRUE; break; } @@ -7220,7 +7220,7 @@ const char *activation_aux(object_type * o_ptr, bool_ doit, int item) case ACT_MUT: { if (!doit) return "gain corruption every 10 turns"; - gain_random_corruption(0); + gain_random_corruption(); /* Timeout is set before return */ break; diff --git a/src/corrupt.c b/src/corrupt.c new file mode 100644 index 00000000..25570303 --- /dev/null +++ b/src/corrupt.c @@ -0,0 +1,916 @@ +#include "angband.h" +#include + +/** + * Vampire corruption helpers + */ + +static void subrace_add_power(player_race_mod *rmp_ptr, int power) +{ + int i; + + for (i=0; i<4; i++) + { + if (rmp_ptr->powers[i] == -1) + { + rmp_ptr->powers[i] = power; + return; + } + } +} + +static void player_gain_vampire_teeth() +{ + player_race_mod *rmp_ptr = NULL; + + switch_subrace(SUBRACE_SAVE, TRUE); + + rmp_ptr = &race_mod_info[SUBRACE_SAVE]; + subrace_add_power(rmp_ptr, PWR_VAMPIRISM); + rmp_ptr->flags1 = rmp_ptr->flags1 + | PR1_VAMPIRE + | PR1_UNDEAD + | PR1_NO_SUBRACE_CHANGE; +} + +static void player_gain_vampire_strength() +{ + player_race_mod *rmp_ptr = &race_mod_info[SUBRACE_SAVE]; + /* Apply the bonuses/penalities */ + rmp_ptr->r_mhp = rmp_ptr->r_mhp + 1; + rmp_ptr->r_exp = rmp_ptr->r_exp + 100; + + rmp_ptr->r_adj[A_STR + 1] = rmp_ptr->r_adj[A_STR + 1] + 3; + rmp_ptr->r_adj[A_INT + 1] = rmp_ptr->r_adj[A_INT + 1] + 2; + rmp_ptr->r_adj[A_WIS + 1] = rmp_ptr->r_adj[A_WIS + 1] - 3; + rmp_ptr->r_adj[A_DEX + 1] = rmp_ptr->r_adj[A_DEX + 1] - 2; + rmp_ptr->r_adj[A_CON + 1] = rmp_ptr->r_adj[A_CON + 1] + 1; + rmp_ptr->r_adj[A_CHR + 1] = rmp_ptr->r_adj[A_CHR + 1] - 4; + + /* be reborn! */ + do_rebirth(); + cmsg_print(TERM_L_DARK, "You feel death slipping inside."); +} + +static void player_gain_vampire() +{ + player_race_mod *rmp_ptr = &race_mod_info[SUBRACE_SAVE]; + + /* Be a Vampire and be proud of it */ + cptr title = get_subrace_title(SUBRACE_SAVE); + if (streq(title, " ") || streq(title, "Vampire")) + { + title = "Vampire"; + rmp_ptr->place = FALSE; + set_subrace_title(SUBRACE_SAVE, title); + } + else + { + char buf[512]; + sprintf(buf, "Vampire %s", title); + set_subrace_title(SUBRACE_SAVE, buf); + } + + /* Bonus/and .. not bonus :) */ + rmp_ptr->flags1 = rmp_ptr->flags1 | PR1_HURT_LITE; + rmp_ptr->oflags2[2] = rmp_ptr->oflags2[2] + | TR2_RES_POIS + | TR2_RES_NETHER + | TR2_RES_COLD + | TR2_RES_DARK + | TR2_HOLD_LIFE; + rmp_ptr->oflags3[2] = rmp_ptr->oflags3[2] + | TR3_LITE1; +} + +/** + * Corruptions + */ +corruption_type corruptions[CORRUPTIONS_MAX] = +{ + /* + * BALROG corruptions + */ + + { /* 0 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_ORANGE, + NULL /* no group */, + "Balrog Aura", + "A corrupted wall of flames surrounds you.", + "The wall of corrupted flames abandons you.", + " Surrounds you with a fiery aura\n" + " But it can burn scrolls when you read them", + { -1 }, + { -1 }, + NULL, + }, + + { /* 1 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_ORANGE, + NULL /* no group */, + "Balrog Wings", + "Wings of shadow grow in your back.", + "The wings in your back fall apart.", + " Creates ugly, but working, wings allowing you to fly\n" + " But it reduces charisma by 4 and dexterity by 2", + { -1 }, + { -1 }, + NULL, + }, + + { /* 2 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_ORANGE, + NULL /* no group */, + "Balrog Strength", + "Your muscles get unnatural strength.", + "Your muscles get weaker again.", + " Provides 3 strength and 1 constitution\n" + " But it reduces charisma by 1 and dexterity by 3", + { -1 }, + { -1 }, + NULL, + }, + + { /* 3 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_YELLOW, + NULL /* no group */, + "Balrog Form", + "You feel the might of a Balrog inside you.", + "The presence of the Balrog seems to abandon you.", + " Allows you to turn into a Balrog at will\n" + " You need Balrog Wings, Balrog Aura and Balrog Strength to activate it", + { CORRUPT_BALROG_AURA, CORRUPT_BALROG_WINGS, CORRUPT_BALROG_STRENGTH }, + { -1 }, + NULL, + }, + + /* + * DEMON corruptions + */ + { /* 4 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Demon Spirit", + "Your spirit opens to corrupted thoughts.", + "Your spirit closes again to the corrupted thoughts.", + " Increases your intelligence by 1\n" + " But reduce your charisma by 2", + { -1 }, + { -1 }, + NULL, + }, + + { /* 5 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Demon Hide", + "Your skin grows into a thick hide.", + "Your skin returns to a natural state.", + " Increases your armour class by your level\n" + " Provides immunity to fire at level 40\n" + " But reduces speed by your level / 7", + { -1 }, + { -1 }, + NULL, + }, + + { /* 6 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Demon Breath", + "Your breath becomes mephitic.", + "Your breath is once again normal.", + " Provides fire breath\n" + " But gives a small chance to spoil potions when you quaff them", + { -1 }, + { -1 }, + NULL, + }, + + { /* 7 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_L_RED, + NULL /* no group */, + "Demon Realm", + "You feel more attuned to the demon realm.", + "You lose your attunement to the demon realm.", + " Provides access to the demon school skill and the use of demonic equipment\n" + " You need Demon Spirit, Demon Hide and Demon Breath to activate it", + { CORRUPT_DEMON_SPIRIT, CORRUPT_DEMON_HIDE, CORRUPT_DEMON_BREATH }, + { -1 }, + NULL, + }, + + /* + * Teleportation corruptions + */ + + { /* 8 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_GREEN, + NULL /* no group */, + "Random teleportation", + "Space seems to fizzle around you.", + "Space solidify again around you.", + " Randomly teleports you around", + { -1 }, + { CORRUPT_ANTI_TELEPORT, -1 }, + NULL, + }, + + { /* 9 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_GREEN, + NULL /* no group */, + "Anti-teleportation", + "Space continuum freezes around you.", + "Space continuum can once more be altered around you.", + " Prevents all teleportations, be it of you or monsters", + { -1 }, + { CORRUPT_RANDOM_TELEPORT, -1 }, + NULL, + }, + + /* + * Troll blood + */ + + { /* 10 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_GREEN, + NULL /* no group */, + "Troll Blood", + "Your blood thickens, you sense corruption in it.", + "Your blood returns to a normal state.", + " Troll blood flows in your veins, granting increased regeneration\n" + " It also enables you to feel the presence of other troll beings\n" + " But it will make your presence more noticeable and aggravating", + { -1 }, + { -1 }, + NULL, + }, + + /* + * The vampire corruption set + */ + + { /* 11 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_L_DARK, + "Vampire", + "Vampiric Teeth", + "You grow vampiric teeth!", + NULL, /* cannot lose */ + " Your teeth allow you to drain blood to feed yourself\n" + " However your stomach now only accepts blood.", + { -1 }, + { -1 }, + player_gain_vampire_teeth, + }, + + { /* 12 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_L_DARK, + "Vampire", + "Vampiric Strength", + "Your body seems more dead than alive.", + NULL, /* cannot lose */ + " Your body seems somewhat dead\n" + " In this near undead state it has improved strength, constitution and intelligence\n" + " But reduced dexterity, wisdom and charisma.", + { CORRUPT_VAMPIRE_TEETH, -1 }, + { -1 }, + player_gain_vampire_strength, + }, + + { /* 13 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_L_DARK, + "Vampire", + "Vampire", + "You die to be reborn in a Vampire form.", + NULL, /* cannot lose */ + " You are a Vampire. As such you resist cold, poison, darkness and nether.\n" + " Your life is sustained, but you cannot stand the light of the sun.", + { CORRUPT_VAMPIRE_STRENGTH, -1 }, + { -1 }, + player_gain_vampire, + }, + + /* + * Activatable corruptions (mutations) + */ + + { /* 14 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Ancalagon's Breath", + "You gain the ability to spit acid.", + "You lose the ability to spit acid.", + " Fires an acid ball.\n" + " Damage=level Radius 1+(level/30)\n" + " Level=9, Cost=9, Stat=DEX, Difficulty=15", + { -1 }, + { -1 }, + NULL, + }, + + { /* 15 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Smaug's Breath", + "You gain the ability to breathe fire.", + "You lose the ability to breathe fire.", + " Fires a fire ball.\n" + " Damage=2*level Radius 1+(level/20)\n" + " Level=20, Cost=10, Stat=CON, Difficulty=18", + { -1 }, + { -1 }, + NULL, + }, + + { /* 16 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Glaurung's Gaze", + "Your eyes look mesmerizing...", + "Your eyes look uninteresting.", + " Tries to make a monster your pet.\n" + " Power=level\n" + " Level=12, Cost=12, Stat=CHR, Difficulty=18", + { -1 }, + { -1 }, + NULL, + }, + + { /* 17 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Saruman's Power", + "You gain the ability to move objects telekinetically.", + "You lose the ability to move objects telekinetically.", + " Move an object in line of sight to you.\n" + " Max weight equal to (level) pounds\n" + " Level=9, Cost=9, Stat=WIS, Difficulty=14", + { -1 }, + { -1 }, + NULL, + }, + + { /* 18 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Teleport", + "You gain the power of teleportation at will.", + "You lose the power of teleportation at will.", + " Teleports the player at will.\n" + " Distance 10+4*level squares\n" + " Level=7, Cost=7, Stat=WIS, Difficulty=15", + { -1 }, + { -1 }, + NULL, + }, + + { /* 19 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Glaurung's Spell", + "You gain the power of Mind Blast.", + "You lose the power of Mind Blast.", + " Fires a mind blasting bolt (psi damage).\n" + " Psi Damage (3+(level-1)/5)d3\n" + " Level=5, Cost=3, Stat=WIS, Difficulty=15", + { -1 }, + { -1 }, + NULL, + }, + + { /* 20 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Vampiric Drain", + "You become vampiric.", + "You are no longer vampiric.", + " You can drain life from a foe like a vampire.\n" + " Drains (level+1d(level))*(level/10) hitpoints,\n" + " heals you and satiates you. Doesn't work on all monsters\n" + " Level=4, Cost=5, Stat=CON, Difficulty=9", + { -1 }, + { -1 }, + NULL, + }, + + { /* 21 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Carcharoth's Nose", + "You smell a metallic odour.", + "You no longer smell a metallic odour.", + " You can detect nearby precious metal (treasure).\n" + " Radius 25\n" + " Level=3, Cost=2, Stat=INT, Difficulty=12", + { -1 }, + { -1 }, + NULL, + }, + + { /* 22 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Huan's Nose", + "You smell filthy monsters.", + "You no longer smell filthy monsters.", + " You can detect nearby monsters.\n" + " Radius 25\n" + " Level=5, Cost=4, Stat=INT, Difficulty=15", + { -1 }, + { -1 }, + NULL, + }, + + { /* 23 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Blink", + "You gain the power of minor teleportation.", + "You lose the power of minor teleportation.", + " You can teleport yourself short distances (10 squares).\n" + " Level=3, Cost=3, Stat=WIS, Difficulty=12", + { -1 }, + { -1 }, + NULL, + }, + + { /* 24 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Eat Rock", + "The walls look delicious.", + "The walls look unappetizing.", + " You can consume solid rock with food benefit,\n" + " leaving an empty space behind.\n" + " Level=8, Cost=12, Stat=CON, Difficulty=18", + { -1 }, + { -1 }, + NULL, + }, + + { /* 25 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Swap Position", + "You feel like walking a mile in someone else's shoes.", + "You feel like staying in your own shoes.", + " You can switch locations with another being,\n" + " unless it resists teleportation.\n" + " Level=15, Cost=12, Stat=DEX, Difficulty=16", + { -1 }, + { -1 }, + NULL, + }, + + { /* 26 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Shriek", + "Your vocal cords get much tougher.", + "Your vocal cords get much weaker.", + " Fires a sound ball and aggravates monsters.\n" + " Damage=level*4, Radius=8, centered on player\n" + " Level=4, Cost=4, Stat=CON, Difficulty=6", + { -1 }, + { -1 }, + NULL, + }, + + { /* 27 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Illuminate", + "You can light up rooms with your presence.", + "You can no longer light up rooms with your presence.", + " You can emit bright light that illuminates an area.\n" + " Damage=2d(level/2) Radius=(level/10)+1\n" + " Level=3, Cost=2, Stat=INT, Difficulty=10", + { -1 }, + { -1 }, + NULL, + }, + + { /* 28 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Detect Curses", + "You can feel evil magics.", + "You can no longer feel evil magics.", + " You can feel the danger of evil magic.\n" + " It detects cursed items in the inventory\n" + " Level=7, Cost=14, Stat=WIS, Difficulty=14", + { -1 }, + { -1 }, + NULL, + }, + + { /* 29 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Berserk", + "You feel a controlled rage.", + "You no longer feel a controlled rage.", + " You can drive yourself into a berserk frenzy.\n" + " It grants super-heroism. Duration=10+1d(level)\n" + " Level=8, Cost=8, Stat=STR, Difficulty=14", + { -1 }, + { -1 }, + NULL, + }, + + { /* 30 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Midas touch", + "You gain the Midas touch.", + "You lose the Midas touch.", + " You can turn ordinary items to gold.\n" + " Turns a non-artifact object into 1/3 its value in gold\n" + " Level=10, Cost=5, Stat=INT, Difficulty=12", + { -1 }, + { -1 }, + NULL, + }, + + { /* 31 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Grow Mold", + "You feel a sudden affinity for mold.", + "You feel a sudden dislike for mold.", + " You can cause mold to grow near you.\n" + " Summons up to 8 molds around the player\n" + " Level=1, Cost=6, Stat=CON, Difficulty=14", + { -1 }, + { -1 }, + NULL, + }, + + { /* 32 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Resist Elements", + "You feel like you can protect yourself.", + "You feel like you might be vulnerable.", + " You can harden yourself to the ravages of the elements.\n" + " Level-dependent chance of gaining resistances to the four \n" + " elements and poison. Duration=20 + d20\n" + " Level=10, Cost=12, Stat=CON, Difficulty=12", + { -1 }, + { -1 }, + NULL, + }, + + { /* 33 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Earthquake", + "You gain the ability to wreck the dungeon.", + "You lose the ability to wreck the dungeon.", + " You can bring down the dungeon around your ears.\n" + " Radius=10, center on the player\n" + " Level=12, Cost=12, Stat=STR, Difficulty=16", + { -1 }, + { -1 }, + NULL, + }, + +}; + +/** + * Initialize corruptions + */ +void init_corruptions() +{ + /* Nothing needed currently */ +} + +/* + * Corruptions + */ +bool_ player_has_corruption(int corruption_idx) +{ + if (corruption_idx < 0) + { + return FALSE; + } + + return (p_ptr->corruptions[corruption_idx]); +} + +static bool_ player_can_gain_corruption(int corruption_idx) +{ + cptr r_name = rp_ptr->title + rp_name; + bool_ allowed = TRUE; /* Allowed by default */ + + assert(corruption_idx >= 0); + + if (corruption_idx == CORRUPT_TROLL_BLOOD) + { + /* Ok trolls should not get this one. never. */ + if (streq(r_name, "Troll")) + { + allowed = FALSE; + } + } + + /* Theme module adds additional restrictions for Maiar */ + + if (game_module_idx == MODULE_THEME) + { + if (streq(r_name, "Maia")) + { + /* We use a whitelist of corruptions for Maiar */ + bool_ allow = FALSE; + if ((corruption_idx == CORRUPT_BALROG_AURA) || + (corruption_idx == CORRUPT_BALROG_WINGS) || + (corruption_idx == CORRUPT_BALROG_STRENGTH) || + (corruption_idx == CORRUPT_BALROG_FORM) || + (corruption_idx == CORRUPT_DEMON_BREATH)) + { + allow = TRUE; + }; + + /* Mix result into 'allowed' flag */ + allowed = allowed & allow; + } + } + + /* Result */ + return allowed; +} + +static bool_ player_allow_corruption(int corruption_idx) +{ + int i; + bool_ found = FALSE; + corruption_type *c_ptr = NULL; + + assert(corruption_idx < CORRUPTIONS_MAX); + c_ptr = &corruptions[corruption_idx]; + + /* Must be allowed by module */ + for (i = 0; c_ptr->modules[i] >= 0; i++) + { + if (c_ptr->modules[i] == game_module_idx) + { + found = TRUE; + } + } + + if (!found) + { + return FALSE; + } + + /* Vampire teeth is special */ + if (corruption_idx == CORRUPT_VAMPIRE_TEETH) + { + if (PRACE_FLAG(PR1_NO_SUBRACE_CHANGE)) + { + return TRUE; + } + else + { + return FALSE; + } + } + + return TRUE; +} + +static void player_set_corruption(int c, bool_ set) +{ + p_ptr->corruptions[c] = set; + p_ptr->redraw = p_ptr->redraw | PR_BASIC; + p_ptr->update = p_ptr->update | PU_BONUS | PU_TORCH | PU_BODY | PU_POWERS; + +} + +void player_gain_corruption(int corruption_idx) +{ + corruption_type *c_ptr = NULL; + assert(corruption_idx >= 0); + assert(corruption_idx < CORRUPTIONS_MAX); + c_ptr = &corruptions[corruption_idx]; + + /* Set the player's corruption flag */ + player_set_corruption(corruption_idx, TRUE); + + /* Invoke callback if necessary */ + if (c_ptr->gain_callback) + { + c_ptr->gain_callback(); + } +} + +static void player_lose_corruption(int corruption_idx) +{ + assert(corruption_idx >= 0); + assert(corruption_idx < CORRUPTIONS_MAX); + + player_set_corruption(corruption_idx, FALSE); + + /* Currently no corruptions need any special handling when lost */ +} + +/* + * Test if we have that corruption + * We must: + * 1) have it or be willing to get it + * 2) have all its dependancies + * 3) have none of its opposing corruptions + * 4) pass the possible tests + */ +static bool_ test_depend_corrupt(s16b corrupt_idx, bool_ can_gain) +{ + s16b i; + corruption_type *c_ptr = NULL; + + assert(corrupt_idx >= 0); + assert(corrupt_idx < CORRUPTIONS_MAX); + + c_ptr = &corruptions[corrupt_idx]; + + if (can_gain) + { + if (p_ptr->corruptions[corrupt_idx]) + { + return FALSE; + } + } else { + if (!p_ptr->corruptions[corrupt_idx]) + { + return FALSE; + } + } + + /* Go through all dependencies */ + for (i=0; c_ptr->depends[i] >= 0; i++) + { + if (!test_depend_corrupt(c_ptr->depends[i], FALSE)) + { + return FALSE; + } + } + + /* Go through all opposers */ + for (i=0; c_ptr->opposes[i] >= 0; i++) + { + if (test_depend_corrupt(c_ptr->opposes[i], FALSE)) + { + return FALSE; + } + } + + /* are we even allowed to get it? */ + return player_can_gain_corruption(corrupt_idx); +} + +void gain_random_corruption() +{ + s16b i, max; + s16b pos[CORRUPTIONS_MAX]; + + /* Get the list of all possible ones */ + max = 0; + for (i=0; i < CORRUPTIONS_MAX; i++) + { + if (test_depend_corrupt(i, TRUE) && + player_allow_corruption(i)) + { + pos[max] = i; + max = max + 1; + } + } + + /* Ok now get one of them */ + if (max > 0) + { + s16b ret = rand_int(max); + int c_idx = pos[ret]; + assert(c_idx < CORRUPTIONS_MAX); + + player_gain_corruption(c_idx); + cmsg_print(TERM_L_RED, corruptions[c_idx].get_text); + } +} + +static void remove_corruption(int c_idx) +{ + assert(c_idx >= 0 && c_idx < CORRUPTIONS_MAX); + assert(corruptions[c_idx].lose_text); + + player_lose_corruption(c_idx); + cmsg_print(TERM_L_RED, corruptions[c_idx].lose_text); +} + +void lose_corruption() +{ + s16b i, max; + s16b pos[CORRUPTIONS_MAX]; + + /* Get the list of all possible ones */ + max = 0; + for (i = 0; i < CORRUPTIONS_MAX; i++) + { + bool_ is_removable = (corruptions[i].lose_text != NULL); + if (test_depend_corrupt(i, FALSE) && is_removable) + { + pos[max] = i; + max = max + 1; + } + } + + /* Ok now get one of them */ + if (max > 0) + { + s16b ret = rand_int(max); + int c_idx = pos[ret]; + + /* Remove the corruption */ + remove_corruption(c_idx); + + /* Ok now lets see if it broke some dependencies */ + for (i = 0; i < max - 1; i++) + { + if (p_ptr->corruptions[pos[i]] != test_depend_corrupt(pos[i], FALSE)) + { + remove_corruption(pos[i]); + } + } + } +} + + +/* + * Dump the corruption list + */ +void dump_corruptions(FILE *fff, bool_ color, bool_ header) +{ + int i; + + assert(fff != NULL); + + for (i = 0; i < CORRUPTIONS_MAX; i++) + { + corruption_type *c_ptr = &corruptions[i]; + + if (header) + { + fprintf(fff, "\n Corruption list:\n"); + header = FALSE; + } + + if (p_ptr->corruptions[i]) + { + byte c = c_ptr->color; + + if (color) + { + fprintf(fff, "#####%c%s:\n", conv_color[c], c_ptr->name); + } + else + { + fprintf(fff, "%s:\n", c_ptr->name); + } + + fprintf(fff, "%s\n", c_ptr->desc); + } + } +} + diff --git a/src/defines.h b/src/defines.h index d40e3b90..b590edc5 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4431,6 +4431,45 @@ #define MODULE_THEME 1 #define MAX_MODULES 2 +/* + * Corruptions + */ +#define CORRUPT_BALROG_AURA 0 +#define CORRUPT_BALROG_WINGS 1 +#define CORRUPT_BALROG_STRENGTH 2 +#define CORRUPT_BALROG_FORM 3 +#define CORRUPT_DEMON_SPIRIT 4 +#define CORRUPT_DEMON_HIDE 5 +#define CORRUPT_DEMON_BREATH 6 +#define CORRUPT_DEMON_REALM 7 +#define CORRUPT_RANDOM_TELEPORT 8 +#define CORRUPT_ANTI_TELEPORT 9 +#define CORRUPT_TROLL_BLOOD 10 +#define CORRUPT_VAMPIRE_TEETH 11 +#define CORRUPT_VAMPIRE_STRENGTH 12 +#define CORRUPT_VAMPIRE_VAMPIRE 13 +#define MUT1_SPIT_ACID 14 +#define MUT1_BR_FIRE 15 +#define MUT1_HYPN_GAZE 16 +#define MUT1_TELEKINES 17 +#define MUT1_VTELEPORT 18 +#define MUT1_MIND_BLST 19 +#define MUT1_VAMPIRISM 20 +#define MUT1_SMELL_MET 21 +#define MUT1_SMELL_MON 22 +#define MUT1_BLINK 23 +#define MUT1_EAT_ROCK 24 +#define MUT1_SWAP_POS 25 +#define MUT1_SHRIEK 26 +#define MUT1_ILLUMINE 27 +#define MUT1_DET_CURSE 28 +#define MUT1_BERSERK 29 +#define MUT1_MIDAS_TCH 30 +#define MUT1_GROW_MOLD 31 +#define MUT1_RESIST 32 +#define MUT1_EARTHQUAKE 33 +#define CORRUPTIONS_MAX 34 + /* * Hooks */ diff --git a/src/externs.h b/src/externs.h index 3f48098c..c82eee41 100644 --- a/src/externs.h +++ b/src/externs.h @@ -583,7 +583,6 @@ extern char gen_skill_modm[MAX_SKILLS]; extern s16b gen_skill_mod[MAX_SKILLS]; extern bool_ linear_stats; extern int max_bact; -extern s16b max_corruptions; extern bool_ option_ingame_help; extern bool_ automatizer_enabled; extern s16b last_teleportation_y; @@ -604,40 +603,6 @@ extern s32b max_gods; extern timer_type *gl_timers; extern s16b tim_precognition; extern const char *get_version_string(); -extern s16b CORRUPT_BALROG_AURA; -extern s16b CORRUPT_BALROG_WINGS; -extern s16b CORRUPT_BALROG_STRENGTH; -extern s16b CORRUPT_BALROG_FORM; -extern s16b CORRUPT_DEMON_SPIRIT; -extern s16b CORRUPT_DEMON_HIDE; -extern s16b CORRUPT_DEMON_BREATH; -extern s16b CORRUPT_DEMON_REALM; -extern s16b CORRUPT_RANDOM_TELEPORT; -extern s16b CORRUPT_ANTI_TELEPORT; -extern s16b CORRUPT_TROLL_BLOOD; -extern s16b CORRUPT_VAMPIRE_TEETH; -extern s16b CORRUPT_VAMPIRE_STRENGTH; -extern s16b CORRUPT_VAMPIRE_VAMPIRE; -extern s16b MUT1_SPIT_ACID; -extern s16b MUT1_BR_FIRE; -extern s16b MUT1_HYPN_GAZE; -extern s16b MUT1_TELEKINES; -extern s16b MUT1_VTELEPORT; -extern s16b MUT1_MIND_BLST; -extern s16b MUT1_VAMPIRISM; -extern s16b MUT1_SMELL_MET; -extern s16b MUT1_SMELL_MON; -extern s16b MUT1_BLINK; -extern s16b MUT1_EAT_ROCK; -extern s16b MUT1_SWAP_POS; -extern s16b MUT1_SHRIEK; -extern s16b MUT1_ILLUMINE; -extern s16b MUT1_DET_CURSE; -extern s16b MUT1_BERSERK; -extern s16b MUT1_MIDAS_TCH; -extern s16b MUT1_GROW_MOLD; -extern s16b MUT1_RESIST; -extern s16b MUT1_EARTHQUAKE; extern s16b POWER_INVISIBILITY; extern s16b POWER_WEB; extern s16b POWER_COR_SPACE_TIME; @@ -907,6 +872,13 @@ extern void do_cmd_symbiotic(void); extern s32b sroot(s32b n); extern int clamp_failure_chance(int chance, int minfail); +/* corrupt.c */ +extern void gain_random_corruption(); +extern void dump_corruptions(FILE *OutFile, bool_ color, bool_ header); +extern void lose_corruption(); +extern bool_ player_has_corruption(int corruption_idx); +extern void player_gain_corruption(int corruption_idx); + /* dungeon.c */ extern byte value_check_aux1(object_type *o_ptr); extern byte value_check_aux1_magic(object_type *o_ptr); @@ -1004,7 +976,7 @@ extern errr init_wf_info_txt(FILE *fp, char *buf); extern errr process_dungeon_file(cptr name, int *yval, int *xval, int ymax, int xmax, bool_ init, bool_ full); /* init2.c */ -extern void init_corruptions(s16b new_size); +extern void init_corruptions(); extern void init_spells(s16b new_size); extern void init_schools(s16b new_size); extern void reinit_gods(s16b new_size); @@ -1670,15 +1642,11 @@ extern bool_ set_shadow(int v); extern bool_ set_tim_esp(int v); extern bool_ tgp_pt(int *x, int * y); extern bool_ tgt_pt (int *x, int *y); -extern bool_ gain_random_corruption(int choose_mut); -extern bool_ got_corruptions(void); -extern void dump_corruptions(FILE *OutFile, bool_ color); extern void do_poly_self(void); extern void do_poly_wounds(void); extern bool_ curse_weapon(void); extern bool_ curse_armor(void); extern void random_resistance(object_type * q_ptr, bool_ is_scroll, int specific); -extern bool_ lose_corruption(int choose_mut); extern void great_side_effect(void); extern void nasty_side_effect(void); extern void deadly_side_effect(bool_ god); @@ -1868,11 +1836,6 @@ extern void lua_delete_list(list_type *, int size); extern void lua_add_to_list(list_type *, int idx, cptr str); extern void lua_display_list(int y, int x, int h, int w, cptr title, list_type *list, int max, int begin, int sel, byte sel_color); -extern bool_ player_has_corruption(int corruption_idx); -extern bool_ player_can_gain_corruption(int corruption_idx); -extern void player_gain_corruption(int corruption_idx); -extern void player_lose_corruption(int corruption_idx); - extern cptr compass(int y, int x, int y2, int x2); extern cptr approximate_distance(int y, int x, int y2, int x2); diff --git a/src/files.c b/src/files.c index 56e57975..96ee66a9 100644 --- a/src/files.c +++ b/src/files.c @@ -2736,11 +2736,7 @@ errr file_character(cptr name, bool_ full) file_character_print_grid(fff, FALSE, FALSE); /* Dump corruptions */ - if (got_corruptions()) - { - fprintf(fff, "\n Corruption list:\n"); - dump_corruptions(fff, FALSE); - } + dump_corruptions(fff, FALSE, TRUE); /* Dump skills */ dump_skills(fff); diff --git a/src/init2.c b/src/init2.c index 222293c4..015a1c0f 100644 --- a/src/init2.c +++ b/src/init2.c @@ -4,6 +4,7 @@ #include "angband.h" +#include /* * This file is used to initialise various variables and arrays for the @@ -2159,13 +2160,6 @@ void init_schools(s16b new_size) max_schools = new_size; } -void init_corruptions(s16b new_size) -{ - /* allocate the extra memory */ - C_MAKE(p_ptr->corruptions, new_size, bool_); - max_corruptions = new_size; -} - /* * Initialise some other arrays */ diff --git a/src/loadsave.c b/src/loadsave.c index 287eabd8..74b5112c 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -577,17 +577,20 @@ static bool_ do_extra(int flag) do_s16b(&p_ptr->chaos_patron, flag); - if (flag == LS_SAVE) tmp16s = max_corruptions; + if ((flag == LS_SAVE)) { tmp16s = CORRUPTIONS_MAX; } do_s16b(&tmp16s, flag); + if (tmp16s > CORRUPTIONS_MAX) { + quit("Too many corruptions"); + } for (i = 0; i < tmp16s; i++) { - if ((flag == LS_SAVE) && (i < max_corruptions)) + if ((flag == LS_SAVE)) tmp8u = p_ptr->corruptions[i]; do_byte(&tmp8u, flag); - if ((flag == LS_LOAD) && (i < max_corruptions)) + if ((flag == LS_LOAD)) p_ptr->corruptions[i] = tmp8u; } diff --git a/src/lua_bind.c b/src/lua_bind.c index 1add61e3..df335dd3 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -586,173 +586,7 @@ void lua_display_list(int y, int x, int h, int w, cptr title, list_type* list, i display_list(y, x, h, w, title, list->list, max, begin, sel, sel_color); } -/* - * Corruptions - */ -bool_ player_has_corruption(int corruption_idx) -{ - if (corruption_idx < 0) - { - return FALSE; - } - - - - return (p_ptr->corruptions[corruption_idx]); -} - -bool_ player_can_gain_corruption(int corruption_idx) -{ - cptr r_name = rp_ptr->title + rp_name; - bool_ allowed = TRUE; /* Allowed by default */ - - assert(corruption_idx >= 0); - - if (corruption_idx == CORRUPT_TROLL_BLOOD) - { - /* Ok trolls should not get this one. never. */ - if (streq(r_name, "Troll")) - { - allowed = FALSE; - } - } - - /* Theme module adds additional restrictions for Maiar */ - - if (game_module_idx == MODULE_THEME) - { - if (streq(r_name, "Maia")) - { - /* We use a whitelist of corruptions for Maiar */ - bool_ allow = FALSE; - if ((corruption_idx == CORRUPT_BALROG_AURA) || - (corruption_idx == CORRUPT_BALROG_WINGS) || - (corruption_idx == CORRUPT_BALROG_STRENGTH) || - (corruption_idx == CORRUPT_BALROG_FORM) || - (corruption_idx == CORRUPT_DEMON_BREATH)) - { - allow = TRUE; - }; - - /* Mix result into 'allowed' flag */ - allowed = allowed & allow; - } - } - - /* Result */ - return allowed; -} - -static void subrace_add_power(player_race_mod *rmp_ptr, int power) -{ - int i; - - for (i=0; i<4; i++) - { - if (rmp_ptr->powers[i] == -1) - { - rmp_ptr->powers[i] = power; - return; - } - } -} -static void player_gain_vampire_teeth() -{ - player_race_mod *rmp_ptr = NULL; - - switch_subrace(SUBRACE_SAVE, TRUE); - - rmp_ptr = &race_mod_info[SUBRACE_SAVE]; - subrace_add_power(rmp_ptr, PWR_VAMPIRISM); - rmp_ptr->flags1 = rmp_ptr->flags1 - | PR1_VAMPIRE - | PR1_UNDEAD - | PR1_NO_SUBRACE_CHANGE; -} - -static void player_gain_vampire_strength() -{ - player_race_mod *rmp_ptr = &race_mod_info[SUBRACE_SAVE]; - /* Apply the bonuses/penalities */ - rmp_ptr->r_mhp = rmp_ptr->r_mhp + 1; - rmp_ptr->r_exp = rmp_ptr->r_exp + 100; - - rmp_ptr->r_adj[A_STR + 1] = rmp_ptr->r_adj[A_STR + 1] + 3; - rmp_ptr->r_adj[A_INT + 1] = rmp_ptr->r_adj[A_INT + 1] + 2; - rmp_ptr->r_adj[A_WIS + 1] = rmp_ptr->r_adj[A_WIS + 1] - 3; - rmp_ptr->r_adj[A_DEX + 1] = rmp_ptr->r_adj[A_DEX + 1] - 2; - rmp_ptr->r_adj[A_CON + 1] = rmp_ptr->r_adj[A_CON + 1] + 1; - rmp_ptr->r_adj[A_CHR + 1] = rmp_ptr->r_adj[A_CHR + 1] - 4; - - /* be reborn! */ - do_rebirth(); - cmsg_print(TERM_L_DARK, "You feel death slipping inside."); -} - -static void player_gain_vampire() -{ - player_race_mod *rmp_ptr = &race_mod_info[SUBRACE_SAVE]; - - /* Be a Vampire and be proud of it */ - cptr title = get_subrace_title(SUBRACE_SAVE); - if (streq(title, " ") || streq(title, "Vampire")) - { - title = "Vampire"; - rmp_ptr->place = FALSE; - set_subrace_title(SUBRACE_SAVE, title); - } - else - { - char buf[512]; - sprintf(buf, "Vampire %s", title); - set_subrace_title(SUBRACE_SAVE, buf); - } - - /* Bonus/and .. not bonus :) */ - rmp_ptr->flags1 = rmp_ptr->flags1 | PR1_HURT_LITE; - rmp_ptr->oflags2[2] = rmp_ptr->oflags2[2] - | TR2_RES_POIS - | TR2_RES_NETHER - | TR2_RES_COLD - | TR2_RES_DARK - | TR2_HOLD_LIFE; - rmp_ptr->oflags3[2] = rmp_ptr->oflags3[2] - | TR3_LITE1; -} - -static void player_set_corruption(int c, bool_ set) -{ - p_ptr->corruptions[c] = set; - p_ptr->redraw = p_ptr->redraw | PR_BASIC; - p_ptr->update = p_ptr->update | PU_BONUS | PU_TORCH | PU_BODY | PU_POWERS; - -} - -void player_gain_corruption(int corruption_idx) -{ - player_set_corruption(corruption_idx, TRUE); - - if (corruption_idx == CORRUPT_VAMPIRE_TEETH) - { - player_gain_vampire_teeth(); - } - else if (corruption_idx == CORRUPT_VAMPIRE_STRENGTH) - { - player_gain_vampire_strength(); - } - else if (corruption_idx == CORRUPT_VAMPIRE_VAMPIRE) - { - player_gain_vampire(); - } -} - -void player_lose_corruption(int corruption_idx) -{ - player_set_corruption(corruption_idx, FALSE); - /* Currently no corruptions need - any special handling when lost */ -} /* * Gods diff --git a/src/melee1.c b/src/melee1.c index 4e5d3208..0940f7b4 100644 --- a/src/melee1.c +++ b/src/melee1.c @@ -2877,7 +2877,7 @@ bool_ make_attack_normal(int m_idx, byte divis) { /* Change to resist(but never total protection) */ /* if (magik(3) || (magik(m_ptr->level - (p_ptr->lev / 2)))) - call_lua("gain_corruption", "(s)", "", "Vampire");*/ + gain_corruption("Vampire");*/ } if (explode) diff --git a/src/player.pkg b/src/player.pkg index ad01e9eb..fd7754fc 100644 --- a/src/player.pkg +++ b/src/player.pkg @@ -1793,10 +1793,6 @@ struct player_type byte spellbinder_trigger; /* Corruptions */ - /** @structvar corruptions_aux; - * @brief Boolean - */ - bool corruptions[max_corruptions] @ corruptions_aux; bool corrupt_anti_teleport_stopped; /* Astral */ @@ -1818,44 +1814,44 @@ struct player_type /** * Corruptions */ -extern s16b CORRUPT_BALROG_AURA; -extern s16b CORRUPT_BALROG_WINGS; -extern s16b CORRUPT_BALROG_STRENGTH; -extern s16b CORRUPT_BALROG_FORM; -extern s16b CORRUPT_DEMON_SPIRIT; -extern s16b CORRUPT_DEMON_HIDE; -extern s16b CORRUPT_DEMON_BREATH; -extern s16b CORRUPT_DEMON_REALM; -extern s16b CORRUPT_RANDOM_TELEPORT; -extern s16b CORRUPT_ANTI_TELEPORT; -extern s16b CORRUPT_TROLL_BLOOD; -extern s16b CORRUPT_VAMPIRE_TEETH; -extern s16b CORRUPT_VAMPIRE_STRENGTH; -extern s16b CORRUPT_VAMPIRE_VAMPIRE; -extern s16b MUT1_SPIT_ACID; -extern s16b MUT1_BR_FIRE; -extern s16b MUT1_HYPN_GAZE; -extern s16b MUT1_TELEKINES; -extern s16b MUT1_VTELEPORT; -extern s16b MUT1_MIND_BLST; -extern s16b MUT1_VAMPIRISM; -extern s16b MUT1_SMELL_MET; -extern s16b MUT1_SMELL_MON; -extern s16b MUT1_BLINK; -extern s16b MUT1_EAT_ROCK; -extern s16b MUT1_SWAP_POS; -extern s16b MUT1_SHRIEK; -extern s16b MUT1_ILLUMINE; -extern s16b MUT1_DET_CURSE; -extern s16b MUT1_BERSERK; -extern s16b MUT1_MIDAS_TCH; -extern s16b MUT1_GROW_MOLD; -extern s16b MUT1_RESIST; -extern s16b MUT1_EARTHQUAKE; - -extern bool player_can_gain_corruption(int corruption_idx); +#define CORRUPT_BALROG_AURA 0 +#define CORRUPT_BALROG_WINGS 1 +#define CORRUPT_BALROG_STRENGTH 2 +#define CORRUPT_BALROG_FORM 3 +#define CORRUPT_DEMON_SPIRIT 4 +#define CORRUPT_DEMON_HIDE 5 +#define CORRUPT_DEMON_BREATH 6 +#define CORRUPT_DEMON_REALM 7 +#define CORRUPT_RANDOM_TELEPORT 8 +#define CORRUPT_ANTI_TELEPORT 9 +#define CORRUPT_TROLL_BLOOD 10 +#define CORRUPT_VAMPIRE_TEETH 11 +#define CORRUPT_VAMPIRE_STRENGTH 12 +#define CORRUPT_VAMPIRE_VAMPIRE 13 +#define MUT1_SPIT_ACID 14 +#define MUT1_BR_FIRE 15 +#define MUT1_HYPN_GAZE 16 +#define MUT1_TELEKINES 17 +#define MUT1_VTELEPORT 18 +#define MUT1_MIND_BLST 19 +#define MUT1_VAMPIRISM 20 +#define MUT1_SMELL_MET 21 +#define MUT1_SMELL_MON 22 +#define MUT1_BLINK 23 +#define MUT1_EAT_ROCK 24 +#define MUT1_SWAP_POS 25 +#define MUT1_SHRIEK 26 +#define MUT1_ILLUMINE 27 +#define MUT1_DET_CURSE 28 +#define MUT1_BERSERK 29 +#define MUT1_MIDAS_TCH 30 +#define MUT1_GROW_MOLD 31 +#define MUT1_RESIST 32 +#define MUT1_EARTHQUAKE 33 +#define CORRUPTIONS_MAX 34 + +extern bool player_has_corruption(int corruption_idx); extern void player_gain_corruption(int corruption_idx); -extern void player_lose_corruption(int corruption_idx); /** @name Spellbinder triggers * @{ */ diff --git a/src/script.c b/src/script.c index 89c9ff3b..a5aba3fb 100644 --- a/src/script.c +++ b/src/script.c @@ -245,8 +245,7 @@ void init_lua_init() } /* Finish up the corruptions */ - max = exec_lua("return __corruptions_max"); - init_corruptions(max); + init_corruptions(); } bool_ tome_dofile(char *file) diff --git a/src/tables.c b/src/tables.c index e7a81f11..d0dbb9b7 100644 --- a/src/tables.c +++ b/src/tables.c @@ -4850,3 +4850,4 @@ module_type modules[MAX_MODULES] = } }; + diff --git a/src/types.h b/src/types.h index de90a019..cd08476a 100644 --- a/src/types.h +++ b/src/types.h @@ -1807,7 +1807,7 @@ struct player_type u32b xtra_esp; /* Corruptions */ - bool_ *corruptions; + bool_ corruptions[CORRUPTIONS_MAX]; bool_ corrupt_anti_teleport_stopped; /*** Pet commands ***/ @@ -2583,3 +2583,21 @@ struct module_type } skills; }; + +/** + * Corruptions + */ +typedef struct corruption_type corruption_type; +struct corruption_type +{ + int modules[3]; /* Modules where this corruption is available; terminated with -1 entry */ + byte color; + cptr group; + cptr name; + cptr get_text; + cptr lose_text; /* If NULL, the corruption is NOT removable by any means */ + cptr desc; + s16b depends[5]; /* terminated by a -1 entry */ + s16b opposes[5]; /* terminated by a -1 entry */ + void (*gain_callback)(); /* callback to invoke when gained */ +}; diff --git a/src/variable.c b/src/variable.c index b73a1edf..f775df66 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1541,11 +1541,6 @@ int cli_total = 0; */ int max_bact = 56; -/* - * Max corruptions - */ -s16b max_corruptions = 0; - /* * Ingame contextual help */ @@ -1597,44 +1592,6 @@ timer_type *gl_timers = NULL; */ s16b tim_precognition = 0; -/** - * Corruptions - */ -s16b CORRUPT_BALROG_AURA = -1; -s16b CORRUPT_BALROG_WINGS = -1; -s16b CORRUPT_BALROG_STRENGTH = -1; -s16b CORRUPT_BALROG_FORM = -1; -s16b CORRUPT_DEMON_SPIRIT = -1; -s16b CORRUPT_DEMON_HIDE = -1; -s16b CORRUPT_DEMON_BREATH = -1; -s16b CORRUPT_DEMON_REALM = -1; -s16b CORRUPT_RANDOM_TELEPORT = -1; -s16b CORRUPT_ANTI_TELEPORT = -1; -s16b CORRUPT_TROLL_BLOOD = -1; -s16b CORRUPT_VAMPIRE_TEETH = -1; -s16b CORRUPT_VAMPIRE_STRENGTH = -1; -s16b CORRUPT_VAMPIRE_VAMPIRE = -1; -s16b MUT1_SPIT_ACID = -1; -s16b MUT1_BR_FIRE = -1; -s16b MUT1_HYPN_GAZE = -1; -s16b MUT1_TELEKINES = -1; -s16b MUT1_VTELEPORT = -1; -s16b MUT1_MIND_BLST = -1; -s16b MUT1_VAMPIRISM = -1; -s16b MUT1_SMELL_MET = -1; -s16b MUT1_SMELL_MON = -1; -s16b MUT1_BLINK = -1; -s16b MUT1_EAT_ROCK = -1; -s16b MUT1_SWAP_POS = -1; -s16b MUT1_SHRIEK = -1; -s16b MUT1_ILLUMINE = -1; -s16b MUT1_DET_CURSE = -1; -s16b MUT1_BERSERK = -1; -s16b MUT1_MIDAS_TCH = -1; -s16b MUT1_GROW_MOLD = -1; -s16b MUT1_RESIST = -1; -s16b MUT1_EARTHQUAKE = -1; - /* * Powers diff --git a/src/wizard2.c b/src/wizard2.c index a19b72e0..5e1e38d1 100644 --- a/src/wizard2.c +++ b/src/wizard2.c @@ -1758,7 +1758,7 @@ void do_cmd_debug(void) /* corruption */ case 'M': - (void) gain_random_corruption(command_arg); + gain_random_corruption(); break; /* Specific reward */ diff --git a/src/xtra2.c b/src/xtra2.c index 1a6ec3a0..a3ae9881 100644 --- a/src/xtra2.c +++ b/src/xtra2.c @@ -12,6 +12,7 @@ */ #include "angband.h" +#include /* * Invoke The Rush @@ -5147,7 +5148,7 @@ void gain_level_reward(int chosen_reward) { msg_format("%^s rewards you with a corruption!", chaos_patrons[p_ptr->chaos_patron]); - (void)gain_random_corruption(0); + gain_random_corruption(); return; } @@ -5600,19 +5601,6 @@ bool_ tgt_pt(int *x, int *y) return success; } - -bool_ gain_random_corruption(int choose_mut) -{ - exec_lua("gain_corruption()"); - return (FALSE); -} - -bool_ lose_corruption(int choose_mut) -{ - exec_lua("lose_corruption()"); - return (FALSE); -} - bool_ get_hack_dir(int *dp) { int dir; @@ -5709,51 +5697,6 @@ bool_ get_hack_dir(int *dp) return (TRUE); } -/* - * Do we have at least one corruption? - */ -bool_ got_corruptions() -{ - int i, max; - - max = exec_lua("return __corruptions_max"); - - for (i = 0; i < max; i++) - { - if (exec_lua(format("if test_depend_corrupt(%d) == TRUE then return TRUE else return FALSE end", i))) - { - return TRUE; - } - } - return FALSE; -} - -/* - * Dump the corruption list - */ -void dump_corruptions(FILE *fff, bool_ color) -{ - int i, max; - - if (!fff) return; - - max = exec_lua("return __corruptions_max"); - - for (i = 0; i < max; i++) - { - if (exec_lua(format("if test_depend_corrupt(%d) == TRUE then return TRUE else return FALSE end", i))) - { - int c = exec_lua(format("return __corruptions[%d].color", i)); - - if (color) - fprintf(fff, "#####%c%s:\n", conv_color[c], string_exec_lua(format("return __corruptions[%d].name", i))); - else - fprintf(fff, "%s:\n", string_exec_lua(format("return __corruptions[%d].name", i))); - fprintf(fff, "%s\n", string_exec_lua(format("return __corruptions[%d].desc", i))); - } - } -} - /* * Set "p_ptr->grace", notice observable changes */ @@ -6048,11 +5991,11 @@ void corrupt_corrupted(void) { if (magik(45)) { - lose_corruption(0); + lose_corruption(); } else { - gain_random_corruption(0); + gain_random_corruption(); } /* We are done. */ -- cgit v1.2.3 From 203d42e75a02c68d7cda9ff85023910bd1a0a6f4 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 7 Apr 2012 15:45:47 +0200 Subject: Lua: Refactor Lua-based powers into C --- lib/mods/theme/scpt/init.lua | 3 --- lib/mods/theme/scpt/powers.lua | 59 ------------------------------------------ lib/scpt/init.lua | 3 --- lib/scpt/powers.lua | 59 ------------------------------------------ src/defines.h | 5 +++- src/externs.h | 3 --- src/player.pkg | 6 ++--- src/powers.c | 25 ++++++++++++++++++ src/spells.pkg | 14 ---------- src/tables.c | 21 +++++++++++++++ src/variable.c | 8 ------ 11 files changed, 53 insertions(+), 153 deletions(-) delete mode 100644 lib/mods/theme/scpt/powers.lua delete mode 100644 lib/scpt/powers.lua diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index b70fb773..7a229abd 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -11,9 +11,6 @@ tome_dofile("help.lua") -- let the store specific stuff happen! tome_dofile("stores.lua") --- Add various 'U' powers -tome_dofile("powers.lua") - -- Add the mimic shapes tome_dofile("mimic.lua") diff --git a/lib/mods/theme/scpt/powers.lua b/lib/mods/theme/scpt/powers.lua deleted file mode 100644 index 90d69ac7..00000000 --- a/lib/mods/theme/scpt/powers.lua +++ /dev/null @@ -1,59 +0,0 @@ --- Various 'U' powers - --- Invisibility power, for the mouse mimic shape -POWER_INVISIBILITY = add_power -{ - ["name"] = "invisibility", - ["desc"] = "You are able melt into the shadows to become invisible.", - ["desc_get"] = "You suddenly become able to melt into the shadows.", - ["desc_lose"] = "You lose your shadow-melting ability.", - ["level"] = 30, - ["cost"] = 10, - ["stat"] = A_DEX, - ["fail"] = 20, - ["power"] = function() - set_invis(20 + randint(30), 30) - end, -} - --- Web power, for the spider mimic shape -POWER_WEB = add_power -{ - ["name"] = "web", - ["desc"] = "You are able throw a thick and very resistant spider web.", - ["desc_get"] = "You suddenly become able to weave webs.", - ["desc_lose"] = "You lose your web-weaving capability.", - ["level"] = 25, - ["cost"] = 30, - ["stat"] = A_DEX, - ["fail"] = 20, - ["power"] = function() - -- Warning, beware of f_info changes .. I hate to do that .. - grow_things(16, 1 + (player.lev / 10)) - end, -} - --- Activating/stopping space-continuum --- When stopped it will induce constant mana loss -POWER_COR_SPACE_TIME = add_power -{ - ["name"] = "control space/time continuum", - ["desc"] = "You are able to control the space/time continuum.", - ["desc_get"] = "You become able to control the space/time continuum.", - ["desc_lose"] = "You are no more able to control the space/time continuum.", - ["level"] = 1, - ["cost"] = 10, - ["stat"] = A_WIS, - ["fail"] = 10, - ["power"] = function() - if player.corrupt_anti_teleport_stopped == TRUE then - player.corrupt_anti_teleport_stopped = FALSE - msg_print("You stop controlling your corruption.") - player.update = bor(player.update, PU_BONUS) - else - player.corrupt_anti_teleport_stopped = TRUE - msg_print("You start controlling your corruption, teleportation works once more.") - player.update = bor(player.update, PU_BONUS) - end - end, -} diff --git a/lib/scpt/init.lua b/lib/scpt/init.lua index ea42f927..d0512c76 100644 --- a/lib/scpt/init.lua +++ b/lib/scpt/init.lua @@ -11,9 +11,6 @@ tome_dofile("help.lua") -- let the store specific stuff happen! tome_dofile("stores.lua") --- Add various 'U' powers -tome_dofile("powers.lua") - -- Add the mimic shapes tome_dofile("mimic.lua") diff --git a/lib/scpt/powers.lua b/lib/scpt/powers.lua deleted file mode 100644 index 90d69ac7..00000000 --- a/lib/scpt/powers.lua +++ /dev/null @@ -1,59 +0,0 @@ --- Various 'U' powers - --- Invisibility power, for the mouse mimic shape -POWER_INVISIBILITY = add_power -{ - ["name"] = "invisibility", - ["desc"] = "You are able melt into the shadows to become invisible.", - ["desc_get"] = "You suddenly become able to melt into the shadows.", - ["desc_lose"] = "You lose your shadow-melting ability.", - ["level"] = 30, - ["cost"] = 10, - ["stat"] = A_DEX, - ["fail"] = 20, - ["power"] = function() - set_invis(20 + randint(30), 30) - end, -} - --- Web power, for the spider mimic shape -POWER_WEB = add_power -{ - ["name"] = "web", - ["desc"] = "You are able throw a thick and very resistant spider web.", - ["desc_get"] = "You suddenly become able to weave webs.", - ["desc_lose"] = "You lose your web-weaving capability.", - ["level"] = 25, - ["cost"] = 30, - ["stat"] = A_DEX, - ["fail"] = 20, - ["power"] = function() - -- Warning, beware of f_info changes .. I hate to do that .. - grow_things(16, 1 + (player.lev / 10)) - end, -} - --- Activating/stopping space-continuum --- When stopped it will induce constant mana loss -POWER_COR_SPACE_TIME = add_power -{ - ["name"] = "control space/time continuum", - ["desc"] = "You are able to control the space/time continuum.", - ["desc_get"] = "You become able to control the space/time continuum.", - ["desc_lose"] = "You are no more able to control the space/time continuum.", - ["level"] = 1, - ["cost"] = 10, - ["stat"] = A_WIS, - ["fail"] = 10, - ["power"] = function() - if player.corrupt_anti_teleport_stopped == TRUE then - player.corrupt_anti_teleport_stopped = FALSE - msg_print("You stop controlling your corruption.") - player.update = bor(player.update, PU_BONUS) - else - player.corrupt_anti_teleport_stopped = TRUE - msg_print("You start controlling your corruption, teleportation works once more.") - player.update = bor(player.update, PU_BONUS) - end - end, -} diff --git a/src/defines.h b/src/defines.h index b590edc5..95c8eff5 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4301,7 +4301,7 @@ /* * Powers (mutation, activations, ...) */ -#define POWER_MAX_INIT 62 +#define POWER_MAX_INIT 65 #define PWR_SPIT_ACID 0 #define PWR_BR_FIRE 1 @@ -4366,6 +4366,9 @@ #define PWR_BEAR 59 #define PWR_DODGE 60 #define PWR_BALROG 61 +#define POWER_INVISIBILITY 62 +#define POWER_WEB 63 +#define POWER_COR_SPACE_TIME 64 #define ADD_POWER(pow, p) ((pow)[(p)] = TRUE) diff --git a/src/externs.h b/src/externs.h index c82eee41..c400d76f 100644 --- a/src/externs.h +++ b/src/externs.h @@ -603,9 +603,6 @@ extern s32b max_gods; extern timer_type *gl_timers; extern s16b tim_precognition; extern const char *get_version_string(); -extern s16b POWER_INVISIBILITY; -extern s16b POWER_WEB; -extern s16b POWER_COR_SPACE_TIME; /* plots.c */ extern FILE *hook_file; diff --git a/src/player.pkg b/src/player.pkg index fd7754fc..e5d64cbc 100644 --- a/src/player.pkg +++ b/src/player.pkg @@ -3427,9 +3427,9 @@ extern void desc_god(int g_idx, int d, char *desc); #define PWR_BALROG 61 /** @} */ -extern s16b POWER_INVISIBILITY; -extern s16b POWER_WEB; -extern s16b POWER_COR_SPACE_TIME; +#define POWER_INVISIBILITY 62 +#define POWER_WEB 63 +#define POWER_COR_SPACE_TIME 64 /* Misc */ diff --git a/src/powers.c b/src/powers.c index 12b2c2c0..2f0206aa 100644 --- a/src/powers.c +++ b/src/powers.c @@ -1221,7 +1221,32 @@ static void power_activate(int power) use_ability_blade(); break; + case POWER_INVISIBILITY: + set_invis(20 + randint(30), 30); + break; + + case POWER_WEB: + /* Warning, beware of f_info changes .. I hate to do that .. */ + grow_things(16, 1 + (p_ptr->lev / 10)); + break; + + case POWER_COR_SPACE_TIME: + if (p_ptr->corrupt_anti_teleport_stopped) + { + p_ptr->corrupt_anti_teleport_stopped = FALSE; + msg_print("You stop controlling your corruption."); + p_ptr->update |= PU_BONUS; + } + else + { + p_ptr->corrupt_anti_teleport_stopped = TRUE; + msg_print("You start controlling your corruption, teleportation works once more."); + p_ptr->update |= PU_BONUS; + } + break; + default: + if (!process_hooks(HOOK_ACTIVATE_POWER, "(d)", power)) { msg_format("Warning power_activate() called with invalid power(%d).", power); diff --git a/src/spells.pkg b/src/spells.pkg index 77a1794e..c972a814 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -754,20 +754,6 @@ extern bool project(int who, int rad, int y, int x, int dam, int typ, int flg); */ extern void corrupt_player(void); -/** @fn grow_things(s16b type, int rad) - * @brief Grow "type" things within "rad" distance of the player.\n - * @param type Number \n type of thing to grow (FEAT field). - * @brief Type - * @param rad Number \n rad is the radius of the area where things may grow. - * @brief Radius - * @note - * Grow things\n\n - * Up to (rad * (rad + 11)) things can be grown around the player. The - * grids must support growth. - * @note (see file spells2.c) - */ -extern void grow_things(s16b type, int rad); - /** @fn grow_grass(int rad) * @brief Grow grass within "rad" distance of the player.\n * @param rad Number \n rad is the radius of the area where grass may grow. diff --git a/src/tables.c b/src/tables.c index d0dbb9b7..3df97271 100644 --- a/src/tables.c +++ b/src/tables.c @@ -3571,6 +3571,27 @@ power_type powers_type_init[POWER_MAX_INIT] = "You no longer feel the fire of Udun in you.", 35, 80, A_WIS, 25, }, + { + "invisibility", + "You are able melt into the shadows to become invisible.", + "You suddenly become able to melt into the shadows.", + "You lose your shadow-melting ability.", + 30, 10, A_DEX, 20, + }, + { + "web", + "You are able throw a thick and very resistant spider web.", + "You suddenly become able to weave webs.", + "You lose your web-weaving capability.", + 25, 30, A_DEX, 20, + }, + { + "control space/time continuum", + "You are able to control the space/time continuum.", + "You become able to control the space/time continuum.", + "You are no more able to control the space/time continuum.", + 1, 10, A_WIS, 10, + }, }; /* diff --git a/src/variable.c b/src/variable.c index f775df66..8ad1d14f 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1593,14 +1593,6 @@ timer_type *gl_timers = NULL; s16b tim_precognition = 0; -/* - * Powers - */ -s16b POWER_INVISIBILITY = -1; -s16b POWER_WEB = -1; -s16b POWER_COR_SPACE_TIME = -1; - - /** * Get the version string. */ -- cgit v1.2.3 From 838246d8d5d9febf38452f82692b25d7dc092ef3 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 7 Apr 2012 15:56:19 +0200 Subject: Lua: Remove add_new_power() Lua function --- lib/core/player.lua | 32 -------------------------------- lib/mods/theme/core/player.lua | 32 -------------------------------- src/lua_bind.c | 27 --------------------------- src/spells.pkg | 31 ------------------------------- 4 files changed, 122 deletions(-) diff --git a/lib/core/player.lua b/lib/core/player.lua index 03e9824f..e194b45a 100644 --- a/lib/core/player.lua +++ b/lib/core/player.lua @@ -60,38 +60,6 @@ function player.get_wild_coord() end end --- Create a new power -__power_fct = {} -function add_power(p) - local i - - assert(p.name, "No power name!") - assert(p.desc, "No power desc!") - assert(p.desc_get, "No power desc get!") - assert(p.desc_lose, "No power desc lose!") - assert(p.stat, "No power stat!") - assert(p.level, "No power level!") - assert(p.cost, "No power cost!") - assert(p.fail, "No power fail!") - assert(p.power, "No power power!") - - i = add_new_power(p.name, p.desc, p.desc_get, p.desc_lose, p.level, p.cost, p.stat, p.fail) - __power_fct[i] = p.power - return i -end - -function __power_fct_activate(power) - if __power_fct[power] then - __power_fct[power]() - return TRUE - else - return FALSE - end -end - --- Register in the hook list -add_hook_script(HOOK_ACTIVATE_POWER, "__power_fct_activate", "__power_fct_activate") - --- Mkeys diff --git a/lib/mods/theme/core/player.lua b/lib/mods/theme/core/player.lua index 03e9824f..e194b45a 100644 --- a/lib/mods/theme/core/player.lua +++ b/lib/mods/theme/core/player.lua @@ -60,38 +60,6 @@ function player.get_wild_coord() end end --- Create a new power -__power_fct = {} -function add_power(p) - local i - - assert(p.name, "No power name!") - assert(p.desc, "No power desc!") - assert(p.desc_get, "No power desc get!") - assert(p.desc_lose, "No power desc lose!") - assert(p.stat, "No power stat!") - assert(p.level, "No power level!") - assert(p.cost, "No power cost!") - assert(p.fail, "No power fail!") - assert(p.power, "No power power!") - - i = add_new_power(p.name, p.desc, p.desc_get, p.desc_lose, p.level, p.cost, p.stat, p.fail) - __power_fct[i] = p.power - return i -end - -function __power_fct_activate(power) - if __power_fct[power] then - __power_fct[power]() - return TRUE - else - return FALSE - end -end - --- Register in the hook list -add_hook_script(HOOK_ACTIVATE_POWER, "__power_fct_activate", "__power_fct_activate") - --- Mkeys diff --git a/src/lua_bind.c b/src/lua_bind.c index df335dd3..fa88a7c1 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -77,33 +77,6 @@ void end_object(object_type *o_ptr) FREE(o_ptr, object_type); } -/* - * Powers - */ -s16b add_new_power(cptr name, cptr desc, cptr gain, cptr lose, byte level, byte cost, byte stat, byte diff) -{ - /* Increase the size */ - reinit_powers_type(power_max + 1); - - /* Copy the strings */ - C_MAKE(powers_type[power_max - 1].name, strlen(name) + 1, char); - strcpy(powers_type[power_max - 1].name, name); - C_MAKE(powers_type[power_max - 1].desc_text, strlen(desc) + 1, char); - strcpy(powers_type[power_max - 1].desc_text, desc); - C_MAKE(powers_type[power_max - 1].gain_text, strlen(gain) + 1, char); - strcpy(powers_type[power_max - 1].gain_text, gain); - C_MAKE(powers_type[power_max - 1].lose_text, strlen(lose) + 1, char); - strcpy(powers_type[power_max - 1].lose_text, lose); - - /* Copy the other stuff */ - powers_type[power_max - 1].level = level; - powers_type[power_max - 1].cost = cost; - powers_type[power_max - 1].stat = stat; - powers_type[power_max - 1].diff = diff; - - return (power_max - 1); -} - static char *lua_item_tester_fct; static bool_ lua_item_tester(object_type* o_ptr) { diff --git a/src/spells.pkg b/src/spells.pkg index c972a814..041959d6 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2163,37 +2163,6 @@ extern magic_power *grab_magic_power @ get_magic_power(magic_power *m_ptr, int n */ extern bool lua_spell_success @ magic_power_sucess(magic_power *spell, int stat, char *oups_fct=NULL); -/** @fn add_new_power(cptr name, cptr desc, cptr gain, cptr lose, byte level, byte cost, byte stat, byte diff) - * @dgonly - * @brief Add a new power to the array of magic powers.\n - * @param name String \n name is the name of the power. - * @brief Name - * @param desc String \n desc is the description of the power. - * @brief Description - * @param gain String \n gain describes the effect when the power starts - * working. - * @brief Gain message - * @param lose String \n loss describes the effect when the power stops - * working. - * @brief Lose message - * @param level Number \n level is the magic skill level a player needs to - * use the power. - * @brief Level - * @param cost Number \n cost is the number of mana points required to use the - * power. - * @brief Mana cost - * @param stat Number \n stat is the required casting statistic (INT or WIS). - * @brief Casting statistic - * @param diff Number \n diff is the difficulty. - * @brief Difficulty - * @return Number \n The index of the new power in the magic power array. - * @note - * Note: do not call this function.\n - * By order of DG. - * @note (see file lua_bind.c) - */ -s16b add_new_power(cptr name, cptr desc, cptr gain, cptr lose, byte level, byte cost, byte stat, byte diff); - /** @var power_max * @brief Number * @note Maximum number of innate powers. -- cgit v1.2.3 From b6c2bf9050a56841bb5a82549fd36a98b03e2f41 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 7 Apr 2012 16:16:17 +0200 Subject: Lua: Remove unnecessary dynamism from "powers" handling --- src/birth.c | 10 +--------- src/defines.h | 2 +- src/externs.h | 5 +---- src/init1.c | 28 ++++++++++++++-------------- src/init2.c | 35 ----------------------------------- src/loadsave.c | 7 +++---- src/player.pkg | 8 ++++---- src/powers.c | 11 ++++------- src/spells.pkg | 6 ------ src/spells2.c | 2 +- src/tables.c | 2 +- src/types.h | 4 ++-- src/variable.c | 6 ------ src/xtra1.c | 13 +++++-------- 14 files changed, 37 insertions(+), 102 deletions(-) diff --git a/src/birth.c b/src/birth.c index f050f9d1..47b806e7 100644 --- a/src/birth.c +++ b/src/birth.c @@ -822,21 +822,13 @@ static void player_wipe(void) { int i, j; - bool_ *powers; - /* Wipe special levels */ wipe_saved(); - /* Save the powers & corruptions */ - powers = p_ptr->powers; - /* Hack -- zero the struct */ p_ptr = WIPE(p_ptr, player_type); - /* Restore the powers & corruptions */ - p_ptr->powers = powers; - /* Not dead yet */ p_ptr->lives = 0; @@ -1039,7 +1031,7 @@ static void player_wipe(void) p_ptr->loan = p_ptr->loan_time = 0; /* Wipe the power list */ - for (i = 0; i < POWER_MAX_INIT; i++) + for (i = 0; i < POWER_MAX; i++) { p_ptr->powers_mod[i] = 0; } diff --git a/src/defines.h b/src/defines.h index 95c8eff5..1e36119f 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4301,7 +4301,7 @@ /* * Powers (mutation, activations, ...) */ -#define POWER_MAX_INIT 65 +#define POWER_MAX 65 #define PWR_SPIT_ACID 0 #define PWR_BR_FIRE 1 diff --git a/src/externs.h b/src/externs.h index c400d76f..1d2a9c79 100644 --- a/src/externs.h +++ b/src/externs.h @@ -84,7 +84,7 @@ extern activation activation_info[MAX_T_ACT]; extern inscription_info_type inscription_info[MAX_INSCRIPTIONS]; extern cptr sense_desc[]; extern flags_group flags_groups[MAX_FLAG_GROUP]; -extern power_type powers_type_init[POWER_MAX_INIT]; +extern power_type powers_type[POWER_MAX]; extern quest_type quest_info[MAX_Q_IDX_INIT]; extern cptr artifact_names_list; extern monster_power monster_powers[96]; @@ -564,8 +564,6 @@ extern u32b dungeon_flags2; extern birther previous_char; extern hist_type *bg; extern int max_bg_idx; -extern power_type *powers_type; -extern s16b power_max; extern s32b extra_savefile_parts; extern s16b max_q_idx; extern quest_type *quest; @@ -978,7 +976,6 @@ extern void init_spells(s16b new_size); extern void init_schools(s16b new_size); extern void reinit_gods(s16b new_size); extern void reinit_quests(s16b new_size); -extern void reinit_powers_type(s16b new_size); extern void create_stores_stock(int t); extern errr init_v_info(void); extern void init_file_paths(char *path); diff --git a/src/init1.c b/src/init1.c index 9715831d..4c7e7035 100644 --- a/src/init1.c +++ b/src/init1.c @@ -2047,12 +2047,12 @@ errr init_player_info_txt(FILE *fp, char *buf) s = buf + 4; /* Find it in the list */ - for (i = 0; i < power_max; i++) + for (i = 0; i < POWER_MAX; i++) { if (!stricmp(s, powers_type[i].name)) break; } - if (i == power_max) return (6); + if (i == POWER_MAX) return (6); rp_ptr->powers[powers++] = i; @@ -2425,12 +2425,12 @@ errr init_player_info_txt(FILE *fp, char *buf) s = buf + 4; /* Find it in the list */ - for (i = 0; i < power_max; i++) + for (i = 0; i < POWER_MAX; i++) { if (!stricmp(s, powers_type[i].name)) break; } - if (i == power_max) return (6); + if (i == POWER_MAX) return (6); rmp_ptr->powers[powers++] = i; @@ -2948,12 +2948,12 @@ errr init_player_info_txt(FILE *fp, char *buf) s = buf + 4; /* Find it in the list */ - for (i = 0; i < power_max; i++) + for (i = 0; i < POWER_MAX; i++) { if (!stricmp(s, powers_type[i].name)) break; } - if (i == power_max) return (6); + if (i == POWER_MAX) return (6); c_ptr->powers[powers++] = i; @@ -4352,12 +4352,12 @@ errr init_k_info_txt(FILE *fp, char *buf) s = buf + 2; /* Find it in the list */ - for (i = 0; i < power_max; i++) + for (i = 0; i < POWER_MAX; i++) { if (!stricmp(s, powers_type[i].name)) break; } - if (i == power_max) return (6); + if (i == POWER_MAX) return (6); k_ptr->power = i; @@ -5238,12 +5238,12 @@ errr init_a_info_txt(FILE *fp, char *buf) s = buf + 2; /* Find it in the list */ - for (i = 0; i < power_max; i++) + for (i = 0; i < POWER_MAX; i++) { if (!stricmp(s, powers_type[i].name)) break; } - if (i == power_max) return (6); + if (i == POWER_MAX) return (6); a_ptr->power = i; @@ -6763,12 +6763,12 @@ errr init_e_info_txt(FILE *fp, char *buf) s = buf + 2; /* Find it in the list */ - for (i = 0; i < power_max; i++) + for (i = 0; i < POWER_MAX; i++) { if (!stricmp(s, powers_type[i].name)) break; } - if (i == power_max) return (6); + if (i == POWER_MAX) return (6); e_ptr->power = i; @@ -7252,12 +7252,12 @@ errr init_ra_info_txt(FILE *fp, char *buf) s = buf + 2; /* Find it in the list */ - for (i = 0; i < power_max; i++) + for (i = 0; i < POWER_MAX; i++) { if (!stricmp(s, powers_type[i].name)) break; } - if (i == power_max) return (6); + if (i == POWER_MAX) return (6); ra_ptr->power = i; diff --git a/src/init2.c b/src/init2.c index 015a1c0f..8a20cfb3 100644 --- a/src/init2.c +++ b/src/init2.c @@ -1959,13 +1959,6 @@ static errr init_misc(void) /* Hack -- No messages yet */ message__tail = MESSAGE_BUF; - /* Prepare powers */ - p_ptr->powers = NULL; - powers_type = NULL; - power_max = POWER_MAX_INIT; - reinit_powers_type(power_max); - C_COPY(powers_type, powers_type_init, POWER_MAX_INIT, power_type); - /* Prepare quests */ quest = NULL; max_q_idx = MAX_Q_IDX_INIT; @@ -2080,34 +2073,6 @@ static errr init_wilderness(void) return 0; } -/* - * XXX XXX XXX XXX XXX Realloc is not guaranteed to work (see main-gtk.c - * and main-mac.c. - */ -void reinit_powers_type(s16b new_size) -{ - power_type *new_powers_type; - bool_ *new_powers; - - C_MAKE(new_powers_type, new_size, power_type); - C_MAKE(new_powers, new_size, bool_); - - /* Reallocate the extra memory */ - if (powers_type && p_ptr->powers) - { - C_COPY(new_powers_type, powers_type, power_max, power_type); - C_COPY(new_powers, p_ptr->powers, power_max, bool_); - - C_FREE(powers_type, power_max, power_type); - C_FREE(p_ptr->powers, power_max, bool_); - } - - powers_type = new_powers_type; - p_ptr->powers = new_powers; - - power_max = new_size; -} - void reinit_quests(s16b new_size) { quest_type *new_quest; diff --git a/src/loadsave.c b/src/loadsave.c index 74b5112c..56ebfaa9 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -637,12 +637,11 @@ static bool_ do_extra(int flag) /* Are we in astral mode? */ do_byte((byte*)&p_ptr->astral, flag); - if (flag == LS_SAVE) tmp16s = POWER_MAX_INIT; + if (flag == LS_SAVE) tmp16s = POWER_MAX; do_s16b(&tmp16s, flag); - if ((flag == LS_LOAD) && (tmp16s > POWER_MAX_INIT)) + if ((flag == LS_LOAD) && (tmp16s > POWER_MAX)) note(format("Too many (%u) powers!", tmp16s)); - if (flag == LS_SAVE) tmp16s = POWER_MAX_INIT; - for (i = 0; i < tmp16s; i++) + for (i = 0; i < POWER_MAX; i++) do_byte((byte*)&p_ptr->powers_mod[i], flag); skip_ver_byte(100, flag); diff --git a/src/player.pkg b/src/player.pkg index e5d64cbc..0466b322 100644 --- a/src/player.pkg +++ b/src/player.pkg @@ -1766,15 +1766,15 @@ struct player_type */ byte body_parts[28]; - /** @structvar powers_mod[POWER_MAX_INIT] + /** @structvar powers_mod[POWER_MAX] * @brief Boolean * @note Intrinsinc powers */ - bool powers_mod[POWER_MAX_INIT]; - /** @structvar powers[power_max] + bool powers_mod[POWER_MAX]; + /** @structvar powers[POWER_MAX] * @brief Boolean */ - bool powers[power_max]; + bool powers[POWER_MAX]; /** @structvar spellbinder_num * @brief Number diff --git a/src/powers.c b/src/powers.c index 2f0206aa..613968df 100644 --- a/src/powers.c +++ b/src/powers.c @@ -1297,11 +1297,10 @@ static power_type* select_power(int *x_idx) int max = 0, i, start = 0; power_type* ret; bool_ mode = FALSE; - int *p; + int p[POWER_MAX]; - C_MAKE(p, power_max, int); /* Count the max */ - for (i = 0; i < power_max; i++) + for (i = 0; i < POWER_MAX; i++) { if (p_ptr->powers[i]) { @@ -1375,8 +1374,6 @@ static power_type* select_power(int *x_idx) character_icky = FALSE; } - C_FREE(p, power_max, int); - return ret; } @@ -1390,7 +1387,7 @@ void do_cmd_power() /* Get the skill, if available */ if (repeat_pull(&x_idx)) { - if ((x_idx < 0) || (x_idx >= power_max)) return; + if ((x_idx < 0) || (x_idx >= POWER_MAX)) return; x_ptr = &powers_type[x_idx]; push = FALSE; } @@ -1398,7 +1395,7 @@ void do_cmd_power() else { x_idx = command_arg - 1; - if ((x_idx < 0) || (x_idx >= power_max)) return; + if ((x_idx < 0) || (x_idx >= POWER_MAX)) return; x_ptr = &powers_type[x_idx]; } diff --git a/src/spells.pkg b/src/spells.pkg index 041959d6..6ca95cfc 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2163,12 +2163,6 @@ extern magic_power *grab_magic_power @ get_magic_power(magic_power *m_ptr, int n */ extern bool lua_spell_success @ magic_power_sucess(magic_power *spell, int stat, char *oups_fct=NULL); -/** @var power_max - * @brief Number - * @note Maximum number of innate powers. - */ -extern s16b power_max; - /* Schools */ /** @struct school_spell_type diff --git a/src/spells2.c b/src/spells2.c index 6fb1b1b9..4adab78a 100644 --- a/src/spells2.c +++ b/src/spells2.c @@ -1089,7 +1089,7 @@ void self_knowledge(FILE *fff) } /* List powers */ - for (iter = 0; iter < power_max; iter++) + for (iter = 0; iter < POWER_MAX; iter++) { if (p_ptr->powers[iter]) { diff --git a/src/tables.c b/src/tables.c index 3df97271..b736bb85 100644 --- a/src/tables.c +++ b/src/tables.c @@ -3135,7 +3135,7 @@ flags_group flags_groups[MAX_FLAG_GROUP] = }; /* Powers */ -power_type powers_type_init[POWER_MAX_INIT] = +power_type powers_type[POWER_MAX] = { { "spit acid", diff --git a/src/types.h b/src/types.h index cd08476a..1c9df3f8 100644 --- a/src/types.h +++ b/src/types.h @@ -1827,8 +1827,8 @@ struct player_type bool_ astral; /* We started at the bottom ? */ /* Powers */ - bool_ *powers; /* Actual powers */ - bool_ powers_mod[POWER_MAX_INIT]; /* Intrinsinc powers */ + bool_ powers[POWER_MAX]; /* Actual powers */ + bool_ powers_mod[POWER_MAX]; /* Intrinsinc powers */ /* Skills */ s16b skill_points; diff --git a/src/variable.c b/src/variable.c index 8ad1d14f..52e16e01 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1479,12 +1479,6 @@ birther previous_char; hist_type *bg; int max_bg_idx; -/* - * Powers - */ -s16b power_max = POWER_MAX_INIT; -power_type *powers_type; - /* * Variable savefile stuff */ diff --git a/src/xtra1.c b/src/xtra1.c index 54c079b8..029aa1a5 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -1569,7 +1569,7 @@ bool_ calc_powers_silent = FALSE; static void calc_powers(void) { int i, p = 0; - bool_ *old_powers; + bool_ old_powers[POWER_MAX]; /* Hack -- wait for creation */ if (!character_generated) return; @@ -1577,14 +1577,12 @@ static void calc_powers(void) /* Hack -- handle "xtra" mode */ if (character_xtra) return; - C_MAKE(old_powers, power_max, bool_); - /* Save old powers */ - for (i = 0; i < power_max; i++) old_powers[i] = p_ptr->powers[i]; + for (i = 0; i < POWER_MAX; i++) old_powers[i] = p_ptr->powers[i]; /* Get intrinsincs */ - for (i = 0; i < POWER_MAX_INIT; i++) p_ptr->powers[i] = p_ptr->powers_mod[i]; - for (; i < power_max; i++) p_ptr->powers[i] = 0; + for (i = 0; i < POWER_MAX; i++) p_ptr->powers[i] = p_ptr->powers_mod[i]; + for (; i < POWER_MAX; i++) p_ptr->powers[i] = 0; /* Calculate powers granted by corruptions */ calc_powers_corruption(); @@ -1632,7 +1630,7 @@ static void calc_powers(void) } /* Now lets warn the player */ - for (i = 0; i < power_max; i++) + for (i = 0; i < POWER_MAX; i++) { s32b old = old_powers[i]; s32b new_ = p_ptr->powers[i]; @@ -1648,7 +1646,6 @@ static void calc_powers(void) } calc_powers_silent = FALSE; - C_FREE(old_powers, power_max, bool_); } -- cgit v1.2.3 From 23ead090b5c135702eb8b178d8c74cb347815c29 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 7 Apr 2012 17:45:24 +0200 Subject: Lua: Generalize handling of powers granted by corruptions. --- src/corrupt.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/externs.h | 1 + src/types.h | 1 + src/xtra1.c | 36 +++++++----------------------------- 4 files changed, 66 insertions(+), 29 deletions(-) diff --git a/src/corrupt.c b/src/corrupt.c index 25570303..9c707a67 100644 --- a/src/corrupt.c +++ b/src/corrupt.c @@ -104,6 +104,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + -1, }, { /* 1 */ @@ -118,6 +119,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + -1, }, { /* 2 */ @@ -132,6 +134,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + -1, }, { /* 3 */ @@ -146,6 +149,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { CORRUPT_BALROG_AURA, CORRUPT_BALROG_WINGS, CORRUPT_BALROG_STRENGTH }, { -1 }, NULL, + PWR_BALROG, }, /* @@ -163,6 +167,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + -1, }, { /* 5 */ @@ -178,6 +183,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + -1, }, { /* 6 */ @@ -192,6 +198,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_BR_FIRE, }, { /* 7 */ @@ -206,6 +213,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { CORRUPT_DEMON_SPIRIT, CORRUPT_DEMON_HIDE, CORRUPT_DEMON_BREATH }, { -1 }, NULL, + -1, }, /* @@ -223,6 +231,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { CORRUPT_ANTI_TELEPORT, -1 }, NULL, + -1, }, { /* 9 */ @@ -236,6 +245,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { CORRUPT_RANDOM_TELEPORT, -1 }, NULL, + POWER_COR_SPACE_TIME, }, /* @@ -255,6 +265,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + -1, }, /* @@ -273,6 +284,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, player_gain_vampire_teeth, + -1, }, { /* 12 */ @@ -288,6 +300,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { CORRUPT_VAMPIRE_TEETH, -1 }, { -1 }, player_gain_vampire_strength, + -1, }, { /* 13 */ @@ -302,6 +315,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { CORRUPT_VAMPIRE_STRENGTH, -1 }, { -1 }, player_gain_vampire, + -1, }, /* @@ -321,6 +335,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_SPIT_ACID, }, { /* 15 */ @@ -336,6 +351,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_BR_FIRE, }, { /* 16 */ @@ -351,6 +367,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_HYPN_GAZE, }, { /* 17 */ @@ -366,6 +383,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_TELEKINES, }, { /* 18 */ @@ -381,6 +399,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_VTELEPORT, }, { /* 19 */ @@ -396,6 +415,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_MIND_BLST, }, { /* 20 */ @@ -412,6 +432,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_VAMPIRISM, }, { /* 21 */ @@ -427,6 +448,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_SMELL_MET, }, { /* 22 */ @@ -442,6 +464,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_SMELL_MON, }, { /* 23 */ @@ -456,6 +479,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_BLINK, }, { /* 24 */ @@ -471,6 +495,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_EAT_ROCK, }, { /* 25 */ @@ -486,6 +511,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_SWAP_POS, }, { /* 26 */ @@ -501,6 +527,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_SHRIEK, }, { /* 27 */ @@ -516,6 +543,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_ILLUMINE, }, { /* 28 */ @@ -531,6 +559,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_DET_CURSE, }, { /* 29 */ @@ -546,6 +575,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_BERSERK, }, { /* 30 */ @@ -561,6 +591,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_MIDAS_TCH, }, { /* 31 */ @@ -576,6 +607,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_GROW_MOLD, }, { /* 32 */ @@ -592,6 +624,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_RESIST, }, { /* 33 */ @@ -607,6 +640,7 @@ corruption_type corruptions[CORRUPTIONS_MAX] = { -1 }, { -1 }, NULL, + PWR_EARTHQUAKE, }, }; @@ -914,3 +948,26 @@ void dump_corruptions(FILE *fff, bool_ color, bool_ header) } } +/* + * Get the power granted by a corruption. Returns -1 + * if the given corruption does not grant a power. + */ +s16b get_corruption_power(int corruption_idx) +{ + corruption_type *c_ptr = NULL; + + assert(corruption_idx >= 0); + assert(corruption_idx < CORRUPTIONS_MAX); + + c_ptr = &corruptions[corruption_idx]; + + if ((c_ptr->power >= 0) && (c_ptr->power < POWER_MAX)) + { + return c_ptr->power; + } + else + { + assert(c_ptr->power == -1); /* Sanity check: Should always be the case. */ + return -1; + } +} diff --git a/src/externs.h b/src/externs.h index 1d2a9c79..d53ba409 100644 --- a/src/externs.h +++ b/src/externs.h @@ -873,6 +873,7 @@ extern void dump_corruptions(FILE *OutFile, bool_ color, bool_ header); extern void lose_corruption(); extern bool_ player_has_corruption(int corruption_idx); extern void player_gain_corruption(int corruption_idx); +extern s16b get_corruption_power(int corruption_idx); /* dungeon.c */ extern byte value_check_aux1(object_type *o_ptr); diff --git a/src/types.h b/src/types.h index 1c9df3f8..df2c4f40 100644 --- a/src/types.h +++ b/src/types.h @@ -2600,4 +2600,5 @@ struct corruption_type s16b depends[5]; /* terminated by a -1 entry */ s16b opposes[5]; /* terminated by a -1 entry */ void (*gain_callback)(); /* callback to invoke when gained */ + s16b power; /* index of granted power if >= 0, ignored otherwise */ }; diff --git a/src/xtra1.c b/src/xtra1.c index 029aa1a5..66f5ddd7 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -1523,40 +1523,18 @@ static void calc_spells(void) static void calc_powers_corruption() { /* Map of corruptions to a power */ - s16b power_by_corruption[][2] = - { { CORRUPT_BALROG_FORM , PWR_BALROG }, - { CORRUPT_DEMON_BREATH , PWR_BR_FIRE }, - { CORRUPT_ANTI_TELEPORT , POWER_COR_SPACE_TIME }, - { MUT1_SPIT_ACID , PWR_SPIT_ACID }, - { MUT1_BR_FIRE , PWR_BR_FIRE }, - { MUT1_HYPN_GAZE , PWR_HYPN_GAZE }, - { MUT1_TELEKINES , PWR_TELEKINES }, - { MUT1_VTELEPORT , PWR_VTELEPORT }, - { MUT1_MIND_BLST , PWR_MIND_BLST }, - { MUT1_VAMPIRISM , PWR_VAMPIRISM }, - { MUT1_SMELL_MET , PWR_SMELL_MET }, - { MUT1_SMELL_MON , PWR_SMELL_MON }, - { MUT1_BLINK , PWR_BLINK }, - { MUT1_EAT_ROCK , PWR_EAT_ROCK }, - { MUT1_SWAP_POS , PWR_SWAP_POS }, - { MUT1_SHRIEK , PWR_SHRIEK }, - { MUT1_ILLUMINE , PWR_ILLUMINE }, - { MUT1_DET_CURSE , PWR_DET_CURSE }, - { MUT1_BERSERK , PWR_BERSERK }, - { MUT1_MIDAS_TCH , PWR_MIDAS_TCH }, - { MUT1_GROW_MOLD , PWR_GROW_MOLD }, - { MUT1_RESIST , PWR_RESIST }, - { MUT1_EARTHQUAKE , PWR_EARTHQUAKE }, - { -1 , -1 }, - }; int i; /* Grant powers according to whatever corruptions the player has */ - for (i = 0; power_by_corruption[i][0] >= 0; i++) + for (i = 0; i < CORRUPTIONS_MAX; i++) { - if (player_has_corruption(power_by_corruption[i][0])) + if (player_has_corruption(i)) { - p_ptr->powers[power_by_corruption[i][1]] = TRUE; + int p = get_corruption_power(i); + if (p >= 0) + { + p_ptr->powers[p] = TRUE; + } } } } -- cgit v1.2.3 From 5ea970c82ba3119ca3a5ee68037aee7cdda6dfa3 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 7 Apr 2012 20:47:47 +0200 Subject: Lua: Moved mimicry to C --- lib/core/init.lua | 1 - lib/core/mimc_aux.lua | 96 ------ lib/mods/theme/core/init.lua | 1 - lib/mods/theme/core/mimc_aux.lua | 96 ------ lib/mods/theme/scpt/init.lua | 3 - lib/mods/theme/scpt/mimic.lua | 419 ------------------------ lib/scpt/init.lua | 3 - lib/scpt/mimic.lua | 419 ------------------------ src/CMakeLists.txt | 2 +- src/cmd6.c | 4 +- src/cmd7.c | 2 +- src/defines.h | 1 + src/externs.h | 11 +- src/files.c | 2 +- src/mimic.c | 684 +++++++++++++++++++++++++++++++++++++++ src/object1.c | 4 +- src/object2.c | 8 +- src/randart.c | 3 +- src/types.h | 26 ++ src/util.pkg | 5 + src/xtra1.c | 14 +- src/xtra2.c | 11 - 22 files changed, 739 insertions(+), 1076 deletions(-) delete mode 100644 lib/core/mimc_aux.lua delete mode 100644 lib/mods/theme/core/mimc_aux.lua delete mode 100644 lib/mods/theme/scpt/mimic.lua delete mode 100644 lib/scpt/mimic.lua create mode 100644 src/mimic.c diff --git a/lib/core/init.lua b/lib/core/init.lua index 3db34076..9d0c01a3 100644 --- a/lib/core/init.lua +++ b/lib/core/init.lua @@ -17,7 +17,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "building.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "s_aux.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "mimc_aux.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "quests.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "gods.lua") diff --git a/lib/core/mimc_aux.lua b/lib/core/mimc_aux.lua deleted file mode 100644 index cea1f4dc..00000000 --- a/lib/core/mimc_aux.lua +++ /dev/null @@ -1,96 +0,0 @@ --- Mimic shapes helper file - -__mimics = {} -__mimics_max = 1 -__mimics_names = {} - -function add_mimic_shape(t) - assert(t.name, "no mimic name") - assert(t.desc, "no mimic desc") - assert(t.calc, "no mimic calc") - assert(t.level, "no mimic level") - assert(t.duration, "no mimic duration") - - if not t.limit then t.limit = 0 end - - if not t.obj_name then - t.obj_name = t.name - end - - t.show_name = '['..t.name..']' - - -- if it needs hooks, add them - if t.hooks then - add_hooks(t.hooks) - end - - -- Add it in a name to index hash table - __mimics_names[t.name] = __mimics_max - - __mimics[__mimics_max] = t - __mimics_max = __mimics_max + 1 -end - -function resolve_mimic_name(name) - if __mimics_names[name] then - return __mimics_names[name] - else - return -1 - end -end - -function find_random_mimic_shape(level, limit, realm) - local mimic, tries - - tries = 1000 - while tries > 0 do - tries = tries - 1 - mimic = rand_range(1, __mimics_max - 1) - if (not realm) or (__mimics[mimic].realm == realm) then - if limit >= __mimics[mimic].limit then - if (rand_int(__mimics[mimic].level * 3) < level) and (__mimics[mimic].rarity < 100) and (magik(100 - __mimics[mimic].rarity) == TRUE) then - break - end - end - end - end - if tries > 0 then - return mimic - else - return resolve_mimic_name("Abomination") - end -end - -function get_mimic_info(mimic, info) - if not __mimics[mimic] then return 0 end - return __mimics[mimic][info] -end - -function get_mimic_rand_dur(mimic) - return rand_range(__mimics[mimic].duration[1], __mimics[mimic].duration[2]) -end - -function calc_mimic(mimic) - return __mimics[mimic].calc() -end - -function calc_mimic_power(mimic) - if __mimics[mimic].power then __mimics[mimic].power() end -end - ---- Here comes the only vital shape - -add_mimic_shape -{ - ["name"] = "Abomination", - ["obj_name"] = "Abominable Cloak", - ["desc"] = "Abominations are failed experiments of powerful wizards.", - ["realm"] = nil, - ["level"] = 1, - ["rarity"] = 101, - ["duration"] = {20, 100}, - ["calc"] = function () - apply_flags(TR1_SPEED + TR1_STR + TR1_INT + TR1_WIS + TR1_DEX + TR1_CON + TR1_CHR, 0, 0, 0, 0, 0, -10) - player.xtra_f3 = bor(player.xtra_f3, TR3_AGGRAVATE) - end, -} diff --git a/lib/mods/theme/core/init.lua b/lib/mods/theme/core/init.lua index 3db34076..9d0c01a3 100644 --- a/lib/mods/theme/core/init.lua +++ b/lib/mods/theme/core/init.lua @@ -17,7 +17,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "building.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "s_aux.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "mimc_aux.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "quests.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "gods.lua") diff --git a/lib/mods/theme/core/mimc_aux.lua b/lib/mods/theme/core/mimc_aux.lua deleted file mode 100644 index cea1f4dc..00000000 --- a/lib/mods/theme/core/mimc_aux.lua +++ /dev/null @@ -1,96 +0,0 @@ --- Mimic shapes helper file - -__mimics = {} -__mimics_max = 1 -__mimics_names = {} - -function add_mimic_shape(t) - assert(t.name, "no mimic name") - assert(t.desc, "no mimic desc") - assert(t.calc, "no mimic calc") - assert(t.level, "no mimic level") - assert(t.duration, "no mimic duration") - - if not t.limit then t.limit = 0 end - - if not t.obj_name then - t.obj_name = t.name - end - - t.show_name = '['..t.name..']' - - -- if it needs hooks, add them - if t.hooks then - add_hooks(t.hooks) - end - - -- Add it in a name to index hash table - __mimics_names[t.name] = __mimics_max - - __mimics[__mimics_max] = t - __mimics_max = __mimics_max + 1 -end - -function resolve_mimic_name(name) - if __mimics_names[name] then - return __mimics_names[name] - else - return -1 - end -end - -function find_random_mimic_shape(level, limit, realm) - local mimic, tries - - tries = 1000 - while tries > 0 do - tries = tries - 1 - mimic = rand_range(1, __mimics_max - 1) - if (not realm) or (__mimics[mimic].realm == realm) then - if limit >= __mimics[mimic].limit then - if (rand_int(__mimics[mimic].level * 3) < level) and (__mimics[mimic].rarity < 100) and (magik(100 - __mimics[mimic].rarity) == TRUE) then - break - end - end - end - end - if tries > 0 then - return mimic - else - return resolve_mimic_name("Abomination") - end -end - -function get_mimic_info(mimic, info) - if not __mimics[mimic] then return 0 end - return __mimics[mimic][info] -end - -function get_mimic_rand_dur(mimic) - return rand_range(__mimics[mimic].duration[1], __mimics[mimic].duration[2]) -end - -function calc_mimic(mimic) - return __mimics[mimic].calc() -end - -function calc_mimic_power(mimic) - if __mimics[mimic].power then __mimics[mimic].power() end -end - ---- Here comes the only vital shape - -add_mimic_shape -{ - ["name"] = "Abomination", - ["obj_name"] = "Abominable Cloak", - ["desc"] = "Abominations are failed experiments of powerful wizards.", - ["realm"] = nil, - ["level"] = 1, - ["rarity"] = 101, - ["duration"] = {20, 100}, - ["calc"] = function () - apply_flags(TR1_SPEED + TR1_STR + TR1_INT + TR1_WIS + TR1_DEX + TR1_CON + TR1_CHR, 0, 0, 0, 0, 0, -10) - player.xtra_f3 = bor(player.xtra_f3, TR3_AGGRAVATE) - end, -} diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index 7a229abd..063ca21b 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -11,9 +11,6 @@ tome_dofile("help.lua") -- let the store specific stuff happen! tome_dofile("stores.lua") --- Add the mimic shapes -tome_dofile("mimic.lua") - -- Add the mkey activations tome_dofile("mkeys.lua") diff --git a/lib/mods/theme/scpt/mimic.lua b/lib/mods/theme/scpt/mimic.lua deleted file mode 100644 index f38f70f7..00000000 --- a/lib/mods/theme/scpt/mimic.lua +++ /dev/null @@ -1,419 +0,0 @@ --- Define the various possible mimic shapes - --- Nature shapes -add_mimic_shape -{ - ["name"] = "Mouse", - ["obj_name"] = "Mouse Fur", - ["desc"] = "Mice are small, fast and very stealthy", - ["realm"] = "nature", - ["level"] = 1, - ["rarity"] = 10, - ["duration"] = {20, 40}, - ["calc"] = function () - -- Mice run! - player.pspeed = player.pspeed + 5 + (player.mimic_level / 7) - - -- They can crtawl under your armor to hit you ;) - player.to_h = player.to_h + 10 + (player.mimic_level / 5) - player.dis_to_h = player.dis_to_h + 10 + (player.mimic_level / 5) - - -- But they are not very powerfull - player.to_d = player.to_d / 5 - player.dis_to_d = player.dis_to_d / 5 - - -- But they are stealthy - player.skill_stl = player.skill_stl + 10 + (player.mimic_level / 5) - - -- Stat mods - player.modify_stat(A_STR, -5) - player.modify_stat(A_DEX, 3) - player.modify_stat(A_CON, 1) - - end, - ["power"] = function() - if player.mimic_level >= 30 then - player.add_power(POWER_INVISIBILITY) - end - end, -} - -add_mimic_shape -{ - ["name"] = "Eagle", - ["obj_name"] = "Feathered Cloak", - ["desc"] = "Eagles are master of the air, good hunters with excellent vision.", - ["realm"] = "nature", - ["level"] = 10, - ["rarity"] = 30, - ["duration"] = {10, 50}, - ["calc"] = function () - player.ffall = TRUE - player.pspeed = player.pspeed + 2 + (player.mimic_level / 6) - - player.modify_stat(A_STR, -3) - player.modify_stat(A_DEX, 2 + (player.mimic_level / 15)) - player.modify_stat(A_CON, 4 + (player.mimic_level / 20)) - player.modify_stat(A_INT, -1) - player.modify_stat(A_WIS, 1) - player.modify_stat(A_CHR, -1) - - if player.mimic_level >= 20 then - player.xtra_f4 = bor(player.xtra_f4, TR4_FLY) - player.xtra_f3 = bor(player.xtra_f3, TR3_SEE_INVIS) - end - if player.mimic_level >= 25 then - player.xtra_f2 = bor(player.xtra_f2, TR2_FREE_ACT) - end - if player.mimic_level >= 30 then - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_ELEC) - end - if player.mimic_level >= 30 then - player.xtra_f3 = bor(player.xtra_f3, TR3_SH_ELEC) - end - end, -} - -add_mimic_shape -{ - ["name"] = "Wolf", - ["obj_name"] = "Wolf Pelt", - ["desc"] = "Wolves are masters of movement, strong and have excellent eyesight.", - ["realm"] = "nature", - ["level"] = 20, - ["rarity"] = 40, - ["duration"] = {10, 50}, - ["calc"] = function () - player.modify_stat(A_STR, 2 + (player.mimic_level / 20)) - player.modify_stat(A_DEX, 3 + (player.mimic_level / 20)) - player.modify_stat(A_INT, -3) - player.modify_stat(A_CHR, -2) - - player.pspeed = player.pspeed + 10 + (player.mimic_level / 5) - - player.xtra_f2 = bor(player.xtra_f2, TR2_FREE_ACT) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_FEAR) - - if player.mimic_level >= 10 then - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_COLD) - end - if player.mimic_level >= 15 then - player.xtra_f3 = bor(player.xtra_f3, TR3_SEE_INVIS) - end - if player.mimic_level >= 30 then - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_DARK) - end - if player.mimic_level >= 35 then - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_CONF) - end - end, -} - -add_mimic_shape -{ - ["name"] = "Spider", - ["obj_name"] = "Spider Web", - ["desc"] = "Spiders are clever and become good climbers.", - ["realm"] = "nature", - ["level"] = 25, - ["rarity"] = 50, - ["duration"] = {10, 50}, - ["calc"] = function () - player.modify_stat(A_STR, -4) - player.modify_stat(A_DEX, 1 + (player.mimic_level / 8)) - player.modify_stat(A_INT, 1 + (player.mimic_level / 5)) - player.modify_stat(A_WIS, 1 + (player.mimic_level / 5)) - player.modify_stat(A_CON, -5) - player.modify_stat(A_CHR, -10) - - player.pspeed = player.pspeed + 5 - - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_POIS) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_FEAR) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_DARK) - - if player.mimic_level >= 40 then - player.xtra_f4 = bor(player.xtra_f4, TR4_CLIMB) - end - - end, - ["power"] = function() - if player.mimic_level >= 25 then - player.add_power(POWER_WEB) - end - end, -} - -add_mimic_shape -{ - ["name"] = "Elder Ent", - ["obj_name"] = "Entish Bark", - ["desc"] = "Ents are powerful tree-like beings dating from the dawn of time.", - ["realm"] = "nature", - ["level"] = 40, - ["rarity"] = 60, - ["duration"] = {10, 30}, - ["limit"] = TRUE, - ["calc"] = function () - player.pspeed = player.pspeed - 5 - (player.mimic_level / 10) - - player.to_a = player.to_a + 10 + player.mimic_level - player.dis_to_a = player.dis_to_a + 10 + player.mimic_level - - player.modify_stat(A_STR, player.mimic_level / 5) - player.modify_stat(A_INT, - (player.mimic_level / 7)) - player.modify_stat(A_WIS, - (player.mimic_level / 7)) - player.modify_stat(A_DEX, -4) - player.modify_stat(A_CON, player.mimic_level / 5) - player.modify_stat(A_CHR, -7) - - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_POIS) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_COLD) - player.xtra_f2 = bor(player.xtra_f2, TR2_FREE_ACT) - player.xtra_f3 = bor(player.xtra_f3, TR3_REGEN) - player.xtra_f3 = bor(player.xtra_f3, TR3_SEE_INVIS) - player.xtra_f2 = bor(player.xtra_f2, TR2_SENS_FIRE) - end, - ["power"] = function () - player.add_power(PWR_GROW_TREE) - end, -} - -add_mimic_shape -{ - ["name"] = "Vapour", - ["obj_name"] = "Cloak of Mist", - ["desc"] = "A sentient cloud, darting around", - ["realm"] = "nature", - ["level"] = 15, - ["rarity"] = 10, - ["duration"] = {10, 40}, - ["calc"] = function () - - player.pspeed = player.pspeed + 5 - - --Try to hit a cloud! - player.to_a = player.to_a + 40 + player.mimic_level - player.dis_to_a = player.dis_to_a + 40 + player.mimic_level - - --Try to hit WITH a cloud! - player.to_h = player.to_h - 40 - player.dis_to_h = player.dis_to_h -40 - - -- Stat mods - player.modify_stat(A_STR, -4) - player.modify_stat(A_DEX, 5) - player.modify_stat(A_CON, -4) - player.modify_stat(A_CHR, -10) - - -- But they are stealthy - player.skill_stl = player.skill_stl + 10 + (player.mimic_level / 5) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_POIS) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_SHARDS) - player.xtra_f2 = bor(player.xtra_f2, TR2_IM_COLD) - player.xtra_f2 = bor(player.xtra_f2, TR2_FREE_ACT) - player.xtra_f3 = bor(player.xtra_f3, TR3_REGEN) - player.xtra_f3 = bor(player.xtra_f3, TR3_SEE_INVIS) - player.xtra_f2 = bor(player.xtra_f2, TR2_SENS_FIRE) - player.xtra_f3 = bor(player.xtra_f3, TR3_FEATHER) - end, -} - -add_mimic_shape -{ - ["name"] = "Serpent", - ["obj_name"] = "Snakeskin Cloak", - ["desc"] = "Serpents are fast, lethal predators.", - ["realm"] = "nature", - ["level"] = 30, - ["rarity"] = 25, - ["duration"] = {15, 20}, - ["calc"] = function () - player.pspeed = player.pspeed + 10 + (player.mimic_level / 6) - player.to_a = player.to_a + 3 + (player.mimic_level / 8) - player.dis_to_a = player.dis_to_a + 3 + (player.mimic_level / 8) - - player.modify_stat(A_STR, player.mimic_level / 8) - player.modify_stat(A_INT, -6) - player.modify_stat(A_WIS, -6) - player.modify_stat(A_DEX, -4) - player.modify_stat(A_CON, player.mimic_level / 7) - player.modify_stat(A_CHR, -6) - - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_POIS) - if player.mimic_level >= 25 then - player.xtra_f2 = bor(player.xtra_f2, TR2_FREE_ACT) - end - end, -} - -add_mimic_shape -{ - ["name"] = "Mumak", - ["obj_name"] = "Mumak Hide", - ["desc"] = "A giant, elaphantine form.", - ["realm"] = "nature", - ["level"] = 40, - ["rarity"] = 40, - ["duration"] = {15, 20}, - ["calc"] = function () - player.pspeed = player.pspeed - 5 - (player.mimic_level / 10) - player.to_a = player.to_a + 10 + (player.mimic_level / 6) - player.dis_to_a = player.dis_to_a + 10 + (player.mimic_level / 6) - player.to_d = player.to_d + 5 + ((player.mimic_level * 2) / 3) - player.dis_to_d = player.dis_to_d + 5 + ((player.mimic_level * 2) / 3) - - player.modify_stat(A_STR, player.mimic_level / 4) - player.modify_stat(A_INT, -8) - player.modify_stat(A_WIS, -4) - player.modify_stat(A_DEX, -5) - player.modify_stat(A_CON, player.mimic_level / 3) - player.modify_stat(A_CHR, -10) - - if player.mimic_level >= 10 then - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_FEAR) - end - if player.mimic_level >= 25 then - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_CONF) - end - if player.mimic_level >= 30 then - player.xtra_f2 = bor(player.xtra_f2, TR2_FREE_ACT) - end - if player.mimic_level >= 35 then - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_NEXUS) - end - end, -} - ---------- Extra shapes ----------- - --- For Beornings -add_mimic_shape -{ - ["name"] = "Bear", - ["desc"] = "A fierce, terrible bear.", - ["realm"] = nil, - ["level"] = 1, - ["rarity"] = 101, - ["duration"] = {50, 200}, - ["limit"] = TRUE, - ["calc"] = function () - player.pspeed = player.pspeed - 5 + (player.mimic_level / 5) - - player.to_a = player.to_a + 5 + ((player.mimic_level * 2) / 3) - player.dis_to_a = player.dis_to_a + 5 + ((player.mimic_level * 2) / 3) - - player.modify_stat(A_STR, player.mimic_level / 11) - player.modify_stat(A_INT, player.mimic_level / 11) - player.modify_stat(A_WIS, player.mimic_level / 11) - player.modify_stat(A_DEX, -1) - player.modify_stat(A_CON, player.mimic_level / 11) - player.modify_stat(A_CHR, -10) - - if player.mimic_level >= 10 then - player.xtra_f2 = bor(player.xtra_f2, TR2_FREE_ACT) - end - if player.mimic_level >= 20 then - player.xtra_f3 = bor(player.xtra_f3, TR3_REGEN) - end - if player.mimic_level >= 30 then - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_CONF) - end - if player.mimic_level >= 35 then - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_NEXUS) - end - - -- activate the skill - skill(SKILL_BEAR).hidden = FALSE - end, -} - --- For balrog corruptions -add_mimic_shape -{ - ["name"] = "Balrog", - ["desc"] = "A corrupted maia.", - ["realm"] = nil, - ["level"] = 1, - ["rarity"] = 101, - ["duration"] = {30, 70}, - ["limit"] = TRUE, - ["calc"] = function () - player.modify_stat(A_STR, 5 + player.mimic_level / 5) - player.modify_stat(A_INT, player.mimic_level / 10) - player.modify_stat(A_WIS, - ( 5 + player.mimic_level / 10)) - player.modify_stat(A_DEX, player.mimic_level / 10) - player.modify_stat(A_CON, 5 + player.mimic_level / 5) - player.modify_stat(A_CHR, - ( 5 + player.mimic_level / 10)) - - player.xtra_f2 = bor(player.xtra_f2, TR2_IM_ACID) - player.xtra_f2 = bor(player.xtra_f2, TR2_IM_FIRE) - player.xtra_f2 = bor(player.xtra_f2, TR2_IM_ELEC) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_DARK) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_CHAOS) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_POIS) - player.xtra_f2 = bor(player.xtra_f2, TR2_HOLD_LIFE) - player.xtra_f3 = bor(player.xtra_f3, TR3_FEATHER) - player.xtra_f3 = bor(player.xtra_f3, TR3_REGEN) - player.xtra_f3 = bor(player.xtra_f3, TR3_SH_FIRE) - player.xtra_f3 = bor(player.xtra_f3, TR3_LITE1) - return 1 - end, -} - --- For avatar spell -add_mimic_shape -{ - ["name"] = "Maia", - ["desc"] = "A near god-like being.", - ["realm"] = nil, - ["level"] = 1, - ["rarity"] = 101, - ["duration"] = {30, 70}, - ["limit"] = TRUE, - ["calc"] = function () - player.modify_stat(A_STR, 5 + player.mimic_level / 5) - player.modify_stat(A_INT, 5 + player.mimic_level / 5) - player.modify_stat(A_WIS, 5 + player.mimic_level / 5) - player.modify_stat(A_DEX, 5 + player.mimic_level / 5) - player.modify_stat(A_CON, 5 + player.mimic_level / 5) - player.modify_stat(A_CHR, 5 + player.mimic_level / 5) - - player.xtra_f2 = bor(player.xtra_f2, TR2_IM_FIRE) - player.xtra_f2 = bor(player.xtra_f2, TR2_IM_ELEC) - player.xtra_f2 = bor(player.xtra_f2, TR2_IM_ACID) - player.xtra_f2 = bor(player.xtra_f2, TR2_IM_COLD) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_POIS) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_LITE) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_DARK) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_CHAOS) - player.xtra_f2 = bor(player.xtra_f2, TR2_HOLD_LIFE) - player.xtra_f3 = bor(player.xtra_f3, TR3_FEATHER) - player.xtra_f3 = bor(player.xtra_f3, TR3_REGEN) - return 2 - end, -} - --- For Geomancy -add_mimic_shape -{ - ["name"] = "Fire Elem.", - ["desc"] = "A towering column of flames", - ["realm"] = nil, - ["level"] = 1, - ["rarity"] = 101, - ["duration"] = {10, 10}, - ["limit"] = TRUE, - ["calc"] = function () - player.modify_stat(A_STR, 5 + (player.mimic_level / 5)) - player.modify_stat(A_DEX, 5 + (player.mimic_level / 5)) - player.modify_stat(A_WIS, -5 - (player.mimic_level / 5)) - - player.xtra_f2 = bor(player.xtra_f2, TR2_IM_FIRE) - -- was immune to poison in the 3.0.0 version - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_POIS) - player.xtra_f3 = bor(player.xtra_f3, TR3_SH_FIRE) - player.xtra_f3 = bor(player.xtra_f3, TR3_LITE1) - return 0 - end, -} diff --git a/lib/scpt/init.lua b/lib/scpt/init.lua index d0512c76..3b461d19 100644 --- a/lib/scpt/init.lua +++ b/lib/scpt/init.lua @@ -11,9 +11,6 @@ tome_dofile("help.lua") -- let the store specific stuff happen! tome_dofile("stores.lua") --- Add the mimic shapes -tome_dofile("mimic.lua") - -- Add the mkey activations tome_dofile("mkeys.lua") diff --git a/lib/scpt/mimic.lua b/lib/scpt/mimic.lua deleted file mode 100644 index 6529f35c..00000000 --- a/lib/scpt/mimic.lua +++ /dev/null @@ -1,419 +0,0 @@ --- Define the various possible mimic shapes - --- Nature shapes -add_mimic_shape -{ - ["name"] = "Mouse", - ["obj_name"] = "Mouse Fur", - ["desc"] = "Mice are small, fast and very stealthy", - ["realm"] = "nature", - ["level"] = 1, - ["rarity"] = 10, - ["duration"] = {20, 40}, - ["calc"] = function () - -- Mice run! - player.pspeed = player.pspeed + 5 + (player.mimic_level / 7) - - -- They can crtawl under your armor to hit you ;) - player.to_h = player.to_h + 10 + (player.mimic_level / 5) - player.dis_to_h = player.dis_to_h + 10 + (player.mimic_level / 5) - - -- But they are not very powerfull - player.to_d = player.to_d / 5 - player.dis_to_d = player.dis_to_d / 5 - - -- But they are stealthy - player.skill_stl = player.skill_stl + 10 + (player.mimic_level / 5) - - -- Stat mods - player.modify_stat(A_STR, -5) - player.modify_stat(A_DEX, 3) - player.modify_stat(A_CON, 1) - - end, - ["power"] = function() - if player.mimic_level >= 30 then - player.add_power(POWER_INVISIBILITY) - end - end, -} - -add_mimic_shape -{ - ["name"] = "Eagle", - ["obj_name"] = "Feathers Cloak", - ["desc"] = "Eagles are master of the air, good hunters with excellent vision.", - ["realm"] = "nature", - ["level"] = 10, - ["rarity"] = 30, - ["duration"] = {10, 50}, - ["calc"] = function () - player.ffall = TRUE - player.pspeed = player.pspeed + 2 + (player.mimic_level / 6) - - player.modify_stat(A_STR, -3) - player.modify_stat(A_DEX, 2 + (player.mimic_level / 15)) - player.modify_stat(A_CON, 4 + (player.mimic_level / 20)) - player.modify_stat(A_INT, -1) - player.modify_stat(A_WIS, 1) - player.modify_stat(A_CHR, -1) - - if player.mimic_level >= 20 then - player.xtra_f4 = bor(player.xtra_f4, TR4_FLY) - player.xtra_f3 = bor(player.xtra_f3, TR3_SEE_INVIS) - end - if player.mimic_level >= 25 then - player.xtra_f2 = bor(player.xtra_f2, TR2_FREE_ACT) - end - if player.mimic_level >= 30 then - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_ELEC) - end - if player.mimic_level >= 30 then - player.xtra_f3 = bor(player.xtra_f3, TR3_SH_ELEC) - end - end, -} - -add_mimic_shape -{ - ["name"] = "Wolf", - ["obj_name"] = "Wolf Pelt", - ["desc"] = "Wolves are masters of movement, strong and have excellent eyesight.", - ["realm"] = "nature", - ["level"] = 20, - ["rarity"] = 40, - ["duration"] = {10, 50}, - ["calc"] = function () - player.modify_stat(A_STR, 2 + (player.mimic_level / 20)) - player.modify_stat(A_DEX, 3 + (player.mimic_level / 20)) - player.modify_stat(A_INT, -3) - player.modify_stat(A_CHR, -2) - - player.pspeed = player.pspeed + 10 + (player.mimic_level / 5) - - player.xtra_f2 = bor(player.xtra_f2, TR2_FREE_ACT) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_FEAR) - - if player.mimic_level >= 10 then - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_COLD) - end - if player.mimic_level >= 15 then - player.xtra_f3 = bor(player.xtra_f3, TR3_SEE_INVIS) - end - if player.mimic_level >= 30 then - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_DARK) - end - if player.mimic_level >= 35 then - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_CONF) - end - end, -} - -add_mimic_shape -{ - ["name"] = "Spider", - ["obj_name"] = "Spider Web", - ["desc"] = "Spiders are clever and become good climbers.", - ["realm"] = "nature", - ["level"] = 25, - ["rarity"] = 50, - ["duration"] = {10, 50}, - ["calc"] = function () - player.modify_stat(A_STR, -4) - player.modify_stat(A_DEX, 1 + (player.mimic_level / 8)) - player.modify_stat(A_INT, 1 + (player.mimic_level / 5)) - player.modify_stat(A_WIS, 1 + (player.mimic_level / 5)) - player.modify_stat(A_CON, -5) - player.modify_stat(A_CHR, -10) - - player.pspeed = player.pspeed + 5 - - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_POIS) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_FEAR) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_DARK) - - if player.mimic_level >= 40 then - player.xtra_f4 = bor(player.xtra_f4, TR4_CLIMB) - end - - end, - ["power"] = function() - if player.mimic_level >= 25 then - player.add_power(POWER_WEB) - end - end, -} - -add_mimic_shape -{ - ["name"] = "Elder Ent", - ["obj_name"] = "Entish Bark", - ["desc"] = "Ents are powerful tree-like beings dating from the dawn of time.", - ["realm"] = "nature", - ["level"] = 40, - ["rarity"] = 60, - ["duration"] = {10, 30}, - ["limit"] = TRUE, - ["calc"] = function () - player.pspeed = player.pspeed - 5 - (player.mimic_level / 10) - - player.to_a = player.to_a + 10 + player.mimic_level - player.dis_to_a = player.dis_to_a + 10 + player.mimic_level - - player.modify_stat(A_STR, player.mimic_level / 5) - player.modify_stat(A_INT, - (player.mimic_level / 7)) - player.modify_stat(A_WIS, - (player.mimic_level / 7)) - player.modify_stat(A_DEX, -4) - player.modify_stat(A_CON, player.mimic_level / 5) - player.modify_stat(A_CHR, -7) - - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_POIS) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_COLD) - player.xtra_f2 = bor(player.xtra_f2, TR2_FREE_ACT) - player.xtra_f3 = bor(player.xtra_f3, TR3_REGEN) - player.xtra_f3 = bor(player.xtra_f3, TR3_SEE_INVIS) - player.xtra_f2 = bor(player.xtra_f2, TR2_SENS_FIRE) - end, - ["power"] = function () - player.add_power(PWR_GROW_TREE) - end, -} - -add_mimic_shape -{ - ["name"] = "Vapour", - ["obj_name"] = "Cloak of Mist", - ["desc"] = "A sentient cloud, darting around", - ["realm"] = "nature", - ["level"] = 15, - ["rarity"] = 10, - ["duration"] = {10, 40}, - ["calc"] = function () - - player.pspeed = player.pspeed + 5 - - --Try to hit a cloud! - player.to_a = player.to_a + 40 + player.mimic_level - player.dis_to_a = player.dis_to_a + 40 + player.mimic_level - - --Try to hit WITH a cloud! - player.to_h = player.to_h - 40 - player.dis_to_h = player.dis_to_h -40 - - -- Stat mods - player.modify_stat(A_STR, -4) - player.modify_stat(A_DEX, 5) - player.modify_stat(A_CON, -4) - player.modify_stat(A_CHR, -10) - - -- But they are stealthy - player.skill_stl = player.skill_stl + 10 + (player.mimic_level / 5) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_POIS) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_SHARDS) - player.xtra_f2 = bor(player.xtra_f2, TR2_IM_COLD) - player.xtra_f2 = bor(player.xtra_f2, TR2_FREE_ACT) - player.xtra_f3 = bor(player.xtra_f3, TR3_REGEN) - player.xtra_f3 = bor(player.xtra_f3, TR3_SEE_INVIS) - player.xtra_f2 = bor(player.xtra_f2, TR2_SENS_FIRE) - player.xtra_f3 = bor(player.xtra_f3, TR3_FEATHER) - end, -} - -add_mimic_shape -{ - ["name"] = "Serpent", - ["obj_name"] = "Snakeskin Cloak", - ["desc"] = "Serpents are fast, lethal predators.", - ["realm"] = "nature", - ["level"] = 30, - ["rarity"] = 25, - ["duration"] = {15, 20}, - ["calc"] = function () - player.pspeed = player.pspeed + 10 + (player.mimic_level / 6) - player.to_a = player.to_a + 3 + (player.mimic_level / 8) - player.dis_to_a = player.dis_to_a + 3 + (player.mimic_level / 8) - - player.modify_stat(A_STR, player.mimic_level / 8) - player.modify_stat(A_INT, -6) - player.modify_stat(A_WIS, -6) - player.modify_stat(A_DEX, -4) - player.modify_stat(A_CON, player.mimic_level / 7) - player.modify_stat(A_CHR, -6) - - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_POIS) - if player.mimic_level >= 25 then - player.xtra_f2 = bor(player.xtra_f2, TR2_FREE_ACT) - end - end, -} - -add_mimic_shape -{ - ["name"] = "Mumak", - ["obj_name"] = "Mumak Hide", - ["desc"] = "A giant, elaphantine form.", - ["realm"] = "nature", - ["level"] = 40, - ["rarity"] = 40, - ["duration"] = {15, 20}, - ["calc"] = function () - player.pspeed = player.pspeed - 5 - (player.mimic_level / 10) - player.to_a = player.to_a + 10 + (player.mimic_level / 6) - player.dis_to_a = player.dis_to_a + 10 + (player.mimic_level / 6) - player.to_d = player.to_d + 5 + ((player.mimic_level * 2) / 3) - player.dis_to_d = player.dis_to_d + 5 + ((player.mimic_level * 2) / 3) - - player.modify_stat(A_STR, player.mimic_level / 4) - player.modify_stat(A_INT, -8) - player.modify_stat(A_WIS, -4) - player.modify_stat(A_DEX, -5) - player.modify_stat(A_CON, player.mimic_level / 3) - player.modify_stat(A_CHR, -10) - - if player.mimic_level >= 10 then - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_FEAR) - end - if player.mimic_level >= 25 then - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_CONF) - end - if player.mimic_level >= 30 then - player.xtra_f2 = bor(player.xtra_f2, TR2_FREE_ACT) - end - if player.mimic_level >= 35 then - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_NEXUS) - end - end, -} - ---------- Extra shapes ----------- - --- For Beornings -add_mimic_shape -{ - ["name"] = "Bear", - ["desc"] = "A fierce, terrible bear.", - ["realm"] = nil, - ["level"] = 1, - ["rarity"] = 101, - ["duration"] = {50, 200}, - ["limit"] = TRUE, - ["calc"] = function () - player.pspeed = player.pspeed - 5 + (player.mimic_level / 5) - - player.to_a = player.to_a + 5 + ((player.mimic_level * 2) / 3) - player.dis_to_a = player.dis_to_a + 5 + ((player.mimic_level * 2) / 3) - - player.modify_stat(A_STR, player.mimic_level / 11) - player.modify_stat(A_INT, player.mimic_level / 11) - player.modify_stat(A_WIS, player.mimic_level / 11) - player.modify_stat(A_DEX, -1) - player.modify_stat(A_CON, player.mimic_level / 11) - player.modify_stat(A_CHR, -10) - - if player.mimic_level >= 10 then - player.xtra_f2 = bor(player.xtra_f2, TR2_FREE_ACT) - end - if player.mimic_level >= 20 then - player.xtra_f3 = bor(player.xtra_f3, TR3_REGEN) - end - if player.mimic_level >= 30 then - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_CONF) - end - if player.mimic_level >= 35 then - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_NEXUS) - end - - -- activate the skill - skill(SKILL_BEAR).hidden = FALSE - end, -} - --- For balrog corruptions -add_mimic_shape -{ - ["name"] = "Balrog", - ["desc"] = "A corrupted maia.", - ["realm"] = nil, - ["level"] = 1, - ["rarity"] = 101, - ["duration"] = {30, 70}, - ["limit"] = TRUE, - ["calc"] = function () - player.modify_stat(A_STR, 5 + player.mimic_level / 5) - player.modify_stat(A_INT, player.mimic_level / 10) - player.modify_stat(A_WIS, - ( 5 + player.mimic_level / 10)) - player.modify_stat(A_DEX, player.mimic_level / 10) - player.modify_stat(A_CON, 5 + player.mimic_level / 5) - player.modify_stat(A_CHR, - ( 5 + player.mimic_level / 10)) - - player.xtra_f2 = bor(player.xtra_f2, TR2_IM_ACID) - player.xtra_f2 = bor(player.xtra_f2, TR2_IM_FIRE) - player.xtra_f2 = bor(player.xtra_f2, TR2_IM_ELEC) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_DARK) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_CHAOS) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_POIS) - player.xtra_f2 = bor(player.xtra_f2, TR2_HOLD_LIFE) - player.xtra_f3 = bor(player.xtra_f3, TR3_FEATHER) - player.xtra_f3 = bor(player.xtra_f3, TR3_REGEN) - player.xtra_f3 = bor(player.xtra_f3, TR3_SH_FIRE) - player.xtra_f3 = bor(player.xtra_f3, TR3_LITE1) - return 1 - end, -} - --- For avatar spell -add_mimic_shape -{ - ["name"] = "Maia", - ["desc"] = "A near god-like being.", - ["realm"] = nil, - ["level"] = 1, - ["rarity"] = 101, - ["duration"] = {30, 70}, - ["limit"] = TRUE, - ["calc"] = function () - player.modify_stat(A_STR, 5 + player.mimic_level / 5) - player.modify_stat(A_INT, 5 + player.mimic_level / 5) - player.modify_stat(A_WIS, 5 + player.mimic_level / 5) - player.modify_stat(A_DEX, 5 + player.mimic_level / 5) - player.modify_stat(A_CON, 5 + player.mimic_level / 5) - player.modify_stat(A_CHR, 5 + player.mimic_level / 5) - - player.xtra_f2 = bor(player.xtra_f2, TR2_IM_FIRE) - player.xtra_f2 = bor(player.xtra_f2, TR2_IM_ELEC) - player.xtra_f2 = bor(player.xtra_f2, TR2_IM_ACID) - player.xtra_f2 = bor(player.xtra_f2, TR2_IM_COLD) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_POIS) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_LITE) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_DARK) - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_CHAOS) - player.xtra_f2 = bor(player.xtra_f2, TR2_HOLD_LIFE) - player.xtra_f3 = bor(player.xtra_f3, TR3_FEATHER) - player.xtra_f3 = bor(player.xtra_f3, TR3_REGEN) - return 2 - end, -} - --- For Geomancy -add_mimic_shape -{ - ["name"] = "Fire Elem.", - ["desc"] = "A towering column of flames", - ["realm"] = nil, - ["level"] = 1, - ["rarity"] = 101, - ["duration"] = {10, 10}, - ["limit"] = TRUE, - ["calc"] = function () - player.modify_stat(A_STR, 5 + (player.mimic_level / 5)) - player.modify_stat(A_DEX, 5 + (player.mimic_level / 5)) - player.modify_stat(A_WIS, -5 - (player.mimic_level / 5)) - - player.xtra_f2 = bor(player.xtra_f2, TR2_IM_FIRE) - -- was immune to poison in the 3.0.0 version - player.xtra_f2 = bor(player.xtra_f2, TR2_RES_POIS) - player.xtra_f3 = bor(player.xtra_f3, TR3_SH_FIRE) - player.xtra_f3 = bor(player.xtra_f3, TR3_LITE1) - return 0 - end, -} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d610e193..c2ed88a3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -9,7 +9,7 @@ SET(SRCS object1.c object2.c randart.c squeltch.c traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c - spells1.c spells2.c corrupt.c + spells1.c spells2.c corrupt.c mimic.c status.c files.c notes.c loadsave.c cmd1.c cmd2.c cmd3.c cmd4.c cmd5.c cmd6.c cmd7.c help.c diff --git a/src/cmd6.c b/src/cmd6.c index 67fad8e2..15790ca4 100644 --- a/src/cmd6.c +++ b/src/cmd6.c @@ -2389,9 +2389,7 @@ static bool_ quaff_potion(int tval, int sval, int pval, int pval2) { if (!p_ptr->mimic_form) { - s32b time; - - call_lua("get_mimic_rand_dur", "(d)", "d", pval2, &time); + s32b time = get_mimic_random_duration(pval2); set_mimic(time, pval2, (p_ptr->lev * 2) / 3); diff --git a/src/cmd7.c b/src/cmd7.c index aca14dcd..f174e96a 100644 --- a/src/cmd7.c +++ b/src/cmd7.c @@ -735,7 +735,7 @@ static int get_mimic_chance(int mimic) { s32b chance; - call_lua("get_mimic_info", "(d,s)", "d", mimic, "level", &chance); + chance = get_mimic_level(mimic); chance *= 3; chance -= get_skill_scale(SKILL_MIMICRY, 150); diff --git a/src/defines.h b/src/defines.h index 1e36119f..f716e326 100644 --- a/src/defines.h +++ b/src/defines.h @@ -223,6 +223,7 @@ /* Mimicry */ #define MAX_MIMIC_POWERS 5 +#define MIMIC_FORMS_MAX 14 /* Symbiosis */ #define MAX_SYMBIOTIC_POWERS 9 diff --git a/src/externs.h b/src/externs.h index d53ba409..fd6802d8 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1521,6 +1521,16 @@ extern int get_keymap_mode(); /* main.c */ extern bool_ private_check_user_directory(cptr dirpath); +/* mimic.c */ +extern s16b resolve_mimic_name(cptr name); +extern s16b find_random_mimic_shape(byte level, bool_ limit); +extern cptr get_mimic_name(s16b mf_idx); +extern cptr get_mimic_object_name(s16b mf_idx); +extern byte get_mimic_level(s16b mf_idx); +extern s32b get_mimic_random_duration(s16b mf_idx); +extern byte calc_mimic(); +extern void calc_mimic_power(); + /* xtra1.c */ extern void fix_message(void); extern void apply_flags(u32b f1, u32b f2, u32b f3, u32b f4, u32b f5, u32b esp, s16b pval, s16b tval, s16b to_h, s16b to_d, s16b to_a); @@ -1545,7 +1555,6 @@ extern void fate_desc(char *desc, int fate); extern void dump_fates(FILE *OutFile); /* xtra2.c */ -extern int resolve_mimic_name(cptr name); extern void do_rebirth(void); extern cptr get_subrace_title(int racem); extern void set_subrace_title(int racem, cptr name); diff --git a/src/files.c b/src/files.c index 96ee66a9..4e1a1984 100644 --- a/src/files.c +++ b/src/files.c @@ -2644,7 +2644,7 @@ errr file_character(cptr name, bool_ full) if (p_ptr->tim_mimic) { - call_lua("get_mimic_info", "(d,s)", "s", p_ptr->mimic_form, "name", &mimic); + mimic = get_mimic_name(p_ptr->mimic_form); fprintf(fff, "\n You %s disguised as a %s.", (death ? "were" : "are"), mimic); } } diff --git a/src/mimic.c b/src/mimic.c new file mode 100644 index 00000000..6d241500 --- /dev/null +++ b/src/mimic.c @@ -0,0 +1,684 @@ +#include "angband.h" +#include + +static s32b abomination_calc() +{ + apply_flags(TR1_SPEED + TR1_STR + TR1_INT + TR1_WIS + TR1_DEX + TR1_CON + TR1_CHR, 0, 0, 0, 0, 0, -10, 0, 0, 0, 0); + p_ptr->xtra_f3 |= TR3_AGGRAVATE; + + return 0; +} + +static s32b mouse_calc() +{ + /* Mice run! */ + p_ptr->pspeed += 5 + (p_ptr->mimic_level / 7); + + /* They can crawl under your armor to hit you ;) */ + p_ptr->to_h = p_ptr->to_h + 10 + (p_ptr->mimic_level / 5); + p_ptr->dis_to_h = p_ptr->dis_to_h + 10 + (p_ptr->mimic_level / 5); + + /* But they are not very powerfull */ + p_ptr->to_d = p_ptr->to_d / 5; + p_ptr->dis_to_d = p_ptr->dis_to_d / 5; + + /* But they are stealthy */ + p_ptr->skill_stl = p_ptr->skill_stl + 10 + (p_ptr->mimic_level / 5); + + /* Stat mods */ + p_ptr->stat_add[A_STR] += -5; + p_ptr->stat_add[A_DEX] += 3; + p_ptr->stat_add[A_CON] += 1; + + return 0; +} + +static void mouse_power() +{ + if (p_ptr->mimic_level >= 30) + { + p_ptr->powers[POWER_INVISIBILITY] = TRUE; + } +} + +static s32b eagle_calc() +{ + p_ptr->ffall = TRUE; + p_ptr->pspeed = p_ptr->pspeed + 2 + (p_ptr->mimic_level / 6); + + p_ptr->stat_add[A_STR] += -3; + p_ptr->stat_add[A_DEX] += 2 + (p_ptr->mimic_level / 15); + p_ptr->stat_add[A_CON] += 4 + (p_ptr->mimic_level / 20); + p_ptr->stat_add[A_INT] += -1; + p_ptr->stat_add[A_WIS] += 1; + p_ptr->stat_add[A_CHR] += -1; + + if (p_ptr->mimic_level >= 20) + { + p_ptr->xtra_f4 |= TR4_FLY; + p_ptr->xtra_f3 |= TR3_SEE_INVIS; + } + + if (p_ptr->mimic_level >= 25) + { + p_ptr->xtra_f2 |= TR2_FREE_ACT; + } + + if (p_ptr->mimic_level >= 30) + { + p_ptr->xtra_f2 |= TR2_RES_ELEC; + } + + if (p_ptr->mimic_level >= 35) + { + p_ptr->xtra_f3 |= TR3_SH_ELEC; + } + + return 0; +} + +static s32b wolf_calc() +{ + p_ptr->stat_add[A_STR] += 2 + (p_ptr->mimic_level / 20); + p_ptr->stat_add[A_DEX] += 3 + (p_ptr->mimic_level / 20); + p_ptr->stat_add[A_INT] += -3; + p_ptr->stat_add[A_CHR] += -2; + + p_ptr->pspeed = p_ptr->pspeed + 10 + (p_ptr->mimic_level / 5); + + p_ptr->xtra_f2 |= TR2_FREE_ACT; + p_ptr->xtra_f2 |= TR2_RES_FEAR; + + if (p_ptr->mimic_level >= 10) + { + p_ptr->xtra_f2 |= TR2_RES_COLD; + } + + if (p_ptr->mimic_level >= 15) + { + p_ptr->xtra_f3 |= TR3_SEE_INVIS; + } + + if (p_ptr->mimic_level >= 30) + { + p_ptr->xtra_f2 |= TR2_RES_DARK; + } + + if (p_ptr->mimic_level >= 35) + { + p_ptr->xtra_f2 |= TR2_RES_CONF; + } + + return 0; +} + +static s32b spider_calc() +{ + p_ptr->stat_add[A_STR] += -4; + p_ptr->stat_add[A_DEX] += 1 + (p_ptr->mimic_level / 8); + p_ptr->stat_add[A_INT] += 1 + (p_ptr->mimic_level / 5); + p_ptr->stat_add[A_WIS] += 1 + (p_ptr->mimic_level / 5); + p_ptr->stat_add[A_CON] += -5; + p_ptr->stat_add[A_CHR] += -10; + + p_ptr->pspeed = p_ptr->pspeed + 5; + + p_ptr->xtra_f2 |= TR2_RES_POIS; + p_ptr->xtra_f2 |= TR2_RES_FEAR; + p_ptr->xtra_f2 |= TR2_RES_DARK; + + if (p_ptr->mimic_level >= 40) + { + p_ptr->xtra_f4 |= TR4_CLIMB; + } + + return 0; +} + +static void spider_power() +{ + if (p_ptr->mimic_level >= 25) + { + p_ptr->powers[POWER_WEB] = TRUE; + } +} + +static s32b ent_calc() +{ + p_ptr->pspeed = p_ptr->pspeed - 5 - (p_ptr->mimic_level / 10); + + p_ptr->to_a = p_ptr->to_a + 10 + p_ptr->mimic_level; + p_ptr->dis_to_a = p_ptr->dis_to_a + 10 + p_ptr->mimic_level; + + p_ptr->stat_add[A_STR] += p_ptr->mimic_level / 5; + p_ptr->stat_add[A_INT] += - (p_ptr->mimic_level / 7); + p_ptr->stat_add[A_WIS] += - (p_ptr->mimic_level / 7); + p_ptr->stat_add[A_DEX] += -4; + p_ptr->stat_add[A_CON] += p_ptr->mimic_level / 5; + p_ptr->stat_add[A_CHR] += -7; + + p_ptr->xtra_f2 |= TR2_RES_POIS; + p_ptr->xtra_f2 |= TR2_RES_COLD; + p_ptr->xtra_f2 |= TR2_FREE_ACT; + p_ptr->xtra_f3 |= TR3_REGEN; + p_ptr->xtra_f3 |= TR3_SEE_INVIS; + p_ptr->xtra_f2 |= TR2_SENS_FIRE; + + return 0; +} + +static void ent_power() +{ + p_ptr->powers[PWR_GROW_TREE] = TRUE; +} + +static s32b vapour_calc() +{ + p_ptr->pspeed = p_ptr->pspeed + 5; + + /* Try to hit a cloud! */ + p_ptr->to_a = p_ptr->to_a + 40 + p_ptr->mimic_level; + p_ptr->dis_to_a = p_ptr->dis_to_a + 40 + p_ptr->mimic_level; + + /* Try to hit WITH a cloud! */ + p_ptr->to_h = p_ptr->to_h - 40; + p_ptr->dis_to_h = p_ptr->dis_to_h - 40; + + /* Stat mods */ + p_ptr->stat_add[A_STR] += -4; + p_ptr->stat_add[A_DEX] += 5; + p_ptr->stat_add[A_CON] += -4; + p_ptr->stat_add[A_CHR] += -10; + + /* But they are stealthy */ + p_ptr->skill_stl = p_ptr->skill_stl + 10 + (p_ptr->mimic_level / 5); + p_ptr->xtra_f2 |= TR2_RES_POIS; + p_ptr->xtra_f2 |= TR2_RES_SHARDS; + p_ptr->xtra_f2 |= TR2_IM_COLD; + p_ptr->xtra_f2 |= TR2_FREE_ACT; + p_ptr->xtra_f3 |= TR3_REGEN; + p_ptr->xtra_f3 |= TR3_SEE_INVIS; + p_ptr->xtra_f2 |= TR2_SENS_FIRE; + p_ptr->xtra_f3 |= TR3_FEATHER; + + return 0; +} + +static s32b serpent_calc() +{ + p_ptr->pspeed = p_ptr->pspeed + 10 + (p_ptr->mimic_level / 6); + + p_ptr->to_a = p_ptr->to_a + 3 + (p_ptr->mimic_level / 8); + p_ptr->dis_to_a = p_ptr->dis_to_a + 3 + (p_ptr->mimic_level / 8); + + p_ptr->stat_add[A_STR] += p_ptr->mimic_level / 8; + p_ptr->stat_add[A_INT] += -6; + p_ptr->stat_add[A_WIS] += -6; + p_ptr->stat_add[A_DEX] += -4; + p_ptr->stat_add[A_CON] += p_ptr->mimic_level / 7; + p_ptr->stat_add[A_CHR] += -6; + + p_ptr->xtra_f2 |= TR2_RES_POIS; + if (p_ptr->mimic_level >= 25) + { + p_ptr->xtra_f2 |= TR2_FREE_ACT; + } + + return 0; +} + +static s32b mumak_calc() +{ + p_ptr->pspeed = p_ptr->pspeed - 5 - (p_ptr->mimic_level / 10); + + p_ptr->to_a = p_ptr->to_a + 10 + (p_ptr->mimic_level / 6); + p_ptr->dis_to_a = p_ptr->dis_to_a + 10 + (p_ptr->mimic_level / 6); + p_ptr->to_d = p_ptr->to_d + 5 + ((p_ptr->mimic_level * 2) / 3); + p_ptr->dis_to_d = p_ptr->dis_to_d + 5 + ((p_ptr->mimic_level * 2) / 3); + + p_ptr->stat_add[A_STR] += p_ptr->mimic_level / 4; + p_ptr->stat_add[A_INT] += -8; + p_ptr->stat_add[A_WIS] += -4; + p_ptr->stat_add[A_DEX] += -5; + p_ptr->stat_add[A_CON] += p_ptr->mimic_level / 3; + p_ptr->stat_add[A_CHR] += -10; + + if (p_ptr->mimic_level >= 10) + { + p_ptr->xtra_f2 |= TR2_RES_FEAR; + } + + if (p_ptr->mimic_level >= 25) + { + p_ptr->xtra_f2 |= TR2_RES_CONF; + } + + if (p_ptr->mimic_level >= 30) + { + p_ptr->xtra_f2 |= TR2_FREE_ACT; + } + + if (p_ptr->mimic_level >= 35) + { + p_ptr->xtra_f2 |= TR2_RES_NEXUS; + } + + return 0; +} + +static s32b bear_calc() +{ + p_ptr->pspeed = p_ptr->pspeed - 5 + (p_ptr->mimic_level / 5); + + p_ptr->to_a = p_ptr->to_a + 5 + ((p_ptr->mimic_level * 2) / 3); + p_ptr->dis_to_a = p_ptr->dis_to_a + 5 + ((p_ptr->mimic_level * 2) / 3); + + p_ptr->stat_add[A_STR] += p_ptr->mimic_level / 11; + p_ptr->stat_add[A_INT] += p_ptr->mimic_level / 11; + p_ptr->stat_add[A_WIS] += p_ptr->mimic_level / 11; + p_ptr->stat_add[A_DEX] += -1; + p_ptr->stat_add[A_CON] += p_ptr->mimic_level / 11; + p_ptr->stat_add[A_CHR] += -10; + + if (p_ptr->mimic_level >= 10) + { + p_ptr->xtra_f2 |= TR2_FREE_ACT; + } + + if (p_ptr->mimic_level >= 20) + { + p_ptr->xtra_f3 |= TR3_REGEN; + } + + if (p_ptr->mimic_level >= 30) + { + p_ptr->xtra_f2 |= TR2_RES_CONF; + } + + if (p_ptr->mimic_level >= 35) + { + p_ptr->xtra_f2 |= TR2_RES_NEXUS; + } + + /* activate the skill */ + s_info[SKILL_BEAR].hidden = FALSE; + + return 0; +} + +static s32b balrog_calc() +{ + p_ptr->stat_add[A_STR] += 5 + p_ptr->mimic_level / 5; + p_ptr->stat_add[A_INT] += p_ptr->mimic_level / 10; + p_ptr->stat_add[A_WIS] += - ( 5 + p_ptr->mimic_level / 10); + p_ptr->stat_add[A_DEX] += p_ptr->mimic_level / 10; + p_ptr->stat_add[A_CON] += 5 + p_ptr->mimic_level / 5; + p_ptr->stat_add[A_CHR] += - ( 5 + p_ptr->mimic_level / 10); + + p_ptr->xtra_f2 |= TR2_IM_ACID; + p_ptr->xtra_f2 |= TR2_IM_FIRE; + p_ptr->xtra_f2 |= TR2_IM_ELEC; + p_ptr->xtra_f2 |= TR2_RES_DARK; + p_ptr->xtra_f2 |= TR2_RES_CHAOS; + p_ptr->xtra_f2 |= TR2_RES_POIS; + p_ptr->xtra_f2 |= TR2_HOLD_LIFE; + p_ptr->xtra_f3 |= TR3_FEATHER; + p_ptr->xtra_f3 |= TR3_REGEN; + p_ptr->xtra_f3 |= TR3_SH_FIRE; + p_ptr->xtra_f3 |= TR3_LITE1; + + return 1; /* Adds a blow */ +} + +static s32b maia_calc() +{ + p_ptr->stat_add[A_STR] += 5 + p_ptr->mimic_level / 5; + p_ptr->stat_add[A_INT] += 5 + p_ptr->mimic_level / 5; + p_ptr->stat_add[A_WIS] += 5 + p_ptr->mimic_level / 5; + p_ptr->stat_add[A_DEX] += 5 + p_ptr->mimic_level / 5; + p_ptr->stat_add[A_CON] += 5 + p_ptr->mimic_level / 5; + p_ptr->stat_add[A_CHR] += 5 + p_ptr->mimic_level / 5; + + p_ptr->xtra_f2 |= TR2_IM_FIRE; + p_ptr->xtra_f2 |= TR2_IM_ELEC; + p_ptr->xtra_f2 |= TR2_IM_ACID; + p_ptr->xtra_f2 |= TR2_IM_COLD; + p_ptr->xtra_f2 |= TR2_RES_POIS; + p_ptr->xtra_f2 |= TR2_RES_LITE; + p_ptr->xtra_f2 |= TR2_RES_DARK; + p_ptr->xtra_f2 |= TR2_RES_CHAOS; + p_ptr->xtra_f2 |= TR2_HOLD_LIFE; + p_ptr->xtra_f3 |= TR3_FEATHER; + p_ptr->xtra_f3 |= TR3_REGEN; + + return 2; /* Add two blows */ +} + +static s32b fire_elemental_calc() +{ + p_ptr->stat_add[A_STR] += 5 + (p_ptr->mimic_level / 5); + p_ptr->stat_add[A_DEX] += 5 + (p_ptr->mimic_level / 5); + p_ptr->stat_add[A_WIS] += -5 - (p_ptr->mimic_level / 5); + + p_ptr->xtra_f2 |= TR2_IM_FIRE; + p_ptr->xtra_f2 |= TR2_RES_POIS; + p_ptr->xtra_f3 |= TR3_SH_FIRE; + p_ptr->xtra_f3 |= TR3_LITE1; + + return 0; +} + +/* + * Mimicry forms + */ +mimic_form_type mimic_forms[MIMIC_FORMS_MAX] = +{ + { /* 0 */ + { MODULE_TOME, MODULE_THEME, -1 }, + "Abomination", /* MUST be at index 0! */ + "Abominable Cloak", + "Abominations are failed experiments of powerful wizards.", + NULL /* no realm */, + FALSE, + 1, 101, {20, 100}, + abomination_calc, + NULL, + }, + + /* + * Nature forms + */ + + { /* 1 */ + { MODULE_TOME, MODULE_THEME, -1 }, + "Mouse", + "Mouse Fur", + "Mice are small, fast and very stealthy", + "nature", + FALSE, + 1, 10, {20, 40}, + mouse_calc, + mouse_power, + }, + + { /* 2 */ + { MODULE_TOME, -1 }, + "Eagle", + "Feathers Cloak", + "Eagles are master of the air, good hunters with excellent vision.", + "nature", + FALSE, + 10, 30, {10, 50}, + eagle_calc, + NULL, + }, + + { /* 3 */ + { MODULE_THEME, -1 }, + "Eagle", + "Feathered Cloak", + "Eagles are master of the air, good hunters with excellent vision.", + "nature", + FALSE, + 10, 30, {10, 50}, + eagle_calc, + NULL, + }, + + { /* 4 */ + { MODULE_TOME, MODULE_THEME, -1 }, + "Wolf", + "Wolf Pelt", + "Wolves are masters of movement, strong and have excellent eyesight.", + "nature", + FALSE, + 20, 40, {10, 50}, + wolf_calc, + NULL, + }, + + { /* 5 */ + { MODULE_TOME, MODULE_THEME, -1 }, + "Spider", + "Spider Web", + "Spiders are clever and become good climbers.", + "nature", + FALSE, + 25, 50, {10, 50}, + spider_calc, + spider_power, + }, + + { /* 6 */ + { MODULE_TOME, MODULE_THEME, -1 }, + "Elder Ent", + "Entish Bark", + "Ents are powerful tree-like beings dating from the dawn of time.", + "nature", + TRUE, + 40, 60, {10, 30}, + ent_calc, + ent_power, + }, + + { /* 7 */ + { MODULE_TOME, MODULE_THEME, -1 }, + "Vapour", + "Cloak of Mist", + "A sentient cloud, darting around", + "nature", + FALSE, + 15, 10, {10, 40}, + vapour_calc, + NULL, + }, + + { /* 8 */ + { MODULE_TOME, MODULE_THEME, -1 }, + "Serpent", + "Snakeskin Cloak", + "Serpents are fast, lethal predators.", + "nature", + FALSE, + 30, 25, {15, 20}, + serpent_calc, + NULL, + }, + + { /* 9 */ + { MODULE_TOME, MODULE_THEME, -1 }, + "Mumak", + "Mumak Hide", + "A giant, elaphantine form.", + "nature", + FALSE, + 40, 40, {15, 20}, + mumak_calc, + NULL, + }, + + /* + * Extra shapes + */ + + { /* 10 */ + { MODULE_TOME, MODULE_THEME, -1 }, + "Bear", + NULL, + "A fierce, terrible bear.", + NULL /* no realm */, + TRUE, + 1, 101, {50, 200}, + bear_calc, + NULL, + }, + + { /* 11 */ + { MODULE_TOME, MODULE_THEME, -1 }, + "Balrog", + NULL, + "A corrupted maia.", + NULL /* no realm */, + TRUE, + 1, 101, {30, 70}, + balrog_calc, + NULL, + }, + + { /* 12 */ + { MODULE_TOME, MODULE_THEME, -1 }, + "Maia", + NULL, + "A near god-like being.", + NULL /* no realm */, + TRUE, + 1, 101, {30, 70}, + maia_calc, + NULL, + }, + + { /* 13 */ + { MODULE_TOME, MODULE_THEME, -1 }, + "Fire Elem.", + NULL, + "A towering column of flames", + NULL /* no realm */, + TRUE, + 1, 101, {10, 10}, + fire_elemental_calc, + NULL, + }, + +}; + +/* + * Is the mimicry form enabled for the current module? + */ +static bool_ mimic_form_enabled(mimic_form_type *f) +{ + int i; + + for (i = 0; f->modules[i] >= 0; i++) + { + if (f->modules[i] == game_module_idx) + { + return TRUE; + } + } + + return FALSE; +} + +/* + * Get a mimic form by index + */ +static mimic_form_type *get_mimic_form(int mf_idx) +{ + assert(mf_idx >= 0); + assert(mf_idx < MIMIC_FORMS_MAX); + return &mimic_forms[mf_idx]; +} + +/* + * Find a mimic by name + */ +s16b resolve_mimic_name(cptr name) +{ + s16b i; + + for (i = 0; i < MIMIC_FORMS_MAX; i++) + { + mimic_form_type *mf_ptr = get_mimic_form(i); + if (mimic_form_enabled(mf_ptr) && streq(mf_ptr->name, name)) + { + return i; + } + } + + return -1; +} + +/* + * Find a random mimic form + */ +s16b find_random_mimic_shape(byte level, bool_ limit) +{ + int tries = 1000; + + while (tries > 0) + { + int mf_idx = 0; + mimic_form_type *mf_ptr = NULL; + + tries = tries - 1; + + mf_idx = rand_int(MIMIC_FORMS_MAX); + mf_ptr = get_mimic_form(mf_idx); + + if (mimic_form_enabled(mf_ptr)) + { + if (limit >= mf_ptr->limit) + { + if ((rand_int(mf_ptr->level * 3) < level) && + (mf_ptr->rarity < 100) && + (magik(100 - mf_ptr->rarity))) + { + return mf_idx; + } + } + } + } + /* Abomination */ + return 0; +} + +/* + * Get mimic name + */ +cptr get_mimic_name(s16b mf_idx) +{ + return get_mimic_form(mf_idx)->name; +} + +/* + * Get mimic object name + */ +cptr get_mimic_object_name(s16b mf_idx) +{ + return get_mimic_form(mf_idx)->obj_name; +} + +/* + * Get mimic object level + */ +byte get_mimic_level(s16b mf_idx) +{ + return get_mimic_form(mf_idx)->level; +} + +/* + * Get a random duration for the given mimic form + */ +s32b get_mimic_random_duration(s16b mf_idx) +{ + mimic_form_type *mf_ptr = get_mimic_form(mf_idx); + return rand_range(mf_ptr->duration.min, mf_ptr->duration.max); +} + +/* + * Calculate bonuses for player's current mimic form + */ +byte calc_mimic() +{ + mimic_form_type *mf_ptr = get_mimic_form(p_ptr->mimic_form); + return mf_ptr->calc(); +} + +/* + * Calculate powers for player's current mimic form + */ +void calc_mimic_power() +{ + mimic_form_type *mf_ptr = get_mimic_form(p_ptr->mimic_form); + return mf_ptr->power(); +} diff --git a/src/object1.c b/src/object1.c index fef7fb85..857deb2c 100644 --- a/src/object1.c +++ b/src/object1.c @@ -1509,7 +1509,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode) } else { - call_lua("get_mimic_info", "(d,s)", "s", o_ptr->pval2, "name", &modstr); + modstr = get_mimic_name(o_ptr->pval2); } if (((plain_descriptions) && (aware)) || o_ptr->ident & IDENT_STOREB) basenm = "& Potion~"; @@ -1540,7 +1540,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode) show_armour = TRUE; if (o_ptr->sval == SV_MIMIC_CLOAK) { - call_lua("get_mimic_info", "(d,s)", "s", o_ptr->pval2, "obj_name", &modstr); + modstr = get_mimic_object_name(o_ptr->pval2); } break; } diff --git a/src/object2.c b/src/object2.c index 98afb815..75fc7fa8 100644 --- a/src/object2.c +++ b/src/object2.c @@ -2761,9 +2761,7 @@ static void a_m_aux_2(object_type *o_ptr, int level, int power) o_ptr->pval = randint(4); /* No cursed elven cloaks...? */ else if (o_ptr->sval == SV_MIMIC_CLOAK) { - s32b mimic; - - call_lua("find_random_mimic_shape", "(d,d)", "d", level, TRUE, &mimic); + s32b mimic = find_random_mimic_shape(level, TRUE); o_ptr->pval2 = mimic; } break; @@ -3437,9 +3435,7 @@ static void a_m_aux_4(object_type *o_ptr, int level, int power) case TV_POTION2: if (o_ptr->sval == SV_POTION2_MIMIC) { - s32b mimic; - - call_lua("find_random_mimic_shape", "(d,d)", "d", level, FALSE, &mimic); + s32b mimic = find_random_mimic_shape(level, FALSE); o_ptr->pval2 = mimic; } break; diff --git a/src/randart.c b/src/randart.c index 298ee83a..580fa144 100644 --- a/src/randart.c +++ b/src/randart.c @@ -388,8 +388,7 @@ bool_ create_artifact(object_type *o_ptr, bool_ a_scroll, bool_ get_name) /* HACKS for ToME */ if (o_ptr->tval == TV_CLOAK && o_ptr->sval == SV_MIMIC_CLOAK) { - s32b mimic; - call_lua("find_random_mimic_shape", "(d,d)", "d", 127, TRUE, &mimic); + s32b mimic = find_random_mimic_shape(127, TRUE); o_ptr->pval2 = mimic; } else if (f5 & TR5_SPELL_CONTAIN) diff --git a/src/types.h b/src/types.h index df2c4f40..040a0149 100644 --- a/src/types.h +++ b/src/types.h @@ -2602,3 +2602,29 @@ struct corruption_type void (*gain_callback)(); /* callback to invoke when gained */ s16b power; /* index of granted power if >= 0, ignored otherwise */ }; + +/** + * Mimicry forms + */ +typedef struct mimic_duration_type mimic_duration_type; +struct mimic_duration_type +{ + s16b min; + s16b max; +}; + +typedef struct mimic_form_type mimic_form_type; +struct mimic_form_type +{ + int modules[3]; /* Modules where this mimicry form is available; terminated with a -1 entry */ + cptr name; /* Name of mimicry form */ + cptr obj_name; /* Object mimicry form name */ + cptr desc; /* Description */ + cptr realm; /* Realm of mimicry */ + bool_ limit; /* If true, the form is not available except through special means */ + byte level; + byte rarity; + mimic_duration_type duration; + s32b (*calc)(); /* Callback to calculate bonuses; return number of blows to add */ + void (*power)(); /* Callback to calculate powers */ +}; diff --git a/src/util.pkg b/src/util.pkg index d00dcb76..0be3cb8b 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -2474,3 +2474,8 @@ extern bool drop_text_left(byte c, cptr s, int y, int o); extern bool drop_text_right(byte c, cptr s, int y, int o); extern void quest_library_gen_hook(); + +/** + * Mimicry + */ +extern s16b resolve_mimic_name(cptr name); diff --git a/src/xtra1.c b/src/xtra1.c index 66f5ddd7..09315ed3 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -249,7 +249,7 @@ static void prt_title(void) /* Mimic shape */ if (p_ptr->mimic_form) { - call_lua("get_mimic_info", "(d,s)", "s", p_ptr->mimic_form, "show_name", &p); + p = get_mimic_name(p_ptr->mimic_form); } /* Wizard */ @@ -1592,7 +1592,9 @@ static void calc_powers(void) } } else if (p_ptr->mimic_form) - call_lua("calc_mimic_power", "(d)", "", p_ptr->mimic_form); + { + calc_mimic_power(); + } /* Add in class powers */ for (i = 0; i < 4; i++) @@ -2262,14 +2264,6 @@ void calc_body_bonus() } -byte calc_mimic() -{ - s32b blow = 0; - - call_lua("calc_mimic", "(d)", "d", p_ptr->mimic_form, &blow); - return blow; -} - /* Returns the number of extra blows based on abilities. */ static int get_extra_blows_ability() { /* Count bonus abilities */ diff --git a/src/xtra2.c b/src/xtra2.c index a3ae9881..7fae3fbf 100644 --- a/src/xtra2.c +++ b/src/xtra2.c @@ -6061,14 +6061,3 @@ void do_rebirth() lite_spot(p_ptr->py, p_ptr->px); } - -/* - * Quick mimic name to index function - */ -int resolve_mimic_name(cptr name) -{ - s32b idx; - - call_lua("resolve_mimic_name", "(s)", "d", name, &idx); - return idx; -} -- cgit v1.2.3 From 92a7621e525ead5f41715efb92499cf289d2eea5 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 7 Apr 2012 21:11:58 +0200 Subject: Lua: Move Library Quest building action to C --- lib/mods/theme/scpt/library.lua | 42 -------------------------- lib/scpt/library.lua | 42 -------------------------- src/bldg.c | 6 ++++ src/defines.h | 1 + src/plots.h | 1 + src/q_library.c | 65 +++++++++++++++++++++++++++++++++++++++++ src/variable.c | 2 +- 7 files changed, 74 insertions(+), 85 deletions(-) diff --git a/lib/mods/theme/scpt/library.lua b/lib/mods/theme/scpt/library.lua index 38c26599..d2851a23 100644 --- a/lib/mods/theme/scpt/library.lua +++ b/lib/mods/theme/scpt/library.lua @@ -160,45 +160,3 @@ add_quest end, }, } - --- Library store action -add_building_action -{ - ["index"] = 61, - ["action"] = function() - -- the quest hasn't been requested already, right? - if quest(LIBRARY_QUEST).status == QUEST_STATUS_UNTAKEN then - -- quest has been taken now - quest(LIBRARY_QUEST).status = QUEST_STATUS_TAKEN - - -- issue instructions - msg_print("I need get some stock from my main library, but it is infested with monsters!") - msg_print("Please use the side entrance and vanquish the intruders for me.") - - return TRUE, FALSE, TRUE - -- if quest completed - elseif (quest(LIBRARY_QUEST).status == QUEST_STATUS_COMPLETED) then - msg_print("Thank you! Let me make a special book for you.") - msg_print("Tell me three spells and I will write them in the book.") - library_quest_fill_book() - if library_quest_book_slots_left() == 0 then - quest(LIBRARY_QUEST).status = QUEST_STATUS_REWARDED - book = create_object(TV_BOOK, 61) - book.art_name = quark_add(player_name()) - book.found = OBJ_FOUND_REWARD - set_aware(book) - set_known(book) - inven_carry(book, FALSE) - end - - -- if the player asks for a quest when they already have it, but haven't failed it, give them some extra instructions - elseif (quest(LIBRARY_QUEST).status == QUEST_STATUS_TAKEN) then - msg_print("Please use the side entrance and vanquish the intruders for me.") - - -- quest failed or completed, then give no more quests - elseif (quest(LIBRARY_QUEST).status == QUEST_STATUS_FAILED) or (quest(LIBRARY_QUEST).status == QUEST_STATUS_REWARDED) then - msg_print("I have no more quests for you.") - end - return TRUE - end, -} diff --git a/lib/scpt/library.lua b/lib/scpt/library.lua index 5c98fe86..ad546b54 100644 --- a/lib/scpt/library.lua +++ b/lib/scpt/library.lua @@ -157,45 +157,3 @@ add_quest end, }, } - --- Library store action -add_building_action -{ - ["index"] = 61, - ["action"] = function() - -- the quest hasn't been requested already, right? - if quest(LIBRARY_QUEST).status == QUEST_STATUS_UNTAKEN then - -- quest has been taken now - quest(LIBRARY_QUEST).status = QUEST_STATUS_TAKEN - - -- issue instructions - msg_print("I need get some stock from my main library, but it is infested with monsters!") - msg_print("Please use the side entrance and vanquish the intruders for me.") - - return TRUE, FALSE, TRUE - -- if quest completed - elseif (quest(LIBRARY_QUEST).status == QUEST_STATUS_COMPLETED) then - msg_print("Thank you! Let me make a special book for you.") - msg_print("Tell me three spells and I will write them in the book.") - library_quest_fill_book() - if library_quest_book_slots_left() == 0 then - quest(LIBRARY_QUEST).status = QUEST_STATUS_REWARDED - book = create_object(TV_BOOK, 61) - book.art_name = quark_add(player_name()) - book.found = OBJ_FOUND_REWARD - set_aware(book) - set_known(book) - inven_carry(book, FALSE) - end - - -- if the player asks for a quest when they already have it, but haven't failed it, give them some extra instructions - elseif (quest(LIBRARY_QUEST).status == QUEST_STATUS_TAKEN) then - msg_print("Please use the side entrance and vanquish the intruders for me.") - - -- quest failed or completed, then give no more quests - elseif (quest(LIBRARY_QUEST).status == QUEST_STATUS_FAILED) or (quest(LIBRARY_QUEST).status == QUEST_STATUS_REWARDED) then - msg_print("I have no more quests for you.") - end - return TRUE - end, -} diff --git a/src/bldg.c b/src/bldg.c index 1845e838..66ca9d9d 100644 --- a/src/bldg.c +++ b/src/bldg.c @@ -2042,6 +2042,12 @@ bool_ bldg_process_command(store_type *s_ptr, int i) break; } + case BACT_LIBRARY_QUEST: + { + quest_library_building(&paid, &recreate); + break; + } + default: { if (process_hooks_ret(HOOK_BUILDING_ACTION, "dd", "(d)", bact)) diff --git a/src/defines.h b/src/defines.h index f716e326..d78ed058 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4046,6 +4046,7 @@ #define BACT_PAY_BACK_LOAN 53 #define BACT_DROP_ITEM 54 #define BACT_GET_ITEM 55 +#define BACT_LIBRARY_QUEST 61 /* If one adds new BACT_ do NOT forget to increase max_bact in variables.c */ diff --git a/src/plots.h b/src/plots.h index 2d78ee02..73e4b8a8 100644 --- a/src/plots.h +++ b/src/plots.h @@ -55,3 +55,4 @@ extern bool_ quest_bounty_describe(FILE *fff); /******* Plot Library Quest *******/ extern void quest_library_gen_hook(); +extern void quest_library_building(bool_ *paid, bool_ *recreate); diff --git a/src/q_library.c b/src/q_library.c index 25f20717..6bb8baaa 100644 --- a/src/q_library.c +++ b/src/q_library.c @@ -240,3 +240,68 @@ void quest_library_gen_hook() library_quest_place_nrandom( 10, 10, 37, 67, MONSTER_MITHRIL_GOLEM, 1); } + +static int get_status() +{ + return exec_lua("return quest(LIBRARY_QUEST).status"); +} + +static void set_status(int new_status) +{ + exec_lua(format("quest(LIBRARY_QUEST).status = %d", new_status)); +} + +void quest_library_building(bool_ *paid, bool_ *recreate) +{ + int status = get_status(); + + /* the quest hasn't been requested already, right? */ + if (status == QUEST_STATUS_UNTAKEN) + { + /* quest has been taken now */ + set_status(QUEST_STATUS_TAKEN); + + /* issue instructions */ + msg_print("I need get some stock from my main library, but it is infested with monsters!"); + msg_print("Please use the side entrance and vanquish the intruders for me."); + + *paid = FALSE; + *recreate = TRUE; + } + + /* if quest completed */ + else if (status == QUEST_STATUS_COMPLETED) + { + msg_print("Thank you! Let me make a special book for you."); + msg_print("Tell me three spells and I will write them in the book."); + library_quest_fill_book(); + if (library_quest_book_slots_left() == 0) + { + set_status(QUEST_STATUS_REWARDED); + + { + object_type forge; + object_type *q_ptr = &forge; + object_prep(q_ptr, lookup_kind(TV_BOOK, 61)); + q_ptr->art_name = quark_add(player_name); + q_ptr->found = OBJ_FOUND_REWARD; + object_aware(q_ptr); + object_known(q_ptr); + inven_carry(q_ptr, FALSE); + } + } + } + + /* if the player asks for a quest when they already have it, + * but haven't failed it, give them some extra instructions */ + else if (status == QUEST_STATUS_TAKEN) + { + msg_print("Please use the side entrance and vanquish the intruders for me."); + } + + /* quest failed or completed, then give no more quests */ + else if ((status == QUEST_STATUS_FAILED) || (status == QUEST_STATUS_REWARDED)) + { + msg_print("I have no more quests for you."); + } +} diff --git a/src/variable.c b/src/variable.c index 52e16e01..c4388457 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1533,7 +1533,7 @@ int cli_total = 0; /* * max_bact, only used so that lua scripts can add new bacts without worrying about the numbers */ -int max_bact = 56; +int max_bact = 127; /* * Ingame contextual help -- cgit v1.2.3 From 565da158d150828f1be9a1b69332b30a59428ceb Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 7 Apr 2012 21:31:57 +0200 Subject: Lua: Remove spurious differences between ToME and Theme --- lib/mods/theme/scpt/fireprof.lua | 38 ++++++++++++++++++++++---------------- lib/scpt/fireprof.lua | 38 ++++++++++++++++++++++---------------- 2 files changed, 44 insertions(+), 32 deletions(-) diff --git a/lib/mods/theme/scpt/fireprof.lua b/lib/mods/theme/scpt/fireprof.lua index 8691b821..c63e6ef5 100644 --- a/lib/mods/theme/scpt/fireprof.lua +++ b/lib/mods/theme/scpt/fireprof.lua @@ -69,13 +69,13 @@ add_quest -- no teleport level_flags2 = DF2_NO_TELEPORT - -- determine type of rune + -- determine type of item fireproof_quest.essence = randint(5) -- create essence essence = create_object(TV_RUNE2, fireproof_quest.essence) - -- mark rune + -- mark item essence.pval2 = fireproof_quest.essence essence.note = quark_add("quest") @@ -129,7 +129,7 @@ add_quest [HOOK_STAIR] = function() local ret - -- only ask this if player about to go up stairs of quest and hasn't retrieved rune + -- only ask this if player about to go up stairs of quest and hasn't retrieved item if (player.inside_quest ~= FIREPROOF_QUEST) or (quest(FIREPROOF_QUEST).status == QUEST_STATUS_COMPLETED) then return FALSE @@ -156,13 +156,13 @@ add_quest end, [HOOK_GET] = function(o_ptr) - -- if they're in the quest and haven't picked up the rune already, continue + -- if they're in the quest and haven't picked up the item already, continue if (player.inside_quest ~= FIREPROOF_QUEST) or (quest(FIREPROOF_QUEST).status == QUEST_STATUS_COMPLETED) then return FALSE else - -- check that it's the real rune and not another one generated via the random object placing in fireproof.map + -- check that it's the real item and not another one generated via the random object placing in fireproof.map if (o_ptr.pval2 == fireproof_quest.essence) then -- ok mark the quest 'completed' @@ -182,6 +182,12 @@ add_building_action ["index"] = 56, ["action"] = function() + local i1 = "I need a very special rune for a spell I am working on. I am too old to " + local p = "Which rune?" + local pni = "You have no runes to return" + local tval = TV_RUNE2 + local location = "The rune is in a cave just behind the shop." + local num_books, num_staff, num_scroll num_books = fireproof_quest.item_points_remaining / fireproof_quest.BOOK_POINTS @@ -196,36 +202,36 @@ add_building_action fireproof_quest.item_points_remaining = fireproof_quest.TOTAL_ITEM_POINTS -- issue instructions - msg_print("I need a very special rune for a spell I am working on. I am too old to ") + msg_print(i1) msg_print("fetch it myself. Please bring it back to me. You can find it north of here.") msg_print("Be careful with it, it's fragile and might be destroyed easily.") return TRUE, FALSE, TRUE - -- if quest completed (rune was retrieved) + -- if quest completed (item was retrieved) elseif (quest(FIREPROOF_QUEST).status == QUEST_STATUS_COMPLETED) then - -- ask for rune - ret, item = get_item("Which rune?", - "You have no runes to return", + -- ask for item + ret, item = get_item(p, + pni, bor(USE_INVEN), function (obj) - -- check it's the 'marked' rune - if (obj.tval == TV_RUNE2) and (obj.sval == fireproof_quest.essence) and (obj.pval2 == fireproof_quest.essence) then + -- check it's the 'marked' item + if (obj.tval == tval) and (obj.sval == fireproof_quest.essence) and (obj.pval2 == fireproof_quest.essence) then return TRUE end return FALSE end ) - -- didn't get the rune? + -- didn't get the item? if (ret == FALSE) then return TRUE - -- got the rune! + -- got the item! else - -- take rune + -- take item inven_item_increase(item, -1) inven_item_optimize(item) msg_print("Great! Let me fireproof some of your items in thanks. I can do "..num_books.." books, ") @@ -261,7 +267,7 @@ add_building_action -- if the player asks for a quest when they already have it, but haven't failed it, give them some extra instructions elseif (quest(FIREPROOF_QUEST).status == QUEST_STATUS_TAKEN) then - msg_print("The rune is in a cave just behind the shop.") + msg_print(location) -- ok not all books have been fireproofed... lets do the rest elseif (quest(FIREPROOF_QUEST).status == QUEST_STATUS_FINISHED) then diff --git a/lib/scpt/fireprof.lua b/lib/scpt/fireprof.lua index 0a3aad28..0feb348b 100644 --- a/lib/scpt/fireprof.lua +++ b/lib/scpt/fireprof.lua @@ -69,13 +69,13 @@ add_quest -- no teleport level_flags2 = DF2_NO_TELEPORT - -- determine type of essence + -- determine type of item fireproof_quest.essence = randint(18) -- create essence essence = create_object(TV_BATERIE, fireproof_quest.essence) - -- mark essence + -- mark item essence.pval2 = fireproof_quest.essence essence.note = quark_add("quest") @@ -129,7 +129,7 @@ add_quest [HOOK_STAIR] = function() local ret - -- only ask this if player about to go up stairs of quest and hasn;t retrieved essence + -- only ask this if player about to go up stairs of quest and hasn't retrieved item if (player.inside_quest ~= FIREPROOF_QUEST) or (quest(FIREPROOF_QUEST).status == QUEST_STATUS_COMPLETED) then return FALSE @@ -156,13 +156,13 @@ add_quest end, [HOOK_GET] = function(o_ptr) - -- if they're in the quest and haven't picked up the essence already, continue + -- if they're in the quest and haven't picked up the item already, continue if (player.inside_quest ~= FIREPROOF_QUEST) or (quest(FIREPROOF_QUEST).status == QUEST_STATUS_COMPLETED) then return FALSE else - -- check that it's the real essence and not another one generated via the random object placing in fireproof.map + -- check that it's the real item and not another one generated via the random object placing in fireproof.map if (o_ptr.pval2 == fireproof_quest.essence) then -- ok mark the quest 'completed' @@ -182,6 +182,12 @@ add_building_action ["index"] = 56, ["action"] = function() + local i1 = "I need a very special essence for a spell I am working on. I am too old to " + local p = "Which essence?" + local pni = "You have no essences to return" + local tval = TV_BATERIE + local location = "The essence is in a cave just behind the shop." + local num_books, num_staff, num_scroll num_books = fireproof_quest.item_points_remaining / fireproof_quest.BOOK_POINTS @@ -196,36 +202,36 @@ add_building_action fireproof_quest.item_points_remaining = fireproof_quest.TOTAL_ITEM_POINTS -- issue instructions - msg_print("I need a very special essence for a spell I am working on. I am too old to ") + msg_print(i1) msg_print("fetch it myself. Please bring it back to me. You can find it north of here.") msg_print("Be careful with it, it's fragile and might be destroyed easily.") return TRUE, FALSE, TRUE - -- if quest completed (essence was retrieved) + -- if quest completed (item was retrieved) elseif (quest(FIREPROOF_QUEST).status == QUEST_STATUS_COMPLETED) then - -- ask for essence - ret, item = get_item("Which essence?", - "You have no essences to return", + -- ask for item + ret, item = get_item(p, + pni, bor(USE_INVEN), function (obj) - -- check it's the 'marked' essence - if (obj.tval == TV_BATERIE) and (obj.sval == fireproof_quest.essence) and (obj.pval2 == fireproof_quest.essence) then + -- check it's the 'marked' item + if (obj.tval == tval) and (obj.sval == fireproof_quest.essence) and (obj.pval2 == fireproof_quest.essence) then return TRUE end return FALSE end ) - -- didn't get the essence? + -- didn't get the item? if (ret == FALSE) then return TRUE - -- got the essence! + -- got the item! else - -- take essence + -- take item inven_item_increase(item, -1) inven_item_optimize(item) msg_print("Great! Let me fireproof some of your items in thanks. I can do "..num_books.." books, ") @@ -261,7 +267,7 @@ add_building_action -- if the player asks for a quest when they already have it, but haven't failed it, give them some extra instructions elseif (quest(FIREPROOF_QUEST).status == QUEST_STATUS_TAKEN) then - msg_print("The essence is in a cave just behind the shop.") + msg_print(location) -- ok not all books have been fireproofed... lets do the rest elseif (quest(FIREPROOF_QUEST).status == QUEST_STATUS_FINISHED) then -- cgit v1.2.3 From 61da8b12362ed22ca3c1d82ebec953035cd2f8d9 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 7 Apr 2012 22:01:06 +0200 Subject: Lua: Refactor "fireproofing" quest into C --- lib/mods/theme/scpt/fireprof.lua | 421 ---------------------------- lib/mods/theme/scpt/init.lua | 1 - lib/scpt/fireprof.lua | 421 ---------------------------- lib/scpt/init.lua | 1 - src/bldg.c | 6 + src/defines.h | 4 +- src/externs.h | 1 + src/plots.c | 4 + src/plots.h | 5 + src/q_fireprof.c | 584 +++++++++++++++++++++++++++++++++++++++ src/tables.c | 17 +- src/traps.c | 11 + 12 files changed, 630 insertions(+), 846 deletions(-) delete mode 100644 lib/mods/theme/scpt/fireprof.lua delete mode 100644 lib/scpt/fireprof.lua create mode 100644 src/q_fireprof.c diff --git a/lib/mods/theme/scpt/fireprof.lua b/lib/mods/theme/scpt/fireprof.lua deleted file mode 100644 index c63e6ef5..00000000 --- a/lib/mods/theme/scpt/fireprof.lua +++ /dev/null @@ -1,421 +0,0 @@ --- The Old Mages/Fireproofing quest: Bring back a rune from a fiery cave and get some books/scrolls/staves fireproofed in return - -fireproof_quest = {} - - --- change this constant (and the FOO_POINTS ones) to adjust the no of items fire-proofed as a reward -fireproof_quest.TOTAL_ITEM_POINTS = 24 - --- These constants are how many 'points' each type of item will take up. So currently, you can fireproof 3 books, 4 staves or 12 scrolls. -fireproof_quest.BOOK_POINTS = 4 -fireproof_quest.STAFF_POINTS = 3 -fireproof_quest.SCROLL_POINTS = 1 - -add_quest -{ - ["global"] = "FIREPROOF_QUEST", - ["name"] = "Old Mages quest", - ["desc"] = function() - local num_books, num_staff, num_scroll - - num_books = fireproof_quest.item_points_remaining / fireproof_quest.BOOK_POINTS - num_staff = fireproof_quest.item_points_remaining / fireproof_quest.STAFF_POINTS - num_scroll = fireproof_quest.item_points_remaining / fireproof_quest.SCROLL_POINTS - - -- Quest taken - if (quest(FIREPROOF_QUEST).status == QUEST_STATUS_TAKEN) then - print_hook("#####yAn Old Mages Quest!\n") - print_hook("Retrieve the strange rune for the old mage in Lothlorien.\n") - print_hook("\n") - -- essence retrieved, not taken to mage - elseif (quest(FIREPROOF_QUEST).status == QUEST_STATUS_COMPLETED) then - print_hook("#####yAn Old Mages Quest!\n") - print_hook("You have retrieved the rune for the old mage in Lothlorien. Perhaps you \n") - print_hook("should see about a reward.\n") - print_hook("\n") - -- essence returned, not all books fireproofed - elseif (quest(FIREPROOF_QUEST).status == QUEST_STATUS_FINISHED) and (fireproof_quest.item_points_remaining > 0) then - print_hook("#####yAn Old Mages Quest!\n") - print_hook("You have retrieved the rune for the old mage in Lothlorien. He will still \n") - print_hook("fireproof "..num_books.." book(s) or "..num_staff.." staff/staves or "..num_scroll.." scroll(s) for you.\n") - print_hook("\n") - end - end, - ["level"] = 20, - ["data"] = { - -- store some variables - ["fireproof_quest.item_points_remaining"] = fireproof_quest.TOTAL_ITEM_POINTS, - ["fireproof_quest.essence"] = 0, - }, - ["hooks"] = { - -- Start the game without the quest, need to request it - [HOOK_BIRTH_OBJECTS] = function() - quest(FIREPROOF_QUEST).status = QUEST_STATUS_UNTAKEN - - -- reset some variables on birth - fireproof_quest.item_points_remaining = fireproof_quest.TOTAL_ITEM_POINTS - fireproof_quest.essence = 0 - end, - [HOOK_GEN_QUEST] = function() - local essence, y, x, traps, tries, trap_y, trap_x, grid - - -- Only if player doing this quest - if (player.inside_quest ~= FIREPROOF_QUEST) then - return FALSE - else - -- load the map - load_map("fireprof.map", 2, 2) - - -- no teleport - level_flags2 = DF2_NO_TELEPORT - - -- determine type of item - fireproof_quest.essence = randint(5) - - -- create essence - essence = create_object(TV_RUNE2, fireproof_quest.essence) - - -- mark item - essence.pval2 = fireproof_quest.essence - essence.note = quark_add("quest") - - -- roll for co-ordinates in top half of map - y = randint(3) + 2 - x = randint(45) + 2 - - -- drop it - drop_near(essence, -1, y, x) - - -- how many traps to generate - traps = rand_range(10, 30) - - -- generate the traps - while (traps > 0) do - - -- initialise tries variable - tries = 0 - - -- make sure it's a safe place - while (tries == 0) do - - -- get grid coordinates - trap_y = randint(19) + 2 - trap_x = randint(45) + 2 - grid = cave(trap_y, trap_x) - - -- are the coordinates on a stair, or a wall? - if (cave_is(grid, FF1_PERMANENT) ~= 0) or (cave_is(grid, FF1_FLOOR) == 0) then - - -- try again - tries = 0 - else - -- not a stair, then stop this 'while' - tries = 1 - end - end - - -- randomise level of trap - trap_level = rand_range(20, 40) - - -- put the trap there - place_trap(trap_y, trap_x, trap_level) - - -- that's one less trap to place - traps = traps - 1 - end - return TRUE - end - end, - [HOOK_STAIR] = function() - local ret - - -- only ask this if player about to go up stairs of quest and hasn't retrieved item - if (player.inside_quest ~= FIREPROOF_QUEST) or - (quest(FIREPROOF_QUEST).status == QUEST_STATUS_COMPLETED) then - return FALSE - else - if cave(player.py, player.px).feat ~= FEAT_LESS then return end - - -- flush all pending input - flush() - - -- confirm - ret = get_check("Really abandon the quest?") - - -- if yes, then - if (ret == TRUE) then - - -- fail the quest - quest(FIREPROOF_QUEST).status = QUEST_STATUS_FAILED - return FALSE - else - -- if no, they stay in the quest - return TRUE - end - end - end, - [HOOK_GET] = function(o_ptr) - - -- if they're in the quest and haven't picked up the item already, continue - if (player.inside_quest ~= FIREPROOF_QUEST) or - (quest(FIREPROOF_QUEST).status == QUEST_STATUS_COMPLETED) then - return FALSE - else - - -- check that it's the real item and not another one generated via the random object placing in fireproof.map - if (o_ptr.pval2 == fireproof_quest.essence) then - - -- ok mark the quest 'completed' - quest(FIREPROOF_QUEST).status = QUEST_STATUS_COMPLETED - msg_print(TERM_YELLOW, "Fine! Looks like you've found it.") - end - end - end, - - }, -} - --- add the bit that determines what happens when the request 'q'uest bit is done in the wizard spire -add_building_action -{ - -- Index is used in ba_info.txt to set the actions - ["index"] = 56, - ["action"] = function() - - local i1 = "I need a very special rune for a spell I am working on. I am too old to " - local p = "Which rune?" - local pni = "You have no runes to return" - local tval = TV_RUNE2 - local location = "The rune is in a cave just behind the shop." - - local num_books, num_staff, num_scroll - - num_books = fireproof_quest.item_points_remaining / fireproof_quest.BOOK_POINTS - num_staff = fireproof_quest.item_points_remaining / fireproof_quest.STAFF_POINTS - num_scroll = fireproof_quest.item_points_remaining / fireproof_quest.SCROLL_POINTS - - -- the quest hasn;t been requested already, right? - if quest(FIREPROOF_QUEST).status == QUEST_STATUS_UNTAKEN then - - -- quest has been taken now - quest(FIREPROOF_QUEST).status = QUEST_STATUS_TAKEN - fireproof_quest.item_points_remaining = fireproof_quest.TOTAL_ITEM_POINTS - - -- issue instructions - msg_print(i1) - msg_print("fetch it myself. Please bring it back to me. You can find it north of here.") - msg_print("Be careful with it, it's fragile and might be destroyed easily.") - - return TRUE, FALSE, TRUE - -- if quest completed (item was retrieved) - elseif (quest(FIREPROOF_QUEST).status == QUEST_STATUS_COMPLETED) then - - -- ask for item - ret, item = get_item(p, - pni, - bor(USE_INVEN), - function (obj) - - -- check it's the 'marked' item - if (obj.tval == tval) and (obj.sval == fireproof_quest.essence) and (obj.pval2 == fireproof_quest.essence) then - return TRUE - end - return FALSE - end - ) - - -- didn't get the item? - if (ret == FALSE) then - return TRUE - - -- got the item! - else - - -- take item - inven_item_increase(item, -1) - inven_item_optimize(item) - msg_print("Great! Let me fireproof some of your items in thanks. I can do "..num_books.." books, ") - msg_print(num_staff.." staves, or "..num_scroll.." scrolls.") - - -- how many items to proof? - local items = fireproof_quest.item_points_remaining - - -- repeat till up to 3 (value defined as TOTAL_ITEM_POINTS constant) books fireproofed - while items > 0 do - ret = fireproof() - - -- don't loop the fireproof if there's nothing to fireproof - if ret == FALSE then - break - end - - -- subtract item points - items = fireproof_quest.item_points_remaining - end - - -- have they all been done? - if (fireproof_quest.item_points_remaining == 0) then - -- mark quest to make sure no more quests are given - quest(FIREPROOF_QUEST).status = QUEST_STATUS_REWARDED - else - -- mark in preparation of anymore books to fireproof - quest(FIREPROOF_QUEST).status = QUEST_STATUS_FINISHED - end - - - end - - -- if the player asks for a quest when they already have it, but haven't failed it, give them some extra instructions - elseif (quest(FIREPROOF_QUEST).status == QUEST_STATUS_TAKEN) then - msg_print(location) - - -- ok not all books have been fireproofed... lets do the rest - elseif (quest(FIREPROOF_QUEST).status == QUEST_STATUS_FINISHED) then - - -- how many books still to proof? - local items = fireproof_quest.item_points_remaining - - -- repeat as necessary - while items > 0 do - ret = fireproof() - - -- don't loop the fireproof if there's nothing to fireproof - if ret == FALSE then - break - else - -- have they all been done? - if (fireproof_quest.item_points_remaining == 0) then quest(FIREPROOF_QUEST).status = QUEST_STATUS_REWARDED end - end - - -- subtract item points - items = fireproof_quest.item_points_remaining - end - - -- quest failed or completed, then give no more quests - elseif (quest(FIREPROOF_QUEST).status == QUEST_STATUS_FAILED) or (quest(FIREPROOF_QUEST).status == QUEST_STATUS_REWARDED) then - msg_print("I have no more quests for you") - end - return TRUE - end, -} - --- the routine that checks for a book and actually fireproofs it -function fireproof() - - local ret, item, obj2, stack, obj3, carry_it - - ret, item = get_item("Which item shall I fireproof?", - "You have no more items I can fireproof, come back when you have some.", - bor(USE_INVEN), - function (obj) - - -- get some flags - local f1, f2, f3, f4, f5, esp = object_flags(obj) - - -- is it a book/staff/scroll, is it already fireproof? - if ((obj.tval == TV_BOOK) or (obj.tval == TV_SCROLL) or (obj.tval == TV_STAFF)) and (band(f3, TR3_IGNORE_FIRE) == 0) then - return TRUE - end - return FALSE - end - ) - - -- get the object type from the number - obj2 = get_object(item) - - -- check we have enough points (if we 'got' an item) - if (ret == TRUE) then - ret2, stack = enough_points(obj2) - end - - -- did either routine fail? - if (ret == FALSE) or (ret2 == FALSE) then - return FALSE - else - - -- are we part of the items from a stack? - if (obj2.number ~= stack) then - - -- make a new object to handle - object_copy(obj_forge, obj2) - - -- give it the right number of items - obj_forge.number = stack - - -- adjust for number of items in pack not to be fireproofed - obj2.number = obj2.number - stack - obj3 = obj_forge - - -- we'll need to add this to the inventory after fireproofing - carry_it = TRUE - else - - -- use the whole stack - obj3 = obj2 - - -- we'll be dealing this while it's still in the inventory - carry_it = FALSE - end - - -- make it fireproof - obj3.name2 = 149 - - -- apply it, making sure the pvals don't change with apply_magic (it would change the type of book!) - local oldpval = obj3.pval - local oldpval2 = obj3.pval2 - local oldpval3 = obj3.pval3 - apply_magic(obj3, -1, FALSE, FALSE, FALSE) - obj3.pval = oldpval - obj3.pval2 = oldpval2 - obj3.pval3 = oldpval3 - - -- put it in the inventory if it's only part of a stack - if (carry_it == TRUE) then - inven_carry(obj3, TRUE) - end - - -- id and notice it - set_known(obj3) - set_aware(obj3) - - return TRUE - end -end - --- This function makes sure the player has enough 'points' left to fireproof stuff. -function enough_points(obj) - local item_value, stack - - -- are the items in a stack? - if (obj.number > 1) then - - -- how many to fireproof? - stack = get_quantity("How many would you like fireproofed?", obj.number) - else - stack = 1 - end - - -- check for item type and multiply number in the stack by the amount of points per item of that type - if (obj.tval == TV_BOOK) then - item_value = fireproof_quest.BOOK_POINTS * stack - elseif (obj.tval == TV_STAFF) then - item_value = fireproof_quest.STAFF_POINTS * stack - elseif (obj.tval == TV_SCROLL) then - item_value = fireproof_quest.SCROLL_POINTS * stack - end - - -- do we have enough points? - if (item_value > fireproof_quest.item_points_remaining) then - msg_print("I do not have enough fireproofing material for that.") - return FALSE - else - -- if so then subtract those points before we do the fireproofing - fireproof_quest.item_points_remaining = fireproof_quest.item_points_remaining - item_value - end - - -- Used all the points? the quest is completely rewarded. - if fireproof_quest.item_points_remaining == 0 then quest(FIREPROOF_QUEST).status = QUEST_STATUS_REWARDED end - - return TRUE, stack -end - diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index 063ca21b..05954033 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -23,7 +23,6 @@ tome_dofile("spells.lua") -- Add some quests tome_dofile("god.lua") -tome_dofile("fireprof.lua") tome_dofile("library.lua") -- Add joke stuff diff --git a/lib/scpt/fireprof.lua b/lib/scpt/fireprof.lua deleted file mode 100644 index 0feb348b..00000000 --- a/lib/scpt/fireprof.lua +++ /dev/null @@ -1,421 +0,0 @@ --- The Old Mages/Fireproofing quest: Bring back an essence from a fiery cave and get some books/scrolls/staves fireproofed in return - -fireproof_quest = {} - - --- change this constant (and the FOO_POINTS ones) to adjust the no of items fire-proofed as a reward -fireproof_quest.TOTAL_ITEM_POINTS = 12 - --- These constants are how many 'points' each type of item will take up. So currently, you can fireproof 3 books, 4 staves or 12 scrolls. -fireproof_quest.BOOK_POINTS = 4 -fireproof_quest.STAFF_POINTS = 3 -fireproof_quest.SCROLL_POINTS = 1 - -add_quest -{ - ["global"] = "FIREPROOF_QUEST", - ["name"] = "Old Mages quest", - ["desc"] = function() - local num_books, num_staff, num_scroll - - num_books = fireproof_quest.item_points_remaining / fireproof_quest.BOOK_POINTS - num_staff = fireproof_quest.item_points_remaining / fireproof_quest.STAFF_POINTS - num_scroll = fireproof_quest.item_points_remaining / fireproof_quest.SCROLL_POINTS - - -- Quest taken - if (quest(FIREPROOF_QUEST).status == QUEST_STATUS_TAKEN) then - print_hook("#####yAn Old Mages Quest!\n") - print_hook("Retrieve the strange essence for the old mage in Lothlorien.\n") - print_hook("\n") - -- essence retrieved, not taken to mage - elseif (quest(FIREPROOF_QUEST).status == QUEST_STATUS_COMPLETED) then - print_hook("#####yAn Old Mages Quest!\n") - print_hook("You have retrieved the essence for the old mage in Lothlorien. Perhaps you \n") - print_hook("should see about a reward.\n") - print_hook("\n") - -- essence returned, not all books fireproofed - elseif (quest(FIREPROOF_QUEST).status == QUEST_STATUS_FINISHED) and (fireproof_quest.item_points_remaining > 0) then - print_hook("#####yAn Old Mages Quest!\n") - print_hook("You have retrieved the essence for the old mage in Lothlorien. He will still \n") - print_hook("fireproof "..num_books.." book(s) or "..num_staff.." staff/staves or "..num_scroll.." scroll(s) for you.\n") - print_hook("\n") - end - end, - ["level"] = 20, - ["data"] = { - -- store some variables - ["fireproof_quest.item_points_remaining"] = fireproof_quest.TOTAL_ITEM_POINTS, - ["fireproof_quest.essence"] = 0, - }, - ["hooks"] = { - -- Start the game without the quest, need to request it - [HOOK_BIRTH_OBJECTS] = function() - quest(FIREPROOF_QUEST).status = QUEST_STATUS_UNTAKEN - - -- reset some variables on birth - fireproof_quest.item_points_remaining = fireproof_quest.TOTAL_ITEM_POINTS - fireproof_quest.essence = 0 - end, - [HOOK_GEN_QUEST] = function() - local essence, y, x, traps, tries, trap_y, trap_x, grid - - -- Only if player doing this quest - if (player.inside_quest ~= FIREPROOF_QUEST) then - return FALSE - else - -- load the map - load_map("fireprof.map", 2, 2) - - -- no teleport - level_flags2 = DF2_NO_TELEPORT - - -- determine type of item - fireproof_quest.essence = randint(18) - - -- create essence - essence = create_object(TV_BATERIE, fireproof_quest.essence) - - -- mark item - essence.pval2 = fireproof_quest.essence - essence.note = quark_add("quest") - - -- roll for co-ordinates in top half of map - y = randint(3) + 2 - x = randint(45) + 2 - - -- drop it - drop_near(essence, -1, y, x) - - -- how many traps to generate - traps = rand_range(10, 30) - - -- generate the traps - while (traps > 0) do - - -- initialise tries variable - tries = 0 - - -- make sure it's a safe place - while (tries == 0) do - - -- get grid coordinates - trap_y = randint(19) + 2 - trap_x = randint(45) + 2 - grid = cave(trap_y, trap_x) - - -- are the coordinates on a stair, or a wall? - if (cave_is(grid, FF1_PERMANENT) ~= 0) or (cave_is(grid, FF1_FLOOR) == 0) then - - -- try again - tries = 0 - else - -- not a stair, then stop this 'while' - tries = 1 - end - end - - -- randomise level of trap - trap_level = rand_range(20, 40) - - -- put the trap there - place_trap(trap_y, trap_x, trap_level) - - -- that's one less trap to place - traps = traps - 1 - end - return TRUE - end - end, - [HOOK_STAIR] = function() - local ret - - -- only ask this if player about to go up stairs of quest and hasn't retrieved item - if (player.inside_quest ~= FIREPROOF_QUEST) or - (quest(FIREPROOF_QUEST).status == QUEST_STATUS_COMPLETED) then - return FALSE - else - if cave(player.py, player.px).feat ~= FEAT_LESS then return end - - -- flush all pending input - flush() - - -- confirm - ret = get_check("Really abandon the quest?") - - -- if yes, then - if (ret == TRUE) then - - -- fail the quest - quest(FIREPROOF_QUEST).status = QUEST_STATUS_FAILED - return FALSE - else - -- if no, they stay in the quest - return TRUE - end - end - end, - [HOOK_GET] = function(o_ptr) - - -- if they're in the quest and haven't picked up the item already, continue - if (player.inside_quest ~= FIREPROOF_QUEST) or - (quest(FIREPROOF_QUEST).status == QUEST_STATUS_COMPLETED) then - return FALSE - else - - -- check that it's the real item and not another one generated via the random object placing in fireproof.map - if (o_ptr.pval2 == fireproof_quest.essence) then - - -- ok mark the quest 'completed' - quest(FIREPROOF_QUEST).status = QUEST_STATUS_COMPLETED - msg_print(TERM_YELLOW, "Fine! Looks like you've found it.") - end - end - end, - - }, -} - --- add the bit that determines what happens when the request 'q'uest bit is done in the wizard spire -add_building_action -{ - -- Index is used in ba_info.txt to set the actions - ["index"] = 56, - ["action"] = function() - - local i1 = "I need a very special essence for a spell I am working on. I am too old to " - local p = "Which essence?" - local pni = "You have no essences to return" - local tval = TV_BATERIE - local location = "The essence is in a cave just behind the shop." - - local num_books, num_staff, num_scroll - - num_books = fireproof_quest.item_points_remaining / fireproof_quest.BOOK_POINTS - num_staff = fireproof_quest.item_points_remaining / fireproof_quest.STAFF_POINTS - num_scroll = fireproof_quest.item_points_remaining / fireproof_quest.SCROLL_POINTS - - -- the quest hasn;t been requested already, right? - if quest(FIREPROOF_QUEST).status == QUEST_STATUS_UNTAKEN then - - -- quest has been taken now - quest(FIREPROOF_QUEST).status = QUEST_STATUS_TAKEN - fireproof_quest.item_points_remaining = fireproof_quest.TOTAL_ITEM_POINTS - - -- issue instructions - msg_print(i1) - msg_print("fetch it myself. Please bring it back to me. You can find it north of here.") - msg_print("Be careful with it, it's fragile and might be destroyed easily.") - - return TRUE, FALSE, TRUE - -- if quest completed (item was retrieved) - elseif (quest(FIREPROOF_QUEST).status == QUEST_STATUS_COMPLETED) then - - -- ask for item - ret, item = get_item(p, - pni, - bor(USE_INVEN), - function (obj) - - -- check it's the 'marked' item - if (obj.tval == tval) and (obj.sval == fireproof_quest.essence) and (obj.pval2 == fireproof_quest.essence) then - return TRUE - end - return FALSE - end - ) - - -- didn't get the item? - if (ret == FALSE) then - return TRUE - - -- got the item! - else - - -- take item - inven_item_increase(item, -1) - inven_item_optimize(item) - msg_print("Great! Let me fireproof some of your items in thanks. I can do "..num_books.." books, ") - msg_print(num_staff.." staves, or "..num_scroll.." scrolls.") - - -- how many items to proof? - local items = fireproof_quest.item_points_remaining - - -- repeat till up to 3 (value defined as TOTAL_ITEM_POINTS constant) books fireproofed - while items > 0 do - ret = fireproof() - - -- don't loop the fireproof if there's nothing to fireproof - if ret == FALSE then - break - end - - -- subtract item points - items = fireproof_quest.item_points_remaining - end - - -- have they all been done? - if (fireproof_quest.item_points_remaining == 0) then - -- mark quest to make sure no more quests are given - quest(FIREPROOF_QUEST).status = QUEST_STATUS_REWARDED - else - -- mark in preparation of anymore books to fireproof - quest(FIREPROOF_QUEST).status = QUEST_STATUS_FINISHED - end - - - end - - -- if the player asks for a quest when they already have it, but haven't failed it, give them some extra instructions - elseif (quest(FIREPROOF_QUEST).status == QUEST_STATUS_TAKEN) then - msg_print(location) - - -- ok not all books have been fireproofed... lets do the rest - elseif (quest(FIREPROOF_QUEST).status == QUEST_STATUS_FINISHED) then - - -- how many books still to proof? - local items = fireproof_quest.item_points_remaining - - -- repeat as necessary - while items > 0 do - ret = fireproof() - - -- don't loop the fireproof if there's nothing to fireproof - if ret == FALSE then - break - else - -- have they all been done? - if (fireproof_quest.item_points_remaining == 0) then quest(FIREPROOF_QUEST).status = QUEST_STATUS_REWARDED end - end - - -- subtract item points - items = fireproof_quest.item_points_remaining - end - - -- quest failed or completed, then give no more quests - elseif (quest(FIREPROOF_QUEST).status == QUEST_STATUS_FAILED) or (quest(FIREPROOF_QUEST).status == QUEST_STATUS_REWARDED) then - msg_print("I have no more quests for you") - end - return TRUE - end, -} - --- the routine that checks for a book and actually fireproofs it -function fireproof() - - local ret, item, obj2, stack, obj3, carry_it - - ret, item = get_item("Which item shall I fireproof?", - "You have no more items I can fireproof, come back when you have some.", - bor(USE_INVEN), - function (obj) - - -- get some flags - local f1, f2, f3, f4, f5, esp = object_flags(obj) - - -- is it a book/staff/scroll, is it already fireproof? - if ((obj.tval == TV_BOOK) or (obj.tval == TV_SCROLL) or (obj.tval == TV_STAFF)) and (band(f3, TR3_IGNORE_FIRE) == 0) then - return TRUE - end - return FALSE - end - ) - - -- get the object type from the number - obj2 = get_object(item) - - -- check we have enough points (if we 'got' an item) - if (ret == TRUE) then - ret2, stack = enough_points(obj2) - end - - -- did either routine fail? - if (ret == FALSE) or (ret2 == FALSE) then - return FALSE - else - - -- are we part of the items from a stack? - if (obj2.number ~= stack) then - - -- make a new object to handle - object_copy(obj_forge, obj2) - - -- give it the right number of items - obj_forge.number = stack - - -- adjust for number of items in pack not to be fireproofed - obj2.number = obj2.number - stack - obj3 = obj_forge - - -- we'll need to add this to the inventory after fireproofing - carry_it = TRUE - else - - -- use the whole stack - obj3 = obj2 - - -- we'll be dealing this while it's still in the inventory - carry_it = FALSE - end - - -- make it fireproof - obj3.name2 = 149 - - -- apply it, making sure the pvals don't change with apply_magic (it would change the type of book!) - local oldpval = obj3.pval - local oldpval2 = obj3.pval2 - local oldpval3 = obj3.pval3 - apply_magic(obj3, -1, FALSE, FALSE, FALSE) - obj3.pval = oldpval - obj3.pval2 = oldpval2 - obj3.pval3 = oldpval3 - - -- put it in the inventory if it's only part of a stack - if (carry_it == TRUE) then - inven_carry(obj3, TRUE) - end - - -- id and notice it - set_known(obj3) - set_aware(obj3) - - return TRUE - end -end - --- This function makes sure the player has enough 'points' left to fireproof stuff. -function enough_points(obj) - local item_value, stack - - -- are the items in a stack? - if (obj.number > 1) then - - -- how many to fireproof? - stack = get_quantity("How many would you like fireproofed?", obj.number) - else - stack = 1 - end - - -- check for item type and multiply number in the stack by the amount of points per item of that type - if (obj.tval == TV_BOOK) then - item_value = fireproof_quest.BOOK_POINTS * stack - elseif (obj.tval == TV_STAFF) then - item_value = fireproof_quest.STAFF_POINTS * stack - elseif (obj.tval == TV_SCROLL) then - item_value = fireproof_quest.SCROLL_POINTS * stack - end - - -- do we have enough points? - if (item_value > fireproof_quest.item_points_remaining) then - msg_print("I do not have enough fireproofing material for that.") - return FALSE - else - -- if so then subtract those points before we do the fireproofing - fireproof_quest.item_points_remaining = fireproof_quest.item_points_remaining - item_value - end - - -- Used all the points? the quest is completely rewarded. - if fireproof_quest.item_points_remaining == 0 then quest(FIREPROOF_QUEST).status = QUEST_STATUS_REWARDED end - - return TRUE, stack -end - diff --git a/lib/scpt/init.lua b/lib/scpt/init.lua index 3b461d19..48ac15a7 100644 --- a/lib/scpt/init.lua +++ b/lib/scpt/init.lua @@ -22,7 +22,6 @@ tome_dofile("gods.lua") -- Add some quests tome_dofile("god.lua") -tome_dofile("fireprof.lua") tome_dofile("library.lua") -- Add joke stuff diff --git a/src/bldg.c b/src/bldg.c index 66ca9d9d..bf284a7a 100644 --- a/src/bldg.c +++ b/src/bldg.c @@ -2048,6 +2048,12 @@ bool_ bldg_process_command(store_type *s_ptr, int i) break; } + case BACT_FIREPROOF_QUEST: + { + quest_fireproof_building(&paid, &recreate); + break; + } + default: { if (process_hooks_ret(HOOK_BUILDING_ACTION, "dd", "(d)", bact)) diff --git a/src/defines.h b/src/defines.h index d78ed058..94074690 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4046,6 +4046,7 @@ #define BACT_PAY_BACK_LOAN 53 #define BACT_DROP_ITEM 54 #define BACT_GET_ITEM 55 +#define BACT_FIREPROOF_QUEST 56 #define BACT_LIBRARY_QUEST 61 /* If one adds new BACT_ do NOT forget to increase max_bact in variables.c */ @@ -4418,7 +4419,8 @@ #define QUEST_HAUNTED 24 #define QUEST_EVIL 25 #define QUEST_BOUNTY 26 -#define MAX_Q_IDX_INIT 27 +#define QUEST_FIREPROOF 27 +#define MAX_Q_IDX_INIT 28 #define PLOT_MAIN 0 #define PLOT_BREE 1 diff --git a/src/externs.h b/src/externs.h index fd6802d8..cf56abcc 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1213,6 +1213,7 @@ extern void do_cmd_power(void); extern bool_ player_activate_trap_type(s16b y, s16b x, object_type *i_ptr, s16b item); extern void player_activate_door_trap(s16b y, s16b x); extern void place_trap(int y, int x); +extern void place_trap_leveled(int y, int x, int lev); extern void place_trap_object(object_type *o_ptr); extern void wiz_place_trap(int y, int x, int idx); extern void do_cmd_set_trap(void); diff --git a/src/plots.c b/src/plots.c index b26d1e20..08d0ea90 100644 --- a/src/plots.c +++ b/src/plots.c @@ -11,6 +11,7 @@ */ #include "angband.h" +#include #include "lua/lua.h" #include "tolua.h" @@ -477,3 +478,6 @@ bool_ quest_null_hook(int q) /************************** Library Quest *************************/ #include "q_library.c" + +/************************* Fireproofing Quest *********************/ +#include "q_fireprof.c" diff --git a/src/plots.h b/src/plots.h index 73e4b8a8..702bb55e 100644 --- a/src/plots.h +++ b/src/plots.h @@ -56,3 +56,8 @@ extern bool_ quest_bounty_describe(FILE *fff); /******* Plot Library Quest *******/ extern void quest_library_gen_hook(); extern void quest_library_building(bool_ *paid, bool_ *recreate); + +/******* Plot Fireproof Quest *********/ +extern void quest_fireproof_building(bool_ *paid, bool_ *recreate); +extern bool_ quest_fireproof_init_hook(int q); +extern bool_ quest_fireproof_describe(FILE *fff); diff --git a/src/q_fireprof.c b/src/q_fireprof.c new file mode 100644 index 00000000..35ca7d7e --- /dev/null +++ b/src/q_fireprof.c @@ -0,0 +1,584 @@ +#undef cquest +#define cquest (quest[QUEST_FIREPROOF]) + +#define print_hook(fmt,...) do { fprintf(hook_file, fmt, ##__VA_ARGS__); } while (0) + +/* + * Per-module "settings" + */ +typedef struct fireproof_settings fireproof_settings; +struct fireproof_settings +{ + byte tval; /* tval of object to use. */ + cptr tval_name; /* descriptive name of tval */ + cptr tval_name_plural; /* descriptive name of tval (plural) */ + byte sval_max; /* max sval of object to use; sval will be 1<=X<=sval_max. */ + s32b total_points; /* total number of points awarded */ +}; + +static fireproof_settings const *fireproof_get_settings() +{ + static fireproof_settings fireproof_settings_tome = + { TV_BATERIE, "essence", "essences", 18, 12 }; + static fireproof_settings fireproof_settings_theme = + { TV_RUNE2, "rune", "runes", 5, 24 }; + + if (game_module_idx == MODULE_TOME) + { + return &fireproof_settings_tome; + } + if (game_module_idx == MODULE_THEME) + { + return &fireproof_settings_theme; + } + /* If we get here we're in trouble. */ + assert(FALSE); + return NULL; +} + +/* These constants are how many 'points' each type of item will take + * up. So currently, you can fireproof 3 books, 4 staves or 12 + * scrolls. */ +#define FIREPROOF_BOOK_POINTS 4 +#define FIREPROOF_STAFF_POINTS 3 +#define FIREPROOF_SCROLL_POINTS 1 + +static s32b get_item_points_remaining() +{ + fireproof_settings const *settings = fireproof_get_settings(); + return settings->total_points - cquest.data[0]; +} + +static void set_item_points_remaining(s32b v) +{ + fireproof_settings const *settings = fireproof_get_settings(); + cquest.data[0] = settings->total_points - v; +} + +static void fireproof_set_sval(int sval_max) +{ + cquest.data[1] = sval_max; +} + +static int fireproof_get_sval() +{ + return cquest.data[1]; +} + +static bool_ item_tester_hook_eligible(object_type *o_ptr) +{ + /* check it's the 'marked' item */ + if ((o_ptr->tval == fireproof_get_settings()->tval) && + (o_ptr->sval == fireproof_get_sval()) && + (o_ptr->pval2 == fireproof_get_sval())) + { + return TRUE; + } + else + { + return FALSE; + } +} + +static bool_ item_tester_hook_proofable(object_type *o_ptr) +{ + u32b f1, f2, f3, f4, f5, esp; + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* is it a book/staff/scroll, is it already fireproof? */ + if (((o_ptr->tval == TV_BOOK) || + (o_ptr->tval == TV_SCROLL) || + (o_ptr->tval == TV_STAFF)) + && ((f3 & TR3_IGNORE_FIRE) == 0)) + { + return TRUE; + } + else + { + return FALSE; + } +} + +/* + * This function makes sure the player has enough 'points' left to fireproof stuff. + */ +static bool_ fireproof_enough_points(object_type *o_ptr, int *stack) +{ + int item_value; + + /* are the items in a stack? */ + if (o_ptr->number > 1) + { + /* how many to fireproof? */ + *stack = get_quantity("How many would you like fireproofed?", o_ptr->number); + } + else + { + *stack = 1; + } + + /* check for item type and multiply number in the stack by the + * amount of points per item of that type */ + if (o_ptr->tval == TV_BOOK) + { + item_value = FIREPROOF_BOOK_POINTS * (*stack); + } + else if (o_ptr->tval == TV_STAFF) + { + item_value = FIREPROOF_STAFF_POINTS * (*stack); + } + else if (o_ptr->tval == TV_SCROLL) + { + item_value = FIREPROOF_SCROLL_POINTS * (*stack); + } + + /* do we have enough points? */ + if (item_value > get_item_points_remaining()) + { + msg_print("I do not have enough fireproofing material for that."); + return FALSE; + } + else + { + /* if so then subtract those points before we do the fireproofing */ + set_item_points_remaining(get_item_points_remaining() - item_value); + } + + /* Used all the points? the quest is completely rewarded. */ + if (get_item_points_remaining() == 0) + { + cquest.status = QUEST_STATUS_REWARDED; + } + + return TRUE; +} + +static bool_ fireproof() +{ + int ret, item, stack = 0; + object_type *obj2 = NULL; + bool_ ret2; + + item_tester_hook = item_tester_hook_proofable; + ret = get_item(&item, + "Which item shall I fireproof?", + "You have no more items I can fireproof, come back when you have some.", + USE_INVEN); + + /* get the object type from the number */ + obj2 = get_object(item); + + /* check we have enough points (if we 'got' an item) */ + if (ret == TRUE) { + ret2 = fireproof_enough_points(obj2, &stack); + } + + /* did either routine fail? */ + if ((ret == FALSE) || (ret2 == FALSE)) + { + return FALSE; + } + else + { + bool_ carry_it; + object_type *obj3; + object_type obj_forge; + s32b oldpval, oldpval2, oldpval3; + + /* are we part of the items from a stack? */ + if (obj2->number != stack) { + + /* make a new object to handle */ + object_copy(&obj_forge, obj2); + + /* give it the right number of items */ + obj_forge.number = stack; + + /* adjust for number of items in pack not to be fireproofed */ + obj2->number = obj2->number - stack; + obj3 = &obj_forge; + + /* we'll need to add this to the inventory after fireproofing */ + carry_it = TRUE; + } + else + { + /* use the whole stack */ + obj3 = obj2; + + /* we'll be dealing this while it's still in the inventory */ + carry_it = FALSE; + } + + /* make it fireproof */ + obj3->name2 = 149; + + /* apply it, making sure the pvals don't change with + * apply_magic (it would change the type of book!) */ + oldpval = obj3->pval; + oldpval2 = obj3->pval2; + oldpval3 = obj3->pval3; + apply_magic(obj3, -1, FALSE, FALSE, FALSE); + obj3->pval = oldpval; + obj3->pval2 = oldpval2; + obj3->pval3 = oldpval3; + + /* put it in the inventory if it's only part of a stack */ + if (carry_it == TRUE) + { + inven_carry(obj3, TRUE); + } + + /* id and notice it */ + object_known(obj3); + object_aware(obj3); + + return TRUE; + } +} + + +void quest_fireproof_building(bool_ *paid, bool_ *recreate) +{ + fireproof_settings const *settings = fireproof_get_settings(); + int num_books, num_staff, num_scroll; + + num_books = get_item_points_remaining() / FIREPROOF_BOOK_POINTS; + num_staff = get_item_points_remaining() / FIREPROOF_STAFF_POINTS; + num_scroll = get_item_points_remaining() / FIREPROOF_SCROLL_POINTS; + + /* the quest hasn't been requested already, right? */ + if (cquest.status == QUEST_STATUS_UNTAKEN) + { + /* quest has been taken now */ + cquest.status = QUEST_STATUS_TAKEN; + + /* issue instructions */ + msg_format("I need a very special %s for a spell I am" + " working on. I am too old to ", settings->tval_name); + msg_print("fetch it myself. Please bring it back to me. You can find it north of here."); + msg_print("Be careful with it, it's fragile and might be destroyed easily."); + + *paid = FALSE; + *recreate = TRUE; + } + + /* if quest completed (item was retrieved) */ + else if (cquest.status == QUEST_STATUS_COMPLETED) + { + char p[512]; + char pni[512]; + int item_idx; + int ret; + + /* generate prompt strings */ + snprintf(p , sizeof(p) , "Which %s?", settings->tval_name); + snprintf(pni, sizeof(pni), "You have no %s to return", settings->tval_name_plural); + + /* ask for item */ + item_tester_hook = item_tester_hook_eligible; + ret = get_item(&item_idx, p, pni, USE_INVEN); + + /* didn't get the item? */ + if (!ret) + { + return; + } + + /* got the item! */ + else + { + int items; + + /* take item */ + inc_stack_size_ex(item_idx, -1, OPTIMIZE, NO_DESCRIBE); + + msg_print(format("Great! Let me fireproof some of your items in thanks. I can do %d books, ", num_books)); + msg_print(format("%d staves, or %d scrolls.", num_staff, num_scroll)); + + /* how many items to proof? */ + items = get_item_points_remaining(); + + /* repeat till up to 3 (value defined as constant) books fireproofed */ + while (items > 0) + { + ret = fireproof(); + + /* don't loop the fireproof if there's nothing to fireproof */ + if (ret == FALSE) + { + break; + } + + /* subtract item points */ + items = get_item_points_remaining(); + } + + /* have they all been done? */ + if (get_item_points_remaining() == 0) + { + /* mark quest to make sure no more quests are given */ + cquest.status = QUEST_STATUS_REWARDED; + } + else + { + /* mark in preparation of anymore books to fireproof */ + cquest.status = QUEST_STATUS_FINISHED; + } + } + } + + /* if the player asks for a quest when they already have it, but haven't failed it, give them some extra instructions */ + else if (cquest.status == QUEST_STATUS_TAKEN) + { + msg_format("The %s is in a cave just behind the shop.", + settings->tval_name); + } + + /* ok not all books have been fireproofed... lets do the rest */ + else if (cquest.status == QUEST_STATUS_FINISHED) + { + + /* how many books still to proof? */ + int items = get_item_points_remaining(); + + /* repeat as necessary */ + while (items > 0) + { + int ret = fireproof(); + + /* don't loop the fireproof if there's nothing to fireproof */ + if (ret == FALSE) + { + break; + } + else + { + /* have they all been done? */ + if (get_item_points_remaining() == 0) + { + cquest.status = QUEST_STATUS_REWARDED; + } + } + + /* subtract item points */ + items = get_item_points_remaining(); + } + + } + + /* quest failed or completed, then give no more quests */ + else if ((cquest.status == QUEST_STATUS_FAILED) || + (cquest.status == QUEST_STATUS_REWARDED)) + { + msg_print("I have no more quests for you"); + } +} + +static bool_ fireproof_get_hook(char *fmt) +{ + object_type *o_ptr = param_pile[0].o_ptr; + assert(o_ptr != NULL); + + /* check that player is in the quest, haven't picked up the + * item already, and check that it's the real item and not another one + * generated via random object placement */ + if ((p_ptr->inside_quest == QUEST_FIREPROOF) && + (cquest.status != QUEST_STATUS_COMPLETED) && + (o_ptr->pval2 == fireproof_get_sval())) + { + /* ok mark the quest 'completed' */ + cquest.status = QUEST_STATUS_COMPLETED; + cmsg_print(TERM_YELLOW, "Fine! Looks like you've found it."); + } + + return FALSE; +} + +static bool_ fireproof_stair_hook(char *fmt) +{ + /* only ask this if player about to go up stairs of quest and + * hasn't retrieved item */ + if ((p_ptr->inside_quest != QUEST_FIREPROOF) || + (cquest.status == QUEST_STATUS_COMPLETED)) + { + return FALSE; + } + else + { + bool ret; + + if (cave[p_ptr->py][p_ptr->px].feat != FEAT_LESS) + { + return FALSE; + } + + /* flush all pending input */ + flush(); + + /* confirm */ + ret = get_check("Really abandon the quest?"); + + /* if yes, then */ + if (ret == TRUE) + { + /* fail the quest */ + cquest.status = QUEST_STATUS_FAILED; + return FALSE; + } + else + { + /* if no, they stay in the quest */ + return TRUE; + } + } +} + +bool_ quest_fireproof_describe(FILE *hook_file) +{ + fireproof_settings const *settings = fireproof_get_settings(); + int num_books, num_staff, num_scroll; + int status = cquest.status; + + num_books = get_item_points_remaining() / FIREPROOF_BOOK_POINTS; + num_staff = get_item_points_remaining() / FIREPROOF_STAFF_POINTS; + num_scroll = get_item_points_remaining() / FIREPROOF_SCROLL_POINTS; + + if (status == QUEST_STATUS_TAKEN) + { + /* Quest taken */ + print_hook("#####yAn Old Mages Quest!\n"); + print_hook("Retrieve the strange %s for the old mage " + "in Lothlorien.\n", settings->tval_name); + print_hook("\n"); + } + else if (status == QUEST_STATUS_COMPLETED) + { + /* essence retrieved, not taken to mage */ + print_hook("#####yAn Old Mages Quest!\n"); + print_hook("You have retrieved the %s for the old " + "mage in Lothlorien. Perhaps you \n", settings->tval_name); + print_hook("should see about a reward.\n"); + print_hook("\n"); + } + else if ((status == QUEST_STATUS_FINISHED) && + (get_item_points_remaining() > 0)) + { + /* essence returned, not all books fireproofed */ + print_hook("#####yAn Old Mages Quest!\n"); + print_hook("You have retrieved the %s for the old " + "mage in Lothlorien. He will still \n", settings->tval_name); + print_hook("fireproof %d book(s) or %d staff/staves " + "or %d scroll(s) for you.\n", + num_books, num_staff, num_scroll); + print_hook("\n"); + } + + return TRUE; +} + +static bool_ fireproof_gen_hook(char *fmt) +{ + fireproof_settings const *settings = fireproof_get_settings(); + + /* Only if player doing this quest */ + if (p_ptr->inside_quest != QUEST_FIREPROOF) + { + return FALSE; + } + + /* Go ahead */ + { + int traps, trap_y, trap_x; + + /* load the map */ + { + int x0 = 2; + int y0 = 2; + load_map("fireprof.map", &y0, &x0); + } + + /* no teleport */ + dungeon_flags2 = DF2_NO_TELEPORT; + + /* determine type of item */ + fireproof_set_sval(randint(settings->sval_max)); + + /* create essence */ + { + int x, y; + object_type forge; + + object_prep(&forge, lookup_kind(settings->tval, fireproof_get_sval())); + + /* mark item */ + forge.pval2 = fireproof_get_sval(); + forge.note = quark_add("quest"); + + /* roll for co-ordinates in top half of map */ + y = randint(3) + 2; + x = randint(45) + 2; + + /* drop it */ + drop_near(&forge, -1, y, x); + } + + /* how many traps to generate */ + traps = rand_range(10, 30); + + /* generate the traps */ + while (traps > 0) + { + int tries = 0, trap_level = 0; + + /* make sure it's a safe place */ + while (tries == 0) + { + /* get grid coordinates */ + trap_y = randint(19) + 2; + trap_x = randint(45) + 2; + cave_type *c_ptr = &cave[trap_y][trap_x]; + + /* are the coordinates on a stair, or a wall? */ + if (((f_info[c_ptr->feat].flags1 & FF1_PERMANENT) != 0) || + ((f_info[c_ptr->feat].flags1 & FF1_FLOOR) == 0)) + { + /* try again */ + tries = 0; + } + else + { + /* not a stair, then stop this 'while' */ + tries = 1; + } + } + + /* randomise level of trap */ + trap_level = rand_range(20, 40); + + /* put the trap there */ + place_trap_leveled(trap_y, trap_x, trap_level); + + /* that's one less trap to place */ + traps = traps - 1; + } + + return TRUE; + } +} + +bool_ quest_fireproof_init_hook(int q) +{ + /* Only need hooks if the quest is unfinished. */ + if ((cquest.status >= QUEST_STATUS_UNTAKEN) && + (cquest.status < QUEST_STATUS_FINISHED)) + { + add_hook(HOOK_GEN_QUEST, fireproof_gen_hook , "fireproof_gen_hook"); + add_hook(HOOK_GET , fireproof_get_hook , "fireproof_get_hook"); + add_hook(HOOK_STAIR , fireproof_stair_hook, "fireproof_stair_hook"); + } + + return FALSE; +} + +#undef print_hook diff --git a/src/tables.c b/src/tables.c index b736bb85..259fd5ae 100644 --- a/src/tables.c +++ b/src/tables.c @@ -4285,7 +4285,22 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] = {0, 0, 0, 0}, quest_bounty_describe, }, - + /* Fireproofing */ + { + FALSE, + TRUE, + "Old Mages quest", + { + "", /* dynamic desc */ + }, + QUEST_STATUS_UNTAKEN, + 20, + NULL, + HOOK_TYPE_C, + quest_fireproof_init_hook, + {0, 0, 0, 0}, + quest_fireproof_describe, + }, }; diff --git a/src/traps.c b/src/traps.c index 1c8e36c9..0006edc7 100644 --- a/src/traps.c +++ b/src/traps.c @@ -2061,6 +2061,17 @@ void place_trap(int y, int x) } +/* + * Place a leveled trap at given position + */ +void place_trap_leveled(int y, int x, int lev) +{ + int prev_dun_level = dun_level; + dun_level = lev; + place_trap(y,x); + dun_level = prev_dun_level; +} + /* * Places a random trap on the given chest. * -- cgit v1.2.3 From 1a33c8c5f7eb8d36642c59c37284cc8f06c3e102 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 8 Apr 2012 17:52:16 +0200 Subject: Lua: Library quest: Move more generation code to C --- lib/mods/theme/scpt/library.lua | 13 +------------ lib/scpt/library.lua | 13 +------------ src/plots.h | 2 +- src/q_library.c | 23 ++++++++++++++++++++++- src/util.pkg | 2 +- 5 files changed, 26 insertions(+), 27 deletions(-) diff --git a/lib/mods/theme/scpt/library.lua b/lib/mods/theme/scpt/library.lua index d2851a23..fca935fb 100644 --- a/lib/mods/theme/scpt/library.lua +++ b/lib/mods/theme/scpt/library.lua @@ -98,18 +98,7 @@ add_quest end, [HOOK_GEN_QUEST] = function() - -- Only if player doing this quest - if (player.inside_quest ~= LIBRARY_QUEST) then - return FALSE - end - - load_map("library.map", 2, 2) - level_flags2 = DF2_NO_GENO - - -- generate monsters - quest_library_gen_hook() - - return TRUE + return quest_library_gen_hook() end, [HOOK_STAIR] = function() local ret diff --git a/lib/scpt/library.lua b/lib/scpt/library.lua index ad546b54..202ba268 100644 --- a/lib/scpt/library.lua +++ b/lib/scpt/library.lua @@ -95,18 +95,7 @@ add_quest end, [HOOK_GEN_QUEST] = function() - -- Only if player doing this quest - if (player.inside_quest ~= LIBRARY_QUEST) then - return FALSE - end - - load_map("library.map", 2, 2) - level_flags2 = DF2_NO_GENO - - -- generate monsters - quest_library_gen_hook() - - return TRUE + return quest_library_gen_hook() end, [HOOK_STAIR] = function() local ret diff --git a/src/plots.h b/src/plots.h index 702bb55e..da8a6cd2 100644 --- a/src/plots.h +++ b/src/plots.h @@ -54,7 +54,7 @@ extern bool_ quest_bounty_get_item(); extern bool_ quest_bounty_describe(FILE *fff); /******* Plot Library Quest *******/ -extern void quest_library_gen_hook(); +extern bool_ quest_library_gen_hook(); extern void quest_library_building(bool_ *paid, bool_ *recreate); /******* Plot Fireproof Quest *********/ diff --git a/src/q_library.c b/src/q_library.c index 6bb8baaa..d7a098cd 100644 --- a/src/q_library.c +++ b/src/q_library.c @@ -7,6 +7,11 @@ #define MONSTER_IRON_GOLEM 367 #define MONSTER_MITHRIL_GOLEM 464 +static int LIBRARY_QUEST() +{ + return get_lua_int("LIBRARY_QUEST"); +} + static s16b library_quest_place_random(int minY, int minX, int maxY, int maxX, int r_idx) { int y = randint(maxY - minY + 1) + minY; @@ -214,8 +219,22 @@ void library_quest_fill_book() screen_load(); } -void quest_library_gen_hook() +bool_ quest_library_gen_hook() { + /* Only if player doing this quest */ + if (p_ptr->inside_quest != LIBRARY_QUEST()) + { + return FALSE; + } + + { + int y = 2; + int x = 2; + load_map("library.map", &y, &x); + dungeon_flags2 = DF2_NO_GENO; + } + + /* Generate monsters */ library_quest_place_nrandom( 4, 4, 14, 37, MONSTER_LICH, damroll(4,2)); @@ -239,6 +258,8 @@ void quest_library_gen_hook() library_quest_place_nrandom( 10, 10, 37, 67, MONSTER_MITHRIL_GOLEM, 1); + + return TRUE; } static int get_status() diff --git a/src/util.pkg b/src/util.pkg index 0be3cb8b..49924e7f 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -2473,7 +2473,7 @@ extern void lite_spot(int y, int x); extern bool drop_text_left(byte c, cptr s, int y, int o); extern bool drop_text_right(byte c, cptr s, int y, int o); -extern void quest_library_gen_hook(); +extern bool quest_library_gen_hook(); /** * Mimicry -- cgit v1.2.3 From 00205df89e9c1bc2560d907c7fe6f9530a493d3b Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 8 Apr 2012 18:06:02 +0200 Subject: Lua: Library quest: Move HOOK_STAIR code to C --- lib/mods/theme/scpt/library.lua | 25 +--------------------- lib/scpt/library.lua | 25 +--------------------- src/plots.h | 1 + src/q_library.c | 46 +++++++++++++++++++++++++++++++++++++++++ src/util.pkg | 1 + 5 files changed, 50 insertions(+), 48 deletions(-) diff --git a/lib/mods/theme/scpt/library.lua b/lib/mods/theme/scpt/library.lua index fca935fb..1f7e7d49 100644 --- a/lib/mods/theme/scpt/library.lua +++ b/lib/mods/theme/scpt/library.lua @@ -101,30 +101,7 @@ add_quest return quest_library_gen_hook() end, [HOOK_STAIR] = function() - local ret - - -- only ask this if player about to go up stairs of quest and hasn't won yet - if (player.inside_quest ~= LIBRARY_QUEST) or (quest(LIBRARY_QUEST).status == QUEST_STATUS_COMPLETED) then - return FALSE - end - - if cave(player.py, player.px).feat ~= FEAT_LESS then return end - - -- flush all pending input - flush() - - -- confirm - ret = get_check("Really abandon the quest?") - - -- if yes, then - if ret == TRUE then - -- fail the quest - quest(LIBRARY_QUEST).status = QUEST_STATUS_FAILED - return FALSE - else - -- if no, they stay in the quest - return TRUE - end + return quest_library_stair_hook() end, [HOOK_MONSTER_DEATH] = function() -- if they're in the quest and haven't won, continue diff --git a/lib/scpt/library.lua b/lib/scpt/library.lua index 202ba268..6368409d 100644 --- a/lib/scpt/library.lua +++ b/lib/scpt/library.lua @@ -98,30 +98,7 @@ add_quest return quest_library_gen_hook() end, [HOOK_STAIR] = function() - local ret - - -- only ask this if player about to go up stairs of quest and hasn't won yet - if (player.inside_quest ~= LIBRARY_QUEST) or (quest(LIBRARY_QUEST).status == QUEST_STATUS_COMPLETED) then - return FALSE - end - - if cave(player.py, player.px).feat ~= FEAT_LESS then return end - - -- flush all pending input - flush() - - -- confirm - ret = get_check("Really abandon the quest?") - - -- if yes, then - if ret == TRUE then - -- fail the quest - quest(LIBRARY_QUEST).status = QUEST_STATUS_FAILED - return FALSE - else - -- if no, they stay in the quest - return TRUE - end + return quest_library_stair_hook() end, [HOOK_MONSTER_DEATH] = function() -- if they're in the quest and haven't won, continue diff --git a/src/plots.h b/src/plots.h index da8a6cd2..ce938a69 100644 --- a/src/plots.h +++ b/src/plots.h @@ -55,6 +55,7 @@ extern bool_ quest_bounty_describe(FILE *fff); /******* Plot Library Quest *******/ extern bool_ quest_library_gen_hook(); +extern bool_ quest_library_stair_hook(); extern void quest_library_building(bool_ *paid, bool_ *recreate); /******* Plot Fireproof Quest *********/ diff --git a/src/q_library.c b/src/q_library.c index d7a098cd..8804e2dc 100644 --- a/src/q_library.c +++ b/src/q_library.c @@ -12,6 +12,16 @@ static int LIBRARY_QUEST() return get_lua_int("LIBRARY_QUEST"); } +static int library_quest_get_status() +{ + return exec_lua("return quest(LIBRARY_QUEST).status"); +} + +static void library_quest_set_status(int new_status) +{ + exec_lua(format("quest(LIBRARY_QUEST).status = %d", new_status)); +} + static s16b library_quest_place_random(int minY, int minX, int maxY, int maxX, int r_idx) { int y = randint(maxY - minY + 1) + minY; @@ -262,6 +272,42 @@ bool_ quest_library_gen_hook() return TRUE; } +bool_ quest_library_stair_hook() +{ + bool_ ret; + + /* only ask this if player about to go up stairs of quest and hasn't won yet */ + if ((p_ptr->inside_quest != LIBRARY_QUEST()) || + (library_quest_get_status() == QUEST_STATUS_COMPLETED)) + { + return FALSE; + } + + if (cave[p_ptr->py][p_ptr->px].feat != FEAT_LESS) + { + return FALSE; + } + + /* flush all pending input */ + flush(); + + /* confirm */ + ret = get_check("Really abandon the quest?"); + + /* if yes, then */ + if (ret == TRUE) + { + /* fail the quest */ + library_quest_set_status(QUEST_STATUS_FAILED); + return FALSE; + } + else + { + /* if no, they stay in the quest */ + return TRUE; + } +} + static int get_status() { return exec_lua("return quest(LIBRARY_QUEST).status"); diff --git a/src/util.pkg b/src/util.pkg index 49924e7f..c117ef0f 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -2474,6 +2474,7 @@ extern bool drop_text_left(byte c, cptr s, int y, int o); extern bool drop_text_right(byte c, cptr s, int y, int o); extern bool quest_library_gen_hook(); +extern bool quest_library_stair_hook(); /** * Mimicry -- cgit v1.2.3 From 2c0ec2974884386d9b332c6004758e64ab8ce709 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 8 Apr 2012 18:19:19 +0200 Subject: Lua: Library quest: Move HOOK_MONSTER_DEATH code to C --- lib/mods/theme/scpt/library.lua | 20 +------------------- lib/scpt/library.lua | 20 +------------------- src/plots.h | 1 + src/q_library.c | 38 +++++++++++++++++++++++++++++--------- src/util.pkg | 1 + 5 files changed, 33 insertions(+), 47 deletions(-) diff --git a/lib/mods/theme/scpt/library.lua b/lib/mods/theme/scpt/library.lua index 1f7e7d49..5ba5ed4c 100644 --- a/lib/mods/theme/scpt/library.lua +++ b/lib/mods/theme/scpt/library.lua @@ -104,25 +104,7 @@ add_quest return quest_library_stair_hook() end, [HOOK_MONSTER_DEATH] = function() - -- if they're in the quest and haven't won, continue - if (player.inside_quest ~= LIBRARY_QUEST) or (quest(LIBRARY_QUEST).status == QUEST_STATUS_COMPLETED) then - return FALSE - end - - i = 1 - count = -1 - while i <= m_max do - local monster = m_list[i] - if (monster.r_idx > 0) and (monster.status <= MSTATUS_ENEMY) then - count = count + 1 - end - i = i + 1 - end - - if count == 0 then - quest(LIBRARY_QUEST).status = QUEST_STATUS_COMPLETED - msg_print(TERM_YELLOW, "The library is safe now.") - end + return quest_library_monster_death_hook() end, }, } diff --git a/lib/scpt/library.lua b/lib/scpt/library.lua index 6368409d..2ee8c7d3 100644 --- a/lib/scpt/library.lua +++ b/lib/scpt/library.lua @@ -101,25 +101,7 @@ add_quest return quest_library_stair_hook() end, [HOOK_MONSTER_DEATH] = function() - -- if they're in the quest and haven't won, continue - if (player.inside_quest ~= LIBRARY_QUEST) or (quest(LIBRARY_QUEST).status == QUEST_STATUS_COMPLETED) then - return FALSE - end - - i = 1 - count = -1 - while i <= m_max do - local monster = m_list[i] - if (monster.r_idx > 0) and (monster.status <= MSTATUS_ENEMY) then - count = count + 1 - end - i = i + 1 - end - - if count == 0 then - quest(LIBRARY_QUEST).status = QUEST_STATUS_COMPLETED - msg_print(TERM_YELLOW, "The library is safe now.") - end + return quest_library_monster_death_hook() end, }, } diff --git a/src/plots.h b/src/plots.h index ce938a69..eabbf052 100644 --- a/src/plots.h +++ b/src/plots.h @@ -56,6 +56,7 @@ extern bool_ quest_bounty_describe(FILE *fff); /******* Plot Library Quest *******/ extern bool_ quest_library_gen_hook(); extern bool_ quest_library_stair_hook(); +extern void quest_library_monster_death_hook(); extern void quest_library_building(bool_ *paid, bool_ *recreate); /******* Plot Fireproof Quest *********/ diff --git a/src/q_library.c b/src/q_library.c index 8804e2dc..6aa47a81 100644 --- a/src/q_library.c +++ b/src/q_library.c @@ -308,25 +308,45 @@ bool_ quest_library_stair_hook() } } -static int get_status() +void quest_library_monster_death_hook() { - return exec_lua("return quest(LIBRARY_QUEST).status"); -} + int i, count = -1; -static void set_status(int new_status) -{ - exec_lua(format("quest(LIBRARY_QUEST).status = %d", new_status)); + /* if they're in the quest and haven't won, continue */ + if ((p_ptr->inside_quest != LIBRARY_QUEST()) || + (library_quest_get_status() == QUEST_STATUS_COMPLETED)) + { + return; + } + + /* Count all the enemies left alive */ + for (i = 0; i < m_max; i++) + { + monster_type *m_ptr = &m_list[i]; + if ((m_ptr->r_idx > 0) && + (m_ptr->status <= MSTATUS_ENEMY)) + { + count = count + 1; + } + } + + /* We've just killed the last monster */ + if (count == 0) + { + library_quest_set_status(QUEST_STATUS_COMPLETED); + cmsg_print(TERM_YELLOW, "The library is safe now."); + } } void quest_library_building(bool_ *paid, bool_ *recreate) { - int status = get_status(); + int status = library_quest_get_status(); /* the quest hasn't been requested already, right? */ if (status == QUEST_STATUS_UNTAKEN) { /* quest has been taken now */ - set_status(QUEST_STATUS_TAKEN); + library_quest_set_status(QUEST_STATUS_TAKEN); /* issue instructions */ msg_print("I need get some stock from my main library, but it is infested with monsters!"); @@ -344,7 +364,7 @@ void quest_library_building(bool_ *paid, bool_ *recreate) library_quest_fill_book(); if (library_quest_book_slots_left() == 0) { - set_status(QUEST_STATUS_REWARDED); + library_quest_set_status(QUEST_STATUS_REWARDED); { object_type forge; diff --git a/src/util.pkg b/src/util.pkg index c117ef0f..cb986b68 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -2475,6 +2475,7 @@ extern bool drop_text_right(byte c, cptr s, int y, int o); extern bool quest_library_gen_hook(); extern bool quest_library_stair_hook(); +extern void quest_library_monster_death_hook(); /** * Mimicry -- cgit v1.2.3 From ab026914d25d77fb14172922c66e630536180252 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 8 Apr 2012 19:07:44 +0200 Subject: Lua: Library quest: Move quest creation to C --- lib/mods/theme/scpt/library.lua | 46 -------------- lib/scpt/library.lua | 46 -------------- src/defines.h | 3 +- src/externs.h | 4 -- src/plots.h | 5 +- src/q_library.c | 129 ++++++++++++++++++++++++++++------------ src/quest.pkg | 6 -- src/tables.c | 16 +++++ src/util.pkg | 4 -- 9 files changed, 112 insertions(+), 147 deletions(-) diff --git a/lib/mods/theme/scpt/library.lua b/lib/mods/theme/scpt/library.lua index 5ba5ed4c..51512de1 100644 --- a/lib/mods/theme/scpt/library.lua +++ b/lib/mods/theme/scpt/library.lua @@ -62,49 +62,3 @@ function library_quest.print_spell(color, y, spl) end return y end - --- Quest data and hooks -add_quest -{ - ["global"] = "LIBRARY_QUEST", - ["name"] = "Library quest", - ["desc"] = function() - -- Quest taken - if (quest(LIBRARY_QUEST).status == QUEST_STATUS_TAKEN) then - print_hook("#####yAn Old Mages Quest! (Danger Level: 35)\n") - print_hook("Make the library safe for the old mage in Minas Anor.\n") - print_hook("\n") - -- Quest done, book not gotten yet - elseif (quest(LIBRARY_QUEST).status == QUEST_STATUS_COMPLETED) then - print_hook("#####yAn Old Mages Quest!\n") - print_hook("You have made the library safe for the old mage in Minas Anor.\n") - print_hook("Perhaps you should see about a reward.\n") - print_hook("\n") - end - end, - ["level"] = 35, - ["data"] = - { - ["school_book[61][1]"] = -1, - ["school_book[61][2]"] = -1, - ["school_book[61][3]"] = -1 - }, - ["hooks"] = - { - -- Start the game without the quest, need to request it - [HOOK_BIRTH_OBJECTS] = function() - quest(LIBRARY_QUEST).status = QUEST_STATUS_UNTAKEN - school_book[61] = {-1, -1, -1} - end, - - [HOOK_GEN_QUEST] = function() - return quest_library_gen_hook() - end, - [HOOK_STAIR] = function() - return quest_library_stair_hook() - end, - [HOOK_MONSTER_DEATH] = function() - return quest_library_monster_death_hook() - end, - }, -} diff --git a/lib/scpt/library.lua b/lib/scpt/library.lua index 2ee8c7d3..b8a5ebed 100644 --- a/lib/scpt/library.lua +++ b/lib/scpt/library.lua @@ -59,49 +59,3 @@ function library_quest.print_spell(color, y, spl) end return y end - --- Quest data and hooks -add_quest -{ - ["global"] = "LIBRARY_QUEST", - ["name"] = "Library quest", - ["desc"] = function() - -- Quest taken - if (quest(LIBRARY_QUEST).status == QUEST_STATUS_TAKEN) then - print_hook("#####yAn Old Mages Quest! (Danger Level: 35)\n") - print_hook("Make the library safe for the old mage in Minas Anor.\n") - print_hook("\n") - -- Quest done, book not gotten yet - elseif (quest(LIBRARY_QUEST).status == QUEST_STATUS_COMPLETED) then - print_hook("#####yAn Old Mages Quest!\n") - print_hook("You have made the library safe for the old mage in Minas Anor.\n") - print_hook("Perhaps you should see about a reward.\n") - print_hook("\n") - end - end, - ["level"] = 35, - ["data"] = - { - ["school_book[61][1]"] = -1, - ["school_book[61][2]"] = -1, - ["school_book[61][3]"] = -1 - }, - ["hooks"] = - { - -- Start the game without the quest, need to request it - [HOOK_BIRTH_OBJECTS] = function() - quest(LIBRARY_QUEST).status = QUEST_STATUS_UNTAKEN - school_book[61] = {-1, -1, -1} - end, - - [HOOK_GEN_QUEST] = function() - return quest_library_gen_hook() - end, - [HOOK_STAIR] = function() - return quest_library_stair_hook() - end, - [HOOK_MONSTER_DEATH] = function() - return quest_library_monster_death_hook() - end, - }, -} diff --git a/src/defines.h b/src/defines.h index 94074690..41b96bba 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4420,7 +4420,8 @@ #define QUEST_EVIL 25 #define QUEST_BOUNTY 26 #define QUEST_FIREPROOF 27 -#define MAX_Q_IDX_INIT 28 +#define QUEST_LIBRARY 28 +#define MAX_Q_IDX_INIT 29 #define PLOT_MAIN 0 #define PLOT_BREE 1 diff --git a/src/externs.h b/src/externs.h index cf56abcc..2da4f38d 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1849,10 +1849,6 @@ extern bool_ drop_text_right(byte c, cptr s, int y, int o); extern void increase_mana(int delta); -/* q_library.c */ -extern void library_quest_fill_book(); -extern int library_quest_book_slots_left(); - /* skills.c */ extern void dump_skills(FILE *fff); extern s16b find_skill(cptr name); diff --git a/src/plots.h b/src/plots.h index eabbf052..f1dcce8c 100644 --- a/src/plots.h +++ b/src/plots.h @@ -54,9 +54,8 @@ extern bool_ quest_bounty_get_item(); extern bool_ quest_bounty_describe(FILE *fff); /******* Plot Library Quest *******/ -extern bool_ quest_library_gen_hook(); -extern bool_ quest_library_stair_hook(); -extern void quest_library_monster_death_hook(); +extern bool_ quest_library_init_hook(int q); +extern bool_ quest_library_describe(FILE *fff); extern void quest_library_building(bool_ *paid, bool_ *recreate); /******* Plot Fireproof Quest *********/ diff --git a/src/q_library.c b/src/q_library.c index 6aa47a81..d19b15d8 100644 --- a/src/q_library.c +++ b/src/q_library.c @@ -1,4 +1,7 @@ #undef cquest +#define cquest (quest[QUEST_LIBRARY]) + +#define print_hook(fmt,...) do { fprintf(hook_file, fmt, ##__VA_ARGS__); } while (0) #define MONSTER_LICH 518 #define MONSTER_MONASTIC_LICH 611 @@ -7,21 +10,6 @@ #define MONSTER_IRON_GOLEM 367 #define MONSTER_MITHRIL_GOLEM 464 -static int LIBRARY_QUEST() -{ - return get_lua_int("LIBRARY_QUEST"); -} - -static int library_quest_get_status() -{ - return exec_lua("return quest(LIBRARY_QUEST).status"); -} - -static void library_quest_set_status(int new_status) -{ - exec_lua(format("quest(LIBRARY_QUEST).status = %d", new_status)); -} - static s16b library_quest_place_random(int minY, int minX, int maxY, int maxX, int r_idx) { int y = randint(maxY - minY + 1) + minY; @@ -40,17 +28,17 @@ static void library_quest_place_nrandom(int minY, int minX, int maxY, int maxX, } } -static int library_quest_book_get_slot(int slot) +static s32b library_quest_book_get_slot(int slot) { - return exec_lua(format("return school_book[61][%d]", slot)); + return cquest.data[slot-1]; } -static int library_quest_book_set_slot(int slot, int spell) +static void library_quest_book_set_slot(int slot, s32b spell) { - return exec_lua(format("school_book[61][%d] = %d", slot, spell)); + cquest.data[slot-1] = spell; } -int library_quest_book_slots_left() +static int library_quest_book_slots_left() { if (library_quest_book_get_slot(1) == -1) { return 3; @@ -65,7 +53,15 @@ int library_quest_book_slots_left() static bool_ library_quest_book_contains_spell(int spell) { - return exec_lua(format("return spell_in_book(61, %d)", spell)); + int i; + for (i = 1; i <= 3; i++) + { + if (library_quest_book_get_slot(i) == spell) + { + return TRUE; + } + } + return FALSE; } static int library_quest_bookable_spells_at(int i) { @@ -84,6 +80,15 @@ static int library_quest_print_spell_desc(int s, int y) { return exec_lua(format("print_spell_desc(%d, %d)", s, y)); } +static void quest_library_finalize_book() +{ + int i = 0; + for (i = 1; i <= 3; i++) + { + exec_lua(format("school_book[61][%d] = %d", i, library_quest_book_get_slot(i))); + } +} + static void library_quest_add_spell(int spell) { if (library_quest_book_get_slot(1) == -1) { library_quest_book_set_slot(1, spell); @@ -155,13 +160,15 @@ static void library_quest_print_spells(int first, int current) } } -void library_quest_fill_book() +static void library_quest_fill_book() { int width, height, margin, first, current; bool_ done; /* Always start with a cleared book */ - exec_lua("school_book[61] = {-1, -1, -1}"); + library_quest_book_set_slot(1, -1); + library_quest_book_set_slot(2, -1); + library_quest_book_set_slot(3, -1); screen_save(); Term_get_size(&width, &height); @@ -229,10 +236,10 @@ void library_quest_fill_book() screen_load(); } -bool_ quest_library_gen_hook() +static bool_ quest_library_gen_hook() { /* Only if player doing this quest */ - if (p_ptr->inside_quest != LIBRARY_QUEST()) + if (p_ptr->inside_quest != QUEST_LIBRARY) { return FALSE; } @@ -272,13 +279,13 @@ bool_ quest_library_gen_hook() return TRUE; } -bool_ quest_library_stair_hook() +static bool_ quest_library_stair_hook() { bool_ ret; /* only ask this if player about to go up stairs of quest and hasn't won yet */ - if ((p_ptr->inside_quest != LIBRARY_QUEST()) || - (library_quest_get_status() == QUEST_STATUS_COMPLETED)) + if ((p_ptr->inside_quest != QUEST_LIBRARY) || + (cquest.status == QUEST_STATUS_COMPLETED)) { return FALSE; } @@ -298,7 +305,7 @@ bool_ quest_library_stair_hook() if (ret == TRUE) { /* fail the quest */ - library_quest_set_status(QUEST_STATUS_FAILED); + cquest.status = QUEST_STATUS_FAILED; return FALSE; } else @@ -308,15 +315,15 @@ bool_ quest_library_stair_hook() } } -void quest_library_monster_death_hook() +static bool_ quest_library_monster_death_hook(char *fmt) { int i, count = -1; /* if they're in the quest and haven't won, continue */ - if ((p_ptr->inside_quest != LIBRARY_QUEST()) || - (library_quest_get_status() == QUEST_STATUS_COMPLETED)) + if ((p_ptr->inside_quest != QUEST_LIBRARY) || + (cquest.status == QUEST_STATUS_COMPLETED)) { - return; + return FALSE; } /* Count all the enemies left alive */ @@ -333,20 +340,23 @@ void quest_library_monster_death_hook() /* We've just killed the last monster */ if (count == 0) { - library_quest_set_status(QUEST_STATUS_COMPLETED); + cquest.status = QUEST_STATUS_COMPLETED; cmsg_print(TERM_YELLOW, "The library is safe now."); } + + /* Normal processing */ + return FALSE; } void quest_library_building(bool_ *paid, bool_ *recreate) { - int status = library_quest_get_status(); + int status = cquest.status; /* the quest hasn't been requested already, right? */ if (status == QUEST_STATUS_UNTAKEN) { /* quest has been taken now */ - library_quest_set_status(QUEST_STATUS_TAKEN); + cquest.status = QUEST_STATUS_TAKEN; /* issue instructions */ msg_print("I need get some stock from my main library, but it is infested with monsters!"); @@ -364,7 +374,7 @@ void quest_library_building(bool_ *paid, bool_ *recreate) library_quest_fill_book(); if (library_quest_book_slots_left() == 0) { - library_quest_set_status(QUEST_STATUS_REWARDED); + cquest.status = QUEST_STATUS_REWARDED; { object_type forge; @@ -376,6 +386,8 @@ void quest_library_building(bool_ *paid, bool_ *recreate) object_known(q_ptr); inven_carry(q_ptr, FALSE); } + + quest_library_finalize_book(); } } @@ -392,3 +404,46 @@ void quest_library_building(bool_ *paid, bool_ *recreate) msg_print("I have no more quests for you."); } } + +bool_ quest_library_describe(FILE *hook_file) +{ + if (cquest.status == QUEST_STATUS_TAKEN) + { + print_hook("#####yAn Old Mages Quest! (Danger Level: 35)\n"); + print_hook("Make the library safe for the old mage in Minas Anor.\n"); + print_hook("\n"); + } + else if (cquest.status == QUEST_STATUS_COMPLETED) + { + /* Quest done, book not gotten yet */ + print_hook("#####yAn Old Mages Quest!\n"); + print_hook("You have made the library safe for the old mage in Minas Anor.\n"); + print_hook("Perhaps you should see about a reward.\n"); + print_hook("\n"); + } + + /* Normal processing */ + return TRUE; +} + +bool_ quest_library_init_hook(int q) +{ + /* Only need hooks if the quest is unfinished. */ + if ((cquest.status >= QUEST_STATUS_UNTAKEN) && + (cquest.status < QUEST_STATUS_FINISHED)) + { + add_hook(HOOK_GEN_QUEST , quest_library_gen_hook , "library_gen_hook"); + add_hook(HOOK_STAIR , quest_library_stair_hook , "library_stair_hook"); + add_hook(HOOK_MONSTER_DEATH, quest_library_monster_death_hook, "library_monster_death_hook"); + } + + /* If quest was rewarded we need to initialize the real player's spellbook. */ + if (cquest.status == QUEST_STATUS_REWARDED) + { + quest_library_finalize_book(); + } + + return FALSE; +} + +#undef print_hook diff --git a/src/quest.pkg b/src/quest.pkg index 7476bc9b..487c62af 100644 --- a/src/quest.pkg +++ b/src/quest.pkg @@ -159,9 +159,3 @@ extern s16b add_new_quest @ new_quest(char *name); * @note (see file lua_bind.c) */ extern void desc_quest @ quest_desc(int q_idx, int d, char *desc); - -/** - * Library Quest - */ -extern void library_quest_fill_book(); -extern int library_quest_book_slots_left(); diff --git a/src/tables.c b/src/tables.c index 259fd5ae..3eea2d39 100644 --- a/src/tables.c +++ b/src/tables.c @@ -4301,6 +4301,22 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] = {0, 0, 0, 0}, quest_fireproof_describe, }, + /* Library */ + { + FALSE, + TRUE, + "Library quest", + { + "", /* dynamic desc */ + }, + QUEST_STATUS_UNTAKEN, + 35, + NULL, + HOOK_TYPE_C, + quest_library_init_hook, + { -1, -1, -1, -1 }, + quest_library_describe, + }, }; diff --git a/src/util.pkg b/src/util.pkg index cb986b68..738af28e 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -2473,10 +2473,6 @@ extern void lite_spot(int y, int x); extern bool drop_text_left(byte c, cptr s, int y, int o); extern bool drop_text_right(byte c, cptr s, int y, int o); -extern bool quest_library_gen_hook(); -extern bool quest_library_stair_hook(); -extern void quest_library_monster_death_hook(); - /** * Mimicry */ -- cgit v1.2.3 From 976701ed6d6a45214bc2ea9fea3f6f7299ae379c Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 8 Apr 2012 20:30:54 +0200 Subject: Lua: God quest: Move place_rand_dung() to C --- lib/mods/theme/scpt/god.lua | 51 +----------------------- lib/scpt/god.lua | 51 +----------------------- src/CMakeLists.txt | 1 + src/plots.h | 3 ++ src/q_god.c | 97 +++++++++++++++++++++++++++++++++++++++++++++ src/quest.pkg | 5 +++ 6 files changed, 108 insertions(+), 100 deletions(-) create mode 100644 src/q_god.c diff --git a/lib/mods/theme/scpt/god.lua b/lib/mods/theme/scpt/god.lua index 7567178c..71a85660 100644 --- a/lib/mods/theme/scpt/god.lua +++ b/lib/mods/theme/scpt/god.lua @@ -114,7 +114,7 @@ add_quest god_quest.quests_given = god_quest.quests_given + 1 -- actually place the dungeon in a random place - place_rand_dung() + quest_god_place_rand_dung() -- store the variables of the coords where the player was given the quest god_quest.player_y, god_quest.player_x = player.get_wild_coord() @@ -277,55 +277,6 @@ add_quest }, } --- this function places the lost temple at a randomly determined place. -function place_rand_dung() - local tries, grid - - -- erase old dungeon - if (god_quest.quests_given > 0) then - place_dungeon(god_quest.dung_y, god_quest.dung_x) - - -- erase old recall level - max_dlv[god_quest.DUNGEON_GOD + 1] = 0 - end - - -- initialise tries variable - tries = 1000 - - while tries > 0 do - - tries = tries - 1 - -- get grid coordinates, within a range which prevents dungeon being generated at the very edge of the wilderness (would crash the game). - god_quest.dung_x = rand_range(1, max_wild_x-2) - god_quest.dung_y = rand_range(1, max_wild_y-2) - - -- Is there a town/dungeon/potentially impassable feature there, ? - if (wild_map(god_quest.dung_y, god_quest.dung_x).entrance ~= 0) - or (wild_feat(wild_map(god_quest.dung_y, god_quest.dung_x)).entrance ~= 0) - or (wild_feat(wild_map(god_quest.dung_y, god_quest.dung_x)).terrain_idx == TERRAIN_EDGE) - or (wild_feat(wild_map(god_quest.dung_y, god_quest.dung_x)).terrain_idx == TERRAIN_DEEP_WATER) - or (wild_feat(wild_map(god_quest.dung_y, god_quest.dung_x)).terrain_idx == TERRAIN_TREES) - or (wild_feat(wild_map(god_quest.dung_y, god_quest.dung_x)).terrain_idx == TERRAIN_SHALLOW_LAVA) - or (wild_feat(wild_map(god_quest.dung_y, god_quest.dung_x)).terrain_idx == TERRAIN_DEEP_LAVA) - or (wild_feat(wild_map(god_quest.dung_y, god_quest.dung_x)).terrain_idx == TERRAIN_MOUNTAIN) then - -- try again - else - --neither player, nor wall, then stop this 'while' - break - end - end - - -- Uhuh BAD ! lets use the default location up bree - if tries == 0 then - god_quest.dung_x = 32 - god_quest.dung_y = 19 - end - - -- create god dungeon in that place - place_dungeon(god_quest.dung_y, god_quest.dung_x, god_quest.DUNGEON_GOD) - -end - -- this function generates the relic at a randomly determined place in the temple. function generate_relic() local tries, grid, x, y, relic diff --git a/lib/scpt/god.lua b/lib/scpt/god.lua index 3f32888b..cc8b8fff 100644 --- a/lib/scpt/god.lua +++ b/lib/scpt/god.lua @@ -106,7 +106,7 @@ add_quest god_quest.quests_given = god_quest.quests_given + 1 -- actually place the dungeon in a random place - place_rand_dung() + quest_god_place_rand_dung() -- store the variables of the coords where the player was given the quest god_quest.player_y, god_quest.player_x = player.get_wild_coord() @@ -269,55 +269,6 @@ add_quest }, } --- this function places the lost temple at a randomly determined place. -function place_rand_dung() - local tries, grid - - -- erase old dungeon - if (god_quest.quests_given > 0) then - place_dungeon(god_quest.dung_y, god_quest.dung_x) - - -- erase old recall level - max_dlv[god_quest.DUNGEON_GOD + 1] = 0 - end - - -- initialise tries variable - tries = 1000 - - while tries > 0 do - - tries = tries - 1 - -- get grid coordinates, within a range which prevents dungeon being generated at the very edge of the wilderness (would crash the game). - god_quest.dung_x = rand_range(1, max_wild_x-2) - god_quest.dung_y = rand_range(1, max_wild_y-2) - - -- Is there a town/dungeon/potentially impassable feature there, ? - if (wild_map(god_quest.dung_y, god_quest.dung_x).entrance ~= 0) - or (wild_feat(wild_map(god_quest.dung_y, god_quest.dung_x)).entrance ~= 0) - or (wild_feat(wild_map(god_quest.dung_y, god_quest.dung_x)).terrain_idx == TERRAIN_EDGE) - or (wild_feat(wild_map(god_quest.dung_y, god_quest.dung_x)).terrain_idx == TERRAIN_DEEP_WATER) - or (wild_feat(wild_map(god_quest.dung_y, god_quest.dung_x)).terrain_idx == TERRAIN_TREES) - or (wild_feat(wild_map(god_quest.dung_y, god_quest.dung_x)).terrain_idx == TERRAIN_SHALLOW_LAVA) - or (wild_feat(wild_map(god_quest.dung_y, god_quest.dung_x)).terrain_idx == TERRAIN_DEEP_LAVA) - or (wild_feat(wild_map(god_quest.dung_y, god_quest.dung_x)).terrain_idx == TERRAIN_MOUNTAIN) then - -- try again - else - --neither player, nor wall, then stop this 'while' - break - end - end - - -- Uhuh BAD ! lets use the default location up bree - if tries == 0 then - god_quest.dung_x = 32 - god_quest.dung_y = 19 - end - - -- create god dungeon in that place - place_dungeon(god_quest.dung_y, god_quest.dung_x, god_quest.DUNGEON_GOD) - -end - -- this function generates the relic at a randomly determined place in the temple. function generate_relic() local tries, grid, x, y, relic diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c2ed88a3..a453e573 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,6 +6,7 @@ SET(SRCS z-rand.c z-util.c z-form.c z-virt.c z-term.c variable.c tables.c plots.c util.c cave.c dungeon.c melee1.c melee2.c modules.c + q_god.c object1.c object2.c randart.c squeltch.c traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.h b/src/plots.h index f1dcce8c..eaeeb818 100644 --- a/src/plots.h +++ b/src/plots.h @@ -62,3 +62,6 @@ extern void quest_library_building(bool_ *paid, bool_ *recreate); extern void quest_fireproof_building(bool_ *paid, bool_ *recreate); extern bool_ quest_fireproof_init_hook(int q); extern bool_ quest_fireproof_describe(FILE *fff); + +/******* Plot God Quest **************/ +extern void quest_god_place_rand_dung(); diff --git a/src/q_god.c b/src/q_god.c new file mode 100644 index 00000000..070b2a02 --- /dev/null +++ b/src/q_god.c @@ -0,0 +1,97 @@ +#include "angband.h" +#include + +/* d_idx of the god_quest (Lost Temple) dungeon */ +#define DUNGEON_GOD 30 + +static int get_quests_given() +{ + return get_lua_int("god_quest.quests_given"); +} + +static int get_dung_y() +{ + return get_lua_int("god_quest.dung_y"); +} + +static int get_dung_x() +{ + return get_lua_int("god_quest.dung_x"); +} + +static void set_dung_y(int y) +{ + exec_lua(format("god_quest.dung_y = %d", y)); +} + +static void set_dung_x(int x) +{ + exec_lua(format("god_quest.dung_x = %d", x)); +} + +void quest_god_place_rand_dung() +{ + int x = -1, y = -1, tries; + + /* erase old dungeon */ + if (get_quests_given() > 0) + { + wild_map[get_dung_y()][get_dung_x()].entrance = 0; + + /* erase old recall level */ + max_dlv[DUNGEON_GOD] = 0; + } + + /* initialise tries variable */ + tries = 1000; + while (tries > 0) + { + wilderness_map *w_ptr = NULL; + wilderness_type_info *wf_ptr = NULL; + tries = tries - 1; + + /* get grid coordinates, within a range which prevents + * dungeon being generated at the very edge of the + * wilderness (would crash the game). */ + x = rand_range(1, max_wild_x-2); + y = rand_range(1, max_wild_y-2); + + /* Is there a town/dungeon/potentially impassable feature there, ? */ + w_ptr = &wild_map[y][x]; + wf_ptr = &wf_info[w_ptr->feat]; + + if ((w_ptr->entrance != 0) || + (wf_ptr->entrance != 0) || + (wf_ptr->terrain_idx == TERRAIN_EDGE) || + (wf_ptr->terrain_idx == TERRAIN_DEEP_WATER) || + (wf_ptr->terrain_idx == TERRAIN_TREES) || + (wf_ptr->terrain_idx == TERRAIN_SHALLOW_LAVA) || + (wf_ptr->terrain_idx == TERRAIN_DEEP_LAVA) || + (wf_ptr->terrain_idx == TERRAIN_MOUNTAIN)) + { + /* try again */ + } + else + { + /* either player, nor wall, then stop this 'while' */ + break; + } + } + + assert(x >= 0); + assert(y >= 0); + + if (tries == 0) + { + /* Use Bree as last resort */ + x = 32; + y = 19; + } + + /* create god dungeon in that place */ + wild_map[y][x].entrance = 1000 + DUNGEON_GOD; + + /* set quest variables */ + set_dung_x(x); + set_dung_y(y); +} diff --git a/src/quest.pkg b/src/quest.pkg index 487c62af..3b8fc922 100644 --- a/src/quest.pkg +++ b/src/quest.pkg @@ -159,3 +159,8 @@ extern s16b add_new_quest @ new_quest(char *name); * @note (see file lua_bind.c) */ extern void desc_quest @ quest_desc(int q_idx, int d, char *desc); + +/* + * God quest + */ +extern void quest_god_place_rand_dung(); -- cgit v1.2.3 From 3db3a9506e165a6480c51d79ee8ddb2ca509f600 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 8 Apr 2012 20:52:58 +0200 Subject: Lua: Remove now-unused Lua code --- lib/core/dungeon.lua | 20 -------------------- lib/mods/theme/core/dungeon.lua | 20 -------------------- 2 files changed, 40 deletions(-) diff --git a/lib/core/dungeon.lua b/lib/core/dungeon.lua index ba4fd38a..13030eac 100644 --- a/lib/core/dungeon.lua +++ b/lib/core/dungeon.lua @@ -1,29 +1,9 @@ -- Internal lua file in charge of dungeon stuff -function place_dungeon(y, x, d_idx) - if d_idx then - wild_map(y, x).entrance = 1000 + d_idx - else - wild_map(y, x).entrance = 0 - end -end - function dungeon(d_idx) return d_info[1 + d_idx] end -function wild_feat(wild) - return wf_info[1 + wild.feat] -end - function explode_dir(dir) return ddy[dir + 1], ddx[dir + 1] end - --- Place a trap for a specific level -function place_trap(y, x, level) - local old_dun = dun_level - dun_level = level - %place_trap(y, x) - dun_level = old_dun -end diff --git a/lib/mods/theme/core/dungeon.lua b/lib/mods/theme/core/dungeon.lua index ba4fd38a..13030eac 100644 --- a/lib/mods/theme/core/dungeon.lua +++ b/lib/mods/theme/core/dungeon.lua @@ -1,29 +1,9 @@ -- Internal lua file in charge of dungeon stuff -function place_dungeon(y, x, d_idx) - if d_idx then - wild_map(y, x).entrance = 1000 + d_idx - else - wild_map(y, x).entrance = 0 - end -end - function dungeon(d_idx) return d_info[1 + d_idx] end -function wild_feat(wild) - return wf_info[1 + wild.feat] -end - function explode_dir(dir) return ddy[dir + 1], ddx[dir + 1] end - --- Place a trap for a specific level -function place_trap(y, x, level) - local old_dun = dun_level - dun_level = level - %place_trap(y, x) - dun_level = old_dun -end -- cgit v1.2.3 From 588796622eef2419931bf759188a90822be8574f Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 8 Apr 2012 21:11:11 +0200 Subject: Lua: God quest: Move generate_relic() to C --- lib/mods/theme/scpt/god.lua | 59 ++---------------------------- lib/scpt/god.lua | 59 ++---------------------------- src/plots.h | 1 + src/q_god.c | 88 +++++++++++++++++++++++++++++++++++++++++++++ src/quest.pkg | 1 + 5 files changed, 94 insertions(+), 114 deletions(-) diff --git a/lib/mods/theme/scpt/god.lua b/lib/mods/theme/scpt/god.lua index 71a85660..1c932029 100644 --- a/lib/mods/theme/scpt/god.lua +++ b/lib/mods/theme/scpt/god.lua @@ -174,12 +174,12 @@ add_quest else -- Force relic generation on 5th attempt if others have been unsuccessful. if (god_quest.relic_gen_tries == 4) and (god_quest.relic_generated == FALSE) then - generate_relic() + quest_god_generate_relic() else -- 1/5 chance of generation chance = randint(5) if (chance == 5) then - generate_relic() + quest_god_generate_relic() else god_quest.relic_gen_tries = god_quest.relic_gen_tries + 1 end @@ -277,61 +277,6 @@ add_quest }, } --- this function generates the relic at a randomly determined place in the temple. -function generate_relic() - local tries, grid, x, y, relic - - -- initialise tries variable - tries = 1000 - - while (tries > 0) do - - tries = tries - 1 - -- get grid coordinates from current height/width, minus one to prevent relic being generated in outside wall. (would crash the game) - y = randint(cur_hgt-1) - x = randint(cur_wid-1) - grid = cave(y, x) - - -- are the coordinates on a floor, not on a permanent feature (eg stairs), and not on a trap ? - if (cave_is(grid, FF1_FLOOR) == TRUE) and (cave_is(grid, FF1_PERMANENT) == FALSE) and (grid.t_idx == 0) then break end - - end - - -- create relic - relic = create_object(TV_JUNK, god_quest.relic_num) - - -- inscribe it to prevent automatizer 'accidents' - relic.note = quark_add("quest") - - -- If no safe co-ords were found, put it in the players backpack - if tries == 0 then - - -- explain it - msg_print(TERM_L_BLUE, "You luckily stumble across the relic on the stairs!") - - if (inven_carry_okay(relic)) then - inven_carry(relic, FALSE) - else - -- no place found, drop it on the stairs - drop_near(relic, -1, player.py, player.px) - end - - else - -- drop it - drop_near(relic, -1, y, x) - end - - -- Only generate once! - god_quest.relic_generated = TRUE - - -- Reset some variables - god_quest.relic_gen_tries = 0 - -end - - - - function set_god_dungeon_attributes() -- dungeon properties altered according to which god player is worshipping, diff --git a/lib/scpt/god.lua b/lib/scpt/god.lua index cc8b8fff..bb7aa92c 100644 --- a/lib/scpt/god.lua +++ b/lib/scpt/god.lua @@ -166,12 +166,12 @@ add_quest else -- Force relic generation on 5th attempt if others have been unsuccessful. if (god_quest.relic_gen_tries == 4) and (god_quest.relic_generated == FALSE) then - generate_relic() + quest_god_generate_relic() else -- 1/5 chance of generation chance = randint(5) if (chance == 5) then - generate_relic() + quest_god_generate_relic() else god_quest.relic_gen_tries = god_quest.relic_gen_tries + 1 end @@ -269,61 +269,6 @@ add_quest }, } --- this function generates the relic at a randomly determined place in the temple. -function generate_relic() - local tries, grid, x, y, relic - - -- initialise tries variable - tries = 1000 - - while (tries > 0) do - - tries = tries - 1 - -- get grid coordinates from current height/width, minus one to prevent relic being generated in outside wall. (would crash the game) - y = randint(cur_hgt-1) - x = randint(cur_wid-1) - grid = cave(y, x) - - -- are the coordinates on a floor, not on a permanent feature (eg stairs), and not on a trap ? - if (cave_is(grid, FF1_FLOOR) == TRUE) and (cave_is(grid, FF1_PERMANENT) == FALSE) and (grid.t_idx == 0) then break end - - end - - -- create relic - relic = create_object(TV_JUNK, god_quest.relic_num) - - -- inscribe it to prevent automatizer 'accidents' - relic.note = quark_add("quest") - - -- If no safe co-ords were found, put it in the players backpack - if tries == 0 then - - -- explain it - msg_print(TERM_L_BLUE, "You luckily stumble across the relic on the stairs!") - - if (inven_carry_okay(relic)) then - inven_carry(relic, FALSE) - else - -- no place found, drop it on the stairs - drop_near(relic, -1, player.py, player.px) - end - - else - -- drop it - drop_near(relic, -1, y, x) - end - - -- Only generate once! - god_quest.relic_generated = TRUE - - -- Reset some variables - god_quest.relic_gen_tries = 0 - -end - - - - function set_god_dungeon_attributes() -- dungeon properties altered according to which god player is worshipping, diff --git a/src/plots.h b/src/plots.h index eaeeb818..31653f36 100644 --- a/src/plots.h +++ b/src/plots.h @@ -65,3 +65,4 @@ extern bool_ quest_fireproof_describe(FILE *fff); /******* Plot God Quest **************/ extern void quest_god_place_rand_dung(); +extern void quest_god_generate_relic(); diff --git a/src/q_god.c b/src/q_god.c index 070b2a02..5725c984 100644 --- a/src/q_god.c +++ b/src/q_god.c @@ -29,6 +29,32 @@ static void set_dung_x(int x) exec_lua(format("god_quest.dung_x = %d", x)); } +static int get_relic_num() +{ + return get_lua_int("god_quest.relic_num"); +} + +static void set_relic_generated(bool_ v) +{ + switch (v) + { + case TRUE: + exec_lua("god_quest.relic_generated = TRUE"); + break; + case FALSE: + exec_lua("god_quest.relic_generated = FALSE"); + break; + default: + assert(FALSE); + break; + } +} + +static void set_relic_gen_tries(int v) +{ + exec_lua(format("god_quest.relic_gen_tries = %d", v)); +} + void quest_god_place_rand_dung() { int x = -1, y = -1, tries; @@ -95,3 +121,65 @@ void quest_god_place_rand_dung() set_dung_x(x); set_dung_y(y); } + +void quest_god_generate_relic() +{ + int tries = 1000, x = -1, y = -1; + object_type relic; + + tries = 1000; + + while (tries > 0) + { + cave_type *c_ptr; + tries = tries - 1; + /* get grid coordinates from current height/width, + * minus one to prevent relic being generated in + * outside wall. (would crash the game) */ + y = randint(cur_hgt-1); + x = randint(cur_wid-1); + c_ptr = &cave[y][x]; + + /* are the coordinates on a floor, not on a permanent feature (eg stairs), and not on a trap ? */ + if ((f_info[c_ptr->feat].flags1 & FF1_FLOOR) && + (!(f_info[c_ptr->feat].flags1 & FF1_PERMANENT)) && + (c_ptr->t_idx == 0)) + { + break; + } + } + + /* create relic */ + object_prep(&relic, lookup_kind(TV_JUNK, get_relic_num())); + + /* inscribe it to prevent automatizer 'accidents' */ + relic.note = quark_add("quest"); + + /* If no safe co-ords were found, put it in the players backpack */ + if (tries == 0) + { + /* explain it */ + cmsg_print(TERM_L_BLUE, "You luckily stumble across the relic on the stairs!"); + + if (inven_carry_okay(&relic)) + { + inven_carry(&relic, FALSE); + } + else + { + /* no place found, drop it on the stairs */ + drop_near(&relic, -1, p_ptr->py, p_ptr->px); + } + } + else + { + /* drop it */ + drop_near(&relic, -1, y, x); + } + + /* Only generate once! */ + set_relic_generated(TRUE); + + /* Reset some variables */ + set_relic_gen_tries(0); +} diff --git a/src/quest.pkg b/src/quest.pkg index 3b8fc922..e5780e3f 100644 --- a/src/quest.pkg +++ b/src/quest.pkg @@ -164,3 +164,4 @@ extern void desc_quest @ quest_desc(int q_idx, int d, char *desc); * God quest */ extern void quest_god_place_rand_dung(); +extern void quest_god_generate_relic(); -- cgit v1.2.3 From ebba95ce9866866cccfc6e5fbf7dfbd5445f3b08 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 8 Apr 2012 21:48:41 +0200 Subject: Lua: Move per-god dungeon setup to C --- lib/mods/theme/scpt/god.lua | 384 +------------------------------------- lib/scpt/god.lua | 220 +--------------------- src/plots.h | 9 + src/q_god.c | 438 ++++++++++++++++++++++++++++++++++++++++++++ src/quest.pkg | 9 + 5 files changed, 470 insertions(+), 590 deletions(-) diff --git a/lib/mods/theme/scpt/god.lua b/lib/mods/theme/scpt/god.lua index 1c932029..fe8caf5f 100644 --- a/lib/mods/theme/scpt/god.lua +++ b/lib/mods/theme/scpt/god.lua @@ -281,389 +281,23 @@ function set_god_dungeon_attributes() -- dungeon properties altered according to which god player is worshipping, if player.pgod == GOD_ERU then - - -- The Eru temple is based on Meneltarma. - -- W: Not too many monsters (they'll be tough though, with big levels) - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_level = 14 - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_chance = 200 - - -- L: Dirt and grass. More dirt at bottom, more grass at top. rocky ground would be nice - dungeon(god_quest.DUNGEON_GOD).floor1 = 88 - dungeon(god_quest.DUNGEON_GOD).floor2 = 89 - dungeon(god_quest.DUNGEON_GOD).floor_percent1[1] = 70 - dungeon(god_quest.DUNGEON_GOD).floor_percent2[1] = 30 - dungeon(god_quest.DUNGEON_GOD).floor_percent1[2] = 10 - dungeon(god_quest.DUNGEON_GOD).floor_percent2[2] = 90 - - -- A: Outer wall mountain chain. other walls granite - dungeon(god_quest.DUNGEON_GOD).fill_type1 = 97 - dungeon(god_quest.DUNGEON_GOD).fill_percent1[1] = 100 - dungeon(god_quest.DUNGEON_GOD).outer_wall = 57 - dungeon(god_quest.DUNGEON_GOD).inner_wall = 97 - dungeon(god_quest.DUNGEON_GOD).fill_method = 2 - - -- O: "At Meneltarma no weapon or tool had ever been borne" (but invaders would have left a small number) - dungeon(god_quest.DUNGEON_GOD).objs.treasure = 45 - dungeon(god_quest.DUNGEON_GOD).objs.combat = 5 - dungeon(god_quest.DUNGEON_GOD).objs.magic = 45 - dungeon(god_quest.DUNGEON_GOD).objs.tools = 5 - - -- F: A large pillar, with stairs created at edges. (You can't climb a rock through the middle, can you?) - dungeon(god_quest.DUNGEON_GOD).flags1 = bor(DF1_BIG, DF1_NO_DOORS, DF1_CIRCULAR_ROOMS, DF1_EMPTY, DF1_TOWER, DF1_FLAT, DF1_ADJUST_LEVEL_2) - dungeon(god_quest.DUNGEON_GOD).flags2 = bor(DF2_ADJUST_LEVEL_1_2, DF2_NO_SHAFT, DF2_ADJUST_LEVEL_PLAYER) - - -- R: - dungeon(god_quest.DUNGEON_GOD).rules[1].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[1].percent = 50 - - -- M: We want evil or flying characters - dungeon(god_quest.DUNGEON_GOD).rules[1].mflags3 = RF3_EVIL - - dungeon(god_quest.DUNGEON_GOD).rules[2].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[2].percent = 50 - - -- M: We want evil or flying characters - dungeon(god_quest.DUNGEON_GOD).rules[2].mflags7 = RF7_CAN_FLY - - + quest_god_set_god_dungeon_attributes_eru() elseif player.pgod == GOD_MANWE then - - -- Manwe's lost temple is high in the clouds - -- W: Has average number of monsters. - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_level = 18 - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_chance = 160 - - - -- L: floor will be 'cloud-like vapour' and pools of 'condensing water' - dungeon(god_quest.DUNGEON_GOD).floor1 = 208 - dungeon(god_quest.DUNGEON_GOD).floor2 = 209 - dungeon(god_quest.DUNGEON_GOD).floor_percent1[1] = 85 - dungeon(god_quest.DUNGEON_GOD).floor_percent2[1] = 15 - - -- A: Outer wall is 'hail stone wall', inner wall 'dense fog'. FIlled at max smoothing, like islands. - dungeon(god_quest.DUNGEON_GOD).fill_type1 = 211 - dungeon(god_quest.DUNGEON_GOD).fill_percent1[1] = 100 - dungeon(god_quest.DUNGEON_GOD).outer_wall = 210 - dungeon(god_quest.DUNGEON_GOD).inner_wall = 211 - dungeon(god_quest.DUNGEON_GOD).fill_method = 4 - - -- O: Can't imagine Manwe having much treasure. Little need for tools in a cloud temple. lots of magical stuff though... - dungeon(god_quest.DUNGEON_GOD).objs.treasure = 15 - dungeon(god_quest.DUNGEON_GOD).objs.combat = 25 - dungeon(god_quest.DUNGEON_GOD).objs.magic = 55 - dungeon(god_quest.DUNGEON_GOD).objs.tools = 5 - - -- F: It's open, goes up like a tower, give it a few interesting rooms, make the monsters hard(ish). - dungeon(god_quest.DUNGEON_GOD).flags1 = bor(DF1_NO_DOORS, DF1_TOWER, DF1_CAVERN, DF1_ADJUST_LEVEL_2) - dungeon(god_quest.DUNGEON_GOD).flags2 = bor(DF2_NO_SHAFT, DF2_ADJUST_LEVEL_PLAYER) - - -- R: - dungeon(god_quest.DUNGEON_GOD).rules[1].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[1].percent = 20 - dungeon(god_quest.DUNGEON_GOD).rules[2].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[2].percent = 20 - dungeon(god_quest.DUNGEON_GOD).rules[3].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[3].percent = 20 - dungeon(god_quest.DUNGEON_GOD).rules[4].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[4].percent = 20 - dungeon(god_quest.DUNGEON_GOD).rules[5].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[5].percent = 20 - - -- M: We want air(poison-type) or flying characters. Orcs too. They would have ransacked his elf-loving temple :) - dungeon(god_quest.DUNGEON_GOD).rules[1].mflags2 = RF2_INVISIBLE - dungeon(god_quest.DUNGEON_GOD).rules[2].mflags3 = bor(RF3_ORC, RF3_IM_POIS) - dungeon(god_quest.DUNGEON_GOD).rules[3].mflags4 = bor(RF4_BR_POIS, RF4_BR_GRAV) - dungeon(god_quest.DUNGEON_GOD).rules[4].mflags5 = RF5_BA_POIS - dungeon(god_quest.DUNGEON_GOD).rules[5].mflags7 = RF7_CAN_FLY - - + quest_god_set_god_dungeon_attributes_manwe() elseif player.pgod == GOD_TULKAS then - - -- Tulkas dungeon is quite normal, possibly a bit boring to be honest. Maybe I should add something radical to it. - -- 'The house of Tulkas in the midmost of Valmar was a house of mirth and revelry. It sprang into the air with many storeys, - -- and had a tower of bronze and pillars of copper in a wide arcade' - -- W: but with lots of monsters - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_level = 20 - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_chance = 120 - - -- L: floor is normal - dungeon(god_quest.DUNGEON_GOD).floor1 = 1 - dungeon(god_quest.DUNGEON_GOD).floor_percent1[1] = 100 - - -- A: Granite walls - dungeon(god_quest.DUNGEON_GOD).fill_type1 = 56 - dungeon(god_quest.DUNGEON_GOD).fill_percent1[1] = 100 - dungeon(god_quest.DUNGEON_GOD).outer_wall = 58 - dungeon(god_quest.DUNGEON_GOD).inner_wall = 57 - dungeon(god_quest.DUNGEON_GOD).fill_method = 0 - - -- O: Loads of combat drops - dungeon(god_quest.DUNGEON_GOD).objs.treasure = 10 - dungeon(god_quest.DUNGEON_GOD).objs.combat = 70 - dungeon(god_quest.DUNGEON_GOD).objs.magic = 5 - dungeon(god_quest.DUNGEON_GOD).objs.tools = 15 - - -- F: fairly standard - dungeon(god_quest.DUNGEON_GOD).flags1 = bor(DF1_NO_DESTROY, DF1_ADJUST_LEVEL_2) - dungeon(god_quest.DUNGEON_GOD).flags2 = DF2_ADJUST_LEVEL_PLAYER - - -- R: - dungeon(god_quest.DUNGEON_GOD).rules[1].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[1].percent = 100 - - -- M: plenty demons please - dungeon(god_quest.DUNGEON_GOD).rules[1].mflags3 = bor(RF3_DEMON, RF3_EVIL) - - + quest_god_set_god_dungeon_attributes_tulkas() elseif player.pgod == GOD_MELKOR then - - -- Melkors dungeon will be dark, fiery and stuff - -- Many many monsters! (but prob ADJUST_LEVEL_1_2) - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_level = 24 - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_chance = 80 - - - -- L: floor is dirt/mud/nether - dungeon(god_quest.DUNGEON_GOD).floor1 = 88 - dungeon(god_quest.DUNGEON_GOD).floor2 = 94 - dungeon(god_quest.DUNGEON_GOD).floor3 = 102 - dungeon(god_quest.DUNGEON_GOD).floor_percent1[1] = 45 - dungeon(god_quest.DUNGEON_GOD).floor_percent2[1] = 45 - dungeon(god_quest.DUNGEON_GOD).floor_percent3[1] = 10 - dungeon(god_quest.DUNGEON_GOD).floor_percent1[2] = 35 - dungeon(god_quest.DUNGEON_GOD).floor_percent2[2] = 35 - dungeon(god_quest.DUNGEON_GOD).floor_percent3[2] = 30 - - -- A: Granite walls to fill but glass walls for room perimeters (you can see the nasty monsters coming) - dungeon(god_quest.DUNGEON_GOD).fill_type1 = 188 - dungeon(god_quest.DUNGEON_GOD).fill_percent1[1] = 100 - dungeon(god_quest.DUNGEON_GOD).outer_wall = 188 - dungeon(god_quest.DUNGEON_GOD).inner_wall = 57 - dungeon(god_quest.DUNGEON_GOD).fill_method = 1 - - -- O: Even drops - dungeon(god_quest.DUNGEON_GOD).objs.treasure = 25 - dungeon(god_quest.DUNGEON_GOD).objs.combat = 25 - dungeon(god_quest.DUNGEON_GOD).objs.magic = 25 - dungeon(god_quest.DUNGEON_GOD).objs.tools = 25 - - -- F: Small, lava rivers, nasty monsters hehehehehe - dungeon(god_quest.DUNGEON_GOD).flags1 = bor(DF1_SMALL, DF1_LAVA_RIVERS, DF1_ADJUST_LEVEL_1) - dungeon(god_quest.DUNGEON_GOD).flags2 = bor(DF2_ADJUST_LEVEL_1_2, DF2_ADJUST_LEVEL_PLAYER) - - -- R: No restrictions on monsters here - dungeon(god_quest.DUNGEON_GOD).rules[1].mode = 0 - dungeon(god_quest.DUNGEON_GOD).rules[1].percent = 80 - - -- R: Apart from making sure we have some GOOD ones - dungeon(god_quest.DUNGEON_GOD).rules[2].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[2].percent = 20 - - -- M: - dungeon(god_quest.DUNGEON_GOD).rules[2].mflags3 = RF3_GOOD - + quest_god_set_god_dungeon_attributes_melkor() elseif player.pgod == GOD_YAVANNA then - - -- Yavannas dungeon will be very natural, tress and stuff. - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_level = 22 - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_chance = 100 - - -- L: floor is grass/flowers, plus dirt so not always regenerating quick! - dungeon(god_quest.DUNGEON_GOD).floor1 = 89 - dungeon(god_quest.DUNGEON_GOD).floor2 = 199 - dungeon(god_quest.DUNGEON_GOD).floor3 = 88 - dungeon(god_quest.DUNGEON_GOD).floor_percent1[1] = 40 - dungeon(god_quest.DUNGEON_GOD).floor_percent2[1] = 15 - dungeon(god_quest.DUNGEON_GOD).floor_percent3[1] = 45 - - -- A: Tree walls to fill, small trees for inner walls - dungeon(god_quest.DUNGEON_GOD).fill_type1 = 96 - dungeon(god_quest.DUNGEON_GOD).fill_percent1[1] = 100 - dungeon(god_quest.DUNGEON_GOD).outer_wall = 202 - dungeon(god_quest.DUNGEON_GOD).inner_wall = 96 - dungeon(god_quest.DUNGEON_GOD).fill_method = 1 - - -- O: nt much combat.. tools where ransackers have tried to chop trees down. - dungeon(god_quest.DUNGEON_GOD).objs.treasure = 20 - dungeon(god_quest.DUNGEON_GOD).objs.combat = 10 - dungeon(god_quest.DUNGEON_GOD).objs.magic = 30 - dungeon(god_quest.DUNGEON_GOD).objs.tools = 40 - - -- F: Natural looking - dungeon(god_quest.DUNGEON_GOD).flags1 = bor(DF1_NO_DOORS, DF1_WATER_RIVERS, DF1_NO_DESTROY, DF1_ADJUST_LEVEL_1, DF1_NO_RECALL) - dungeon(god_quest.DUNGEON_GOD).flags2 = bor(DF2_ADJUST_LEVEL_1_2, DF2_NO_SHAFT, DF2_NO_GENO, DF2_ADJUST_LEVEL_PLAYER) - - -- R: Demons, Undead, non-living - dungeon(god_quest.DUNGEON_GOD).rules[1].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[1].percent = 100 - - -- M: - dungeon(god_quest.DUNGEON_GOD).rules[1].mflags3 = bor(RF3_DEMON, RF3_UNDEAD, RF3_NONLIVING) - + quest_god_set_god_dungeon_attributes_yavanna() elseif player.pgod == GOD_AULE then - - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_level = 24 - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_chance = 80 - - -- L: floor is dirt/mud/shallow water - dungeon(god_quest.DUNGEON_GOD).floor1 = 88 - dungeon(god_quest.DUNGEON_GOD).floor2 = 94 - dungeon(god_quest.DUNGEON_GOD).floor3 = 84 - dungeon(god_quest.DUNGEON_GOD).floor_percent1[1] = 45 - dungeon(god_quest.DUNGEON_GOD).floor_percent2[1] = 45 - dungeon(god_quest.DUNGEON_GOD).floor_percent3[1] = 10 - dungeon(god_quest.DUNGEON_GOD).floor_percent1[2] = 35 - dungeon(god_quest.DUNGEON_GOD).floor_percent2[2] = 35 - dungeon(god_quest.DUNGEON_GOD).floor_percent3[2] = 30 - - -- A: Grey mountains, inner walls are low hills - dungeon(god_quest.DUNGEON_GOD).fill_type1 = 216 - dungeon(god_quest.DUNGEON_GOD).fill_percent1[1] = 100 - dungeon(god_quest.DUNGEON_GOD).outer_wall = 216 - dungeon(god_quest.DUNGEON_GOD).inner_wall = 213 - dungeon(god_quest.DUNGEON_GOD).fill_method = 1 - - -- O: Weapons and tools only - dungeon(god_quest.DUNGEON_GOD).objs.treasure = 0 - dungeon(god_quest.DUNGEON_GOD).objs.combat = 50 - dungeon(god_quest.DUNGEON_GOD).objs.magic = 0 - dungeon(god_quest.DUNGEON_GOD).objs.tools = 50 - - -- F: Small, no destroyed levels, min monster level = dungeon level - dungeon(god_quest.DUNGEON_GOD).flags1 = bor(DF1_SMALL, DF1_NO_DESTROY, DF1_ADJUST_LEVEL_1, DF1_NO_STREAMERS) - - -- R: No restrictions on monsters here - dungeon(god_quest.DUNGEON_GOD).rules[1].mode = 0 - dungeon(god_quest.DUNGEON_GOD).rules[1].percent = 80 - + quest_god_set_god_dungeon_attributes_aule() elseif player.pgod == GOD_VARDA then - - -- Varda lives with Manwe, so high in the clouds - -- W: Has average number of monsters. - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_level = 18 - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_chance = 160 - - - -- L: floor will be grass and flowers - dungeon(god_quest.DUNGEON_GOD).floor1 = 89 - dungeon(god_quest.DUNGEON_GOD).floor2 = 82 - dungeon(god_quest.DUNGEON_GOD).floor_percent1[1] = 85 - dungeon(god_quest.DUNGEON_GOD).floor_percent2[1] = 15 - - -- A: Outer wall is 'hail stone wall', inner wall 'dense fog'. Filled at max smoothing, like islands. - dungeon(god_quest.DUNGEON_GOD).fill_type1 = 211 - dungeon(god_quest.DUNGEON_GOD).fill_percent1[1] = 100 - dungeon(god_quest.DUNGEON_GOD).outer_wall = 210 - dungeon(god_quest.DUNGEON_GOD).inner_wall = 211 - dungeon(god_quest.DUNGEON_GOD).fill_method = 4 - - -- O: Varda likes magical items and tools, not much treasure or weapons - dungeon(god_quest.DUNGEON_GOD).objs.treasure = 15 - dungeon(god_quest.DUNGEON_GOD).objs.combat = 5 - dungeon(god_quest.DUNGEON_GOD).objs.magic = 55 - dungeon(god_quest.DUNGEON_GOD).objs.tools = 25 - - -- F: It's open, goes up like a tower, give it a few interesting rooms, make the monsters hard(ish). - dungeon(god_quest.DUNGEON_GOD).flags1 = bor(DF1_NO_DOORS, DF1_TOWER, DF1_CAVERN, DF1_ADJUST_LEVEL_1) - dungeon(god_quest.DUNGEON_GOD).flags2 = bor(DF2_NO_SHAFT, DF2_ADJUST_LEVEL_PLAYER) - - -- R: - dungeon(god_quest.DUNGEON_GOD).rules[1].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[1].percent = 20 - dungeon(god_quest.DUNGEON_GOD).rules[2].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[2].percent = 20 - dungeon(god_quest.DUNGEON_GOD).rules[3].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[3].percent = 20 - dungeon(god_quest.DUNGEON_GOD).rules[4].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[4].percent = 20 - dungeon(god_quest.DUNGEON_GOD).rules[5].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[5].percent = 20 - - -- M: We want air(poison-type) or flying characters. Orcs too. - dungeon(god_quest.DUNGEON_GOD).rules[1].mflags2 = RF2_INVISIBLE - dungeon(god_quest.DUNGEON_GOD).rules[2].mflags3 = bor(RF3_ORC, RF3_IM_POIS) - dungeon(god_quest.DUNGEON_GOD).rules[3].mflags4 = bor(RF4_BR_POIS, RF4_BR_GRAV) - dungeon(god_quest.DUNGEON_GOD).rules[4].mflags5 = RF5_BA_POIS - dungeon(god_quest.DUNGEON_GOD).rules[5].mflags7 = RF7_CAN_FLY - - + quest_god_set_god_dungeon_attributes_varda() elseif player.pgod == GOD_ULMO then - - -- Mandos dungeon is basically Tulkas, except with undead. - -- W: but with lots of monsters - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_level = 20 - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_chance = 120 - - -- L: floor is dirt - dungeon(god_quest.DUNGEON_GOD).floor1 = 88 - dungeon(god_quest.DUNGEON_GOD).floor_percent1[1] = 100 - - -- A: Cheat: walls are water. - dungeon(god_quest.DUNGEON_GOD).fill_type1 = 187 - dungeon(god_quest.DUNGEON_GOD).fill_percent1[1] = 100 - dungeon(god_quest.DUNGEON_GOD).outer_wall = 238 - dungeon(god_quest.DUNGEON_GOD).inner_wall = 84 - dungeon(god_quest.DUNGEON_GOD).fill_method = 0 - - -- O: Lots of treasure, not much else. - dungeon(god_quest.DUNGEON_GOD).objs.treasure = 90 - dungeon(god_quest.DUNGEON_GOD).objs.combat = 0 - dungeon(god_quest.DUNGEON_GOD).objs.magic = 5 - dungeon(god_quest.DUNGEON_GOD).objs.tools = 5 - - -- F: fairly standard - dungeon(god_quest.DUNGEON_GOD).flags1 = bor(DF1_NO_DESTROY, DF1_ADJUST_LEVEL_2) - dungeon(god_quest.DUNGEON_GOD).flags2 = DF2_ADJUST_LEVEL_PLAYER - - -- R: - dungeon(god_quest.DUNGEON_GOD).rules[1].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[1].percent = 35 - dungeon(god_quest.DUNGEON_GOD).rules[2].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[2].percent = 30 - dungeon(god_quest.DUNGEON_GOD).rules[3].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[3].percent = 30 - - -- M: Aquatic creatures only. - dungeon(god_quest.DUNGEON_GOD).rules[1].mflags3 = RF7_CAN_FLY - dungeon(god_quest.DUNGEON_GOD).rules[2].mflags3 = RF7_AQUATIC - dungeon(god_quest.DUNGEON_GOD).rules[3].mflags3 = RF3_RES_WATE - + quest_god_set_god_dungeon_attributes_ulmo() elseif player.pgod == GOD_MANDOS then - - -- Mandos dungeon is basically Tulkas, except with undead. - -- W: but with lots of monsters - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_level = 20 - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_chance = 120 - - -- L: floor is normal - dungeon(god_quest.DUNGEON_GOD).floor1 = 1 - dungeon(god_quest.DUNGEON_GOD).floor_percent1[1] = 100 - - -- A: Granite walls - dungeon(god_quest.DUNGEON_GOD).fill_type1 = 56 - dungeon(god_quest.DUNGEON_GOD).fill_percent1[1] = 100 - dungeon(god_quest.DUNGEON_GOD).outer_wall = 58 - dungeon(god_quest.DUNGEON_GOD).inner_wall = 57 - dungeon(god_quest.DUNGEON_GOD).fill_method = 0 - - -- O: Loads of combat drops - dungeon(god_quest.DUNGEON_GOD).objs.treasure = 10 - dungeon(god_quest.DUNGEON_GOD).objs.combat = 70 - dungeon(god_quest.DUNGEON_GOD).objs.magic = 5 - dungeon(god_quest.DUNGEON_GOD).objs.tools = 15 - - -- F: fairly standard - dungeon(god_quest.DUNGEON_GOD).flags1 = bor(DF1_NO_DESTROY, DF1_ADJUST_LEVEL_2) - dungeon(god_quest.DUNGEON_GOD).flags2 = DF2_ADJUST_LEVEL_PLAYER - - -- R: - dungeon(god_quest.DUNGEON_GOD).rules[1].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[1].percent = 100 - - -- M: vampires! - dungeon(god_quest.DUNGEON_GOD).rules[1].r_char = "V" - dungeon(god_quest.DUNGEON_GOD).rules[1].mflags3 = bor(RF3_UNDEAD, RF3_EVIL) - + quest_god_set_god_dungeon_attributes_mandos() end -- W: All dungeons are 5 levels deep, and created at 2/3 of the player clvl when the quest is given diff --git a/lib/scpt/god.lua b/lib/scpt/god.lua index bb7aa92c..1b668b47 100644 --- a/lib/scpt/god.lua +++ b/lib/scpt/god.lua @@ -273,225 +273,15 @@ function set_god_dungeon_attributes() -- dungeon properties altered according to which god player is worshipping, if player.pgod == GOD_ERU then - - -- The Eru temple is based on Meneltarma. - -- W: Not too many monsters (they'll be tough though, with big levels) - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_level = 14 - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_chance = 200 - - -- L: Dirt and grass. More dirt at bottom, more grass at top. rocky ground would be nice - dungeon(god_quest.DUNGEON_GOD).floor1 = 88 - dungeon(god_quest.DUNGEON_GOD).floor2 = 89 - dungeon(god_quest.DUNGEON_GOD).floor_percent1[1] = 70 - dungeon(god_quest.DUNGEON_GOD).floor_percent2[1] = 30 - dungeon(god_quest.DUNGEON_GOD).floor_percent1[2] = 10 - dungeon(god_quest.DUNGEON_GOD).floor_percent2[2] = 90 - - -- A: Outer wall mountain chain. other walls granite - dungeon(god_quest.DUNGEON_GOD).fill_type1 = 97 - dungeon(god_quest.DUNGEON_GOD).fill_percent1[1] = 100 - dungeon(god_quest.DUNGEON_GOD).outer_wall = 57 - dungeon(god_quest.DUNGEON_GOD).inner_wall = 97 - dungeon(god_quest.DUNGEON_GOD).fill_method = 2 - - -- O: "At Meneltarma no weapon or tool had ever been borne" (but invaders would have left a small number) - dungeon(god_quest.DUNGEON_GOD).objs.treasure = 45 - dungeon(god_quest.DUNGEON_GOD).objs.combat = 5 - dungeon(god_quest.DUNGEON_GOD).objs.magic = 45 - dungeon(god_quest.DUNGEON_GOD).objs.tools = 5 - - -- F: A large pillar, with stairs created at edges. (You can't climb a rock through the middle, can you?) - dungeon(god_quest.DUNGEON_GOD).flags1 = bor(DF1_BIG, DF1_NO_DOORS, DF1_CIRCULAR_ROOMS, DF1_EMPTY, DF1_TOWER, DF1_FLAT, DF1_ADJUST_LEVEL_2) - dungeon(god_quest.DUNGEON_GOD).flags2 = bor(DF2_ADJUST_LEVEL_1_2, DF2_NO_SHAFT, DF2_ADJUST_LEVEL_PLAYER) - - -- R: - dungeon(god_quest.DUNGEON_GOD).rules[1].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[1].percent = 50 - - -- M: We want evil or flying characters - dungeon(god_quest.DUNGEON_GOD).rules[1].mflags3 = RF3_EVIL - - dungeon(god_quest.DUNGEON_GOD).rules[2].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[2].percent = 50 - - -- M: We want evil or flying characters - dungeon(god_quest.DUNGEON_GOD).rules[2].mflags7 = RF7_CAN_FLY - - + quest_god_set_god_dungeon_attributes_eru() elseif player.pgod == GOD_MANWE then - - -- Manwe's lost temple is high in the clouds - -- W: Has average number of monsters. - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_level = 18 - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_chance = 160 - - - -- L: floor will be 'cloud-like vapour' and pools of 'condensing water' - dungeon(god_quest.DUNGEON_GOD).floor1 = 208 - dungeon(god_quest.DUNGEON_GOD).floor2 = 209 - dungeon(god_quest.DUNGEON_GOD).floor_percent1[1] = 85 - dungeon(god_quest.DUNGEON_GOD).floor_percent2[1] = 15 - - -- A: Outer wall is 'hail stone wall', inner wall 'dense fog'. FIlled at max smoothing, like islands. - dungeon(god_quest.DUNGEON_GOD).fill_type1 = 211 - dungeon(god_quest.DUNGEON_GOD).fill_percent1[1] = 100 - dungeon(god_quest.DUNGEON_GOD).outer_wall = 210 - dungeon(god_quest.DUNGEON_GOD).inner_wall = 211 - dungeon(god_quest.DUNGEON_GOD).fill_method = 4 - - -- O: Can't imagine Manwe having much treasure. Little need for tools in a cloud temple. lots of magical stuff though... - dungeon(god_quest.DUNGEON_GOD).objs.treasure = 15 - dungeon(god_quest.DUNGEON_GOD).objs.combat = 25 - dungeon(god_quest.DUNGEON_GOD).objs.magic = 55 - dungeon(god_quest.DUNGEON_GOD).objs.tools = 5 - - -- F: It's open, goes up like a tower, give it a few interesting rooms, make the monsters hard(ish). - dungeon(god_quest.DUNGEON_GOD).flags1 = bor(DF1_NO_DOORS, DF1_TOWER, DF1_CAVERN, DF1_ADJUST_LEVEL_2) - dungeon(god_quest.DUNGEON_GOD).flags2 = bor(DF2_NO_SHAFT, DF2_ADJUST_LEVEL_PLAYER) - - -- R: - dungeon(god_quest.DUNGEON_GOD).rules[1].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[1].percent = 20 - dungeon(god_quest.DUNGEON_GOD).rules[2].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[2].percent = 20 - dungeon(god_quest.DUNGEON_GOD).rules[3].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[3].percent = 20 - dungeon(god_quest.DUNGEON_GOD).rules[4].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[4].percent = 20 - dungeon(god_quest.DUNGEON_GOD).rules[5].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[5].percent = 20 - - -- M: We want air(poison-type) or flying characters. Orcs too. They would have ransacked his elf-loving temple :) - dungeon(god_quest.DUNGEON_GOD).rules[1].mflags2 = RF2_INVISIBLE - dungeon(god_quest.DUNGEON_GOD).rules[2].mflags3 = bor(RF3_ORC, RF3_IM_POIS) - dungeon(god_quest.DUNGEON_GOD).rules[3].mflags4 = bor(RF4_BR_POIS, RF4_BR_GRAV) - dungeon(god_quest.DUNGEON_GOD).rules[4].mflags5 = RF5_BA_POIS - dungeon(god_quest.DUNGEON_GOD).rules[5].mflags7 = RF7_CAN_FLY - - + quest_god_set_god_dungeon_attributes_manwe() elseif player.pgod == GOD_TULKAS then - - -- Tulkas dungeon is quite normal, possibly a bit boring to be honest. Maybe I should add something radical to it. - -- 'The house of Tulkas in the midmost of Valmar was a house of mirth and revelry. It sprang into the air with many storeys, - -- and had a tower of bronze and pillars of copper in a wide arcade' - -- W: but with lots of monsters - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_level = 20 - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_chance = 120 - - -- L: floor is normal - dungeon(god_quest.DUNGEON_GOD).floor1 = 1 - dungeon(god_quest.DUNGEON_GOD).floor_percent1[1] = 100 - - -- A: Granite walls - dungeon(god_quest.DUNGEON_GOD).fill_type1 = 56 - dungeon(god_quest.DUNGEON_GOD).fill_percent1[1] = 100 - dungeon(god_quest.DUNGEON_GOD).outer_wall = 58 - dungeon(god_quest.DUNGEON_GOD).inner_wall = 57 - dungeon(god_quest.DUNGEON_GOD).fill_method = 0 - - -- O: Loads of combat drops - dungeon(god_quest.DUNGEON_GOD).objs.treasure = 10 - dungeon(god_quest.DUNGEON_GOD).objs.combat = 70 - dungeon(god_quest.DUNGEON_GOD).objs.magic = 5 - dungeon(god_quest.DUNGEON_GOD).objs.tools = 15 - - -- F: fairly standard - dungeon(god_quest.DUNGEON_GOD).flags1 = bor(DF1_NO_DESTROY, DF1_ADJUST_LEVEL_2) - dungeon(god_quest.DUNGEON_GOD).flags2 = DF2_ADJUST_LEVEL_PLAYER - - -- R: - dungeon(god_quest.DUNGEON_GOD).rules[1].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[1].percent = 100 - - -- M: plenty demons please - dungeon(god_quest.DUNGEON_GOD).rules[1].mflags3 = bor(RF3_DEMON, RF3_EVIL) - - + quest_god_set_god_dungeon_attributes_tulkas() elseif player.pgod == GOD_MELKOR then - - -- Melkors dungeon will be dark, fiery and stuff - -- Many many monsters! (but prob ADJUST_LEVEL_1_2) - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_level = 24 - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_chance = 80 - - - -- L: floor is dirt/mud/nether - dungeon(god_quest.DUNGEON_GOD).floor1 = 88 - dungeon(god_quest.DUNGEON_GOD).floor2 = 94 - dungeon(god_quest.DUNGEON_GOD).floor3 = 102 - dungeon(god_quest.DUNGEON_GOD).floor_percent1[1] = 45 - dungeon(god_quest.DUNGEON_GOD).floor_percent2[1] = 45 - dungeon(god_quest.DUNGEON_GOD).floor_percent3[1] = 10 - dungeon(god_quest.DUNGEON_GOD).floor_percent1[2] = 35 - dungeon(god_quest.DUNGEON_GOD).floor_percent2[2] = 35 - dungeon(god_quest.DUNGEON_GOD).floor_percent3[2] = 30 - - -- A: Granite walls to fill but glass walls for room perimeters (you can see the nasty monsters coming) - dungeon(god_quest.DUNGEON_GOD).fill_type1 = 188 - dungeon(god_quest.DUNGEON_GOD).fill_percent1[1] = 100 - dungeon(god_quest.DUNGEON_GOD).outer_wall = 188 - dungeon(god_quest.DUNGEON_GOD).inner_wall = 57 - dungeon(god_quest.DUNGEON_GOD).fill_method = 1 - - -- O: Even drops - dungeon(god_quest.DUNGEON_GOD).objs.treasure = 25 - dungeon(god_quest.DUNGEON_GOD).objs.combat = 25 - dungeon(god_quest.DUNGEON_GOD).objs.magic = 25 - dungeon(god_quest.DUNGEON_GOD).objs.tools = 25 - - -- F: Small, lava rivers, nasty monsters hehehehehe - dungeon(god_quest.DUNGEON_GOD).flags1 = bor(DF1_SMALL, DF1_LAVA_RIVERS, DF1_ADJUST_LEVEL_1) - dungeon(god_quest.DUNGEON_GOD).flags2 = bor(DF2_ADJUST_LEVEL_1_2, DF2_ADJUST_LEVEL_PLAYER) - - -- R: No restrictions on monsters here - dungeon(god_quest.DUNGEON_GOD).rules[1].mode = 0 - dungeon(god_quest.DUNGEON_GOD).rules[1].percent = 80 - - -- R: Apart from making sure we have some GOOD ones - dungeon(god_quest.DUNGEON_GOD).rules[2].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[2].percent = 20 - - -- M: - dungeon(god_quest.DUNGEON_GOD).rules[2].mflags3 = RF3_GOOD - + quest_god_set_god_dungeon_attributes_melkor() elseif player.pgod == GOD_YAVANNA then - - -- Yavannas dungeon will be very natural, tress and stuff. - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_level = 22 - dungeon(god_quest.DUNGEON_GOD).min_m_alloc_chance = 100 - - -- L: floor is grass/flowers, plus dirt so not always regenerating quick! - dungeon(god_quest.DUNGEON_GOD).floor1 = 89 - dungeon(god_quest.DUNGEON_GOD).floor2 = 199 - dungeon(god_quest.DUNGEON_GOD).floor3 = 88 - dungeon(god_quest.DUNGEON_GOD).floor_percent1[1] = 40 - dungeon(god_quest.DUNGEON_GOD).floor_percent2[1] = 15 - dungeon(god_quest.DUNGEON_GOD).floor_percent3[1] = 45 - - -- A: Tree walls to fill, small trees for inner walls - dungeon(god_quest.DUNGEON_GOD).fill_type1 = 96 - dungeon(god_quest.DUNGEON_GOD).fill_percent1[1] = 100 - dungeon(god_quest.DUNGEON_GOD).outer_wall = 202 - dungeon(god_quest.DUNGEON_GOD).inner_wall = 96 - dungeon(god_quest.DUNGEON_GOD).fill_method = 1 - - -- O: nt much combat.. tools where ransackers have tried to chop trees down. - dungeon(god_quest.DUNGEON_GOD).objs.treasure = 20 - dungeon(god_quest.DUNGEON_GOD).objs.combat = 10 - dungeon(god_quest.DUNGEON_GOD).objs.magic = 30 - dungeon(god_quest.DUNGEON_GOD).objs.tools = 40 - - -- F: Natural looking - dungeon(god_quest.DUNGEON_GOD).flags1 = bor(DF1_NO_DOORS, DF1_WATER_RIVERS, DF1_NO_DESTROY, DF1_ADJUST_LEVEL_1, DF1_NO_RECALL) - dungeon(god_quest.DUNGEON_GOD).flags2 = bor(DF2_ADJUST_LEVEL_1_2, DF2_NO_SHAFT, DF2_NO_GENO, DF2_ADJUST_LEVEL_PLAYER) - - -- R: Demons, Undead, non-living - dungeon(god_quest.DUNGEON_GOD).rules[1].mode = 3 - dungeon(god_quest.DUNGEON_GOD).rules[1].percent = 100 - - -- M: - dungeon(god_quest.DUNGEON_GOD).rules[1].mflags3 = bor(RF3_DEMON, RF3_UNDEAD, RF3_NONLIVING) - + quest_god_set_god_dungeon_attributes_yavanna() end -- W: All dungeons are 5 levels deep, and created at 2/3 of the player clvl when the quest is given diff --git a/src/plots.h b/src/plots.h index 31653f36..9ec9bf80 100644 --- a/src/plots.h +++ b/src/plots.h @@ -66,3 +66,12 @@ extern bool_ quest_fireproof_describe(FILE *fff); /******* Plot God Quest **************/ extern void quest_god_place_rand_dung(); extern void quest_god_generate_relic(); +extern void quest_god_set_god_dungeon_attributes_eru(); +extern void quest_god_set_god_dungeon_attributes_manwe(); +extern void quest_god_set_god_dungeon_attributes_tulkas(); +extern void quest_god_set_god_dungeon_attributes_melkor(); +extern void quest_god_set_god_dungeon_attributes_yavanna(); +extern void quest_god_set_god_dungeon_attributes_aule(); +extern void quest_god_set_god_dungeon_attributes_varda(); +extern void quest_god_set_god_dungeon_attributes_ulmo(); +extern void quest_god_set_god_dungeon_attributes_mandos(); diff --git a/src/q_god.c b/src/q_god.c index 5725c984..9b302011 100644 --- a/src/q_god.c +++ b/src/q_god.c @@ -183,3 +183,441 @@ void quest_god_generate_relic() /* Reset some variables */ set_relic_gen_tries(0); } + +void quest_god_set_god_dungeon_attributes_eru() +{ + /* The Eru temple is based on Meneltarma. */ + + /* W: Not too many monsters (they'll be tough though, with big + * levels) */ + d_info[DUNGEON_GOD].min_m_alloc_level = 14; + d_info[DUNGEON_GOD].max_m_alloc_chance = 200; + + /* L: Dirt and grass. More dirt at bottom, more grass at + * top. rocky ground would be nice */ + d_info[DUNGEON_GOD].floor1 = 88; + d_info[DUNGEON_GOD].floor2 = 89; + d_info[DUNGEON_GOD].floor_percent1[0] = 70; + d_info[DUNGEON_GOD].floor_percent2[0] = 30; + d_info[DUNGEON_GOD].floor_percent1[1] = 10; + d_info[DUNGEON_GOD].floor_percent2[1] = 90; + + /* A: Outer wall mountain chain. other walls granite */ + d_info[DUNGEON_GOD].fill_type1 = 97; + d_info[DUNGEON_GOD].fill_percent1[0] = 100; + d_info[DUNGEON_GOD].outer_wall = 57; + d_info[DUNGEON_GOD].inner_wall = 97; + d_info[DUNGEON_GOD].fill_method = 2; + + /* O: "At Meneltarma no weapon or tool had ever been borne" + * (but invaders would have left a small number) */ + d_info[DUNGEON_GOD].objs.treasure = 45; + d_info[DUNGEON_GOD].objs.combat = 5; + d_info[DUNGEON_GOD].objs.magic = 45; + d_info[DUNGEON_GOD].objs.tools = 5; + + /* F: A large pillar, with stairs created at edges. (You can't + * climb a rock through the middle, can you?) */ + d_info[DUNGEON_GOD].flags1 = + DF1_BIG | DF1_NO_DOORS | DF1_CIRCULAR_ROOMS | + DF1_EMPTY | DF1_TOWER | DF1_FLAT | DF1_ADJUST_LEVEL_2; + d_info[DUNGEON_GOD].flags2 = + DF2_ADJUST_LEVEL_1_2 | + DF2_NO_SHAFT | + DF2_ADJUST_LEVEL_PLAYER; + + /* R: */ + d_info[DUNGEON_GOD].rules[0].mode = 3; + d_info[DUNGEON_GOD].rules[0].percent = 50; + + /* M: We want evil or flying characters */ + d_info[DUNGEON_GOD].rules[0].mflags3 = RF3_EVIL; + + d_info[DUNGEON_GOD].rules[1].mode = 3; + d_info[DUNGEON_GOD].rules[1].percent = 50; + + /* M: We want evil or flying characters */ + d_info[DUNGEON_GOD].rules[1].mflags7 = RF7_CAN_FLY; +} + +void quest_god_set_god_dungeon_attributes_manwe() +{ + /* Manwe's lost temple is high in the clouds */ + + /* W: Has average number of monsters. */ + d_info[DUNGEON_GOD].min_m_alloc_level = 18; + d_info[DUNGEON_GOD].max_m_alloc_chance = 160; + + /* L: floor will be 'cloud-like vapour' and pools of + * 'condensing water' */ + d_info[DUNGEON_GOD].floor1 = 208; + d_info[DUNGEON_GOD].floor2 = 209; + d_info[DUNGEON_GOD].floor_percent1[0] = 85; + d_info[DUNGEON_GOD].floor_percent2[0] = 15; + + /* A: Outer wall is 'hail stone wall', inner wall 'dense + * fog'. FIlled at max smoothing, like islands. */ + d_info[DUNGEON_GOD].fill_type1 = 211; + d_info[DUNGEON_GOD].fill_percent1[0] = 100; + d_info[DUNGEON_GOD].outer_wall = 210; + d_info[DUNGEON_GOD].inner_wall = 211; + d_info[DUNGEON_GOD].fill_method = 4; + + /* O: Can't imagine Manwe having much treasure. Little need + * for tools in a cloud temple. lots of magical stuff + * though... */ + d_info[DUNGEON_GOD].objs.treasure = 15; + d_info[DUNGEON_GOD].objs.combat = 25; + d_info[DUNGEON_GOD].objs.magic = 55; + d_info[DUNGEON_GOD].objs.tools = 5; + + /* F: It's open, goes up like a tower, give it a few + * interesting rooms, make the monsters hard(ish). */ + d_info[DUNGEON_GOD].flags1 = + DF1_NO_DOORS | DF1_TOWER | + DF1_CAVERN | DF1_ADJUST_LEVEL_2; + d_info[DUNGEON_GOD].flags2 = + DF2_NO_SHAFT | DF2_ADJUST_LEVEL_PLAYER; + + /* R: */ + d_info[DUNGEON_GOD].rules[0].mode = 3; + d_info[DUNGEON_GOD].rules[0].percent = 20; + d_info[DUNGEON_GOD].rules[1].mode = 3; + d_info[DUNGEON_GOD].rules[1].percent = 20; + d_info[DUNGEON_GOD].rules[2].mode = 3; + d_info[DUNGEON_GOD].rules[2].percent = 20; + d_info[DUNGEON_GOD].rules[3].mode = 3; + d_info[DUNGEON_GOD].rules[3].percent = 20; + d_info[DUNGEON_GOD].rules[4].mode = 3; + d_info[DUNGEON_GOD].rules[4].percent = 20; + + /* M: We want air(poison-type) or flying characters. Orcs + * too. They would have ransacked his elf-loving temple :) */ + d_info[DUNGEON_GOD].rules[0].mflags2 = RF2_INVISIBLE; + d_info[DUNGEON_GOD].rules[1].mflags3 = RF3_ORC | RF3_IM_POIS; + d_info[DUNGEON_GOD].rules[2].mflags4 = RF4_BR_POIS | RF4_BR_GRAV; + d_info[DUNGEON_GOD].rules[3].mflags5 = RF5_BA_POIS; + d_info[DUNGEON_GOD].rules[4].mflags7 = RF7_CAN_FLY; +} + +void quest_god_set_god_dungeon_attributes_tulkas() +{ + /* Tulkas dungeon is quite normal, possibly a bit boring to be + * honest. Maybe I should add something radical to it. 'The + * house of Tulkas in the midmost of Valmar was a house of + * mirth and revelry. It sprang into the air with many + * storeys, and had a tower of bronze and pillars of copper in + * a wide arcade' + */ + + /* W: but with lots of monsters */ + d_info[DUNGEON_GOD].min_m_alloc_level = 20; + d_info[DUNGEON_GOD].max_m_alloc_chance = 120; + + /* L: floor is normal */ + d_info[DUNGEON_GOD].floor1 = 1; + d_info[DUNGEON_GOD].floor_percent1[0] = 100; + + /* A: Granite walls */ + d_info[DUNGEON_GOD].fill_type1 = 56; + d_info[DUNGEON_GOD].fill_percent1[0] = 100; + d_info[DUNGEON_GOD].outer_wall = 58; + d_info[DUNGEON_GOD].inner_wall = 57; + d_info[DUNGEON_GOD].fill_method = 0; + + /* O: Loads of combat drops */ + d_info[DUNGEON_GOD].objs.treasure = 10; + d_info[DUNGEON_GOD].objs.combat = 70; + d_info[DUNGEON_GOD].objs.magic = 5; + d_info[DUNGEON_GOD].objs.tools = 15; + + /* F: fairly standard */ + d_info[DUNGEON_GOD].flags1 = DF1_NO_DESTROY | DF1_ADJUST_LEVEL_2; + d_info[DUNGEON_GOD].flags2 = DF2_ADJUST_LEVEL_PLAYER; + + /* R: */ + d_info[DUNGEON_GOD].rules[0].mode = 3; + d_info[DUNGEON_GOD].rules[0].percent = 100; + + /* M: plenty demons please */ + d_info[DUNGEON_GOD].rules[0].mflags3 = RF3_DEMON | RF3_EVIL; +} + +void quest_god_set_god_dungeon_attributes_melkor() +{ + /* Melkors dungeon will be dark, fiery and stuff */ + + /* Many many monsters! (but prob ADJUST_LEVEL_1_2) */ + d_info[DUNGEON_GOD].min_m_alloc_level = 24; + d_info[DUNGEON_GOD].max_m_alloc_chance = 80; + + /* L: floor is dirt/mud/nether */ + d_info[DUNGEON_GOD].floor1 = 88; + d_info[DUNGEON_GOD].floor2 = 94; + d_info[DUNGEON_GOD].floor3 = 102; + d_info[DUNGEON_GOD].floor_percent1[0] = 45; + d_info[DUNGEON_GOD].floor_percent2[0] = 45; + d_info[DUNGEON_GOD].floor_percent3[0] = 10; + d_info[DUNGEON_GOD].floor_percent1[1] = 35; + d_info[DUNGEON_GOD].floor_percent2[1] = 35; + d_info[DUNGEON_GOD].floor_percent3[1] = 30; + + /* A: Granite walls to fill but glass walls for room + * perimeters (you can see the nasty monsters coming) */ + d_info[DUNGEON_GOD].fill_type1 = 188; + d_info[DUNGEON_GOD].fill_percent1[0] = 100; + d_info[DUNGEON_GOD].outer_wall = 188; + d_info[DUNGEON_GOD].inner_wall = 57; + d_info[DUNGEON_GOD].fill_method = 1; + + /* O: Even drops */ + d_info[DUNGEON_GOD].objs.treasure = 25; + d_info[DUNGEON_GOD].objs.combat = 25; + d_info[DUNGEON_GOD].objs.magic = 25; + d_info[DUNGEON_GOD].objs.tools = 25; + + /* F: Small, lava rivers, nasty monsters hehehehehe */ + d_info[DUNGEON_GOD].flags1 = DF1_SMALL | DF1_LAVA_RIVERS | DF1_ADJUST_LEVEL_1; + d_info[DUNGEON_GOD].flags2 = DF2_ADJUST_LEVEL_1_2 | DF2_ADJUST_LEVEL_PLAYER; + + /* R: No restrictions on monsters here */ + d_info[DUNGEON_GOD].rules[0].mode = 0; + d_info[DUNGEON_GOD].rules[0].percent = 80; + + /* R: Apart from making sure we have some GOOD ones */ + d_info[DUNGEON_GOD].rules[1].mode = 3; + d_info[DUNGEON_GOD].rules[1].percent = 20; + + /* M: */ + d_info[DUNGEON_GOD].rules[1].mflags3 = RF3_GOOD; +} + +void quest_god_set_god_dungeon_attributes_yavanna() +{ + /* Yavannas dungeon will be very natural, tress and stuff. */ + + d_info[DUNGEON_GOD].min_m_alloc_level = 22; + d_info[DUNGEON_GOD].max_m_alloc_chance = 100; + + /* L: floor is grass/flowers, plus dirt so not always + * regenerating quick! */ + d_info[DUNGEON_GOD].floor1 = 89; + d_info[DUNGEON_GOD].floor2 = 199; + d_info[DUNGEON_GOD].floor3 = 88; + d_info[DUNGEON_GOD].floor_percent1[0] = 40; + d_info[DUNGEON_GOD].floor_percent2[0] = 15; + d_info[DUNGEON_GOD].floor_percent3[0] = 45; + + /* A: Tree walls to fill, small trees for inner walls */ + d_info[DUNGEON_GOD].fill_type1 = 96; + d_info[DUNGEON_GOD].fill_percent1[0] = 100; + d_info[DUNGEON_GOD].outer_wall = 202; + d_info[DUNGEON_GOD].inner_wall = 96; + d_info[DUNGEON_GOD].fill_method = 1; + + /* O: not much combat.. tools where ransackers have tried to + * chop trees down. */ + d_info[DUNGEON_GOD].objs.treasure = 20; + d_info[DUNGEON_GOD].objs.combat = 10; + d_info[DUNGEON_GOD].objs.magic = 30; + d_info[DUNGEON_GOD].objs.tools = 40; + + /* F: Natural looking */ + d_info[DUNGEON_GOD].flags1 = + DF1_NO_DOORS | DF1_WATER_RIVERS | + DF1_NO_DESTROY | DF1_ADJUST_LEVEL_1 | + DF1_NO_RECALL; + d_info[DUNGEON_GOD].flags2 = + DF2_ADJUST_LEVEL_1_2 | DF2_NO_SHAFT | + DF2_NO_GENO | DF2_ADJUST_LEVEL_PLAYER; + + /* R: Demons, Undead, non-living */ + d_info[DUNGEON_GOD].rules[0].mode = 3; + d_info[DUNGEON_GOD].rules[0].percent = 100; + + /* M: */ + d_info[DUNGEON_GOD].rules[0].mflags3 = + RF3_DEMON | RF3_UNDEAD | RF3_NONLIVING; +} + +void quest_god_set_god_dungeon_attributes_aule() +{ + d_info[DUNGEON_GOD].min_m_alloc_level = 24; + d_info[DUNGEON_GOD].max_m_alloc_chance = 80; + + /* L: floor is dirt/mud/shallow water */ + d_info[DUNGEON_GOD].floor1 = 88; + d_info[DUNGEON_GOD].floor2 = 94; + d_info[DUNGEON_GOD].floor3 = 84; + d_info[DUNGEON_GOD].floor_percent1[0] = 45; + d_info[DUNGEON_GOD].floor_percent2[0] = 45; + d_info[DUNGEON_GOD].floor_percent3[0] = 10; + d_info[DUNGEON_GOD].floor_percent1[1] = 35; + d_info[DUNGEON_GOD].floor_percent2[1] = 35; + d_info[DUNGEON_GOD].floor_percent3[1] = 30; + + /* A: Grey mountains, inner walls are low hills */ + d_info[DUNGEON_GOD].fill_type1 = 216; + d_info[DUNGEON_GOD].fill_percent1[0] = 100; + d_info[DUNGEON_GOD].outer_wall = 216; + d_info[DUNGEON_GOD].inner_wall = 213; + d_info[DUNGEON_GOD].fill_method = 1; + + /* O: Weapons and tools only */ + d_info[DUNGEON_GOD].objs.treasure = 0; + d_info[DUNGEON_GOD].objs.combat = 50; + d_info[DUNGEON_GOD].objs.magic = 0; + d_info[DUNGEON_GOD].objs.tools = 50; + + /* F: Small, no destroyed levels, min monster level = dungeon + * level */ + d_info[DUNGEON_GOD].flags1 = + DF1_SMALL | DF1_NO_DESTROY | + DF1_ADJUST_LEVEL_1 | DF1_NO_STREAMERS; + + /* R: No restrictions on monsters here */ + d_info[DUNGEON_GOD].rules[0].mode = 0; + d_info[DUNGEON_GOD].rules[0].percent = 80; +} + +void quest_god_set_god_dungeon_attributes_varda() +{ + /* Varda lives with Manwe, so high in the clouds */ + + /* W: Has average number of monsters. */ + d_info[DUNGEON_GOD].min_m_alloc_level = 18; + d_info[DUNGEON_GOD].max_m_alloc_chance = 160; + + /* L: floor will be grass and flowers */ + d_info[DUNGEON_GOD].floor1 = 89; + d_info[DUNGEON_GOD].floor2 = 82; + d_info[DUNGEON_GOD].floor_percent1[0] = 85; + d_info[DUNGEON_GOD].floor_percent2[0] = 15; + + /* A: Outer wall is 'hail stone wall', inner wall 'dense + * fog'. Filled at max smoothing, like islands. */ + d_info[DUNGEON_GOD].fill_type1 = 211; + d_info[DUNGEON_GOD].fill_percent1[0] = 100; + d_info[DUNGEON_GOD].outer_wall = 210; + d_info[DUNGEON_GOD].inner_wall = 211; + d_info[DUNGEON_GOD].fill_method = 4; + + /* O: Varda likes magical items and tools, not much treasure + * or weapons */ + d_info[DUNGEON_GOD].objs.treasure = 15; + d_info[DUNGEON_GOD].objs.combat = 5; + d_info[DUNGEON_GOD].objs.magic = 55; + d_info[DUNGEON_GOD].objs.tools = 25; + + /* F: It's open, goes up like a tower, give it a few + * interesting rooms, make the monsters hard(ish). */ + d_info[DUNGEON_GOD].flags1 = + DF1_NO_DOORS | DF1_TOWER | + DF1_CAVERN | DF1_ADJUST_LEVEL_1; + d_info[DUNGEON_GOD].flags2 = + DF2_NO_SHAFT | DF2_ADJUST_LEVEL_PLAYER; + + /* R: */ + d_info[DUNGEON_GOD].rules[0].mode = 3; + d_info[DUNGEON_GOD].rules[0].percent = 20; + d_info[DUNGEON_GOD].rules[1].mode = 3; + d_info[DUNGEON_GOD].rules[1].percent = 20; + d_info[DUNGEON_GOD].rules[2].mode = 3; + d_info[DUNGEON_GOD].rules[2].percent = 20; + d_info[DUNGEON_GOD].rules[3].mode = 3; + d_info[DUNGEON_GOD].rules[3].percent = 20; + d_info[DUNGEON_GOD].rules[4].mode = 3; + d_info[DUNGEON_GOD].rules[4].percent = 20; + + /* M: We want air(poison-type) or flying characters. Orcs too. */ + d_info[DUNGEON_GOD].rules[0].mflags2 = RF2_INVISIBLE; + d_info[DUNGEON_GOD].rules[1].mflags3 = RF3_ORC | RF3_IM_POIS; + d_info[DUNGEON_GOD].rules[2].mflags4 = RF4_BR_POIS | RF4_BR_GRAV; + d_info[DUNGEON_GOD].rules[3].mflags5 = RF5_BA_POIS; + d_info[DUNGEON_GOD].rules[4].mflags7 = RF7_CAN_FLY; +} + +void quest_god_set_god_dungeon_attributes_ulmo() +{ + /* Ulmo dungeon is basically Tulkas, except with acquatic creatures. */ + + /* W: but with lots of monsters */ + d_info[DUNGEON_GOD].min_m_alloc_level = 20; + d_info[DUNGEON_GOD].max_m_alloc_chance = 120; + + /* L: floor is dirt */ + d_info[DUNGEON_GOD].floor1 = 88; + d_info[DUNGEON_GOD].floor_percent1[0] = 100; + + /* A: Cheat: walls are water. */ + d_info[DUNGEON_GOD].fill_type1 = 187; + d_info[DUNGEON_GOD].fill_percent1[0] = 100; + d_info[DUNGEON_GOD].outer_wall = 238; + d_info[DUNGEON_GOD].inner_wall = 84; + d_info[DUNGEON_GOD].fill_method = 0; + + /* O: Lots of treasure, not much else. */ + d_info[DUNGEON_GOD].objs.treasure = 90; + d_info[DUNGEON_GOD].objs.combat = 0; + d_info[DUNGEON_GOD].objs.magic = 5; + d_info[DUNGEON_GOD].objs.tools = 5; + + /* F: fairly standard */ + d_info[DUNGEON_GOD].flags1 = DF1_NO_DESTROY | DF1_ADJUST_LEVEL_2; + d_info[DUNGEON_GOD].flags2 = DF2_ADJUST_LEVEL_PLAYER; + + /* R: */ + d_info[DUNGEON_GOD].rules[0].mode = 3; + d_info[DUNGEON_GOD].rules[0].percent = 35; + d_info[DUNGEON_GOD].rules[1].mode = 3; + d_info[DUNGEON_GOD].rules[1].percent = 30; + d_info[DUNGEON_GOD].rules[2].mode = 3; + d_info[DUNGEON_GOD].rules[2].percent = 30; + + /* M: Aquatic creatures only. */ + d_info[DUNGEON_GOD].rules[0].mflags3 = RF7_CAN_FLY; + d_info[DUNGEON_GOD].rules[1].mflags3 = RF7_AQUATIC; + d_info[DUNGEON_GOD].rules[2].mflags3 = RF3_RES_WATE; +} + +void quest_god_set_god_dungeon_attributes_mandos() +{ + /* Mandos dungeon is basically Tulkas, except with undead. */ + + /* W: but with lots of monsters */ + d_info[DUNGEON_GOD].min_m_alloc_level = 20; + d_info[DUNGEON_GOD].max_m_alloc_chance = 120; + + /* L: floor is normal */ + d_info[DUNGEON_GOD].floor1 = 1; + d_info[DUNGEON_GOD].floor_percent1[0] = 100; + + /* A: Granite walls */ + d_info[DUNGEON_GOD].fill_type1 = 56; + d_info[DUNGEON_GOD].fill_percent1[0] = 100; + d_info[DUNGEON_GOD].outer_wall = 58; + d_info[DUNGEON_GOD].inner_wall = 57; + d_info[DUNGEON_GOD].fill_method = 0; + + /* O: Loads of combat drops */ + d_info[DUNGEON_GOD].objs.treasure = 10; + d_info[DUNGEON_GOD].objs.combat = 70; + d_info[DUNGEON_GOD].objs.magic = 5; + d_info[DUNGEON_GOD].objs.tools = 15; + + /* F: fairly standard */ + d_info[DUNGEON_GOD].flags1 = DF1_NO_DESTROY | DF1_ADJUST_LEVEL_2; + d_info[DUNGEON_GOD].flags2 = DF2_ADJUST_LEVEL_PLAYER; + + /* R: */ + d_info[DUNGEON_GOD].rules[0].mode = 3; + d_info[DUNGEON_GOD].rules[0].percent = 100; + + /* M: vampires! */ + d_info[DUNGEON_GOD].rules[0].r_char[0] = 'V'; + d_info[DUNGEON_GOD].rules[0].r_char[1] = '\0'; + d_info[DUNGEON_GOD].rules[0].r_char[2] = '\0'; + d_info[DUNGEON_GOD].rules[0].r_char[3] = '\0'; + d_info[DUNGEON_GOD].rules[0].r_char[4] = '\0'; + d_info[DUNGEON_GOD].rules[0].mflags3 = RF3_UNDEAD | RF3_EVIL; +} diff --git a/src/quest.pkg b/src/quest.pkg index e5780e3f..c2610d9e 100644 --- a/src/quest.pkg +++ b/src/quest.pkg @@ -165,3 +165,12 @@ extern void desc_quest @ quest_desc(int q_idx, int d, char *desc); */ extern void quest_god_place_rand_dung(); extern void quest_god_generate_relic(); +extern void quest_god_set_god_dungeon_attributes_eru(); +extern void quest_god_set_god_dungeon_attributes_manwe(); +extern void quest_god_set_god_dungeon_attributes_tulkas(); +extern void quest_god_set_god_dungeon_attributes_melkor(); +extern void quest_god_set_god_dungeon_attributes_yavanna(); +extern void quest_god_set_god_dungeon_attributes_aule(); +extern void quest_god_set_god_dungeon_attributes_varda(); +extern void quest_god_set_god_dungeon_attributes_ulmo(); +extern void quest_god_set_god_dungeon_attributes_mandos(); -- cgit v1.2.3 From 4a6957a3ac191fa7e75f3f421d97b70058a6fad8 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 8 Apr 2012 22:50:44 +0200 Subject: Lua: God quests: Correct and streamline handling of directions --- lib/mods/theme/scpt/god.lua | 57 +++++++++++++++++++++------------------------ lib/scpt/god.lua | 57 +++++++++++++++++++++------------------------ 2 files changed, 54 insertions(+), 60 deletions(-) diff --git a/lib/mods/theme/scpt/god.lua b/lib/mods/theme/scpt/god.lua index fe8caf5f..ef9bf2f4 100644 --- a/lib/mods/theme/scpt/god.lua +++ b/lib/mods/theme/scpt/god.lua @@ -12,30 +12,39 @@ god_quest.MAX_NUM_GOD_QUESTS = 7 -- d_idx of the god_quest (Lost Temple) dungeon god_quest.DUNGEON_GOD = 30 +-- Show directions given a function to print +function print_directions(feel_it, pfunc) + local home, home_axis, home_distance, home2, home2_axis, home2_distance = get_god_quest_axes() + + local feel_it_str = "." + if feel_it == TRUE then + feel_it_str = ", I can feel it.'" + end + + if home_axis ~= "close" then + pfunc("The temple lies "..home_distance.." to the "..home_axis.." of "..home..", ") + else + pfunc("The temple lies very close to "..home..", ") + end + if home2_axis ~= "close" then + pfunc( "and "..home2_distance.." to the "..home2_axis.." of "..home2..feel_it_str) + else + pfunc("and very close to "..home2..feel_it_str) + end +end + add_quest { ["global"] = "GOD_QUEST", ["name"] = "God quest", ["desc"] = function() - if quest(GOD_QUEST).status == QUEST_STATUS_TAKEN then - - -- get the direction that the dungeon lies from lothlorien/angband - local home, home_axis, home_distance, home2, home2_axis, home2_distance = get_god_quest_axes() - print_hook("#####yGod quest "..god_quest.quests_given.."!\n") print_hook("Thou art to find the lost temple of thy God and\n"); print_hook("to retrieve the lost part of the relic for thy God! \n") - if home_axis ~= "close" then - print_hook("The temple lies "..home_distance.." to the "..home_axis.." of "..home..", \n") - else - print_hook("The temple lies very close to "..home..", \n") - end - if home2_axis ~= "close" then - print_hook( "and "..home2_distance.." to the "..home2_axis.." of "..home2..", I can feel it.' \n") - else - print_hook("and very close to "..home2..", I can feel it.' \n") - end + print_directions(FALSE, function (line) + print_hook(line .. "\n") + end) print_hook("\n") end end, @@ -70,8 +79,6 @@ add_quest god_quest.relic_generated = FALSE end, [HOOK_PLAYER_LEVEL] = function(gained) - local home_axis, home - if gained > 0 then -- roll for chance of quest local give_god_quest = magik(god_quest.CHANCE_OF_GOD_QUEST) @@ -119,9 +126,6 @@ add_quest -- store the variables of the coords where the player was given the quest god_quest.player_y, god_quest.player_x = player.get_wild_coord() - -- establish direction of player and 'home' from dungeon - local home, home_axis, home_distance, home2, home2_axis, home2_distance = get_god_quest_axes() - -- God issues instructions cmsg_print(TERM_L_BLUE, "The voice of "..deity(player.pgod).name.." booms in your head:") @@ -131,17 +135,10 @@ add_quest cmsg_print(TERM_YELLOW, "Thou art to find my lost temple and retrieve a piece of the relic.") cmsg_print(TERM_YELLOW, "When thy task is done, thou art to lift it in the air and call upon my name.") cmsg_print(TERM_YELLOW, "I shall then come to reclaim what is mine!") - if home_axis ~= "close" then - cmsg_print(TERM_YELLOW, "The temple lies "..home_distance.." to the "..home_axis.." of "..home..", ") - else - cmsg_print(TERM_YELLOW, "The temple lies very close to "..home..",") - end - if home2_axis ~= "close" then - cmsg_print(TERM_YELLOW, "and "..home2_distance.." to the "..home2_axis.." of "..home2..", I can feel it.'") - else - cmsg_print(TERM_YELLOW, "and very close to "..home2..", I can feel it.'") - end + print_directions(TRUE, function (line) + cmsg_print(TERM_YELLOW, line) + end) -- Prepare depth of dungeon. If this was generated in set_god_dungeon_attributes(), -- then we'd have trouble if someone levelled up in the dungeon! diff --git a/lib/scpt/god.lua b/lib/scpt/god.lua index 1b668b47..6fbff307 100644 --- a/lib/scpt/god.lua +++ b/lib/scpt/god.lua @@ -12,30 +12,39 @@ god_quest.MAX_NUM_GOD_QUESTS = 5 -- d_idx of the god_quest (Lost Temple) dungeon god_quest.DUNGEON_GOD = 30 +-- Show directions given a function to print +function print_directions(feel_it, pfunc) + local home, home_axis, home_distance, home2, home2_axis, home2_distance = get_god_quest_axes() + + local feel_it_str = "." + if feel_it == TRUE then + feel_it_str = ", I can feel it.'" + end + + if home_axis ~= "close" then + pfunc("The temple lies "..home_distance.." to the "..home_axis.." of "..home..", ") + else + pfunc("The temple lies very close to "..home..", ") + end + if home2_axis ~= "close" then + pfunc( "and "..home2_distance.." to the "..home2_axis.." of "..home2..feel_it_str) + else + pfunc("and very close to "..home2..feel_it_str) + end +end + add_quest { ["global"] = "GOD_QUEST", ["name"] = "God quest", ["desc"] = function() - if quest(GOD_QUEST).status == QUEST_STATUS_TAKEN then - - -- get the direction that the dungeon lies from lothlorien/angband - local home, home_axis, home_distance, home2, home2_axis, home2_distance = get_god_quest_axes() - print_hook("#####yGod quest "..god_quest.quests_given.."!\n") print_hook("Thou art to find the lost temple of thy God and\n"); print_hook("to retrieve the lost part of the relic for thy God! \n") - if home_axis ~= "close" then - print_hook("The temple lies "..home_distance.." to the "..home_axis.." of "..home..", \n") - else - print_hook("The temple lies very close to "..home..", \n") - end - if home2_axis ~= "close" then - print_hook( "and "..home2_distance.." to the "..home2_axis.." of "..home2..".\n") - else - print_hook("and very close to "..home2..".\n") - end + print_directions(FALSE, function (line) + print_hook(line .. "\n") + end) print_hook("\n") end end, @@ -70,8 +79,6 @@ add_quest god_quest.relic_generated = FALSE end, [HOOK_PLAYER_LEVEL] = function(gained) - local home_axis, home - if gained > 0 then -- roll for chance of quest local give_god_quest = magik(god_quest.CHANCE_OF_GOD_QUEST) @@ -111,9 +118,6 @@ add_quest -- store the variables of the coords where the player was given the quest god_quest.player_y, god_quest.player_x = player.get_wild_coord() - -- establish direction of player and 'home' from dungeon - local home, home_axis, home_distance, home2, home2_axis, home2_distance = get_god_quest_axes() - -- God issues instructions cmsg_print(TERM_L_BLUE, "The voice of "..deity(player.pgod).name.." booms in your head:") @@ -123,17 +127,10 @@ add_quest cmsg_print(TERM_YELLOW, "Thou art to find my lost temple and retrieve a piece of the relic.") cmsg_print(TERM_YELLOW, "When thy task is done, thou art to lift it in the air and call upon my name.") cmsg_print(TERM_YELLOW, "I shall then come to reclaim what is mine!") - if home_axis ~= "close" then - cmsg_print(TERM_YELLOW, "The temple lies "..home_distance.." to the "..home_axis.." of "..home..", ") - else - cmsg_print(TERM_YELLOW, "The temple lies very close to "..home..",") - end - if home2_axis ~= "close" then - cmsg_print(TERM_YELLOW, "and "..home2_distance.." to the "..home2_axis.." of "..home2..", I can feel it.'") - else - cmsg_print(TERM_YELLOW, "and very close to "..home2..", I can feel it.'") - end + print_directions(TRUE, function (line) + cmsg_print(TERM_YELLOW, line) + end) -- Prepare depth of dungeon. If this was generated in set_god_dungeon_attributes(), -- then we'd have trouble if someone levelled up in the dungeon! -- cgit v1.2.3 From ee2c62aa4c179945ba24a2545239328a28c8adc1 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 8 Apr 2012 23:26:05 +0200 Subject: Lua: God quests: Factor out differences between ToME/Theme --- lib/mods/theme/scpt/god.lua | 43 ++++++++++++++++++++++++------------------- lib/scpt/god.lua | 27 ++++++++++++++++----------- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/lib/mods/theme/scpt/god.lua b/lib/mods/theme/scpt/god.lua index ef9bf2f4..be8c09a5 100644 --- a/lib/mods/theme/scpt/god.lua +++ b/lib/mods/theme/scpt/god.lua @@ -33,6 +33,29 @@ function print_directions(feel_it, pfunc) end end +-- Set up relic number according to god +function setup_relic_number() + if player.pgod == GOD_ERU then + god_quest.relic_num = 7 + elseif player.pgod == GOD_MANWE then + god_quest.relic_num = 8 + elseif player.pgod == GOD_TULKAS then + god_quest.relic_num = 9 + elseif player.pgod == GOD_MELKOR then + god_quest.relic_num = 10 + elseif player.pgod == GOD_YAVANNA then + god_quest.relic_num = 11 + elseif player.pgod == GOD_AULE then + god_quest.relic_num = 16 + elseif player.pgod == GOD_VARDA then + god_quest.relic_num = 17 + elseif player.pgod == GOD_ULMO then + god_quest.relic_num = 18 + elseif player.pgod == GOD_MANDOS then + god_quest.relic_num = 19 + end +end + add_quest { ["global"] = "GOD_QUEST", @@ -95,25 +118,7 @@ add_quest return else -- each god has different characteristics, so the quests are differnet depending on your god - if player.pgod == GOD_ERU then - god_quest.relic_num = 7 - elseif player.pgod == GOD_MANWE then - god_quest.relic_num = 8 - elseif player.pgod == GOD_TULKAS then - god_quest.relic_num = 9 - elseif player.pgod == GOD_MELKOR then - god_quest.relic_num = 10 - elseif player.pgod == GOD_YAVANNA then - god_quest.relic_num = 11 - elseif player.pgod == GOD_AULE then - god_quest.relic_num = 16 - elseif player.pgod == GOD_VARDA then - god_quest.relic_num = 17 - elseif player.pgod == GOD_ULMO then - god_quest.relic_num = 18 - elseif player.pgod == GOD_MANDOS then - god_quest.relic_num = 19 - end + setup_relic_number() -- This var will need resetting god_quest.relic_generated = FALSE diff --git a/lib/scpt/god.lua b/lib/scpt/god.lua index 6fbff307..938ef802 100644 --- a/lib/scpt/god.lua +++ b/lib/scpt/god.lua @@ -33,6 +33,21 @@ function print_directions(feel_it, pfunc) end end +-- Set up relic number according to god +function setup_relic_number() + if player.pgod == GOD_ERU then + god_quest.relic_num = 7 + elseif player.pgod == GOD_MANWE then + god_quest.relic_num = 8 + elseif player.pgod == GOD_TULKAS then + god_quest.relic_num = 9 + elseif player.pgod == GOD_MELKOR then + god_quest.relic_num = 10 + elseif player.pgod == GOD_YAVANNA then + god_quest.relic_num = 11 + end +end + add_quest { ["global"] = "GOD_QUEST", @@ -95,17 +110,7 @@ add_quest return else -- each god has different characteristics, so the quests are differnet depending on your god - if player.pgod == GOD_ERU then - god_quest.relic_num = 7 - elseif player.pgod == GOD_MANWE then - god_quest.relic_num = 8 - elseif player.pgod == GOD_TULKAS then - god_quest.relic_num = 9 - elseif player.pgod == GOD_MELKOR then - god_quest.relic_num = 10 - elseif player.pgod == GOD_YAVANNA then - god_quest.relic_num =11 - end + setup_relic_number() -- This var will need resetting god_quest.relic_generated = FALSE -- cgit v1.2.3 From c07642d436b48aa3687b5e74d6ec68997ed3cd99 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 8 Apr 2012 23:44:37 +0200 Subject: Lua: God quests: Move HOOK_LEVEL_END_GEN code to C --- lib/mods/theme/scpt/god.lua | 35 +-------------------- lib/scpt/god.lua | 35 +-------------------- src/plots.h | 1 + src/q_god.c | 75 +++++++++++++++++++++++++++++++++++++++++++++ src/quest.pkg | 1 + 5 files changed, 79 insertions(+), 68 deletions(-) diff --git a/lib/mods/theme/scpt/god.lua b/lib/mods/theme/scpt/god.lua index be8c09a5..d5097e85 100644 --- a/lib/mods/theme/scpt/god.lua +++ b/lib/mods/theme/scpt/god.lua @@ -153,40 +153,7 @@ add_quest end end, [HOOK_LEVEL_END_GEN] = function() - local chance - - -- Check for dungeon - if (current_dungeon_idx ~= god_quest.DUNGEON_GOD) or (quest(GOD_QUEST).status == QUEST_STATUS_UNTAKEN) then - return - -- if the relic has been created at this point, then it was created on the *PREVIOUS* call of HOOK_LEVEL_END_GEN, and - -- therefore the player has caused another level generation in the temple and hence failed the quest. - elseif (god_quest.relic_generated == TRUE) and quest(GOD_QUEST).status ~= QUEST_STATUS_FAILED then - - -- fail the quest, don't give another one, don't give this message again - quest(GOD_QUEST).status = QUEST_STATUS_FAILED - -- God issues instructions - cmsg_print(TERM_L_BLUE, "The voice of "..deity(player.pgod).name.." booms in your head:") - - cmsg_print(TERM_YELLOW, "'Thou art a fool!") - cmsg_print(TERM_YELLOW, "I told thee to look carefully for the relic. It appears thou hast missed the") - cmsg_print(TERM_YELLOW, "opportunity to claim it in my name, as I sense that those monsters who ") - cmsg_print(TERM_YELLOW, "have overrun my temple have destroyed it themselves.") - cmsg_print(TERM_YELLOW, "I shall not ask thee to do such a thing again, as thou hast failed me in this") - cmsg_print(TERM_YELLOW, "simple task!'") - else - -- Force relic generation on 5th attempt if others have been unsuccessful. - if (god_quest.relic_gen_tries == 4) and (god_quest.relic_generated == FALSE) then - quest_god_generate_relic() - else - -- 1/5 chance of generation - chance = randint(5) - if (chance == 5) then - quest_god_generate_relic() - else - god_quest.relic_gen_tries = god_quest.relic_gen_tries + 1 - end - end - end + quest_god_level_end_gen_hook() end, [HOOK_ENTER_DUNGEON] = function(d_idx) -- call the function to set the dungeon variables (dependant on pgod) the first time we enter the dungeon diff --git a/lib/scpt/god.lua b/lib/scpt/god.lua index 938ef802..d3908a43 100644 --- a/lib/scpt/god.lua +++ b/lib/scpt/god.lua @@ -145,40 +145,7 @@ add_quest end end, [HOOK_LEVEL_END_GEN] = function() - local chance - - -- Check for dungeon - if (current_dungeon_idx ~= god_quest.DUNGEON_GOD) or (quest(GOD_QUEST).status == QUEST_STATUS_UNTAKEN) then - return - -- if the relic has been created at this point, then it was created on the *PREVIOUS* call of HOOK_LEVEL_END_GEN, and - -- therefore the player has caused another level generation in the temple and hence failed the quest. - elseif (god_quest.relic_generated == TRUE) and quest(GOD_QUEST).status ~= QUEST_STATUS_FAILED then - - -- fail the quest, don't give another one, don't give this message again - quest(GOD_QUEST).status = QUEST_STATUS_FAILED - -- God issues instructions - cmsg_print(TERM_L_BLUE, "The voice of "..deity(player.pgod).name.." booms in your head:") - - cmsg_print(TERM_YELLOW, "'Thou art a fool!") - cmsg_print(TERM_YELLOW, "I told thee to look carefully for the relic. It appears thou hast missed the") - cmsg_print(TERM_YELLOW, "opportunity to claim it in my name, as I sense that those monsters who ") - cmsg_print(TERM_YELLOW, "have overrun my temple have destroyed it themselves.") - cmsg_print(TERM_YELLOW, "I shall not ask thee to do such a thing again, as thou hast failed me in this") - cmsg_print(TERM_YELLOW, "simple task!'") - else - -- Force relic generation on 5th attempt if others have been unsuccessful. - if (god_quest.relic_gen_tries == 4) and (god_quest.relic_generated == FALSE) then - quest_god_generate_relic() - else - -- 1/5 chance of generation - chance = randint(5) - if (chance == 5) then - quest_god_generate_relic() - else - god_quest.relic_gen_tries = god_quest.relic_gen_tries + 1 - end - end - end + quest_god_level_end_gen_hook() end, [HOOK_ENTER_DUNGEON] = function(d_idx) -- call the function to set the dungeon variables (dependant on pgod) the first time we enter the dungeon diff --git a/src/plots.h b/src/plots.h index 9ec9bf80..47f5e30f 100644 --- a/src/plots.h +++ b/src/plots.h @@ -75,3 +75,4 @@ extern void quest_god_set_god_dungeon_attributes_aule(); extern void quest_god_set_god_dungeon_attributes_varda(); extern void quest_god_set_god_dungeon_attributes_ulmo(); extern void quest_god_set_god_dungeon_attributes_mandos(); +extern void quest_god_level_end_gen_hook(); diff --git a/src/q_god.c b/src/q_god.c index 9b302011..3c0f38a5 100644 --- a/src/q_god.c +++ b/src/q_god.c @@ -34,6 +34,16 @@ static int get_relic_num() return get_lua_int("god_quest.relic_num"); } +static int get_status() +{ + return exec_lua("return quest(GOD_QUEST).status"); +} + +static void set_status(int new_status) +{ + exec_lua(format("quest(GOD_QUEST).status = %d", new_status)); +} + static void set_relic_generated(bool_ v) { switch (v) @@ -50,11 +60,21 @@ static void set_relic_generated(bool_ v) } } +static bool_ get_relic_generated() +{ + return get_lua_int("god_quest.relic_generated"); +} + static void set_relic_gen_tries(int v) { exec_lua(format("god_quest.relic_gen_tries = %d", v)); } +static int get_relic_gen_tries() +{ + return get_lua_int("god_quest.relic_gen_tries"); +} + void quest_god_place_rand_dung() { int x = -1, y = -1, tries; @@ -621,3 +641,58 @@ void quest_god_set_god_dungeon_attributes_mandos() d_info[DUNGEON_GOD].rules[0].r_char[4] = '\0'; d_info[DUNGEON_GOD].rules[0].mflags3 = RF3_UNDEAD | RF3_EVIL; } + +void quest_god_level_end_gen_hook() +{ + /* Check for dungeon */ + if ((dungeon_type != DUNGEON_GOD) || + (get_status() == QUEST_STATUS_UNTAKEN)) + { + return; + } + + /* if the relic has been created at this point, then it was + created on the *PREVIOUS* call of HOOK_LEVEL_END_GEN, and + therefore the player has caused another level generation in + the temple and hence failed the quest.*/ + + else if ((get_relic_generated() == TRUE) && + (get_status() != QUEST_STATUS_FAILED)) + { + /* fail the quest, don't give another one, don't give + * this message again */ + set_status(QUEST_STATUS_FAILED); + + /* God issues instructions */ + cmsg_format(TERM_L_BLUE, "The voice of %s booms in your head:", deity_info[p_ptr->pgod].name); + + cmsg_print(TERM_YELLOW, "'Thou art a fool!"); + cmsg_print(TERM_YELLOW, "I told thee to look carefully for the relic. It appears thou hast missed the"); + cmsg_print(TERM_YELLOW, "opportunity to claim it in my name, as I sense that those monsters who "); + cmsg_print(TERM_YELLOW, "have overrun my temple have destroyed it themselves."); + cmsg_print(TERM_YELLOW, "I shall not ask thee to do such a thing again, as thou hast failed me in this"); + cmsg_print(TERM_YELLOW, "simple task!'"); + } + + /* Force relic generation on 5th attempt if others have been + * unsuccessful. */ + + else if ((get_relic_gen_tries() == 4) && + (get_relic_generated() == FALSE)) + { + quest_god_generate_relic(); + } + + else + { + /* 1/5 chance of generation */ + if (magik(20)) + { + quest_god_generate_relic(); + } + else + { + set_relic_gen_tries(get_relic_gen_tries() + 1); + } + } +} diff --git a/src/quest.pkg b/src/quest.pkg index c2610d9e..3bb707a4 100644 --- a/src/quest.pkg +++ b/src/quest.pkg @@ -174,3 +174,4 @@ extern void quest_god_set_god_dungeon_attributes_aule(); extern void quest_god_set_god_dungeon_attributes_varda(); extern void quest_god_set_god_dungeon_attributes_ulmo(); extern void quest_god_set_god_dungeon_attributes_mandos(); +extern void quest_god_level_end_gen_hook(); -- cgit v1.2.3 From 19a72f1025b0c25b62db56748e0e1f7097227abc Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 8 Apr 2012 23:57:24 +0200 Subject: Lua: God quests: Prepare for moving HOOK_PLAYER_LEVEL code to C --- lib/mods/theme/scpt/god.lua | 10 +++++++--- lib/scpt/god.lua | 10 +++++++--- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/lib/mods/theme/scpt/god.lua b/lib/mods/theme/scpt/god.lua index d5097e85..a7c79924 100644 --- a/lib/mods/theme/scpt/god.lua +++ b/lib/mods/theme/scpt/god.lua @@ -33,6 +33,12 @@ function print_directions(feel_it, pfunc) end end +function msg_directions() + print_directions(TRUE, function (line) + cmsg_print(TERM_YELLOW, line) + end) +end + -- Set up relic number according to god function setup_relic_number() if player.pgod == GOD_ERU then @@ -141,9 +147,7 @@ add_quest cmsg_print(TERM_YELLOW, "When thy task is done, thou art to lift it in the air and call upon my name.") cmsg_print(TERM_YELLOW, "I shall then come to reclaim what is mine!") - print_directions(TRUE, function (line) - cmsg_print(TERM_YELLOW, line) - end) + msg_directions() -- Prepare depth of dungeon. If this was generated in set_god_dungeon_attributes(), -- then we'd have trouble if someone levelled up in the dungeon! diff --git a/lib/scpt/god.lua b/lib/scpt/god.lua index d3908a43..53363d65 100644 --- a/lib/scpt/god.lua +++ b/lib/scpt/god.lua @@ -33,6 +33,12 @@ function print_directions(feel_it, pfunc) end end +function msg_directions() + print_directions(TRUE, function (line) + cmsg_print(TERM_YELLOW, line) + end) +end + -- Set up relic number according to god function setup_relic_number() if player.pgod == GOD_ERU then @@ -133,9 +139,7 @@ add_quest cmsg_print(TERM_YELLOW, "When thy task is done, thou art to lift it in the air and call upon my name.") cmsg_print(TERM_YELLOW, "I shall then come to reclaim what is mine!") - print_directions(TRUE, function (line) - cmsg_print(TERM_YELLOW, line) - end) + msg_directions() -- Prepare depth of dungeon. If this was generated in set_god_dungeon_attributes(), -- then we'd have trouble if someone levelled up in the dungeon! -- cgit v1.2.3 From 7fc396e625a96e48419b60359f721ad082d7f475 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 9 Apr 2012 00:07:46 +0200 Subject: Lua: God quests: Move HOOK_PLAYER_LEVEL code to C --- lib/mods/theme/scpt/god.lua | 48 +---------------- lib/scpt/god.lua | 48 +---------------- src/plots.h | 1 + src/q_god.c | 128 ++++++++++++++++++++++++++++++++++++++++++++ src/quest.pkg | 1 + 5 files changed, 132 insertions(+), 94 deletions(-) diff --git a/lib/mods/theme/scpt/god.lua b/lib/mods/theme/scpt/god.lua index a7c79924..061b23e6 100644 --- a/lib/mods/theme/scpt/god.lua +++ b/lib/mods/theme/scpt/god.lua @@ -108,53 +108,7 @@ add_quest god_quest.relic_generated = FALSE end, [HOOK_PLAYER_LEVEL] = function(gained) - if gained > 0 then - -- roll for chance of quest - local give_god_quest = magik(god_quest.CHANCE_OF_GOD_QUEST) - - -- check player is worshipping a god, not already on a god quest. - if (player.astral ~= FALSE) or (player.pgod <= 0) - or (quest(GOD_QUEST).status == QUEST_STATUS_TAKEN) or (quest(GOD_QUEST).status == QUEST_STATUS_FAILED) - or (god_quest.quests_given >= god_quest.MAX_NUM_GOD_QUESTS) or (give_god_quest == FALSE) - or ((current_dungeon_idx == god_quest.DUNGEON_GOD) and (dun_level > 0)) or (player.lev <= god_quest.dun_minplev) then - -- Don't let a player get quests with trickery - if player.lev > god_quest.dun_minplev then - god_quest.dun_minplev = player.lev - end - return - else - -- each god has different characteristics, so the quests are differnet depending on your god - setup_relic_number() - - -- This var will need resetting - god_quest.relic_generated = FALSE - quest(GOD_QUEST).status = QUEST_STATUS_TAKEN - god_quest.quests_given = god_quest.quests_given + 1 - - -- actually place the dungeon in a random place - quest_god_place_rand_dung() - - -- store the variables of the coords where the player was given the quest - god_quest.player_y, god_quest.player_x = player.get_wild_coord() - - -- God issues instructions - cmsg_print(TERM_L_BLUE, "The voice of "..deity(player.pgod).name.." booms in your head:") - - cmsg_print(TERM_YELLOW, "'I have a task for thee.") - cmsg_print(TERM_YELLOW, "Centuries ago an ancient relic of mine was broken apart.") - cmsg_print(TERM_YELLOW, "The pieces of it have been lost in fallen temples.") - cmsg_print(TERM_YELLOW, "Thou art to find my lost temple and retrieve a piece of the relic.") - cmsg_print(TERM_YELLOW, "When thy task is done, thou art to lift it in the air and call upon my name.") - cmsg_print(TERM_YELLOW, "I shall then come to reclaim what is mine!") - - msg_directions() - - -- Prepare depth of dungeon. If this was generated in set_god_dungeon_attributes(), - -- then we'd have trouble if someone levelled up in the dungeon! - god_quest.dun_mindepth = player.lev*2/3 - god_quest.dun_maxdepth = god_quest.dun_mindepth + 4 - end - end + quest_god_player_level_hook(gained) end, [HOOK_LEVEL_END_GEN] = function() quest_god_level_end_gen_hook() diff --git a/lib/scpt/god.lua b/lib/scpt/god.lua index 53363d65..3ccd14a0 100644 --- a/lib/scpt/god.lua +++ b/lib/scpt/god.lua @@ -100,53 +100,7 @@ add_quest god_quest.relic_generated = FALSE end, [HOOK_PLAYER_LEVEL] = function(gained) - if gained > 0 then - -- roll for chance of quest - local give_god_quest = magik(god_quest.CHANCE_OF_GOD_QUEST) - - -- check player is worshipping a god, not already on a god quest. - if (player.astral ~= FALSE) or (player.pgod <= 0) - or (quest(GOD_QUEST).status == QUEST_STATUS_TAKEN) or (quest(GOD_QUEST).status == QUEST_STATUS_FAILED) - or (god_quest.quests_given >= god_quest.MAX_NUM_GOD_QUESTS) or (give_god_quest == FALSE) - or ((current_dungeon_idx == god_quest.DUNGEON_GOD) and (dun_level > 0)) or (player.lev <= god_quest.dun_minplev) then - -- Don't let a player get quests with trickery - if player.lev > god_quest.dun_minplev then - god_quest.dun_minplev = player.lev - end - return - else - -- each god has different characteristics, so the quests are differnet depending on your god - setup_relic_number() - - -- This var will need resetting - god_quest.relic_generated = FALSE - quest(GOD_QUEST).status = QUEST_STATUS_TAKEN - god_quest.quests_given = god_quest.quests_given + 1 - - -- actually place the dungeon in a random place - quest_god_place_rand_dung() - - -- store the variables of the coords where the player was given the quest - god_quest.player_y, god_quest.player_x = player.get_wild_coord() - - -- God issues instructions - cmsg_print(TERM_L_BLUE, "The voice of "..deity(player.pgod).name.." booms in your head:") - - cmsg_print(TERM_YELLOW, "'I have a task for thee.") - cmsg_print(TERM_YELLOW, "Centuries ago an ancient relic of mine was broken apart.") - cmsg_print(TERM_YELLOW, "The pieces of it have been lost in fallen temples.") - cmsg_print(TERM_YELLOW, "Thou art to find my lost temple and retrieve a piece of the relic.") - cmsg_print(TERM_YELLOW, "When thy task is done, thou art to lift it in the air and call upon my name.") - cmsg_print(TERM_YELLOW, "I shall then come to reclaim what is mine!") - - msg_directions() - - -- Prepare depth of dungeon. If this was generated in set_god_dungeon_attributes(), - -- then we'd have trouble if someone levelled up in the dungeon! - god_quest.dun_mindepth = player.lev*2/3 - god_quest.dun_maxdepth = god_quest.dun_mindepth + 4 - end - end + quest_god_player_level_hook(gained) end, [HOOK_LEVEL_END_GEN] = function() quest_god_level_end_gen_hook() diff --git a/src/plots.h b/src/plots.h index 47f5e30f..01e6db0b 100644 --- a/src/plots.h +++ b/src/plots.h @@ -76,3 +76,4 @@ extern void quest_god_set_god_dungeon_attributes_varda(); extern void quest_god_set_god_dungeon_attributes_ulmo(); extern void quest_god_set_god_dungeon_attributes_mandos(); extern void quest_god_level_end_gen_hook(); +extern void quest_god_player_level_hook(int gained); diff --git a/src/q_god.c b/src/q_god.c index 3c0f38a5..020b8ca1 100644 --- a/src/q_god.c +++ b/src/q_god.c @@ -3,12 +3,18 @@ /* d_idx of the god_quest (Lost Temple) dungeon */ #define DUNGEON_GOD 30 +#define CHANCE_OF_GOD_QUEST 21 static int get_quests_given() { return get_lua_int("god_quest.quests_given"); } +static void set_quests_given(int i) +{ + exec_lua(format("god_quest.quests_given = %d", i)); +} + static int get_dung_y() { return get_lua_int("god_quest.dung_y"); @@ -44,6 +50,11 @@ static void set_status(int new_status) exec_lua(format("quest(GOD_QUEST).status = %d", new_status)); } +static int MAX_NUM_GOD_QUESTS() +{ + return get_lua_int("god_quest.MAX_NUM_GOD_QUESTS"); +} + static void set_relic_generated(bool_ v) { switch (v) @@ -75,6 +86,52 @@ static int get_relic_gen_tries() return get_lua_int("god_quest.relic_gen_tries"); } +static void set_player_y(int y) +{ + exec_lua(format("god_quest.player_y = %d", y)); +} + +static void set_player_x(int x) +{ + exec_lua(format("god_quest.player_x = %d", x)); +} + +static int get_dun_mindepth() +{ + return get_lua_int("god_quest.dun_mindepth"); +} + +static void set_dun_mindepth(int d) +{ + exec_lua(format("god_quest.dun_mindepth = %d", d)); +} + +static void set_dun_maxdepth(int d) +{ + exec_lua(format("god_quest.dun_maxdepth = %d", d)); + +} + +static void set_dun_minplev(int p) +{ + exec_lua(format("god_quest.dun_minplev = %d", p)); +} + +static int get_dun_minplev() +{ + return get_lua_int("god_quest.dun_minplev"); +} + +static void setup_relic_number() +{ + exec_lua("setup_relic_number()"); +} + +static void msg_directions() +{ + exec_lua("msg_directions()"); +} + void quest_god_place_rand_dung() { int x = -1, y = -1, tries; @@ -696,3 +753,74 @@ void quest_god_level_end_gen_hook() } } } + +void quest_god_player_level_hook(int gained) +{ + if (gained <= 0) + { + return; + } + + /* check player is worshipping a god, not already on a god quest. */ + if ((p_ptr->astral) || + (p_ptr->pgod <= 0) || + (get_status() == QUEST_STATUS_TAKEN) || + (get_status() == QUEST_STATUS_FAILED) || + (get_quests_given() >= MAX_NUM_GOD_QUESTS()) || + (magik(CHANCE_OF_GOD_QUEST) == FALSE) || + ((dungeon_type == DUNGEON_GOD) && + (dun_level > 0)) || + (p_ptr->lev <= get_dun_minplev())) + { + /* Don't let a player get quests with trickery */ + if (p_ptr->lev > get_dun_minplev()) + { + set_dun_minplev(p_ptr->lev); + } + return; + } + else + { + /* each god has different characteristics, so the quests are differnet depending on your god */ + setup_relic_number(); + + /* This var will need resetting */ + set_relic_generated(FALSE); + set_status(QUEST_STATUS_TAKEN); + set_quests_given(get_quests_given() + 1); + + /* actually place the dungeon in a random place */ + quest_god_place_rand_dung(); + + /* store the variables of the coords where the player was given the quest */ + if (p_ptr->wild_mode) + { + set_player_x(p_ptr->px); + set_player_y(p_ptr->py); + } + else + { + set_player_x(p_ptr->wilderness_x); + set_player_y(p_ptr->wilderness_y); + } + + /* God issues instructions */ + cmsg_format(TERM_L_BLUE, "The voice of %s booms in your head:", deity_info[p_ptr->pgod].name); + + cmsg_print(TERM_YELLOW, "'I have a task for thee."); + cmsg_print(TERM_YELLOW, "Centuries ago an ancient relic of mine was broken apart."); + cmsg_print(TERM_YELLOW, "The pieces of it have been lost in fallen temples."); + cmsg_print(TERM_YELLOW, "Thou art to find my lost temple and retrieve a piece of the relic."); + cmsg_print(TERM_YELLOW, "When thy task is done, thou art to lift it in the air and call upon my name."); + cmsg_print(TERM_YELLOW, "I shall then come to reclaim what is mine!"); + + msg_directions(); + + /* Prepare depth of dungeon. If this was + * generated in set_god_dungeon_attributes(), + * then we'd have trouble if someone levelled + * up in the dungeon! */ + set_dun_mindepth(p_ptr->lev*2/3); + set_dun_maxdepth(get_dun_mindepth() + 4); + } +} diff --git a/src/quest.pkg b/src/quest.pkg index 3bb707a4..91f0e780 100644 --- a/src/quest.pkg +++ b/src/quest.pkg @@ -175,3 +175,4 @@ extern void quest_god_set_god_dungeon_attributes_varda(); extern void quest_god_set_god_dungeon_attributes_ulmo(); extern void quest_god_set_god_dungeon_attributes_mandos(); extern void quest_god_level_end_gen_hook(); +extern void quest_god_player_level_hook(int gained); -- cgit v1.2.3 From d497a80b25bb612d63daa70582fca5eeaa708fec Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 9 Apr 2012 00:47:44 +0200 Subject: Lua: God quests: Move HOOK_GET code to C --- lib/mods/theme/scpt/god.lua | 41 +---------------------------- lib/scpt/god.lua | 41 +---------------------------- src/plots.h | 1 + src/q_god.c | 64 +++++++++++++++++++++++++++++++++++++++++++++ src/quest.pkg | 1 + 5 files changed, 68 insertions(+), 80 deletions(-) diff --git a/lib/mods/theme/scpt/god.lua b/lib/mods/theme/scpt/god.lua index 061b23e6..7a03f49f 100644 --- a/lib/mods/theme/scpt/god.lua +++ b/lib/mods/theme/scpt/god.lua @@ -138,46 +138,7 @@ add_quest end end, [HOOK_GET] = function(o_ptr, item) - -- Is it the relic, and check to make sure the relic hasn't already been identified - if (quest(GOD_QUEST).status == QUEST_STATUS_TAKEN) and (o_ptr.tval == TV_JUNK) and (o_ptr.sval == god_quest.relic_num) - and (o_ptr.pval ~= TRUE) and (god_quest.relics_found < god_quest.quests_given) then - - -- more God talky-talky - cmsg_print(TERM_L_BLUE, deity(player.pgod).name.." speaks to you:") - - -- Is it the last piece of the relic? - if (god_quest.quests_given == god_quest.MAX_NUM_GOD_QUESTS) then - cmsg_print(TERM_YELLOW, "'At last! Thou hast found all of the relic pieces.") - - -- reward player by increasing prayer skill - cmsg_print(TERM_YELLOW, "Thou hast done exceptionally well! I shall increase thy prayer skill even more!'") - skill(SKILL_PRAY).value = skill(SKILL_PRAY).value + (10 * (skill(SKILL_PRAY).mod)) - - -- Take the relic piece - floor_item_increase(item, -1) - floor_item_optimize(item) - else - cmsg_print(TERM_YELLOW, "'Well done! Thou hast found part of the relic.") - cmsg_print(TERM_YELLOW, "I shall surely ask thee to find more of it later!") - cmsg_print(TERM_YELLOW, "I will take it from thee for now'") - - -- Take the relic piece - floor_item_increase(item, -1) - floor_item_optimize(item) - - -- reward player by increasing prayer skill - cmsg_print(TERM_YELLOW, "'As a reward, I shall teach thee how to pray better'") - skill(SKILL_PRAY).value = skill(SKILL_PRAY).value + (5 * (skill(SKILL_PRAY).mod)) - end - - -- relic piece has been identified - o_ptr.pval = TRUE - god_quest.relics_found = god_quest.relics_found + 1 - - -- Make sure quests can be given again if neccesary - quest(GOD_QUEST).status = QUEST_STATUS_UNTAKEN - return TRUE - end + return quest_god_get_hook(item) end, [HOOK_CHAR_DUMP] = function() diff --git a/lib/scpt/god.lua b/lib/scpt/god.lua index 3ccd14a0..9e1f2039 100644 --- a/lib/scpt/god.lua +++ b/lib/scpt/god.lua @@ -130,46 +130,7 @@ add_quest end end, [HOOK_GET] = function(o_ptr, item) - -- Is it the relic, and check to make sure the relic hasn't already been identified - if (quest(GOD_QUEST).status == QUEST_STATUS_TAKEN) and (o_ptr.tval == TV_JUNK) and (o_ptr.sval == god_quest.relic_num) - and (o_ptr.pval ~= TRUE) and (god_quest.relics_found < god_quest.quests_given) then - - -- more God talky-talky - cmsg_print(TERM_L_BLUE, deity(player.pgod).name.." speaks to you:") - - -- Is it the last piece of the relic? - if (god_quest.quests_given == god_quest.MAX_NUM_GOD_QUESTS) then - cmsg_print(TERM_YELLOW, "'At last! Thou hast found all of the relic pieces.") - - -- reward player by increasing prayer skill - cmsg_print(TERM_YELLOW, "Thou hast done exceptionally well! I shall increase thy prayer skill even more!'") - skill(SKILL_PRAY).value = skill(SKILL_PRAY).value + (10 * (skill(SKILL_PRAY).mod)) - - -- Take the relic piece - floor_item_increase(item, -1) - floor_item_optimize(item) - else - cmsg_print(TERM_YELLOW, "'Well done! Thou hast found part of the relic.") - cmsg_print(TERM_YELLOW, "I shall surely ask thee to find more of it later!") - cmsg_print(TERM_YELLOW, "I will take it from thee for now'") - - -- Take the relic piece - floor_item_increase(item, -1) - floor_item_optimize(item) - - -- reward player by increasing prayer skill - cmsg_print(TERM_YELLOW, "'As a reward, I shall teach thee how to pray better'") - skill(SKILL_PRAY).value = skill(SKILL_PRAY).value + (5 * (skill(SKILL_PRAY).mod)) - end - - -- relic piece has been identified - o_ptr.pval = TRUE - god_quest.relics_found = god_quest.relics_found + 1 - - -- Make sure quests can be given again if neccesary - quest(GOD_QUEST).status = QUEST_STATUS_UNTAKEN - return TRUE - end + return quest_god_get_hook(item) end, [HOOK_CHAR_DUMP] = function() diff --git a/src/plots.h b/src/plots.h index 01e6db0b..27cf25f0 100644 --- a/src/plots.h +++ b/src/plots.h @@ -77,3 +77,4 @@ extern void quest_god_set_god_dungeon_attributes_ulmo(); extern void quest_god_set_god_dungeon_attributes_mandos(); extern void quest_god_level_end_gen_hook(); extern void quest_god_player_level_hook(int gained); +extern bool_ quest_god_get_hook(int o_idx); diff --git a/src/q_god.c b/src/q_god.c index 020b8ca1..bc2920a9 100644 --- a/src/q_god.c +++ b/src/q_god.c @@ -122,6 +122,16 @@ static int get_dun_minplev() return get_lua_int("god_quest.dun_minplev"); } +static int get_relics_found() +{ + return get_lua_int("god_quest.relics_found"); +} + +static void set_relics_found(int v) +{ + exec_lua(format("god_quest.relics_found = %d", v)); +} + static void setup_relic_number() { exec_lua("setup_relic_number()"); @@ -824,3 +834,57 @@ void quest_god_player_level_hook(int gained) set_dun_maxdepth(get_dun_mindepth() + 4); } } + +bool_ quest_god_get_hook(int item) +{ + object_type *o_ptr = NULL; + + item = -item; /* Workaround */ + o_ptr = get_object(item); + + /* -- Is it the relic, and check to make sure the relic hasn't already been identified */ + if ((get_status() == QUEST_STATUS_TAKEN) && + (o_ptr->tval == TV_JUNK) && + (o_ptr->sval == get_relic_num()) && + (o_ptr->pval != TRUE) && + (get_relics_found() < get_quests_given())) + { + cmsg_format(TERM_L_BLUE, "%s speaks to you:", deity_info[p_ptr->pgod].name); + + /* Is it the last piece of the relic? */ + if (get_quests_given() == MAX_NUM_GOD_QUESTS()) + { + cmsg_print(TERM_YELLOW, "'At last! Thou hast found all of the relic pieces."); + + /* reward player by increasing prayer skill */ + cmsg_print(TERM_YELLOW, "Thou hast done exceptionally well! I shall increase thy prayer skill even more!'"); + s_info[SKILL_PRAY].value += (10 * s_info[SKILL_PRAY].mod); + } + else + { + cmsg_print(TERM_YELLOW, "'Well done! Thou hast found part of the relic."); + cmsg_print(TERM_YELLOW, "I shall surely ask thee to find more of it later!"); + cmsg_print(TERM_YELLOW, "I will take it from thee for now'"); + + /* reward player by increasing prayer skill */ + cmsg_print(TERM_YELLOW, "'As a reward, I shall teach thee how to pray better'"); + s_info[SKILL_PRAY].value += (5 * s_info[SKILL_PRAY].mod); + } + + /* Take the relic piece */ + inc_stack_size_ex(item, -1, OPTIMIZE, NO_DESCRIBE); + + /* relic piece has been identified */ + o_ptr->pval = TRUE; + set_relics_found(get_relics_found() + 1); + + /* Make sure quests can be given again if neccesary */ + set_status(QUEST_STATUS_UNTAKEN); + + /* Prevent further processing of 'take' action; we've + destroyed the item. */ + return TRUE; + } + + return FALSE; +} diff --git a/src/quest.pkg b/src/quest.pkg index 91f0e780..dc5a91fc 100644 --- a/src/quest.pkg +++ b/src/quest.pkg @@ -176,3 +176,4 @@ extern void quest_god_set_god_dungeon_attributes_ulmo(); extern void quest_god_set_god_dungeon_attributes_mandos(); extern void quest_god_level_end_gen_hook(); extern void quest_god_player_level_hook(int gained); +extern bool quest_god_get_hook(int o_idx); -- cgit v1.2.3 From b89a8b18c480f6c96b5f8ba1f67a29c45ab2007d Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 9 Apr 2012 10:17:39 +0200 Subject: Lua: God quests: Move HOOK_CHAR_DUMP code to C --- lib/mods/theme/scpt/god.lua | 21 +-------------------- lib/scpt/god.lua | 21 +-------------------- src/plots.h | 1 + src/q_god.c | 33 +++++++++++++++++++++++++++++++++ src/quest.pkg | 1 + 5 files changed, 37 insertions(+), 40 deletions(-) diff --git a/lib/mods/theme/scpt/god.lua b/lib/mods/theme/scpt/god.lua index 7a03f49f..d05d5ce1 100644 --- a/lib/mods/theme/scpt/god.lua +++ b/lib/mods/theme/scpt/god.lua @@ -141,26 +141,7 @@ add_quest return quest_god_get_hook(item) end, [HOOK_CHAR_DUMP] = function() - - if (god_quest.quests_given > 0) then - - local relics = god_quest.relics_found - local append_text = "" - if (god_quest.relics_found == god_quest.MAX_NUM_GOD_QUESTS) then - relics = "all" - append_text = " and pleased your god" - else - if (god_quest.relics_found == 0) then - relics = "none" - end - if (quest(GOD_QUEST).status == QUEST_STATUS_FAILED) then - append_text = " and failed in your quest" - end - end - - print_hook("\n You found "..(relics).." of the relic pieces"..(append_text)..".") - - end + return quest_god_char_dump() end, }, } diff --git a/lib/scpt/god.lua b/lib/scpt/god.lua index 9e1f2039..e8b4fe74 100644 --- a/lib/scpt/god.lua +++ b/lib/scpt/god.lua @@ -133,26 +133,7 @@ add_quest return quest_god_get_hook(item) end, [HOOK_CHAR_DUMP] = function() - - if (god_quest.quests_given > 0) then - - local relics = god_quest.relics_found - local append_text = "" - if (god_quest.relics_found == god_quest.MAX_NUM_GOD_QUESTS) then - relics = "all" - append_text = " and pleased your god" - else - if (god_quest.relics_found == 0) then - relics = "none" - end - if (quest(GOD_QUEST).status == QUEST_STATUS_FAILED) then - append_text = " and failed in your quest" - end - end - - print_hook("\n You found "..(relics).." of the relic pieces"..(append_text)..".") - - end + return quest_god_char_dump() end, }, } diff --git a/src/plots.h b/src/plots.h index 27cf25f0..4631d3cd 100644 --- a/src/plots.h +++ b/src/plots.h @@ -78,3 +78,4 @@ extern void quest_god_set_god_dungeon_attributes_mandos(); extern void quest_god_level_end_gen_hook(); extern void quest_god_player_level_hook(int gained); extern bool_ quest_god_get_hook(int o_idx); +extern void quest_god_char_dump(); diff --git a/src/q_god.c b/src/q_god.c index bc2920a9..a83deb40 100644 --- a/src/q_god.c +++ b/src/q_god.c @@ -1,6 +1,8 @@ #include "angband.h" #include +#define print_hook(fmt,...) do { fprintf(hook_file, fmt, ##__VA_ARGS__); } while (0) + /* d_idx of the god_quest (Lost Temple) dungeon */ #define DUNGEON_GOD 30 #define CHANCE_OF_GOD_QUEST 21 @@ -888,3 +890,34 @@ bool_ quest_god_get_hook(int item) return FALSE; } + +void quest_god_char_dump() +{ + if (get_quests_given() > 0) + { + int relics = get_relics_found(); + char relics_text[128]; + cptr append_text = ""; + + snprintf(relics_text, sizeof(relics_text), "%d", relics); + + if (relics == MAX_NUM_GOD_QUESTS()) + { + strcpy(relics_text, "all"); + append_text = " and pleased your god"; + } + else + { + if (relics == 0) + { + strcpy(relics_text, "none"); + } + if (get_status() == QUEST_STATUS_FAILED) + { + append_text = " and failed in your quest"; + } + } + + print_hook("\n You found %s of the relic pieces%s.", relics_text, append_text); + } +} diff --git a/src/quest.pkg b/src/quest.pkg index dc5a91fc..fb2f3b84 100644 --- a/src/quest.pkg +++ b/src/quest.pkg @@ -177,3 +177,4 @@ extern void quest_god_set_god_dungeon_attributes_mandos(); extern void quest_god_level_end_gen_hook(); extern void quest_god_player_level_hook(int gained); extern bool quest_god_get_hook(int o_idx); +extern void quest_god_char_dump(); -- cgit v1.2.3 From c81957d766f664bbffc5ec1976a5013f955e0d82 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 9 Apr 2012 10:28:06 +0200 Subject: Lua: God quests: Move dungeon setup "dispatch" to C --- lib/mods/theme/scpt/god.lua | 51 ++----------------------- lib/scpt/god.lua | 43 ++-------------------- src/plots.h | 10 +---- src/q_god.c | 90 ++++++++++++++++++++++++++++++++++++++++----- src/quest.pkg | 10 +---- 5 files changed, 89 insertions(+), 115 deletions(-) diff --git a/lib/mods/theme/scpt/god.lua b/lib/mods/theme/scpt/god.lua index d05d5ce1..54314d60 100644 --- a/lib/mods/theme/scpt/god.lua +++ b/lib/mods/theme/scpt/god.lua @@ -114,28 +114,13 @@ add_quest quest_god_level_end_gen_hook() end, [HOOK_ENTER_DUNGEON] = function(d_idx) - -- call the function to set the dungeon variables (dependant on pgod) the first time we enter the dungeon - if d_idx ~= god_quest.DUNGEON_GOD then - return - else - set_god_dungeon_attributes() - end + quest_god_enter_dungeon_hook(d_idx) end, [HOOK_GEN_LEVEL_BEGIN] = function() - -- call the function to set the dungeon variables (dependant on pgod) when we WoR back into the dungeon - if current_dungeon_idx ~= god_quest.DUNGEON_GOD then - return - else - set_god_dungeon_attributes() - end + quest_god_enter_dungeon_hook(current_dungeon_idx) end, [HOOK_STAIR] = function() - -- call the function to set the dungeon variables (dependant on pgod) every time we go down a level - if current_dungeon_idx ~= god_quest.DUNGEON_GOD then - return - else - set_god_dungeon_attributes() - end + quest_god_enter_dungeon_hook(current_dungeon_idx) end, [HOOK_GET] = function(o_ptr, item) return quest_god_get_hook(item) @@ -146,36 +131,6 @@ add_quest }, } -function set_god_dungeon_attributes() - - -- dungeon properties altered according to which god player is worshipping, - if player.pgod == GOD_ERU then - quest_god_set_god_dungeon_attributes_eru() - elseif player.pgod == GOD_MANWE then - quest_god_set_god_dungeon_attributes_manwe() - elseif player.pgod == GOD_TULKAS then - quest_god_set_god_dungeon_attributes_tulkas() - elseif player.pgod == GOD_MELKOR then - quest_god_set_god_dungeon_attributes_melkor() - elseif player.pgod == GOD_YAVANNA then - quest_god_set_god_dungeon_attributes_yavanna() - elseif player.pgod == GOD_AULE then - quest_god_set_god_dungeon_attributes_aule() - elseif player.pgod == GOD_VARDA then - quest_god_set_god_dungeon_attributes_varda() - elseif player.pgod == GOD_ULMO then - quest_god_set_god_dungeon_attributes_ulmo() - elseif player.pgod == GOD_MANDOS then - quest_god_set_god_dungeon_attributes_mandos() - end - - -- W: All dungeons are 5 levels deep, and created at 2/3 of the player clvl when the quest is given - dungeon(god_quest.DUNGEON_GOD).mindepth = god_quest.dun_mindepth - dungeon(god_quest.DUNGEON_GOD).maxdepth = god_quest.dun_maxdepth - dungeon(god_quest.DUNGEON_GOD).minplev = god_quest.dun_minplev - -end - -- Calling this function returns the direction the dungeon is in from the players position at the time -- the quest was given, and also the direction from angband (if the player is worshipping Melkor) or lothlorien. function get_god_quest_axes() diff --git a/lib/scpt/god.lua b/lib/scpt/god.lua index e8b4fe74..d478bf1e 100644 --- a/lib/scpt/god.lua +++ b/lib/scpt/god.lua @@ -106,28 +106,13 @@ add_quest quest_god_level_end_gen_hook() end, [HOOK_ENTER_DUNGEON] = function(d_idx) - -- call the function to set the dungeon variables (dependant on pgod) the first time we enter the dungeon - if d_idx ~= god_quest.DUNGEON_GOD then - return - else - set_god_dungeon_attributes() - end + quest_god_enter_dungeon_hook(d_idx) end, [HOOK_GEN_LEVEL_BEGIN] = function() - -- call the function to set the dungeon variables (dependant on pgod) when we WoR back into the dungeon - if current_dungeon_idx ~= god_quest.DUNGEON_GOD then - return - else - set_god_dungeon_attributes() - end + quest_god_enter_dungeon_hook(current_dungeon_idx) end, [HOOK_STAIR] = function() - -- call the function to set the dungeon variables (dependant on pgod) every time we go down a level - if current_dungeon_idx ~= god_quest.DUNGEON_GOD then - return - else - set_god_dungeon_attributes() - end + quest_god_enter_dungeon_hook(current_dungeon_idx) end, [HOOK_GET] = function(o_ptr, item) return quest_god_get_hook(item) @@ -138,28 +123,6 @@ add_quest }, } -function set_god_dungeon_attributes() - - -- dungeon properties altered according to which god player is worshipping, - if player.pgod == GOD_ERU then - quest_god_set_god_dungeon_attributes_eru() - elseif player.pgod == GOD_MANWE then - quest_god_set_god_dungeon_attributes_manwe() - elseif player.pgod == GOD_TULKAS then - quest_god_set_god_dungeon_attributes_tulkas() - elseif player.pgod == GOD_MELKOR then - quest_god_set_god_dungeon_attributes_melkor() - elseif player.pgod == GOD_YAVANNA then - quest_god_set_god_dungeon_attributes_yavanna() - end - - -- W: All dungeons are 5 levels deep, and created at 2/3 of the player clvl when the quest is given - dungeon(god_quest.DUNGEON_GOD).mindepth = god_quest.dun_mindepth - dungeon(god_quest.DUNGEON_GOD).maxdepth = god_quest.dun_maxdepth - dungeon(god_quest.DUNGEON_GOD).minplev = god_quest.dun_minplev - -end - -- Calling this function returns the direction the dungeon is in from the players position at the time -- the quest was given, and also the direction from angband (if the player is worshipping Melkor) or lothlorien. function get_god_quest_axes() diff --git a/src/plots.h b/src/plots.h index 4631d3cd..cc13a7b4 100644 --- a/src/plots.h +++ b/src/plots.h @@ -66,16 +66,8 @@ extern bool_ quest_fireproof_describe(FILE *fff); /******* Plot God Quest **************/ extern void quest_god_place_rand_dung(); extern void quest_god_generate_relic(); -extern void quest_god_set_god_dungeon_attributes_eru(); -extern void quest_god_set_god_dungeon_attributes_manwe(); -extern void quest_god_set_god_dungeon_attributes_tulkas(); -extern void quest_god_set_god_dungeon_attributes_melkor(); -extern void quest_god_set_god_dungeon_attributes_yavanna(); -extern void quest_god_set_god_dungeon_attributes_aule(); -extern void quest_god_set_god_dungeon_attributes_varda(); -extern void quest_god_set_god_dungeon_attributes_ulmo(); -extern void quest_god_set_god_dungeon_attributes_mandos(); extern void quest_god_level_end_gen_hook(); extern void quest_god_player_level_hook(int gained); extern bool_ quest_god_get_hook(int o_idx); extern void quest_god_char_dump(); +extern void quest_god_enter_dungeon_hook(int d_idx); diff --git a/src/q_god.c b/src/q_god.c index a83deb40..7c48f128 100644 --- a/src/q_god.c +++ b/src/q_god.c @@ -108,6 +108,12 @@ static void set_dun_mindepth(int d) exec_lua(format("god_quest.dun_mindepth = %d", d)); } +static int get_dun_maxdepth() +{ + return get_lua_int("god_quest.dun_maxdepth"); + +} + static void set_dun_maxdepth(int d) { exec_lua(format("god_quest.dun_maxdepth = %d", d)); @@ -273,7 +279,7 @@ void quest_god_generate_relic() set_relic_gen_tries(0); } -void quest_god_set_god_dungeon_attributes_eru() +static void quest_god_set_god_dungeon_attributes_eru() { /* The Eru temple is based on Meneltarma. */ @@ -329,7 +335,7 @@ void quest_god_set_god_dungeon_attributes_eru() d_info[DUNGEON_GOD].rules[1].mflags7 = RF7_CAN_FLY; } -void quest_god_set_god_dungeon_attributes_manwe() +static void quest_god_set_god_dungeon_attributes_manwe() { /* Manwe's lost temple is high in the clouds */ @@ -389,7 +395,7 @@ void quest_god_set_god_dungeon_attributes_manwe() d_info[DUNGEON_GOD].rules[4].mflags7 = RF7_CAN_FLY; } -void quest_god_set_god_dungeon_attributes_tulkas() +static void quest_god_set_god_dungeon_attributes_tulkas() { /* Tulkas dungeon is quite normal, possibly a bit boring to be * honest. Maybe I should add something radical to it. 'The @@ -432,7 +438,7 @@ void quest_god_set_god_dungeon_attributes_tulkas() d_info[DUNGEON_GOD].rules[0].mflags3 = RF3_DEMON | RF3_EVIL; } -void quest_god_set_god_dungeon_attributes_melkor() +static void quest_god_set_god_dungeon_attributes_melkor() { /* Melkors dungeon will be dark, fiery and stuff */ @@ -481,7 +487,7 @@ void quest_god_set_god_dungeon_attributes_melkor() d_info[DUNGEON_GOD].rules[1].mflags3 = RF3_GOOD; } -void quest_god_set_god_dungeon_attributes_yavanna() +static void quest_god_set_god_dungeon_attributes_yavanna() { /* Yavannas dungeon will be very natural, tress and stuff. */ @@ -529,7 +535,7 @@ void quest_god_set_god_dungeon_attributes_yavanna() RF3_DEMON | RF3_UNDEAD | RF3_NONLIVING; } -void quest_god_set_god_dungeon_attributes_aule() +static void quest_god_set_god_dungeon_attributes_aule() { d_info[DUNGEON_GOD].min_m_alloc_level = 24; d_info[DUNGEON_GOD].max_m_alloc_chance = 80; @@ -569,7 +575,7 @@ void quest_god_set_god_dungeon_attributes_aule() d_info[DUNGEON_GOD].rules[0].percent = 80; } -void quest_god_set_god_dungeon_attributes_varda() +static void quest_god_set_god_dungeon_attributes_varda() { /* Varda lives with Manwe, so high in the clouds */ @@ -626,7 +632,7 @@ void quest_god_set_god_dungeon_attributes_varda() d_info[DUNGEON_GOD].rules[4].mflags7 = RF7_CAN_FLY; } -void quest_god_set_god_dungeon_attributes_ulmo() +static void quest_god_set_god_dungeon_attributes_ulmo() { /* Ulmo dungeon is basically Tulkas, except with acquatic creatures. */ @@ -669,7 +675,7 @@ void quest_god_set_god_dungeon_attributes_ulmo() d_info[DUNGEON_GOD].rules[2].mflags3 = RF3_RES_WATE; } -void quest_god_set_god_dungeon_attributes_mandos() +static void quest_god_set_god_dungeon_attributes_mandos() { /* Mandos dungeon is basically Tulkas, except with undead. */ @@ -921,3 +927,69 @@ void quest_god_char_dump() print_hook("\n You found %s of the relic pieces%s.", relics_text, append_text); } } + +static void set_god_dungeon_attributes() +{ + /* dungeon properties altered according to which god player is worshipping, */ + if (p_ptr->pgod == GOD_ERU) + { + quest_god_set_god_dungeon_attributes_eru(); + } + else if (p_ptr->pgod == GOD_MANWE) + { + quest_god_set_god_dungeon_attributes_manwe(); + } + else if (p_ptr->pgod == GOD_TULKAS) + { + quest_god_set_god_dungeon_attributes_tulkas(); + } + else if (p_ptr->pgod == GOD_MELKOR) + { + quest_god_set_god_dungeon_attributes_melkor(); + } + else if (p_ptr->pgod == GOD_YAVANNA) + { + quest_god_set_god_dungeon_attributes_yavanna(); + } + else if (p_ptr->pgod == get_god_AULE()) + { + quest_god_set_god_dungeon_attributes_aule(); + } + else if (p_ptr->pgod == get_god_VARDA()) + { + quest_god_set_god_dungeon_attributes_varda(); + } + else if (p_ptr->pgod == get_god_ULMO()) + { + quest_god_set_god_dungeon_attributes_ulmo(); + } + else if (p_ptr->pgod == get_god_MANDOS()) + { + quest_god_set_god_dungeon_attributes_mandos(); + } + else + { + assert(FALSE); /* Uh, oh! */ + } + + /* W: All dungeons are 5 levels deep, and created at 2/3 of + * the player clvl when the quest is given */ + { + dungeon_info_type *d_ptr = &d_info[DUNGEON_GOD]; + d_ptr->mindepth = get_dun_mindepth(); + d_ptr->maxdepth = get_dun_maxdepth(); + d_ptr->min_plev = get_dun_minplev(); + } +} + +void quest_god_enter_dungeon_hook(int d_idx) +{ + /* call the function to set the dungeon variables (dependant + * on pgod) the first time we enter the dungeon */ + if (d_idx != DUNGEON_GOD) + { + return; + } + + set_god_dungeon_attributes(); +} diff --git a/src/quest.pkg b/src/quest.pkg index fb2f3b84..dca1ca4c 100644 --- a/src/quest.pkg +++ b/src/quest.pkg @@ -165,16 +165,8 @@ extern void desc_quest @ quest_desc(int q_idx, int d, char *desc); */ extern void quest_god_place_rand_dung(); extern void quest_god_generate_relic(); -extern void quest_god_set_god_dungeon_attributes_eru(); -extern void quest_god_set_god_dungeon_attributes_manwe(); -extern void quest_god_set_god_dungeon_attributes_tulkas(); -extern void quest_god_set_god_dungeon_attributes_melkor(); -extern void quest_god_set_god_dungeon_attributes_yavanna(); -extern void quest_god_set_god_dungeon_attributes_aule(); -extern void quest_god_set_god_dungeon_attributes_varda(); -extern void quest_god_set_god_dungeon_attributes_ulmo(); -extern void quest_god_set_god_dungeon_attributes_mandos(); extern void quest_god_level_end_gen_hook(); extern void quest_god_player_level_hook(int gained); extern bool quest_god_get_hook(int o_idx); extern void quest_god_char_dump(); +extern void quest_god_enter_dungeon_hook(int d_idx); -- cgit v1.2.3 From 4d4de63ce360e1b4fe6248b6e18ebd48f618d504 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 9 Apr 2012 11:16:40 +0200 Subject: Lua: Clean up handling of Theme GOD_* variables --- src/externs.h | 8 ++++---- src/lua_bind.c | 32 -------------------------------- src/player.pkg | 5 +++++ src/q_god.c | 8 ++++---- src/spells1.c | 4 ++-- src/variable.c | 4 ++++ src/xtra1.c | 6 +++--- 7 files changed, 22 insertions(+), 45 deletions(-) diff --git a/src/externs.h b/src/externs.h index 2da4f38d..774be450 100644 --- a/src/externs.h +++ b/src/externs.h @@ -598,6 +598,10 @@ extern s32b DUNGEON_ASTRAL_WILD_X; extern s32b DUNGEON_ASTRAL_WILD_Y; extern deity_type *deity_info; extern s32b max_gods; +extern s32b GOD_AULE; +extern s32b GOD_VARDA; +extern s32b GOD_ULMO; +extern s32b GOD_MANDOS; extern timer_type *gl_timers; extern s16b tim_precognition; extern const char *get_version_string(); @@ -1800,10 +1804,6 @@ extern void desc_quest(int q_idx, int d, char *desc); extern s16b add_new_gods(char *name); extern void desc_god(int g_idx, int d, char *desc); extern int get_lua_int(cptr name); -extern s16b get_god_AULE(); -extern s16b get_god_VARDA(); -extern s16b get_god_ULMO(); -extern s16b get_god_MANDOS(); extern bool_ get_com_lua(cptr promtp, int *com); diff --git a/src/lua_bind.c b/src/lua_bind.c index fa88a7c1..ca65cffd 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -589,38 +589,6 @@ int get_lua_int(cptr name) return exec_lua(format("return %s", name)); } -static int get_god_theme(cptr name) -{ - if (game_module_idx == MODULE_THEME) - { - return exec_lua(format("return GOD_%s", name)); - } - else - { - return -1; - } -} - -s16b get_god_AULE() -{ - return get_god_theme("AULE"); -} - -s16b get_god_MANDOS() -{ - return get_god_theme("MANDOS"); -} - -s16b get_god_VARDA() -{ - return get_god_theme("VARDA"); -} - -s16b get_god_ULMO() -{ - return get_god_theme("ULMO"); -} - /* * Returns the direction of the compass that y2, x2 is from y, x * the return value will be one of the following: north, south, diff --git a/src/player.pkg b/src/player.pkg index 0466b322..e9649729 100644 --- a/src/player.pkg +++ b/src/player.pkg @@ -3098,6 +3098,11 @@ extern s16b dun_level; #define GOD_YAVANNA 5 /** @} */ +extern s32b GOD_AULE; +extern s32b GOD_VARDA; +extern s32b GOD_ULMO; +extern s32b GOD_MANDOS; + /** @fn inc_piety(int god, s32b amt) * @brief Increase piety for god "god" by amount "amt".\n diff --git a/src/q_god.c b/src/q_god.c index 7c48f128..04a5eb15 100644 --- a/src/q_god.c +++ b/src/q_god.c @@ -951,19 +951,19 @@ static void set_god_dungeon_attributes() { quest_god_set_god_dungeon_attributes_yavanna(); } - else if (p_ptr->pgod == get_god_AULE()) + else if (p_ptr->pgod == GOD_AULE) { quest_god_set_god_dungeon_attributes_aule(); } - else if (p_ptr->pgod == get_god_VARDA()) + else if (p_ptr->pgod == GOD_VARDA) { quest_god_set_god_dungeon_attributes_varda(); } - else if (p_ptr->pgod == get_god_ULMO()) + else if (p_ptr->pgod == GOD_ULMO) { quest_god_set_god_dungeon_attributes_ulmo(); } - else if (p_ptr->pgod == get_god_MANDOS()) + else if (p_ptr->pgod == GOD_MANDOS) { quest_god_set_god_dungeon_attributes_mandos(); } diff --git a/src/spells1.c b/src/spells1.c index 8350a4ff..477dfdb9 100644 --- a/src/spells1.c +++ b/src/spells1.c @@ -944,7 +944,7 @@ void recall_player(int d, int f) */ static void project_check_gods(int typ) { - if (p_ptr->pgod == get_god_VARDA()) + if (p_ptr->pgod == GOD_VARDA) { if ((typ == GF_LITE) || (typ == GF_LITE_WEAK)) { @@ -953,7 +953,7 @@ static void project_check_gods(int typ) } } - if (p_ptr->pgod == get_god_ULMO()) + if (p_ptr->pgod == GOD_ULMO) { if ((typ == GF_FIRE) || (typ == GF_HELL_FIRE) || diff --git a/src/variable.c b/src/variable.c index c4388457..c3530df8 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1575,6 +1575,10 @@ s32b DUNGEON_ASTRAL_WILD_Y = 19; */ deity_type *deity_info; s32b max_gods = MAX_GODS_INIT; +s32b GOD_AULE = -99; +s32b GOD_VARDA = -99; +s32b GOD_ULMO = -99; +s32b GOD_MANDOS = -99; /* * Timers diff --git a/src/xtra1.c b/src/xtra1.c index 09315ed3..9c368a0f 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -2444,7 +2444,7 @@ static void calc_gods() } /* Aule provides to-hit/damage bonuses and fire resistance */ - GOD(get_god_AULE()) + GOD(GOD_AULE) { if (p_ptr->grace > 0) { @@ -2470,7 +2470,7 @@ static void calc_gods() /* Mandos provides nether resistance and, while praying, nether immunity and prevents teleportation. */ - GOD(get_god_MANDOS()) + GOD(GOD_MANDOS) { p_ptr->resist_neth = TRUE; @@ -2489,7 +2489,7 @@ static void calc_gods() /* Ulmo provides water breath and, while praying can provide poison resistance and magic breath. */ - GOD(get_god_ULMO()) + GOD(GOD_ULMO) { p_ptr->water_breath = TRUE; -- cgit v1.2.3 From 88a95bb6561ba7474f420fee1c73eeea18dfb1e4 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 9 Apr 2012 11:44:28 +0200 Subject: Lua: Display character bonuses from gods properly --- src/files.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/xtra1.c | 2 +- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/files.c b/src/files.c index 4e1a1984..c52beef9 100644 --- a/src/files.c +++ b/src/files.c @@ -1595,6 +1595,48 @@ void player_flags(u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp) if (p_ptr->grace > 10000) (*f1) |= TR1_STR; } + GOD(GOD_AULE) + { + if (p_ptr->grace > 5000) + { + (*f2) |= TR2_RES_FIRE; + } + } + + GOD(GOD_MANDOS) + { + (*f2) |= TR2_RES_NETHER; + + if ((p_ptr->grace > 10000) && + (p_ptr->praying == TRUE)) + { + (*f3) |= TR3_NO_TELE; + } + + if ((p_ptr->grace > 20000) && + (p_ptr->praying == TRUE)) + { + (*f4) |= TR4_IM_NETHER; + } + } + + GOD(GOD_ULMO) + { + (*f5) |= TR5_WATER_BREATH; + + if ((p_ptr->grace > 1000) && + (p_ptr->praying == TRUE)) + { + (*f2) |= TR2_RES_POIS; + } + + if ((p_ptr->grace > 15000) && + (p_ptr->praying == TRUE)) + { + (*f5) |= TR5_MAGIC_BREATH; + } + } + /* Classes */ for (i = 1; i <= p_ptr->lev; i++) { diff --git a/src/xtra1.c b/src/xtra1.c index 9c368a0f..c1189484 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -2449,7 +2449,7 @@ static void calc_gods() if (p_ptr->grace > 0) { int bonus; - /* Resist fire, not shown on the character screen (?) */ + /* Resist fire*/ if (p_ptr->grace > 5000) { p_ptr->resist_fire = TRUE; -- cgit v1.2.3 From 1d3171629ae1aea66f0f57cde7d4390c7fc760c1 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 9 Apr 2012 11:59:07 +0200 Subject: Lua: God quests: Move relic "setup" code to C --- lib/mods/theme/scpt/god.lua | 23 ----------------------- lib/scpt/god.lua | 15 --------------- src/q_god.c | 23 ++++++++++++++++++++++- 3 files changed, 22 insertions(+), 39 deletions(-) diff --git a/lib/mods/theme/scpt/god.lua b/lib/mods/theme/scpt/god.lua index 54314d60..31aafd17 100644 --- a/lib/mods/theme/scpt/god.lua +++ b/lib/mods/theme/scpt/god.lua @@ -39,29 +39,6 @@ function msg_directions() end) end --- Set up relic number according to god -function setup_relic_number() - if player.pgod == GOD_ERU then - god_quest.relic_num = 7 - elseif player.pgod == GOD_MANWE then - god_quest.relic_num = 8 - elseif player.pgod == GOD_TULKAS then - god_quest.relic_num = 9 - elseif player.pgod == GOD_MELKOR then - god_quest.relic_num = 10 - elseif player.pgod == GOD_YAVANNA then - god_quest.relic_num = 11 - elseif player.pgod == GOD_AULE then - god_quest.relic_num = 16 - elseif player.pgod == GOD_VARDA then - god_quest.relic_num = 17 - elseif player.pgod == GOD_ULMO then - god_quest.relic_num = 18 - elseif player.pgod == GOD_MANDOS then - god_quest.relic_num = 19 - end -end - add_quest { ["global"] = "GOD_QUEST", diff --git a/lib/scpt/god.lua b/lib/scpt/god.lua index d478bf1e..b8426182 100644 --- a/lib/scpt/god.lua +++ b/lib/scpt/god.lua @@ -39,21 +39,6 @@ function msg_directions() end) end --- Set up relic number according to god -function setup_relic_number() - if player.pgod == GOD_ERU then - god_quest.relic_num = 7 - elseif player.pgod == GOD_MANWE then - god_quest.relic_num = 8 - elseif player.pgod == GOD_TULKAS then - god_quest.relic_num = 9 - elseif player.pgod == GOD_MELKOR then - god_quest.relic_num = 10 - elseif player.pgod == GOD_YAVANNA then - god_quest.relic_num = 11 - end -end - add_quest { ["global"] = "GOD_QUEST", diff --git a/src/q_god.c b/src/q_god.c index 04a5eb15..7b5f69b4 100644 --- a/src/q_god.c +++ b/src/q_god.c @@ -142,7 +142,28 @@ static void set_relics_found(int v) static void setup_relic_number() { - exec_lua("setup_relic_number()"); + int i; + int sval_by_god[][2] = { + { GOD_ERU, 7 }, + { GOD_MANWE, 8 }, + { GOD_TULKAS, 9 }, + { GOD_MELKOR, 10 }, + { GOD_YAVANNA, 11 }, + { GOD_AULE, 16 }, + { GOD_VARDA, 17 }, + { GOD_ULMO, 18 }, + { GOD_MANDOS, 19 }, + { -1, -1 }, + }; + + for (i = 0; sval_by_god[i][1] != -1; i++) + { + if (p_ptr->pgod == sval_by_god[i][0]) + { + int sval = sval_by_god[i][1]; + exec_lua(format("god_quest.relic_num = %d", sval)); + } + } } static void msg_directions() -- cgit v1.2.3 From 95bc3fc78d071be59870e418bb6229992fd5796a Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 9 Apr 2012 12:12:44 +0200 Subject: Lua: God quests: Move description code to C --- lib/mods/theme/scpt/god.lua | 73 +------------- lib/scpt/god.lua | 73 +------------- src/externs.h | 3 - src/lua_bind.c | 82 ---------------- src/plots.h | 1 + src/q_god.c | 233 +++++++++++++++++++++++++++++++++++++++++++- src/quest.pkg | 1 + src/util.pkg | 6 -- 8 files changed, 234 insertions(+), 238 deletions(-) diff --git a/lib/mods/theme/scpt/god.lua b/lib/mods/theme/scpt/god.lua index 31aafd17..fdb7296c 100644 --- a/lib/mods/theme/scpt/god.lua +++ b/lib/mods/theme/scpt/god.lua @@ -12,48 +12,11 @@ god_quest.MAX_NUM_GOD_QUESTS = 7 -- d_idx of the god_quest (Lost Temple) dungeon god_quest.DUNGEON_GOD = 30 --- Show directions given a function to print -function print_directions(feel_it, pfunc) - local home, home_axis, home_distance, home2, home2_axis, home2_distance = get_god_quest_axes() - - local feel_it_str = "." - if feel_it == TRUE then - feel_it_str = ", I can feel it.'" - end - - if home_axis ~= "close" then - pfunc("The temple lies "..home_distance.." to the "..home_axis.." of "..home..", ") - else - pfunc("The temple lies very close to "..home..", ") - end - if home2_axis ~= "close" then - pfunc( "and "..home2_distance.." to the "..home2_axis.." of "..home2..feel_it_str) - else - pfunc("and very close to "..home2..feel_it_str) - end -end - -function msg_directions() - print_directions(TRUE, function (line) - cmsg_print(TERM_YELLOW, line) - end) -end - add_quest { ["global"] = "GOD_QUEST", ["name"] = "God quest", - ["desc"] = function() - if quest(GOD_QUEST).status == QUEST_STATUS_TAKEN then - print_hook("#####yGod quest "..god_quest.quests_given.."!\n") - print_hook("Thou art to find the lost temple of thy God and\n"); - print_hook("to retrieve the lost part of the relic for thy God! \n") - print_directions(FALSE, function (line) - print_hook(line .. "\n") - end) - print_hook("\n") - end - end, + ["desc"] = function() quest_god_describe() end, ["level"] = -1, ["data"] = { ["god_quest.relic_num"] = 1, @@ -107,37 +70,3 @@ add_quest end, }, } - --- Calling this function returns the direction the dungeon is in from the players position at the time --- the quest was given, and also the direction from angband (if the player is worshipping Melkor) or lothlorien. -function get_god_quest_axes() - local home, home_y_coord, home_x_coord, home_axis, home2, home2_y_coord, home2_x_coord, home2_axis, mydistance - - -- different values for different gods... - if player.pgod ~= GOD_MELKOR then - - -- one of the valar, "home" is lothlorien, home2 is Minas Arnor - home = "Bree" - home_y_coord = 21 - home_x_coord = 35 - home2 = "Minas Anor" - home2_y_coord = 56 - home2_x_coord = 60 - else - -- Melkor, "home" is angband, home2 is Barad-dur - home = "the Pits of Angband" - home_y_coord = 7 - home_x_coord = 11 - home2 = "the Land of Mordor" - home2_y_coord = 49 - home2_x_coord = 70 - end - - home_axis = compass(home_y_coord, home_x_coord, god_quest.dung_y, god_quest.dung_x) - home2_axis = compass(home2_y_coord, home2_x_coord, god_quest.dung_y, god_quest.dung_x) - - home_distance = approximate_distance(home_y_coord, home_x_coord, god_quest.dung_y, god_quest.dung_x) - home2_distance = approximate_distance(home2_y_coord, home2_x_coord, god_quest.dung_y, god_quest.dung_x) - - return home, home_axis, home_distance, home2, home2_axis, home2_distance -end diff --git a/lib/scpt/god.lua b/lib/scpt/god.lua index b8426182..ad842c44 100644 --- a/lib/scpt/god.lua +++ b/lib/scpt/god.lua @@ -12,48 +12,11 @@ god_quest.MAX_NUM_GOD_QUESTS = 5 -- d_idx of the god_quest (Lost Temple) dungeon god_quest.DUNGEON_GOD = 30 --- Show directions given a function to print -function print_directions(feel_it, pfunc) - local home, home_axis, home_distance, home2, home2_axis, home2_distance = get_god_quest_axes() - - local feel_it_str = "." - if feel_it == TRUE then - feel_it_str = ", I can feel it.'" - end - - if home_axis ~= "close" then - pfunc("The temple lies "..home_distance.." to the "..home_axis.." of "..home..", ") - else - pfunc("The temple lies very close to "..home..", ") - end - if home2_axis ~= "close" then - pfunc( "and "..home2_distance.." to the "..home2_axis.." of "..home2..feel_it_str) - else - pfunc("and very close to "..home2..feel_it_str) - end -end - -function msg_directions() - print_directions(TRUE, function (line) - cmsg_print(TERM_YELLOW, line) - end) -end - add_quest { ["global"] = "GOD_QUEST", ["name"] = "God quest", - ["desc"] = function() - if quest(GOD_QUEST).status == QUEST_STATUS_TAKEN then - print_hook("#####yGod quest "..god_quest.quests_given.."!\n") - print_hook("Thou art to find the lost temple of thy God and\n"); - print_hook("to retrieve the lost part of the relic for thy God! \n") - print_directions(FALSE, function (line) - print_hook(line .. "\n") - end) - print_hook("\n") - end - end, + ["desc"] = function() quest_god_describe() end, ["level"] = -1, ["data"] = { ["god_quest.relic_num"] = 1, @@ -107,37 +70,3 @@ add_quest end, }, } - --- Calling this function returns the direction the dungeon is in from the players position at the time --- the quest was given, and also the direction from angband (if the player is worshipping Melkor) or lothlorien. -function get_god_quest_axes() - local home, home_y_coord, home_x_coord, home_axis, home2, home2_y_coord, home2_x_coord, home2_axis, mydistance - - -- different values for different gods... - if player.pgod ~= GOD_MELKOR then - - -- one of the valar, "home" is lothlorien, home2 is Minas Arnor - home = "Bree" - home_y_coord = 21 - home_x_coord = 34 - home2 = "Minas Anor" - home2_y_coord = 56 - home2_x_coord = 60 - else - -- Melkor, "home" is angband, home2 is Barad-dur - home = "the Pits of Angband" - home_y_coord = 7 - home_x_coord = 34 - home2 = "the Land of Mordor" - home2_y_coord = 58 - home2_x_coord = 65 - end - - home_axis = compass(home_y_coord, home_x_coord, god_quest.dung_y, god_quest.dung_x) - home2_axis = compass(home2_y_coord, home2_x_coord, god_quest.dung_y, god_quest.dung_x) - - home_distance = approximate_distance(home_y_coord, home_x_coord, god_quest.dung_y, god_quest.dung_x) - home2_distance = approximate_distance(home2_y_coord, home2_x_coord, god_quest.dung_y, god_quest.dung_x) - - return home, home_axis, home_distance, home2, home2_axis, home2_distance -end diff --git a/src/externs.h b/src/externs.h index 774be450..4ab14bfd 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1841,9 +1841,6 @@ extern void lua_delete_list(list_type *, int size); extern void lua_add_to_list(list_type *, int idx, cptr str); extern void lua_display_list(int y, int x, int h, int w, cptr title, list_type *list, int max, int begin, int sel, byte sel_color); -extern cptr compass(int y, int x, int y2, int x2); -extern cptr approximate_distance(int y, int x, int y2, int x2); - extern bool_ drop_text_left(byte c, cptr s, int y, int o); extern bool_ drop_text_right(byte c, cptr s, int y, int o); diff --git a/src/lua_bind.c b/src/lua_bind.c index ca65cffd..a9e1b476 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -589,88 +589,6 @@ int get_lua_int(cptr name) return exec_lua(format("return %s", name)); } -/* - * Returns the direction of the compass that y2, x2 is from y, x - * the return value will be one of the following: north, south, - * east, west, north-east, south-east, south-west, north-west, - * or "close" if it is within 2 tiles. - */ -cptr compass(int y, int x, int y2, int x2) -{ - static char compass_dir[64]; - - // is it close to the north/south meridian? - int y_diff = y2 - y; - - // determine if y2, x2 is to the north or south of y, x - const char *y_axis; - if ((y_diff > -3) && (y_diff < 3)) - { - y_axis = 0; - } - else if (y2 > y) - { - y_axis = "south"; - } - else - { - y_axis = "north"; - } - - // is it close to the east/west meridian? - int x_diff = x2 - x; - - // determine if y2, x2 is to the east or west of y, x - const char *x_axis; - if ((x_diff > -3) && (x_diff < 3)) - { - x_axis = 0; - } - else if (x2 > x) - { - x_axis = "east"; - } - else - { - x_axis = "west"; - } - - // Maybe it is very close - if ((!x_axis) && (!y_axis)) { strcpy(compass_dir, "close"); } - // Maybe it is (almost) due N/S - else if (!x_axis) { strcpy(compass_dir, y_axis); } - // Maybe it is (almost) due E/W - else if (!y_axis) { strcpy(compass_dir, x_axis); } - // or if it is neither - else { sprintf(compass_dir, "%s-%s", y_axis, x_axis); } - return compass_dir; -} - -/* Returns a relative approximation of the 'distance' of y2, x2 from y, x. */ -cptr approximate_distance(int y, int x, int y2, int x2) -{ - // how far to away to the north/south? - int y_diff = abs(y2 - y); - // how far to away to the east/west? - int x_diff = abs(x2 - x); - // find which one is the larger distance - int most_dist = x_diff; - if (y_diff > most_dist) { - most_dist = y_diff; - } - - // how far away then? - if (most_dist >= 41) { - return "a very long way"; - } else if (most_dist >= 25) { - return "a long way"; - } else if (most_dist >= 8) { - return "quite some way"; - } else { - return "not very far"; - } -} - bool_ drop_text_left(byte c, cptr str, int y, int o) { int i = strlen(str); diff --git a/src/plots.h b/src/plots.h index cc13a7b4..bd3d80c4 100644 --- a/src/plots.h +++ b/src/plots.h @@ -71,3 +71,4 @@ extern void quest_god_player_level_hook(int gained); extern bool_ quest_god_get_hook(int o_idx); extern void quest_god_char_dump(); extern void quest_god_enter_dungeon_hook(int d_idx); +extern void quest_god_describe(); diff --git a/src/q_god.c b/src/q_god.c index 7b5f69b4..6be1e062 100644 --- a/src/q_god.c +++ b/src/q_god.c @@ -3,6 +3,92 @@ #define print_hook(fmt,...) do { fprintf(hook_file, fmt, ##__VA_ARGS__); } while (0) +/* + * Returns the direction of the compass that y2, x2 is from y, x + * the return value will be one of the following: north, south, + * east, west, north-east, south-east, south-west, north-west, + * or "close" if it is within 2 tiles. + * + * The returned string is allocated with strdup(). + */ +static char *compass(int y, int x, int y2, int x2) +{ + char compass_dir[64]; + + // is it close to the north/south meridian? + int y_diff = y2 - y; + + // determine if y2, x2 is to the north or south of y, x + const char *y_axis; + if ((y_diff > -3) && (y_diff < 3)) + { + y_axis = 0; + } + else if (y2 > y) + { + y_axis = "south"; + } + else + { + y_axis = "north"; + } + + // is it close to the east/west meridian? + int x_diff = x2 - x; + + // determine if y2, x2 is to the east or west of y, x + const char *x_axis; + if ((x_diff > -3) && (x_diff < 3)) + { + x_axis = 0; + } + else if (x2 > x) + { + x_axis = "east"; + } + else + { + x_axis = "west"; + } + + // Maybe it is very close + if ((!x_axis) && (!y_axis)) { strcpy(compass_dir, "close"); } + // Maybe it is (almost) due N/S + else if (!x_axis) { strcpy(compass_dir, y_axis); } + // Maybe it is (almost) due E/W + else if (!y_axis) { strcpy(compass_dir, x_axis); } + // or if it is neither + else { sprintf(compass_dir, "%s-%s", y_axis, x_axis); } + + /* Return a copy */ + return strdup(compass_dir); +} + +/* Returns a relative approximation of the 'distance' of y2, x2 from y, x. */ +static cptr approximate_distance(int y, int x, int y2, int x2) +{ + // how far to away to the north/south? + int y_diff = abs(y2 - y); + // how far to away to the east/west? + int x_diff = abs(x2 - x); + // find which one is the larger distance + int most_dist = x_diff; + if (y_diff > most_dist) { + most_dist = y_diff; + } + + // how far away then? + if (most_dist >= 41) { + return "a very long way"; + } else if (most_dist >= 25) { + return "a long way"; + } else if (most_dist >= 8) { + return "quite some way"; + } else { + return "not very far"; + } +} + /* d_idx of the god_quest (Lost Temple) dungeon */ #define DUNGEON_GOD 30 #define CHANCE_OF_GOD_QUEST 21 @@ -166,9 +252,150 @@ static void setup_relic_number() } } -static void msg_directions() +static void get_home_coordinates(int *home1_y, int *home1_x, char **home1, + int *home2_y, int *home2_x, char **home2) { - exec_lua("msg_directions()"); + /* Which are the waypoints? */ + if (p_ptr->pgod != GOD_MELKOR) + { + *home1 = "Bree"; + *home2 = "Minas Anor"; + } + else + { + *home1 = "the Pits of Angband"; + *home2 = "the Land of Mordor"; + } + + /* Module specific locations */ + if (game_module_idx == MODULE_TOME) + { + if (p_ptr->pgod != GOD_MELKOR) + { + *home1_y = 21; + *home1_x = 34; + *home2_y = 56; + *home2_x = 60; + } + else + { + *home1_y = 7; + *home1_x = 34; + *home2_y = 58; + *home2_x = 65; + } + } + else if (game_module_idx == MODULE_THEME) + { + if (p_ptr->pgod != GOD_MELKOR) + { + *home1_y = 21; + *home1_x = 35; + *home2_y = 56; + *home2_x = 60; + } + else + { + *home1_y = 7; + *home1_x = 11; + *home2_y = 49; + *home2_x = 70; + } + } + else + { + assert(FALSE); /* Uh, oh */ + } +} + +/* Print using cmsg_print. */ +static void print_using_cmsg(cptr line) +{ + cmsg_print(TERM_YELLOW, line); +} + +/* Print using print_hook. */ +static void print_using_print_hook(cptr line) +{ + print_hook("%s\n", line); +} + +/* Show directions */ +static void print_directions(bool_ feel_it, void (*pfunc)(cptr)) +{ + int home1_y, home1_x; + int home2_y, home2_x; + char *home1 = NULL; + char *home2 = NULL; + char *home1_axis = NULL; + char *home2_axis = NULL; + cptr home1_distance = NULL; + cptr home2_distance = NULL; + cptr feel_it_str = feel_it ? ", I can feel it.'" : "."; + char buf[256]; + + get_home_coordinates( + &home1_y, &home1_x, &home1, + &home2_y, &home2_x, &home2); + + home1_axis = compass(home1_y, home1_x, get_dung_y(), get_dung_x()); + home2_axis = compass(home2_y, home2_x, get_dung_y(), get_dung_x()); + + home1_distance = approximate_distance(home1_y, home1_x, get_dung_y(), get_dung_x()); + home2_distance = approximate_distance(home2_y, home2_x, get_dung_y(), get_dung_x()); + + /* Build the message */ + if (!streq(home1_axis, "close")) + { + snprintf(buf, sizeof(buf), + "The temple lies %s to the %s of %s, ", + home1_distance, + home1_axis, + home1); + pfunc(buf); + } + else + { + snprintf(buf, sizeof(buf), + "The temple lies very close to %s, ", + home1); + pfunc(buf); + } + + if (!streq(home2_axis, "close")) + { + snprintf(buf, sizeof(buf), + "and %s to the %s of %s%s", + home2_distance, + home2_axis, + home2, + feel_it_str); + pfunc(buf); + } + else + { + snprintf(buf, sizeof(buf), + "and very close to %s%s", + home2, + feel_it_str); + pfunc(buf); + } + + /* Free dyanmically allocated strings */ + free(home1_axis); + free(home2_axis); +} + +void quest_god_describe() +{ + if (get_status() == QUEST_STATUS_TAKEN) + { + print_hook("#####yGod quest %d!\n", get_quests_given()); + print_hook("Thou art to find the lost temple of thy God and\n"); + print_hook("to retrieve the lost part of the relic for thy God! \n"); + print_directions(FALSE, print_using_print_hook); + print_hook("\n"); + } } void quest_god_place_rand_dung() @@ -853,7 +1080,7 @@ void quest_god_player_level_hook(int gained) cmsg_print(TERM_YELLOW, "When thy task is done, thou art to lift it in the air and call upon my name."); cmsg_print(TERM_YELLOW, "I shall then come to reclaim what is mine!"); - msg_directions(); + print_directions(TRUE, print_using_cmsg); /* Prepare depth of dungeon. If this was * generated in set_god_dungeon_attributes(), diff --git a/src/quest.pkg b/src/quest.pkg index dca1ca4c..6a71a0f4 100644 --- a/src/quest.pkg +++ b/src/quest.pkg @@ -170,3 +170,4 @@ extern void quest_god_player_level_hook(int gained); extern bool quest_god_get_hook(int o_idx); extern void quest_god_char_dump(); extern void quest_god_enter_dungeon_hook(int d_idx); +extern void quest_god_describe(); diff --git a/src/util.pkg b/src/util.pkg index 738af28e..de84ac11 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -1305,12 +1305,6 @@ extern cptr get_player_race_name(int pr, int ps); */ extern void quit(cptr str); -/* - * compass, approximate_distance - */ -extern cptr compass(int y, int x, int y2, int x2); -extern cptr approximate_distance(int y, int x, int y2, int x2); - /** @fn text_out_c(byte a, cptr str) * @brief Output text to the screen (in color) or to a file depending on the * selected hook.\n -- cgit v1.2.3 From ca69f68a90b3f577f1d8711c08828696ad6025ac Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 9 Apr 2012 13:36:31 +0200 Subject: Lua: God quests: Remove unused player_{x,y} quest variables --- lib/mods/theme/scpt/god.lua | 2 -- lib/scpt/god.lua | 2 -- src/q_god.c | 22 ---------------------- 3 files changed, 26 deletions(-) diff --git a/lib/mods/theme/scpt/god.lua b/lib/mods/theme/scpt/god.lua index fdb7296c..ec806c9c 100644 --- a/lib/mods/theme/scpt/god.lua +++ b/lib/mods/theme/scpt/god.lua @@ -29,8 +29,6 @@ add_quest ["god_quest.relic_generated"] = FALSE, ["god_quest.dung_x"] = 1, ["god_quest.dung_y"] = 1, - ["god_quest.player_x"] = 0, - ["god_quest.player_y"] = 0, }, ["hooks"] = { -- Start the game without the quest, given it by chance diff --git a/lib/scpt/god.lua b/lib/scpt/god.lua index ad842c44..ad199f68 100644 --- a/lib/scpt/god.lua +++ b/lib/scpt/god.lua @@ -29,8 +29,6 @@ add_quest ["god_quest.relic_generated"] = FALSE, ["god_quest.dung_x"] = 1, ["god_quest.dung_y"] = 1, - ["god_quest.player_x"] = 0, - ["god_quest.player_y"] = 0, }, ["hooks"] = { -- Start the game without the quest, given it by chance diff --git a/src/q_god.c b/src/q_god.c index 6be1e062..e2a308bc 100644 --- a/src/q_god.c +++ b/src/q_god.c @@ -174,16 +174,6 @@ static int get_relic_gen_tries() return get_lua_int("god_quest.relic_gen_tries"); } -static void set_player_y(int y) -{ - exec_lua(format("god_quest.player_y = %d", y)); -} - -static void set_player_x(int x) -{ - exec_lua(format("god_quest.player_x = %d", x)); -} - static int get_dun_mindepth() { return get_lua_int("god_quest.dun_mindepth"); @@ -1058,18 +1048,6 @@ void quest_god_player_level_hook(int gained) /* actually place the dungeon in a random place */ quest_god_place_rand_dung(); - /* store the variables of the coords where the player was given the quest */ - if (p_ptr->wild_mode) - { - set_player_x(p_ptr->px); - set_player_y(p_ptr->py); - } - else - { - set_player_x(p_ptr->wilderness_x); - set_player_y(p_ptr->wilderness_y); - } - /* God issues instructions */ cmsg_format(TERM_L_BLUE, "The voice of %s booms in your head:", deity_info[p_ptr->pgod].name); -- cgit v1.2.3 From 83d568690a9250b87d9d982170e1a8918364dea2 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 9 Apr 2012 14:12:48 +0200 Subject: Lua: God quests: Move quest setup to C --- lib/mods/theme/scpt/god.lua | 70 --------- lib/mods/theme/scpt/init.lua | 1 - lib/scpt/god.lua | 70 --------- lib/scpt/init.lua | 1 - src/birth.c | 2 +- src/defines.h | 3 +- src/loadsave.c | 2 +- src/plots.h | 10 +- src/q_god.c | 354 ++++++++++++++++++++----------------------- src/quest.pkg | 12 -- src/tables.c | 25 +++ src/types.h | 2 +- 12 files changed, 195 insertions(+), 357 deletions(-) delete mode 100644 lib/mods/theme/scpt/god.lua delete mode 100644 lib/scpt/god.lua diff --git a/lib/mods/theme/scpt/god.lua b/lib/mods/theme/scpt/god.lua deleted file mode 100644 index ec806c9c..00000000 --- a/lib/mods/theme/scpt/god.lua +++ /dev/null @@ -1,70 +0,0 @@ --- The god quest: find randomly placed relic in a randomly placed dungeon! - --- set some global variables (stored in the save file via the ["data"] key) -god_quest = {} - --- increase this number to make god quests more common, to a max value of 100 -god_quest.CHANCE_OF_GOD_QUEST = 21 - --- increase this number to make more quests -god_quest.MAX_NUM_GOD_QUESTS = 7 - --- d_idx of the god_quest (Lost Temple) dungeon -god_quest.DUNGEON_GOD = 30 - -add_quest -{ - ["global"] = "GOD_QUEST", - ["name"] = "God quest", - ["desc"] = function() quest_god_describe() end, - ["level"] = -1, - ["data"] = { - ["god_quest.relic_num"] = 1, - ["god_quest.quests_given"] = 0, - ["god_quest.relics_found"] = 0, - ["god_quest.dun_mindepth"] = 1, - ["god_quest.dun_maxdepth"] = 4, - ["god_quest.dun_minplev"] = 0, - ["god_quest.relic_gen_tries"] = 0, - ["god_quest.relic_generated"] = FALSE, - ["god_quest.dung_x"] = 1, - ["god_quest.dung_y"] = 1, - }, - ["hooks"] = { - -- Start the game without the quest, given it by chance - [HOOK_BIRTH_OBJECTS] = function() - quest(GOD_QUEST).status = QUEST_STATUS_UNTAKEN - - -- initialise save-file stored variables when new character is created - god_quest.relic_num = 1 - god_quest.quests_given = 0 - god_quest.relics_found = 0 - god_quest.dun_mindepth = 1 - god_quest.dun_maxdepth = 4 - god_quest.dun_minplev = 0 - god_quest.relic_gen_tries = 0 - god_quest.relic_generated = FALSE - end, - [HOOK_PLAYER_LEVEL] = function(gained) - quest_god_player_level_hook(gained) - end, - [HOOK_LEVEL_END_GEN] = function() - quest_god_level_end_gen_hook() - end, - [HOOK_ENTER_DUNGEON] = function(d_idx) - quest_god_enter_dungeon_hook(d_idx) - end, - [HOOK_GEN_LEVEL_BEGIN] = function() - quest_god_enter_dungeon_hook(current_dungeon_idx) - end, - [HOOK_STAIR] = function() - quest_god_enter_dungeon_hook(current_dungeon_idx) - end, - [HOOK_GET] = function(o_ptr, item) - return quest_god_get_hook(item) - end, - [HOOK_CHAR_DUMP] = function() - return quest_god_char_dump() - end, - }, -} diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index 05954033..6a509a27 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -22,7 +22,6 @@ tome_dofile("gods_new.lua") tome_dofile("spells.lua") -- Add some quests -tome_dofile("god.lua") tome_dofile("library.lua") -- Add joke stuff diff --git a/lib/scpt/god.lua b/lib/scpt/god.lua deleted file mode 100644 index ad199f68..00000000 --- a/lib/scpt/god.lua +++ /dev/null @@ -1,70 +0,0 @@ --- The god quest: find randomly placed relic in a randomly placed dungeon! - --- set some global variables (stored in the save file via the ["data"] key) -god_quest = {} - --- increase this number to make god quests more common, to a max value of 100 -god_quest.CHANCE_OF_GOD_QUEST = 21 - --- increase this number to make more quests -god_quest.MAX_NUM_GOD_QUESTS = 5 - --- d_idx of the god_quest (Lost Temple) dungeon -god_quest.DUNGEON_GOD = 30 - -add_quest -{ - ["global"] = "GOD_QUEST", - ["name"] = "God quest", - ["desc"] = function() quest_god_describe() end, - ["level"] = -1, - ["data"] = { - ["god_quest.relic_num"] = 1, - ["god_quest.quests_given"] = 0, - ["god_quest.relics_found"] = 0, - ["god_quest.dun_mindepth"] = 1, - ["god_quest.dun_maxdepth"] = 4, - ["god_quest.dun_minplev"] = 0, - ["god_quest.relic_gen_tries"] = 0, - ["god_quest.relic_generated"] = FALSE, - ["god_quest.dung_x"] = 1, - ["god_quest.dung_y"] = 1, - }, - ["hooks"] = { - -- Start the game without the quest, given it by chance - [HOOK_BIRTH_OBJECTS] = function() - quest(GOD_QUEST).status = QUEST_STATUS_UNTAKEN - - -- initialise save-file stored variables when new character is created - god_quest.relic_num = 1 - god_quest.quests_given = 0 - god_quest.relics_found = 0 - god_quest.dun_mindepth = 1 - god_quest.dun_maxdepth = 4 - god_quest.dun_minplev = 0 - god_quest.relic_gen_tries = 0 - god_quest.relic_generated = FALSE - end, - [HOOK_PLAYER_LEVEL] = function(gained) - quest_god_player_level_hook(gained) - end, - [HOOK_LEVEL_END_GEN] = function() - quest_god_level_end_gen_hook() - end, - [HOOK_ENTER_DUNGEON] = function(d_idx) - quest_god_enter_dungeon_hook(d_idx) - end, - [HOOK_GEN_LEVEL_BEGIN] = function() - quest_god_enter_dungeon_hook(current_dungeon_idx) - end, - [HOOK_STAIR] = function() - quest_god_enter_dungeon_hook(current_dungeon_idx) - end, - [HOOK_GET] = function(o_ptr, item) - return quest_god_get_hook(item) - end, - [HOOK_CHAR_DUMP] = function() - return quest_god_char_dump() - end, - }, -} diff --git a/lib/scpt/init.lua b/lib/scpt/init.lua index 48ac15a7..ef85b5e9 100644 --- a/lib/scpt/init.lua +++ b/lib/scpt/init.lua @@ -21,7 +21,6 @@ tome_dofile("spells.lua") tome_dofile("gods.lua") -- Add some quests -tome_dofile("god.lua") tome_dofile("library.lua") -- Add joke stuff diff --git a/src/birth.c b/src/birth.c index 47b806e7..75ff1ed2 100644 --- a/src/birth.c +++ b/src/birth.c @@ -861,7 +861,7 @@ static void player_wipe(void) for (i = 0; i < MAX_Q_IDX_INIT; i++) { quest[i].status = QUEST_STATUS_UNTAKEN; - for (j = 0; j < 4; j++) + for (j = 0; j < sizeof(quest[i].data)/sizeof(quest[i].data[0]); j++) { quest[i].data[j] = 0; } diff --git a/src/defines.h b/src/defines.h index 41b96bba..abdd4a90 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4421,7 +4421,8 @@ #define QUEST_BOUNTY 26 #define QUEST_FIREPROOF 27 #define QUEST_LIBRARY 28 -#define MAX_Q_IDX_INIT 29 +#define QUEST_GOD 29 +#define MAX_Q_IDX_INIT 30 #define PLOT_MAIN 0 #define PLOT_BREE 1 diff --git a/src/loadsave.c b/src/loadsave.c index 56ebfaa9..fe89a451 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -2703,7 +2703,7 @@ static bool_ do_savefile_aux(int flag) for (i = 0; i < max_quests_ldsv; i++) { do_s16b(&quest[i].status, flag); - for (j = 0; j < 4; j++) + for (j = 0; j < sizeof(quest[i].data)/sizeof(quest[i].data[0]); j++) { do_s32b(&(quest[i].data[j]), flag); } diff --git a/src/plots.h b/src/plots.h index bd3d80c4..91115856 100644 --- a/src/plots.h +++ b/src/plots.h @@ -64,11 +64,5 @@ extern bool_ quest_fireproof_init_hook(int q); extern bool_ quest_fireproof_describe(FILE *fff); /******* Plot God Quest **************/ -extern void quest_god_place_rand_dung(); -extern void quest_god_generate_relic(); -extern void quest_god_level_end_gen_hook(); -extern void quest_god_player_level_hook(int gained); -extern bool_ quest_god_get_hook(int o_idx); -extern void quest_god_char_dump(); -extern void quest_god_enter_dungeon_hook(int d_idx); -extern void quest_god_describe(); +extern bool_ quest_god_describe(FILE *); +extern bool_ quest_god_init_hook(int q); diff --git a/src/q_god.c b/src/q_god.c index e2a308bc..0c90985a 100644 --- a/src/q_god.c +++ b/src/q_god.c @@ -1,7 +1,20 @@ #include "angband.h" #include -#define print_hook(fmt,...) do { fprintf(hook_file, fmt, ##__VA_ARGS__); } while (0) +#define cquest (quest[QUEST_GOD]) +#define cquest_quests_given (cquest.data[0]) +#define cquest_relics_found (cquest.data[1]) +#define cquest_dun_mindepth (cquest.data[2]) +#define cquest_dun_maxdepth (cquest.data[3]) +#define cquest_dun_minplev (cquest.data[4]) +#define cquest_relic_gen_tries (cquest.data[5]) +#define cquest_relic_generated (cquest.data[6]) +#define cquest_dung_x (cquest.data[7]) +#define cquest_dung_y (cquest.data[8]) + +/* d_idx of the god_quest (Lost Temple) dungeon */ +#define DUNGEON_GOD 30 +#define CHANCE_OF_GOD_QUEST 21 /* * Returns the direction of the compass that y2, x2 is from y, x @@ -89,134 +102,22 @@ static cptr approximate_distance(int y, int x, int y2, int x2) } } -/* d_idx of the god_quest (Lost Temple) dungeon */ -#define DUNGEON_GOD 30 -#define CHANCE_OF_GOD_QUEST 21 - -static int get_quests_given() -{ - return get_lua_int("god_quest.quests_given"); -} - -static void set_quests_given(int i) -{ - exec_lua(format("god_quest.quests_given = %d", i)); -} - -static int get_dung_y() -{ - return get_lua_int("god_quest.dung_y"); -} - -static int get_dung_x() -{ - return get_lua_int("god_quest.dung_x"); -} - -static void set_dung_y(int y) -{ - exec_lua(format("god_quest.dung_y = %d", y)); -} - -static void set_dung_x(int x) -{ - exec_lua(format("god_quest.dung_x = %d", x)); -} - -static int get_relic_num() -{ - return get_lua_int("god_quest.relic_num"); -} - -static int get_status() -{ - return exec_lua("return quest(GOD_QUEST).status"); -} - -static void set_status(int new_status) -{ - exec_lua(format("quest(GOD_QUEST).status = %d", new_status)); -} - static int MAX_NUM_GOD_QUESTS() { - return get_lua_int("god_quest.MAX_NUM_GOD_QUESTS"); -} - -static void set_relic_generated(bool_ v) -{ - switch (v) + if (game_module_idx == MODULE_TOME) { - case TRUE: - exec_lua("god_quest.relic_generated = TRUE"); - break; - case FALSE: - exec_lua("god_quest.relic_generated = FALSE"); - break; - default: - assert(FALSE); - break; + return 5; } + if (game_module_idx == MODULE_THEME) + { + return 7; + } + /* Uh, oh. */ + assert(FALSE); + return 0; } -static bool_ get_relic_generated() -{ - return get_lua_int("god_quest.relic_generated"); -} - -static void set_relic_gen_tries(int v) -{ - exec_lua(format("god_quest.relic_gen_tries = %d", v)); -} - -static int get_relic_gen_tries() -{ - return get_lua_int("god_quest.relic_gen_tries"); -} - -static int get_dun_mindepth() -{ - return get_lua_int("god_quest.dun_mindepth"); -} - -static void set_dun_mindepth(int d) -{ - exec_lua(format("god_quest.dun_mindepth = %d", d)); -} - -static int get_dun_maxdepth() -{ - return get_lua_int("god_quest.dun_maxdepth"); - -} - -static void set_dun_maxdepth(int d) -{ - exec_lua(format("god_quest.dun_maxdepth = %d", d)); - -} - -static void set_dun_minplev(int p) -{ - exec_lua(format("god_quest.dun_minplev = %d", p)); -} - -static int get_dun_minplev() -{ - return get_lua_int("god_quest.dun_minplev"); -} - -static int get_relics_found() -{ - return get_lua_int("god_quest.relics_found"); -} - -static void set_relics_found(int v) -{ - exec_lua(format("god_quest.relics_found = %d", v)); -} - -static void setup_relic_number() +static byte get_relic_num() { int i; int sval_by_god[][2] = { @@ -237,9 +138,12 @@ static void setup_relic_number() if (p_ptr->pgod == sval_by_god[i][0]) { int sval = sval_by_god[i][1]; - exec_lua(format("god_quest.relic_num = %d", sval)); + return sval; } } + + /* Uh, oh. */ + assert(FALSE); } static void get_home_coordinates(int *home1_y, int *home1_x, char **home1, @@ -299,19 +203,20 @@ static void get_home_coordinates(int *home1_y, int *home1_x, char **home1, } /* Print using cmsg_print. */ -static void print_using_cmsg(cptr line) +static void print_using_cmsg(cptr line, void *dummy) { cmsg_print(TERM_YELLOW, line); } /* Print using print_hook. */ -static void print_using_print_hook(cptr line) +static void print_using_print_hook(cptr line, void *f_) { - print_hook("%s\n", line); + FILE *f = (FILE *) f_; + fprintf(f, "%s\n", line); } /* Show directions */ -static void print_directions(bool_ feel_it, void (*pfunc)(cptr)) +static void print_directions(bool_ feel_it, void (*pfunc)(cptr, void *), void *pfdata) { int home1_y, home1_x; int home2_y, home2_x; @@ -328,11 +233,11 @@ static void print_directions(bool_ feel_it, void (*pfunc)(cptr)) &home1_y, &home1_x, &home1, &home2_y, &home2_x, &home2); - home1_axis = compass(home1_y, home1_x, get_dung_y(), get_dung_x()); - home2_axis = compass(home2_y, home2_x, get_dung_y(), get_dung_x()); + home1_axis = compass(home1_y, home1_x, cquest_dung_y, cquest_dung_x); + home2_axis = compass(home2_y, home2_x, cquest_dung_y, cquest_dung_x); - home1_distance = approximate_distance(home1_y, home1_x, get_dung_y(), get_dung_x()); - home2_distance = approximate_distance(home2_y, home2_x, get_dung_y(), get_dung_x()); + home1_distance = approximate_distance(home1_y, home1_x, cquest_dung_y, cquest_dung_x); + home2_distance = approximate_distance(home2_y, home2_x, cquest_dung_y, cquest_dung_x); /* Build the message */ if (!streq(home1_axis, "close")) @@ -342,14 +247,14 @@ static void print_directions(bool_ feel_it, void (*pfunc)(cptr)) home1_distance, home1_axis, home1); - pfunc(buf); + pfunc(buf, pfdata); } else { snprintf(buf, sizeof(buf), "The temple lies very close to %s, ", home1); - pfunc(buf); + pfunc(buf, pfdata); } if (!streq(home2_axis, "close")) @@ -360,7 +265,7 @@ static void print_directions(bool_ feel_it, void (*pfunc)(cptr)) home2_axis, home2, feel_it_str); - pfunc(buf); + pfunc(buf, pfdata); } else { @@ -368,7 +273,7 @@ static void print_directions(bool_ feel_it, void (*pfunc)(cptr)) "and very close to %s%s", home2, feel_it_str); - pfunc(buf); + pfunc(buf, pfdata); } /* Free dyanmically allocated strings */ @@ -376,16 +281,18 @@ static void print_directions(bool_ feel_it, void (*pfunc)(cptr)) free(home2_axis); } -void quest_god_describe() +bool_ quest_god_describe(FILE *fff) { - if (get_status() == QUEST_STATUS_TAKEN) + if (cquest.status == QUEST_STATUS_TAKEN) { - print_hook("#####yGod quest %d!\n", get_quests_given()); - print_hook("Thou art to find the lost temple of thy God and\n"); - print_hook("to retrieve the lost part of the relic for thy God! \n"); - print_directions(FALSE, print_using_print_hook); - print_hook("\n"); + fprintf(fff, "#####yGod quest %d!\n", cquest_quests_given); + fprintf(fff, "Thou art to find the lost temple of thy God and\n"); + fprintf(fff, "to retrieve the lost part of the relic for thy God! \n"); + print_directions(FALSE, print_using_print_hook, fff); + fprintf(fff, "\n"); } + + return TRUE; } void quest_god_place_rand_dung() @@ -393,9 +300,9 @@ void quest_god_place_rand_dung() int x = -1, y = -1, tries; /* erase old dungeon */ - if (get_quests_given() > 0) + if (cquest_quests_given > 0) { - wild_map[get_dung_y()][get_dung_x()].entrance = 0; + wild_map[cquest_dung_y][cquest_dung_x].entrance = 0; /* erase old recall level */ max_dlv[DUNGEON_GOD] = 0; @@ -451,8 +358,8 @@ void quest_god_place_rand_dung() wild_map[y][x].entrance = 1000 + DUNGEON_GOD; /* set quest variables */ - set_dung_x(x); - set_dung_y(y); + cquest_dung_x = x; + cquest_dung_y = y; } void quest_god_generate_relic() @@ -511,10 +418,10 @@ void quest_god_generate_relic() } /* Only generate once! */ - set_relic_generated(TRUE); + cquest_relic_generated = TRUE; /* Reset some variables */ - set_relic_gen_tries(0); + cquest_relic_gen_tries = 0; } static void quest_god_set_god_dungeon_attributes_eru() @@ -955,13 +862,13 @@ static void quest_god_set_god_dungeon_attributes_mandos() d_info[DUNGEON_GOD].rules[0].mflags3 = RF3_UNDEAD | RF3_EVIL; } -void quest_god_level_end_gen_hook() +static bool_ quest_god_level_end_gen_hook(char *fmt) { /* Check for dungeon */ if ((dungeon_type != DUNGEON_GOD) || - (get_status() == QUEST_STATUS_UNTAKEN)) + (cquest.status == QUEST_STATUS_UNTAKEN)) { - return; + return FALSE; } /* if the relic has been created at this point, then it was @@ -969,12 +876,12 @@ void quest_god_level_end_gen_hook() therefore the player has caused another level generation in the temple and hence failed the quest.*/ - else if ((get_relic_generated() == TRUE) && - (get_status() != QUEST_STATUS_FAILED)) + else if ((cquest_relic_generated == TRUE) && + (cquest.status != QUEST_STATUS_FAILED)) { /* fail the quest, don't give another one, don't give * this message again */ - set_status(QUEST_STATUS_FAILED); + cquest.status = QUEST_STATUS_FAILED; /* God issues instructions */ cmsg_format(TERM_L_BLUE, "The voice of %s booms in your head:", deity_info[p_ptr->pgod].name); @@ -990,8 +897,8 @@ void quest_god_level_end_gen_hook() /* Force relic generation on 5th attempt if others have been * unsuccessful. */ - else if ((get_relic_gen_tries() == 4) && - (get_relic_generated() == FALSE)) + else if ((cquest_relic_gen_tries == 4) && + (cquest_relic_generated == FALSE)) { quest_god_generate_relic(); } @@ -1005,45 +912,46 @@ void quest_god_level_end_gen_hook() } else { - set_relic_gen_tries(get_relic_gen_tries() + 1); + cquest_relic_gen_tries = cquest_relic_gen_tries + 1; } } + + return FALSE; } -void quest_god_player_level_hook(int gained) +bool_ quest_god_player_level_hook(char *fmt) { + s32b gained = get_next_arg(fmt); + if (gained <= 0) { - return; + return FALSE; } /* check player is worshipping a god, not already on a god quest. */ if ((p_ptr->astral) || (p_ptr->pgod <= 0) || - (get_status() == QUEST_STATUS_TAKEN) || - (get_status() == QUEST_STATUS_FAILED) || - (get_quests_given() >= MAX_NUM_GOD_QUESTS()) || + (cquest.status == QUEST_STATUS_TAKEN) || + (cquest.status == QUEST_STATUS_FAILED) || + (cquest_quests_given >= MAX_NUM_GOD_QUESTS()) || (magik(CHANCE_OF_GOD_QUEST) == FALSE) || ((dungeon_type == DUNGEON_GOD) && (dun_level > 0)) || - (p_ptr->lev <= get_dun_minplev())) + (p_ptr->lev <= cquest_dun_minplev)) { /* Don't let a player get quests with trickery */ - if (p_ptr->lev > get_dun_minplev()) + if (p_ptr->lev > cquest_dun_minplev) { - set_dun_minplev(p_ptr->lev); + cquest_dun_minplev = p_ptr->lev; } - return; + return FALSE; } else { - /* each god has different characteristics, so the quests are differnet depending on your god */ - setup_relic_number(); - /* This var will need resetting */ - set_relic_generated(FALSE); - set_status(QUEST_STATUS_TAKEN); - set_quests_given(get_quests_given() + 1); + cquest.status = QUEST_STATUS_TAKEN; + cquest_relic_generated = FALSE; + cquest_quests_given = cquest_quests_given + 1; /* actually place the dungeon in a random place */ quest_god_place_rand_dung(); @@ -1058,35 +966,41 @@ void quest_god_player_level_hook(int gained) cmsg_print(TERM_YELLOW, "When thy task is done, thou art to lift it in the air and call upon my name."); cmsg_print(TERM_YELLOW, "I shall then come to reclaim what is mine!"); - print_directions(TRUE, print_using_cmsg); + print_directions(TRUE, print_using_cmsg, NULL); /* Prepare depth of dungeon. If this was * generated in set_god_dungeon_attributes(), * then we'd have trouble if someone levelled * up in the dungeon! */ - set_dun_mindepth(p_ptr->lev*2/3); - set_dun_maxdepth(get_dun_mindepth() + 4); + cquest_dun_mindepth = p_ptr->lev*2/3; + cquest_dun_maxdepth = cquest_dun_mindepth + 4; } + + return FALSE; } -bool_ quest_god_get_hook(int item) +bool_ quest_god_get_hook(char *fmt) { + s32b item; object_type *o_ptr = NULL; + get_next_arg("d"); /* ignore first arg */ + item = get_next_arg("d"); + item = -item; /* Workaround */ o_ptr = get_object(item); /* -- Is it the relic, and check to make sure the relic hasn't already been identified */ - if ((get_status() == QUEST_STATUS_TAKEN) && + if ((cquest.status == QUEST_STATUS_TAKEN) && (o_ptr->tval == TV_JUNK) && (o_ptr->sval == get_relic_num()) && (o_ptr->pval != TRUE) && - (get_relics_found() < get_quests_given())) + (cquest_relics_found < cquest_quests_given)) { cmsg_format(TERM_L_BLUE, "%s speaks to you:", deity_info[p_ptr->pgod].name); /* Is it the last piece of the relic? */ - if (get_quests_given() == MAX_NUM_GOD_QUESTS()) + if (cquest_quests_given == MAX_NUM_GOD_QUESTS()) { cmsg_print(TERM_YELLOW, "'At last! Thou hast found all of the relic pieces."); @@ -1110,10 +1024,10 @@ bool_ quest_god_get_hook(int item) /* relic piece has been identified */ o_ptr->pval = TRUE; - set_relics_found(get_relics_found() + 1); + cquest_relics_found = cquest_relics_found + 1; /* Make sure quests can be given again if neccesary */ - set_status(QUEST_STATUS_UNTAKEN); + cquest.status = QUEST_STATUS_UNTAKEN; /* Prevent further processing of 'take' action; we've destroyed the item. */ @@ -1123,11 +1037,11 @@ bool_ quest_god_get_hook(int item) return FALSE; } -void quest_god_char_dump() +static bool_ quest_god_char_dump_hook(char *fmt) { - if (get_quests_given() > 0) + if (cquest_quests_given > 0) { - int relics = get_relics_found(); + int relics = cquest_relics_found; char relics_text[128]; cptr append_text = ""; @@ -1144,14 +1058,18 @@ void quest_god_char_dump() { strcpy(relics_text, "none"); } - if (get_status() == QUEST_STATUS_FAILED) + if (cquest.status == QUEST_STATUS_FAILED) { append_text = " and failed in your quest"; } } - print_hook("\n You found %s of the relic pieces%s.", relics_text, append_text); + fprintf(hook_file, "\n You found %s of the relic pieces%s.", + relics_text, + append_text); } + + return FALSE; } static void set_god_dungeon_attributes() @@ -1202,13 +1120,13 @@ static void set_god_dungeon_attributes() * the player clvl when the quest is given */ { dungeon_info_type *d_ptr = &d_info[DUNGEON_GOD]; - d_ptr->mindepth = get_dun_mindepth(); - d_ptr->maxdepth = get_dun_maxdepth(); - d_ptr->min_plev = get_dun_minplev(); + d_ptr->mindepth = cquest_dun_mindepth; + d_ptr->maxdepth = cquest_dun_maxdepth; + d_ptr->min_plev = cquest_dun_minplev; } } -void quest_god_enter_dungeon_hook(int d_idx) +static void quest_god_dungeon_setup(int d_idx) { /* call the function to set the dungeon variables (dependant * on pgod) the first time we enter the dungeon */ @@ -1219,3 +1137,57 @@ void quest_god_enter_dungeon_hook(int d_idx) set_god_dungeon_attributes(); } + +static bool_ quest_god_enter_dungeon_hook(char *fmt) +{ + s32b d_idx = get_next_arg(fmt); + quest_god_dungeon_setup(d_idx); + return FALSE; +} + +static bool_ quest_god_gen_level_begin_hook(char *fmt) +{ + quest_god_dungeon_setup(dungeon_type); + return FALSE; +} + +static bool_ quest_god_stair_hook(char *fmt) +{ + quest_god_dungeon_setup(dungeon_type); + return FALSE; +} + +static bool_ quest_god_birth_objects_hook(char *fmt) +{ + cquest_quests_given = 0; + cquest_relics_found = 0; + cquest_dun_mindepth = 1; + cquest_dun_maxdepth = 4; + cquest_dun_minplev = 0; + cquest_relic_gen_tries = 0; + cquest_relic_generated = FALSE; + + return FALSE; +} + +bool_ quest_god_init_hook(int q) +{ + /* Only need hooks if the quest is unfinished. */ + if ((cquest.status >= QUEST_STATUS_UNTAKEN) && + (cquest.status < QUEST_STATUS_FINISHED)) + { + add_hook(HOOK_LEVEL_END_GEN, quest_god_level_end_gen_hook, "q_god_level_end_gen"); + add_hook(HOOK_ENTER_DUNGEON, quest_god_enter_dungeon_hook, "q_god_enter_dungeon"); + add_hook(HOOK_GEN_LEVEL_BEGIN, quest_god_gen_level_begin_hook, "q_god_gen_level_begin"); + add_hook(HOOK_STAIR, quest_god_stair_hook, "q_god_hook_stair"); + add_hook(HOOK_GET, quest_god_get_hook, "q_god_get"); + add_hook(HOOK_CHAR_DUMP, quest_god_char_dump_hook, "q_god_char_dump"); + add_hook(HOOK_PLAYER_LEVEL, quest_god_player_level_hook, "q_god_player_level"); + } + + /* Need this to re-initialize at birth; the quest data is + * zeroed which isn't quite right. */ + add_hook(HOOK_BIRTH_OBJECTS, quest_god_birth_objects_hook, "q_god_birth_objects"); + + return FALSE; +} diff --git a/src/quest.pkg b/src/quest.pkg index 6a71a0f4..487c62af 100644 --- a/src/quest.pkg +++ b/src/quest.pkg @@ -159,15 +159,3 @@ extern s16b add_new_quest @ new_quest(char *name); * @note (see file lua_bind.c) */ extern void desc_quest @ quest_desc(int q_idx, int d, char *desc); - -/* - * God quest - */ -extern void quest_god_place_rand_dung(); -extern void quest_god_generate_relic(); -extern void quest_god_level_end_gen_hook(); -extern void quest_god_player_level_hook(int gained); -extern bool quest_god_get_hook(int o_idx); -extern void quest_god_char_dump(); -extern void quest_god_enter_dungeon_hook(int d_idx); -extern void quest_god_describe(); diff --git a/src/tables.c b/src/tables.c index 3eea2d39..594c4f16 100644 --- a/src/tables.c +++ b/src/tables.c @@ -4317,6 +4317,31 @@ quest_type quest_init_tome[MAX_Q_IDX_INIT] = { -1, -1, -1, -1 }, quest_library_describe, }, + /* God quest */ + { + FALSE, + TRUE, + "God quest", + { + "", /* dynamic desc */ + }, + QUEST_STATUS_UNTAKEN, + -1, + NULL, + HOOK_TYPE_C, + quest_god_init_hook, + { 0 /* quests_given */, + 0 /* relics_found */, + 1 /* dun_mindepth */, + 4 /* dun_maxdepth */, + 0 /* dun_minplev */, + 0 /* relic_gen_tries */, + FALSE /* relic_generated */, + 1 /* dung_x */, + 1 /* dung_y */, + }, + quest_god_describe, + }, }; diff --git a/src/types.h b/src/types.h index 040a0149..027ce678 100644 --- a/src/types.h +++ b/src/types.h @@ -2254,7 +2254,7 @@ struct quest_type bool_ (*init)(int q); /* Function that takes care of generating hardcoded quests */ - s32b data[4]; /* Various datas used by the quests */ + s32b data[9]; /* Various datas used by the quests */ bool_ (*gen_desc)(FILE *fff); /* Function for generating description. */ }; -- cgit v1.2.3 From b92fe01dfebbfed138d0cec1ac23c608be881dfc Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 9 Apr 2012 15:37:46 +0200 Subject: Lua: God quests: Make more functions static --- src/q_god.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/q_god.c b/src/q_god.c index 0c90985a..ecc26d96 100644 --- a/src/q_god.c +++ b/src/q_god.c @@ -295,7 +295,7 @@ bool_ quest_god_describe(FILE *fff) return TRUE; } -void quest_god_place_rand_dung() +static void quest_god_place_rand_dung() { int x = -1, y = -1, tries; @@ -362,7 +362,7 @@ void quest_god_place_rand_dung() cquest_dung_y = y; } -void quest_god_generate_relic() +static void quest_god_generate_relic() { int tries = 1000, x = -1, y = -1; object_type relic; @@ -919,7 +919,7 @@ static bool_ quest_god_level_end_gen_hook(char *fmt) return FALSE; } -bool_ quest_god_player_level_hook(char *fmt) +static bool_ quest_god_player_level_hook(char *fmt) { s32b gained = get_next_arg(fmt); @@ -979,7 +979,7 @@ bool_ quest_god_player_level_hook(char *fmt) return FALSE; } -bool_ quest_god_get_hook(char *fmt) +static bool_ quest_god_get_hook(char *fmt) { s32b item; object_type *o_ptr = NULL; -- cgit v1.2.3 From 93e3dd939f24965125641ca4a08135a6e723c1a3 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 9 Apr 2012 15:41:46 +0200 Subject: Lua: Remove quests.lua and remove unnecessary dynamism for quests --- lib/core/init.lua | 1 - lib/core/quests.lua | 57 ------------------------------------------ lib/mods/theme/core/init.lua | 1 - lib/mods/theme/core/quests.lua | 57 ------------------------------------------ src/birth.c | 2 +- src/cmd4.c | 10 +++----- src/defines.h | 2 +- src/externs.h | 6 +---- src/files.c | 2 +- src/init1.c | 4 +-- src/init2.c | 26 ------------------- src/loadsave.c | 10 ++++---- src/lua_bind.c | 15 ----------- src/plots.c | 2 +- src/quest.pkg | 34 +++---------------------- src/tables.c | 2 +- src/variable.c | 3 +-- src/wild.c | 8 ++++-- src/wizard2.c | 2 +- 19 files changed, 27 insertions(+), 217 deletions(-) delete mode 100644 lib/core/quests.lua delete mode 100644 lib/mods/theme/core/quests.lua diff --git a/lib/core/init.lua b/lib/core/init.lua index 9d0c01a3..d294adb4 100644 --- a/lib/core/init.lua +++ b/lib/core/init.lua @@ -17,7 +17,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "building.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "s_aux.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "quests.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "gods.lua") -- Load the ingame contextual help diff --git a/lib/core/quests.lua b/lib/core/quests.lua deleted file mode 100644 index dfe9db51..00000000 --- a/lib/core/quests.lua +++ /dev/null @@ -1,57 +0,0 @@ --- Quest helper files - --- Quest structs - -__quest_hook = {} -__quest_callbacks = {} -__quest_callbacks_max = 0 -__quest_dynamic_desc = {} - -function add_quest(q) - local i, index, d, z, qq - - assert(q.global, "No quest global name") - assert(q.name, "No quest name") - assert(q.desc, "No quest desc") - assert(q.level, "No quest level") - assert(q.hooks, "No quest hooks") - - i = new_quest(q.name); - setglobal(q.global, i) - - -- Make it save & load - add_loadsave("quest("..q.global..").status", QUEST_STATUS_UNTAKEN) - - if type(q.desc) == "table" then - z = 0 - for index, d in q.desc do - quest_desc(i, z, d); - z = z + 1 - end - else - __quest_dynamic_desc[i] = q.desc - quest(i).dynamic_desc = TRUE - end - quest(i).level = q.level - if not q.silent then - quest(i).silent = FALSE - else - quest(i).silent = q.silent - end - __quest_hook[i] = q.hooks - for index, d in q.hooks do - add_hook_script(index, "__lua__quest_callback"..__quest_callbacks_max, "__lua__quest_callback"..__quest_callbacks_max) - setglobal("__lua__quest_callback"..__quest_callbacks_max, d) - __quest_callbacks_max = __quest_callbacks_max + 1 - end - if q.data then - for index, d in q.data do - -- Besure it exists - setglobal(index, d) - - -- Make it save & load - add_loadsave(index, d) - end - end - return i -end diff --git a/lib/mods/theme/core/init.lua b/lib/mods/theme/core/init.lua index 9d0c01a3..d294adb4 100644 --- a/lib/mods/theme/core/init.lua +++ b/lib/mods/theme/core/init.lua @@ -17,7 +17,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "building.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "s_aux.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "quests.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "gods.lua") -- Load the ingame contextual help diff --git a/lib/mods/theme/core/quests.lua b/lib/mods/theme/core/quests.lua deleted file mode 100644 index dfe9db51..00000000 --- a/lib/mods/theme/core/quests.lua +++ /dev/null @@ -1,57 +0,0 @@ --- Quest helper files - --- Quest structs - -__quest_hook = {} -__quest_callbacks = {} -__quest_callbacks_max = 0 -__quest_dynamic_desc = {} - -function add_quest(q) - local i, index, d, z, qq - - assert(q.global, "No quest global name") - assert(q.name, "No quest name") - assert(q.desc, "No quest desc") - assert(q.level, "No quest level") - assert(q.hooks, "No quest hooks") - - i = new_quest(q.name); - setglobal(q.global, i) - - -- Make it save & load - add_loadsave("quest("..q.global..").status", QUEST_STATUS_UNTAKEN) - - if type(q.desc) == "table" then - z = 0 - for index, d in q.desc do - quest_desc(i, z, d); - z = z + 1 - end - else - __quest_dynamic_desc[i] = q.desc - quest(i).dynamic_desc = TRUE - end - quest(i).level = q.level - if not q.silent then - quest(i).silent = FALSE - else - quest(i).silent = q.silent - end - __quest_hook[i] = q.hooks - for index, d in q.hooks do - add_hook_script(index, "__lua__quest_callback"..__quest_callbacks_max, "__lua__quest_callback"..__quest_callbacks_max) - setglobal("__lua__quest_callback"..__quest_callbacks_max, d) - __quest_callbacks_max = __quest_callbacks_max + 1 - end - if q.data then - for index, d in q.data do - -- Besure it exists - setglobal(index, d) - - -- Make it save & load - add_loadsave(index, d) - end - end - return i -end diff --git a/src/birth.c b/src/birth.c index 75ff1ed2..243f080e 100644 --- a/src/birth.c +++ b/src/birth.c @@ -858,7 +858,7 @@ static void player_wipe(void) } /* Wipe the quests */ - for (i = 0; i < MAX_Q_IDX_INIT; i++) + for (i = 0; i < MAX_Q_IDX; i++) { quest[i].status = QUEST_STATUS_UNTAKEN; for (j = 0; j < sizeof(quest[i].data)/sizeof(quest[i].data[0]); j++) diff --git a/src/cmd4.c b/src/cmd4.c index 29d01c73..af98b0ed 100644 --- a/src/cmd4.c +++ b/src/cmd4.c @@ -4127,7 +4127,7 @@ static void do_cmd_knowledge_quests(void) char file_name[1024]; - int *order; + int order[MAX_Q_IDX] = { }; int num = 0; @@ -4140,14 +4140,12 @@ static void do_cmd_knowledge_quests(void) /* Open a new file */ fff = my_fopen(file_name, "w"); - C_MAKE(order, max_q_idx, int); - - for (i = 0; i < max_q_idx; i++) + for (i = 0; i < MAX_Q_IDX; i++) { insert_sort_quest(order, &num, i); } - for (z = 0; z < max_q_idx; z++) + for (z = 0; z < MAX_Q_IDX; z++) { i = order[z]; @@ -4194,8 +4192,6 @@ static void do_cmd_knowledge_quests(void) } } - C_FREE(order, max_q_idx, int); - /* Close the file */ my_fclose(fff); diff --git a/src/defines.h b/src/defines.h index abdd4a90..93b6e9a6 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4422,7 +4422,7 @@ #define QUEST_FIREPROOF 27 #define QUEST_LIBRARY 28 #define QUEST_GOD 29 -#define MAX_Q_IDX_INIT 30 +#define MAX_Q_IDX 30 #define PLOT_MAIN 0 #define PLOT_BREE 1 diff --git a/src/externs.h b/src/externs.h index 4ab14bfd..bb92e921 100644 --- a/src/externs.h +++ b/src/externs.h @@ -85,7 +85,6 @@ extern inscription_info_type inscription_info[MAX_INSCRIPTIONS]; extern cptr sense_desc[]; extern flags_group flags_groups[MAX_FLAG_GROUP]; extern power_type powers_type[POWER_MAX]; -extern quest_type quest_info[MAX_Q_IDX_INIT]; extern cptr artifact_names_list; extern monster_power monster_powers[96]; extern tval_desc tval_descs[]; @@ -94,7 +93,7 @@ extern int month_day[9]; extern cptr month_name[9]; extern cli_comm *cli_info; extern int cli_total; -extern quest_type quest_init_tome[MAX_Q_IDX_INIT]; +extern quest_type quest[MAX_Q_IDX]; extern int max_body_part[BODY_MAX]; extern gf_name_type gf_names[]; extern module_type modules[MAX_MODULES]; @@ -565,8 +564,6 @@ extern birther previous_char; extern hist_type *bg; extern int max_bg_idx; extern s32b extra_savefile_parts; -extern s16b max_q_idx; -extern quest_type *quest; extern bool_ player_char_health; extern s16b max_spells; extern spell_type *school_spells; @@ -1798,7 +1795,6 @@ extern void find_position(int y, int x, int *yy, int *xx); extern bool_ summon_lua_okay(int r_idx); extern bool_ lua_summon_monster(int y, int x, int lev, bool_ ffriend, char *fct); -extern s16b add_new_quest(char *name); extern void desc_quest(int q_idx, int d, char *desc); extern s16b add_new_gods(char *name); diff --git a/src/files.c b/src/files.c index c52beef9..f860e809 100644 --- a/src/files.c +++ b/src/files.c @@ -4329,7 +4329,7 @@ long total_points(void) temp += p_ptr->au / 5; /* Completing quest increase score */ - for (i = 0; i < max_q_idx; i++) + for (i = 0; i < MAX_Q_IDX; i++) { if (quest[i].status >= QUEST_STATUS_COMPLETED) { diff --git a/src/init1.c b/src/init1.c index 4c7e7035..43d9690f 100644 --- a/src/init1.c +++ b/src/init1.c @@ -10812,7 +10812,7 @@ static errr process_dungeon_file_aux(char *buf, int *yval, int *xval, int xvalst i = strlen(zz[8]) - 1; if (zz[8][i] == '"') zz[8][i] = '\0'; letter[index].special = 0; - for (i = 0; i < max_q_idx; i++) + for (i = 0; i < MAX_Q_IDX; i++) { if (!strcmp(&zz[8][1], quest[i].name)) { @@ -11659,7 +11659,7 @@ static cptr process_dungeon_file_expr(char **sp, char *fp) for (i = 0; (c[i] != '"') && (c[i] != '\0'); i++); if (c[i] == '"') c[i] = '\0'; strcpy(pref_tmp_value, "-1"); - for (i = 0; i < max_q_idx; i++) + for (i = 0; i < MAX_Q_IDX; i++) { if (streq(c, quest[i].name)) { diff --git a/src/init2.c b/src/init2.c index 8a20cfb3..1f6e66e6 100644 --- a/src/init2.c +++ b/src/init2.c @@ -1959,13 +1959,6 @@ static errr init_misc(void) /* Hack -- No messages yet */ message__tail = MESSAGE_BUF; - /* Prepare quests */ - quest = NULL; - max_q_idx = MAX_Q_IDX_INIT; - reinit_quests(max_q_idx); - - C_COPY(quest, quest_init_tome, MAX_Q_IDX_INIT, quest_type); - /* Prepare gods */ deity_info = NULL; max_gods = MAX_GODS_INIT; @@ -2073,25 +2066,6 @@ static errr init_wilderness(void) return 0; } -void reinit_quests(s16b new_size) -{ - quest_type *new_quest; - - C_MAKE(new_quest, new_size, quest_type); - - /* Reallocate the extra memory */ - if (quest) - { - C_COPY(new_quest, quest, max_q_idx, quest_type); - - C_FREE(quest, max_q_idx, quest_type); - } - - quest = new_quest; - - max_q_idx = new_size; -} - void reinit_gods(s16b new_size) { deity_type *new_deity; diff --git a/src/loadsave.c b/src/loadsave.c index fe89a451..1787670b 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -2689,18 +2689,18 @@ static bool_ do_savefile_aux(int flag) do_s16b(&(d_info[i].t_num), flag); } - if (flag == LS_SAVE) max_quests_ldsv = MAX_Q_IDX_INIT; - /* Number of quests */ + /* Sanity check number of quests */ + if (flag == LS_SAVE) max_quests_ldsv = MAX_Q_IDX; do_u16b(&max_quests_ldsv, flag); /* Incompatible save files */ - if ((flag == LS_LOAD) && (max_quests_ldsv > MAX_Q_IDX_INIT)) + if ((flag == LS_LOAD) && (max_quests_ldsv != MAX_Q_IDX)) { - note(format("Too many (%u) quests!", max_quests_ldsv)); + note(format("Invalid number of quests (%u)!", max_quests_ldsv)); return (FALSE); } - for (i = 0; i < max_quests_ldsv; i++) + for (i = 0; i < MAX_Q_IDX; i++) { do_s16b(&quest[i].status, flag); for (j = 0; j < sizeof(quest[i].data)/sizeof(quest[i].data[0]); j++) diff --git a/src/lua_bind.c b/src/lua_bind.c index a9e1b476..ce49a06e 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -154,21 +154,6 @@ bool_ lua_summon_monster(int y, int x, int lev, bool_ friend_, char *fct) /* * Quests */ -s16b add_new_quest(char *name) -{ - int i; - - /* Increase the size */ - reinit_quests(max_q_idx + 1); - quest[max_q_idx - 1].type = HOOK_TYPE_LUA; - strncpy(quest[max_q_idx - 1].name, name, 39); - - for (i = 0; i < 10; i++) - strncpy(quest[max_q_idx - 1].desc[i], "", 39); - - return (max_q_idx - 1); -} - void desc_quest(int q_idx, int d, char *desc) { if (d >= 0 && d < 10) diff --git a/src/plots.c b/src/plots.c index 08d0ea90..e16cbe2a 100644 --- a/src/plots.c +++ b/src/plots.c @@ -40,7 +40,7 @@ void init_hooks() { int i; - for (i = 0; i < MAX_Q_IDX_INIT; i++) + for (i = 0; i < MAX_Q_IDX; i++) { if ((quest[i].type == HOOK_TYPE_C) && (quest[i].init != NULL)) quest[i].init(i); } diff --git a/src/quest.pkg b/src/quest.pkg index 487c62af..f9b3fe7e 100644 --- a/src/quest.pkg +++ b/src/quest.pkg @@ -76,6 +76,8 @@ typedef unsigned int u32b; #define QUEST_STATUS_FAILED_DONE 6 /** @} */ +#define MAX_Q_IDX 30 + /** @struct quest_type * @brief Quest */ @@ -112,17 +114,11 @@ struct quest_type byte type; }; -/** @var max_q_idx - * @brief Number - * @note Maximum number of quests in quest list - */ -extern s16b max_q_idx; - /** @var quest_aux; * @brief quest_type * @note Array of quests */ -extern quest_type quest[max_q_idx] @ quest_aux; +extern quest_type quest[MAX_Q_IDX] @ quest_aux; $static quest_type *lua_get_quest(int q_idx){return &quest[q_idx];} @@ -135,27 +131,3 @@ $static quest_type *lua_get_quest(int q_idx){return &quest[q_idx];} */ static quest_type *lua_get_quest @ quest(int q_idx); -/** @fn new_quest(char *name); - * @dgonly - * @brief Add a new quest to the end of the quest array.\n - * @param *name String \n the name of the new quest. - * @brief Quest name - * @return Number \n The index of the new quest in the quest array. - * @note (see file lua_bind.c) - */ -extern s16b add_new_quest @ new_quest(char *name); - -/** @fn quest_desc(int q_idx, int d, char *desc); - * @dgonly - * @brief Return the description of a quest.\n - * @param q_idx Number \n the index of a quest in the quest array. - * @brief Quest index - * @param d Number \n the index of a line in the quest description. - * @brief Description line - * @param *desc String - * @brief Description - * @return *desc String \n Line "d" of the description of quest with index - * "q_idx" in the quest array. - * @note (see file lua_bind.c) - */ -extern void desc_quest @ quest_desc(int q_idx, int d, char *desc); diff --git a/src/tables.c b/src/tables.c index 594c4f16..9b77d07b 100644 --- a/src/tables.c +++ b/src/tables.c @@ -3597,7 +3597,7 @@ power_type powers_type[POWER_MAX] = /* * The Quests */ -quest_type quest_init_tome[MAX_Q_IDX_INIT] = +quest_type quest[MAX_Q_IDX] = { { FALSE, diff --git a/src/variable.c b/src/variable.c index c3530df8..c09d9720 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1487,8 +1487,7 @@ s32b extra_savefile_parts = 0; /* * Quests */ -s16b max_q_idx = MAX_Q_IDX_INIT; -quest_type *quest; +quest_type quest[MAX_Q_IDX]; /* * Display the player as a special symbol when in bad health ? diff --git a/src/wild.c b/src/wild.c index 7a9d1c51..279b79d9 100644 --- a/src/wild.c +++ b/src/wild.c @@ -525,10 +525,12 @@ void wilderness_gen(int refresh) } /* Set rewarded quests to finished */ - for (i = 0; i < max_q_idx; i++) + for (i = 0; i < MAX_Q_IDX; i++) { if (quest[i].status == QUEST_STATUS_REWARDED) + { quest[i].status = QUEST_STATUS_FINISHED; + } } process_hooks(HOOK_WILD_GEN, "(d)", FALSE); @@ -591,10 +593,12 @@ void wilderness_gen_small() p_ptr->py = p_ptr->wilderness_y; /* Set rewarded quests to finished */ - for (i = 0; i < max_q_idx; i++) + for (i = 0; i < MAX_Q_IDX; i++) { if (quest[i].status == QUEST_STATUS_REWARDED) + { quest[i].status = QUEST_STATUS_FINISHED; + } } process_hooks(HOOK_WILD_GEN, "(d)", TRUE); diff --git a/src/wizard2.c b/src/wizard2.c index 5e1e38d1..6f691171 100644 --- a/src/wizard2.c +++ b/src/wizard2.c @@ -1795,7 +1795,7 @@ void do_cmd_debug(void) case 'q': { /* if (quest[command_arg].status == QUEST_STATUS_UNTAKEN)*/ - if ((command_arg >= 1) && (command_arg < MAX_Q_IDX_INIT) && (command_arg != QUEST_RANDOM)) + if ((command_arg >= 1) && (command_arg < MAX_Q_IDX) && (command_arg != QUEST_RANDOM)) { quest[command_arg].status = QUEST_STATUS_TAKEN; *(quest[command_arg].plot) = command_arg; -- cgit v1.2.3 From 6ec947a8fc5b4aeb6ee54948b9b1a9ced583f8ba Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 9 Apr 2012 16:24:03 +0200 Subject: Lua: Remove quest_type "type" field. --- src/bldg.c | 2 +- src/cmd4.c | 14 ++------------ src/loadsave.c | 5 ++++- src/plots.c | 5 ++++- src/quest.pkg | 6 ------ src/tables.c | 30 ------------------------------ src/types.h | 2 -- src/wizard2.c | 2 +- 8 files changed, 12 insertions(+), 54 deletions(-) diff --git a/src/bldg.c b/src/bldg.c index bf284a7a..e35cc023 100644 --- a/src/bldg.c +++ b/src/bldg.c @@ -869,7 +869,7 @@ static bool_ castle_quest(int y, int x) get_questinfo(plots[plot]); /* Add the hooks */ - if (quest[plots[plot]].type == HOOK_TYPE_C) quest[plots[plot]].init(plots[plot]); + quest[plots[plot]].init(plots[plot]); return (TRUE); } diff --git a/src/cmd4.c b/src/cmd4.c index af98b0ed..2bc7b7e8 100644 --- a/src/cmd4.c +++ b/src/cmd4.c @@ -4152,19 +4152,9 @@ static void do_cmd_knowledge_quests(void) /* Dynamic quests */ if (quest[i].dynamic_desc) { - /* C type quests */ - if (quest[i].type == HOOK_TYPE_C) + if (!quest[i].gen_desc(fff)) { - if (!quest[i].gen_desc(fff)) - { - continue; - } - } - /* MUST be a lua quest */ - else - { - hook_file = fff; - exec_lua(format("__quest_dynamic_desc[%d]()", i)); + continue; } } diff --git a/src/loadsave.c b/src/loadsave.c index 1787670b..eddac55b 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -2709,7 +2709,10 @@ static bool_ do_savefile_aux(int flag) } /* Init the hooks */ - if ((flag == LS_LOAD) && (quest[i].type == HOOK_TYPE_C)) quest[i].init(i); + if (flag == LS_LOAD) + { + quest[i].init(i); + } } /* Position in the wilderness */ diff --git a/src/plots.c b/src/plots.c index e16cbe2a..6015420a 100644 --- a/src/plots.c +++ b/src/plots.c @@ -42,7 +42,10 @@ void init_hooks() for (i = 0; i < MAX_Q_IDX; i++) { - if ((quest[i].type == HOOK_TYPE_C) && (quest[i].init != NULL)) quest[i].init(i); + if (quest[i].init != NULL) + { + quest[i].init(i); + } } } diff --git a/src/quest.pkg b/src/quest.pkg index f9b3fe7e..5021659e 100644 --- a/src/quest.pkg +++ b/src/quest.pkg @@ -106,12 +106,6 @@ struct quest_type * @note Dungeon level */ s16b level; - - /** @structvar type - * @brief Number - * @note Lua or C ? - */ - byte type; }; /** @var quest_aux; diff --git a/src/tables.c b/src/tables.c index 9b77d07b..a3470ede 100644 --- a/src/tables.c +++ b/src/tables.c @@ -3619,7 +3619,6 @@ quest_type quest[MAX_Q_IDX] = 0, NULL, - HOOK_TYPE_C, quest_null_hook, {0, 0}, NULL, @@ -3644,7 +3643,6 @@ quest_type quest[MAX_Q_IDX] = 70, &plots[PLOT_MAIN], - HOOK_TYPE_C, quest_necro_init_hook, {0, 0}, NULL, @@ -3669,7 +3667,6 @@ quest_type quest[MAX_Q_IDX] = 99, &plots[PLOT_MAIN], - HOOK_TYPE_C, quest_sauron_init_hook, {0, 0}, NULL, @@ -3694,7 +3691,6 @@ quest_type quest[MAX_Q_IDX] = 100, &plots[PLOT_MAIN], - HOOK_TYPE_C, quest_morgoth_init_hook, {0, 0}, NULL, @@ -3721,7 +3717,6 @@ quest_type quest[MAX_Q_IDX] = 5, &plots[PLOT_BREE], - HOOK_TYPE_C, quest_thieves_init_hook, {0, 0}, NULL, @@ -3747,7 +3742,6 @@ quest_type quest[MAX_Q_IDX] = 5, NULL, - HOOK_TYPE_C, quest_random_init_hook, {0, 0}, quest_random_describe, @@ -3773,7 +3767,6 @@ quest_type quest[MAX_Q_IDX] = 25, &plots[PLOT_OTHER], - HOOK_TYPE_C, quest_hobbit_init_hook, {0, 0}, NULL, @@ -3799,7 +3792,6 @@ quest_type quest[MAX_Q_IDX] = 40, &plots[PLOT_BREE], - HOOK_TYPE_C, quest_nazgul_init_hook, {0, 0}, NULL, @@ -3825,7 +3817,6 @@ quest_type quest[MAX_Q_IDX] = 30, &plots[PLOT_BREE], - HOOK_TYPE_C, quest_troll_init_hook, {FALSE, 0}, NULL, @@ -3851,7 +3842,6 @@ quest_type quest[MAX_Q_IDX] = 30, &plots[PLOT_BREE], - HOOK_TYPE_C, quest_wight_init_hook, {FALSE, 0}, NULL, @@ -3878,7 +3868,6 @@ quest_type quest[MAX_Q_IDX] = 25, &plots[PLOT_LORIEN], - HOOK_TYPE_C, quest_spider_init_hook, {0, 0}, NULL, @@ -3903,7 +3892,6 @@ quest_type quest[MAX_Q_IDX] = 30, &plots[PLOT_LORIEN], - HOOK_TYPE_C, quest_poison_init_hook, {0, 0}, NULL, @@ -3929,7 +3917,6 @@ quest_type quest[MAX_Q_IDX] = 20, &plots[PLOT_OTHER], - HOOK_TYPE_C, quest_narsil_init_hook, {0, 0}, NULL, @@ -3955,7 +3942,6 @@ quest_type quest[MAX_Q_IDX] = 30, &plots[PLOT_GONDOLIN], - HOOK_TYPE_C, quest_eol_init_hook, {0, 0}, NULL, @@ -3980,7 +3966,6 @@ quest_type quest[MAX_Q_IDX] = 37, &plots[PLOT_GONDOLIN], - HOOK_TYPE_C, quest_nirnaeth_init_hook, {0, 0}, NULL, @@ -4005,7 +3990,6 @@ quest_type quest[MAX_Q_IDX] = 80, &plots[PLOT_GONDOLIN], - HOOK_TYPE_C, quest_invasion_init_hook, {0, 0}, NULL, @@ -4031,7 +4015,6 @@ quest_type quest[MAX_Q_IDX] = 80, &plots[PLOT_MINAS], - HOOK_TYPE_C, quest_between_init_hook, {0, 0}, NULL, @@ -4056,7 +4039,6 @@ quest_type quest[MAX_Q_IDX] = 99, &plots[PLOT_MAIN], - HOOK_TYPE_C, quest_one_init_hook, {0, 0}, NULL, @@ -4082,7 +4064,6 @@ quest_type quest[MAX_Q_IDX] = 3, &plots[PLOT_OTHER], - HOOK_TYPE_C, quest_shroom_init_hook, {0, 0}, NULL, @@ -4108,7 +4089,6 @@ quest_type quest[MAX_Q_IDX] = 60, &plots[PLOT_OTHER], - HOOK_TYPE_C, quest_thrain_init_hook, {0, 0}, NULL, @@ -4135,7 +4115,6 @@ quest_type quest[MAX_Q_IDX] = 150, &plots[PLOT_MAIN], - HOOK_TYPE_C, quest_ultra_good_init_hook, {0, 0}, NULL, @@ -4160,7 +4139,6 @@ quest_type quest[MAX_Q_IDX] = 150, &plots[PLOT_MAIN], - HOOK_TYPE_C, quest_ultra_evil_init_hook, {0, 0}, NULL, @@ -4186,7 +4164,6 @@ quest_type quest[MAX_Q_IDX] = 15, &plots[PLOT_LORIEN], - HOOK_TYPE_C, quest_wolves_init_hook, {0, 0}, NULL, @@ -4212,7 +4189,6 @@ quest_type quest[MAX_Q_IDX] = 25, &plots[PLOT_GONDOLIN], - HOOK_TYPE_C, quest_dragons_init_hook, {0, 0}, NULL, @@ -4238,7 +4214,6 @@ quest_type quest[MAX_Q_IDX] = 45, &plots[PLOT_MINAS], - HOOK_TYPE_C, quest_haunted_init_hook, {0, 0}, NULL, @@ -4264,7 +4239,6 @@ quest_type quest[MAX_Q_IDX] = 60, &plots[PLOT_KHAZAD], - HOOK_TYPE_C, quest_evil_init_hook, {0, 0}, NULL, @@ -4280,7 +4254,6 @@ quest_type quest[MAX_Q_IDX] = QUEST_STATUS_UNTAKEN, -1, NULL, - HOOK_TYPE_C, quest_bounty_init_hook, {0, 0, 0, 0}, quest_bounty_describe, @@ -4296,7 +4269,6 @@ quest_type quest[MAX_Q_IDX] = QUEST_STATUS_UNTAKEN, 20, NULL, - HOOK_TYPE_C, quest_fireproof_init_hook, {0, 0, 0, 0}, quest_fireproof_describe, @@ -4312,7 +4284,6 @@ quest_type quest[MAX_Q_IDX] = QUEST_STATUS_UNTAKEN, 35, NULL, - HOOK_TYPE_C, quest_library_init_hook, { -1, -1, -1, -1 }, quest_library_describe, @@ -4328,7 +4299,6 @@ quest_type quest[MAX_Q_IDX] = QUEST_STATUS_UNTAKEN, -1, NULL, - HOOK_TYPE_C, quest_god_init_hook, { 0 /* quests_given */, 0 /* relics_found */, diff --git a/src/types.h b/src/types.h index 027ce678..c594f79b 100644 --- a/src/types.h +++ b/src/types.h @@ -2250,8 +2250,6 @@ struct quest_type s16b *plot; /* Which plot does it belongs to? */ - byte type; /* Lua or C ? */ - bool_ (*init)(int q); /* Function that takes care of generating hardcoded quests */ s32b data[9]; /* Various datas used by the quests */ diff --git a/src/wizard2.c b/src/wizard2.c index 6f691171..36efa148 100644 --- a/src/wizard2.c +++ b/src/wizard2.c @@ -1799,7 +1799,7 @@ void do_cmd_debug(void) { quest[command_arg].status = QUEST_STATUS_TAKEN; *(quest[command_arg].plot) = command_arg; - if (quest[command_arg].type == HOOK_TYPE_C) quest[command_arg].init(command_arg); + quest[command_arg].init(command_arg); break; } break; -- cgit v1.2.3 From 07a11792fc5f385130b36da44aa71c32cb96c514 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 9 Apr 2012 16:33:20 +0200 Subject: Remove unnecessary dynamic_desc field from quest_type --- src/cmd4.c | 4 ++-- src/quest.pkg | 6 ------ src/tables.c | 30 ------------------------------ src/types.h | 2 -- 4 files changed, 2 insertions(+), 40 deletions(-) diff --git a/src/cmd4.c b/src/cmd4.c index 2bc7b7e8..d0099360 100644 --- a/src/cmd4.c +++ b/src/cmd4.c @@ -4149,8 +4149,8 @@ static void do_cmd_knowledge_quests(void) { i = order[z]; - /* Dynamic quests */ - if (quest[i].dynamic_desc) + /* Dynamic descriptions */ + if (quest[i].gen_desc != NULL) { if (!quest[i].gen_desc(fff)) { diff --git a/src/quest.pkg b/src/quest.pkg index 5021659e..aed3569a 100644 --- a/src/quest.pkg +++ b/src/quest.pkg @@ -89,12 +89,6 @@ struct quest_type */ bool silent; - /** @structvar dynamic_desc - * @brief Boolean - * @note Do we need to ask a function to get the description ? - */ - bool dynamic_desc; - /** @structvar status * @brief Number * @note Is the quest taken, completed, finished? diff --git a/src/tables.c b/src/tables.c index a3470ede..18a9329a 100644 --- a/src/tables.c +++ b/src/tables.c @@ -3600,7 +3600,6 @@ power_type powers_type[POWER_MAX] = quest_type quest[MAX_Q_IDX] = { { - FALSE, FALSE, "", { @@ -3624,7 +3623,6 @@ quest_type quest[MAX_Q_IDX] = NULL, }, { - FALSE, FALSE, "Dol Guldur", { @@ -3648,7 +3646,6 @@ quest_type quest[MAX_Q_IDX] = NULL, }, { - FALSE, FALSE, "Sauron", { @@ -3672,7 +3669,6 @@ quest_type quest[MAX_Q_IDX] = NULL, }, { - FALSE, FALSE, "Morgoth", { @@ -3698,7 +3694,6 @@ quest_type quest[MAX_Q_IDX] = /* Bree plot */ { - FALSE, FALSE, "Thieves!", { @@ -3724,7 +3719,6 @@ quest_type quest[MAX_Q_IDX] = { FALSE, - TRUE, "Random Quest", { "", @@ -3748,7 +3742,6 @@ quest_type quest[MAX_Q_IDX] = }, { - FALSE, FALSE, "Lost Hobbit", { @@ -3773,7 +3766,6 @@ quest_type quest[MAX_Q_IDX] = }, { - FALSE, FALSE, "The Dark Horseman", { @@ -3798,7 +3790,6 @@ quest_type quest[MAX_Q_IDX] = }, { - FALSE, FALSE, "The Trolls Glade", { @@ -3823,7 +3814,6 @@ quest_type quest[MAX_Q_IDX] = }, { - FALSE, FALSE, "The Wight Grave", { @@ -3849,7 +3839,6 @@ quest_type quest[MAX_Q_IDX] = /* Lorien plot */ { - FALSE, FALSE, "Spiders of Mirkwood", { @@ -3873,7 +3862,6 @@ quest_type quest[MAX_Q_IDX] = NULL, }, { - FALSE, FALSE, "Poisoned Water", { @@ -3898,7 +3886,6 @@ quest_type quest[MAX_Q_IDX] = }, /* Other quests */ { - FALSE, FALSE, "The Broken Sword", { @@ -3923,7 +3910,6 @@ quest_type quest[MAX_Q_IDX] = }, /* Gondolin plot */ { - FALSE, FALSE, "Eol the Dark Elf", { @@ -3947,7 +3933,6 @@ quest_type quest[MAX_Q_IDX] = NULL, }, { - FALSE, FALSE, "Nirnaeth Arnoediad", { @@ -3971,7 +3956,6 @@ quest_type quest[MAX_Q_IDX] = NULL, }, { - FALSE, FALSE, "Invasion of Gondolin", { @@ -3996,7 +3980,6 @@ quest_type quest[MAX_Q_IDX] = }, /* Minas Anor Plot*/ { - FALSE, FALSE, "The Last Alliance", { @@ -4020,7 +4003,6 @@ quest_type quest[MAX_Q_IDX] = NULL, }, { - FALSE, FALSE, "The One Ring", { @@ -4045,7 +4027,6 @@ quest_type quest[MAX_Q_IDX] = }, { - FALSE, FALSE, "Mushroom supplies", { @@ -4070,7 +4051,6 @@ quest_type quest[MAX_Q_IDX] = }, { - FALSE, FALSE, "The prisoner of Dol Guldur", { @@ -4096,7 +4076,6 @@ quest_type quest[MAX_Q_IDX] = /* The 2 ultra endings go here */ { - FALSE, FALSE, "Falling Toward Apotheosis", { @@ -4120,7 +4099,6 @@ quest_type quest[MAX_Q_IDX] = NULL, }, { - FALSE, FALSE, "Falling Toward Apotheosis", { @@ -4145,7 +4123,6 @@ quest_type quest[MAX_Q_IDX] = }, /* More Lorien */ { - FALSE, FALSE, "Wolves!", { @@ -4170,7 +4147,6 @@ quest_type quest[MAX_Q_IDX] = }, /* More Gondolin */ { - FALSE, FALSE, "Dragons!", { @@ -4195,7 +4171,6 @@ quest_type quest[MAX_Q_IDX] = }, /* More Minas Anor */ { - FALSE, FALSE, "Haunted House!", { @@ -4220,7 +4195,6 @@ quest_type quest[MAX_Q_IDX] = }, /* Khazad-Dum Plot*/ { - FALSE, FALSE, "Evil!", { @@ -4246,7 +4220,6 @@ quest_type quest[MAX_Q_IDX] = /* Bounty */ { FALSE, - TRUE, "Bounty quest", { "", /* dynamic desc */ @@ -4261,7 +4234,6 @@ quest_type quest[MAX_Q_IDX] = /* Fireproofing */ { FALSE, - TRUE, "Old Mages quest", { "", /* dynamic desc */ @@ -4276,7 +4248,6 @@ quest_type quest[MAX_Q_IDX] = /* Library */ { FALSE, - TRUE, "Library quest", { "", /* dynamic desc */ @@ -4291,7 +4262,6 @@ quest_type quest[MAX_Q_IDX] = /* God quest */ { FALSE, - TRUE, "God quest", { "", /* dynamic desc */ diff --git a/src/types.h b/src/types.h index c594f79b..7b6019ae 100644 --- a/src/types.h +++ b/src/types.h @@ -2238,8 +2238,6 @@ struct quest_type { bool_ silent; - bool_ dynamic_desc; /* Do we need to ask a function to get the description ? */ - char name[40]; /* Quest name */ char desc[10][80]; /* Quest desc */ -- cgit v1.2.3 From d71c748f56b479ab97408fe2d42eaf0898982fb7 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 9 Apr 2012 20:52:39 +0200 Subject: Lua: Remove the need for script for Minas Tirith <-> Gondolin link --- lib/mods/theme/edit/t_minas.txt | 2 +- lib/mods/theme/scpt/gondolin.lua | 36 +++--------------------------------- src/defines.h | 2 +- src/tables.c | 8 ++++++++ 4 files changed, 13 insertions(+), 35 deletions(-) diff --git a/lib/mods/theme/edit/t_minas.txt b/lib/mods/theme/edit/t_minas.txt index b96481d8..cea53634 100644 --- a/lib/mods/theme/edit/t_minas.txt +++ b/lib/mods/theme/edit/t_minas.txt @@ -15,7 +15,7 @@ F:w:8:3:0:0:0:0:0:24 # Quest 16 finished, reward is a between gate ?:[EQU $QUEST16 5] -F:Z:176:3:0:0:0:0:0:0 +F:Z:176:3:0:0:0:0:0:2 ?:1 diff --git a/lib/mods/theme/scpt/gondolin.lua b/lib/mods/theme/scpt/gondolin.lua index c85d8f53..f70f2044 100644 --- a/lib/mods/theme/scpt/gondolin.lua +++ b/lib/mods/theme/scpt/gondolin.lua @@ -1,36 +1,6 @@ --- This script makes the void jumpgates between Minas Anor and Gondolin appear in Gondolin rather than in a weird wilderness spot --- as well as making the Save Gondolin quest take the player straight to Gondolin instead of the Secret Valley. --- Many thanks to TheFalcon for the code. - -function minas_gate() - if (quest(16).status == QUEST_STATUS_FINISHED) and (player.wilderness_y == 56) and (player.wilderness_x == 60) and (player.wild_mode == FALSE) then - cave(35,10).feat = 159 - end -end - -add_hook_script(HOOK_QUEST_FINISH, "minas_gate", "minas_gate") -add_hook_script(HOOK_WILD_GEN, "minas_gate", "minas_gate") - -function minas_jump(direction) - if (quest(16).status == QUEST_STATUS_FINISHED) and (player.wilderness_y == 56) and (player.wilderness_x == 60) and (player.wild_mode == FALSE) then - if (player.px == 10) and (player.py == 35) then - if (direction == "down") then - player.wilderness_x = 3 - player.wilderness_y = 11 - player.wild_mode = FALSE - player.px = 119 - player.py = 25 - player.oldpx = player.px - player.oldpy = player.py - dun_level = 0 - player.leaving = TRUE - return TRUE - end - end - end -end - -add_hook_script(HOOK_STAIR, "minas_jump", "minas_jump") +-- This script makes the Save Gondolin quest take the player straight +-- to Gondolin instead of the Secret Valley. Many thanks to TheFalcon +-- for the code. add_loadsave("tolan_count", 0) diff --git a/src/defines.h b/src/defines.h index 93b6e9a6..3fc34864 100644 --- a/src/defines.h +++ b/src/defines.h @@ -863,7 +863,7 @@ /* Features 0xCF - 0xFF -- unused */ -#define MAX_BETWEEN_EXITS 2 +#define MAX_BETWEEN_EXITS 3 /* * Number of effects diff --git a/src/tables.c b/src/tables.c index 18a9329a..c5a22204 100644 --- a/src/tables.c +++ b/src/tables.c @@ -4673,6 +4673,14 @@ between_exit between_exits[MAX_BETWEEN_EXITS] = 10, 35, 0, 0 }, + /* Theme: Minas Tirith -> Gondolin link */ + { + 0, + FALSE, + 3, 11, + 119, 25, + 0, 0 + }, }; /* -- cgit v1.2.3 From 293365ee62d199fc90c33eece8a8a3ffe6726d8a Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 9 Apr 2012 20:54:03 +0200 Subject: Lua: Remove Theme script forcing player to Gondolin at level 45 --- lib/mods/theme/scpt/gondolin.lua | 33 --------------------------------- lib/mods/theme/scpt/init.lua | 3 --- 2 files changed, 36 deletions(-) delete mode 100644 lib/mods/theme/scpt/gondolin.lua diff --git a/lib/mods/theme/scpt/gondolin.lua b/lib/mods/theme/scpt/gondolin.lua deleted file mode 100644 index f70f2044..00000000 --- a/lib/mods/theme/scpt/gondolin.lua +++ /dev/null @@ -1,33 +0,0 @@ --- This script makes the Save Gondolin quest take the player straight --- to Gondolin instead of the Secret Valley. Many thanks to TheFalcon --- for the code. - -add_loadsave("tolan_count", 0) - -function tolan_travel() - if (quest(15).status == QUEST_STATUS_TAKEN) and (tolan_count == 0) then - player.wilderness_x = 3 - player.wilderness_y = 11 - player.wild_mode = FALSE - player.px = 117 - player.py = 25 - player.oldpx = player.px - player.oldpy = player.py - dun_level = 0 - player.leaving = TRUE - tolan_count = 1 - return TRUE - end -end - -add_hook_script(HOOK_END_TURN, "tolan_travel", "tolan_travel") - -add_hooks -{ - [HOOK_BIRTH] = function() - if tolan_count >=1 - then tolan_count = 0 - else - end - end -} \ No newline at end of file diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index 6a509a27..93a6e772 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -39,6 +39,3 @@ tome_dofile("monsters.lua") -- Add miscellaneous stuff tome_dofile("misc.lua") - --- Add map-related quest fix -tome_dofile("gondolin.lua") \ No newline at end of file -- cgit v1.2.3 From c14f382bb54811eeeeef9df8d455e6b770acd795 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 9 Apr 2012 20:59:23 +0200 Subject: Lua: Remove quest.pkg --- src/CMakeLists.txt | 3 +- src/externs.h | 2 - src/lua_bind.c | 9 ---- src/quest.pkg | 121 ----------------------------------------------------- src/script.c | 2 - 5 files changed, 1 insertion(+), 136 deletions(-) delete mode 100644 src/quest.pkg diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a453e573..f8a0b24f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,7 +19,7 @@ SET(SRCS wizard2.c init2.c birth.c wizard1.c init1.c main.c # Lua bits: lua_bind.c script.c w_mnster.c w_player.c w_play_c.c w_z_pack.c - w_obj.c w_util.c w_spells.c w_quest.c w_dun.c + w_obj.c w_util.c w_spells.c w_dun.c ) # Need a few additional source files for Windows. @@ -58,7 +58,6 @@ TOLUA_FILE(z_pack w_z_pack.c) TOLUA_FILE(object w_obj.c) TOLUA_FILE(util w_util.c) TOLUA_FILE(spells w_spells.c) -TOLUA_FILE(quest w_quest.c) TOLUA_FILE(dungeon w_dun.c) # tome executable diff --git a/src/externs.h b/src/externs.h index bb92e921..6c13aa27 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1795,8 +1795,6 @@ extern void find_position(int y, int x, int *yy, int *xx); extern bool_ summon_lua_okay(int r_idx); extern bool_ lua_summon_monster(int y, int x, int lev, bool_ ffriend, char *fct); -extern void desc_quest(int q_idx, int d, char *desc); - extern s16b add_new_gods(char *name); extern void desc_god(int g_idx, int d, char *desc); extern int get_lua_int(cptr name); diff --git a/src/lua_bind.c b/src/lua_bind.c index ce49a06e..ff6680be 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -151,15 +151,6 @@ bool_ lua_summon_monster(int y, int x, int lev, bool_ friend_, char *fct) return summon_specific_friendly(y, x, lev, SUMMON_LUA, TRUE); } -/* - * Quests - */ -void desc_quest(int q_idx, int d, char *desc) -{ - if (d >= 0 && d < 10) - strncpy(quest[q_idx].desc[d], desc, 79); -} - /* * Misc */ diff --git a/src/quest.pkg b/src/quest.pkg deleted file mode 100644 index aed3569a..00000000 --- a/src/quest.pkg +++ /dev/null @@ -1,121 +0,0 @@ -/* File: quest.pkg */ - -/* - * Purpose: Lua interface definitions for quests. - * To be processed by tolua to generate C source code. - */ - -$#include "angband.h" - -/** @typedef cptr - * @note String - */ -typedef char* cptr; - -/** @typedef errr - * @note Number - */ -typedef int errr; - -/** @typedef bool - * @note Boolean - */ -typedef unsigned char bool; - -/** @typedef byte - * @note Number - */ -typedef unsigned char byte; - -/** @typedef s16b - * @note Number - */ -typedef signed short s16b; - -/** @typedef u16b - * @note Number - */ -typedef unsigned short u16b; - -/** @typedef s32b - * @note Number - */ -typedef signed int s32b; - -/** @typedef u32b - * @note Number - */ -typedef unsigned int u32b; - -/** @name Quest Status Flags - * @brief Quest status - * @{ */ - -/** @def QUEST_STATUS_IGNORED */ -#define QUEST_STATUS_IGNORED -1 - -/** @def QUEST_STATUS_UNTAKEN */ -#define QUEST_STATUS_UNTAKEN 0 - -/** @def QUEST_STATUS_TAKEN */ -#define QUEST_STATUS_TAKEN 1 - -/** @def QUEST_STATUS_COMPLETED */ -#define QUEST_STATUS_COMPLETED 2 - -/** @def QUEST_STATUS_REWARDED */ -#define QUEST_STATUS_REWARDED 3 - -/** @def QUEST_STATUS_FAILED */ -#define QUEST_STATUS_FAILED 4 - -/** @def QUEST_STATUS_FINISHED */ -#define QUEST_STATUS_FINISHED 5 - -/** @def QUEST_STATUS_FAILED_DONE */ -#define QUEST_STATUS_FAILED_DONE 6 -/** @} */ - -#define MAX_Q_IDX 30 - -/** @struct quest_type - * @brief Quest - */ -struct quest_type -{ - /** @structvar silent - * @brief Boolean - * @note Does quest appear on quest list? - */ - bool silent; - - /** @structvar status - * @brief Number - * @note Is the quest taken, completed, finished? - */ - s16b status; - - /** @structvar level - * @brief Number - * @note Dungeon level - */ - s16b level; -}; - -/** @var quest_aux; - * @brief quest_type - * @note Array of quests - */ -extern quest_type quest[MAX_Q_IDX] @ quest_aux; - -$static quest_type *lua_get_quest(int q_idx){return &quest[q_idx];} - -/** @fn quest(int q_idx); - * @brief Return quest with index "q_idx" from quest array.\n - * @param q_idx Number \n the index of a quest in the quest array. - * @brief Quest index - * @return quest_type \n The quest at index "q_idx". - * @note (see file w_quest.c) - */ -static quest_type *lua_get_quest @ quest(int q_idx); - diff --git a/src/script.c b/src/script.c index a5aba3fb..c9979c17 100644 --- a/src/script.c +++ b/src/script.c @@ -24,7 +24,6 @@ int tolua_util_open (lua_State *L); int tolua_z_pack_open (lua_State *L); int tolua_object_open (lua_State *L); int tolua_spells_open (lua_State *L); -int tolua_quest_open (lua_State *L); int tolua_dungeon_open (lua_State *L); /* @@ -217,7 +216,6 @@ void init_lua() tolua_object_open(L); tolua_monster_open(L); tolua_spells_open(L); - tolua_quest_open(L); tolua_dungeon_open(L); } -- cgit v1.2.3 From 5180b7b60f69b9a4a7642328df3a292cadb9fd49 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 9 Apr 2012 22:55:21 +0200 Subject: Remove the now-unnecessary Secret Valley --- lib/mods/theme/edit/w_info.txt | 2 +- lib/mods/theme/edit/wf_info.txt | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/mods/theme/edit/w_info.txt b/lib/mods/theme/edit/w_info.txt index 18cf7a0f..6ca43cfd 100644 --- a/lib/mods/theme/edit/w_info.txt +++ b/lib/mods/theme/edit/w_info.txt @@ -14,7 +14,7 @@ W:D:XWWWWAAAAAW%AAAA========WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW W:D:XWWWWWWAAWAAAWW===========WWWWWWW...WWWWWWWWWW..........WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW.EEEEEEEEEEEX W:D:XWWWWWWWWWWWWWW==========..WWW....WWWWWWWW................WWWWGGGGWWWWWWWW......WWWWW.EEEEEEEEEEEEEEX W:D:XTM.MMMMWWWW===...====...........HHHH..................GGGGGGGWWWDWWWW.........WWWW.EEEEEEEEEEEEEEEEX -W:D:XT.2MMM=======.BB.=............HHHHHHHH..&&&&&...J..GGGGGGGGGGGGG.................tEEEEEtEEEEttEEEEEX +W:D:XT.2MMM=======.BB.=............HHHHHHHH..&&&&&......GGGGGGGGGGGGG.................tEEEEEtEEEEttEEEEEX ?:[EQU $TOWN_DESTROY2 1] W:M:0:1 W:D:XT.PMMM=======.BB.=............HHHHHHHH..&&&&&......GGGGGGGGGGGGG.................tEEEEEtEEEEttEEEEEX diff --git a/lib/mods/theme/edit/wf_info.txt b/lib/mods/theme/edit/wf_info.txt index acdba872..4b7f9991 100644 --- a/lib/mods/theme/edit/wf_info.txt +++ b/lib/mods/theme/edit/wf_info.txt @@ -301,12 +301,6 @@ D:Anduin, the great river W:35:0:0:227:3:~ X:187:227:187:84:84:227:84:84:222:227:84:84:227:84:84:227:88:94 -# Former location of Gondolin (to avoid silliness with Maeglin quest) -N:48:Secret Valley -D:the secret valley with directions to Gondolin -W:0:0:12:89:1:J -X:228:228:228:228:228:228:228:228:228:228:228:228:228:228:228:228:228:228 - ### New Towns ### # Beorn's Halls -- cgit v1.2.3 From 462adc54506f1555582a60eb35ca077317185f05 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 10 Apr 2012 19:25:00 +0200 Subject: Lua: Gods: Move Varda's HOOK_PROCESS_WORLD to C --- lib/mods/theme/scpt/gods_new.lua | 27 ----------------- src/dungeon.c | 64 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 27 deletions(-) diff --git a/lib/mods/theme/scpt/gods_new.lua b/lib/mods/theme/scpt/gods_new.lua index 0a3b7283..2c227a3f 100644 --- a/lib/mods/theme/scpt/gods_new.lua +++ b/lib/mods/theme/scpt/gods_new.lua @@ -141,33 +141,6 @@ GOD_VARDA = add_god }, ["hooks"] = { - [HOOK_PROCESS_WORLD] = function() - if (player.pgod == GOD_VARDA) then - GRACE_DELAY = GRACE_DELAY + 1 - - -- piety increase if in light - if (GRACE_DELAY >= 15) then - if band(cave(player.py, player.px).info, CAVE_GLOW) ~= 0 then - set_grace(player.grace + 2) - end - if ( - (get_race_name() == "Orc") or - (get_race_name() == "Troll") or - (get_race_name() == "Dragon") or - (get_race_name() == "Demon")) then - -- Varda hates evils - set_grace(player.grace - 2) - else - set_grace(player.grace - 1) - end - - if (player.praying == TRUE) then - set_grace(player.grace - 1) - end - GRACE_DELAY = 0 - end - end - end, [HOOK_CALC_LITE] = function() if (player.pgod == GOD_VARDA) then -- increase lite radius diff --git a/src/dungeon.c b/src/dungeon.c index bcd727ca..ddbd36bf 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -1061,6 +1061,67 @@ static void process_world_corruptions() } +/* + * Shim for accessing Lua variable. + */ +static bool_ grace_delay_trigger() +{ + int grace_delay = get_lua_int("GRACE_DELAY"); + int new_grace_delay = 1 + grace_delay; + exec_lua(format("GRACE_DELAY = %d", new_grace_delay)); + + if (new_grace_delay >= 15) + { + /* reset */ + exec_lua("GRACE_DELAY = 0"); + /* triggered */ + return TRUE; + } + else + { + /* not triggered */ + return FALSE; + } +} + +/* + * Hook for gods + */ +static void process_world_gods() +{ + const char *race_name = rp_ptr->title + rp_name; + + GOD(GOD_VARDA) + { + if (grace_delay_trigger()) + { + /* Piety increases if in light. */ + if (cave[p_ptr->py][p_ptr->px].info & CAVE_GLOW) + { + inc_piety(GOD_ALL, 2); + } + + if (streq(race_name, "Orc") || + streq(race_name, "Troll") || + streq(race_name, "Dragon") || + streq(race_name, "Demon")) + { + /* Varda hates evil races */ + inc_piety(GOD_ALL, -2); + } else { + /* ... and everyone slightly less */ + inc_piety(GOD_ALL, -1); + } + + /* Prayer uses piety */ + if (p_ptr->praying) + { + inc_piety(GOD_ALL, -1); + } + } + } +} + /* * Handle certain things once every 10 game turns * @@ -1110,6 +1171,9 @@ static void process_world(void) /* Handle corruptions */ process_world_corruptions(); + /* Handle gods */ + process_world_gods(); + /* Handle the player song */ check_music(); } -- cgit v1.2.3 From 2586acc8701593574b52922af7540d3efa83b5b9 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 10 Apr 2012 19:40:52 +0200 Subject: Lua: Gods: Move Ulmo's HOOK_PROCESS_WORLD to C --- lib/mods/theme/scpt/gods_new.lua | 39 ------------------------------------ src/dungeon.c | 43 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/lib/mods/theme/scpt/gods_new.lua b/lib/mods/theme/scpt/gods_new.lua index 2c227a3f..8f97441a 100644 --- a/lib/mods/theme/scpt/gods_new.lua +++ b/lib/mods/theme/scpt/gods_new.lua @@ -204,45 +204,6 @@ GOD_ULMO = add_god end end end, - [HOOK_PROCESS_WORLD] = function() - if (player.pgod == GOD_ULMO) then - GRACE_DELAY = GRACE_DELAY + 1 - if GRACE_DELAY >= 15 then - -- Ulmo likes the Edain (except Easterlings) - if - (get_race_name() == "Human") or - (get_race_name() == "Dunadan") or - (get_race_name() == "Druadan") or - (get_race_name() == "RohanKnight") then - set_grace(player.grace + 1) - - elseif ( - (get_race_name() == "Easterling") or - (get_race_name() == "Demon") or - (get_race_name() == "Orc")) then - -- hated races - set_grace(player.grace - 2) - else - set_grace(player.grace + 1) - end - - if (player.praying == TRUE) then - set_grace(player.grace - 1) - end - -- Search inventory for axe or hammer - Gain 1 point of grace for each hammer or axe - for i = 0, INVEN_TOTAL - 1 do - if ((player.inventory(i).tval) == TV_POLEARM) then - if ((player.inventory(i).sval) == SV_TRIDENT) then - set_grace(player.grace + 1) - end - end - end - - GRACE_DELAY = 0 - end - - end - end, }, } diff --git a/src/dungeon.c b/src/dungeon.c index ddbd36bf..fa9da194 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -1120,6 +1120,49 @@ static void process_world_gods() } } } + + GOD(GOD_ULMO) + { + if (grace_delay_trigger()) + { + int i; + /* Ulmo likes the Edain (except Easterlings) */ + if (streq(race_name, "Human") || + streq(race_name, "Dunadan") || + streq(race_name, "Druadan") || + streq(race_name, "RohanKnight")) + { + inc_piety(GOD_ALL, 2); + } + else if (streq(race_name, "Easterling") || + streq(race_name, "Demon") || + streq(race_name, "Orc")) + { + /* hated races */ + inc_piety(GOD_ALL, -2); + } + else + { + inc_piety(GOD_ALL, 1); + } + + if (p_ptr->praying) + { + inc_piety(GOD_ALL, -1); + } + + /* Gain 1 point for each trident in inventory */ + for (i = 0; i < INVEN_TOTAL; i++) + { + if ((p_ptr->inventory[i].tval == TV_POLEARM) && + (p_ptr->inventory[i].sval == SV_TRIDENT)) + { + inc_piety(GOD_ALL, 1); + } + } + } + } + } /* -- cgit v1.2.3 From 767d7864bbeff83c8ad2f70a86dd5b8445cdccc7 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 10 Apr 2012 19:59:22 +0200 Subject: Lua: Gods: Move Aule's HOOK_PROCESS_WORLD to C --- lib/mods/theme/scpt/gods_new.lua | 58 ---------------------------- src/dungeon.c | 81 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 58 deletions(-) diff --git a/lib/mods/theme/scpt/gods_new.lua b/lib/mods/theme/scpt/gods_new.lua index 8f97441a..8a5eecfa 100644 --- a/lib/mods/theme/scpt/gods_new.lua +++ b/lib/mods/theme/scpt/gods_new.lua @@ -2,17 +2,6 @@ add_loadsave("GRACE_DELAY",0) -function aule_stone_skin() -local type - if player.grace >= 10000 then - type = SHIELD_COUNTER - else - type = 0 - end - - set_shield(randint(10) + 10 + (player.grace / 100), 10 + (player.grace / 100), type, 2 + (player.grace / 200), 3 + (player.grace / 400)) -end - GOD_AULE = add_god { ["name"] = "Aule the Smith", @@ -22,53 +11,6 @@ GOD_AULE = add_god }, ["hooks"] = { - [HOOK_PROCESS_WORLD] = function() - if (player.pgod == GOD_AULE) then - GRACE_DELAY = GRACE_DELAY + 1 - if GRACE_DELAY >= 15 then - -- Aule likes Dwarves and Dark Elves (Eol's influence here) - if - (get_race_name() ~= "Dwarf") and - (get_race_name() ~= "Petty-dwarf") and - (get_race_name() ~= "Gnome") and - (get_race_name() ~= "Dark-Elf") then - set_grace(player.grace - 1) - end - - -- Search inventory for axe or hammer - Gain 1 point of grace for each hammer or axe - for i = 0, INVEN_TOTAL - 1 do - if ((player.inventory(i).tval) == TV_AXE) then - set_grace(player.grace + 1) - end - if ((player.inventory(i).tval) == TV_HAFTED) then - if (((player.inventory(i).sval) == SV_WAR_HAMMER) or ((player.inventory(i).sval) == SV_LUCERN_HAMMER) or ((player.inventory(i).sval) == SV_GREAT_HAMMER)) then - set_grace(player.grace + 1) - end - end - end - - if (player.praying == TRUE) then - set_grace(player.grace - 2) - - -- Chance of casting Stoneskin if praying - local chance - if (player.grace >= 50000) then - chance = 50000 - else - chance = 50000 - player.grace - end - - if (randint(100000) <= 100000 / chance) then - aule_stone_skin() - msg_print("Aule casts Stone Skin on you.") - end - - end - GRACE_DELAY = 0 - end - - end - end, [HOOK_SACRIFICE_GOD] = function() if (player.pgod == GOD_AULE) then local ret, item, obj, value diff --git a/src/dungeon.c b/src/dungeon.c index fa9da194..282def7e 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -1163,6 +1163,87 @@ static void process_world_gods() } } + GOD(GOD_AULE) + { + if (grace_delay_trigger()) + { + int i; + + /* Aule likes Dwarves and Dark Elves (Eol's + * influence here) */ + if (!(streq(race_name, "Dwarf") || + streq(race_name, "Petty-dwarf") || + streq(race_name, "Gnome") || + streq(race_name, "Dark-Elf"))) + { + inc_piety(GOD_ALL, -1); + } + + /* Search inventory for axe or hammer - Gain 1 + * point of grace for each hammer or axe */ + for (i = 0; i < INVEN_TOTAL; i++) + { + int tval = p_ptr->inventory[i].tval; + int sval = p_ptr->inventory[i].sval; + + switch (tval) + { + case TV_AXE: + inc_piety(GOD_ALL, 1); + break; + + case TV_HAFTED: + if ((sval == SV_WAR_HAMMER) || + (sval == SV_LUCERN_HAMMER) || + (sval == SV_GREAT_HAMMER)) + { + inc_piety(GOD_ALL, 1); + } + break; + } + } + + /* Praying may grant you a free stone skin + * once in a while */ + if (p_ptr->praying) + { + int chance; + s32b grace; + + inc_piety(GOD_ALL, -2); + grace = p_ptr->grace; /* shorthand */ + + chance = 1; + if (grace >= 50000) + { + chance = 50000; + } + else + { + chance = 50000 - grace; + } + + if (randint(100000) <= 100000 / chance) + { + s16b type = 0; + + if (grace >= 10000) + { + type = SHIELD_COUNTER; + } + + set_shield( + randint(10) + 10 + (grace / 100), + 10 + (grace / 100), + type, + 2 + (grace / 200), + 3 + (grace / 400)); + + msg_print("Aule casts Stone Skin on you."); + } + } + } + } } /* -- cgit v1.2.3 From 4904124f7669d16c28271c1b94bc78633c699723 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 10 Apr 2012 20:09:44 +0200 Subject: Lua: Gods: Move Mandos's HOOK_PROCESS_WORLD to C --- lib/mods/theme/scpt/gods_new.lua | 33 --------------------------------- src/dungeon.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 33 deletions(-) diff --git a/lib/mods/theme/scpt/gods_new.lua b/lib/mods/theme/scpt/gods_new.lua index 8a5eecfa..8ad9f1a0 100644 --- a/lib/mods/theme/scpt/gods_new.lua +++ b/lib/mods/theme/scpt/gods_new.lua @@ -158,39 +158,6 @@ GOD_MANDOS = add_god }, ["hooks"] = { - [HOOK_PROCESS_WORLD] = function() - if (player.pgod == GOD_MANDOS) then - GRACE_DELAY = GRACE_DELAY + 1 - if GRACE_DELAY >= 15 then - -- He loves astral beings - if (get_subrace_name() == "LostSoul") then - set_grace(player.grace + 1) - end - - -- He likes High Elves only, though, as races - if (get_race_name() ~= "High-Elf") then - set_grace(player.grace - 1) - end - end - -- piety increase if (condition) - if (GRACE_DELAY >= 15) then - if ( - (get_subrace_name() == "Vampire") or - (get_race_name() == "Demon")) then - -- hated races - set_grace(player.grace - 10) - else - set_grace(player.grace + 2) - end - -- he really doesn't like to be disturbed - if (player.praying == TRUE) then - set_grace(player.grace - 5) - end - GRACE_DELAY = 0 - end - - end - end, [HOOK_MONSTER_DEATH] = function(m_idx) if (player.pgod == GOD_MANDOS) then m_ptr = monster(m_idx) diff --git a/src/dungeon.c b/src/dungeon.c index 282def7e..db936b8a 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -1090,6 +1090,7 @@ static bool_ grace_delay_trigger() static void process_world_gods() { const char *race_name = rp_ptr->title + rp_name; + const char *subrace_name = rmp_ptr->title + rmp_name; GOD(GOD_VARDA) { @@ -1244,6 +1245,41 @@ static void process_world_gods() } } } + + GOD(GOD_MANDOS) + { + if (grace_delay_trigger()) + { + /* He loves astral beings */ + if (streq(subrace_name, "LostSoul")) + { + inc_piety(GOD_ALL, 1); + } + + /* He likes High Elves only, though, as races */ + if (!streq(race_name, "High-Elf")) + { + inc_piety(GOD_ALL, -1); + } + + /* Really hates vampires and demons */ + if (streq(subrace_name, "Vampire") || + streq(race_name, "Demon")) + { + inc_piety(GOD_ALL, -10); + } + else + { + inc_piety(GOD_ALL, 2); + } + /* he really doesn't like to be disturbed */ + if (p_ptr->praying) + { + inc_piety(GOD_ALL, -5); + } + } + } + } /* -- cgit v1.2.3 From b34352dcd834057993a5e4c146b5b61cca41da15 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 10 Apr 2012 20:17:39 +0200 Subject: Lua: Gods: Move GRACE_DELAY Lua variable to player_type struct --- lib/mods/theme/scpt/gods_new.lua | 2 -- lib/mods/theme/scpt/player.lua | 3 --- src/dungeon.c | 8 +++----- src/loadsave.c | 1 + src/types.h | 1 + 5 files changed, 5 insertions(+), 10 deletions(-) diff --git a/lib/mods/theme/scpt/gods_new.lua b/lib/mods/theme/scpt/gods_new.lua index 8ad9f1a0..b6ff3b04 100644 --- a/lib/mods/theme/scpt/gods_new.lua +++ b/lib/mods/theme/scpt/gods_new.lua @@ -1,7 +1,5 @@ -- This file contains all the new gods -add_loadsave("GRACE_DELAY",0) - GOD_AULE = add_god { ["name"] = "Aule the Smith", diff --git a/lib/mods/theme/scpt/player.lua b/lib/mods/theme/scpt/player.lua index 0e9faff6..e2920642 100644 --- a/lib/mods/theme/scpt/player.lua +++ b/lib/mods/theme/scpt/player.lua @@ -3,9 +3,6 @@ ------------------------------------------------------------------------------ function __birth_hook_objects() - -- Grace delay for adding piety - GRACE_DELAY = 0 - -- Start the undeads, as undeads with the corruptions if get_subrace_name() == "Vampire" then player_gain_corruption(CORRUPT_VAMPIRE_TEETH) diff --git a/src/dungeon.c b/src/dungeon.c index db936b8a..57aafb0b 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -1066,14 +1066,12 @@ static void process_world_corruptions() */ static bool_ grace_delay_trigger() { - int grace_delay = get_lua_int("GRACE_DELAY"); - int new_grace_delay = 1 + grace_delay; - exec_lua(format("GRACE_DELAY = %d", new_grace_delay)); + p_ptr->grace_delay++; - if (new_grace_delay >= 15) + if (p_ptr->grace_delay >= 15) { /* reset */ - exec_lua("GRACE_DELAY = 0"); + p_ptr->grace_delay = 0; /* triggered */ return TRUE; } diff --git a/src/loadsave.c b/src/loadsave.c index eddac55b..cb9156a9 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -458,6 +458,7 @@ static bool_ do_extra(int flag) /* Gods */ do_s32b(&p_ptr->grace, flag); + do_s32b(&p_ptr->grace_delay, flag); do_byte((byte*)&p_ptr->praying, flag); do_s16b(&p_ptr->melkor_sacrifice, flag); do_byte(&p_ptr->pgod, flag); diff --git a/src/types.h b/src/types.h index 7b6019ae..fc4f7356 100644 --- a/src/types.h +++ b/src/types.h @@ -1489,6 +1489,7 @@ struct player_type u16b csane_frac; /* Cur sanity frac */ s32b grace; /* Your God's appreciation factor. */ + s32b grace_delay; /* Delay factor for granting piety. */ byte pgod; /* Your God. */ bool_ praying; /* Praying to your god. */ s16b melkor_sacrifice; /* How much hp has been sacrified for damage */ -- cgit v1.2.3 From 2a7627098fd014fc7b835e67cf37a3b615dbf5c4 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 10 Apr 2012 20:58:10 +0200 Subject: Lua: Gods: Move Aule's HOOK_SACRIFICE_GOD to C --- lib/mods/theme/scpt/gods_new.lua | 33 -------------------------------- src/cmd2.c | 41 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 33 deletions(-) diff --git a/lib/mods/theme/scpt/gods_new.lua b/lib/mods/theme/scpt/gods_new.lua index b6ff3b04..61aba56b 100644 --- a/lib/mods/theme/scpt/gods_new.lua +++ b/lib/mods/theme/scpt/gods_new.lua @@ -9,39 +9,6 @@ GOD_AULE = add_god }, ["hooks"] = { - [HOOK_SACRIFICE_GOD] = function() - if (player.pgod == GOD_AULE) then - local ret, item, obj, value - ret, item = get_item( - "Sacrifice which item? ", - "You have nothing to sacrifice.", - USE_INVEN, - function(obj) - -- perhaps restrict this only to metal armour and weapons - if (obj.found == OBJ_FOUND_SELFMADE) then - return TRUE - end - return FALSE - end - ) - - -- Item selected - if ret == TRUE then - -- Increase piety by the value of the item / 10 - -- object_value is not available in Lua, therefore I used the - -- cost of the base item, without magical boni - obj = get_object(item) - -- value = object_value(obj)/10 - value = k_info[obj.k_idx + 1].cost/10 - - set_grace(player.grace + value) - - -- remove the object - inven_item_increase(item, -1) - inven_item_optimize(item) - end - end - end, [HOOK_MONSTER_DEATH] = function(m_idx) if (player.pgod == GOD_AULE) then m_ptr = monster(m_idx) diff --git a/src/cmd2.c b/src/cmd2.c index 2d05c125..c38e874c 100644 --- a/src/cmd2.c +++ b/src/cmd2.c @@ -4573,6 +4573,43 @@ static bool_ item_tester_hook_sacrifiable(object_type *o_ptr) return (FALSE); } +/* + * Is item eligible for sacrifice to Aule? + */ +static bool_ item_tester_hook_sacrifice_aule(object_type *o_ptr) +{ + /* perhaps restrict this only to metal armour and weapons */ + return (o_ptr->found == OBJ_FOUND_SELFMADE); +} + +/* + * Handle sacrifices to Aule + */ +static void do_cmd_sacrifice_aule() +{ + int item; + + item_tester_hook = item_tester_hook_sacrifice_aule; + if (!get_item(&item, + "Sacrifice which item? ", + "You have nothing to sacrifice.", + USE_INVEN)) + { + return; + } + + /* Increase piety by the value of the item / 10. */ + { + object_type *o_ptr = get_object(item); + s32b delta = object_value(o_ptr) / 10; + + inc_piety(GOD_ALL, delta); + } + + /* Destroy the object */ + inc_stack_size(item, -1); +} + /* * Handle sacrifices. * Grace is increased by value of sacrifice. @@ -4666,6 +4703,10 @@ void do_cmd_sacrifice(void) inc_stack_size(item, -1); } } + else if (p_ptr->pgod == GOD_AULE) + { + do_cmd_sacrifice_aule(); + } else { process_hooks(HOOK_SACRIFICE_GOD, "()", ""); -- cgit v1.2.3 From 7d12fa73c521994841f3339a363bc5748ea9cbc8 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 10 Apr 2012 21:02:45 +0200 Subject: Lua: Gods: Remove now-unused HOOK_SACRIFICE_GOD --- src/cmd2.c | 8 +++----- src/defines.h | 1 - src/util.pkg | 6 ------ 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/cmd2.c b/src/cmd2.c index c38e874c..8c602db3 100644 --- a/src/cmd2.c +++ b/src/cmd2.c @@ -4703,14 +4703,12 @@ void do_cmd_sacrifice(void) inc_stack_size(item, -1); } } - else if (p_ptr->pgod == GOD_AULE) + + GOD(GOD_AULE) { do_cmd_sacrifice_aule(); } - else - { - process_hooks(HOOK_SACRIFICE_GOD, "()", ""); - } + } } } diff --git a/src/defines.h b/src/defines.h index 3fc34864..2375c852 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4541,7 +4541,6 @@ #define HOOK_LOAD_END 61 #define HOOK_RECALL 62 #define HOOK_FOLLOW_GOD 63 -#define HOOK_SACRIFICE_GOD 64 #define HOOK_BODY_PARTS 65 #define HOOK_APPLY_MAGIC 66 #define HOOK_PLAYER_EXP 67 diff --git a/src/util.pkg b/src/util.pkg index de84ac11..f9c94966 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -724,12 +724,6 @@ typedef unsigned int u32b; */ #define HOOK_FOLLOW_GOD 63 -/** @def HOOK_SACRIFICE_GOD - * @brief Player sacrifices to a god. - * @note (see file cmd2.c) - */ -#define HOOK_SACRIFICE_GOD 64 - /** @def HOOK_BODY_PARTS * @brief Calculate which body parts the player has. * @note (see file xtra1.c) -- cgit v1.2.3 From f8d2b1c87281c1d48515f11b1ca2e98ef7aef827 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 10 Apr 2012 21:30:25 +0200 Subject: Lua: Gods: Move Aule's HOOK_MONSTER_DEATH to C --- lib/mods/theme/scpt/gods_new.lua | 27 ----------------- src/xtra2.c | 64 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 27 deletions(-) diff --git a/lib/mods/theme/scpt/gods_new.lua b/lib/mods/theme/scpt/gods_new.lua index 61aba56b..1256932a 100644 --- a/lib/mods/theme/scpt/gods_new.lua +++ b/lib/mods/theme/scpt/gods_new.lua @@ -9,33 +9,6 @@ GOD_AULE = add_god }, ["hooks"] = { - [HOOK_MONSTER_DEATH] = function(m_idx) - if (player.pgod == GOD_AULE) then - m_ptr = monster(m_idx) - if - (m_ptr.r_idx == test_monster_name("Petty-dwarf")) or - (m_ptr.r_idx == test_monster_name("Petty-dwarf mage")) or - (m_ptr.r_idx == test_monster_name("Dark dwarven warrior")) or - (m_ptr.r_idx == test_monster_name("Dark dwarven smith")) or - (m_ptr.r_idx == test_monster_name("Dark dwarven lord")) or - (m_ptr.r_idx == test_monster_name("Dark dwarven priest")) or - (m_ptr.r_idx == test_monster_name("Dwarven warrior")) then - -- Aule dislikes you killing dwarves - set_grace(player.grace - 20) - end - if - (m_ptr.r_idx == test_monster_name("Nar, the Dwarf")) or - (m_ptr.r_idx == test_monster_name("Naugladur, Lord of Nogrod")) or - (m_ptr.r_idx == test_monster_name("Telchar the Smith")) or - (m_ptr.r_idx == test_monster_name("Fundin Bluecloak")) or - (m_ptr.r_idx == test_monster_name("Khim, Son of Mim")) or - (m_ptr.r_idx == test_monster_name("Ibun, Son of Mim")) or - (m_ptr.r_idx == test_monster_name("Mim, Betrayer of Turin")) then - -- These uniques earn a bigger penalty - set_grace(player.grace - 500) - end - end - end, } } diff --git a/src/xtra2.c b/src/xtra2.c index 7fae3fbf..5a9d8cb6 100644 --- a/src/xtra2.c +++ b/src/xtra2.c @@ -2326,6 +2326,67 @@ void place_corpse(monster_type *m_ptr) } +/* + * Check if monster race is in a given list. The list + * must be NULL-terminated. + */ +static bool_ monster_race_in_list_p(monster_type *m_ptr, cptr races[]) +{ + int i=0; + for (i=0; races[i] != NULL; i++) + { + if (m_ptr->r_idx == test_monster_name(races[i])) { + return TRUE; + } + } + /* Not found */ + return FALSE; +} + +/* + * Handle the "death" of a monster (Gods) + */ +static void monster_death_gods(int m_idx, monster_type *m_ptr) +{ + if (p_ptr->pgod == GOD_AULE) + { + /* TODO: This should really be a racial flag + which can be added to the r_info file. */ + cptr DWARVES[] = { + "Petty-dwarf", + "Petty-dwarf mage", + "Dark dwarven warrior", + "Dark dwarven smith", + "Dark dwarven lord", + "Dark dwarven priest", + "Dwarven warrior", + NULL, + }; + cptr UNIQUE_DWARVES[] = { + "Nar, the Dwarf", + "Naugladur, Lord of Nogrod", + "Telchar the Smith", + "Fundin Bluecloak", + "Khim, Son of Mim", + "Ibun, Son of Mim", + "Mim, Betrayer of Turin", + NULL, + }; + + /* Aule dislikes the killing of dwarves */ + if (monster_race_in_list_p(m_ptr, DWARVES)) + { + inc_piety(GOD_ALL, -20); + } + + /* ... and UNIQUE dwarves */ + if (monster_race_in_list_p(m_ptr, UNIQUE_DWARVES)) + { + inc_piety(GOD_ALL, -500); + } + } +} + /* * Handle the "death" of a monster. * @@ -2369,6 +2430,9 @@ void monster_death(int m_idx) /* Process the appropriate hooks */ process_hooks(HOOK_MONSTER_DEATH, "(d)", m_idx); + /* Per-god processing */ + monster_death_gods(m_idx, m_ptr); + /* If companion dies, take note */ if (m_ptr->status == MSTATUS_COMPANION) p_ptr->companion_killed++; -- cgit v1.2.3 From ac2d8a787a2345333e83227e9ab83b281a75d645 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 10 Apr 2012 21:36:59 +0200 Subject: Lua: Gods: Move Ulmo's HOOK_MONSTER_DEATH to C --- lib/mods/theme/scpt/gods_new.lua | 45 --------------------------------- src/xtra2.c | 54 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 45 deletions(-) diff --git a/lib/mods/theme/scpt/gods_new.lua b/lib/mods/theme/scpt/gods_new.lua index 1256932a..1ce90ce4 100644 --- a/lib/mods/theme/scpt/gods_new.lua +++ b/lib/mods/theme/scpt/gods_new.lua @@ -39,51 +39,6 @@ GOD_ULMO = add_god }, ["hooks"] = { - [HOOK_MONSTER_DEATH] = function(m_idx) - if (player.pgod == GOD_ULMO) then - m_ptr = monster(m_idx) - if - (m_ptr.r_idx == test_monster_name("Swordfish")) or - (m_ptr.r_idx == test_monster_name("Barracuda")) or - (m_ptr.r_idx == test_monster_name("Globefish")) or - (m_ptr.r_idx == test_monster_name("Aquatic bear")) or - (m_ptr.r_idx == test_monster_name("Pike")) or - (m_ptr.r_idx == test_monster_name("Electric eel")) or - (m_ptr.r_idx == test_monster_name("Giant crayfish")) or - (m_ptr.r_idx == test_monster_name("Mermaid")) or - (m_ptr.r_idx == test_monster_name("Leviathan")) or - (m_ptr.r_idx == test_monster_name("Box jellyfish")) or - (m_ptr.r_idx == test_monster_name("Giant piranha")) or - (m_ptr.r_idx == test_monster_name("Piranha")) or - (m_ptr.r_idx == test_monster_name("Ocean naga")) or - (m_ptr.r_idx == test_monster_name("Whale")) or - (m_ptr.r_idx == test_monster_name("Octopus")) or - (m_ptr.r_idx == test_monster_name("Giant octopus")) or - (m_ptr.r_idx == test_monster_name("Drowned soul")) or - (m_ptr.r_idx == test_monster_name("Tiger shark")) or - (m_ptr.r_idx == test_monster_name("Hammerhead shark")) or - (m_ptr.r_idx == test_monster_name("Great white shark")) or - (m_ptr.r_idx == test_monster_name("White shark")) or - (m_ptr.r_idx == test_monster_name("Stargazer")) or - (m_ptr.r_idx == test_monster_name("Flounder")) or - (m_ptr.r_idx == test_monster_name("Giant turtle")) or - (m_ptr.r_idx == test_monster_name("Killer whale")) or - (m_ptr.r_idx == test_monster_name("Water naga")) or - (m_ptr.r_idx == test_monster_name("Behemoth")) then - -- He doesn't like it if you kill these monsters - set_grace(player.grace - 20) - end - if - (m_ptr.r_idx == test_monster_name("Seahorse")) or - (m_ptr.r_idx == test_monster_name("Aquatic elven warrior")) or - (m_ptr.r_idx == test_monster_name("Aquatic elven mage")) or - (m_ptr.r_idx == test_monster_name("Wavelord")) or - (m_ptr.r_idx == test_monster_name("The Watcher in the Water")) then - -- These monsters earn higher penalties - set_grace(player.grace - 500) - end - end - end, }, } diff --git a/src/xtra2.c b/src/xtra2.c index 5a9d8cb6..8d1f1867 100644 --- a/src/xtra2.c +++ b/src/xtra2.c @@ -2385,6 +2385,60 @@ static void monster_death_gods(int m_idx, monster_type *m_ptr) inc_piety(GOD_ALL, -500); } } + + if (p_ptr->pgod == GOD_ULMO) + { + /* He doesn't like it if you kill these monsters */ + cptr MINOR_RACES[] = { + "Swordfish", + "Barracuda", + "Globefish", + "Aquatic bear", + "Pike", + "Electric eel", + "Giant crayfish", + "Mermaid", + "Leviathan", + "Box jellyfish", + "Giant piranha", + "Piranha", + "Ocean naga", + "Whale", + "Octopus", + "Giant octopus", + "Drowned soul", + "Tiger shark", + "Hammerhead shark", + "Great white shark", + "White shark", + "Stargazer", + "Flounder", + "Giant turtle", + "Killer whale", + "Water naga", + "Behemoth", + NULL, + }; + /* These monsters earn higher penalties */ + cptr MAJOR_RACES[] = { + "Seahorse", + "Aquatic elven warrior", + "Aquatic elven mage", + "Wavelord", + "The Watcher in the Water", + NULL, + }; + + if (monster_race_in_list_p(m_ptr, MINOR_RACES)) + { + inc_piety(GOD_ALL, -20); + } + + if (monster_race_in_list_p(m_ptr, MAJOR_RACES)) + { + inc_piety(GOD_ALL, -500); + } + } } /* -- cgit v1.2.3 From bc2f31566512bc0c41aa3ab5b19ce3e907b6c0cf Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 10 Apr 2012 21:49:54 +0200 Subject: Lua: Gods: Move Mandos' HOOK_MONSTER_DEATH to C --- lib/mods/theme/scpt/gods_new.lua | 63 ---------------------------- src/xtra2.c | 88 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 63 deletions(-) diff --git a/lib/mods/theme/scpt/gods_new.lua b/lib/mods/theme/scpt/gods_new.lua index 1ce90ce4..3d01ec87 100644 --- a/lib/mods/theme/scpt/gods_new.lua +++ b/lib/mods/theme/scpt/gods_new.lua @@ -51,68 +51,5 @@ GOD_MANDOS = add_god }, ["hooks"] = { - [HOOK_MONSTER_DEATH] = function(m_idx) - if (player.pgod == GOD_MANDOS) then - m_ptr = monster(m_idx) - if - (m_ptr.r_idx == test_monster_name("Vampire")) or - (m_ptr.r_idx == test_monster_name("Master vampire")) or - (m_ptr.r_idx == test_monster_name("Oriental vampire")) or - (m_ptr.r_idx == test_monster_name("Vampire lord")) or - (m_ptr.r_idx == test_monster_name("Vampire orc")) or - (m_ptr.r_idx == test_monster_name("Vampire yeek")) or - (m_ptr.r_idx == test_monster_name("Vampire ogre")) or - (m_ptr.r_idx == test_monster_name("Vampire troll")) or - (m_ptr.r_idx == test_monster_name("Vampire dwarf")) or - (m_ptr.r_idx == test_monster_name("Vampire gnome")) or - (m_ptr.r_idx == test_monster_name("Elder vampire")) then - -- He really likes it if you kill Vampires (but not the adventurer kind :P) - set_grace(player.grace + 50) - end - - if - (m_ptr.r_idx == test_monster_name("Vampire elf")) or - (m_ptr.r_idx == test_monster_name("Thuringwethil, the Vampire Messenger")) then - -- He *loves* it if you kill vampire Elves - -- He will also thank you extra kindly if you kill Thuringwethil - set_grace(player.grace + 200) - end - - if - (m_ptr.r_idx == test_monster_name("Dark elf")) or - (m_ptr.r_idx == test_monster_name("Dark elven druid")) or - (m_ptr.r_idx == test_monster_name("Eol, the Dark Elf")) or - (m_ptr.r_idx == test_monster_name("Maeglin, the Traitor of Gondolin")) or - (m_ptr.r_idx == test_monster_name("Dark elven mage")) or - (m_ptr.r_idx == test_monster_name("Dark elven warrior")) or - (m_ptr.r_idx == test_monster_name("Dark elven priest")) or - (m_ptr.r_idx == test_monster_name("Dark elven lord")) or - (m_ptr.r_idx == test_monster_name("Dark elven warlock")) or - (m_ptr.r_idx == test_monster_name("Dark elven sorcerer")) then - -- He doesn't like it if you kill normal Elves (means more work for him :P) - set_grace(player.grace - 20) - end - if - (m_ptr.r_idx == test_monster_name("Glorfindel of Rivendell")) or - (m_ptr.r_idx == test_monster_name("Finrod Felagund")) or - (m_ptr.r_idx == test_monster_name("Thranduil, King of the Wood Elves")) or - (m_ptr.r_idx == test_monster_name("Aquatic elven warrior")) or - (m_ptr.r_idx == test_monster_name("Aquatic elven mage")) or - (m_ptr.r_idx == test_monster_name("High-elven ranger")) or - (m_ptr.r_idx == test_monster_name("Elven archer")) then - -- He hates it if you kill coaligned Elves - set_grace(player.grace - 200) - end - if - (m_ptr.r_idx == test_monster_name("Child spirit")) or - (m_ptr.r_idx == test_monster_name("Young spirit")) or - (m_ptr.r_idx == test_monster_name("Mature spirit")) or - (m_ptr.r_idx == test_monster_name("Experienced spirit")) or - (m_ptr.r_idx == test_monster_name("Wise spirit")) then - -- He *hates* it if you kill the coaligned Spirits - set_grace(player.grace - 1000) - end - end - end } } diff --git a/src/xtra2.c b/src/xtra2.c index 8d1f1867..7958827b 100644 --- a/src/xtra2.c +++ b/src/xtra2.c @@ -2439,6 +2439,94 @@ static void monster_death_gods(int m_idx, monster_type *m_ptr) inc_piety(GOD_ALL, -500); } } + + if (p_ptr->pgod == GOD_MANDOS) + { + cptr MINOR_BONUS_RACES[] = { + "Vampire", + "Master vampire", + "Oriental vampire", + "Vampire lord", + "Vampire orc", + "Vampire yeek", + "Vampire ogre", + "Vampire troll", + "Vampire dwarf", + "Vampire gnome", + "Elder vampire", + NULL, + }; + cptr MAJOR_BONUS_RACES[] = { + "Vampire elf", + "Thuringwethil, the Vampire Messenger", + NULL, + }; + cptr MINOR_PENALTY[] = { + "Dark elf", + "Dark elven druid", + "Eol, the Dark Elf", + "Maeglin, the Traitor of Gondolin", + "Dark elven mage", + "Dark elven warrior", + "Dark elven priest", + "Dark elven lord", + "Dark elven warlock", + "Dark elven sorcerer", + NULL, + }; + cptr MEDIUM_PENALTY[] = { + "Glorfindel of Rivendell", + "Finrod Felagund", + "Thranduil, King of the Wood Elves", + "Aquatic elven warrior", + "Aquatic elven mage", + "High-elven ranger", + "Elven archer", + NULL, + }; + cptr MAJOR_PENALTY[] = { + "Child spirit", + "Young spirit", + "Mature spirit", + "Experienced spirit", + "Wise spirit", + NULL, + }; + + if (monster_race_in_list_p(m_ptr, MINOR_BONUS_RACES)) + { + /* He really likes it if you kill Vampires + * (but not the adventurer kind :P) */ + inc_piety(GOD_ALL, 50); + } + + if (monster_race_in_list_p(m_ptr, MAJOR_BONUS_RACES)) + { + /* He *loves* it if you kill vampire Elves. He + * will also thank you extra kindly if you + * kill Thuringwethil */ + inc_piety(GOD_ALL, 200); + } + + if (monster_race_in_list_p(m_ptr, MINOR_PENALTY)) + { + /* He doesn't like it if you kill normal Elves + * (means more work for him :P) */ + inc_piety(GOD_ALL, -20); + } + + if (monster_race_in_list_p(m_ptr, MEDIUM_PENALTY)) + { + /* He hates it if you kill coaligned Elves */ + inc_piety(GOD_ALL, -200); + } + + if (monster_race_in_list_p(m_ptr, MAJOR_PENALTY)) + { + /* He *hates* it if you kill the coaligned Spirits */ + inc_piety(GOD_ALL, -1000); + } + } } /* -- cgit v1.2.3 From 5a310053e1ed6331155e4c4a3a645291c0a95650 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 10 Apr 2012 21:59:44 +0200 Subject: Lua: Gods: Move Varda's HOOK_CALC_LITE to C --- lib/mods/theme/scpt/gods_new.lua | 6 ------ src/defines.h | 1 - src/util.pkg | 6 ------ src/xtra1.c | 16 ++++++++++++++-- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/lib/mods/theme/scpt/gods_new.lua b/lib/mods/theme/scpt/gods_new.lua index 3d01ec87..e9b9241e 100644 --- a/lib/mods/theme/scpt/gods_new.lua +++ b/lib/mods/theme/scpt/gods_new.lua @@ -21,12 +21,6 @@ GOD_VARDA = add_god }, ["hooks"] = { - [HOOK_CALC_LITE] = function() - if (player.pgod == GOD_VARDA) then - -- increase lite radius - player.cur_lite = player.cur_lite + 1 - end - end, }, } diff --git a/src/defines.h b/src/defines.h index 2375c852..92d7fa10 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4545,7 +4545,6 @@ #define HOOK_APPLY_MAGIC 66 #define HOOK_PLAYER_EXP 67 #define HOOK_BIRTH 68 -#define HOOK_CALC_LITE 69 #define HOOK_LEARN_ABILITY 70 #define HOOK_MOVED 71 #define HOOK_GAME_START 72 diff --git a/src/util.pkg b/src/util.pkg index f9c94966..3e977785 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -760,12 +760,6 @@ typedef unsigned int u32b; */ #define HOOK_BIRTH 68 -/** @def HOOK_CALC_LITE - * @brief Calculate the lite radius. - * @note (see file xtra1.c) - */ -#define HOOK_CALC_LITE 69 - /** @def HOOK_LEARN_ABILITY * @brief Player learns an ability.\n * @param Number ab \n index of ability in ability (ab_info) array. diff --git a/src/xtra1.c b/src/xtra1.c index c1189484..a2f64d0e 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -1969,6 +1969,18 @@ void calc_hitpoints(void) } +/* + * God hooks for light + */ +static void calc_torch_gods() +{ + if (p_ptr->pgod == GOD_VARDA) + { + /* increase lite radius */ + p_ptr->cur_lite += 1; + } +} + /* * Extract and set the current "lite radius" @@ -2018,8 +2030,8 @@ static void calc_torch(void) /* but does glow as an intrinsic. */ if (p_ptr->cur_lite == 0 && p_ptr->lite) p_ptr->cur_lite = 1; - /* Hooked powers */ - process_hooks(HOOK_CALC_LITE, "()"); + /* gods */ + calc_torch_gods(); /* end experimental mods */ -- cgit v1.2.3 From f802db8cbf123d07c8a373b0cfc4188de34f386e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 11 Apr 2012 17:38:55 +0200 Subject: Lua: Gods: Move Theme god definitions to C --- lib/core/gods.lua | 40 ---------------------- lib/core/player.lua | 5 --- lib/mods/theme/core/gods.lua | 40 ---------------------- lib/mods/theme/core/player.lua | 5 --- lib/mods/theme/scpt/gods_new.lua | 49 --------------------------- lib/mods/theme/scpt/init.lua | 1 - src/birth.c | 15 ++++----- src/defines.h | 6 +++- src/externs.h | 10 ++---- src/gods.c | 29 ++++++++++++++-- src/init2.c | 26 --------------- src/lua_bind.c | 23 ------------- src/player.pkg | 63 +++-------------------------------- src/tables.c | 72 +++++++++++++++++++++++++++++++++++++++- src/types.h | 1 + src/variable.c | 10 ------ 16 files changed, 115 insertions(+), 280 deletions(-) delete mode 100644 lib/mods/theme/scpt/gods_new.lua diff --git a/lib/core/gods.lua b/lib/core/gods.lua index 77e0aad5..e69de29b 100644 --- a/lib/core/gods.lua +++ b/lib/core/gods.lua @@ -1,40 +0,0 @@ --- Gods helper files - --- Gods structs - -__gods_hook = {} -__gods_callbacks = {} -__gods_callbacks_max = 0 - -function add_god(q) - local i, index, d, z, qq - - assert(q.name, "No god name") - assert(q.desc, "No god desc") - assert(q.hooks, "No god hooks") - - i = add_new_gods(q.name); - - z = 0 - for index, d in q.desc do - desc_god(i, z, d); - z = z + 1 - end - - __gods_hook[i] = q.hooks - for index, d in q.hooks do - add_hook_script(index, "__lua__gods_callback"..__gods_callbacks_max, "__lua__gods_callback"..__gods_callbacks_max) - setglobal("__lua__gods_callback"..__gods_callbacks_max, d) - __gods_callbacks_max = __gods_callbacks_max + 1 - end - if q.data then - for index, d in q.data do - -- Besure it exists - setglobal(index, d) - - -- Make it save & load - add_loadsave(index, d) - end - end - return i -end diff --git a/lib/core/player.lua b/lib/core/player.lua index e194b45a..cb1b5cab 100644 --- a/lib/core/player.lua +++ b/lib/core/player.lua @@ -3,11 +3,6 @@ -- Lua player funtions -- --- Gods -function deity(i) - return deity_info[1 + i] -end - -------- skill stuff --------- -- Easy skill access diff --git a/lib/mods/theme/core/gods.lua b/lib/mods/theme/core/gods.lua index 77e0aad5..e69de29b 100644 --- a/lib/mods/theme/core/gods.lua +++ b/lib/mods/theme/core/gods.lua @@ -1,40 +0,0 @@ --- Gods helper files - --- Gods structs - -__gods_hook = {} -__gods_callbacks = {} -__gods_callbacks_max = 0 - -function add_god(q) - local i, index, d, z, qq - - assert(q.name, "No god name") - assert(q.desc, "No god desc") - assert(q.hooks, "No god hooks") - - i = add_new_gods(q.name); - - z = 0 - for index, d in q.desc do - desc_god(i, z, d); - z = z + 1 - end - - __gods_hook[i] = q.hooks - for index, d in q.hooks do - add_hook_script(index, "__lua__gods_callback"..__gods_callbacks_max, "__lua__gods_callback"..__gods_callbacks_max) - setglobal("__lua__gods_callback"..__gods_callbacks_max, d) - __gods_callbacks_max = __gods_callbacks_max + 1 - end - if q.data then - for index, d in q.data do - -- Besure it exists - setglobal(index, d) - - -- Make it save & load - add_loadsave(index, d) - end - end - return i -end diff --git a/lib/mods/theme/core/player.lua b/lib/mods/theme/core/player.lua index e194b45a..cb1b5cab 100644 --- a/lib/mods/theme/core/player.lua +++ b/lib/mods/theme/core/player.lua @@ -3,11 +3,6 @@ -- Lua player funtions -- --- Gods -function deity(i) - return deity_info[1 + i] -end - -------- skill stuff --------- -- Easy skill access diff --git a/lib/mods/theme/scpt/gods_new.lua b/lib/mods/theme/scpt/gods_new.lua deleted file mode 100644 index e9b9241e..00000000 --- a/lib/mods/theme/scpt/gods_new.lua +++ /dev/null @@ -1,49 +0,0 @@ --- This file contains all the new gods - -GOD_AULE = add_god -{ - ["name"] = "Aule the Smith", - ["desc"] = - { - "Aule is a smith, and the creator of the Dwarves." - }, - ["hooks"] = - { - } -} - -GOD_VARDA = add_god -{ - ["name"] = "Varda Elentari", - ["desc"] = - { - "The Queen of the Stars. In light is her power and joy." - }, - ["hooks"] = - { - }, -} - -GOD_ULMO = add_god -{ - ["name"] = "Ulmo", - ["desc"] = - { - "Ulmo is called Lord of Waters, he rules all that is water on Arda." - }, - ["hooks"] = - { - }, -} - -GOD_MANDOS = add_god -{ - ["name"] = "Mandos", - ["desc"] = - { - "The Doomsman of the Valar and keeper of the slain." - }, - ["hooks"] = - { - } -} diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index 93a6e772..715f6dc5 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -16,7 +16,6 @@ tome_dofile("mkeys.lua") -- Add god stuff tome_dofile("gods.lua") -tome_dofile("gods_new.lua") -- Add the schools of magic tome_dofile("spells.lua") diff --git a/src/birth.c b/src/birth.c index 243f080e..274b50bf 100644 --- a/src/birth.c +++ b/src/birth.c @@ -2331,16 +2331,17 @@ static bool_ player_birth_aux_ask() } else { - int *choice; + int choice[MAX_GODS]; int max = 0; - C_MAKE(choice, max_gods, int); - /* Get the list of possible gods */ - for (n = 0; n < max_gods; n++) + for (n = 0; n < MAX_GODS; n++) { - if ((cp_ptr->gods | spp_ptr->gods) & BIT(n)) + if (god_enabled(&deity_info[n]) && + ((cp_ptr->gods | spp_ptr->gods) & BIT(n))) + { choice[max++] = n; + } } if (!max) @@ -2368,8 +2369,6 @@ static bool_ player_birth_aux_ask() if (c == 'Q') quit(NULL); if (c == 'S') { - C_FREE(choice, max_gods, int); - return (FALSE); } if (c == '*') @@ -2424,8 +2423,6 @@ static bool_ player_birth_aux_ask() else bell(); } - C_FREE(choice, max_gods, int); - /* Set god */ p_ptr->pgod = k; p_ptr->grace = 0; diff --git a/src/defines.h b/src/defines.h index 92d7fa10..c93abb73 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4698,7 +4698,11 @@ #define GOD_TULKAS 3 #define GOD_MELKOR 4 #define GOD_YAVANNA 5 -#define MAX_GODS_INIT 6 +#define GOD_AULE 6 +#define GOD_VARDA 7 +#define GOD_ULMO 8 +#define GOD_MANDOS 9 +#define MAX_GODS 10 #define GOD(g) if (p_ptr->pgod == (g)) #define PRAY_GOD(g) if ((p_ptr->pgod == (g)) && (p_ptr->praying)) diff --git a/src/externs.h b/src/externs.h index 6c13aa27..cfb07bbd 100644 --- a/src/externs.h +++ b/src/externs.h @@ -60,7 +60,6 @@ extern s16b arena_monsters[MAX_ARENA_MONS]; extern byte extract_energy[300]; extern s32b player_exp[PY_MAX_LEVEL]; extern player_sex sex_info[MAX_SEXES]; -extern deity_type deity_info_init[MAX_GODS_INIT]; extern cptr color_names[16]; extern cptr stat_names[6]; extern cptr stat_names_reduced[6]; @@ -593,12 +592,7 @@ extern s32b DUNGEON_DEATH; extern s32b DUNGEON_ASTRAL; extern s32b DUNGEON_ASTRAL_WILD_X; extern s32b DUNGEON_ASTRAL_WILD_Y; -extern deity_type *deity_info; -extern s32b max_gods; -extern s32b GOD_AULE; -extern s32b GOD_VARDA; -extern s32b GOD_ULMO; -extern s32b GOD_MANDOS; +extern deity_type deity_info[MAX_GODS]; extern timer_type *gl_timers; extern s16b tim_precognition; extern const char *get_version_string(); @@ -1796,7 +1790,6 @@ extern bool_ summon_lua_okay(int r_idx); extern bool_ lua_summon_monster(int y, int x, int lev, bool_ ffriend, char *fct); extern s16b add_new_gods(char *name); -extern void desc_god(int g_idx, int d, char *desc); extern int get_lua_int(cptr name); extern bool_ get_com_lua(cptr promtp, int *com); @@ -1871,3 +1864,4 @@ extern void abandon_god(int god); extern int wisdom_scale(int max); extern int find_god(cptr name); extern void follow_god(int god, bool_ silent); +extern bool_ god_enabled(struct deity_type *deity); diff --git a/src/gods.c b/src/gods.c index b8b8fd3a..56b1380b 100644 --- a/src/gods.c +++ b/src/gods.c @@ -125,15 +125,38 @@ int wisdom_scale(int max) return (i * max) / 37; } +/* + * Check if god is enabled for the current module + */ +bool_ god_enabled(struct deity_type *deity) +{ + int i; + + for (i = 0; deity->modules[i] != -1; i++) + { + if (deity->modules[i] == game_module_idx) + { + return TRUE; + } + } + /* Not enabled */ + return FALSE; +} + /* Find a god by name */ int find_god(cptr name) { int i; - for (i = 0; i < max_gods; i++) + for (i = 0; i < MAX_GODS; i++) { - /* The name matches */ - if (streq(deity_info[i].name, name)) return (i); + /* The name matches and god is "enabled" for the + current module. */ + if (god_enabled(&deity_info[i]) && + streq(deity_info[i].name, name)) + { + return (i); + } } return -1; } diff --git a/src/init2.c b/src/init2.c index 1f6e66e6..71e7bc2b 100644 --- a/src/init2.c +++ b/src/init2.c @@ -1959,13 +1959,6 @@ static errr init_misc(void) /* Hack -- No messages yet */ message__tail = MESSAGE_BUF; - /* Prepare gods */ - deity_info = NULL; - max_gods = MAX_GODS_INIT; - reinit_gods(max_gods); - - C_COPY(deity_info, deity_info_init, MAX_GODS_INIT, deity_type); - /* Prepare schools */ max_spells = 0; max_schools = 0; @@ -2066,25 +2059,6 @@ static errr init_wilderness(void) return 0; } -void reinit_gods(s16b new_size) -{ - deity_type *new_deity; - - C_MAKE(new_deity, new_size, deity_type); - - /* Reallocate the extra memory */ - if (deity_info) - { - C_COPY(new_deity, deity_info, max_gods, deity_type); - - C_FREE(deity_info, max_gods, deity_type); - } - - deity_info = new_deity; - - max_gods = new_size; -} - void init_spells(s16b new_size) { /* allocate the extra memory */ diff --git a/src/lua_bind.c b/src/lua_bind.c index ff6680be..fd7d9cbb 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -537,29 +537,6 @@ void lua_display_list(int y, int x, int h, int w, cptr title, list_type* list, i -/* - * Gods - */ -s16b add_new_gods(char *name) -{ - int i; - - /* Increase the size */ - reinit_gods(max_gods + 1); - deity_info[max_gods - 1].name = string_make(name); - - for (i = 0; i < 10; i++) - strncpy(deity_info[max_gods - 1].desc[i], "", 39); - - return (max_gods - 1); -} - -void desc_god(int g_idx, int d, char *desc) -{ - if (d >= 0 && d < 10) - strncpy(deity_info[g_idx].desc[d], desc, 79); -} - int get_lua_int(cptr name) { return exec_lua(format("return %s", name)); diff --git a/src/player.pkg b/src/player.pkg index e9649729..459ade67 100644 --- a/src/player.pkg +++ b/src/player.pkg @@ -475,21 +475,6 @@ extern s32b player_exp[PY_MAX_LEVEL]; #define PW_BORG_2 0x00008000L /** @} */ -/** @struct deity_type - */ -struct deity_type -{ - /** @structvar name - * @brief String - */ - cptr name; -}; -/** @var deity_info[max_gods] - * @brief deity_type - * @note Array of gods. - */ -extern deity_type deity_info[max_gods]; - /** @name Body parts * @{ */ /** @def BODY_WEAPON */ @@ -3098,10 +3083,10 @@ extern s16b dun_level; #define GOD_YAVANNA 5 /** @} */ -extern s32b GOD_AULE; -extern s32b GOD_VARDA; -extern s32b GOD_ULMO; -extern s32b GOD_MANDOS; +#define GOD_AULE 6 +#define GOD_VARDA 7 +#define GOD_ULMO 8 +#define GOD_MANDOS 9 /** @fn inc_piety(int god, s32b amt) @@ -3136,46 +3121,6 @@ extern void abandon_god(int god); */ extern int wisdom_scale(int max); -/** @fn follow_god(int god, bool silent) - * @brief Player starts to follow god "god".\n - * @param god Number \n the god - * @brief God - * @param silent Boolean \n TRUE if Melkor message is displayed, otherwise - * FALSE. - * @brief Show message? - * @note - * Unbelievers can not follow a god. - * @note - * If the player does not worship a god, they start worshipping "god". If the - * god is Melkor, the player gains the Udun skill (show a message if silent is - * FALSE). - * @note (see file gods.c) - */ -extern void follow_god(int god, bool silent); - -/** @fn add_new_gods(char *name) - * @brief Add a new god to the deity array.\n - * @param *name String \n the name of the god - * @brief God name - * @return Number \n The index of the new god inthe deity array. - * @note (see file lua_bind.c) - */ -extern s16b add_new_gods(char *name); - -/** @fn desc_god(int g_idx, int d, char *desc) - * @brief Return line "d" of the description of god with god index "g_idx".\n - * @param g_idx Number \n the index of god in the deity array. - * @brief God index - * @param d Number \n the line of the description - * (must be in the range 0 to 9). - * @brief Line of description - * @param *desc String - * @brief Description - * @return *desc String \n Line "d" of the god description. - * @note (see file lua_bind.c) - */ -extern void desc_god(int g_idx, int d, char *desc); - /** @name Powers * @{ */ /** @def PWR_SPIT_ACID diff --git a/src/tables.c b/src/tables.c index c5a22204..281395e0 100644 --- a/src/tables.c +++ b/src/tables.c @@ -2739,9 +2739,10 @@ cptr deity_standing[11] = * Only the first four lines are printed at birth. */ -deity_type deity_info_init[MAX_GODS_INIT] = +deity_type deity_info[MAX_GODS] = { { + { MODULE_TOME, MODULE_THEME, -1, }, "Nobody", { "Atheist", @@ -2757,6 +2758,7 @@ deity_type deity_info_init[MAX_GODS_INIT] = }, }, { + { MODULE_TOME, MODULE_THEME, -1, }, "Eru Iluvatar", { "He is the supreme god, he created the world, and most of its inhabitants.", @@ -2772,6 +2774,7 @@ deity_type deity_info_init[MAX_GODS_INIT] = }, }, { + { MODULE_TOME, MODULE_THEME, -1, }, "Manwe Sulimo", { "He is the king of the Valar, most powerful of them after Melkor.", @@ -2787,6 +2790,7 @@ deity_type deity_info_init[MAX_GODS_INIT] = }, }, { + { MODULE_TOME, MODULE_THEME, -1, }, "Tulkas", { "He is the last of the Valar that came to the world, and the fiercest fighter.", @@ -2802,6 +2806,7 @@ deity_type deity_info_init[MAX_GODS_INIT] = }, }, { + { MODULE_TOME, MODULE_THEME, -1, }, "Melkor Bauglir", { "He is the most powerful of the Valar. He became corrupted and he's now ", @@ -2817,6 +2822,7 @@ deity_type deity_info_init[MAX_GODS_INIT] = }, }, { + { MODULE_TOME, MODULE_THEME, -1, }, "Yavanna Kementari", { "She is the Vala of nature, protectress of the great forests of " @@ -2832,6 +2838,70 @@ deity_type deity_info_init[MAX_GODS_INIT] = "", }, }, + { + { MODULE_THEME, -1, }, + "Aule the Smith", + { + "Aule is a smith, and the creator of the Dwarves.", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }, + }, + { + { MODULE_THEME, -1, }, + "Varda Elentari", + { + "The Queen of the Stars. In light is her power and joy.", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }, + }, + { + { MODULE_THEME, -1, }, + "Ulmo", + { + "Ulmo is called Lord of Waters, he rules all that is water" + "on Arda.", + "", + "", + "", + "", + "", + "", + "", + "", + }, + }, + { + { MODULE_THEME, -1, }, + "Mandos", + { + "The Doomsman of the Valar and keeper of the slain.", + "", + "", + "", + "", + "", + "", + "", + "", + "", + }, + }, }; /* jk - to hit, to dam, to ac, to stealth, to disarm, to saving throw */ diff --git a/src/types.h b/src/types.h index fc4f7356..efefc93a 100644 --- a/src/types.h +++ b/src/types.h @@ -1987,6 +1987,7 @@ struct artifact_select_flag { typedef struct deity_type deity_type; struct deity_type { + int modules[3]; /* terminated with -1 */ cptr name; char desc[10][80]; }; diff --git a/src/variable.c b/src/variable.c index c09d9720..11019a22 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1569,16 +1569,6 @@ s32b DUNGEON_ASTRAL = 8; s32b DUNGEON_ASTRAL_WILD_X = 45; s32b DUNGEON_ASTRAL_WILD_Y = 19; -/* - * Gods - */ -deity_type *deity_info; -s32b max_gods = MAX_GODS_INIT; -s32b GOD_AULE = -99; -s32b GOD_VARDA = -99; -s32b GOD_ULMO = -99; -s32b GOD_MANDOS = -99; - /* * Timers */ -- cgit v1.2.3 From 8c31b55cffc3d1d85b90126a9dd2ba6526723fcd Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 11 Apr 2012 17:55:32 +0200 Subject: Lua: Remove empty gods.lua. --- lib/core/gods.lua | 0 lib/core/init.lua | 1 - lib/mods/theme/core/gods.lua | 0 lib/mods/theme/core/init.lua | 1 - 4 files changed, 2 deletions(-) delete mode 100644 lib/core/gods.lua delete mode 100644 lib/mods/theme/core/gods.lua diff --git a/lib/core/gods.lua b/lib/core/gods.lua deleted file mode 100644 index e69de29b..00000000 diff --git a/lib/core/init.lua b/lib/core/init.lua index d294adb4..35f820d3 100644 --- a/lib/core/init.lua +++ b/lib/core/init.lua @@ -17,7 +17,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "building.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "s_aux.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "gods.lua") -- Load the ingame contextual help tome_dofile_anywhere(ANGBAND_DIR_CORE, "help.lua") diff --git a/lib/mods/theme/core/gods.lua b/lib/mods/theme/core/gods.lua deleted file mode 100644 index e69de29b..00000000 diff --git a/lib/mods/theme/core/init.lua b/lib/mods/theme/core/init.lua index d294adb4..35f820d3 100644 --- a/lib/mods/theme/core/init.lua +++ b/lib/mods/theme/core/init.lua @@ -17,7 +17,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "building.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "s_aux.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "gods.lua") -- Load the ingame contextual help tome_dofile_anywhere(ANGBAND_DIR_CORE, "help.lua") -- cgit v1.2.3 From c4db19005072f39faf67235d180d00eab6a4666f Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 11 Apr 2012 18:10:49 +0200 Subject: Lua: Gods: Refactor HOOK_FOLLOW_GOD code to C --- lib/mods/theme/scpt/gods.lua | 16 ---------------- lib/scpt/gods.lua | 16 ---------------- src/defines.h | 1 - src/gods.c | 29 +++++++++++++++++++++++++---- src/util.pkg | 16 ---------------- 5 files changed, 25 insertions(+), 53 deletions(-) diff --git a/lib/mods/theme/scpt/gods.lua b/lib/mods/theme/scpt/gods.lua index 014a4423..f76a3d6a 100644 --- a/lib/mods/theme/scpt/gods.lua +++ b/lib/mods/theme/scpt/gods.lua @@ -1,21 +1,5 @@ add_hooks { - [HOOK_FOLLOW_GOD] = function(god, action) - if action == "ask" then - if not (god == GOD_MELKOR) then - local i = INVEN_WIELD - while i < INVEN_TOTAL do - -- 13 is ART_POWER - if player.inventory(i).name1 == 13 then - msg_print("The One Ring has corrupted you, and you are rejected.") - return TRUE - end - i = i + 1 - end - end - end - return FALSE - end, [HOOK_RECALC_SKILLS] = function() if not (player.pgod == GOD_NONE) and (get_skill(SKILL_ANTIMAGIC) > 0) then msg_print("You no longer believe.") diff --git a/lib/scpt/gods.lua b/lib/scpt/gods.lua index 014a4423..f76a3d6a 100644 --- a/lib/scpt/gods.lua +++ b/lib/scpt/gods.lua @@ -1,21 +1,5 @@ add_hooks { - [HOOK_FOLLOW_GOD] = function(god, action) - if action == "ask" then - if not (god == GOD_MELKOR) then - local i = INVEN_WIELD - while i < INVEN_TOTAL do - -- 13 is ART_POWER - if player.inventory(i).name1 == 13 then - msg_print("The One Ring has corrupted you, and you are rejected.") - return TRUE - end - i = i + 1 - end - end - end - return FALSE - end, [HOOK_RECALC_SKILLS] = function() if not (player.pgod == GOD_NONE) and (get_skill(SKILL_ANTIMAGIC) > 0) then msg_print("You no longer believe.") diff --git a/src/defines.h b/src/defines.h index c93abb73..04920e63 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4540,7 +4540,6 @@ #define HOOK_CALC_MANA 60 #define HOOK_LOAD_END 61 #define HOOK_RECALL 62 -#define HOOK_FOLLOW_GOD 63 #define HOOK_BODY_PARTS 65 #define HOOK_APPLY_MAGIC 66 #define HOOK_PLAYER_EXP 67 diff --git a/src/gods.c b/src/gods.c index 56b1380b..170f56b3 100644 --- a/src/gods.c +++ b/src/gods.c @@ -43,6 +43,30 @@ void abandon_god(int god) } } +/* + * Check if god may be followed by player + */ +static bool_ may_follow_god(int god) +{ + if (god == GOD_MELKOR) + { + int i; + + /* Check if player has wielded The One Ring */ + for (i = INVEN_WIELD; i < INVEN_TOTAL; i++) + { + if (p_ptr->inventory[i].name1 == ART_POWER) + { + msg_print("The One Ring has corrupted " + "you, and you are rejected."); + return FALSE; + } + } + } + /* Default is to allow */ + return TRUE; +} + /* * Get a religion */ @@ -56,7 +80,7 @@ void follow_god(int god, bool_ silent) } /* Are we allowed ? */ - if (process_hooks(HOOK_FOLLOW_GOD, "(d,s)", god, "ask")) + if (!may_follow_god(god)) return; if (p_ptr->pgod == GOD_NONE) @@ -69,9 +93,6 @@ void follow_god(int god, bool_ silent) s_info[SKILL_UDUN].hidden = FALSE; if (!silent) msg_print("You feel the dark powers of Melkor in you. You can now use the Udun skill."); } - - /* Anything to be done? */ - process_hooks(HOOK_FOLLOW_GOD, "(d,s)", god, "done"); } } diff --git a/src/util.pkg b/src/util.pkg index 3e977785..12a28a71 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -708,22 +708,6 @@ typedef unsigned int u32b; */ #define HOOK_RECALL 62 -/** @def HOOK_FOLLOW_GOD - * @brief Player follows a god (gets religion).\n - * @param Number god \n the god to follow. - * @brief God - * @param String action \n "ask" to check if player can follow the god, or - * "done" to do something with the god. - * @brief Action - * @return Boolean \n For "ask": TRUE if player can not follow the god, - * otherwise FALSE. - * @note - * If the action is "ask" and the hook returns TRUE, follow_god() returns. - * If the action is "done" the return code is ignored. - * @note (see file gods.c) - */ -#define HOOK_FOLLOW_GOD 63 - /** @def HOOK_BODY_PARTS * @brief Calculate which body parts the player has. * @note (see file xtra1.c) -- cgit v1.2.3 From eaeaf76609a894e52f12dbbd35597aebbabb113a Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 11 Apr 2012 18:37:18 +0200 Subject: Lua: Gods: Move "become atheist when gaining Anti-magic" to C --- lib/mods/theme/scpt/gods.lua | 10 ---------- lib/mods/theme/scpt/init.lua | 3 --- lib/scpt/gods.lua | 10 ---------- lib/scpt/init.lua | 3 --- src/skills.c | 8 ++++++++ 5 files changed, 8 insertions(+), 26 deletions(-) delete mode 100644 lib/mods/theme/scpt/gods.lua delete mode 100644 lib/scpt/gods.lua diff --git a/lib/mods/theme/scpt/gods.lua b/lib/mods/theme/scpt/gods.lua deleted file mode 100644 index f76a3d6a..00000000 --- a/lib/mods/theme/scpt/gods.lua +++ /dev/null @@ -1,10 +0,0 @@ -add_hooks -{ - [HOOK_RECALC_SKILLS] = function() - if not (player.pgod == GOD_NONE) and (get_skill(SKILL_ANTIMAGIC) > 0) then - msg_print("You no longer believe.") - abandon_god(GOD_ALL) - end - return FALSE - end, -} diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index 715f6dc5..300dc66b 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -14,9 +14,6 @@ tome_dofile("stores.lua") -- Add the mkey activations tome_dofile("mkeys.lua") --- Add god stuff -tome_dofile("gods.lua") - -- Add the schools of magic tome_dofile("spells.lua") diff --git a/lib/scpt/gods.lua b/lib/scpt/gods.lua deleted file mode 100644 index f76a3d6a..00000000 --- a/lib/scpt/gods.lua +++ /dev/null @@ -1,10 +0,0 @@ -add_hooks -{ - [HOOK_RECALC_SKILLS] = function() - if not (player.pgod == GOD_NONE) and (get_skill(SKILL_ANTIMAGIC) > 0) then - msg_print("You no longer believe.") - abandon_god(GOD_ALL) - end - return FALSE - end, -} diff --git a/lib/scpt/init.lua b/lib/scpt/init.lua index ef85b5e9..fa066d7f 100644 --- a/lib/scpt/init.lua +++ b/lib/scpt/init.lua @@ -17,9 +17,6 @@ tome_dofile("mkeys.lua") -- Add the schools of magic tome_dofile("spells.lua") --- Add god stuff -tome_dofile("gods.lua") - -- Add some quests tome_dofile("library.lua") diff --git a/src/skills.c b/src/skills.c index 9890e96d..253eff3f 100644 --- a/src/skills.c +++ b/src/skills.c @@ -366,6 +366,14 @@ void recalc_skills(bool_ init) msg_format("You have gained %d new thaumaturgy spells.", thaum_gain); } + /* Antimagic means you don't believe in gods. */ + if ((p_ptr->pgod != GOD_NONE) && + (s_info[SKILL_ANTIMAGIC].value > 0)) + { + msg_print("You no longer believe."); + abandon_god(GOD_ALL); + } + process_hooks(HOOK_RECALC_SKILLS, "()"); /* Update stuffs */ -- cgit v1.2.3 From 571ab5e1b1e20c8dc87a48a518caeee6f4e8a825 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 11 Apr 2012 19:44:49 +0200 Subject: Lua: Move intros to C --- lib/mods/theme/scpt/init.lua | 3 - lib/mods/theme/scpt/intro.lua | 43 --------- lib/scpt/init.lua | 3 - lib/scpt/intro.lua | 39 --------- src/defines.h | 1 - src/dungeon.c | 3 +- src/externs.h | 5 +- src/lua_bind.c | 70 --------------- src/modules.c | 199 ++++++++++++++++++++++++++++++++++++++++++ src/tables.c | 4 + src/types.h | 2 + src/util.pkg | 9 -- 12 files changed, 209 insertions(+), 172 deletions(-) delete mode 100644 lib/mods/theme/scpt/intro.lua delete mode 100644 lib/scpt/intro.lua diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index 300dc66b..cf291ab2 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -27,9 +27,6 @@ tome_dofile("joke.lua") -- Some tests, if the file is not present, this is fine tome_dofile_anywhere(ANGBAND_DIR_SCPT, "dg_test.lua", FALSE) --- A nice custom intro :) -tome_dofile("intro.lua") - -- Add monster interaction tome_dofile("monsters.lua") diff --git a/lib/mods/theme/scpt/intro.lua b/lib/mods/theme/scpt/intro.lua deleted file mode 100644 index 3cdce225..00000000 --- a/lib/mods/theme/scpt/intro.lua +++ /dev/null @@ -1,43 +0,0 @@ -function tome_intro() - screen_save() - Term_clear() - - if (TRUE == drop_text_left(TERM_L_BLUE, "Three Rings for the Elven-kings under the sky,", 10, 0)) then screen_load() return end - if (TRUE == drop_text_right(TERM_L_BLUE, "Seven for the Dwarf-lords in their halls of stone,", 11, -1)) then screen_load() return end - if (TRUE == drop_text_left(TERM_L_BLUE, "Nine for Mortal Men doomed to die,", 12, 0)) then screen_load() return end - if (TRUE == drop_text_right(TERM_L_BLUE, "One for the Dark Lord on his dark throne", 13, -1)) then screen_load() return end - if (TRUE == drop_text_left(TERM_L_BLUE, "In the land of Mordor, where the Shadows lie.", 14, 0)) then screen_load() return end - if (TRUE == drop_text_right(TERM_L_BLUE, "One Ring to rule them all, One Ring to find them,", 15, -1)) then screen_load() return end - if (TRUE == drop_text_left(TERM_L_BLUE, "One Ring to bring them all and in the darkness bind them", 16, 0)) then screen_load() return end - if (TRUE == drop_text_right(TERM_L_BLUE, "In the land of Mordor, where the Shadows lie.", 17, -1)) then screen_load() return end - if (TRUE == drop_text_right(TERM_L_GREEN, "--J.R.R. Tolkien", 18, 0)) then screen_load() return end - if (TRUE == drop_text_left(TERM_WHITE, "[Press any key to continue]", 23, -1)) then screen_load() return end - - Term_putch(0, 0, TERM_DARK, 32) - inkey_scan = FALSE - inkey() - - Term_clear() - - if (TRUE == drop_text_left(TERM_L_BLUE, "furiosity", 8, 0)) then screen_load() return end - if (TRUE == drop_text_right(TERM_WHITE, "in collaboration with", 9, -1)) then screen_load() return end - if (TRUE == drop_text_left(TERM_L_GREEN, "DarkGod and all the ToME contributors,", 10, 0)) then screen_load() return end - if (TRUE == drop_text_right(TERM_L_GREEN, "module creators, t-o-m-e.net forum posters,", 11, -1)) then screen_load() return end - if (TRUE == drop_text_left(TERM_WHITE, "and", 12, 0)) then screen_load() return end - if (TRUE == drop_text_right(TERM_L_GREEN, "by the grace of the Valar", 13, -1)) then screen_load() return end - - if (TRUE == drop_text_left(TERM_WHITE, "present", 15, 1)) then screen_load() return end - if (TRUE == drop_text_right(TERM_YELLOW, "Theme (a module for ToME)", 16, 0)) then screen_load() return end - - if (TRUE == drop_text_left(TERM_WHITE, "[Press any key to continue]", 23, -1)) then screen_load() return end - Term_putch(0, 0, TERM_DARK, 32) - - inkey_scan = FALSE - - inkey() - - screen_load() - return -end - -add_hook_script(HOOK_INIT, "tome_intro", "lua_intro_init") diff --git a/lib/scpt/init.lua b/lib/scpt/init.lua index fa066d7f..5d8fb5e8 100644 --- a/lib/scpt/init.lua +++ b/lib/scpt/init.lua @@ -26,6 +26,3 @@ tome_dofile("joke.lua") -- Some tests, if the file is not present, this is fine tome_dofile_anywhere(ANGBAND_DIR_SCPT, "dg_test.lua", FALSE) - --- A nice custom intro :) -tome_dofile("intro.lua") diff --git a/lib/scpt/intro.lua b/lib/scpt/intro.lua deleted file mode 100644 index ef6041a5..00000000 --- a/lib/scpt/intro.lua +++ /dev/null @@ -1,39 +0,0 @@ -function tome_intro() - screen_save() - Term_clear() - - if (TRUE == drop_text_left(TERM_L_BLUE, "Art thou an adventurer,", 10, 0)) then screen_load() return end - if (TRUE == drop_text_right(TERM_L_BLUE, "One who passes through the waterfalls we call danger", 11, -1)) then screen_load() return end - if (TRUE == drop_text_left(TERM_L_BLUE, "to find the true nature of the legends beyond them?", 12, 0)) then screen_load() return end - if (TRUE == drop_text_right(TERM_L_BLUE, "If this is so, then seeketh me.", 13, -1)) then screen_load() return end - - if (TRUE == drop_text_left(TERM_WHITE, "[Press any key to continue]", 23, -1)) then screen_load() return end - - Term_putch(0, 0, TERM_DARK, 32) - inkey_scan = FALSE - inkey() - - Term_clear() - - if (TRUE == drop_text_left(TERM_L_BLUE, "DarkGod", 8, 0)) then screen_load() return end - if (TRUE == drop_text_right(TERM_WHITE, "in collaboration with", 9, -1)) then screen_load() return end - if (TRUE == drop_text_left(TERM_L_GREEN, "Eru Iluvatar,", 10, 0)) then screen_load() return end - if (TRUE == drop_text_right(TERM_L_GREEN, "Manwe", 11, -1)) then screen_load() return end - if (TRUE == drop_text_left(TERM_WHITE, "and", 12, 0)) then screen_load() return end - if (TRUE == drop_text_right(TERM_L_GREEN, "All the T.o.M.E. contributors(see credits.txt)", 13, -1)) then screen_load() return end - - if (TRUE == drop_text_left(TERM_WHITE, "present", 15, 1)) then screen_load() return end - if (TRUE == drop_text_right(TERM_YELLOW, "T.o.M.E.", 16, 0)) then screen_load() return end - - if (TRUE == drop_text_left(TERM_WHITE, "[Press any key to continue]", 23, -1)) then screen_load() return end - Term_putch(0, 0, TERM_DARK, 32) - - inkey_scan = FALSE - - inkey() - - screen_load() - return -end - -add_hook_script(HOOK_INIT, "tome_intro", "lua_intro_init") diff --git a/src/defines.h b/src/defines.h index 04920e63..439048e8 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4504,7 +4504,6 @@ #define HOOK_MONSTER_AI 19 #define HOOK_PLAYER_LEVEL 20 #define HOOK_WIELD 21 -#define HOOK_INIT 22 #define HOOK_AIM 24 #define HOOK_USE 25 #define HOOK_ACTIVATE 26 diff --git a/src/dungeon.c b/src/dungeon.c index 57aafb0b..ec2ab0e4 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -5567,7 +5567,8 @@ void play_game(bool_ new_game) /* Roll new character */ if (new_game) { - process_hooks(HOOK_INIT, "()"); + /* Show intro */ + modules[game_module_idx].intro(); /* The dungeon is not ready */ character_dungeon = FALSE; diff --git a/src/externs.h b/src/externs.h index cfb07bbd..4dd5424f 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1771,6 +1771,8 @@ extern void module_reset_dir(cptr dir, cptr new_path); extern cptr force_module; extern bool_ select_module(void); extern bool_ module_savefile_loadable(cptr savefile_mod); +extern void tome_intro(); +extern void theme_intro(); /* lua_bind.c */ @@ -1828,9 +1830,6 @@ extern void lua_delete_list(list_type *, int size); extern void lua_add_to_list(list_type *, int idx, cptr str); extern void lua_display_list(int y, int x, int h, int w, cptr title, list_type *list, int max, int begin, int sel, byte sel_color); -extern bool_ drop_text_left(byte c, cptr s, int y, int o); -extern bool_ drop_text_right(byte c, cptr s, int y, int o); - extern void increase_mana(int delta); /* skills.c */ diff --git a/src/lua_bind.c b/src/lua_bind.c index fd7d9cbb..a01b1fbc 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -542,76 +542,6 @@ int get_lua_int(cptr name) return exec_lua(format("return %s", name)); } -bool_ drop_text_left(byte c, cptr str, int y, int o) -{ - int i = strlen(str); - int x = 39 - (strlen(str) / 2) + o; - while (i > 0) - { - int a = 0; - int time = 0; - - if (str[i-1] != ' ') - { - while (a < x + i - 1) - { - Term_putch(a - 1, y, c, 32); - Term_putch(a, y, c, str[i-1]); - time = time + 1; - if (time >= 4) - { - Term_xtra(TERM_XTRA_DELAY, 1); - time = 0; - } - Term_redraw_section(a - 1, y, a, y); - a = a + 1; - - inkey_scan = TRUE; - if (inkey()) { - return TRUE; - } - } - } - - i = i - 1; - } - return FALSE; -} - -bool_ drop_text_right(byte c, cptr str, int y, int o) -{ - int x = 39 - (strlen(str) / 2) + o; - int i = 1; - while (i <= strlen(str)) - { - int a = 79; - int time = 0; - - if (str[i-1] != ' ') { - while (a >= x + i - 1) - { - Term_putch(a + 1, y, c, 32); - Term_putch(a, y, c, str[i-1]); - time = time + 1; - if (time >= 4) { - Term_xtra(TERM_XTRA_DELAY, 1); - time = 0; - } - Term_redraw_section(a, y, a + 1, y); - a = a - 1; - - inkey_scan = TRUE; - if (inkey()) { - return TRUE; - } - } - } - - i = i + 1; - } - return FALSE; -} - void increase_mana(int delta) { char buf[256]; diff --git a/src/modules.c b/src/modules.c index 5f582d92..8a4c5644 100644 --- a/src/modules.c +++ b/src/modules.c @@ -296,3 +296,202 @@ bool_ select_module() /* Shouldnt happen */ return (FALSE); } + +static bool_ dleft(byte c, cptr str, int y, int o) +{ + int i = strlen(str); + int x = 39 - (strlen(str) / 2) + o; + while (i > 0) + { + int a = 0; + int time = 0; + + if (str[i-1] != ' ') + { + while (a < x + i - 1) + { + Term_putch(a - 1, y, c, 32); + Term_putch(a, y, c, str[i-1]); + time = time + 1; + if (time >= 4) + { + Term_xtra(TERM_XTRA_DELAY, 1); + time = 0; + } + Term_redraw_section(a - 1, y, a, y); + a = a + 1; + + inkey_scan = TRUE; + if (inkey()) { + return TRUE; + } + } + } + + i = i - 1; + } + return FALSE; +} + +static bool_ dright(byte c, cptr str, int y, int o) +{ + int x = 39 - (strlen(str) / 2) + o; + int i = 1; + while (i <= strlen(str)) + { + int a = 79; + int time = 0; + + if (str[i-1] != ' ') { + while (a >= x + i - 1) + { + Term_putch(a + 1, y, c, 32); + Term_putch(a, y, c, str[i-1]); + time = time + 1; + if (time >= 4) { + Term_xtra(TERM_XTRA_DELAY, 1); + time = 0; + } + Term_redraw_section(a, y, a + 1, y); + a = a - 1; + + inkey_scan = TRUE; + if (inkey()) { + return TRUE; + } + } + } + + i = i + 1; + } + return FALSE; +} + +typedef struct intro_text intro_text; +struct intro_text +{ + bool_ (*drop_func)(byte, cptr, int, int); + byte color; + cptr text; + int y0; + int x0; +}; + +static bool_ show_intro(intro_text intro_texts[]) +{ + int i = 0; + + Term_clear(); + for (i = 0; ; i++) + { + intro_text *it = &intro_texts[i]; + if (it->drop_func == NULL) + { + break; + } + else if (it->drop_func(it->color, it->text, it->y0, it->x0)) + { + /* Abort */ + return TRUE; + } + } + + /* Wait for key */ + Term_putch(0, 0, TERM_DARK, 32); + inkey_scan = FALSE; + inkey(); + + /* Continue */ + return FALSE; +} + +void tome_intro() +{ + intro_text intro1[] = + { + { dleft , TERM_L_BLUE, "Art thou an adventurer,", 10, 0, }, + { dright, TERM_L_BLUE, "One who passes through the waterfalls we call danger", 11, -1, }, + { dleft , TERM_L_BLUE, "to find the true nature of the legends beyond them?", 12, 0, }, + { dright, TERM_L_BLUE, "If this is so, then seeketh me.", 13, -1, }, + { dleft , TERM_WHITE , "[Press any key to continue]", 23, -1, }, + { NULL, } + }; + intro_text intro2[] = + { + { dleft , TERM_L_BLUE , "DarkGod", 8, 0, }, + { dright, TERM_WHITE , "in collaboration with", 9, -1, }, + { dleft , TERM_L_GREEN, "Eru Iluvatar,", 10, 0, }, + { dright, TERM_L_GREEN, "Manwe", 11, -1, }, + { dleft , TERM_WHITE , "and", 12, 0, }, + { dright, TERM_L_GREEN, "All the T.o.M.E. contributors(see credits.txt)", 13, -1, }, + { dleft , TERM_WHITE , "present", 15, 1, }, + { dright, TERM_YELLOW , "T.o.M.E.", 16, 0, }, + { dleft , TERM_WHITE , "[Press any key to continue]", 23, -1, }, + { NULL, } + }; + + screen_save(); + + /* Intro 1 */ + if (show_intro(intro1)) + { + goto exit; + } + + /* Intro 2 */ + if (show_intro(intro2)) + { + goto exit; + } + +exit: + screen_load(); +} + +void theme_intro() +{ + struct intro_text intro1[] = + { + { dleft , TERM_L_BLUE , "Three Rings for the Elven-kings under the sky,", 10, 0, }, + { dright, TERM_L_BLUE , "Seven for the Dwarf-lords in their halls of stone,", 11, -1, }, + { dleft , TERM_L_BLUE , "Nine for Mortal Men doomed to die,", 12, 0, }, + { dright, TERM_L_BLUE , "One for the Dark Lord on his dark throne", 13, -1, }, + { dleft , TERM_L_BLUE , "In the land of Mordor, where the Shadows lie.", 14, 0, }, + { dright, TERM_L_BLUE , "One Ring to rule them all, One Ring to find them,", 15, -1, }, + { dleft , TERM_L_BLUE , "One Ring to bring them all and in the darkness bind them", 16, 0, }, + { dright, TERM_L_BLUE , "In the land of Mordor, where the Shadows lie.", 17, -1, }, + { dright, TERM_L_GREEN, "--J.R.R. Tolkien", 18, 0, }, + { dleft , TERM_WHITE , "[Press any key to continue]", 23, -1, }, + { NULL, }, + }; + struct intro_text intro2[] = + { + { dleft , TERM_L_BLUE , "furiosity", 8, 0, }, + { dright, TERM_WHITE , "in collaboration with", 9, -1, }, + { dleft , TERM_L_GREEN, "DarkGod and all the ToME contributors,", 10, 0, }, + { dright, TERM_L_GREEN, "module creators, t-o-m-e.net forum posters,", 11, -1, }, + { dleft , TERM_WHITE , "and", 12, 0, }, + { dright, TERM_L_GREEN, "by the grace of the Valar", 13, -1, }, + { dleft , TERM_WHITE , "present", 15, 1, }, + { dright, TERM_YELLOW , "Theme (a module for ToME)", 16, 0, }, + { dleft , TERM_WHITE , "[Press any key to continue]", 23, -1, }, + { NULL, }, + }; + + screen_save(); + + /* Intro 1 */ + if (show_intro(intro1)) + { + goto exit; + } + + /* Intro 2 */ + if (show_intro(intro2)) + { + goto exit; + } + +exit: + screen_load(); +} diff --git a/src/tables.c b/src/tables.c index 281395e0..a06c0143 100644 --- a/src/tables.c +++ b/src/tables.c @@ -4924,6 +4924,8 @@ module_type modules[MAX_MODULES] = 50, /* Skills: */ { 6, 4, }, + /* Intro function */ + tome_intro, }, { @@ -4942,6 +4944,8 @@ module_type modules[MAX_MODULES] = 50, /* Skill overage: */ { 6, 5, }, + /* Intro function */ + theme_intro, } }; diff --git a/src/types.h b/src/types.h index efefc93a..ea8213a3 100644 --- a/src/types.h +++ b/src/types.h @@ -2580,6 +2580,8 @@ struct module_type s32b max_skill_overage; } skills; + /* Function to show introduction to module */ + void (*intro)(); }; /** diff --git a/src/util.pkg b/src/util.pkg index 12a28a71..a730ee9a 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -355,12 +355,6 @@ typedef unsigned int u32b; */ #define HOOK_WIELD 21 -/** @def HOOK_INIT - * @brief Game initialised. - * @note (see file dungeon.c) - */ -#define HOOK_INIT 22 - /** @def HOOK_AIM */ #define HOOK_AIM 24 @@ -2436,9 +2430,6 @@ extern void calc_bonuses(bool silent); extern void note_spot(int y, int x); extern void lite_spot(int y, int x); -extern bool drop_text_left(byte c, cptr s, int y, int o); -extern bool drop_text_right(byte c, cptr s, int y, int o); - /** * Mimicry */ -- cgit v1.2.3 From e9e75f37fe3ca6b5702f8de49c1c2581a6719cef Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 11 Apr 2012 20:12:11 +0200 Subject: Add empty spells3.c as preparation for moving spells. --- src/CMakeLists.txt | 2 +- src/spells3.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 src/spells3.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f8a0b24f..18975f17 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,7 +10,7 @@ SET(SRCS object1.c object2.c randart.c squeltch.c traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c - spells1.c spells2.c corrupt.c mimic.c + spells1.c spells2.c spells3.c corrupt.c mimic.c status.c files.c notes.c loadsave.c cmd1.c cmd2.c cmd3.c cmd4.c cmd5.c cmd6.c cmd7.c help.c diff --git a/src/spells3.c b/src/spells3.c new file mode 100644 index 00000000..e1cb08b3 --- /dev/null +++ b/src/spells3.c @@ -0,0 +1,2 @@ +#include "angband.h" + -- cgit v1.2.3 From d97af20d1ac71ba79e6bcfd46b1753dc6737d266 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 11 Apr 2012 21:10:40 +0200 Subject: Lua: Move "Air" school spell functions to C --- lib/mods/theme/scpt/s_air.lua | 65 ++++------------- lib/scpt/s_air.lua | 65 ++++------------- src/externs.h | 21 ++++++ src/spells.pkg | 23 ++++++ src/spells3.c | 162 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 230 insertions(+), 106 deletions(-) diff --git a/lib/mods/theme/scpt/s_air.lua b/lib/mods/theme/scpt/s_air.lua index afd1f584..7b585317 100644 --- a/lib/mods/theme/scpt/s_air.lua +++ b/lib/mods/theme/scpt/s_air.lua @@ -18,19 +18,8 @@ NOXIOUSCLOUD = add_spell ["max_level"] = { 25, 50 }, }, }, - ["spell"] = function() - local ret, dir, type - - ret, dir = get_aim_dir() - if ret == FALSE then return end - if get_level(NOXIOUSCLOUD, 50) >= 30 then type = GF_UNBREATH - else type = GF_POIS end - fire_cloud(type, dir, 7 + get_level(NOXIOUSCLOUD, 150), 3, 5 + get_level(NOXIOUSCLOUD, 40)) - return TRUE - end, - ["info"] = function() - return "dam "..(7 + get_level(NOXIOUSCLOUD, 150)).." rad 3 dur "..(5 + get_level(NOXIOUSCLOUD, 40)) - end, + ["spell"] = function() return air_noxious_cloud() end, + ["info"] = function() return air_noxious_cloud_info() end, ["desc"] = { "Creates a cloud of poison", "The cloud will persist for some turns, damaging all monsters passing by", @@ -57,17 +46,8 @@ AIRWINGS = add_spell }, }, ["inertia"] = { 1, 10 }, - ["spell"] = function() - if get_level(AIRWINGS, 50) >= 16 then - if player.tim_fly == 0 then return set_tim_fly(randint(10) + 5 + get_level(AIRWINGS, 25)) end - else - if player.tim_ffall == 0 then return set_tim_ffall(randint(10) + 5 + get_level(AIRWINGS, 25)) end - end - return FALSE - end, - ["info"] = function() - return "dur "..(5 + get_level(AIRWINGS, 25)).."+d10" - end, + ["spell"] = function() return air_wings_of_winds() end, + ["info"] = function() return air_wings_of_winds_info() end, ["desc"] = { "Grants the power of levitation", "At level 16 it grants the power of controlled flight" @@ -83,12 +63,8 @@ INVISIBILITY = add_spell ["mana_max"] = 20, ["fail"] = 50, ["inertia"] = { 1, 30 }, - ["spell"] = function() - if player.tim_invisible == 0 then return set_invis(randint(20) + 15 + get_level(INVISIBILITY, 50), 20 + get_level(INVISIBILITY, 50)) end - end, - ["info"] = function() - return "dur "..(15 + get_level(INVISIBILITY, 50)).."+d20 power "..(20 + get_level(INVISIBILITY, 50)) - end, + ["spell"] = function() return air_invisibility() end, + ["info"] = function() return air_invisibility_info() end, ["desc"] = { "Grants invisibility" } @@ -113,15 +89,8 @@ POISONBLOOD = add_spell }, }, ["inertia"] = { 1, 35 }, - ["spell"] = function() - local obvious = nil - if player.oppose_pois == 0 then obvious = set_oppose_pois(randint(30) + 25 + get_level(POISONBLOOD, 25)) end - if (player.tim_poison == 0) and (get_level(POISONBLOOD, 50) >= 15) then obvious = is_obvious(set_poison(randint(30) + 25 + get_level(POISONBLOOD, 25)), obvious) end - return obvious - end, - ["info"] = function() - return "dur "..(25 + get_level(POISONBLOOD, 25)).."+d30" - end, + ["spell"] = function() return air_poison_blood() end, + ["info"] = function() return air_poison_blood_info() end, ["desc"] = { "Grants resist poison", "At level 15 it provides poison branding to wielded weapon" @@ -147,13 +116,8 @@ THUNDERSTORM = add_spell }, }, ["inertia"] = { 2, 15 }, - ["spell"] = function() - if player.tim_thunder == 0 then return set_tim_thunder(randint(10) + 10 + get_level(THUNDERSTORM, 25), 5 + get_level(THUNDERSTORM, 10), 10 + get_level(THUNDERSTORM, 25)) end - return FALSE - end, - ["info"] = function() - return "dam "..(5 + get_level(THUNDERSTORM, 10)).."d"..(10 + get_level(THUNDERSTORM, 25)).." dur "..(10 + get_level(THUNDERSTORM, 25)).."+d10" - end, + ["spell"] = function() return air_thunderstorm() end, + ["info"] = function() return air_thunderstorm_info() end, ["desc"] = { "Charges up the air around you with electricity", "Each turn it will throw a thunder bolt at a random monster in sight", @@ -180,13 +144,8 @@ STERILIZE = add_spell ["max_level"] = { 20, 50 }, }, }, - ["spell"] = function() - set_no_breeders((30) + 20 + get_level(STERILIZE, 70)) - return TRUE - end, - ["info"] = function() - return "dur "..(20 + get_level(STERILIZE, 70)).."+d30" - end, + ["spell"] = function() return air_sterilize() end, + ["info"] = function() return air_sterilize_info() end, ["desc"] = { "Prevents explosive breeding for a while." } diff --git a/lib/scpt/s_air.lua b/lib/scpt/s_air.lua index afd1f584..7b585317 100644 --- a/lib/scpt/s_air.lua +++ b/lib/scpt/s_air.lua @@ -18,19 +18,8 @@ NOXIOUSCLOUD = add_spell ["max_level"] = { 25, 50 }, }, }, - ["spell"] = function() - local ret, dir, type - - ret, dir = get_aim_dir() - if ret == FALSE then return end - if get_level(NOXIOUSCLOUD, 50) >= 30 then type = GF_UNBREATH - else type = GF_POIS end - fire_cloud(type, dir, 7 + get_level(NOXIOUSCLOUD, 150), 3, 5 + get_level(NOXIOUSCLOUD, 40)) - return TRUE - end, - ["info"] = function() - return "dam "..(7 + get_level(NOXIOUSCLOUD, 150)).." rad 3 dur "..(5 + get_level(NOXIOUSCLOUD, 40)) - end, + ["spell"] = function() return air_noxious_cloud() end, + ["info"] = function() return air_noxious_cloud_info() end, ["desc"] = { "Creates a cloud of poison", "The cloud will persist for some turns, damaging all monsters passing by", @@ -57,17 +46,8 @@ AIRWINGS = add_spell }, }, ["inertia"] = { 1, 10 }, - ["spell"] = function() - if get_level(AIRWINGS, 50) >= 16 then - if player.tim_fly == 0 then return set_tim_fly(randint(10) + 5 + get_level(AIRWINGS, 25)) end - else - if player.tim_ffall == 0 then return set_tim_ffall(randint(10) + 5 + get_level(AIRWINGS, 25)) end - end - return FALSE - end, - ["info"] = function() - return "dur "..(5 + get_level(AIRWINGS, 25)).."+d10" - end, + ["spell"] = function() return air_wings_of_winds() end, + ["info"] = function() return air_wings_of_winds_info() end, ["desc"] = { "Grants the power of levitation", "At level 16 it grants the power of controlled flight" @@ -83,12 +63,8 @@ INVISIBILITY = add_spell ["mana_max"] = 20, ["fail"] = 50, ["inertia"] = { 1, 30 }, - ["spell"] = function() - if player.tim_invisible == 0 then return set_invis(randint(20) + 15 + get_level(INVISIBILITY, 50), 20 + get_level(INVISIBILITY, 50)) end - end, - ["info"] = function() - return "dur "..(15 + get_level(INVISIBILITY, 50)).."+d20 power "..(20 + get_level(INVISIBILITY, 50)) - end, + ["spell"] = function() return air_invisibility() end, + ["info"] = function() return air_invisibility_info() end, ["desc"] = { "Grants invisibility" } @@ -113,15 +89,8 @@ POISONBLOOD = add_spell }, }, ["inertia"] = { 1, 35 }, - ["spell"] = function() - local obvious = nil - if player.oppose_pois == 0 then obvious = set_oppose_pois(randint(30) + 25 + get_level(POISONBLOOD, 25)) end - if (player.tim_poison == 0) and (get_level(POISONBLOOD, 50) >= 15) then obvious = is_obvious(set_poison(randint(30) + 25 + get_level(POISONBLOOD, 25)), obvious) end - return obvious - end, - ["info"] = function() - return "dur "..(25 + get_level(POISONBLOOD, 25)).."+d30" - end, + ["spell"] = function() return air_poison_blood() end, + ["info"] = function() return air_poison_blood_info() end, ["desc"] = { "Grants resist poison", "At level 15 it provides poison branding to wielded weapon" @@ -147,13 +116,8 @@ THUNDERSTORM = add_spell }, }, ["inertia"] = { 2, 15 }, - ["spell"] = function() - if player.tim_thunder == 0 then return set_tim_thunder(randint(10) + 10 + get_level(THUNDERSTORM, 25), 5 + get_level(THUNDERSTORM, 10), 10 + get_level(THUNDERSTORM, 25)) end - return FALSE - end, - ["info"] = function() - return "dam "..(5 + get_level(THUNDERSTORM, 10)).."d"..(10 + get_level(THUNDERSTORM, 25)).." dur "..(10 + get_level(THUNDERSTORM, 25)).."+d10" - end, + ["spell"] = function() return air_thunderstorm() end, + ["info"] = function() return air_thunderstorm_info() end, ["desc"] = { "Charges up the air around you with electricity", "Each turn it will throw a thunder bolt at a random monster in sight", @@ -180,13 +144,8 @@ STERILIZE = add_spell ["max_level"] = { 20, 50 }, }, }, - ["spell"] = function() - set_no_breeders((30) + 20 + get_level(STERILIZE, 70)) - return TRUE - end, - ["info"] = function() - return "dur "..(20 + get_level(STERILIZE, 70)).."+d30" - end, + ["spell"] = function() return air_sterilize() end, + ["info"] = function() return air_sterilize_info() end, ["desc"] = { "Prevents explosive breeding for a while." } diff --git a/src/externs.h b/src/externs.h index 4dd5424f..4fa71a2f 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1400,6 +1400,27 @@ extern void geomancy_random_floor(int y, int x, bool_ kill_wall); extern void geomancy_dig(int oy, int ox, int dir, int length); extern void channel_the_elements(int y, int x, int level); +/* spells3.c */ +extern s32b NOXIOUSCLOUD; +extern s32b AIRWINGS; +extern s32b INVISIBILITY; +extern s32b POISONBLOOD; +extern s32b THUNDERSTORM; +extern s32b STERILIZE; + +bool_ *air_noxious_cloud(); +char *air_noxious_cloud_info(); +bool_ *air_wings_of_winds(); +char *air_wings_of_winds_info(); +bool_ *air_invisibility(); +char *air_invisibility_info(); +bool_ *air_poison_blood(); +char *air_poison_blood_info(); +bool_ *air_thunderstorm(); +char *air_thunderstorm_info(); +bool_ *air_sterilize(); +char *air_sterilize_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index 6ca95cfc..de5d55bc 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2421,3 +2421,26 @@ extern void get_pos_player(int dis, int *ny=0, int *nx=0); extern void geomancy_random_floor(int y, int x, bool kill_wall); extern void geomancy_dig(int y, int x, int dir, int length); extern void channel_the_elements(int y, int x, int level); + +/* + * Air + */ +extern s32b NOXIOUSCLOUD; +extern s32b AIRWINGS; +extern s32b INVISIBILITY; +extern s32b POISONBLOOD; +extern s32b THUNDERSTORM; +extern s32b STERILIZE; + +bool_ *air_noxious_cloud(); +char *air_noxious_cloud_info(); +bool_ *air_wings_of_winds(); +char *air_wings_of_winds_info(); +bool_ *air_invisibility(); +char *air_invisibility_info(); +bool_ *air_poison_blood(); +char *air_poison_blood_info(); +bool_ *air_thunderstorm(); +char *air_thunderstorm_info(); +bool_ *air_sterilize(); +char *air_sterilize_info(); diff --git a/src/spells3.c b/src/spells3.c index e1cb08b3..0b5d5443 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -1,2 +1,164 @@ #include "angband.h" +s32b NOXIOUSCLOUD = -1; /* Identifier */ +s32b AIRWINGS = -1; /* Identifier */ +s32b INVISIBILITY; +s32b POISONBLOOD; +s32b THUNDERSTORM; +s32b STERILIZE; + +/* FIXME: Hackish workaround while we're still tied to Lua. This lets + us return Lua's "nil" and a non-nil value (which is all the s_aux.lua + cares about). */ +bool_ *NO_CAST = NULL; +bool_ CAST_VAL = 0xca; /* Any value will do */ +bool_ *CAST = &CAST_VAL; + +static s32b get_level_s(int sp, int max) +{ + return get_level(sp, max, 1); +} + +bool_ *air_noxious_cloud() +{ + int dir, type; + + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + if (get_level_s(NOXIOUSCLOUD, 50) >= 30) + { + type = GF_UNBREATH; + } + else + { + type = GF_POIS; + } + + fire_cloud(type, dir, 7 + get_level_s(NOXIOUSCLOUD, 150), 3, 5 + get_level_s(NOXIOUSCLOUD, 40)); + return CAST; +} + +char *air_noxious_cloud_info() +{ + static char buf[128]; + sprintf(buf, + "dam %d rad 3 dur %d", + (7 + get_level_s(NOXIOUSCLOUD, 150)), + (5 + get_level_s(NOXIOUSCLOUD, 40))); + return buf; +} + +bool_ *air_wings_of_winds() +{ + if (get_level_s(AIRWINGS, 50) >= 16) + { + if (p_ptr->tim_fly == 0) + { + set_tim_fly(randint(10) + 5 + get_level_s(AIRWINGS, 25)); + return CAST; + } + else if (p_ptr->tim_ffall == 0) + { + set_tim_ffall(randint(10) + 5 + get_level_s(AIRWINGS, 25)); + return CAST; + } + } + + return NO_CAST; +} + +char *air_wings_of_winds_info() +{ + static char buf[128]; + sprintf(buf, "dur %d+d10", (5 + get_level_s(AIRWINGS, 25))); + return buf; +} + +bool_ *air_invisibility() +{ + if (p_ptr->tim_invisible == 0) + { + set_invis(randint(20) + 15 + get_level_s(INVISIBILITY, 50), 20 + get_level_s(INVISIBILITY, 50)); + return CAST; + } + + return NO_CAST; +} + +char *air_invisibility_info() +{ + static char buf[128]; + sprintf(buf, "dur %d+d20 power %d", + (15 + get_level_s(INVISIBILITY, 50)), + (20 + get_level_s(INVISIBILITY, 50))); + return buf; +} + +bool_ *air_poison_blood() +{ + bool_ *cast = NO_CAST; + + if (p_ptr->oppose_pois == 0) + { + set_oppose_pois(randint(30) + 25 + get_level_s(POISONBLOOD, 25)); + cast = CAST; + } + + if ((p_ptr->tim_poison == 0) && + (get_level_s(POISONBLOOD, 50) >= 15)) + { + set_poison(randint(30) + 25 + get_level_s(POISONBLOOD, 25)); + cast = CAST; + } + + return cast; +} + +char *air_poison_blood_info() +{ + static char buf[128]; + sprintf(buf, + "dur %d+d30", + (25 + get_level_s(POISONBLOOD, 25))); + return buf; +} + +bool_ *air_thunderstorm() +{ + if (p_ptr->tim_thunder == 0) + { + set_tim_thunder(randint(10) + 10 + get_level_s(THUNDERSTORM, 25), 5 + get_level_s(THUNDERSTORM, 10), 10 + get_level_s(THUNDERSTORM, 25)); + return CAST; + } + + return NO_CAST; +} + +char *air_thunderstorm_info() +{ + static char buf[128]; + sprintf(buf, + "dam %dd%d dur %d+d10", + (5 + get_level_s(THUNDERSTORM, 10)), + (10 + get_level_s(THUNDERSTORM, 25)), + (10 + get_level_s(THUNDERSTORM, 25))); + return buf; +} + +bool_ *air_sterilize() +{ + set_no_breeders((30) + 20 + get_level_s(STERILIZE, 70)); + return CAST; +} + +char *air_sterilize_info() +{ + static char buf[128]; + sprintf(buf, + "dur %d+d30", + (20 + get_level_s(STERILIZE, 70))); + return buf; +} -- cgit v1.2.3 From 9de9180942450aea8ded755c94510cf6d2542a5a Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 12 Apr 2012 07:39:30 +0200 Subject: Lua: Move "Conveyance" spell functions to C --- lib/mods/theme/scpt/s_convey.lua | 108 +++------------------- lib/scpt/s_convey.lua | 108 +++------------------- src/externs.h | 20 ++++ src/spells.pkg | 23 +++++ src/spells3.c | 192 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 259 insertions(+), 192 deletions(-) diff --git a/lib/mods/theme/scpt/s_convey.lua b/lib/mods/theme/scpt/s_convey.lua index 1105a850..265218fa 100644 --- a/lib/mods/theme/scpt/s_convey.lua +++ b/lib/mods/theme/scpt/s_convey.lua @@ -9,21 +9,8 @@ BLINK = add_spell ["mana_max"] = 3, ["fail"] = 10, ["inertia"] = { 1, 5 }, - ["spell"] = function() - if get_level(BLINK, 50) >= 30 then - local oy, ox = player.py, player.px - - teleport_player(10 + get_level(BLINK, 8)) - create_between_gate(0, oy, ox) - return TRUE - else - teleport_player(10 + get_level(BLINK, 8)) - return TRUE - end - end, - ["info"] = function() - return "distance "..(10 + get_level(BLINK, 8)) - end, + ["spell"] = function() return convey_blink() end, + ["info"] = function() return convey_blink_info() end, ["desc"] = { "Teleports you on a small scale range", "At level 30 it creates void jumpgates", @@ -48,15 +35,8 @@ DISARM = add_spell ["max_level"] = { 10, 50 }, }, }, - ["spell"] = function() - local obvious - obvious = destroy_doors_touch() - if get_level(DISARM, 50) >= 10 then obvious = is_obvious(destroy_traps_touch(), obvious) end - return obvious - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return convey_disarm() end, + ["info"] = function() return convey_disarm_info() end, ["desc"] = { "Destroys doors and disarms traps", "At level 10 it unlocks doors and disarms traps", @@ -82,14 +62,8 @@ TELEPORT = add_spell }, }, ["inertia"] = { 1, 10 }, - ["spell"] = function() - player.energy = player.energy - (25 - get_level(TELEPORT, 50)) - teleport_player(100 + get_level(TELEPORT, 100)) - return TRUE - end, - ["info"] = function() - return "distance "..(100 + get_level(TELEPORT, 100)) - end, + ["spell"] = function() return convey_teleport() end, + ["info"] = function() return convey_teleport_info() end, ["desc"] = { "Teleports you around the level. The casting time decreases with level", } @@ -113,24 +87,8 @@ TELEAWAY = add_spell ["max_level"] = { 20, 50 }, }, }, - ["spell"] = function() - local ret, dir - - if get_level(TELEAWAY, 50) >= 20 then - return project_los(GF_AWAY_ALL, 100) - elseif get_level(TELEAWAY, 50) >= 10 then - ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_ball(GF_AWAY_ALL, dir, 100, 3 + get_level(TELEAWAY, 4)) - else - ret, dir = get_aim_dir() - if ret == FALSE then return end - return teleport_monster(dir) - end - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return convey_teleport_away() end, + ["info"] = function() return convey_teleport_away_info() end, ["desc"] = { "Teleports a line of monsters away", "At level 10 it turns into a ball", @@ -146,46 +104,8 @@ RECALL = add_spell ["mana"] = 25, ["mana_max"] = 25, ["fail"] = 60, - ["spell"] = function() - local ret, x, y, c_ptr - ret, x, y = tgt_pt() - if ret == FALSE then return end - c_ptr = cave(y, x) - if (y == player.py) and (x == player.px) then - local d = 21 - get_level(RECALL, 15) - if d < 0 then - d = 0 - end - local f = 15 - get_level(RECALL, 10) - if f < 1 then - f = 1 - end - recall_player(d, f) - return TRUE - elseif c_ptr.m_idx > 0 then - swap_position(y, x) - return TRUE - elseif c_ptr.o_idx > 0 then - set_target(y, x) - if get_level(RECALL, 50) >= 15 then - fetch(5, 10 + get_level(RECALL, 150), FALSE) - else - fetch(5, 10 + get_level(RECALL, 150), TRUE) - end - return TRUE - end - end, - ["info"] = function() - local d = 21 - get_level(RECALL, 15) - if d < 0 then - d = 0 - end - local f = 15 - get_level(RECALL, 10) - if f < 1 then - f = 1 - end - return "dur "..f.."+d"..d.." weight "..(1 + get_level(RECALL, 15)).."lb" - end, + ["spell"] = function() return convey_recall() end, + ["info"] = function() return convey_recall_info() end, ["desc"] = { "Cast on yourself it will recall you to the surface/dungeon.", "Cast at a monster you will swap positions with the monster.", @@ -212,12 +132,8 @@ PROBABILITY_TRAVEL = add_spell }, }, ["inertia"] = { 6, 40 }, - ["spell"] = function() - return set_prob_travel(randint(20) + get_level(PROBABILITY_TRAVEL, 60)) - end, - ["info"] = function() - return "dur "..get_level(PROBABILITY_TRAVEL, 60).."+d20" - end, + ["spell"] = function() return convey_probability_travel() end, + ["info"] = function() return convey_probability_travel_info() end, ["desc"] = { "Renders you immaterial, when you hit a wall you travel through it and", "instantly appear on the other side of it. You can also float up and down", diff --git a/lib/scpt/s_convey.lua b/lib/scpt/s_convey.lua index e7856c43..d81af28b 100644 --- a/lib/scpt/s_convey.lua +++ b/lib/scpt/s_convey.lua @@ -9,21 +9,8 @@ BLINK = add_spell ["mana_max"] = 3, ["fail"] = 10, ["inertia"] = { 1, 5 }, - ["spell"] = function() - if get_level(BLINK, 50) >= 30 then - local oy, ox = player.py, player.px - - teleport_player(10 + get_level(BLINK, 8)) - create_between_gate(0, oy, ox) - return TRUE - else - teleport_player(10 + get_level(BLINK, 8)) - return TRUE - end - end, - ["info"] = function() - return "distance "..(10 + get_level(BLINK, 8)) - end, + ["spell"] = function() return convey_blink() end, + ["info"] = function() return convey_blink_info() end, ["desc"] = { "Teleports you on a small scale range", "At level 30 it creates void jumpgates", @@ -48,15 +35,8 @@ DISARM = add_spell ["max_level"] = { 10, 50 }, }, }, - ["spell"] = function() - local obvious - obvious = destroy_doors_touch() - if get_level(DISARM, 50) >= 10 then obvious = is_obvious(destroy_traps_touch(), obvious) end - return obvious - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return convey_disarm() end, + ["info"] = function() return convey_disarm_info() end, ["desc"] = { "Destroys doors and traps", "At level 10 it destroys doors and traps, then reveals and unlocks any secret", @@ -83,14 +63,8 @@ TELEPORT = add_spell }, }, ["inertia"] = { 1, 10 }, - ["spell"] = function() - player.energy = player.energy - (25 - get_level(TELEPORT, 50)) - teleport_player(100 + get_level(TELEPORT, 100)) - return TRUE - end, - ["info"] = function() - return "distance "..(100 + get_level(TELEPORT, 100)) - end, + ["spell"] = function() return convey_teleport() end, + ["info"] = function() return convey_teleport_info() end, ["desc"] = { "Teleports you around the level. The casting time decreases with level", } @@ -114,24 +88,8 @@ TELEAWAY = add_spell ["max_level"] = { 20, 50 }, }, }, - ["spell"] = function() - local ret, dir - - if get_level(TELEAWAY, 50) >= 20 then - return project_los(GF_AWAY_ALL, 100) - elseif get_level(TELEAWAY, 50) >= 10 then - ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_ball(GF_AWAY_ALL, dir, 100, 3 + get_level(TELEAWAY, 4)) - else - ret, dir = get_aim_dir() - if ret == FALSE then return end - return teleport_monster(dir) - end - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return convey_teleport_away() end, + ["info"] = function() return convey_teleport_away_info() end, ["desc"] = { "Teleports a line of monsters away", "At level 10 it turns into a ball", @@ -147,46 +105,8 @@ RECALL = add_spell ["mana"] = 25, ["mana_max"] = 25, ["fail"] = 60, - ["spell"] = function() - local ret, x, y, c_ptr - ret, x, y = tgt_pt() - if ret == FALSE then return end - c_ptr = cave(y, x) - if (y == player.py) and (x == player.px) then - local d = 21 - get_level(RECALL, 15) - if d < 0 then - d = 0 - end - local f = 15 - get_level(RECALL, 10) - if f < 1 then - f = 1 - end - recall_player(d, f) - return TRUE - elseif c_ptr.m_idx > 0 then - swap_position(y, x) - return TRUE - elseif c_ptr.o_idx > 0 then - set_target(y, x) - if get_level(RECALL, 50) >= 15 then - fetch(5, 10 + get_level(RECALL, 150), FALSE) - else - fetch(5, 10 + get_level(RECALL, 150), TRUE) - end - return TRUE - end - end, - ["info"] = function() - local d = 21 - get_level(RECALL, 15) - if d < 0 then - d = 0 - end - local f = 15 - get_level(RECALL, 10) - if f < 1 then - f = 1 - end - return "dur "..f.."+d"..d.." weight "..(1 + get_level(RECALL, 15)).."lb" - end, + ["spell"] = function() return convey_recall() end, + ["info"] = function() return convey_recall_info() end, ["desc"] = { "Cast on yourself it will recall you to the surface/dungeon.", "Cast at a monster you will swap positions with the monster.", @@ -213,12 +133,8 @@ PROBABILITY_TRAVEL = add_spell }, }, ["inertia"] = { 6, 40 }, - ["spell"] = function() - return set_prob_travel(randint(20) + get_level(PROBABILITY_TRAVEL, 60)) - end, - ["info"] = function() - return "dur "..get_level(PROBABILITY_TRAVEL, 60).."+d20" - end, + ["spell"] = function() return convey_probability_travel() end, + ["info"] = function() return convey_probability_travel_info() end, ["desc"] = { "Renders you immaterial, when you hit a wall you travel through it and", "instantly appear on the other side of it. You can also float up and down", diff --git a/src/externs.h b/src/externs.h index 4fa71a2f..6a3bdb07 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1421,6 +1421,26 @@ char *air_thunderstorm_info(); bool_ *air_sterilize(); char *air_sterilize_info(); +extern s32b BLINK; +extern s32b DISARM; +extern s32b TELEPORT; +extern s32b TELEAWAY; +extern s32b RECALL; +extern s32b PROBABILITY_TRAVEL; + +bool_ *convey_blink(); +char *convey_blink_info(); +bool_ *convey_disarm(); +char *convey_disarm_info(); +bool_ *convey_teleport(); +char *convey_teleport_info(); +bool_ *convey_teleport_away(); +char *convey_teleport_away_info(); +bool_ *convey_recall(); +char *convey_recall_info(); +bool_ *convey_probability_travel(); +char *convey_probability_travel_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index de5d55bc..f1a83a23 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2444,3 +2444,26 @@ bool_ *air_thunderstorm(); char *air_thunderstorm_info(); bool_ *air_sterilize(); char *air_sterilize_info(); + +/* + * Conveyance + */ +extern s32b BLINK; +extern s32b DISARM; +extern s32b TELEPORT; +extern s32b TELEAWAY; +extern s32b RECALL; +extern s32b PROBABILITY_TRAVEL; + +bool_ *convey_blink(); +char *convey_blink_info(); +bool_ *convey_disarm(); +char *convey_disarm_info(); +bool_ *convey_teleport(); +char *convey_teleport_info(); +bool_ *convey_teleport_away(); +char *convey_teleport_away_info(); +bool_ *convey_recall(); +char *convey_recall_info(); +bool_ *convey_probability_travel(); +char *convey_probability_travel_info(); diff --git a/src/spells3.c b/src/spells3.c index 0b5d5443..dd75aac0 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -7,6 +7,13 @@ s32b POISONBLOOD; s32b THUNDERSTORM; s32b STERILIZE; +s32b BLINK; +s32b DISARM; +s32b TELEPORT; +s32b TELEAWAY; +s32b RECALL; +s32b PROBABILITY_TRAVEL; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua cares about). */ @@ -162,3 +169,188 @@ char *air_sterilize_info() (20 + get_level_s(STERILIZE, 70))); return buf; } + +bool_ *convey_blink() +{ + if (get_level_s(BLINK, 50) >= 30) + { + int oy = p_ptr->py; + int ox = p_ptr->px; + + teleport_player(10 + get_level_s(BLINK, 8)); + create_between_gate(0, oy, ox); + return CAST; + } + else + { + teleport_player(10 + get_level_s(BLINK, 8)); + return CAST; + } +} + +char *convey_blink_info() +{ + static char buf[128]; + sprintf(buf, + "distance %d", + (10 + get_level_s(BLINK, 8))); + return buf; +} + +bool_ *convey_disarm() +{ + destroy_doors_touch(); + if (get_level_s(DISARM, 50) >= 10) + { + destroy_traps_touch(); + } + + return CAST; +} + +char *convey_disarm_info() +{ + return ""; +} + +bool_ *convey_teleport() +{ + p_ptr->energy -= (25 - get_level_s(TELEPORT, 50)); + teleport_player(100 + get_level_s(TELEPORT, 100)); + return CAST; +} + +char *convey_teleport_info() +{ + static char buf[128]; + sprintf(buf, + "distance %d", + (100 + get_level_s(TELEPORT, 100))); + return buf; +} + +bool_ *convey_teleport_away() +{ + if (get_level_s(TELEAWAY, 50) >= 20) + { + project_hack(GF_AWAY_ALL, 100); + return CAST; + } + else if (get_level_s(TELEAWAY, 50) >= 10) + { + int dir; + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + fire_ball(GF_AWAY_ALL, dir, 100, 3 + get_level_s(TELEAWAY, 4)); + return CAST; + } + else + { + int dir; + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + teleport_monster(dir); + return CAST; + } +} + +char *convey_teleport_away_info() +{ + return ""; +} + +static int recall_get_d() +{ + int d = 21 - get_level_s(RECALL, 15); + if (d < 0) + { + d = 0; + } + return d; +} + +static int recall_get_f() +{ + int f = 15 - get_level_s(RECALL, 10); + if (f < 1) + { + f = 1; + } + return f; +} + +bool_ *convey_recall() +{ + int x,y; + cave_type *c_ptr; + + if (!tgt_pt(&x, &y)) + { + return NO_CAST; + } + + c_ptr = &cave[y][x]; + + if ((y == p_ptr->py) && + (x == p_ptr->px)) + { + int d = recall_get_d(); + int f = recall_get_f(); + recall_player(d, f); + return CAST; + } + else if (c_ptr->m_idx > 0) + { + swap_position(y, x); + return CAST; + } + else if (c_ptr->o_idx > 0) + { + set_target(y, x); + if (get_level_s(RECALL, 50) >= 15) + { + fetch(5, 10 + get_level_s(RECALL, 150), FALSE); + } + else + { + fetch(5, 10 + get_level_s(RECALL, 150), TRUE); + } + return CAST; + } + else + { + return NO_CAST; + } +} + +char *convey_recall_info() +{ + static char buf[128]; + int d = recall_get_d(); + int f = recall_get_f(); + + sprintf(buf, + "dur %d+d%d weight %dlb", + f, d, (1 + get_level_s(RECALL, 15))); + return buf; +} + +bool_ *convey_probability_travel() +{ + set_prob_travel(randint(20) + get_level_s(PROBABILITY_TRAVEL, 60)); + return CAST; +} + +char *convey_probability_travel_info() +{ + static char buf[128]; + sprintf(buf, + "dur %d+d20", + get_level_s(PROBABILITY_TRAVEL, 60)); + return buf; +} -- cgit v1.2.3 From a8c1bacade298c3166014a287cb5abc61244212b Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 12 Apr 2012 19:34:01 +0200 Subject: Lua: Move "Demonology" spell functions to C --- lib/mods/theme/scpt/s_demon.lua | 177 +++------------------ lib/scpt/s_demon.lua | 177 +++------------------ src/externs.h | 29 ++++ src/spells.pkg | 32 ++++ src/spells3.c | 332 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 429 insertions(+), 318 deletions(-) diff --git a/lib/mods/theme/scpt/s_demon.lua b/lib/mods/theme/scpt/s_demon.lua index ada97310..d8f29a60 100644 --- a/lib/mods/theme/scpt/s_demon.lua +++ b/lib/mods/theme/scpt/s_demon.lua @@ -20,24 +20,8 @@ DEMON_BLADE = add_spell ["max_level"] = { 20, 40 }, }, }, - ["spell"] = function() - local type, rad - - type = GF_FIRE - if get_level(DEMON_BLADE) >= 30 then type = GF_HELL_FIRE end - - rad = 0 - if get_level(DEMON_BLADE) >= 45 then rad = 1 end - - return set_project(randint(20) + get_level(DEMON_BLADE, 80), - type, - 4 + get_level(DEMON_BLADE, 40), - rad, - bor(PROJECT_STOP, PROJECT_KILL)) - end, - ["info"] = function() - return "dur "..(get_level(DEMON_BLADE, 80)).."+d20 dam "..(4 + get_level(DEMON_BLADE, 40)).."/blow" - end, + ["spell"] = function() return demonology_demon_blade() end, + ["info"] = function() return demonology_demon_blade_info() end, ["desc"] = { "Imbues your blade with fire to deal more damage", "At level 30 it deals hellfire damage", @@ -54,35 +38,8 @@ DEMON_MADNESS = add_spell ["mana_max"] = 20, ["fail"] = 25, ["random"] = 0, - ["spell"] = function() - local ret, dir, type, y1, x1, y2, x2 - - ret, dir = get_aim_dir() - if ret == FALSE then return end - - type = GF_CHAOS - if magik(33) == TRUE then type = GF_CONFUSION end - if magik(33) == TRUE then type = GF_CHARM end - - -- Calc the coordinates of arrival - y1, x1 = get_target(dir) - y2 = player.py - (y1 - player.py) - x2 = player.px - (x1 - player.px) - - local obvious = nil - obvious = project(0, 1 + get_level(DEMON_MADNESS, 4, 0), - y1, x1, - 20 + get_level(DEMON_MADNESS, 200), - type, bor(PROJECT_STOP, PROJECT_GRID, PROJECT_ITEM, PROJECT_KILL)) - obvious = is_obvious(project(0, 1 + get_level(DEMON_MADNESS, 4, 0), - y2, x2, - 20 + get_level(DEMON_MADNESS, 200), - type, bor(PROJECT_STOP, PROJECT_GRID, PROJECT_ITEM, PROJECT_KILL)), obvious) - return obvious - end, - ["info"] = function() - return "dam "..(20 + get_level(DEMON_MADNESS, 200)).." rad "..(1 + get_level(DEMON_MADNESS, 4, 0)) - end, + ["spell"] = function() return demonology_demon_madness() end, + ["info"] = function() return demonology_demon_madness_info() end, ["desc"] = { "Fire 2 balls in opposite directions of randomly chaos, confusion or charm", } @@ -97,16 +54,8 @@ DEMON_FIELD = add_spell ["mana_max"] = 60, ["fail"] = 60, ["random"] = 0, - ["spell"] = function() - local ret, dir - - ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_cloud(GF_NEXUS, dir, 20 + get_level(DEMON_FIELD, 70), 7, 30 + get_level(DEMON_FIELD, 100)) - end, - ["info"] = function() - return "dam "..(20 + get_level(DEMON_FIELD, 70)).." dur "..(30 + get_level(DEMON_FIELD, 100)) - end, + ["spell"] = function() return demonology_demon_field() end, + ["info"] = function() return demonology_demon_field_info() end, ["desc"] = { "Fires a cloud of deadly nexus over a radius of 7", } @@ -123,12 +72,8 @@ DOOM_SHIELD = add_spell ["mana_max"] = 30, ["fail"] = 10, ["random"] = 0, - ["spell"] = function() - return set_shield(randint(10) + 20 + get_level(DOOM_SHIELD, 100), -300 + get_level(DOOM_SHIELD, 100), SHIELD_COUNTER, 1 + get_level(DOOM_SHIELD, 14), 10 + get_level(DOOM_SHIELD, 15)) - end, - ["info"] = function() - return "dur "..(20 + get_level(DOOM_SHIELD, 100)).."+d10 dam "..(1 + get_level(DOOM_SHIELD, 14)).."d"..(10 + get_level(DOOM_SHIELD, 15)) - end, + ["spell"] = function() return demonology_doom_shield() end, + ["info"] = function() return demonology_doom_shield_info() end, ["desc"] = { "Raises a mirror of pain around you, doing very high damage to your foes", "that dare hit you, but greatly reduces your armour class", @@ -144,41 +89,8 @@ UNHOLY_WORD = add_spell ["mana_max"] = 45, ["fail"] = 55, ["random"] = 0, - ["spell"] = function() - local ret, x, y, c_ptr - ret, x, y = tgt_pt() - if ret == FALSE then return end - c_ptr = cave(y, x) - - -- ok that is a monster - if c_ptr.m_idx > 0 then - local m_ptr = monster(c_ptr.m_idx) - if m_ptr.status ~= MSTATUS_PET then - msg_print("You can only target a pet.") - return - end - - -- Oups he is angry now - if magik(30 - get_level(UNHOLY_WORD, 25, 0)) == TRUE then - local m_name = monster_desc(m_ptr, 0).." turns against you." - msg_print(strupper(strsub(m_name, 0, 1))..strsub(m_name, 2)) - else - local m_name = monster_desc(m_ptr, 0) - msg_print("You consume "..m_name..".") - - local heal = (m_ptr.hp * 100) / m_ptr.maxhp - heal = ((30 + get_level(UNHOLY_WORD, 50, 0)) * heal) / 100 - - hp_player(heal) - - delete_monster_idx(c_ptr.m_idx) - end - return TRUE - end - end, - ["info"] = function() - return "heal mhp% of "..(30 + get_level(UNHOLY_WORD, 50, 0)).."%" - end, + ["spell"] = function() return demonology_unholy_word() end, + ["info"] = function() return demonology_unholy_word_info() end, ["desc"] = { "Kills a pet to heal you", "There is a chance that the pet won't die but will turn against you", @@ -195,12 +107,8 @@ DEMON_CLOAK = add_spell ["mana_max"] = 40, ["fail"] = 70, ["random"] = 0, - ["spell"] = function() - return set_tim_reflect(randint(5) + 5 + get_level(DEMON_CLOAK, 15, 0)) - end, - ["info"] = function() - return "dur "..(5 + get_level(DEMON_CLOAK, 15, 0)).."+d5" - end, + ["spell"] = function() return demonology_demon_cloak() end, + ["info"] = function() return demonology_demon_cloak_info() end, ["desc"] = { "Raises a mirror that can reflect bolts and arrows for a time", } @@ -217,23 +125,8 @@ DEMON_SUMMON = add_spell ["mana_max"] = 50, ["fail"] = 30, ["random"] = 0, - ["spell"] = function() - local type = SUMMON_DEMON - local level = dun_level - local minlevel = 4 - if level < minlevel then level=minlevel end - summon_specific_level = 5 + get_level(DEMON_SUMMON, 100) - if get_level(DEMON_SUMMON) >= 35 then type = SUMMON_HI_DEMON end - if summon_monster(player.py, player.px, level, TRUE, type) == TRUE then - return TRUE - else - msg_print("Something blocks your summoning!") - return FALSE - end - end, - ["info"] = function() - return "level "..(5 + get_level(DEMON_SUMMON, 100)) - end, + ["spell"] = function() return demonology_summon_demon() end, + ["info"] = function() return demonology_summon_demon_info() end, ["desc"] = { "Summons a leveled demon to your side", "At level 35 it summons a high demon", @@ -249,37 +142,8 @@ DISCHARGE_MINION = add_spell ["mana_max"] = 50, ["fail"] = 30, ["random"] = 0, - ["spell"] = function() - local ret, x, y, c_ptr - ret, x, y = tgt_pt() - if ret == FALSE then return end - c_ptr = cave(y, x) - - -- ok that is a monster - if c_ptr.m_idx > 0 then - local m_ptr = monster(c_ptr.m_idx) - if m_ptr.status ~= MSTATUS_PET then - msg_print("You can only target a pet.") - return - end - - local dam = m_ptr.hp - delete_monster_idx(c_ptr.m_idx) - dam = (dam * (20 + get_level(DISCHARGE_MINION, 60, 0))) / 100 - if dam > 100 + get_level(DISCHARGE_MINION, 500, 0) then - dam = 100 + get_level(DISCHARGE_MINION, 500, 0) - end - - -- We use project instead of fire_ball because we must tell it exactly where to land - return project(0, 2, - y, x, - dam, - GF_GRAVITY, bor(PROJECT_STOP, PROJECT_GRID, PROJECT_ITEM, PROJECT_KILL)) - end - end, - ["info"] = function() - return "dam "..(20 + get_level(DISCHARGE_MINION, 60, 0)).."% max "..(100 + get_level(DISCHARGE_MINION, 500, 0)) - end, + ["spell"] = function() return demonology_discharge_minion() end, + ["info"] = function() return demonology_discharge_minion_info() end, ["desc"] = { "The targeted pet will explode in a burst of gravity", } @@ -294,13 +158,8 @@ CONTROL_DEMON = add_spell ["mana_max"] = 70, ["fail"] = 55, ["random"] = 0, - ["spell"] = function() - local ret, dir = get_aim_dir() - return fire_ball(GF_CONTROL_DEMON, dir, 50 + get_level(CONTROL_DEMON, 250), 0) - end, - ["info"] = function() - return "power "..(50 + get_level(CONTROL_DEMON, 250)) - end, + ["spell"] = function() return demonology_control_demon() end, + ["info"] = function() return demonology_control_demon_info() end, ["desc"] = { "Attempts to control a demon", } diff --git a/lib/scpt/s_demon.lua b/lib/scpt/s_demon.lua index ada97310..d8f29a60 100644 --- a/lib/scpt/s_demon.lua +++ b/lib/scpt/s_demon.lua @@ -20,24 +20,8 @@ DEMON_BLADE = add_spell ["max_level"] = { 20, 40 }, }, }, - ["spell"] = function() - local type, rad - - type = GF_FIRE - if get_level(DEMON_BLADE) >= 30 then type = GF_HELL_FIRE end - - rad = 0 - if get_level(DEMON_BLADE) >= 45 then rad = 1 end - - return set_project(randint(20) + get_level(DEMON_BLADE, 80), - type, - 4 + get_level(DEMON_BLADE, 40), - rad, - bor(PROJECT_STOP, PROJECT_KILL)) - end, - ["info"] = function() - return "dur "..(get_level(DEMON_BLADE, 80)).."+d20 dam "..(4 + get_level(DEMON_BLADE, 40)).."/blow" - end, + ["spell"] = function() return demonology_demon_blade() end, + ["info"] = function() return demonology_demon_blade_info() end, ["desc"] = { "Imbues your blade with fire to deal more damage", "At level 30 it deals hellfire damage", @@ -54,35 +38,8 @@ DEMON_MADNESS = add_spell ["mana_max"] = 20, ["fail"] = 25, ["random"] = 0, - ["spell"] = function() - local ret, dir, type, y1, x1, y2, x2 - - ret, dir = get_aim_dir() - if ret == FALSE then return end - - type = GF_CHAOS - if magik(33) == TRUE then type = GF_CONFUSION end - if magik(33) == TRUE then type = GF_CHARM end - - -- Calc the coordinates of arrival - y1, x1 = get_target(dir) - y2 = player.py - (y1 - player.py) - x2 = player.px - (x1 - player.px) - - local obvious = nil - obvious = project(0, 1 + get_level(DEMON_MADNESS, 4, 0), - y1, x1, - 20 + get_level(DEMON_MADNESS, 200), - type, bor(PROJECT_STOP, PROJECT_GRID, PROJECT_ITEM, PROJECT_KILL)) - obvious = is_obvious(project(0, 1 + get_level(DEMON_MADNESS, 4, 0), - y2, x2, - 20 + get_level(DEMON_MADNESS, 200), - type, bor(PROJECT_STOP, PROJECT_GRID, PROJECT_ITEM, PROJECT_KILL)), obvious) - return obvious - end, - ["info"] = function() - return "dam "..(20 + get_level(DEMON_MADNESS, 200)).." rad "..(1 + get_level(DEMON_MADNESS, 4, 0)) - end, + ["spell"] = function() return demonology_demon_madness() end, + ["info"] = function() return demonology_demon_madness_info() end, ["desc"] = { "Fire 2 balls in opposite directions of randomly chaos, confusion or charm", } @@ -97,16 +54,8 @@ DEMON_FIELD = add_spell ["mana_max"] = 60, ["fail"] = 60, ["random"] = 0, - ["spell"] = function() - local ret, dir - - ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_cloud(GF_NEXUS, dir, 20 + get_level(DEMON_FIELD, 70), 7, 30 + get_level(DEMON_FIELD, 100)) - end, - ["info"] = function() - return "dam "..(20 + get_level(DEMON_FIELD, 70)).." dur "..(30 + get_level(DEMON_FIELD, 100)) - end, + ["spell"] = function() return demonology_demon_field() end, + ["info"] = function() return demonology_demon_field_info() end, ["desc"] = { "Fires a cloud of deadly nexus over a radius of 7", } @@ -123,12 +72,8 @@ DOOM_SHIELD = add_spell ["mana_max"] = 30, ["fail"] = 10, ["random"] = 0, - ["spell"] = function() - return set_shield(randint(10) + 20 + get_level(DOOM_SHIELD, 100), -300 + get_level(DOOM_SHIELD, 100), SHIELD_COUNTER, 1 + get_level(DOOM_SHIELD, 14), 10 + get_level(DOOM_SHIELD, 15)) - end, - ["info"] = function() - return "dur "..(20 + get_level(DOOM_SHIELD, 100)).."+d10 dam "..(1 + get_level(DOOM_SHIELD, 14)).."d"..(10 + get_level(DOOM_SHIELD, 15)) - end, + ["spell"] = function() return demonology_doom_shield() end, + ["info"] = function() return demonology_doom_shield_info() end, ["desc"] = { "Raises a mirror of pain around you, doing very high damage to your foes", "that dare hit you, but greatly reduces your armour class", @@ -144,41 +89,8 @@ UNHOLY_WORD = add_spell ["mana_max"] = 45, ["fail"] = 55, ["random"] = 0, - ["spell"] = function() - local ret, x, y, c_ptr - ret, x, y = tgt_pt() - if ret == FALSE then return end - c_ptr = cave(y, x) - - -- ok that is a monster - if c_ptr.m_idx > 0 then - local m_ptr = monster(c_ptr.m_idx) - if m_ptr.status ~= MSTATUS_PET then - msg_print("You can only target a pet.") - return - end - - -- Oups he is angry now - if magik(30 - get_level(UNHOLY_WORD, 25, 0)) == TRUE then - local m_name = monster_desc(m_ptr, 0).." turns against you." - msg_print(strupper(strsub(m_name, 0, 1))..strsub(m_name, 2)) - else - local m_name = monster_desc(m_ptr, 0) - msg_print("You consume "..m_name..".") - - local heal = (m_ptr.hp * 100) / m_ptr.maxhp - heal = ((30 + get_level(UNHOLY_WORD, 50, 0)) * heal) / 100 - - hp_player(heal) - - delete_monster_idx(c_ptr.m_idx) - end - return TRUE - end - end, - ["info"] = function() - return "heal mhp% of "..(30 + get_level(UNHOLY_WORD, 50, 0)).."%" - end, + ["spell"] = function() return demonology_unholy_word() end, + ["info"] = function() return demonology_unholy_word_info() end, ["desc"] = { "Kills a pet to heal you", "There is a chance that the pet won't die but will turn against you", @@ -195,12 +107,8 @@ DEMON_CLOAK = add_spell ["mana_max"] = 40, ["fail"] = 70, ["random"] = 0, - ["spell"] = function() - return set_tim_reflect(randint(5) + 5 + get_level(DEMON_CLOAK, 15, 0)) - end, - ["info"] = function() - return "dur "..(5 + get_level(DEMON_CLOAK, 15, 0)).."+d5" - end, + ["spell"] = function() return demonology_demon_cloak() end, + ["info"] = function() return demonology_demon_cloak_info() end, ["desc"] = { "Raises a mirror that can reflect bolts and arrows for a time", } @@ -217,23 +125,8 @@ DEMON_SUMMON = add_spell ["mana_max"] = 50, ["fail"] = 30, ["random"] = 0, - ["spell"] = function() - local type = SUMMON_DEMON - local level = dun_level - local minlevel = 4 - if level < minlevel then level=minlevel end - summon_specific_level = 5 + get_level(DEMON_SUMMON, 100) - if get_level(DEMON_SUMMON) >= 35 then type = SUMMON_HI_DEMON end - if summon_monster(player.py, player.px, level, TRUE, type) == TRUE then - return TRUE - else - msg_print("Something blocks your summoning!") - return FALSE - end - end, - ["info"] = function() - return "level "..(5 + get_level(DEMON_SUMMON, 100)) - end, + ["spell"] = function() return demonology_summon_demon() end, + ["info"] = function() return demonology_summon_demon_info() end, ["desc"] = { "Summons a leveled demon to your side", "At level 35 it summons a high demon", @@ -249,37 +142,8 @@ DISCHARGE_MINION = add_spell ["mana_max"] = 50, ["fail"] = 30, ["random"] = 0, - ["spell"] = function() - local ret, x, y, c_ptr - ret, x, y = tgt_pt() - if ret == FALSE then return end - c_ptr = cave(y, x) - - -- ok that is a monster - if c_ptr.m_idx > 0 then - local m_ptr = monster(c_ptr.m_idx) - if m_ptr.status ~= MSTATUS_PET then - msg_print("You can only target a pet.") - return - end - - local dam = m_ptr.hp - delete_monster_idx(c_ptr.m_idx) - dam = (dam * (20 + get_level(DISCHARGE_MINION, 60, 0))) / 100 - if dam > 100 + get_level(DISCHARGE_MINION, 500, 0) then - dam = 100 + get_level(DISCHARGE_MINION, 500, 0) - end - - -- We use project instead of fire_ball because we must tell it exactly where to land - return project(0, 2, - y, x, - dam, - GF_GRAVITY, bor(PROJECT_STOP, PROJECT_GRID, PROJECT_ITEM, PROJECT_KILL)) - end - end, - ["info"] = function() - return "dam "..(20 + get_level(DISCHARGE_MINION, 60, 0)).."% max "..(100 + get_level(DISCHARGE_MINION, 500, 0)) - end, + ["spell"] = function() return demonology_discharge_minion() end, + ["info"] = function() return demonology_discharge_minion_info() end, ["desc"] = { "The targeted pet will explode in a burst of gravity", } @@ -294,13 +158,8 @@ CONTROL_DEMON = add_spell ["mana_max"] = 70, ["fail"] = 55, ["random"] = 0, - ["spell"] = function() - local ret, dir = get_aim_dir() - return fire_ball(GF_CONTROL_DEMON, dir, 50 + get_level(CONTROL_DEMON, 250), 0) - end, - ["info"] = function() - return "power "..(50 + get_level(CONTROL_DEMON, 250)) - end, + ["spell"] = function() return demonology_control_demon() end, + ["info"] = function() return demonology_control_demon_info() end, ["desc"] = { "Attempts to control a demon", } diff --git a/src/externs.h b/src/externs.h index 6a3bdb07..a7fd0c42 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1441,6 +1441,35 @@ char *convey_recall_info(); bool_ *convey_probability_travel(); char *convey_probability_travel_info(); +extern s32b DEMON_BLADE; +extern s32b DEMON_MADNESS; +extern s32b DEMON_FIELD; +extern s32b DOOM_SHIELD; +extern s32b UNHOLY_WORD; +extern s32b DEMON_CLOAK; +extern s32b DEMON_SUMMON; +extern s32b DISCHARGE_MINION; +extern s32b CONTROL_DEMON; + +bool_ *demonology_demon_blade(); +char *demonology_demon_blade_info(); +bool_ *demonology_demon_madness(); +char *demonology_demon_madness_info(); +bool_ *demonology_demon_field(); +char *demonology_demon_field_info(); +bool_ *demonology_doom_shield(); +char *demonology_doom_shield_info(); +bool_ *demonology_unholy_word(); +char *demonology_unholy_word_info(); +bool_ *demonology_demon_cloak(); +char *demonology_demon_cloak_info(); +bool_ *demonology_summon_demon(); +char *demonology_summon_demon_info(); +bool_ *demonology_discharge_minion(); +char *demonology_discharge_minion_info(); +bool_ *demonology_control_demon(); +char *demonology_control_demon_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index f1a83a23..040001ff 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2467,3 +2467,35 @@ bool_ *convey_recall(); char *convey_recall_info(); bool_ *convey_probability_travel(); char *convey_probability_travel_info(); + +/* + * Demonology + */ +extern s32b DEMON_BLADE; +extern s32b DEMON_MADNESS; +extern s32b DEMON_FIELD; +extern s32b DOOM_SHIELD; +extern s32b UNHOLY_WORD; +extern s32b DEMON_CLOAK; +extern s32b DEMON_SUMMON; +extern s32b DISCHARGE_MINION; +extern s32b CONTROL_DEMON; + +bool_ *demonology_demon_blade(); +char *demonology_demon_blade_info(); +bool_ *demonology_demon_madness(); +char *demonology_demon_madness_info(); +bool_ *demonology_demon_field(); +char *demonology_demon_field_info(); +bool_ *demonology_doom_shield(); +char *demonology_doom_shield_info(); +bool_ *demonology_unholy_word(); +char *demonology_unholy_word_info(); +bool_ *demonology_demon_cloak(); +char *demonology_demon_cloak_info(); +bool_ *demonology_summon_demon(); +char *demonology_summon_demon_info(); +bool_ *demonology_discharge_minion(); +char *demonology_discharge_minion_info(); +bool_ *demonology_control_demon(); +char *demonology_control_demon_info(); diff --git a/src/spells3.c b/src/spells3.c index dd75aac0..3e95c92d 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -14,6 +14,16 @@ s32b TELEAWAY; s32b RECALL; s32b PROBABILITY_TRAVEL; +s32b DEMON_BLADE; +s32b DEMON_MADNESS; +s32b DEMON_FIELD; +s32b DOOM_SHIELD; +s32b UNHOLY_WORD; +s32b DEMON_CLOAK; +s32b DEMON_SUMMON; +s32b DISCHARGE_MINION; +s32b CONTROL_DEMON; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua cares about). */ @@ -354,3 +364,325 @@ char *convey_probability_travel_info() get_level_s(PROBABILITY_TRAVEL, 60)); return buf; } + +bool_ *demonology_demon_blade() +{ + int rad, type; + + type = GF_FIRE; + if (get_level_s(DEMON_BLADE, 50) >= 30) + { + type = GF_HELL_FIRE; + } + + rad = 0; + if (get_level_s(DEMON_BLADE, 50) >= 45) + { + rad = 1; + } + + set_project(randint(20) + get_level_s(DEMON_BLADE, 80), + type, + 4 + get_level_s(DEMON_BLADE, 40), + rad, + PROJECT_STOP | PROJECT_KILL); + return CAST; +} + +char *demonology_demon_blade_info() +{ + static char buf[128]; + sprintf(buf, + "dur %d+d20 dam %d/blow", + (get_level_s(DEMON_BLADE, 80)), + (4 + get_level_s(DEMON_BLADE, 40))); + return buf; +} + +bool_ *demonology_demon_madness() +{ + int dir, type, y1, x1, y2, x2; + + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + type = GF_CHAOS; + if (magik(33)) + { + type = GF_CONFUSION; + } + if (magik(33)) + { + type = GF_CHARM; + } + + /* Calc the coordinates of arrival */ + get_target(dir, &y1, &x1); + y2 = p_ptr->py - (y1 - p_ptr->py); + x2 = p_ptr->px - (x1 - p_ptr->px); + + project(0, 1 + get_level(DEMON_MADNESS, 4, 0), + y1, x1, + 20 + get_level_s(DEMON_MADNESS, 200), + type, + PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL); + project(0, 1 + get_level(DEMON_MADNESS, 4, 0), + y2, x2, + 20 + get_level_s(DEMON_MADNESS, 200), + type, + PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL); + + return CAST; +} + +char *demonology_demon_madness_info() +{ + static char buf[128]; + sprintf(buf, + "dam %d rad %d", + (20 + get_level_s(DEMON_MADNESS, 200)), + (1 + get_level(DEMON_MADNESS, 4, 0))); + return buf; +} + +bool_ *demonology_demon_field() +{ + int dir; + + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + fire_cloud(GF_NEXUS, + dir, + 20 + get_level_s(DEMON_FIELD, 70), + 7, + 30 + get_level_s(DEMON_FIELD, 100)); + return CAST; +} + +char *demonology_demon_field_info() +{ + static char buf[128]; + sprintf(buf, + "dam %d dur %d", + (20 + get_level_s(DEMON_FIELD, 70)), + (30 + get_level_s(DEMON_FIELD, 100))); + return buf; +} + +bool_ *demonology_doom_shield() +{ + set_shield(randint(10) + 20 + get_level_s(DOOM_SHIELD, 100), + -300 + get_level_s(DOOM_SHIELD, 100), + SHIELD_COUNTER, + 1 + get_level_s(DOOM_SHIELD, 14), + 10 + get_level_s(DOOM_SHIELD, 15)); + return CAST; +} + +char *demonology_doom_shield_info() +{ + static char buf[128]; + sprintf(buf, + "dur %d+d10 dam %dd%d", + (20 + get_level_s(DOOM_SHIELD, 100)), + (1 + get_level_s(DOOM_SHIELD, 14)), + (10 + get_level_s(DOOM_SHIELD, 15))); + return buf; +} + +bool_ *demonology_unholy_word() +{ + int x, y; + cave_type *c_ptr = NULL; + + if (!tgt_pt(&x, &y)) + { + return NO_CAST; + } + + c_ptr = &cave[y][x]; + if (c_ptr->m_idx > 0) + { + monster_type *m_ptr = &m_list[c_ptr->m_idx]; + + if (m_ptr->status != MSTATUS_PET) + { + msg_print("You can only target a pet."); + return NO_CAST; + } + + /* Oops he is angry now */ + if (magik(30 - get_level(UNHOLY_WORD, 25, 0))) + { + char buf[128]; + monster_desc(buf, m_ptr, 0); + if (buf[0] != '\0') + { + buf[0] = toupper(buf[0]); + } + + msg_format("%s turns against you.", buf); + } + else + { + char buf[128]; + s32b heal; + + monster_desc(buf, m_ptr, 0); + msg_format("You consume %s.", buf); + + heal = (m_ptr->hp * 100) / m_ptr->maxhp; + heal = ((30 + get_level(UNHOLY_WORD, 50, 0)) * heal) / 100; + + hp_player(heal); + + delete_monster_idx(c_ptr->m_idx); + } + + return CAST; + } + else + { + return NO_CAST; + } +} + +char *demonology_unholy_word_info() +{ + static char buf[128]; + sprintf(buf, + "heal mhp%% of %d%%", + (30 + get_level(UNHOLY_WORD, 50, 0))); + return buf; +} + +bool_ *demonology_demon_cloak() +{ + set_tim_reflect(randint(5) + 5 + get_level(DEMON_CLOAK, 15, 0)); + return CAST; +} + +char *demonology_demon_cloak_info() +{ + static char buf[128]; + sprintf(buf, + "dur %d+d5", + (5 + get_level(DEMON_CLOAK, 15, 0))); + return buf; +} + +bool_ *demonology_summon_demon() +{ + int type, level, minlevel; + + level = dun_level; + + minlevel = 4; + if (level < minlevel) + { + level = minlevel; + } + + summon_specific_level = 5 + get_level_s(DEMON_SUMMON, 100); + + type = SUMMON_DEMON; + if (get_level_s(DEMON_SUMMON, 50) >= 35) + { + type = SUMMON_HI_DEMON; + } + + if (!summon_specific_friendly(p_ptr->py, p_ptr->px, level, type, TRUE)) + { + msg_print("Something blocks your summoning!"); + } + + return CAST; +} + +char *demonology_summon_demon_info() +{ + static char buf[128]; + sprintf(buf, + "level %d", + (5 + get_level_s(DEMON_SUMMON, 100))); + return buf; +} + +bool_ *demonology_discharge_minion() +{ + cave_type *c_ptr; + int x, y; + + if (!tgt_pt(&x, &y)) + { + return NO_CAST; + } + + c_ptr = &cave[y][x]; + if (c_ptr->m_idx > 0) + { + s32b dam; + monster_type *m_ptr = &m_list[c_ptr->m_idx]; + + if (m_ptr->status != MSTATUS_PET) + { + msg_print("You can only target a pet."); + return NO_CAST; + } + + delete_monster_idx(c_ptr->m_idx); + + dam = m_ptr->hp; + dam = (dam * (20 + get_level(DISCHARGE_MINION, 60, 0))) / 100; + if (dam > 100 + get_level(DISCHARGE_MINION, 500, 0)) + { + dam = 100 + get_level(DISCHARGE_MINION, 500, 0); + } + + /* We use project instead of fire_ball because we must tell it exactly where to land */ + project(0, 2, y, x, dam, + GF_GRAVITY, + PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL); + return CAST; + } + else + { + return NO_CAST; + } +} + +char *demonology_discharge_minion_info() +{ + static char buf[128]; + sprintf(buf, + "dam %d%% max %d", + (20 + get_level(DISCHARGE_MINION, 60, 0)), + (100 + get_level(DISCHARGE_MINION, 500, 0))); + return buf; +} + +bool_ *demonology_control_demon() +{ + int dir; + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + fire_ball(GF_CONTROL_DEMON, dir, 50 + get_level_s(CONTROL_DEMON, 250), 0); + return CAST; +} + +char *demonology_control_demon_info() +{ + static char buf[128]; + sprintf(buf, + "power %d", + (50 + get_level_s(CONTROL_DEMON, 250))); + return buf; +} -- cgit v1.2.3 From 976ca14dbe8d44b0653927a656d352a1c7de4897 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 12 Apr 2012 20:57:46 +0200 Subject: Lua: Move "Divination" spell functions to C --- lib/mods/theme/scpt/s_divin.lua | 101 +++---------------------- lib/scpt/s_divin.lua | 101 +++---------------------- src/externs.h | 20 +++++ src/spells.pkg | 23 ++++++ src/spells3.c | 163 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 230 insertions(+), 178 deletions(-) diff --git a/lib/mods/theme/scpt/s_divin.lua b/lib/mods/theme/scpt/s_divin.lua index 60b0275f..e077f1f0 100644 --- a/lib/mods/theme/scpt/s_divin.lua +++ b/lib/mods/theme/scpt/s_divin.lua @@ -9,17 +9,8 @@ STARIDENTIFY = add_spell ["mana"] = 30, ["mana_max"] = 30, ["fail"] = 80, - ["spell"] = function() - if get_check("Cast on yourself?") == TRUE then - self_knowledge() - else - identify_fully() - end - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return divination_greater_identify() end, + ["info"] = function() return divination_greater_identify_info() end, ["desc"] = { "Asks for an object and fully identify it, providing the full list of powers", "Cast at yourself it will reveal your powers" @@ -44,34 +35,8 @@ IDENTIFY = add_spell ["max_level"] = { 15, 40 }, }, }, - ["spell"] = function() - if get_level(IDENTIFY, 50) >= 27 then - local obvious - obvious = identify_pack() - obvious = is_obvious(fire_ball(GF_IDENTIFY, 0, 1, get_level(IDENTIFY, 3)), obvious) - if obvious == TRUE then - player.notice = bor(player.notice, PN_COMBINE, PN_REORDER) - end - return obvious - elseif get_level(IDENTIFY, 50) >= 17 then - local obvious - obvious = identify_pack() - obvious = is_obvious(fire_ball(GF_IDENTIFY, 0, 1, 0), obvious) - if obvious == TRUE then - player.notice = bor(player.notice, PN_COMBINE, PN_REORDER) - end - return obvious - else - if ident_spell() == TRUE then return TRUE else return end - end - end, - ["info"] = function() - if get_level(IDENTIFY, 50) >= 27 then - return "rad "..(get_level(IDENTIFY, 3)) - else - return "" - end - end, + ["spell"] = function() return divination_identify() end, + ["info"] = function() return divination_identify_info() end, ["desc"] = { "Asks for an object and identifies it", "At level 17 it identifies all objects in the inventory", @@ -99,17 +64,8 @@ VISION = add_spell }, }, ["inertia"] = { 2, 200 }, - ["spell"] = function() - if get_level(VISION, 50) >= 25 then - wiz_lite_extra() - else - map_area() - end - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return divination_vision() end, + ["info"] = function() return divination_vision_info() end, ["desc"] = { "Detects the layout of the surrounding area", "At level 25 it maps and lights the whole level", @@ -135,21 +91,8 @@ SENSEHIDDEN = add_spell }, }, ["inertia"] = { 1, 10 }, - ["spell"] = function() - local obvious = nil - obvious = detect_traps(15 + get_level(SENSEHIDDEN, 40, 0)) - if get_level(SENSEHIDDEN, 50) >= 15 then - obvious = is_obvious(set_tim_invis(10 + randint(20) + get_level(SENSEHIDDEN, 40)), obvious) - end - return obvious - end, - ["info"] = function() - if get_level(SENSEHIDDEN, 50) >= 15 then - return "rad "..(15 + get_level(SENSEHIDDEN, 40)).." dur "..(10 + get_level(SENSEHIDDEN, 40)).."+d20" - else - return "rad "..(15 + get_level(SENSEHIDDEN, 40)) - end - end, + ["spell"] = function() return divination_sense_hidden() end, + ["info"] = function() return divination_sense_hidden_info() end, ["desc"] = { "Detects the traps in a certain radius around you", "At level 15 it allows you to sense invisible for a while" @@ -175,15 +118,8 @@ REVEALWAYS = add_spell }, }, ["inertia"] = { 1, 10 }, - ["spell"] = function() - local obvious - obvious = detect_doors(10 + get_level(REVEALWAYS, 40, 0)) - obvious = is_obvious(detect_stairs(10 + get_level(REVEALWAYS, 40, 0)), obvious) - return obvious - end, - ["info"] = function() - return "rad "..(10 + get_level(REVEALWAYS, 40)) - end, + ["spell"] = function() return divination_reveal_ways() end, + ["info"] = function() return divination_reveal_ways_info() end, ["desc"] = { "Detects the doors/stairs/ways in a certain radius around you", } @@ -208,21 +144,8 @@ SENSEMONSTERS = add_spell }, }, ["inertia"] = { 1, 10 }, - ["spell"] = function() - local obvious - obvious = detect_monsters_normal(10 + get_level(SENSEMONSTERS, 40, 0)) - if get_level(SENSEMONSTERS, 50) >= 30 then - obvious = is_obvious(set_tim_esp(10 + randint(10) + get_level(SENSEMONSTERS, 20)), obvious) - end - return obvious - end, - ["info"] = function() - if get_level(SENSEMONSTERS, 50) >= 30 then - return "rad "..(10 + get_level(SENSEMONSTERS, 40)).." dur "..(10 + get_level(SENSEMONSTERS, 20)).."+d10" - else - return "rad "..(10 + get_level(SENSEMONSTERS, 40)) - end - end, + ["spell"] = function() return divination_sense_monsters() end, + ["info"] = function() return divination_sense_monsters_info() end, ["desc"] = { "Detects all monsters near you", "At level 30 it allows you to sense monster minds for a while" diff --git a/lib/scpt/s_divin.lua b/lib/scpt/s_divin.lua index 60b0275f..e077f1f0 100644 --- a/lib/scpt/s_divin.lua +++ b/lib/scpt/s_divin.lua @@ -9,17 +9,8 @@ STARIDENTIFY = add_spell ["mana"] = 30, ["mana_max"] = 30, ["fail"] = 80, - ["spell"] = function() - if get_check("Cast on yourself?") == TRUE then - self_knowledge() - else - identify_fully() - end - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return divination_greater_identify() end, + ["info"] = function() return divination_greater_identify_info() end, ["desc"] = { "Asks for an object and fully identify it, providing the full list of powers", "Cast at yourself it will reveal your powers" @@ -44,34 +35,8 @@ IDENTIFY = add_spell ["max_level"] = { 15, 40 }, }, }, - ["spell"] = function() - if get_level(IDENTIFY, 50) >= 27 then - local obvious - obvious = identify_pack() - obvious = is_obvious(fire_ball(GF_IDENTIFY, 0, 1, get_level(IDENTIFY, 3)), obvious) - if obvious == TRUE then - player.notice = bor(player.notice, PN_COMBINE, PN_REORDER) - end - return obvious - elseif get_level(IDENTIFY, 50) >= 17 then - local obvious - obvious = identify_pack() - obvious = is_obvious(fire_ball(GF_IDENTIFY, 0, 1, 0), obvious) - if obvious == TRUE then - player.notice = bor(player.notice, PN_COMBINE, PN_REORDER) - end - return obvious - else - if ident_spell() == TRUE then return TRUE else return end - end - end, - ["info"] = function() - if get_level(IDENTIFY, 50) >= 27 then - return "rad "..(get_level(IDENTIFY, 3)) - else - return "" - end - end, + ["spell"] = function() return divination_identify() end, + ["info"] = function() return divination_identify_info() end, ["desc"] = { "Asks for an object and identifies it", "At level 17 it identifies all objects in the inventory", @@ -99,17 +64,8 @@ VISION = add_spell }, }, ["inertia"] = { 2, 200 }, - ["spell"] = function() - if get_level(VISION, 50) >= 25 then - wiz_lite_extra() - else - map_area() - end - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return divination_vision() end, + ["info"] = function() return divination_vision_info() end, ["desc"] = { "Detects the layout of the surrounding area", "At level 25 it maps and lights the whole level", @@ -135,21 +91,8 @@ SENSEHIDDEN = add_spell }, }, ["inertia"] = { 1, 10 }, - ["spell"] = function() - local obvious = nil - obvious = detect_traps(15 + get_level(SENSEHIDDEN, 40, 0)) - if get_level(SENSEHIDDEN, 50) >= 15 then - obvious = is_obvious(set_tim_invis(10 + randint(20) + get_level(SENSEHIDDEN, 40)), obvious) - end - return obvious - end, - ["info"] = function() - if get_level(SENSEHIDDEN, 50) >= 15 then - return "rad "..(15 + get_level(SENSEHIDDEN, 40)).." dur "..(10 + get_level(SENSEHIDDEN, 40)).."+d20" - else - return "rad "..(15 + get_level(SENSEHIDDEN, 40)) - end - end, + ["spell"] = function() return divination_sense_hidden() end, + ["info"] = function() return divination_sense_hidden_info() end, ["desc"] = { "Detects the traps in a certain radius around you", "At level 15 it allows you to sense invisible for a while" @@ -175,15 +118,8 @@ REVEALWAYS = add_spell }, }, ["inertia"] = { 1, 10 }, - ["spell"] = function() - local obvious - obvious = detect_doors(10 + get_level(REVEALWAYS, 40, 0)) - obvious = is_obvious(detect_stairs(10 + get_level(REVEALWAYS, 40, 0)), obvious) - return obvious - end, - ["info"] = function() - return "rad "..(10 + get_level(REVEALWAYS, 40)) - end, + ["spell"] = function() return divination_reveal_ways() end, + ["info"] = function() return divination_reveal_ways_info() end, ["desc"] = { "Detects the doors/stairs/ways in a certain radius around you", } @@ -208,21 +144,8 @@ SENSEMONSTERS = add_spell }, }, ["inertia"] = { 1, 10 }, - ["spell"] = function() - local obvious - obvious = detect_monsters_normal(10 + get_level(SENSEMONSTERS, 40, 0)) - if get_level(SENSEMONSTERS, 50) >= 30 then - obvious = is_obvious(set_tim_esp(10 + randint(10) + get_level(SENSEMONSTERS, 20)), obvious) - end - return obvious - end, - ["info"] = function() - if get_level(SENSEMONSTERS, 50) >= 30 then - return "rad "..(10 + get_level(SENSEMONSTERS, 40)).." dur "..(10 + get_level(SENSEMONSTERS, 20)).."+d10" - else - return "rad "..(10 + get_level(SENSEMONSTERS, 40)) - end - end, + ["spell"] = function() return divination_sense_monsters() end, + ["info"] = function() return divination_sense_monsters_info() end, ["desc"] = { "Detects all monsters near you", "At level 30 it allows you to sense monster minds for a while" diff --git a/src/externs.h b/src/externs.h index a7fd0c42..168fd2ab 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1470,6 +1470,26 @@ char *demonology_discharge_minion_info(); bool_ *demonology_control_demon(); char *demonology_control_demon_info(); +extern s32b STARIDENTIFY; +extern s32b IDENTIFY; +extern s32b VISION; +extern s32b SENSEHIDDEN; +extern s32b REVEALWAYS; +extern s32b SENSEMONSTERS; + +bool_ *divination_greater_identify(); +char *divination_greater_identify_info(); +bool_ *divination_identify(); +char *divination_identify_info(); +bool_ *divination_vision(); +char *divination_vision_info(); +bool_ *divination_sense_hidden(); +char *divination_sense_hidden_info(); +bool_ *divination_reveal_ways(); +char *divination_reveal_ways_info(); +bool_ *divination_sense_monsters(); +char *divination_sense_monsters_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index 040001ff..5cf18354 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2499,3 +2499,26 @@ bool_ *demonology_discharge_minion(); char *demonology_discharge_minion_info(); bool_ *demonology_control_demon(); char *demonology_control_demon_info(); + +/* + * Divination + */ +extern s32b STARIDENTIFY; +extern s32b IDENTIFY; +extern s32b VISION; +extern s32b SENSEHIDDEN; +extern s32b REVEALWAYS; +extern s32b SENSEMONSTERS; + +bool_ *divination_greater_identify(); +char *divination_greater_identify_info(); +bool_ *divination_identify(); +char *divination_identify_info(); +bool_ *divination_vision(); +char *divination_vision_info(); +bool_ *divination_sense_hidden(); +char *divination_sense_hidden_info(); +bool_ *divination_reveal_ways(); +char *divination_reveal_ways_info(); +bool_ *divination_sense_monsters(); +char *divination_sense_monsters_info(); diff --git a/src/spells3.c b/src/spells3.c index 3e95c92d..086c6940 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -24,6 +24,13 @@ s32b DEMON_SUMMON; s32b DISCHARGE_MINION; s32b CONTROL_DEMON; +s32b STARIDENTIFY; +s32b IDENTIFY; +s32b VISION; +s32b SENSEHIDDEN; +s32b REVEALWAYS; +s32b SENSEMONSTERS; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua cares about). */ @@ -686,3 +693,159 @@ char *demonology_control_demon_info() (50 + get_level_s(CONTROL_DEMON, 250))); return buf; } + +bool_ *divination_greater_identify() +{ + if (get_check("Cast on yourself?")) + { + self_knowledge(NULL); + } + else + { + identify_fully(); + } + return CAST; +} + +char *divination_greater_identify_info() +{ + return ""; +} + +bool_ *divination_identify() +{ + if (get_level_s(IDENTIFY, 50) >= 27) + { + identify_pack(); + fire_ball(GF_IDENTIFY, 0, 1, get_level_s(IDENTIFY, 3)); + p_ptr->notice |= (PN_COMBINE | PN_REORDER); + return CAST; + } + else if (get_level_s(IDENTIFY, 50) >= 17) + { + identify_pack(); + fire_ball(GF_IDENTIFY, 0, 1, 0); + p_ptr->notice |= (PN_COMBINE | PN_REORDER); + return CAST; + } + else if (ident_spell() == TRUE) + { + return CAST; + } + else + { + return NO_CAST; + } +} + +char *divination_identify_info() +{ + static char buf[128]; + + if (get_level_s(IDENTIFY, 50) >= 27) + { + sprintf(buf, "rad %d", get_level_s(IDENTIFY, 3)); + return buf; + } + else + { + return ""; + } +} + +bool_ *divination_vision() +{ + if (get_level_s(VISION, 50) >= 25) + { + wiz_lite_extra(); + } + else + { + map_area(); + } + return CAST; + +} + +char *divination_vision_info() +{ + return ""; +} + +bool_ *divination_sense_hidden() +{ + detect_traps(15 + get_level(SENSEHIDDEN, 40, 0)); + if (get_level_s(SENSEHIDDEN, 50) >= 15) + { + set_tim_invis(10 + randint(20) + get_level_s(SENSEHIDDEN, 40)); + } + return CAST; +} + +char *divination_sense_hidden_info() +{ + static char buf[128]; + + if (get_level_s(SENSEHIDDEN, 50) >= 15) + { + sprintf(buf, + "rad %d dur %d+d20", + (15 + get_level_s(SENSEHIDDEN, 40)), + (10 + get_level_s(SENSEHIDDEN, 40))); + } + else + { + sprintf(buf, + "rad %d", + (15 + get_level_s(SENSEHIDDEN, 40))); + } + + return buf; +} + +bool_ *divination_reveal_ways() +{ + detect_doors(10 + get_level(REVEALWAYS, 40, 0)); + detect_stairs(10 + get_level(REVEALWAYS, 40, 0)); + return CAST; +} + +char *divination_reveal_ways_info() +{ + static char buf[128]; + sprintf(buf, + "rad %d", + (10 + get_level_s(REVEALWAYS, 40))); + return buf; +} + +bool_ *divination_sense_monsters() +{ + detect_monsters_normal(10 + get_level(SENSEMONSTERS, 40, 0)); + if (get_level_s(SENSEMONSTERS, 50) >= 30) + { + set_tim_esp(10 + randint(10) + get_level_s(SENSEMONSTERS, 20)); + } + return CAST; +} + +char *divination_sense_monsters_info() +{ + static char buf[128]; + + if (get_level_s(SENSEMONSTERS, 50) >= 30) + { + sprintf(buf, + "rad %d dur %d+d10", + (10 + get_level_s(SENSEMONSTERS, 40)), + (10 + get_level_s(SENSEMONSTERS, 20))); + } + else + { + sprintf(buf, + "rad %d", + (10 + get_level_s(SENSEMONSTERS, 40))); + } + + return buf; +} -- cgit v1.2.3 From 98c69abb1f65c27d586b9af0574a9b8bfb8265a7 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 13 Apr 2012 07:44:18 +0200 Subject: Lua: Move "Earth" spell functions to C --- lib/mods/theme/scpt/s_earth.lua | 81 +++----------------- lib/scpt/s_earth.lua | 81 +++----------------- src/externs.h | 17 +++++ src/spells.pkg | 20 +++++ src/spells3.c | 158 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 215 insertions(+), 142 deletions(-) diff --git a/lib/mods/theme/scpt/s_earth.lua b/lib/mods/theme/scpt/s_earth.lua index 23aa001c..9825fc84 100644 --- a/lib/mods/theme/scpt/s_earth.lua +++ b/lib/mods/theme/scpt/s_earth.lua @@ -9,22 +9,8 @@ STONESKIN = add_spell ["mana_max"] = 50, ["fail"] = 10, ["inertia"] = { 2, 50 }, - ["spell"] = function() - local type - if get_level(STONESKIN, 50) >= 25 then - type = SHIELD_COUNTER - else - type = 0 - end - return set_shield(randint(10) + 10 + get_level(STONESKIN, 100), 10 + get_level(STONESKIN, 50), type, 2 + get_level(STONESKIN, 5), 3 + get_level(STONESKIN, 5)) - end, - ["info"] = function() - if get_level(STONESKIN, 50) >= 25 then - return "dam "..(2 + get_level(STONESKIN, 5)).."d"..(3 + get_level(STONESKIN, 5)).." dur "..(10 + get_level(STONESKIN, 100)).."+d10 AC "..(10 + get_level(STONESKIN, 50)) - else - return "dur "..(10 + get_level(STONESKIN, 100)).."+d10 AC "..(10 + get_level(STONESKIN, 50)) - end - end, + ["spell"] = function() return earth_stone_skin() end, + ["info"] = function() return earth_stone_skin_info() end, ["desc"] = { "Creates a shield of earth around you to protect you", "At level 25 it starts dealing damage to attackers" @@ -49,15 +35,8 @@ DIG = add_spell ["max_level"] = { 1, 1 }, }, }, - ["spell"] = function() - local ret, dir - ret, dir = get_aim_dir() - if ret == FALSE then return end - return wall_to_mud(dir) - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return earth_dig() end, + ["info"] = function() return earth_dig_info() end, ["desc"] = { "Digs a hole in a wall much faster than any shovels", } @@ -81,20 +60,8 @@ STONEPRISON = add_spell ["max_level"] = { 5, 20 }, }, }, - ["spell"] = function() - local ret, x, y - if get_level(STONEPRISON, 50) >= 10 then - ret, x, y = tgt_pt() - else - y = player.py - x = player.px - end - wall_stone(y, x) - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return earth_stone_prison() end, + ["info"] = function() return earth_stone_prison_info() end, ["desc"] = { "Creates a prison of walls around you", "At level 10 it allows you to target a monster" @@ -119,23 +86,8 @@ STRIKE = add_spell ["max_level"] = { 10, 50 }, }, }, - ["spell"] = function() - local ret, dir, rad - ret, dir = get_aim_dir() - if ret == FALSE then return end - if get_level(STRIKE, 50) >= 12 then - return fire_ball(GF_FORCE, dir, 50 + get_level(STRIKE, 50), 1) - else - return fire_ball(GF_FORCE, dir, 50 + get_level(STRIKE, 50), 0) - end - end, - ["info"] = function() - if get_level(STRIKE, 50) >= 12 then - return "dam "..(50 + get_level(STRIKE, 50)).." rad 1" - else - return "dam "..(50 + get_level(STRIKE, 50)) - end - end, + ["spell"] = function() return earth_strike() end, + ["info"] = function() return earth_strike_info() end, ["desc"] = { "Creates a micro-ball of force that will push monsters backwards", "If the monster is caught near a wall, it'll be crushed against it", @@ -162,21 +114,8 @@ SHAKE = add_spell }, }, ["inertia"] = { 2, 50 }, - ["spell"] = function() - local ret, x, y - if get_level(SHAKE, 50) >= 10 then - ret, x, y = tgt_pt() - if ret == FALSE then return end - else - x = player.px - y = player.py - end - earthquake(y, x, 4 + get_level(SHAKE, 10)); - return TRUE - end, - ["info"] = function() - return "rad "..(4 + get_level(SHAKE, 10)) - end, + ["spell"] = function() return earth_shake() end, + ["info"] = function() return earth_shake_info() end, ["desc"] = { "Creates a localised earthquake", "At level 10 it can be targeted at any location" diff --git a/lib/scpt/s_earth.lua b/lib/scpt/s_earth.lua index 23aa001c..9825fc84 100644 --- a/lib/scpt/s_earth.lua +++ b/lib/scpt/s_earth.lua @@ -9,22 +9,8 @@ STONESKIN = add_spell ["mana_max"] = 50, ["fail"] = 10, ["inertia"] = { 2, 50 }, - ["spell"] = function() - local type - if get_level(STONESKIN, 50) >= 25 then - type = SHIELD_COUNTER - else - type = 0 - end - return set_shield(randint(10) + 10 + get_level(STONESKIN, 100), 10 + get_level(STONESKIN, 50), type, 2 + get_level(STONESKIN, 5), 3 + get_level(STONESKIN, 5)) - end, - ["info"] = function() - if get_level(STONESKIN, 50) >= 25 then - return "dam "..(2 + get_level(STONESKIN, 5)).."d"..(3 + get_level(STONESKIN, 5)).." dur "..(10 + get_level(STONESKIN, 100)).."+d10 AC "..(10 + get_level(STONESKIN, 50)) - else - return "dur "..(10 + get_level(STONESKIN, 100)).."+d10 AC "..(10 + get_level(STONESKIN, 50)) - end - end, + ["spell"] = function() return earth_stone_skin() end, + ["info"] = function() return earth_stone_skin_info() end, ["desc"] = { "Creates a shield of earth around you to protect you", "At level 25 it starts dealing damage to attackers" @@ -49,15 +35,8 @@ DIG = add_spell ["max_level"] = { 1, 1 }, }, }, - ["spell"] = function() - local ret, dir - ret, dir = get_aim_dir() - if ret == FALSE then return end - return wall_to_mud(dir) - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return earth_dig() end, + ["info"] = function() return earth_dig_info() end, ["desc"] = { "Digs a hole in a wall much faster than any shovels", } @@ -81,20 +60,8 @@ STONEPRISON = add_spell ["max_level"] = { 5, 20 }, }, }, - ["spell"] = function() - local ret, x, y - if get_level(STONEPRISON, 50) >= 10 then - ret, x, y = tgt_pt() - else - y = player.py - x = player.px - end - wall_stone(y, x) - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return earth_stone_prison() end, + ["info"] = function() return earth_stone_prison_info() end, ["desc"] = { "Creates a prison of walls around you", "At level 10 it allows you to target a monster" @@ -119,23 +86,8 @@ STRIKE = add_spell ["max_level"] = { 10, 50 }, }, }, - ["spell"] = function() - local ret, dir, rad - ret, dir = get_aim_dir() - if ret == FALSE then return end - if get_level(STRIKE, 50) >= 12 then - return fire_ball(GF_FORCE, dir, 50 + get_level(STRIKE, 50), 1) - else - return fire_ball(GF_FORCE, dir, 50 + get_level(STRIKE, 50), 0) - end - end, - ["info"] = function() - if get_level(STRIKE, 50) >= 12 then - return "dam "..(50 + get_level(STRIKE, 50)).." rad 1" - else - return "dam "..(50 + get_level(STRIKE, 50)) - end - end, + ["spell"] = function() return earth_strike() end, + ["info"] = function() return earth_strike_info() end, ["desc"] = { "Creates a micro-ball of force that will push monsters backwards", "If the monster is caught near a wall, it'll be crushed against it", @@ -162,21 +114,8 @@ SHAKE = add_spell }, }, ["inertia"] = { 2, 50 }, - ["spell"] = function() - local ret, x, y - if get_level(SHAKE, 50) >= 10 then - ret, x, y = tgt_pt() - if ret == FALSE then return end - else - x = player.px - y = player.py - end - earthquake(y, x, 4 + get_level(SHAKE, 10)); - return TRUE - end, - ["info"] = function() - return "rad "..(4 + get_level(SHAKE, 10)) - end, + ["spell"] = function() return earth_shake() end, + ["info"] = function() return earth_shake_info() end, ["desc"] = { "Creates a localised earthquake", "At level 10 it can be targeted at any location" diff --git a/src/externs.h b/src/externs.h index 168fd2ab..408a7046 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1490,6 +1490,23 @@ char *divination_reveal_ways_info(); bool_ *divination_sense_monsters(); char *divination_sense_monsters_info(); +extern s32b STONESKIN; +extern s32b DIG; +extern s32b STONEPRISON; +extern s32b STRIKE; +extern s32b SHAKE; + +bool_ *earth_stone_skin(); +char *earth_stone_skin_info(); +bool_ *earth_dig(); +char *earth_dig_info(); +bool_ *earth_stone_prison(); +char *earth_stone_prison_info(); +bool_ *earth_strike(); +char *earth_strike_info(); +bool_ *earth_shake(); +char *earth_shake_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index 5cf18354..e9e7c29d 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2522,3 +2522,23 @@ bool_ *divination_reveal_ways(); char *divination_reveal_ways_info(); bool_ *divination_sense_monsters(); char *divination_sense_monsters_info(); + +/* + * Earth + */ +extern s32b STONESKIN; +extern s32b DIG; +extern s32b STONEPRISON; +extern s32b STRIKE; +extern s32b SHAKE; + +bool_ *earth_stone_skin(); +char *earth_stone_skin_info(); +bool_ *earth_dig(); +char *earth_dig_info(); +bool_ *earth_stone_prison(); +char *earth_stone_prison_info(); +bool_ *earth_strike(); +char *earth_strike_info(); +bool_ *earth_shake(); +char *earth_shake_info(); diff --git a/src/spells3.c b/src/spells3.c index 086c6940..fc29ec00 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -31,6 +31,12 @@ s32b SENSEHIDDEN; s32b REVEALWAYS; s32b SENSEMONSTERS; +s32b STONESKIN; +s32b DIG; +s32b STONEPRISON; +s32b STRIKE; +s32b SHAKE; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua cares about). */ @@ -849,3 +855,155 @@ char *divination_sense_monsters_info() return buf; } + +bool_ *earth_stone_skin() +{ + int type; + + type = 0; + if (get_level_s(STONESKIN, 50) >= 25) + { + type = SHIELD_COUNTER; + } + + set_shield(randint(10) + 10 + get_level_s(STONESKIN, 100), + 10 + get_level_s(STONESKIN, 50), + type, + 2 + get_level_s(STONESKIN, 5), + 3 + get_level_s(STONESKIN, 5)); + return CAST; +} + +char *earth_stone_skin_info() +{ + static char buf[128]; + + if (get_level_s(STONESKIN, 50) >= 25) + { + sprintf(buf, + "dam %dd%d dur %d+d10 AC %d", + (2 + get_level_s(STONESKIN, 5)), + (3 + get_level_s(STONESKIN, 5)), + (10 + get_level_s(STONESKIN, 100)), + (10 + get_level_s(STONESKIN, 50))); + } + else + { + sprintf(buf, + "dur %d+d10 AC %d", + (10 + get_level_s(STONESKIN, 100)), + (10 + get_level_s(STONESKIN, 50))); + } + + return buf; +} + +bool_ *earth_dig() +{ + int dir; + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + wall_to_mud(dir); + return CAST; +} + +char *earth_dig_info() +{ + return ""; +} + +bool_ *earth_stone_prison() +{ + int x,y; + + if (get_level_s(STONEPRISON, 50) >= 10) + { + if (!tgt_pt(&x, &y)) + { + return NO_CAST; + } + } + else + { + y = p_ptr->py; + x = p_ptr->px; + } + + wall_stone(y, x); + return CAST; +} + +char *earth_stone_prison_info() +{ + return ""; +} + +bool_ *earth_strike() +{ + int dir, dmg; + + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + dmg = 50 + get_level_s(STRIKE, 50); + if (get_level_s(STRIKE, 50) >= 12) + { + fire_ball(GF_FORCE, dir, dmg, 1); + } + else + { + fire_ball(GF_FORCE, dir, dmg, 0); + } + + return CAST; +} + +char *earth_strike_info() +{ + static char buf[128]; + int dmg = 50 + get_level_s(STRIKE, 50); + + if (get_level_s(STRIKE, 50) >= 12) + { + sprintf(buf, "dam %d rad 1", dmg); + } + else + { + sprintf(buf, "dam %d", dmg); + } + + return buf; +} + +bool_ *earth_shake() +{ + int x,y; + + if (get_level_s(SHAKE, 50) >= 10) + { + if (!tgt_pt(&x, &y)) + { + return NO_CAST; + } + } + else + { + x = p_ptr->px; + y = p_ptr->py; + } + earthquake(y, x, 4 + get_level_s(SHAKE, 10)); + return CAST; +} + +char *earth_shake_info() +{ + static char buf[128]; + sprintf(buf, "rad %d", (4 + get_level_s(SHAKE, 10))); + return buf; +} + -- cgit v1.2.3 From 1e3740888ab90fe2e0ef04b1ae4e3b85c4b5b9b8 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 13 Apr 2012 18:36:50 +0200 Subject: Lua: Move "Eru" spell functions to C --- lib/mods/theme/scpt/s_eru.lua | 58 ++++------------------------ lib/scpt/s_eru.lua | 58 ++++------------------------ src/externs.h | 14 +++++++ src/spells.pkg | 17 ++++++++ src/spells3.c | 90 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 137 insertions(+), 100 deletions(-) diff --git a/lib/mods/theme/scpt/s_eru.lua b/lib/mods/theme/scpt/s_eru.lua index c0cb0aaf..d61b6118 100644 --- a/lib/mods/theme/scpt/s_eru.lua +++ b/lib/mods/theme/scpt/s_eru.lua @@ -14,24 +14,8 @@ ERU_SEE = add_spell -- Unnafected by blindness ["blind"] = FALSE, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local obvious - obvious = set_tim_invis(randint(20) + 10 + get_level(ERU_SEE, 100)) - if get_level(ERU_SEE) >= 30 then - wiz_lite_extra() - obvious = TRUE - elseif get_level(ERU_SEE) >= 10 then - map_area() - obvious = TRUE - end - if get_level(ERU_SEE) >= 20 then - obvious = is_obvious(set_blind(0), obvious) - end - return obvious - end, - ["info"] = function() - return "dur "..(10 + get_level(ERU_SEE, 100)).."+d20" - end, + ["spell"] = function() return eru_see_the_music() end, + ["info"] = function() return eru_see_the_music_info() end, ["desc"] = { "Allows you to 'see' the Great Music from which the world", "originates, allowing you to see unseen things", @@ -53,21 +37,8 @@ ERU_LISTEN = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - if get_level(ERU_LISTEN) >= 30 then - ident_all() - identify_pack() - return TRUE - elseif get_level(ERU_LISTEN) >= 14 then - identify_pack() - return TRUE - else - return ident_spell() - end - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return eru_listen_to_the_music() end, + ["info"] = function() return eru_listen_to_the_music_info() end, ["desc"] = { "Allows you to listen to the Great Music from which the world", "originates, allowing you to understand the meaning of things", @@ -88,17 +59,8 @@ ERU_UNDERSTAND = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - if get_level(ERU_UNDERSTAND) >= 10 then - identify_pack_fully() - return TRUE - else - return identify_fully() - end - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return eru_know_the_music() end, + ["info"] = function() return eru_know_the_music_info() end, ["desc"] = { "Allows you to understand the Great Music from which the world", "originates, allowing you to know the full abilities of things", @@ -118,12 +80,8 @@ ERU_PROT = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - return fire_ball(GF_MAKE_GLYPH, 0, 1, 1 + get_level(ERU_PROT, 2, 0)) - end, - ["info"] = function() - return "rad "..(1 + get_level(ERU_PROT, 2, 0)) - end, + ["spell"] = function() return eru_lay_of_protection() end, + ["info"] = function() return eru_lay_of_protection_info() end, ["desc"] = { "Creates a circle of safety around you", } diff --git a/lib/scpt/s_eru.lua b/lib/scpt/s_eru.lua index c0cb0aaf..d61b6118 100644 --- a/lib/scpt/s_eru.lua +++ b/lib/scpt/s_eru.lua @@ -14,24 +14,8 @@ ERU_SEE = add_spell -- Unnafected by blindness ["blind"] = FALSE, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local obvious - obvious = set_tim_invis(randint(20) + 10 + get_level(ERU_SEE, 100)) - if get_level(ERU_SEE) >= 30 then - wiz_lite_extra() - obvious = TRUE - elseif get_level(ERU_SEE) >= 10 then - map_area() - obvious = TRUE - end - if get_level(ERU_SEE) >= 20 then - obvious = is_obvious(set_blind(0), obvious) - end - return obvious - end, - ["info"] = function() - return "dur "..(10 + get_level(ERU_SEE, 100)).."+d20" - end, + ["spell"] = function() return eru_see_the_music() end, + ["info"] = function() return eru_see_the_music_info() end, ["desc"] = { "Allows you to 'see' the Great Music from which the world", "originates, allowing you to see unseen things", @@ -53,21 +37,8 @@ ERU_LISTEN = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - if get_level(ERU_LISTEN) >= 30 then - ident_all() - identify_pack() - return TRUE - elseif get_level(ERU_LISTEN) >= 14 then - identify_pack() - return TRUE - else - return ident_spell() - end - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return eru_listen_to_the_music() end, + ["info"] = function() return eru_listen_to_the_music_info() end, ["desc"] = { "Allows you to listen to the Great Music from which the world", "originates, allowing you to understand the meaning of things", @@ -88,17 +59,8 @@ ERU_UNDERSTAND = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - if get_level(ERU_UNDERSTAND) >= 10 then - identify_pack_fully() - return TRUE - else - return identify_fully() - end - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return eru_know_the_music() end, + ["info"] = function() return eru_know_the_music_info() end, ["desc"] = { "Allows you to understand the Great Music from which the world", "originates, allowing you to know the full abilities of things", @@ -118,12 +80,8 @@ ERU_PROT = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - return fire_ball(GF_MAKE_GLYPH, 0, 1, 1 + get_level(ERU_PROT, 2, 0)) - end, - ["info"] = function() - return "rad "..(1 + get_level(ERU_PROT, 2, 0)) - end, + ["spell"] = function() return eru_lay_of_protection() end, + ["info"] = function() return eru_lay_of_protection_info() end, ["desc"] = { "Creates a circle of safety around you", } diff --git a/src/externs.h b/src/externs.h index 408a7046..abf9473b 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1507,6 +1507,20 @@ char *earth_strike_info(); bool_ *earth_shake(); char *earth_shake_info(); +extern s32b ERU_SEE; +extern s32b ERU_LISTEN; +extern s32b ERU_UNDERSTAND; +extern s32b ERU_PROT; + +bool_ *eru_see_the_music(); +char *eru_see_the_music_info(); +bool_ *eru_listen_to_the_music(); +char *eru_listen_to_the_music_info(); +bool_ *eru_know_the_music(); +char *eru_know_the_music_info(); +bool_ *eru_lay_of_protection(); +char *eru_lay_of_protection_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index e9e7c29d..d7206b41 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2542,3 +2542,20 @@ bool_ *earth_strike(); char *earth_strike_info(); bool_ *earth_shake(); char *earth_shake_info(); + +/* + * Eru + */ +extern s32b ERU_SEE; +extern s32b ERU_LISTEN; +extern s32b ERU_UNDERSTAND; +extern s32b ERU_PROT; + +bool_ *eru_see_the_music(); +char *eru_see_the_music_info(); +bool_ *eru_listen_to_the_music(); +char *eru_listen_to_the_music_info(); +bool_ *eru_know_the_music(); +char *eru_know_the_music_info(); +bool_ *eru_lay_of_protection(); +char *eru_lay_of_protection_info(); diff --git a/src/spells3.c b/src/spells3.c index fc29ec00..3faefc97 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -37,6 +37,11 @@ s32b STONEPRISON; s32b STRIKE; s32b SHAKE; +s32b ERU_SEE; +s32b ERU_LISTEN; +s32b ERU_UNDERSTAND; +s32b ERU_PROT; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua cares about). */ @@ -1007,3 +1012,88 @@ char *earth_shake_info() return buf; } +bool_ *eru_see_the_music() +{ + set_tim_invis(randint(20) + 10 + get_level_s(ERU_SEE, 100)); + + if (get_level_s(ERU_SEE, 50) >= 30) + { + wiz_lite_extra(); + } + else if (get_level_s(ERU_SEE, 50) >= 10) + { + map_area(); + } + + if (get_level_s(ERU_SEE, 50) >= 20) + { + set_blind(0); + } + + return CAST; +} + +char *eru_see_the_music_info() +{ + static char buf[128]; + sprintf(buf, + "dur %d+d20", + (10 + get_level_s(ERU_SEE, 100))); + return buf; +} + +bool_ *eru_listen_to_the_music() +{ + if (get_level_s(ERU_LISTEN, 50) >= 30) + { + ident_all(); + identify_pack(); + } + else if (get_level_s(ERU_LISTEN, 50) >= 14) + { + identify_pack(); + } + else + { + ident_spell(); + } + return CAST; +} + +char *eru_listen_to_the_music_info() +{ + return ""; +} + +bool_ *eru_know_the_music() +{ + if (get_level_s(ERU_UNDERSTAND, 50) >= 10) + { + identify_pack_fully(); + } + else + { + identify_fully(); + } + return CAST; +} + +char *eru_know_the_music_info() +{ + return ""; +} + +bool_ *eru_lay_of_protection() +{ + fire_ball(GF_MAKE_GLYPH, 0, 1, 1 + get_level(ERU_PROT, 2, 0)); + return CAST; +} + +char *eru_lay_of_protection_info() +{ + static char buf[128]; + sprintf(buf, + "rad %d", + (1 + get_level(ERU_PROT, 2, 0))); + return buf; +} -- cgit v1.2.3 From cf9afa2063fa9123f8653e76d17404775a34313d Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 13 Apr 2012 22:05:41 +0200 Subject: Lua: Move "Fire" spell functions to C --- lib/mods/theme/scpt/s_fire.lua | 113 +++--------------------- lib/scpt/s_fire.lua | 113 +++--------------------- src/externs.h | 17 ++++ src/spells.pkg | 20 +++++ src/spells3.c | 190 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 247 insertions(+), 206 deletions(-) diff --git a/lib/mods/theme/scpt/s_fire.lua b/lib/mods/theme/scpt/s_fire.lua index dbbf7604..37a75032 100644 --- a/lib/mods/theme/scpt/s_fire.lua +++ b/lib/mods/theme/scpt/s_fire.lua @@ -19,27 +19,8 @@ GLOBELIGHT = add_spell }, }, ["inertia"] = { 1, 40 }, - ["spell"] = function() - local obvious - if get_level(GLOBELIGHT, 50) >= 3 then - obvious = lite_area(10, 4) - else - lite_room(player.py, player.px) - obvious = TRUE - end - if get_level(GLOBELIGHT, 50) >= 15 then - obvious = is_obvious(fire_ball(GF_LITE, 0, 10 + get_level(GLOBELIGHT, 100), 5 + get_level(GLOBELIGHT, 6)), obvious) - player.update = bor(player.update, PU_VIEW) - end - return obvious - end, - ["info"] = function() - if get_level(GLOBELIGHT, 50) >= 15 then - return "dam "..(10 + get_level(GLOBELIGHT, 100)).." rad "..(5 + get_level(GLOBELIGHT, 6)) - else - return "" - end - end, + ["spell"] = function() return fire_globe_of_light() end, + ["info"] = function() return fire_globe_of_light_info() end, ["desc"] = { "Creates a globe of pure light", "At level 3 it starts damaging monsters", @@ -65,20 +46,8 @@ FIREFLASH = add_spell ["max_level"] = { 15, 35 }, }, }, - ["spell"] = function() - local ret, dir, type - if (get_level(FIREFLASH, 50) >= 20) then - type = GF_HOLY_FIRE - else - type = GF_FIRE - end - ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_ball(type, dir, 20 + get_level(FIREFLASH, 500), 2 + get_level(FIREFLASH, 5)) - end, - ["info"] = function() - return "dam "..(20 + get_level(FIREFLASH, 500)).." rad "..(2 + get_level(FIREFLASH, 5)) - end, + ["spell"] = function() return fire_fireflash() end, + ["info"] = function() return fire_fireflash_info() end, ["desc"] = { "Conjures a ball of fire to burn your foes to ashes", "At level 20 it turns into a ball of holy fire" @@ -104,18 +73,8 @@ FIERYAURA = add_spell }, }, ["inertia"] = { 2, 15 }, - ["spell"] = function() - local type - if (get_level(FIERYAURA, 50) >= 8) then - type = SHIELD_GREAT_FIRE - else - type = SHIELD_FIRE - end - return set_shield(randint(20) + 10 + get_level(FIERYAURA, 70), 10, type, 5 + get_level(FIERYAURA, 10), 5 + get_level(FIERYAURA, 7)) - end, - ["info"] = function() - return "dam "..(5 + get_level(FIERYAURA, 15)).."d"..(5 + get_level(FIERYAURA, 7)).." dur "..(10 + get_level(FIERYAURA, 70)).."+d20" - end, + ["spell"] = function() return fire_fiery_shield() end, + ["info"] = function() return fire_fiery_shield_info() end, ["desc"] = { "Creates a shield of fierce flames around you", "At level 8 it turns into a greater kind of flame that can not be resisted" @@ -140,21 +99,8 @@ FIREWALL = add_spell ["max_level"] = { 5, 40 }, }, }, - ["spell"] = function() - local ret, dir, type - if (get_level(FIREWALL, 50) >= 6) then - type = GF_HELL_FIRE - else - type = GF_FIRE - end - ret, dir = get_aim_dir() - if ret == FALSE then return end - fire_wall(type, dir, 40 + get_level(FIREWALL, 150), 10 + get_level(FIREWALL, 14)) - return TRUE - end, - ["info"] = function() - return "dam "..(40 + get_level(FIREWALL, 150)).." dur "..(10 + get_level(FIREWALL, 14)) - end, + ["spell"] = function() return fire_firewall() end, + ["info"] = function() return fire_firewall_info() end, ["desc"] = { "Creates a fiery wall to incinerate monsters stupid enough to attack you", "At level 6 it turns into a wall of hell fire" @@ -169,47 +115,8 @@ FIREGOLEM = add_spell ["mana"] = 16, ["mana_max"] = 70, ["fail"] = 40, - ["spell"] = function() - local m_idx, y, x, ret, item - - -- Can we reconnect ? - if do_control_reconnect() == TRUE then - msg_print("Control re-established.") - return - end - - ret, item = get_item("Which light source do you want to use to create the golem?", - "You have no light source for the golem", - bor(USE_INVEN, USE_EQUIP), - function (obj) - if (obj.tval == TV_LITE) and ((obj.sval == SV_LITE_TORCH) or (obj.sval == SV_LITE_LANTERN)) then - return TRUE - end - return FALSE - end - ) - if ret == FALSE then return TRUE end - inven_item_increase(item, -1) - inven_item_describe(item) - inven_item_optimize(item) - - -- Summon it - m_allow_special[1043 + 1] = TRUE - y, x = find_position(player.py, player.px) - m_idx = place_monster_one(y, x, 1043, 0, FALSE, MSTATUS_FRIEND) - m_allow_special[1043 + 1] = FALSE - - -- level it - if m_idx ~= 0 then - monster_set_level(m_idx, 7 + get_level(FIREGOLEM, 70)) - player.control = m_idx - monster(m_idx).mflag = bor(monster(m_idx).mflag, MFLAG_CONTROL) - end - return TRUE - end, - ["info"] = function() - return "golem level "..(7 + get_level(FIREGOLEM, 70)) - end, + ["spell"] = function() return fire_golem() end, + ["info"] = function() return fire_golem_info() end, ["desc"] = { "Creates a fiery golem and controls it", "During the control the available keylist is:", diff --git a/lib/scpt/s_fire.lua b/lib/scpt/s_fire.lua index dbbf7604..37a75032 100644 --- a/lib/scpt/s_fire.lua +++ b/lib/scpt/s_fire.lua @@ -19,27 +19,8 @@ GLOBELIGHT = add_spell }, }, ["inertia"] = { 1, 40 }, - ["spell"] = function() - local obvious - if get_level(GLOBELIGHT, 50) >= 3 then - obvious = lite_area(10, 4) - else - lite_room(player.py, player.px) - obvious = TRUE - end - if get_level(GLOBELIGHT, 50) >= 15 then - obvious = is_obvious(fire_ball(GF_LITE, 0, 10 + get_level(GLOBELIGHT, 100), 5 + get_level(GLOBELIGHT, 6)), obvious) - player.update = bor(player.update, PU_VIEW) - end - return obvious - end, - ["info"] = function() - if get_level(GLOBELIGHT, 50) >= 15 then - return "dam "..(10 + get_level(GLOBELIGHT, 100)).." rad "..(5 + get_level(GLOBELIGHT, 6)) - else - return "" - end - end, + ["spell"] = function() return fire_globe_of_light() end, + ["info"] = function() return fire_globe_of_light_info() end, ["desc"] = { "Creates a globe of pure light", "At level 3 it starts damaging monsters", @@ -65,20 +46,8 @@ FIREFLASH = add_spell ["max_level"] = { 15, 35 }, }, }, - ["spell"] = function() - local ret, dir, type - if (get_level(FIREFLASH, 50) >= 20) then - type = GF_HOLY_FIRE - else - type = GF_FIRE - end - ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_ball(type, dir, 20 + get_level(FIREFLASH, 500), 2 + get_level(FIREFLASH, 5)) - end, - ["info"] = function() - return "dam "..(20 + get_level(FIREFLASH, 500)).." rad "..(2 + get_level(FIREFLASH, 5)) - end, + ["spell"] = function() return fire_fireflash() end, + ["info"] = function() return fire_fireflash_info() end, ["desc"] = { "Conjures a ball of fire to burn your foes to ashes", "At level 20 it turns into a ball of holy fire" @@ -104,18 +73,8 @@ FIERYAURA = add_spell }, }, ["inertia"] = { 2, 15 }, - ["spell"] = function() - local type - if (get_level(FIERYAURA, 50) >= 8) then - type = SHIELD_GREAT_FIRE - else - type = SHIELD_FIRE - end - return set_shield(randint(20) + 10 + get_level(FIERYAURA, 70), 10, type, 5 + get_level(FIERYAURA, 10), 5 + get_level(FIERYAURA, 7)) - end, - ["info"] = function() - return "dam "..(5 + get_level(FIERYAURA, 15)).."d"..(5 + get_level(FIERYAURA, 7)).." dur "..(10 + get_level(FIERYAURA, 70)).."+d20" - end, + ["spell"] = function() return fire_fiery_shield() end, + ["info"] = function() return fire_fiery_shield_info() end, ["desc"] = { "Creates a shield of fierce flames around you", "At level 8 it turns into a greater kind of flame that can not be resisted" @@ -140,21 +99,8 @@ FIREWALL = add_spell ["max_level"] = { 5, 40 }, }, }, - ["spell"] = function() - local ret, dir, type - if (get_level(FIREWALL, 50) >= 6) then - type = GF_HELL_FIRE - else - type = GF_FIRE - end - ret, dir = get_aim_dir() - if ret == FALSE then return end - fire_wall(type, dir, 40 + get_level(FIREWALL, 150), 10 + get_level(FIREWALL, 14)) - return TRUE - end, - ["info"] = function() - return "dam "..(40 + get_level(FIREWALL, 150)).." dur "..(10 + get_level(FIREWALL, 14)) - end, + ["spell"] = function() return fire_firewall() end, + ["info"] = function() return fire_firewall_info() end, ["desc"] = { "Creates a fiery wall to incinerate monsters stupid enough to attack you", "At level 6 it turns into a wall of hell fire" @@ -169,47 +115,8 @@ FIREGOLEM = add_spell ["mana"] = 16, ["mana_max"] = 70, ["fail"] = 40, - ["spell"] = function() - local m_idx, y, x, ret, item - - -- Can we reconnect ? - if do_control_reconnect() == TRUE then - msg_print("Control re-established.") - return - end - - ret, item = get_item("Which light source do you want to use to create the golem?", - "You have no light source for the golem", - bor(USE_INVEN, USE_EQUIP), - function (obj) - if (obj.tval == TV_LITE) and ((obj.sval == SV_LITE_TORCH) or (obj.sval == SV_LITE_LANTERN)) then - return TRUE - end - return FALSE - end - ) - if ret == FALSE then return TRUE end - inven_item_increase(item, -1) - inven_item_describe(item) - inven_item_optimize(item) - - -- Summon it - m_allow_special[1043 + 1] = TRUE - y, x = find_position(player.py, player.px) - m_idx = place_monster_one(y, x, 1043, 0, FALSE, MSTATUS_FRIEND) - m_allow_special[1043 + 1] = FALSE - - -- level it - if m_idx ~= 0 then - monster_set_level(m_idx, 7 + get_level(FIREGOLEM, 70)) - player.control = m_idx - monster(m_idx).mflag = bor(monster(m_idx).mflag, MFLAG_CONTROL) - end - return TRUE - end, - ["info"] = function() - return "golem level "..(7 + get_level(FIREGOLEM, 70)) - end, + ["spell"] = function() return fire_golem() end, + ["info"] = function() return fire_golem_info() end, ["desc"] = { "Creates a fiery golem and controls it", "During the control the available keylist is:", diff --git a/src/externs.h b/src/externs.h index abf9473b..fd156286 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1521,6 +1521,23 @@ char *eru_know_the_music_info(); bool_ *eru_lay_of_protection(); char *eru_lay_of_protection_info(); +extern s32b GLOBELIGHT; +extern s32b FIREFLASH; +extern s32b FIERYAURA; +extern s32b FIREWALL; +extern s32b FIREGOLEM; + +bool_ *fire_globe_of_light(); +char *fire_globe_of_light_info(); +bool_ *fire_fireflash(); +char *fire_fireflash_info(); +bool_ *fire_fiery_shield(); +char *fire_fiery_shield_info(); +bool_ *fire_firewall(); +char *fire_firewall_info(); +bool_ *fire_golem(); +char *fire_golem_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index d7206b41..260cdf50 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2559,3 +2559,23 @@ bool_ *eru_know_the_music(); char *eru_know_the_music_info(); bool_ *eru_lay_of_protection(); char *eru_lay_of_protection_info(); + +/* + * Fire + */ +extern s32b GLOBELIGHT; +extern s32b FIREFLASH; +extern s32b FIERYAURA; +extern s32b FIREWALL; +extern s32b FIREGOLEM; + +bool_ *fire_globe_of_light(); +char *fire_globe_of_light_info(); +bool_ *fire_fireflash(); +char *fire_fireflash_info(); +bool_ *fire_fiery_shield(); +char *fire_fiery_shield_info(); +bool_ *fire_firewall(); +char *fire_firewall_info(); +bool_ *fire_golem(); +char *fire_golem_info(); diff --git a/src/spells3.c b/src/spells3.c index 3faefc97..7c8173ea 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -42,6 +42,12 @@ s32b ERU_LISTEN; s32b ERU_UNDERSTAND; s32b ERU_PROT; +s32b GLOBELIGHT; +s32b FIREFLASH; +s32b FIERYAURA; +s32b FIREWALL; +s32b FIREGOLEM; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua cares about). */ @@ -1097,3 +1103,187 @@ char *eru_lay_of_protection_info() (1 + get_level(ERU_PROT, 2, 0))); return buf; } + +bool_ *fire_globe_of_light() +{ + if (get_level_s(GLOBELIGHT, 50) >= 3) + { + lite_area(10, 4); + } + else + { + lite_room(p_ptr->py, p_ptr->px); + } + + if (get_level_s(GLOBELIGHT, 50) >= 15) + { + fire_ball(GF_LITE, + 0, + 10 + get_level_s(GLOBELIGHT, 100), + 5 + get_level_s(GLOBELIGHT, 6)); + p_ptr->update |= PU_VIEW; + } + return CAST; +} + +char *fire_globe_of_light_info() +{ + static char buf[128]; + + if (get_level_s(GLOBELIGHT, 50) >= 15) + { + sprintf(buf, "dam %d rad %d", + (10 + get_level_s(GLOBELIGHT, 100)), + (5 + get_level_s(GLOBELIGHT, 6))); + } + else + { + buf[0] = '\0'; + } + + return buf; +} + +bool_ *fire_fireflash() +{ + int dir; + int type = GF_FIRE; + + if (get_level_s(FIREFLASH, 50) >= 20) + { + type = GF_HOLY_FIRE; + } + + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + fire_ball(type, dir, + 20 + get_level_s(FIREFLASH, 500), + 2 + get_level_s(FIREFLASH, 5)); + return CAST; +} + +char *fire_fireflash_info() +{ + static char buf[128]; + sprintf(buf, + "dam %d rad %d", + (20 + get_level_s(FIREFLASH, 500)), + (2 + get_level_s(FIREFLASH, 5))); + return buf; +} + +bool_ *fire_fiery_shield() +{ + int type = SHIELD_FIRE; + if (get_level_s(FIERYAURA, 50) >= 8) + { + type = SHIELD_GREAT_FIRE; + } + + set_shield(randint(20) + 10 + get_level_s(FIERYAURA, 70), + 10, + type, + 5 + get_level_s(FIERYAURA, 10), + 5 + get_level_s(FIERYAURA, 7)); + return CAST; +} + +char *fire_fiery_shield_info() +{ + static char buf[128]; + sprintf(buf, + "dam %dd%d dur %d+d20", + (5 + get_level_s(FIERYAURA, 15)), + (5 + get_level_s(FIERYAURA, 7)), + (10 + get_level_s(FIERYAURA, 70))); + return buf; +} + +bool_ *fire_firewall() +{ + int dir; + int type = GF_FIRE; + if (get_level_s(FIREWALL, 50) >= 6) + { + type = GF_HELL_FIRE; + } + + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + fire_wall(type, dir, + 40 + get_level_s(FIREWALL, 150), + 10 + get_level_s(FIREWALL, 14)); + return CAST; +} + +char *fire_firewall_info() +{ + static char buf[128]; + sprintf(buf, + "dam %d dur %d", + (40 + get_level_s(FIREWALL, 150)), + (10 + get_level_s(FIREWALL, 14))); + return buf; +} + +bool_ item_tester_hook_fire_golem(object_type *o_ptr) +{ + return ((o_ptr->tval == TV_LITE) && + ((o_ptr->sval == SV_LITE_TORCH) || + (o_ptr->sval == SV_LITE_LANTERN))); +} + +bool_ *fire_golem() +{ + int item, x, y, m_idx; + + /* Can we reconnect ? */ + if (do_control_reconnect()) + { + msg_print("Control re-established."); + return NO_CAST; + } + + item_tester_hook = item_tester_hook_fire_golem; + if (!get_item(&item, + "Which light source do you want to use to create the golem?", + "You have no light source for the golem", + USE_INVEN | USE_EQUIP)) + { + return NO_CAST; + } + + /* Destroy the source object */ + inc_stack_size(item, -1); + + /* Summon it */ + m_allow_special[1043 + 1] = TRUE; + find_position(p_ptr->py, p_ptr->px, &y, &x); + m_idx = place_monster_one(y, x, 1043, 0, FALSE, MSTATUS_FRIEND); + m_allow_special[1043 + 1] = FALSE; + + /* level it */ + if (m_idx != 0) + { + monster_set_level(m_idx, 7 + get_level_s(FIREGOLEM, 70)); + p_ptr->control = m_idx; + m_list[m_idx].mflag |= MFLAG_CONTROL; + } + + return CAST; +} + +char *fire_golem_info() +{ + static char buf[128]; + sprintf(buf, + "golem level %d", + (7 + get_level_s(FIREGOLEM, 70))); + return buf; +} -- cgit v1.2.3 From ca30fc5a6f92d75ee1c7eec2dd863776fe7afb5f Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 16 Apr 2012 20:20:43 +0200 Subject: Lua: Move "Geomancy" spell functions to C --- lib/mods/theme/scpt/s_geom.lua | 235 ++---------------------- lib/scpt/s_geom.lua | 235 ++---------------------- src/cmd1.c | 11 ++ src/externs.h | 26 +++ src/loadsave.c | 3 + src/spells.pkg | 29 +++ src/spells3.c | 400 +++++++++++++++++++++++++++++++++++++++++ src/types.h | 3 + 8 files changed, 504 insertions(+), 438 deletions(-) diff --git a/lib/mods/theme/scpt/s_geom.lua b/lib/mods/theme/scpt/s_geom.lua index d152bc25..d4ce4437 100644 --- a/lib/mods/theme/scpt/s_geom.lua +++ b/lib/mods/theme/scpt/s_geom.lua @@ -11,20 +11,8 @@ CALL_THE_ELEMENTS = add_spell -- Unnafected by blindness ["blind"] = FALSE, ["random"] = 0, - ["spell"] = function() - local ret, dir = 0, 0 - - if get_level(CALL_THE_ELEMENTS) >= 17 then - ret, dir = get_aim_dir() - if ret == FALSE then return end - end - - fire_ball(GF_ELEMENTAL_GROWTH, dir, 1, 1 + get_level(CALL_THE_ELEMENTS, 5, 0)) - return TRUE - end, - ["info"] = function() - return "rad "..(1 + get_level(CALL_THE_ELEMENTS, 5, 0)) - end, + ["spell"] = function() return geomancy_call_the_elements() end, + ["info"] = function() return geomancy_call_the_elements_info() end, ["desc"] = { "Randomly creates various elements around you", "Each type of element chance is controlled by your level", @@ -44,13 +32,8 @@ CHANNEL_ELEMENTS = add_spell -- Unnafected by blindness ["blind"] = FALSE, ["random"] = 0, - ["spell"] = function() - channel_the_elements(player.py, player.px, get_level(CHANNEL_ELEMENTS)) - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return geomancy_channel_elements() end, + ["info"] = function() return geomancy_channel_elements_info() end, ["desc"] = { "Draws on the caster's immediate environs to form an attack or other effect.", "Grass/Flower heals.", @@ -79,50 +62,8 @@ ELEMENTAL_WAVE = add_spell -- Unnafected by blindness ["blind"] = FALSE, ["random"] = 0, - ["spell"] = function() - local ret, dir = get_rep_dir() - if ret == FALSE then return end - - local y, x = explode_dir(dir) - y = y + player.py - x = x + player.px - - local t = - { - -- Earth stuff - [FEAT_GRASS] = { GF_POIS, GF_POIS, 10 + get_skill_scale(SKILL_EARTH, 200) }, - [FEAT_FLOWER] = { GF_POIS, GF_POIS, 10 + get_skill_scale(SKILL_EARTH, 300) }, - -- cannot turn chasm into a wave - - -- Water stuff - [FEAT_SHAL_WATER] = { GF_WATER, GF_WATER, 10 + get_skill_scale(SKILL_WATER, 200) }, - [FEAT_DEEP_WATER] = { GF_WATER, GF_WATER, 10 + get_skill_scale(SKILL_WATER, 300) }, - [FEAT_ICE] = { GF_ICE, GF_ICE, 10 + get_skill_scale(SKILL_WATER, 200) }, - - -- Fire stuff - [FEAT_SAND] = { GF_LITE, GF_LITE, 10 + get_skill_scale(SKILL_FIRE, 400) }, - [FEAT_SHAL_LAVA] = { GF_FIRE, GF_HOLY_FIRE, 10 + get_skill_scale(SKILL_FIRE, 200) }, - [FEAT_DEEP_LAVA] = { GF_FIRE, GF_HOLY_FIRE, 10 + get_skill_scale(SKILL_FIRE, 300) }, - } - - - local effect = t[cave(y, x).feat] - if not effect then - msg_print("You cannot channel this area.") - else - local typ = effect[1] - if get_level(ELEMENTAL_WAVE) >= 20 then typ = effect[2] end - - cave_set_feat(y, x, FEAT_FLOOR) - - fire_wave(typ, 0, effect[3], 0, 6 + get_level(ELEMENTAL_WAVE, 20), EFF_WAVE + EFF_LAST + getglobal("EFF_DIR"..dir)) - end - - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return geomancy_elemental_wave() end, + ["info"] = function() return geomancy_elemental_wave_info() end, ["desc"] = { "Draws on an adjacent special square to project a slow-moving", "wave of that element in that direction", @@ -145,42 +86,8 @@ VAPORIZE = add_spell ["depend"] = function() if get_skill(SKILL_AIR) >= 4 then return TRUE end end, - ["spell"] = function() - local t = - { - -- Earth stuff - [FEAT_GRASS] = { GF_POIS, GF_POIS, 5 + get_skill_scale(SKILL_EARTH, 100) }, - [FEAT_FLOWER] = { GF_POIS, GF_POIS, 5 + get_skill_scale(SKILL_EARTH, 150) }, - [FEAT_DARK_PIT] = { GF_DARK, GF_DARK, 5 + get_skill_scale(SKILL_EARTH, 200) }, - - -- Water stuff - [FEAT_SHAL_WATER] = { GF_WATER, GF_WATER, 5 + get_skill_scale(SKILL_WATER, 100) }, - [FEAT_DEEP_WATER] = { GF_WATER, GF_WATER, 5 + get_skill_scale(SKILL_WATER, 150) }, - [FEAT_ICE] = { GF_ICE, GF_ICE, 5 + get_skill_scale(SKILL_WATER, 100) }, - - -- Fire stuff - [FEAT_SAND] = { GF_LITE, GF_LITE, 5 + get_skill_scale(SKILL_FIRE, 200) }, - [FEAT_SHAL_LAVA] = { GF_FIRE, GF_HOLY_FIRE, 5 + get_skill_scale(SKILL_FIRE, 100) }, - [FEAT_DEEP_LAVA] = { GF_FIRE, GF_HOLY_FIRE, 5 + get_skill_scale(SKILL_FIRE, 150) }, - } - - local effect = t[cave(player.py, player.px).feat] - if not effect then - msg_print("You cannot channel this area.") - else - local typ = effect[1] - if get_level(VAPORIZE) >= 20 then typ = effect[2] end - - cave_set_feat(player.py, player.px, FEAT_FLOOR) - - fire_cloud(typ, 0, effect[3], 1 + get_level(VAPORIZE, 4), 10 + get_level(VAPORIZE, 20)) - end - - return TRUE - end, - ["info"] = function() - return "rad "..(1 + get_level(VAPORIZE, 4)).." dur "..(10 + get_level(VAPORIZE, 20)) - end, + ["spell"] = function() return geomancy_vaporize() end, + ["info"] = function() return geomancy_vaporize_info() end, ["desc"] = { "Draws upon your immediate environs to form a cloud of damaging vapors", } @@ -201,38 +108,14 @@ GEOLYSIS = add_spell ["depend"] = function() if get_skill(SKILL_EARTH) >= 7 then return TRUE end end, - ["spell"] = function() - local ret, dir = get_rep_dir() - if ret == FALSE then return end - - msg_print("Elements recombine before you, laying down an open path.") - geomancy_dig(player.py, player.px, dir, 5 + get_level(GEOLYSIS, 12)) - - return TRUE - end, - ["info"] = function() - return "length "..(5 + get_level(GEOLYSIS, 12)) - end, + ["spell"] = function() return geomancy_geolysis() end, + ["info"] = function() return geomancy_geolysis_info() end, ["desc"] = { "Burrows deeply and slightly at random into a wall,", "leaving behind tailings of various different sorts of walls in the passage.", } } -player.dripping_tread = 0 -add_loadsave("player.dripping_tread", 0) -add_hooks -{ - [HOOK_MOVED] = function(oy, ox) - if player.dripping_tread > 0 then - geomancy_random_floor(oy, ox, FALSE) - player.dripping_tread = player.dripping_tread - 1 - if player.dripping_tread == 0 then - msg_print("You stop dripping raw elemental energies.") - end - end - end -} DRIPPING_TREAD = add_spell { ["name"] = "Dripping Tread", @@ -248,19 +131,8 @@ DRIPPING_TREAD = add_spell ["depend"] = function() if get_skill(SKILL_WATER) >= 10 then return TRUE end end, - ["spell"] = function() - if player.dripping_tread == 0 then - player.dripping_tread = randint(15) + 10 + get_level(DRIPPING_TREAD) - msg_print("You start dripping raw elemental energies.") - else - player.dripping_tread = 0 - msg_print("You stop dripping raw elemental energies.") - end - return TRUE - end, - ["info"] = function() - return "dur "..(10 + get_level(DRIPPING_TREAD)).."+d15 movs" - end, + ["spell"] = function() return geomancy_dripping_tread() end, + ["info"] = function() return geomancy_dripping_tread_info() end, ["desc"] = { "Causes you to leave random elemental forms behind as you walk", } @@ -281,20 +153,8 @@ GROW_BARRIER = add_spell ["depend"] = function() if get_skill(SKILL_EARTH) >= 12 then return TRUE end end, - ["spell"] = function() - local ret, dir = 0, 0 - - if get_level(GROW_BARRIER) >= 20 then - ret, dir = get_aim_dir() - if ret == FALSE then return end - end - - fire_ball(GF_ELEMENTAL_WALL, dir, 1, 1) - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return geomancy_grow_barrier() end, + ["info"] = function() return geomancy_grow_barrier_info() end, ["desc"] = { "Creates impassable terrain (walls, trees, etc.) around you.", "At level 20 it can be projected around another area.", @@ -312,71 +172,8 @@ ELEMENTAL_MINION = add_spell -- Unnafected by blindness ["random"] = 0, -- Must have at least 12 Earth - ["spell"] = function() - local ret, dir = 0, 0 - - ret, dir = get_rep_dir() - if ret == FALSE then return end - - local t = - { - [FEAT_WALL_EXTRA] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - [FEAT_WALL_OUTER] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - [FEAT_WALL_INNER] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - [FEAT_WALL_SOLID] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - [FEAT_MAGMA] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - [FEAT_QUARTZ] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - [FEAT_MAGMA_H] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - [FEAT_QUARTZ_H] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - [FEAT_MAGMA_K] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - [FEAT_QUARTZ_K] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - - [FEAT_DARK_PIT] = { SKILL_AIR, { "Air elemental", "Ancient blue dragon", "Great Storm Wyrm", "Sky Drake" } }, - - [FEAT_SANDWALL] = { SKILL_FIRE, { "Fire elemental", "Ancient red dragon" } }, - [FEAT_SANDWALL_H] = { SKILL_FIRE, { "Fire elemental", "Ancient red dragon" } }, - [FEAT_SANDWALL_K] = { SKILL_FIRE, { "Fire elemental", "Ancient red dragon" } }, - [FEAT_SHAL_LAVA] = { SKILL_FIRE, { "Fire elemental", "Ancient red dragon" } }, - [FEAT_DEEP_LAVA] = { SKILL_FIRE, { "Fire elemental", "Ancient red dragon" } }, - - [FEAT_ICE_WALL] = { SKILL_WATER, { "Water elemental", "Water troll", "Water demon" } }, - [FEAT_SHAL_WATER] = { SKILL_WATER, { "Water elemental", "Water troll", "Water demon" } }, - [FEAT_DEEP_WATER] = { SKILL_WATER, { "Water elemental", "Water troll", "Water demon" } }, - } - - local y, x = explode_dir(dir) - y = y + player.py - x = x + player.px - - local effect = t[cave(y, x).feat] - if not effect then - msg_print("You cannot summon from this area.") - else - local skill = effect[1] - local types = effect[2] - - local max = get_skill_scale(skill, getn(types)) - if max == 0 then max = 1 end - - local r_idx = test_monster_name(types[rand_range(1, max)]) - - -- Summon it - local my, mx = find_position(y, x) - local m_idx = place_monster_one(my, mx, r_idx, 0, FALSE, MSTATUS_FRIEND) - - -- level it - if m_idx ~= 0 then - monster_set_level(m_idx, 10 + get_level(ELEMENTAL_MINION, 120)) - end - - cave_set_feat(y, x, FEAT_FLOOR) - end - - return TRUE - end, - ["info"] = function() - return "min level "..(10 + get_level(ELEMENTAL_MINION, 120)) - end, + ["spell"] = function() return geomancy_elemental_minion() end, + ["info"] = function() return geomancy_elemental_minion_info() end, ["desc"] = { "Summons a minion from a nearby element.", "Walls can summon Earth elmentals, Xorns and Xarens", diff --git a/lib/scpt/s_geom.lua b/lib/scpt/s_geom.lua index d152bc25..d4ce4437 100644 --- a/lib/scpt/s_geom.lua +++ b/lib/scpt/s_geom.lua @@ -11,20 +11,8 @@ CALL_THE_ELEMENTS = add_spell -- Unnafected by blindness ["blind"] = FALSE, ["random"] = 0, - ["spell"] = function() - local ret, dir = 0, 0 - - if get_level(CALL_THE_ELEMENTS) >= 17 then - ret, dir = get_aim_dir() - if ret == FALSE then return end - end - - fire_ball(GF_ELEMENTAL_GROWTH, dir, 1, 1 + get_level(CALL_THE_ELEMENTS, 5, 0)) - return TRUE - end, - ["info"] = function() - return "rad "..(1 + get_level(CALL_THE_ELEMENTS, 5, 0)) - end, + ["spell"] = function() return geomancy_call_the_elements() end, + ["info"] = function() return geomancy_call_the_elements_info() end, ["desc"] = { "Randomly creates various elements around you", "Each type of element chance is controlled by your level", @@ -44,13 +32,8 @@ CHANNEL_ELEMENTS = add_spell -- Unnafected by blindness ["blind"] = FALSE, ["random"] = 0, - ["spell"] = function() - channel_the_elements(player.py, player.px, get_level(CHANNEL_ELEMENTS)) - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return geomancy_channel_elements() end, + ["info"] = function() return geomancy_channel_elements_info() end, ["desc"] = { "Draws on the caster's immediate environs to form an attack or other effect.", "Grass/Flower heals.", @@ -79,50 +62,8 @@ ELEMENTAL_WAVE = add_spell -- Unnafected by blindness ["blind"] = FALSE, ["random"] = 0, - ["spell"] = function() - local ret, dir = get_rep_dir() - if ret == FALSE then return end - - local y, x = explode_dir(dir) - y = y + player.py - x = x + player.px - - local t = - { - -- Earth stuff - [FEAT_GRASS] = { GF_POIS, GF_POIS, 10 + get_skill_scale(SKILL_EARTH, 200) }, - [FEAT_FLOWER] = { GF_POIS, GF_POIS, 10 + get_skill_scale(SKILL_EARTH, 300) }, - -- cannot turn chasm into a wave - - -- Water stuff - [FEAT_SHAL_WATER] = { GF_WATER, GF_WATER, 10 + get_skill_scale(SKILL_WATER, 200) }, - [FEAT_DEEP_WATER] = { GF_WATER, GF_WATER, 10 + get_skill_scale(SKILL_WATER, 300) }, - [FEAT_ICE] = { GF_ICE, GF_ICE, 10 + get_skill_scale(SKILL_WATER, 200) }, - - -- Fire stuff - [FEAT_SAND] = { GF_LITE, GF_LITE, 10 + get_skill_scale(SKILL_FIRE, 400) }, - [FEAT_SHAL_LAVA] = { GF_FIRE, GF_HOLY_FIRE, 10 + get_skill_scale(SKILL_FIRE, 200) }, - [FEAT_DEEP_LAVA] = { GF_FIRE, GF_HOLY_FIRE, 10 + get_skill_scale(SKILL_FIRE, 300) }, - } - - - local effect = t[cave(y, x).feat] - if not effect then - msg_print("You cannot channel this area.") - else - local typ = effect[1] - if get_level(ELEMENTAL_WAVE) >= 20 then typ = effect[2] end - - cave_set_feat(y, x, FEAT_FLOOR) - - fire_wave(typ, 0, effect[3], 0, 6 + get_level(ELEMENTAL_WAVE, 20), EFF_WAVE + EFF_LAST + getglobal("EFF_DIR"..dir)) - end - - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return geomancy_elemental_wave() end, + ["info"] = function() return geomancy_elemental_wave_info() end, ["desc"] = { "Draws on an adjacent special square to project a slow-moving", "wave of that element in that direction", @@ -145,42 +86,8 @@ VAPORIZE = add_spell ["depend"] = function() if get_skill(SKILL_AIR) >= 4 then return TRUE end end, - ["spell"] = function() - local t = - { - -- Earth stuff - [FEAT_GRASS] = { GF_POIS, GF_POIS, 5 + get_skill_scale(SKILL_EARTH, 100) }, - [FEAT_FLOWER] = { GF_POIS, GF_POIS, 5 + get_skill_scale(SKILL_EARTH, 150) }, - [FEAT_DARK_PIT] = { GF_DARK, GF_DARK, 5 + get_skill_scale(SKILL_EARTH, 200) }, - - -- Water stuff - [FEAT_SHAL_WATER] = { GF_WATER, GF_WATER, 5 + get_skill_scale(SKILL_WATER, 100) }, - [FEAT_DEEP_WATER] = { GF_WATER, GF_WATER, 5 + get_skill_scale(SKILL_WATER, 150) }, - [FEAT_ICE] = { GF_ICE, GF_ICE, 5 + get_skill_scale(SKILL_WATER, 100) }, - - -- Fire stuff - [FEAT_SAND] = { GF_LITE, GF_LITE, 5 + get_skill_scale(SKILL_FIRE, 200) }, - [FEAT_SHAL_LAVA] = { GF_FIRE, GF_HOLY_FIRE, 5 + get_skill_scale(SKILL_FIRE, 100) }, - [FEAT_DEEP_LAVA] = { GF_FIRE, GF_HOLY_FIRE, 5 + get_skill_scale(SKILL_FIRE, 150) }, - } - - local effect = t[cave(player.py, player.px).feat] - if not effect then - msg_print("You cannot channel this area.") - else - local typ = effect[1] - if get_level(VAPORIZE) >= 20 then typ = effect[2] end - - cave_set_feat(player.py, player.px, FEAT_FLOOR) - - fire_cloud(typ, 0, effect[3], 1 + get_level(VAPORIZE, 4), 10 + get_level(VAPORIZE, 20)) - end - - return TRUE - end, - ["info"] = function() - return "rad "..(1 + get_level(VAPORIZE, 4)).." dur "..(10 + get_level(VAPORIZE, 20)) - end, + ["spell"] = function() return geomancy_vaporize() end, + ["info"] = function() return geomancy_vaporize_info() end, ["desc"] = { "Draws upon your immediate environs to form a cloud of damaging vapors", } @@ -201,38 +108,14 @@ GEOLYSIS = add_spell ["depend"] = function() if get_skill(SKILL_EARTH) >= 7 then return TRUE end end, - ["spell"] = function() - local ret, dir = get_rep_dir() - if ret == FALSE then return end - - msg_print("Elements recombine before you, laying down an open path.") - geomancy_dig(player.py, player.px, dir, 5 + get_level(GEOLYSIS, 12)) - - return TRUE - end, - ["info"] = function() - return "length "..(5 + get_level(GEOLYSIS, 12)) - end, + ["spell"] = function() return geomancy_geolysis() end, + ["info"] = function() return geomancy_geolysis_info() end, ["desc"] = { "Burrows deeply and slightly at random into a wall,", "leaving behind tailings of various different sorts of walls in the passage.", } } -player.dripping_tread = 0 -add_loadsave("player.dripping_tread", 0) -add_hooks -{ - [HOOK_MOVED] = function(oy, ox) - if player.dripping_tread > 0 then - geomancy_random_floor(oy, ox, FALSE) - player.dripping_tread = player.dripping_tread - 1 - if player.dripping_tread == 0 then - msg_print("You stop dripping raw elemental energies.") - end - end - end -} DRIPPING_TREAD = add_spell { ["name"] = "Dripping Tread", @@ -248,19 +131,8 @@ DRIPPING_TREAD = add_spell ["depend"] = function() if get_skill(SKILL_WATER) >= 10 then return TRUE end end, - ["spell"] = function() - if player.dripping_tread == 0 then - player.dripping_tread = randint(15) + 10 + get_level(DRIPPING_TREAD) - msg_print("You start dripping raw elemental energies.") - else - player.dripping_tread = 0 - msg_print("You stop dripping raw elemental energies.") - end - return TRUE - end, - ["info"] = function() - return "dur "..(10 + get_level(DRIPPING_TREAD)).."+d15 movs" - end, + ["spell"] = function() return geomancy_dripping_tread() end, + ["info"] = function() return geomancy_dripping_tread_info() end, ["desc"] = { "Causes you to leave random elemental forms behind as you walk", } @@ -281,20 +153,8 @@ GROW_BARRIER = add_spell ["depend"] = function() if get_skill(SKILL_EARTH) >= 12 then return TRUE end end, - ["spell"] = function() - local ret, dir = 0, 0 - - if get_level(GROW_BARRIER) >= 20 then - ret, dir = get_aim_dir() - if ret == FALSE then return end - end - - fire_ball(GF_ELEMENTAL_WALL, dir, 1, 1) - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return geomancy_grow_barrier() end, + ["info"] = function() return geomancy_grow_barrier_info() end, ["desc"] = { "Creates impassable terrain (walls, trees, etc.) around you.", "At level 20 it can be projected around another area.", @@ -312,71 +172,8 @@ ELEMENTAL_MINION = add_spell -- Unnafected by blindness ["random"] = 0, -- Must have at least 12 Earth - ["spell"] = function() - local ret, dir = 0, 0 - - ret, dir = get_rep_dir() - if ret == FALSE then return end - - local t = - { - [FEAT_WALL_EXTRA] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - [FEAT_WALL_OUTER] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - [FEAT_WALL_INNER] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - [FEAT_WALL_SOLID] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - [FEAT_MAGMA] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - [FEAT_QUARTZ] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - [FEAT_MAGMA_H] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - [FEAT_QUARTZ_H] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - [FEAT_MAGMA_K] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - [FEAT_QUARTZ_K] = { SKILL_EARTH, { "Earth elemental", "Xorn", "Xaren" } }, - - [FEAT_DARK_PIT] = { SKILL_AIR, { "Air elemental", "Ancient blue dragon", "Great Storm Wyrm", "Sky Drake" } }, - - [FEAT_SANDWALL] = { SKILL_FIRE, { "Fire elemental", "Ancient red dragon" } }, - [FEAT_SANDWALL_H] = { SKILL_FIRE, { "Fire elemental", "Ancient red dragon" } }, - [FEAT_SANDWALL_K] = { SKILL_FIRE, { "Fire elemental", "Ancient red dragon" } }, - [FEAT_SHAL_LAVA] = { SKILL_FIRE, { "Fire elemental", "Ancient red dragon" } }, - [FEAT_DEEP_LAVA] = { SKILL_FIRE, { "Fire elemental", "Ancient red dragon" } }, - - [FEAT_ICE_WALL] = { SKILL_WATER, { "Water elemental", "Water troll", "Water demon" } }, - [FEAT_SHAL_WATER] = { SKILL_WATER, { "Water elemental", "Water troll", "Water demon" } }, - [FEAT_DEEP_WATER] = { SKILL_WATER, { "Water elemental", "Water troll", "Water demon" } }, - } - - local y, x = explode_dir(dir) - y = y + player.py - x = x + player.px - - local effect = t[cave(y, x).feat] - if not effect then - msg_print("You cannot summon from this area.") - else - local skill = effect[1] - local types = effect[2] - - local max = get_skill_scale(skill, getn(types)) - if max == 0 then max = 1 end - - local r_idx = test_monster_name(types[rand_range(1, max)]) - - -- Summon it - local my, mx = find_position(y, x) - local m_idx = place_monster_one(my, mx, r_idx, 0, FALSE, MSTATUS_FRIEND) - - -- level it - if m_idx ~= 0 then - monster_set_level(m_idx, 10 + get_level(ELEMENTAL_MINION, 120)) - end - - cave_set_feat(y, x, FEAT_FLOOR) - end - - return TRUE - end, - ["info"] = function() - return "min level "..(10 + get_level(ELEMENTAL_MINION, 120)) - end, + ["spell"] = function() return geomancy_elemental_minion() end, + ["info"] = function() return geomancy_elemental_minion_info() end, ["desc"] = { "Summons a minion from a nearby element.", "Walls can summon Earth elmentals, Xorns and Xarens", diff --git a/src/cmd1.c b/src/cmd1.c index 49c0d38f..1184df0c 100644 --- a/src/cmd1.c +++ b/src/cmd1.c @@ -3098,6 +3098,17 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm) /* Some hooks */ if (process_hooks(HOOK_MOVE, "(d,d)", y, x)) return; + if (p_ptr->dripping_tread > 0) + { + geomancy_random_floor(y, x, FALSE); + p_ptr->dripping_tread -= 1; + if (p_ptr->dripping_tread == 0) + { + msg_print("You stop dripping raw elemental energies."); + } + } + + /* Get the monster */ m_ptr = &m_list[c_ptr->m_idx]; mr_ptr = race_inf(m_ptr); diff --git a/src/externs.h b/src/externs.h index fd156286..77d5613e 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1538,6 +1538,32 @@ char *fire_firewall_info(); bool_ *fire_golem(); char *fire_golem_info(); +extern s32b CALL_THE_ELEMENTS; +extern s32b CHANNEL_ELEMENTS; +extern s32b ELEMENTAL_WAVE; +extern s32b VAPORIZE; +extern s32b GEOLYSIS; +extern s32b DRIPPING_TREAD; +extern s32b GROW_BARRIER; +extern s32b ELEMENTAL_MINION; + +bool_ *geomancy_call_the_elements(); +char *geomancy_call_the_elements_info(); +bool_ *geomancy_channel_elements(); +char *geomancy_channel_elements_info(); +bool_ *geomancy_elemental_wave(); +char *geomancy_elemental_wave_info(); +bool_ *geomancy_vaporize(); +char *geomancy_vaporize_info(); +bool_ *geomancy_geolysis(); +char *geomancy_geolysis_info(); +bool_ *geomancy_dripping_tread(); +char *geomancy_dripping_tread_info(); +bool_ *geomancy_grow_barrier(); +char *geomancy_grow_barrier_info(); +bool_ *geomancy_elemental_minion(); +char *geomancy_elemental_minion_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/loadsave.c b/src/loadsave.c index cb9156a9..5116acef 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -2874,6 +2874,9 @@ static bool_ do_savefile_aux(int flag) do_byte(&p_ptr->pet_open_doors, flag); do_byte(&p_ptr->pet_pickup_items, flag); + /* Dripping Tread */ + do_s16b(&p_ptr->dripping_tread, flag); + /* Read the inventory */ if (!do_inventory(flag) && (flag == LS_LOAD)) /* do NOT reverse this ordering */ { diff --git a/src/spells.pkg b/src/spells.pkg index 260cdf50..adfd6f1d 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2579,3 +2579,32 @@ bool_ *fire_firewall(); char *fire_firewall_info(); bool_ *fire_golem(); char *fire_golem_info(); + +/* + * Geomancy + */ +extern s32b CALL_THE_ELEMENTS; +extern s32b CHANNEL_ELEMENTS; +extern s32b ELEMENTAL_WAVE; +extern s32b VAPORIZE; +extern s32b GEOLYSIS; +extern s32b DRIPPING_TREAD; +extern s32b GROW_BARRIER; +extern s32b ELEMENTAL_MINION; + +bool_ *geomancy_call_the_elements(); +char *geomancy_call_the_elements_info(); +bool_ *geomancy_channel_elements(); +char *geomancy_channel_elements_info(); +bool_ *geomancy_elemental_wave(); +char *geomancy_elemental_wave_info(); +bool_ *geomancy_vaporize(); +char *geomancy_vaporize_info(); +bool_ *geomancy_geolysis(); +char *geomancy_geolysis_info(); +bool_ *geomancy_dripping_tread(); +char *geomancy_dripping_tread_info(); +bool_ *geomancy_grow_barrier(); +char *geomancy_grow_barrier_info(); +bool_ *geomancy_elemental_minion(); +char *geomancy_elemental_minion_info(); diff --git a/src/spells3.c b/src/spells3.c index 7c8173ea..c3ca27bc 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -48,6 +48,15 @@ s32b FIERYAURA; s32b FIREWALL; s32b FIREGOLEM; +s32b CALL_THE_ELEMENTS; +s32b CHANNEL_ELEMENTS; +s32b ELEMENTAL_WAVE; +s32b VAPORIZE; +s32b GEOLYSIS; +s32b DRIPPING_TREAD; +s32b GROW_BARRIER; +s32b ELEMENTAL_MINION; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua cares about). */ @@ -1287,3 +1296,394 @@ char *fire_golem_info() (7 + get_level_s(FIREGOLEM, 70))); return buf; } + +bool_ *geomancy_call_the_elements() +{ + int dir = 0; + + if (get_level_s(CALL_THE_ELEMENTS, 50) >= 17) + { + if (!get_aim_dir(&dir)) + { + return FALSE; + } + } + + fire_ball(GF_ELEMENTAL_GROWTH, + dir, + 1, + 1 + get_level(CALL_THE_ELEMENTS, 5, 0)); + + return CAST; +} + +char *geomancy_call_the_elements_info() +{ + static char buf[128]; + sprintf(buf, + "rad %d", + (1 + get_level(CALL_THE_ELEMENTS, 5, 0))); + return buf; +} + +bool_ *geomancy_channel_elements() +{ + channel_the_elements(p_ptr->py, p_ptr->px, get_level_s(CHANNEL_ELEMENTS, 50)); + return CAST; +} + +char *geomancy_channel_elements_info() +{ + return ""; +} + +typedef struct eff_type eff_type; +struct eff_type { + s16b feat; + s16b low_effect; + s16b high_effect; + s16b damage; +}; + +static eff_type *geomancy_find_effect(eff_type effs[], int feat) +{ + int i; + for (i = 0; effs[i].feat >= 0; i++) + { + eff_type *p = &effs[i]; + if (p->feat == feat) + { + return p; + } + } + return NULL; +} + +bool_ *geomancy_elemental_wave() +{ + int dir = 0, y = 0, x = 0; + eff_type *eff_ptr = NULL; + eff_type t[] = + { + /* Earth */ + { FEAT_GRASS, GF_POIS, GF_POIS, 10 + get_skill_scale(SKILL_EARTH, 200) }, + { FEAT_FLOWER, GF_POIS, GF_POIS, 10 + get_skill_scale(SKILL_EARTH, 300) }, + + /* Water */ + { FEAT_SHAL_WATER, GF_WATER, GF_WATER, 10 + get_skill_scale(SKILL_WATER, 200) }, + { FEAT_DEEP_WATER, GF_WATER, GF_WATER, 10 + get_skill_scale(SKILL_WATER, 300) }, + { FEAT_ICE, GF_ICE, GF_ICE, 10 + get_skill_scale(SKILL_WATER, 200) }, + + /* Fire */ + { FEAT_SAND, GF_LITE, GF_LITE, 10 + get_skill_scale(SKILL_FIRE, 400) }, + { FEAT_SHAL_LAVA, GF_FIRE, GF_HOLY_FIRE, 10 + get_skill_scale(SKILL_FIRE, 200) }, + { FEAT_DEEP_LAVA, GF_FIRE, GF_HOLY_FIRE, 10 + get_skill_scale(SKILL_FIRE, 300) }, + { -1, -1, -1, -1 }, + }; + + if (!get_rep_dir(&dir)) + { + return FALSE; + } + + y = ddy[dir] + p_ptr->py; + x = ddx[dir] + p_ptr->px; + + eff_ptr = geomancy_find_effect(t, cave[y][x].feat); + + if (!eff_ptr) + { + msg_print("You cannot channel this area."); + return NO_CAST; + } + else + { + s16b typ = eff_ptr->low_effect; + char buf[16]; + s32b EFF_DIR; + + sprintf(buf, "EFF_DIR%d", dir); + EFF_DIR = get_lua_int(buf); + + if (get_level_s(ELEMENTAL_WAVE, 50) >= 20) + { + typ = eff_ptr->high_effect; + } + + cave_set_feat(y, x, FEAT_FLOOR); + + fire_wave(typ, + 0, + eff_ptr->damage, + 0, + 6 + get_level_s(ELEMENTAL_WAVE, 20), + EFF_WAVE + EFF_LAST + EFF_DIR); + + return CAST; + } +} + +char *geomancy_elemental_wave_info() +{ + return ""; +} + +bool_ *geomancy_vaporize() +{ + eff_type *eff_ptr = NULL; + eff_type t[] = { + /* Earth stuff */ + { FEAT_GRASS, GF_POIS, GF_POIS, 5 + get_skill_scale(SKILL_EARTH, 100) }, + { FEAT_FLOWER, GF_POIS, GF_POIS, 5 + get_skill_scale(SKILL_EARTH, 150) }, + { FEAT_DARK_PIT, GF_DARK, GF_DARK, 5 + get_skill_scale(SKILL_EARTH, 200) }, + /* Water stuff */ + { FEAT_SHAL_WATER, GF_WATER, GF_WATER, 5 + get_skill_scale(SKILL_WATER, 100) }, + { FEAT_DEEP_WATER, GF_WATER, GF_WATER, 5 + get_skill_scale(SKILL_WATER, 150) }, + { FEAT_ICE, GF_ICE, GF_ICE, 5 + get_skill_scale(SKILL_WATER, 100) }, + /* Fire stuff */ + { FEAT_SAND, GF_LITE, GF_LITE, 5 + get_skill_scale(SKILL_FIRE, 200) }, + { FEAT_SHAL_LAVA, GF_FIRE, GF_HOLY_FIRE, 5 + get_skill_scale(SKILL_FIRE, 100) }, + { FEAT_DEEP_LAVA, GF_FIRE, GF_HOLY_FIRE, 5 + get_skill_scale(SKILL_FIRE, 150) }, + { -1, -1, -1, -1 }, + }; + + eff_ptr = geomancy_find_effect(t, cave[p_ptr->py][p_ptr->px].feat); + + if (!eff_ptr) + { + msg_print("You cannot channel this area."); + return NO_CAST; + } + else + { + s16b typ = eff_ptr->low_effect; + if (get_level_s(VAPORIZE, 50) >= 20) + { + typ = eff_ptr->high_effect; + } + + cave_set_feat(p_ptr->py, p_ptr->px, FEAT_FLOOR); + + fire_cloud(typ, + 0, + eff_ptr->damage, + 1 + get_level_s(VAPORIZE, 4), + 10 + get_level_s(VAPORIZE, 20)); + + return CAST; + } +} + +char *geomancy_vaporize_info() +{ + static char buf[128]; + sprintf(buf, + "rad %d dur %d", + (1 + get_level_s(VAPORIZE, 4)), + (10 + get_level_s(VAPORIZE, 20))); + return buf; +} + +bool_ *geomancy_geolysis() +{ + int dir = 0; + + if (!get_rep_dir(&dir)) + { + return NO_CAST; + } + + msg_print("Elements recombine before you, laying down an open path."); + geomancy_dig(p_ptr->py, p_ptr->px, dir, 5 + get_level_s(GEOLYSIS, 12)); + + return CAST; +} + +char *geomancy_geolysis_info() +{ + static char buf[128]; + sprintf(buf, + "length %d", + (5 + get_level_s(GEOLYSIS, 12))); + return buf; +} + +bool_ *geomancy_dripping_tread() +{ + if (p_ptr->dripping_tread == 0) + { + p_ptr->dripping_tread = randint(15) + 10 + get_level_s(DRIPPING_TREAD, 50); + msg_print("You start dripping raw elemental energies."); + } + else + { + p_ptr->dripping_tread = 0; + msg_print("You stop dripping raw elemental energies."); + } + + return CAST; +} + +char *geomancy_dripping_tread_info() +{ + static char buf[128]; + sprintf(buf, + "dur %d+d15 movs", + (10 + get_level_s(DRIPPING_TREAD, 50))); + return buf; +} + +bool_ *geomancy_grow_barrier() +{ + int dir = 0; + + if (get_level_s(GROW_BARRIER, 50) >= 20) + { + if (!get_aim_dir(&dir)) + { + return FALSE; + } + } + + fire_ball(GF_ELEMENTAL_WALL, dir, 1, 1); + return CAST; +} + +char *geomancy_grow_barrier_info() +{ + return ""; +} + +typedef struct geo_summon geo_summon; +struct geo_summon { + s16b feat; + s16b skill_idx; + cptr *summon_names; +}; + +geo_summon *geomancy_find_summon(geo_summon summons[], int feat) +{ + int i; + for (i = 0; summons[i].feat >= 0; i++) + { + geo_summon *summon = &summons[i]; + if (summon->feat == feat) + { + return summon; + } + } + return NULL; +} + +int geomancy_count_elements(cptr *elements) +{ + int i; + for (i = 0; elements[i] != NULL; i++) + { + } + return i; +} + +bool_ *geomancy_elemental_minion() +{ + int dir = 0; + int x = 0, y = 0; + geo_summon *summon_ptr = NULL; + cptr earth_summons[] = { + "Earth elemental", + "Xorn", + "Xaren", + NULL + }; + cptr air_summons[] = { + "Air elemental", + "Ancient blue dragon", + "Great Storm Wyrm", + "Sky Drake", + NULL + }; + cptr fire_summons[] = { + "Fire elemental", + "Ancient red dragon", + NULL + }; + cptr water_summons[] = { + "Water elemental", + "Water troll", + "Water demon", + NULL + }; + geo_summon summons[] = { + { FEAT_WALL_EXTRA, SKILL_EARTH, earth_summons }, + { FEAT_WALL_OUTER, SKILL_EARTH, earth_summons }, + { FEAT_WALL_INNER, SKILL_EARTH, earth_summons }, + { FEAT_WALL_SOLID, SKILL_EARTH, earth_summons }, + { FEAT_MAGMA, SKILL_EARTH, earth_summons }, + { FEAT_QUARTZ, SKILL_EARTH, earth_summons }, + { FEAT_MAGMA_H, SKILL_EARTH, earth_summons }, + { FEAT_QUARTZ_H, SKILL_EARTH, earth_summons }, + { FEAT_MAGMA_K, SKILL_EARTH, earth_summons }, + { FEAT_QUARTZ_K, SKILL_EARTH, earth_summons }, + + { FEAT_DARK_PIT, SKILL_AIR, air_summons }, + + { FEAT_SANDWALL, SKILL_FIRE, fire_summons }, + { FEAT_SANDWALL_H, SKILL_FIRE, fire_summons }, + { FEAT_SANDWALL_K, SKILL_FIRE, fire_summons }, + { FEAT_SHAL_LAVA, SKILL_FIRE, fire_summons }, + { FEAT_DEEP_LAVA, SKILL_FIRE, fire_summons }, + + { FEAT_ICE_WALL, SKILL_WATER, water_summons }, + { FEAT_SHAL_WATER, SKILL_WATER, water_summons }, + { FEAT_DEEP_WATER, SKILL_WATER, water_summons }, + + { -1, -1, NULL }, + }; + + if (!get_rep_dir(&dir)) + { + return NO_CAST; + } + + y = ddy[dir] + p_ptr->py; + x = ddx[dir] + p_ptr->px; + + summon_ptr = geomancy_find_summon(summons, cave[y][x].feat); + + if (!summon_ptr) + { + msg_print("You cannot summon from this area."); + return NO_CAST; + } + else + { + cptr *names = summon_ptr->summon_names; + int max = get_skill_scale(summon_ptr->skill_idx, + geomancy_count_elements(names)); + int r_idx = test_monster_name(names[rand_int(max)]); + int mx, my, m_idx; + + /* Summon it */ + find_position(y, x, &my, &mx); + m_idx = place_monster_one(my, mx, r_idx, 0, FALSE, MSTATUS_FRIEND); + + /* Level it */ + if (m_idx) + { + monster_set_level(m_idx, 10 + get_level_s(ELEMENTAL_MINION, 120)); + } + + cave_set_feat(y, x, FEAT_FLOOR); + + return CAST; + } +} + +char *geomancy_elemental_minion_info() +{ + static char buf[128]; + sprintf(buf, + "min level %d", + (10 + get_level_s(ELEMENTAL_MINION, 120))); + return buf; +} diff --git a/src/types.h b/src/types.h index ea8213a3..ea66ff5f 100644 --- a/src/types.h +++ b/src/types.h @@ -1837,6 +1837,9 @@ struct player_type s16b melee_style; /* How are */ s16b use_piercing_shots; /* for archery */ + /* Dripping Tread spell timer */ + s16b dripping_tread; + /* Help */ help_info help; -- cgit v1.2.3 From 1cd265d4f32d2c624387b1bafc45ed0d18b3d257 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 19 Apr 2012 18:42:11 +0200 Subject: Lua: Move "Mana" spell functions to C --- lib/mods/theme/scpt/s_mana.lua | 59 +++--------------- lib/scpt/s_mana.lua | 59 +++--------------- src/externs.h | 14 +++++ src/spells.pkg | 14 +++++ src/spells3.c | 136 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 180 insertions(+), 102 deletions(-) diff --git a/lib/mods/theme/scpt/s_mana.lua b/lib/mods/theme/scpt/s_mana.lua index 736b06b0..67126fb2 100644 --- a/lib/mods/theme/scpt/s_mana.lua +++ b/lib/mods/theme/scpt/s_mana.lua @@ -1,9 +1,5 @@ -- The mana school -function get_manathrust_dam() - return 3 + get_level(MANATHRUST, 50), 1 + get_level(MANATHRUST, 20) -end - MANATHRUST = add_spell { ["name"] = "Manathrust", @@ -22,19 +18,8 @@ MANATHRUST = add_spell ["max_level"] = { 15, 33 }, }, }, - ["spell"] = function() - local ret, dir - - ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_bolt(GF_MANA, dir, damroll(get_manathrust_dam())) - end, - ["info"] = function() - local x, y - - x, y = get_manathrust_dam() - return "dam "..x.."d"..y - end, + ["spell"] = function() return mana_manathrust() end, + ["info"] = function() return mana_manathrust_info() end, ["desc"] = { "Conjures up mana into a powerful bolt", "The damage is irresistible and will increase with level" @@ -60,17 +45,8 @@ DELCURSES = add_spell }, }, ["inertia"] = { 1, 10 }, - ["spell"] = function() - local done - - if get_level(DELCURSES, 50) >= 20 then done = remove_all_curse() - else done = remove_curse() end - if done == TRUE then msg_print("The curse is broken!") end - return done - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return mana_remove_curses() end, + ["info"] = function() return mana_remove_curses_info() end, ["desc"] = { "Remove curses of worn objects", "At level 20 switches to *remove curses*" @@ -86,17 +62,8 @@ RESISTS = add_spell ["mana_max"] = 20, ["fail"] = 40, ["inertia"] = { 2, 25 }, - ["spell"] = function() - local obvious - if player.oppose_fire == 0 then obvious = set_oppose_fire(randint(10) + 15 + get_level(RESISTS, 50)) end - if player.oppose_cold == 0 then obvious = is_obvious(set_oppose_cold(randint(10) + 15 + get_level(RESISTS, 50)), obvious) end - if player.oppose_elec == 0 then obvious = is_obvious(set_oppose_elec(randint(10) + 15 + get_level(RESISTS, 50)), obvious) end - if player.oppose_acid == 0 then obvious = is_obvious(set_oppose_acid(randint(10) + 15 + get_level(RESISTS, 50)), obvious) end - return obvious - end, - ["info"] = function() - return "dur "..(15 + get_level(RESISTS, 50)).."+d10" - end, + ["spell"] = function() return mana_elemental_shield() end, + ["info"] = function() return mana_elemental_shield_info() end, ["desc"] = { "Provide resistances to the four basic elements", } @@ -111,18 +78,8 @@ MANASHIELD = add_spell ["mana_max"] = 50, ["fail"] = 90, ["inertia"] = { 9, 10}, - ["spell"] = function() - if get_level(MANASHIELD, 50) >= 5 then - if (player.invuln == 0) then - return set_invuln(randint(5) + 3 + get_level(MANASHIELD, 10)) - end - else - if (player.disrupt_shield == 0) then return set_disrupt_shield(randint(5) + 3 + get_level(MANASHIELD, 10)) end - end - end, - ["info"] = function() - return "dur "..(3 + get_level(MANASHIELD, 10)).."+d5" - end, + ["spell"] = function() return mana_disruption_shield() end, + ["info"] = function() return mana_disruption_shield_info() end, ["desc"] = { "Uses mana instead of hp to take damage", "At level 5 switches to Globe of Invulnerability.", diff --git a/lib/scpt/s_mana.lua b/lib/scpt/s_mana.lua index 736b06b0..67126fb2 100644 --- a/lib/scpt/s_mana.lua +++ b/lib/scpt/s_mana.lua @@ -1,9 +1,5 @@ -- The mana school -function get_manathrust_dam() - return 3 + get_level(MANATHRUST, 50), 1 + get_level(MANATHRUST, 20) -end - MANATHRUST = add_spell { ["name"] = "Manathrust", @@ -22,19 +18,8 @@ MANATHRUST = add_spell ["max_level"] = { 15, 33 }, }, }, - ["spell"] = function() - local ret, dir - - ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_bolt(GF_MANA, dir, damroll(get_manathrust_dam())) - end, - ["info"] = function() - local x, y - - x, y = get_manathrust_dam() - return "dam "..x.."d"..y - end, + ["spell"] = function() return mana_manathrust() end, + ["info"] = function() return mana_manathrust_info() end, ["desc"] = { "Conjures up mana into a powerful bolt", "The damage is irresistible and will increase with level" @@ -60,17 +45,8 @@ DELCURSES = add_spell }, }, ["inertia"] = { 1, 10 }, - ["spell"] = function() - local done - - if get_level(DELCURSES, 50) >= 20 then done = remove_all_curse() - else done = remove_curse() end - if done == TRUE then msg_print("The curse is broken!") end - return done - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return mana_remove_curses() end, + ["info"] = function() return mana_remove_curses_info() end, ["desc"] = { "Remove curses of worn objects", "At level 20 switches to *remove curses*" @@ -86,17 +62,8 @@ RESISTS = add_spell ["mana_max"] = 20, ["fail"] = 40, ["inertia"] = { 2, 25 }, - ["spell"] = function() - local obvious - if player.oppose_fire == 0 then obvious = set_oppose_fire(randint(10) + 15 + get_level(RESISTS, 50)) end - if player.oppose_cold == 0 then obvious = is_obvious(set_oppose_cold(randint(10) + 15 + get_level(RESISTS, 50)), obvious) end - if player.oppose_elec == 0 then obvious = is_obvious(set_oppose_elec(randint(10) + 15 + get_level(RESISTS, 50)), obvious) end - if player.oppose_acid == 0 then obvious = is_obvious(set_oppose_acid(randint(10) + 15 + get_level(RESISTS, 50)), obvious) end - return obvious - end, - ["info"] = function() - return "dur "..(15 + get_level(RESISTS, 50)).."+d10" - end, + ["spell"] = function() return mana_elemental_shield() end, + ["info"] = function() return mana_elemental_shield_info() end, ["desc"] = { "Provide resistances to the four basic elements", } @@ -111,18 +78,8 @@ MANASHIELD = add_spell ["mana_max"] = 50, ["fail"] = 90, ["inertia"] = { 9, 10}, - ["spell"] = function() - if get_level(MANASHIELD, 50) >= 5 then - if (player.invuln == 0) then - return set_invuln(randint(5) + 3 + get_level(MANASHIELD, 10)) - end - else - if (player.disrupt_shield == 0) then return set_disrupt_shield(randint(5) + 3 + get_level(MANASHIELD, 10)) end - end - end, - ["info"] = function() - return "dur "..(3 + get_level(MANASHIELD, 10)).."+d5" - end, + ["spell"] = function() return mana_disruption_shield() end, + ["info"] = function() return mana_disruption_shield_info() end, ["desc"] = { "Uses mana instead of hp to take damage", "At level 5 switches to Globe of Invulnerability.", diff --git a/src/externs.h b/src/externs.h index 77d5613e..295b008e 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1564,6 +1564,20 @@ char *geomancy_grow_barrier_info(); bool_ *geomancy_elemental_minion(); char *geomancy_elemental_minion_info(); +extern s32b MANATHRUST; +extern s32b DELCURSES; +extern s32b RESISTS; +extern s32b MANASHIELD; + +bool_ *mana_manathrust(); +char *mana_manathrust_info(); +bool_ *mana_remove_curses(); +char *mana_remove_curses_info(); +bool_ *mana_elemental_shield(); +char *mana_elemental_shield_info(); +bool_ *mana_disruption_shield(); +char *mana_disruption_shield_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index adfd6f1d..458fdc49 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2608,3 +2608,17 @@ bool_ *geomancy_grow_barrier(); char *geomancy_grow_barrier_info(); bool_ *geomancy_elemental_minion(); char *geomancy_elemental_minion_info(); + +extern s32b MANATHRUST; +extern s32b DELCURSES; +extern s32b RESISTS; +extern s32b MANASHIELD; + +bool_ *mana_manathrust(); +char *mana_manathrust_info(); +bool_ *mana_remove_curses(); +char *mana_remove_curses_info(); +bool_ *mana_elemental_shield(); +char *mana_elemental_shield_info(); +bool_ *mana_disruption_shield(); +char *mana_disruption_shield_info(); diff --git a/src/spells3.c b/src/spells3.c index c3ca27bc..d9b36410 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -57,6 +57,11 @@ s32b DRIPPING_TREAD; s32b GROW_BARRIER; s32b ELEMENTAL_MINION; +s32b MANATHRUST; +s32b DELCURSES; +s32b RESISTS; +s32b MANASHIELD; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua cares about). */ @@ -1687,3 +1692,134 @@ char *geomancy_elemental_minion_info() (10 + get_level_s(ELEMENTAL_MINION, 120))); return buf; } + +static void get_manathrust_dam(s16b *num, s16b *sides) +{ + *num = 3 + get_level_s(MANATHRUST, 50); + *sides = 1 + get_level_s(MANATHRUST, 20); +} + +bool_ *mana_manathrust() +{ + int dir; + s16b num = 0; + s16b sides = 0; + + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + get_manathrust_dam(&num, &sides); + fire_bolt(GF_MANA, dir, damroll(num, sides)); + return CAST; +} + +char *mana_manathrust_info() +{ + s16b num = 0; + s16b sides = 0; + static char buf[128]; + + get_manathrust_dam(&num, &sides); + sprintf(buf, + "dam %dd%d", + num, + sides); + return buf; +} + +bool_ *mana_remove_curses() +{ + bool_ done = FALSE; + + if (get_level_s(DELCURSES, 50) >= 20) + { + done = remove_all_curse(); + } + else + { + done = remove_curse(); + } + + if (done) + { + msg_print("The curse is broken!"); + } + + return CAST; +} + +char *mana_remove_curses_info() +{ + return ""; +} + +bool_ *mana_elemental_shield() +{ + bool_ *res = NO_CAST; + + if (p_ptr->oppose_fire == 0) + { + set_oppose_fire(randint(10) + 15 + get_level_s(RESISTS, 50)); + res = CAST; + } + + if (p_ptr->oppose_cold == 0) + { + set_oppose_cold(randint(10) + 15 + get_level_s(RESISTS, 50)); + res = CAST; + } + + if (p_ptr->oppose_elec == 0) + { + set_oppose_elec(randint(10) + 15 + get_level_s(RESISTS, 50)); + res = CAST; + } + + if (p_ptr->oppose_acid == 0) + { + set_oppose_acid(randint(10) + 15 + get_level_s(RESISTS, 50)); + res = CAST; + } + + return res; +} + +char *mana_elemental_shield_info() +{ + static char buf[128]; + sprintf(buf, + "dur %d+d10", + (15 + get_level_s(RESISTS, 50))); + return buf; +} + +bool_ *mana_disruption_shield() +{ + if (get_level_s(MANASHIELD, 50) >= 5) + { + if (p_ptr->invuln == 0) + { + set_invuln(randint(5) + 3 + get_level_s(MANASHIELD, 10)); + return CAST; + } + } + else if (p_ptr->disrupt_shield == 0) + { + set_disrupt_shield(randint(5) + 3 + get_level_s(MANASHIELD, 10)); + return CAST; + } + + return NO_CAST; +} + +char *mana_disruption_shield_info() +{ + static char buf[128]; + sprintf(buf, + "dur %d+d5", + (3 + get_level_s(MANASHIELD, 10))); + return buf; +} + -- cgit v1.2.3 From 4743b501f48b257b32defb201c35ec05cf7feaa9 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 19 Apr 2012 23:11:34 +0200 Subject: Add option to edit piety in wizard mode. --- src/wizard2.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/wizard2.c b/src/wizard2.c index 36efa148..e2683435 100644 --- a/src/wizard2.c +++ b/src/wizard2.c @@ -351,6 +351,23 @@ static void do_cmd_wiz_change_aux(void) /* Update */ check_experience(); + + /* Default */ + sprintf(tmp_val, "%ld", (long) (p_ptr->grace)); + + /* Query */ + if (!get_string("Piety: ", tmp_val, 9)) return; + + /* Extract */ + tmp_long = atol(tmp_val); + + /* Verify */ + if (tmp_long < 0) tmp_long = 0L; + + /* Save */ + p_ptr->grace = tmp_long; + + /* Default */ sprintf(tmp_val, "%d", p_ptr->luck_base); -- cgit v1.2.3 From 1c618e2f21a49e1faccbf27ad146da638af4902b Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 19 Apr 2012 23:15:46 +0200 Subject: Fix: Mimic form power/bonus functions are optional. --- src/mimic.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/mimic.c b/src/mimic.c index 6d241500..90c8a62a 100644 --- a/src/mimic.c +++ b/src/mimic.c @@ -671,7 +671,14 @@ s32b get_mimic_random_duration(s16b mf_idx) byte calc_mimic() { mimic_form_type *mf_ptr = get_mimic_form(p_ptr->mimic_form); - return mf_ptr->calc(); + if (mf_ptr->calc != NULL) + { + return mf_ptr->calc(); + } + else + { + return 0; + } } /* @@ -680,5 +687,8 @@ byte calc_mimic() void calc_mimic_power() { mimic_form_type *mf_ptr = get_mimic_form(p_ptr->mimic_form); - return mf_ptr->power(); + if (mf_ptr->power != NULL) + { + mf_ptr->power(); + } } -- cgit v1.2.3 From 58c866837fda7ba06e465f45fbf68eafe921db86 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 19 Apr 2012 23:18:15 +0200 Subject: Lua: Move 'Manwe' spell functions to C --- lib/mods/theme/scpt/s_manwe.lua | 76 +++------------------- lib/scpt/s_manwe.lua | 76 +++------------------- src/externs.h | 14 ++++ src/spells.pkg | 14 ++++ src/spells3.c | 138 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 182 insertions(+), 136 deletions(-) diff --git a/lib/mods/theme/scpt/s_manwe.lua b/lib/mods/theme/scpt/s_manwe.lua index 6f0f9661..189f50ff 100644 --- a/lib/mods/theme/scpt/s_manwe.lua +++ b/lib/mods/theme/scpt/s_manwe.lua @@ -12,33 +12,8 @@ MANWE_SHIELD = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local dur = get_level(MANWE_SHIELD, 50) + 10 + randint(20) - local obvious - - obvious = set_protevil(dur) - if get_level(MANWE_SHIELD) >= 10 then - local type - - type = 0 - if get_level(MANWE_SHIELD) >= 20 then - type = SHIELD_COUNTER - end - obvious = is_obvious(set_shield(dur, get_level(MANWE_SHIELD, 30), type, 1 + get_level(MANWE_SHIELD, 2), 1 + get_level(MANWE_SHIELD, 6)), obvious) - end - return obvious - end, - ["info"] = function() - local desc = "dur "..(get_level(MANWE_SHIELD, 50) + 10).."+d20" - - if get_level(MANWE_SHIELD) >= 10 then - desc = desc.." AC "..(get_level(MANWE_SHIELD, 30)) - end - if get_level(MANWE_SHIELD) >= 20 then - desc = desc.." dam "..(1 + get_level(MANWE_SHIELD, 2)).."d"..(1 + get_level(MANWE_SHIELD, 6)) - end - return desc - end, + ["spell"] = function() return manwe_wind_shield() end, + ["info"] = function() return manwe_wind_shield_info() end, ["desc"] = { "It surrounds you with a shield of wind that deflects blows from evil monsters", "At level 10 it increases your armour rating", @@ -58,12 +33,8 @@ MANWE_AVATAR = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - return set_mimic(get_level(MANWE_AVATAR, 20) + randint(10), resolve_mimic_name("Maia"), player.lev) - end, - ["info"] = function() - return "dur "..(get_level(MANWE_AVATAR, 20)).."+d10" - end, + ["spell"] = function() return manwe_avatar() end, + ["info"] = function() return manwe_avatar_info() end, ["desc"] = { "It turns you into a full grown Maia", } @@ -81,27 +52,8 @@ MANWE_BLESS = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local dur = get_level(MANWE_BLESS, 70) + 30 + randint(40) - local obvious - - obvious = set_blessed(dur) - obvious = is_obvious(set_afraid(0), obvious) - obvious = is_obvious(set_lite(0), obvious) - if get_level(MANWE_BLESS) >= 10 then - obvious = is_obvious(set_hero(dur), obvious) - end - if get_level(MANWE_BLESS) >= 20 then - obvious = is_obvious(set_shero(dur), obvious) - end - if get_level(MANWE_BLESS) >= 30 then - obvious = is_obvious(set_holy(dur), obvious) - end - return obvious - end, - ["info"] = function() - return "dur "..(get_level(MANWE_BLESS, 70) + 30).."+d40" - end, + ["spell"] = function() return manwe_blessing() end, + ["info"] = function() return manwe_blessing_info() end, ["desc"] = { "Manwe's Blessing removes your fears, blesses you and surrounds you with", "holy light", @@ -123,20 +75,8 @@ MANWE_CALL = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local y, x, m_idx - - y, x = find_position(player.py, player.px) - m_idx = place_monster_one(y, x, test_monster_name("Great eagle"), 0, FALSE, MSTATUS_FRIEND) - - if m_idx ~= 0 then - monster_set_level(m_idx, 20 + get_level(MANWE_CALL, 70, 0)) - return TRUE - end - end, - ["info"] = function() - return "level "..(get_level(MANWE_CALL, 70) + 20) - end, + ["spell"] = function() return manwe_call() end, + ["info"] = function() return manwe_call_info() end, ["desc"] = { "Manwe's Call summons a Great Eagle to help you battle the forces", "of Morgoth" diff --git a/lib/scpt/s_manwe.lua b/lib/scpt/s_manwe.lua index 6f0f9661..189f50ff 100644 --- a/lib/scpt/s_manwe.lua +++ b/lib/scpt/s_manwe.lua @@ -12,33 +12,8 @@ MANWE_SHIELD = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local dur = get_level(MANWE_SHIELD, 50) + 10 + randint(20) - local obvious - - obvious = set_protevil(dur) - if get_level(MANWE_SHIELD) >= 10 then - local type - - type = 0 - if get_level(MANWE_SHIELD) >= 20 then - type = SHIELD_COUNTER - end - obvious = is_obvious(set_shield(dur, get_level(MANWE_SHIELD, 30), type, 1 + get_level(MANWE_SHIELD, 2), 1 + get_level(MANWE_SHIELD, 6)), obvious) - end - return obvious - end, - ["info"] = function() - local desc = "dur "..(get_level(MANWE_SHIELD, 50) + 10).."+d20" - - if get_level(MANWE_SHIELD) >= 10 then - desc = desc.." AC "..(get_level(MANWE_SHIELD, 30)) - end - if get_level(MANWE_SHIELD) >= 20 then - desc = desc.." dam "..(1 + get_level(MANWE_SHIELD, 2)).."d"..(1 + get_level(MANWE_SHIELD, 6)) - end - return desc - end, + ["spell"] = function() return manwe_wind_shield() end, + ["info"] = function() return manwe_wind_shield_info() end, ["desc"] = { "It surrounds you with a shield of wind that deflects blows from evil monsters", "At level 10 it increases your armour rating", @@ -58,12 +33,8 @@ MANWE_AVATAR = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - return set_mimic(get_level(MANWE_AVATAR, 20) + randint(10), resolve_mimic_name("Maia"), player.lev) - end, - ["info"] = function() - return "dur "..(get_level(MANWE_AVATAR, 20)).."+d10" - end, + ["spell"] = function() return manwe_avatar() end, + ["info"] = function() return manwe_avatar_info() end, ["desc"] = { "It turns you into a full grown Maia", } @@ -81,27 +52,8 @@ MANWE_BLESS = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local dur = get_level(MANWE_BLESS, 70) + 30 + randint(40) - local obvious - - obvious = set_blessed(dur) - obvious = is_obvious(set_afraid(0), obvious) - obvious = is_obvious(set_lite(0), obvious) - if get_level(MANWE_BLESS) >= 10 then - obvious = is_obvious(set_hero(dur), obvious) - end - if get_level(MANWE_BLESS) >= 20 then - obvious = is_obvious(set_shero(dur), obvious) - end - if get_level(MANWE_BLESS) >= 30 then - obvious = is_obvious(set_holy(dur), obvious) - end - return obvious - end, - ["info"] = function() - return "dur "..(get_level(MANWE_BLESS, 70) + 30).."+d40" - end, + ["spell"] = function() return manwe_blessing() end, + ["info"] = function() return manwe_blessing_info() end, ["desc"] = { "Manwe's Blessing removes your fears, blesses you and surrounds you with", "holy light", @@ -123,20 +75,8 @@ MANWE_CALL = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local y, x, m_idx - - y, x = find_position(player.py, player.px) - m_idx = place_monster_one(y, x, test_monster_name("Great eagle"), 0, FALSE, MSTATUS_FRIEND) - - if m_idx ~= 0 then - monster_set_level(m_idx, 20 + get_level(MANWE_CALL, 70, 0)) - return TRUE - end - end, - ["info"] = function() - return "level "..(get_level(MANWE_CALL, 70) + 20) - end, + ["spell"] = function() return manwe_call() end, + ["info"] = function() return manwe_call_info() end, ["desc"] = { "Manwe's Call summons a Great Eagle to help you battle the forces", "of Morgoth" diff --git a/src/externs.h b/src/externs.h index 295b008e..e46e864f 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1578,6 +1578,20 @@ char *mana_elemental_shield_info(); bool_ *mana_disruption_shield(); char *mana_disruption_shield_info(); +extern s32b MANWE_SHIELD; +extern s32b MANWE_AVATAR; +extern s32b MANWE_BLESS; +extern s32b MANWE_CALL; + +bool_ *manwe_wind_shield(); +char *manwe_wind_shield_info(); +bool_ *manwe_avatar(); +char *manwe_avatar_info(); +bool_ *manwe_blessing(); +char *manwe_blessing_info(); +bool_ *manwe_call(); +char *manwe_call_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index 458fdc49..0d9d5613 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2622,3 +2622,17 @@ bool_ *mana_elemental_shield(); char *mana_elemental_shield_info(); bool_ *mana_disruption_shield(); char *mana_disruption_shield_info(); + +extern s32b MANWE_SHIELD; +extern s32b MANWE_AVATAR; +extern s32b MANWE_BLESS; +extern s32b MANWE_CALL; + +bool_ *manwe_wind_shield(); +char *manwe_wind_shield_info(); +bool_ *manwe_avatar(); +char *manwe_avatar_info(); +bool_ *manwe_blessing(); +char *manwe_blessing_info(); +bool_ *manwe_call(); +char *manwe_call_info(); diff --git a/src/spells3.c b/src/spells3.c index d9b36410..db183ee0 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -1,5 +1,7 @@ #include "angband.h" +#include + s32b NOXIOUSCLOUD = -1; /* Identifier */ s32b AIRWINGS = -1; /* Identifier */ s32b INVISIBILITY; @@ -62,6 +64,11 @@ s32b DELCURSES; s32b RESISTS; s32b MANASHIELD; +s32b MANWE_SHIELD; +s32b MANWE_AVATAR; +s32b MANWE_BLESS; +s32b MANWE_CALL; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua cares about). */ @@ -1823,3 +1830,134 @@ char *mana_disruption_shield_info() return buf; } +bool_ *manwe_wind_shield() +{ + s32b dur = get_level_s(MANWE_SHIELD, 50) + 10 + randint(20); + + set_protevil(dur); + if (get_level_s(MANWE_SHIELD, 50) >= 10) + { + int type = 0; + if (get_level_s(MANWE_SHIELD, 50) >= 20) + { + type = SHIELD_COUNTER; + } + + set_shield(dur, + get_level_s(MANWE_SHIELD, 30), + type, + 1 + get_level_s(MANWE_SHIELD, 2), + 1 + get_level_s(MANWE_SHIELD, 6)); + } + + return CAST; +} + +char *manwe_wind_shield_info() +{ + static char buf[128]; + + sprintf(buf, + "dur %d+d20", + (get_level_s(MANWE_SHIELD, 50) + 10)); + + if (get_level_s(MANWE_SHIELD, 50) >= 10) + { + char tmp[128]; + sprintf(tmp, " AC %d", get_level_s(MANWE_SHIELD, 30)); + strcat(buf, tmp); + } + + if (get_level_s(MANWE_SHIELD, 50) >= 20) + { + char tmp[128]; + sprintf(tmp, " dam %dd%d", + (1 + get_level_s(MANWE_SHIELD, 2)), + (1 + get_level_s(MANWE_SHIELD, 6))); + strcat(buf, tmp); + } + + return buf; +} + +bool_ *manwe_avatar() +{ + s16b mimic_idx = resolve_mimic_name("Maia"); + assert(mimic_idx >= 0); + + set_mimic(get_level_s(MANWE_AVATAR, 20) + randint(10), + mimic_idx, + p_ptr->lev); + return CAST; +} + +char *manwe_avatar_info() +{ + static char buf[128]; + sprintf(buf, + "dur %d+d10", + get_level_s(MANWE_AVATAR, 20)); + return buf; +} + +bool_ *manwe_blessing() +{ + s32b dur = get_level_s(MANWE_BLESS, 70) + 30 + randint(40); + + set_blessed(dur); + set_afraid(0); + set_lite(0); + + if (get_level_s(MANWE_BLESS, 50) >= 10) + { + set_hero(dur); + } + if (get_level_s(MANWE_BLESS, 50) >= 20) + { + set_shero(dur); + } + if (get_level_s(MANWE_BLESS, 50) >= 30) + { + set_holy(dur); + } + + return CAST; +} + +char *manwe_blessing_info() +{ + static char buf[128]; + sprintf(buf, + "dur %d+d40", + get_level_s(MANWE_BLESS, 70) + 30); + return buf; +} + +bool_ *manwe_call() +{ + int y = 0, x = 0, m_idx = -1, r_idx = -1; + + find_position(p_ptr->py, p_ptr->px, &y, &x); + + r_idx = test_monster_name("Great eagle"); + assert(r_idx >= 1); + + m_idx = place_monster_one(y, x, r_idx, 0, FALSE, MSTATUS_FRIEND); + + if (m_idx > 0) + { + monster_set_level(m_idx, 20 + get_level(MANWE_CALL, 70, 0)); + return CAST; + } + + return NO_CAST; +} + +char *manwe_call_info() +{ + static char buf[128]; + sprintf(buf, + "level %d", + get_level_s(MANWE_CALL, 70) + 20); + return buf; +} -- cgit v1.2.3 From c242c2266a98b95e044834128052bad187186ef0 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 20 Apr 2012 05:13:20 +0200 Subject: Lua: Move "Melkor" spell functions to C --- lib/mods/theme/scpt/s_melkor.lua | 54 +++----------------- lib/scpt/s_melkor.lua | 54 +++----------------- src/cmd1.c | 2 +- src/externs.h | 13 +++++ src/spells.pkg | 11 +++++ src/spells3.c | 103 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 140 insertions(+), 97 deletions(-) diff --git a/lib/mods/theme/scpt/s_melkor.lua b/lib/mods/theme/scpt/s_melkor.lua index b2c693dd..888a5066 100644 --- a/lib/mods/theme/scpt/s_melkor.lua +++ b/lib/mods/theme/scpt/s_melkor.lua @@ -60,20 +60,8 @@ MELKOR_CURSE = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - if target_who == -1 then - msg_print("You must target a monster.") - else - do_melkor_curse(target_who) - end - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return melkor_curse() end, + ["info"] = function() return melkor_curse_info() end, ["desc"] = { "It curses a monster, reducing its melee power", "At level 5 it can be auto-casted (with no piety cost) while fighting", @@ -95,12 +83,8 @@ MELKOR_CORPSE_EXPLOSION = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - return fire_ball(GF_CORPSE_EXPL, 0, 20 + get_level(MELKOR_CORPSE_EXPLOSION, 70), 2 + get_level(MELKOR_CORPSE_EXPLOSION, 5)) - end, - ["info"] = function() - return "dam "..(20 + get_level(MELKOR_CORPSE_EXPLOSION, 70)).."%" - end, + ["spell"] = function() return melkor_corpse_explosion() end, + ["info"] = function() return melkor_corpse_explosion_info() end, ["desc"] = { "It makes corpses in an area around you explode for a percent of their", "hit points as damage", @@ -119,34 +103,8 @@ MELKOR_MIND_STEAL = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - if target_who == -1 then - msg_print("You must target a monster.") - else - local chance, m_ptr, r_ptr - - m_ptr = monster(target_who) - r_ptr = race_info_idx(m_ptr.r_idx, m_ptr.ego) - chance = get_level(MELKOR_MIND_STEAL) - if (randint(m_ptr.level) < chance) and (band(r_ptr.flags1, RF1_UNIQUE) == 0) then - player.control = target_who - m_ptr.mflag = bor(m_ptr.mflag, MFLAG_CONTROL) - - local m_name = monster_desc(m_ptr, 0).." falls under your control." - msg_print(strupper(strsub(m_name, 0, 1))..strsub(m_name, 2)) - else - local m_name = monster_desc(m_ptr, 0).." resists." - msg_print(strupper(strsub(m_name, 0, 1))..strsub(m_name, 2)) - end - return TRUE - end - end, - ["info"] = function() - return "chance 1d(mlvl)<"..(get_level(MELKOR_MIND_STEAL)) - end, + ["spell"] = function() return melkor_mind_steal() end, + ["info"] = function() return melkor_mind_steal_info() end, ["desc"] = { "It allows your spirit to temporarily leave your own body, which will", "be vulnerable, to control one of your enemies body." diff --git a/lib/scpt/s_melkor.lua b/lib/scpt/s_melkor.lua index b2c693dd..888a5066 100644 --- a/lib/scpt/s_melkor.lua +++ b/lib/scpt/s_melkor.lua @@ -60,20 +60,8 @@ MELKOR_CURSE = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - if target_who == -1 then - msg_print("You must target a monster.") - else - do_melkor_curse(target_who) - end - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return melkor_curse() end, + ["info"] = function() return melkor_curse_info() end, ["desc"] = { "It curses a monster, reducing its melee power", "At level 5 it can be auto-casted (with no piety cost) while fighting", @@ -95,12 +83,8 @@ MELKOR_CORPSE_EXPLOSION = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - return fire_ball(GF_CORPSE_EXPL, 0, 20 + get_level(MELKOR_CORPSE_EXPLOSION, 70), 2 + get_level(MELKOR_CORPSE_EXPLOSION, 5)) - end, - ["info"] = function() - return "dam "..(20 + get_level(MELKOR_CORPSE_EXPLOSION, 70)).."%" - end, + ["spell"] = function() return melkor_corpse_explosion() end, + ["info"] = function() return melkor_corpse_explosion_info() end, ["desc"] = { "It makes corpses in an area around you explode for a percent of their", "hit points as damage", @@ -119,34 +103,8 @@ MELKOR_MIND_STEAL = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - if target_who == -1 then - msg_print("You must target a monster.") - else - local chance, m_ptr, r_ptr - - m_ptr = monster(target_who) - r_ptr = race_info_idx(m_ptr.r_idx, m_ptr.ego) - chance = get_level(MELKOR_MIND_STEAL) - if (randint(m_ptr.level) < chance) and (band(r_ptr.flags1, RF1_UNIQUE) == 0) then - player.control = target_who - m_ptr.mflag = bor(m_ptr.mflag, MFLAG_CONTROL) - - local m_name = monster_desc(m_ptr, 0).." falls under your control." - msg_print(strupper(strsub(m_name, 0, 1))..strsub(m_name, 2)) - else - local m_name = monster_desc(m_ptr, 0).." resists." - msg_print(strupper(strsub(m_name, 0, 1))..strsub(m_name, 2)) - end - return TRUE - end - end, - ["info"] = function() - return "chance 1d(mlvl)<"..(get_level(MELKOR_MIND_STEAL)) - end, + ["spell"] = function() return melkor_mind_steal() end, + ["info"] = function() return melkor_mind_steal_info() end, ["desc"] = { "It allows your spirit to temporarily leave your own body, which will", "be vulnerable, to control one of your enemies body." diff --git a/src/cmd1.c b/src/cmd1.c index 1184df0c..ffeb6d2e 100644 --- a/src/cmd1.c +++ b/src/cmd1.c @@ -2475,7 +2475,7 @@ void py_attack(int y, int x, int max_blow) if (chance < 1) chance = 1; if ((p_ptr->grace > 5000) && magik(chance)) { - exec_lua(format("do_melkor_curse(%d)", c_ptr->m_idx)); + do_melkor_curse(c_ptr->m_idx); } } } diff --git a/src/externs.h b/src/externs.h index e46e864f..ac2aef20 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1592,6 +1592,19 @@ char *manwe_blessing_info(); bool_ *manwe_call(); char *manwe_call_info(); +extern s32b MELKOR_CURSE; +extern s32b MELKOR_CORPSE_EXPLOSION; +extern s32b MELKOR_MIND_STEAL; + +void do_melkor_curse(int m_idx); + +bool_ *melkor_curse(); +char *melkor_curse_info(); +bool_ *melkor_corpse_explosion(); +char *melkor_corpse_explosion_info(); +bool_ *melkor_mind_steal(); +char *melkor_mind_steal_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index 0d9d5613..5df1ef10 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2636,3 +2636,14 @@ bool_ *manwe_blessing(); char *manwe_blessing_info(); bool_ *manwe_call(); char *manwe_call_info(); + +extern s32b MELKOR_CURSE; +extern s32b MELKOR_CORPSE_EXPLOSION; +extern s32b MELKOR_MIND_STEAL; + +bool_ *melkor_curse(); +char *melkor_curse_info(); +bool_ *melkor_corpse_explosion(); +char *melkor_corpse_explosion_info(); +bool_ *melkor_mind_steal(); +char *melkor_mind_steal_info(); diff --git a/src/spells3.c b/src/spells3.c index db183ee0..5fa198fb 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -69,6 +69,10 @@ s32b MANWE_AVATAR; s32b MANWE_BLESS; s32b MANWE_CALL; +s32b MELKOR_CURSE; +s32b MELKOR_CORPSE_EXPLOSION; +s32b MELKOR_MIND_STEAL; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua cares about). */ @@ -1961,3 +1965,102 @@ char *manwe_call_info() get_level_s(MANWE_CALL, 70) + 20); return buf; } + +void do_melkor_curse(int m_idx) +{ + exec_lua(format("do_melkor_curse(%d)", m_idx)); +} + +bool_ *melkor_curse() +{ + int dir = 0; + + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + if (target_who < 0) + { + msg_print("You must target a monster."); + return NO_CAST; + } + else + { + do_melkor_curse(target_who); + return CAST; + } +} + +char *melkor_curse_info() +{ + return ""; +} + +bool_ *melkor_corpse_explosion() +{ + fire_ball(GF_CORPSE_EXPL, + 0, + 20 + get_level_s(MELKOR_CORPSE_EXPLOSION, 70), + 2 + get_level_s(MELKOR_CORPSE_EXPLOSION, 5)); + return CAST; +} + +char *melkor_corpse_explosion_info() +{ + static char buf[128]; + sprintf(buf, + "dam %d%%", + 20 + get_level_s(MELKOR_CORPSE_EXPLOSION, 70)); + return buf; +} + +bool_ *melkor_mind_steal() +{ + int dir = 0; + + if (!get_aim_dir(&dir)) + { + return FALSE; + } + + if (target_who < 0) + { + msg_print("You must target a monster."); + return NO_CAST; + } + else + { + monster_type *m_ptr = &m_list[target_who]; + int chance = get_level_s(MELKOR_MIND_STEAL, 50); + monster_race *r_ptr = race_info_idx(m_ptr->r_idx, m_ptr->ego); + char buf[128]; + + monster_desc(buf, m_ptr, 0); + buf[0] = toupper(buf[0]); + + if ((randint(m_ptr->level) < chance) && + ((r_ptr->flags1 & RF1_UNIQUE) == 0)) + { + p_ptr->control = target_who; + m_ptr->mflag |= MFLAG_CONTROL; + strcat(buf, " falls under your control."); + } + else + { + strcat(buf, " resists."); + } + + msg_print(buf); + return CAST; + } +} + +char *melkor_mind_steal_info() +{ + static char buf[128]; + sprintf(buf, + "chance 1d(mlvl)<%d", + get_level_s(MELKOR_MIND_STEAL, 50)); + return buf; +} -- cgit v1.2.3 From 4275c9d3e7a44080997fce9974d442ba4f9f4a54 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 20 Apr 2012 06:20:01 +0200 Subject: Lua: Move "do_melkor_curse" to C --- lib/mods/theme/scpt/s_melkor.lua | 48 ---------------------- lib/scpt/s_melkor.lua | 48 ---------------------- src/spells3.c | 87 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 86 insertions(+), 97 deletions(-) diff --git a/lib/mods/theme/scpt/s_melkor.lua b/lib/mods/theme/scpt/s_melkor.lua index 888a5066..701dca7a 100644 --- a/lib/mods/theme/scpt/s_melkor.lua +++ b/lib/mods/theme/scpt/s_melkor.lua @@ -1,53 +1,5 @@ -- handle the melkor school --- Not included in the spell code directly because I need to call it from somewhere else too -function do_melkor_curse(who) - local m_ptr = monster(who) - - if get_level(MELKOR_CURSE) >= 35 then - local r_ptr = race_info_idx(m_ptr.r_idx, m_ptr.ego) - - m_ptr.maxhp = m_ptr.maxhp - r_ptr.hside; - if m_ptr.maxhp < 1 then m_ptr.maxhp = 1 end - if m_ptr.hp > m_ptr.maxhp then m_ptr.hp = m_ptr.maxhp end - player.redraw = bor(player.redraw, PR_HEALTH) - end - if get_level(MELKOR_CURSE) >= 25 then - m_ptr.speed = m_ptr.speed - get_level(MELKOR_CURSE, 7) - m_ptr.mspeed = m_ptr.mspeed - get_level(MELKOR_CURSE, 7) - - if m_ptr.speed < 70 then m_ptr.speed = 70 end - if m_ptr.mspeed < 70 then m_ptr.mspeed = 70 end - end - if get_level(MELKOR_CURSE) >= 15 then - m_ptr.ac = m_ptr.ac - get_level(MELKOR_CURSE, 50) - - if m_ptr.ac < -70 then m_ptr.ac = -70 end - end - - local i, pow - i = 1 - pow = get_level(MELKOR_CURSE, 2) - while (i <= 4) do - if m_ptr.blow[i].d_dice > 0 then - if m_ptr.blow[i].d_dice < pow then - pow = m_ptr.blow[i].d_dice - end - if m_ptr.blow[i].d_side < pow then - pow = m_ptr.blow[i].d_side - end - m_ptr.blow[i].d_dice = m_ptr.blow[i].d_dice - pow - end - i = i + 1 - end - - local m_name = monster_desc(m_ptr, 0).." looks weaker." - msg_print(strupper(strsub(m_name, 0, 1))..strsub(m_name, 2)) - - -- wake it - m_ptr.csleep = 0; -end - MELKOR_CURSE = add_spell { ["name"] = "Curse", diff --git a/lib/scpt/s_melkor.lua b/lib/scpt/s_melkor.lua index 888a5066..701dca7a 100644 --- a/lib/scpt/s_melkor.lua +++ b/lib/scpt/s_melkor.lua @@ -1,53 +1,5 @@ -- handle the melkor school --- Not included in the spell code directly because I need to call it from somewhere else too -function do_melkor_curse(who) - local m_ptr = monster(who) - - if get_level(MELKOR_CURSE) >= 35 then - local r_ptr = race_info_idx(m_ptr.r_idx, m_ptr.ego) - - m_ptr.maxhp = m_ptr.maxhp - r_ptr.hside; - if m_ptr.maxhp < 1 then m_ptr.maxhp = 1 end - if m_ptr.hp > m_ptr.maxhp then m_ptr.hp = m_ptr.maxhp end - player.redraw = bor(player.redraw, PR_HEALTH) - end - if get_level(MELKOR_CURSE) >= 25 then - m_ptr.speed = m_ptr.speed - get_level(MELKOR_CURSE, 7) - m_ptr.mspeed = m_ptr.mspeed - get_level(MELKOR_CURSE, 7) - - if m_ptr.speed < 70 then m_ptr.speed = 70 end - if m_ptr.mspeed < 70 then m_ptr.mspeed = 70 end - end - if get_level(MELKOR_CURSE) >= 15 then - m_ptr.ac = m_ptr.ac - get_level(MELKOR_CURSE, 50) - - if m_ptr.ac < -70 then m_ptr.ac = -70 end - end - - local i, pow - i = 1 - pow = get_level(MELKOR_CURSE, 2) - while (i <= 4) do - if m_ptr.blow[i].d_dice > 0 then - if m_ptr.blow[i].d_dice < pow then - pow = m_ptr.blow[i].d_dice - end - if m_ptr.blow[i].d_side < pow then - pow = m_ptr.blow[i].d_side - end - m_ptr.blow[i].d_dice = m_ptr.blow[i].d_dice - pow - end - i = i + 1 - end - - local m_name = monster_desc(m_ptr, 0).." looks weaker." - msg_print(strupper(strsub(m_name, 0, 1))..strsub(m_name, 2)) - - -- wake it - m_ptr.csleep = 0; -end - MELKOR_CURSE = add_spell { ["name"] = "Curse", diff --git a/src/spells3.c b/src/spells3.c index 5fa198fb..7fff9935 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -1968,7 +1968,92 @@ char *manwe_call_info() void do_melkor_curse(int m_idx) { - exec_lua(format("do_melkor_curse(%d)", m_idx)); + monster_type *m_ptr = NULL; + assert(m_idx >= 0); + + m_ptr = &m_list[m_idx]; + + if (get_level_s(MELKOR_CURSE, 50) >= 35) + { + monster_race *r_ptr = race_info_idx(m_ptr->r_idx, m_ptr->ego); + + m_ptr->maxhp = m_ptr->maxhp - r_ptr->hside; + if (m_ptr->maxhp < 1) + { + m_ptr->maxhp = 1; + } + if (m_ptr->hp > m_ptr->maxhp) + { + m_ptr->hp = m_ptr->maxhp; + } + + p_ptr->redraw |= PR_HEALTH; + } + + if (get_level_s(MELKOR_CURSE, 50) >= 25) + { + m_ptr->speed = m_ptr->speed - get_level_s(MELKOR_CURSE, 7); + m_ptr->mspeed = m_ptr->mspeed - get_level_s(MELKOR_CURSE, 7); + + if (m_ptr->speed < 70) + { + m_ptr->speed = 70; + } + + if (m_ptr->mspeed < 70) + { + m_ptr->mspeed = 70; + } + } + + if (get_level_s(MELKOR_CURSE, 50) >= 15) + { + m_ptr->ac = m_ptr->ac - get_level_s(MELKOR_CURSE, 50); + + if (m_ptr->ac < -70) + { + m_ptr->ac = -70; + } + } + + /* Reduce melee too */ + { + int i; + int pow = get_level_s(MELKOR_CURSE, 2); + + for (i = 0; i < 4; i++) + { + if (m_ptr->blow[i].d_dice <= 0) + { + break; + } + + if (m_ptr->blow[i].d_dice < pow) + { + pow = m_ptr->blow[i].d_dice; + } + if (m_ptr->blow[i].d_side < pow) + { + pow = m_ptr->blow[i].d_side; + } + + m_ptr->blow[i].d_dice = m_ptr->blow[i].d_dice - pow; + } + } + + /* Describe what happened */ + { + char buf[128]; + + monster_desc(buf, m_ptr, 0); + buf[0] = toupper(buf[0]); + + strcat(buf, " looks weaker."); + msg_print(buf); + } + + /* wake it */ + m_ptr->csleep = 0; } bool_ *melkor_curse() -- cgit v1.2.3 From 6ef98743b002c48fb3bf720fb07936e34926b313 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 8 May 2012 18:59:59 +0200 Subject: Lua: Move "Meta" spell functions to C --- lib/core/util.lua | 7 - lib/mods/theme/core/util.lua | 7 - lib/mods/theme/scpt/s_meta.lua | 203 ++------------------------- lib/scpt/s_meta.lua | 203 ++------------------------- src/birth.c | 4 + src/dungeon.c | 9 +- src/externs.h | 24 ++++ src/init2.c | 5 + src/loadsave.c | 32 +++++ src/lua_bind.c | 2 +- src/player.pkg | 16 --- src/spells.pkg | 49 +++---- src/spells3.c | 310 +++++++++++++++++++++++++++++++++++++++++ src/types.h | 6 +- src/util.c | 19 ++- src/xtra1.c | 2 + 16 files changed, 445 insertions(+), 453 deletions(-) diff --git a/lib/core/util.lua b/lib/core/util.lua index eea13014..048b0d0f 100644 --- a/lib/core/util.lua +++ b/lib/core/util.lua @@ -93,13 +93,6 @@ function new_timer(t) return timer end --- saves all timer values -function save_timer(name) - add_loadsave(name..".enabled", FALSE) - add_loadsave(name..".delay", 1) - add_loadsave(name..".countdown", 1) -end - -- displays a scrolling list function display_list(y, x, h, w, title, list, begin, sel, sel_color) diff --git a/lib/mods/theme/core/util.lua b/lib/mods/theme/core/util.lua index eea13014..048b0d0f 100644 --- a/lib/mods/theme/core/util.lua +++ b/lib/mods/theme/core/util.lua @@ -93,13 +93,6 @@ function new_timer(t) return timer end --- saves all timer values -function save_timer(name) - add_loadsave(name..".enabled", FALSE) - add_loadsave(name..".delay", 1) - add_loadsave(name..".countdown", 1) -end - -- displays a scrolling list function display_list(y, x, h, w, title, list, begin, sel, sel_color) diff --git a/lib/mods/theme/scpt/s_meta.lua b/lib/mods/theme/scpt/s_meta.lua index eab691d8..9040e3af 100644 --- a/lib/mods/theme/scpt/s_meta.lua +++ b/lib/mods/theme/scpt/s_meta.lua @@ -8,25 +8,13 @@ RECHARGE = add_spell ["mana"] = 10, ["mana_max"] = 100, ["fail"] = 20, - ["spell"] = function() - return recharge(60 + get_level(RECHARGE, 140)) - end, - ["info"] = function() - return "power "..(60 + get_level(RECHARGE, 140)) - end, + ["spell"] = function() return meta_recharge() end, + ["info"] = function() return meta_recharge_info() end, ["desc"] = { "Taps on the ambient mana to recharge an object's power (charges or mana)", } } -function get_spellbinder_max() - local i - - i = get_level(SPELLBINDER, 4) - if i > 4 then i = 4 end - return i -end ---' SPELLBINDER = add_spell { ["name"] = "Spellbinder", @@ -35,63 +23,8 @@ SPELLBINDER = add_spell ["mana"] = 100, ["mana_max"] = 300, ["fail"] = 85, - ["spell"] = function() - local i, ret, c - - if player.spellbinder_num ~= 0 then - local t = - { - [SPELLBINDER_HP75] = "75% HP", - [SPELLBINDER_HP50] = "50% HP", - [SPELLBINDER_HP25] = "25% HP", - } - msg_print("The spellbinder is already active.") - msg_print("It will trigger at "..t[player.spellbinder_trigger]..".") - msg_print("With the spells: ") - for i = 1, player.spellbinder_num do - msg_print(spell(player.spellbinder[i]).name) - end - return TRUE - end - - ret, c = get_com("Trigger at [a]75% hp [b]50% hp [c]25% hp?", strbyte("a")) - if ret == FALSE then return TRUE end - - if c == strbyte("a") then - player.spellbinder_trigger = SPELLBINDER_HP75 - elseif c == strbyte("b") then - player.spellbinder_trigger = SPELLBINDER_HP50 - elseif c == strbyte("c") then - player.spellbinder_trigger = SPELLBINDER_HP25 - else - return - end - player.spellbinder_num = get_spellbinder_max() - i = player.spellbinder_num - while i > 0 do - local s - - s = get_school_spell("bind", "is_ok_spell", 0) - if s == -1 then - player.spellbinder_trigger = 0 - player.spellbinder_num = 0 - return TRUE - else - if spell(s).skill_level > 7 + get_level(SPELLBINDER, 35) then - msg_print("You are only allowed spells with a base level of "..(7 + get_level(SPELLBINDER, 35)).."."); - return TRUE - end - end - player.spellbinder[i] = s - i = i - 1 - end - player.energy = player.energy - 3100; - msg_print("Spellbinder ready.") - return TRUE - end, - ["info"] = function() - return "number "..(get_spellbinder_max()).." max level "..(7 + get_level(SPELLBINDER, 35)) - end, + ["spell"] = function() return meta_spellbinder() end, + ["info"] = function() return meta_spellbinder_info() end, ["desc"] = { "Stores spells in a trigger.", "When the condition is met all spells fire off at the same time", @@ -125,38 +58,8 @@ DISPERSEMAGIC = add_spell }, }, ["inertia"] = { 1, 5 }, - ["spell"] = function() - local obvious - obvious = set_blind(0) - obvious = is_obvious(set_lite(0), obvious) - if get_level(DISPERSEMAGIC, 50) >= 5 then - obvious = is_obvious(set_confused(0), obvious) - obvious = is_obvious(set_image(0), obvious) - end - if get_level(DISPERSEMAGIC, 50) >= 10 then - obvious = is_obvious(set_slow(0), obvious) - obvious = is_obvious(set_fast(0, 0), obvious) - obvious = is_obvious(set_light_speed(0), obvious) - end - if get_level(DISPERSEMAGIC, 50) >= 15 then - obvious = is_obvious(set_stun(0), obvious) - obvious = is_obvious(set_meditation(0), obvious) - obvious = is_obvious(set_cut(0), obvious) - end - if get_level(DISPERSEMAGIC, 50) >= 20 then - obvious = is_obvious(set_hero(0), obvious) - obvious = is_obvious(set_shero(0), obvious) - obvious = is_obvious(set_blessed(0), obvious) - obvious = is_obvious(set_shield(0, 0, 0, 0, 0), obvious) - obvious = is_obvious(set_afraid(0), obvious) - obvious = is_obvious(set_parasite(0, 0), obvious) - obvious = is_obvious(set_mimic(0, 0, 0), obvious) - end - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return meta_disperse_magic() end, + ["info"] = function() return meta_disperse_magic_info() end, ["desc"] = { "Dispels a lot of magic that can affect you, be it good or bad", "Level 1: blindness and light", @@ -175,69 +78,14 @@ TRACKER = add_spell ["mana"] = 50, ["mana_max"] = 50, ["fail"] = 95, - ["spell"] = function() - if last_teleportation_y == -1 then - msg_print("There has not been any teleporatation here.") - return TRUE - end - teleport_player_to(last_teleportation_y, last_teleportation_x) - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return meta_tracker() end, + ["info"] = function() return meta_tracker_info() end, ["desc"] = { "Tracks down the last teleportation that happened on the level and teleports", "you to it", } } --- Saves the values of the timer -save_timer("TIMER_INERTIA_CONTROL") -add_loadsave("player.inertia_controlled_spell", -1) -player.inertia_controlled_spell = -1 - --- Automatically cast the inertia controlled spells -TIMER_INERTIA_CONTROL = new_timer -{ - ["enabled"] = FALSE, - ["delay"] = 10, - ["callback"] = function() - -- Don't cast a controlled spell in wilderness mode - if player.antimagic then - msg_print("Your anti-magic field disrupts any magic attempts.") - elseif player.anti_magic then - msg_print("Your anti-magic shell disrupts any magic attempts.") - elseif (player.inertia_controlled_spell ~= -1) and (player.wild_mode == FALSE) then - __spell_spell[player.inertia_controlled_spell]() - end - end, -} - -stop_inertia_controlled_spell = function() - player.inertia_controlled_spell = -1 - TIMER_INERTIA_CONTROL.enabled = FALSE - player.update = bor(player.update, PU_MANA) - return TRUE -end - -add_hooks -{ - -- Reduce the mana by four times the cost of the spell - [HOOK_CALC_MANA] = function(msp) - if player.inertia_controlled_spell ~= -1 then - msp = msp - (get_mana(player.inertia_controlled_spell) * 4) - if msp < 0 then msp = 0 end - return TRUE, msp - end - end, - - -- Stop a previous spell at birth - [HOOK_BIRTH_OBJECTS] = function() - stop_inertia_controlled_spell() - end, -} - INERTIA_CONTROL = add_spell { ["name"] = "Inertia Control", @@ -246,39 +94,8 @@ INERTIA_CONTROL = add_spell ["mana"] = 300, ["mana_max"] = 700, ["fail"] = 95, - ["spell"] = function() - if player.inertia_controlled_spell ~= -1 then - msg_print("You cancel your inertia flow control.") - return stop_inertia_controlled_spell() - end - - local s = get_school_spell("control", "is_ok_spell", 0) - if s == -1 then - return stop_inertia_controlled_spell() - end - - local inertia = __tmp_spells[s].inertia - - if inertia == nil then - msg_print("This spell inertia flow can not be controlled.") - return stop_inertia_controlled_spell() - end - if inertia[1] > get_level(INERTIA_CONTROL, 10) then - msg_print("This spell inertia flow("..inertia[1]..") is too strong to be controlled by your current spell.") - return stop_inertia_controlled_spell() - end - - player.inertia_controlled_spell = s - TIMER_INERTIA_CONTROL.enabled = TRUE - TIMER_INERTIA_CONTROL.delay = inertia[2] - TIMER_INERTIA_CONTROL.countdown = TIMER_INERTIA_CONTROL.delay - player.update = bor(player.update, PU_MANA) - msg_print("Inertia flow controlling spell "..spell(s).name..".") - return TRUE - end, - ["info"] = function() - return "level "..get_level(INERTIA_CONTROL, 10) - end, + ["spell"] = function() return meta_inertia_control() end, + ["info"] = function() return meta_inertia_control_info() end, ["desc"] = { "Changes the energy flow of a spell to be continuously recasted", "at a given interval. The inertia controlled spell reduces your", diff --git a/lib/scpt/s_meta.lua b/lib/scpt/s_meta.lua index eab691d8..9040e3af 100644 --- a/lib/scpt/s_meta.lua +++ b/lib/scpt/s_meta.lua @@ -8,25 +8,13 @@ RECHARGE = add_spell ["mana"] = 10, ["mana_max"] = 100, ["fail"] = 20, - ["spell"] = function() - return recharge(60 + get_level(RECHARGE, 140)) - end, - ["info"] = function() - return "power "..(60 + get_level(RECHARGE, 140)) - end, + ["spell"] = function() return meta_recharge() end, + ["info"] = function() return meta_recharge_info() end, ["desc"] = { "Taps on the ambient mana to recharge an object's power (charges or mana)", } } -function get_spellbinder_max() - local i - - i = get_level(SPELLBINDER, 4) - if i > 4 then i = 4 end - return i -end ---' SPELLBINDER = add_spell { ["name"] = "Spellbinder", @@ -35,63 +23,8 @@ SPELLBINDER = add_spell ["mana"] = 100, ["mana_max"] = 300, ["fail"] = 85, - ["spell"] = function() - local i, ret, c - - if player.spellbinder_num ~= 0 then - local t = - { - [SPELLBINDER_HP75] = "75% HP", - [SPELLBINDER_HP50] = "50% HP", - [SPELLBINDER_HP25] = "25% HP", - } - msg_print("The spellbinder is already active.") - msg_print("It will trigger at "..t[player.spellbinder_trigger]..".") - msg_print("With the spells: ") - for i = 1, player.spellbinder_num do - msg_print(spell(player.spellbinder[i]).name) - end - return TRUE - end - - ret, c = get_com("Trigger at [a]75% hp [b]50% hp [c]25% hp?", strbyte("a")) - if ret == FALSE then return TRUE end - - if c == strbyte("a") then - player.spellbinder_trigger = SPELLBINDER_HP75 - elseif c == strbyte("b") then - player.spellbinder_trigger = SPELLBINDER_HP50 - elseif c == strbyte("c") then - player.spellbinder_trigger = SPELLBINDER_HP25 - else - return - end - player.spellbinder_num = get_spellbinder_max() - i = player.spellbinder_num - while i > 0 do - local s - - s = get_school_spell("bind", "is_ok_spell", 0) - if s == -1 then - player.spellbinder_trigger = 0 - player.spellbinder_num = 0 - return TRUE - else - if spell(s).skill_level > 7 + get_level(SPELLBINDER, 35) then - msg_print("You are only allowed spells with a base level of "..(7 + get_level(SPELLBINDER, 35)).."."); - return TRUE - end - end - player.spellbinder[i] = s - i = i - 1 - end - player.energy = player.energy - 3100; - msg_print("Spellbinder ready.") - return TRUE - end, - ["info"] = function() - return "number "..(get_spellbinder_max()).." max level "..(7 + get_level(SPELLBINDER, 35)) - end, + ["spell"] = function() return meta_spellbinder() end, + ["info"] = function() return meta_spellbinder_info() end, ["desc"] = { "Stores spells in a trigger.", "When the condition is met all spells fire off at the same time", @@ -125,38 +58,8 @@ DISPERSEMAGIC = add_spell }, }, ["inertia"] = { 1, 5 }, - ["spell"] = function() - local obvious - obvious = set_blind(0) - obvious = is_obvious(set_lite(0), obvious) - if get_level(DISPERSEMAGIC, 50) >= 5 then - obvious = is_obvious(set_confused(0), obvious) - obvious = is_obvious(set_image(0), obvious) - end - if get_level(DISPERSEMAGIC, 50) >= 10 then - obvious = is_obvious(set_slow(0), obvious) - obvious = is_obvious(set_fast(0, 0), obvious) - obvious = is_obvious(set_light_speed(0), obvious) - end - if get_level(DISPERSEMAGIC, 50) >= 15 then - obvious = is_obvious(set_stun(0), obvious) - obvious = is_obvious(set_meditation(0), obvious) - obvious = is_obvious(set_cut(0), obvious) - end - if get_level(DISPERSEMAGIC, 50) >= 20 then - obvious = is_obvious(set_hero(0), obvious) - obvious = is_obvious(set_shero(0), obvious) - obvious = is_obvious(set_blessed(0), obvious) - obvious = is_obvious(set_shield(0, 0, 0, 0, 0), obvious) - obvious = is_obvious(set_afraid(0), obvious) - obvious = is_obvious(set_parasite(0, 0), obvious) - obvious = is_obvious(set_mimic(0, 0, 0), obvious) - end - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return meta_disperse_magic() end, + ["info"] = function() return meta_disperse_magic_info() end, ["desc"] = { "Dispels a lot of magic that can affect you, be it good or bad", "Level 1: blindness and light", @@ -175,69 +78,14 @@ TRACKER = add_spell ["mana"] = 50, ["mana_max"] = 50, ["fail"] = 95, - ["spell"] = function() - if last_teleportation_y == -1 then - msg_print("There has not been any teleporatation here.") - return TRUE - end - teleport_player_to(last_teleportation_y, last_teleportation_x) - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return meta_tracker() end, + ["info"] = function() return meta_tracker_info() end, ["desc"] = { "Tracks down the last teleportation that happened on the level and teleports", "you to it", } } --- Saves the values of the timer -save_timer("TIMER_INERTIA_CONTROL") -add_loadsave("player.inertia_controlled_spell", -1) -player.inertia_controlled_spell = -1 - --- Automatically cast the inertia controlled spells -TIMER_INERTIA_CONTROL = new_timer -{ - ["enabled"] = FALSE, - ["delay"] = 10, - ["callback"] = function() - -- Don't cast a controlled spell in wilderness mode - if player.antimagic then - msg_print("Your anti-magic field disrupts any magic attempts.") - elseif player.anti_magic then - msg_print("Your anti-magic shell disrupts any magic attempts.") - elseif (player.inertia_controlled_spell ~= -1) and (player.wild_mode == FALSE) then - __spell_spell[player.inertia_controlled_spell]() - end - end, -} - -stop_inertia_controlled_spell = function() - player.inertia_controlled_spell = -1 - TIMER_INERTIA_CONTROL.enabled = FALSE - player.update = bor(player.update, PU_MANA) - return TRUE -end - -add_hooks -{ - -- Reduce the mana by four times the cost of the spell - [HOOK_CALC_MANA] = function(msp) - if player.inertia_controlled_spell ~= -1 then - msp = msp - (get_mana(player.inertia_controlled_spell) * 4) - if msp < 0 then msp = 0 end - return TRUE, msp - end - end, - - -- Stop a previous spell at birth - [HOOK_BIRTH_OBJECTS] = function() - stop_inertia_controlled_spell() - end, -} - INERTIA_CONTROL = add_spell { ["name"] = "Inertia Control", @@ -246,39 +94,8 @@ INERTIA_CONTROL = add_spell ["mana"] = 300, ["mana_max"] = 700, ["fail"] = 95, - ["spell"] = function() - if player.inertia_controlled_spell ~= -1 then - msg_print("You cancel your inertia flow control.") - return stop_inertia_controlled_spell() - end - - local s = get_school_spell("control", "is_ok_spell", 0) - if s == -1 then - return stop_inertia_controlled_spell() - end - - local inertia = __tmp_spells[s].inertia - - if inertia == nil then - msg_print("This spell inertia flow can not be controlled.") - return stop_inertia_controlled_spell() - end - if inertia[1] > get_level(INERTIA_CONTROL, 10) then - msg_print("This spell inertia flow("..inertia[1]..") is too strong to be controlled by your current spell.") - return stop_inertia_controlled_spell() - end - - player.inertia_controlled_spell = s - TIMER_INERTIA_CONTROL.enabled = TRUE - TIMER_INERTIA_CONTROL.delay = inertia[2] - TIMER_INERTIA_CONTROL.countdown = TIMER_INERTIA_CONTROL.delay - player.update = bor(player.update, PU_MANA) - msg_print("Inertia flow controlling spell "..spell(s).name..".") - return TRUE - end, - ["info"] = function() - return "level "..get_level(INERTIA_CONTROL, 10) - end, + ["spell"] = function() return meta_inertia_control() end, + ["info"] = function() return meta_inertia_control_info() end, ["desc"] = { "Changes the energy flow of a spell to be continuously recasted", "at a given interval. The inertia controlled spell reduces your", diff --git a/src/birth.c b/src/birth.c index 274b50bf..aaef998c 100644 --- a/src/birth.c +++ b/src/birth.c @@ -1038,6 +1038,9 @@ static void player_wipe(void) /* No companions killed */ p_ptr->companion_killed = 0; + + /* Inertia control */ + p_ptr->inertia_controlled_spell = -1; } @@ -1241,6 +1244,7 @@ static void player_outfit(void) } process_hooks(HOOK_BIRTH_OBJECTS, "()"); + meta_inertia_control_hook_birth_objects(); { /* Hack -- Give the player some food */ diff --git a/src/dungeon.c b/src/dungeon.c index ec2ab0e4..fcca8a21 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -1345,7 +1345,14 @@ static void process_world(void) if (!t_ptr->countdown) { t_ptr->countdown = t_ptr->delay; - call_lua(t_ptr->callback, "()", ""); + if (t_ptr->callback_c) + { + t_ptr->callback_c(); + } + if (t_ptr->callback) + { + call_lua(t_ptr->callback, "()", ""); + } } } diff --git a/src/externs.h b/src/externs.h index ac2aef20..e89341a4 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1605,6 +1605,28 @@ char *melkor_corpse_explosion_info(); bool_ *melkor_mind_steal(); char *melkor_mind_steal_info(); +extern s32b RECHARGE; +extern s32b SPELLBINDER; +extern s32b DISPERSEMAGIC; +extern s32b TRACKER; +extern s32b INERTIA_CONTROL; +extern timer_type *TIMER_INERTIA_CONTROL; + +bool_ *meta_recharge(); +char *meta_recharge_info(); +bool_ *meta_spellbinder(); +char *meta_spellbinder_info(); +bool_ *meta_disperse_magic(); +char *meta_disperse_magic_info(); +bool_ *meta_tracker(); +char *meta_tracker_info(); +bool_ *meta_inertia_control(); +char *meta_inertia_control_info(); + +void meta_inertia_control_timer_callback(); +void meta_inertia_control_calc_mana(int *msp); +void meta_inertia_control_hook_birth_objects(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); @@ -1716,6 +1738,7 @@ extern int test_mego_name(cptr name); extern int test_item_name(cptr name); extern char msg_box(cptr text, int y, int x); extern timer_type *new_timer(cptr callback, s32b delay); +extern timer_type *new_timer_c(void (*callback)(), s32b delay); extern void del_timer(timer_type *t_ptr); extern int get_keymap_mode(); @@ -2007,6 +2030,7 @@ extern spell_type *grab_spell_type(s16b num); extern school_type *grab_school_type(s16b num); extern s32b lua_get_level(s32b s, s32b lvl, s32b max, s32b min, s32b bonus); extern s32b get_level_device(s32b s, s32b max, s32b min); +extern int get_mana(s32b s); extern s32b spell_chance(s32b s); extern s32b get_level(s32b s, s32b max, s32b min); extern s32b lua_spell_chance(s32b chance, int level, int skill_level, int mana, int cur_mana, int stat); diff --git a/src/init2.c b/src/init2.c index 71e7bc2b..38de672a 100644 --- a/src/init2.c +++ b/src/init2.c @@ -1974,6 +1974,11 @@ static errr init_misc(void) for (i = 0; i < MAX_EFFECTS; i++) effects[i].time = 0; + /* Initialize timers */ + TIMER_INERTIA_CONTROL = + new_timer_c(meta_inertia_control_timer_callback, + 10); + return 0; } diff --git a/src/loadsave.c b/src/loadsave.c index 5116acef..033aa3a0 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -575,6 +575,7 @@ static bool_ do_extra(int flag) do_s32b(&p_ptr->loan, flag); do_s32b(&p_ptr->loan_time, flag); do_s16b(&p_ptr->absorb_soul, flag); + do_s32b(&p_ptr->inertia_controlled_spell, flag); do_s16b(&p_ptr->chaos_patron, flag); @@ -1062,6 +1063,16 @@ static void do_byte(byte *v, int flag) exit(0); } +static void do_bool(bool_ *f, int flag) +{ + byte b = *f; + do_byte(&b, flag); + if (flag == LS_LOAD) + { + *f = b; + } +} + static void do_u16b(u16b *v, int flag) { if (flag == LS_LOAD) @@ -2499,6 +2510,24 @@ void do_fate(int i, int flag) do_byte((byte*)&fates[i].know, flag); } +/* + * Load/save timers. + */ +static void do_timers(int flag) +{ + timer_type *t_ptr; + + for (t_ptr = gl_timers; t_ptr != NULL; t_ptr = t_ptr->next) + { + if (t_ptr->callback_c) + { + do_bool(&t_ptr->enabled, flag); + do_s32b(&t_ptr->delay, flag); + do_s32b(&t_ptr->countdown, flag); + } + } +} + /* * Actually read the savefile */ @@ -2569,6 +2598,9 @@ static bool_ do_savefile_aux(int flag) strcpy(loaded_game_module, game_module); do_string(loaded_game_module, 80, flag); + /* Timers */ + do_timers(flag); + /* Read RNG state */ do_randomizer(flag); if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Randomizer Info"); diff --git a/src/lua_bind.c b/src/lua_bind.c index a01b1fbc..19fbf529 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -245,7 +245,7 @@ s32b get_level_device(s32b s, s32b max, s32b min) return lvl; } -static int get_mana(s32b s) { +int get_mana(s32b s) { return exec_lua(format("return get_mana(%d)", s)); } diff --git a/src/player.pkg b/src/player.pkg index 459ade67..fdde5229 100644 --- a/src/player.pkg +++ b/src/player.pkg @@ -1761,22 +1761,6 @@ struct player_type */ bool powers[POWER_MAX]; - /** @structvar spellbinder_num - * @brief Number - * @note Number of spells bound - */ - byte spellbinder_num; - /** @structvar spellbinder[4] - * @brief Number - * @note Spell bounds - */ - u32b spellbinder[4]; - /** @structvar spellbinder_trigger - * @brief Number - * @note Spellbinder trigger condition - */ - byte spellbinder_trigger; - /* Corruptions */ bool corrupt_anti_teleport_stopped; diff --git a/src/spells.pkg b/src/spells.pkg index 5df1ef10..63e27f73 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -490,22 +490,6 @@ extern void teleport_away(int m_idx, int dis); */ extern void teleport_player(int dis); -/** @fn teleport_player_to(int ny, int nx) - * @brief Teleport player to a grid near coordinate ("ny", "nx").\n - * @param ny Number \n ny is the y co-ordinate of the location. - * @brief Y coordinate - * @param nx Number \n nx is the x co-ordinate of the location. - * @brief X coordinate - * @note - * Teleport player to a grid near the given location\n\n - * This function is slightly obsessive about correctness.\n - * This function allows teleporting into vaults (!)\n\n - * If the location is empty, the player goes there, otherwise they go to - * a grid as close as possible to the location. - * @note (see file spells1.c) - */ -extern void teleport_player_to(int ny, int nx); - /** @fn teleport_monster_to(int m_idx, int ny, int nx) * @brief Teleport monster indicated by "m_idx" to a grid near coordinate * ("ny", "nx").\n @@ -2382,22 +2366,6 @@ extern s32b lua_spell_device_chance(s32b chance, int level, int base_level); */ extern s32b get_school_spell(cptr do_what, cptr check_fct, s16b force_book); -/** @name Last Teleportation - * @brief Coordinates of last successful teleportation - * @{ */ -/** @var last_teleportation_y - * @brief Number - * @note y-coordinate of last successful teleportation - */ -extern s16b last_teleportation_y; - -/** @var last_teleportation_x - * @brief Number - * @note x-coordinate of last successful teleportation - */ -extern s16b last_teleportation_x; -/** @} */ - /** @fn get_pos_player(int dis, int *ny=0, int *nx=0) * @brief Get a grid near the player.\n * @param dis Number \n is the maximum distance away from the player. @@ -2647,3 +2615,20 @@ bool_ *melkor_corpse_explosion(); char *melkor_corpse_explosion_info(); bool_ *melkor_mind_steal(); char *melkor_mind_steal_info(); + +extern s32b RECHARGE; +extern s32b SPELLBINDER; +extern s32b DISPERSEMAGIC; +extern s32b TRACKER; +extern s32b INERTIA_CONTROL; + +bool_ *meta_recharge(); +char *meta_recharge_info(); +bool_ *meta_spellbinder(); +char *meta_spellbinder_info(); +bool_ *meta_disperse_magic(); +char *meta_disperse_magic_info(); +bool_ *meta_tracker(); +char *meta_tracker_info(); +bool_ *meta_inertia_control(); +char *meta_inertia_control_info(); diff --git a/src/spells3.c b/src/spells3.c index 7fff9935..47abba72 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -73,6 +73,13 @@ s32b MELKOR_CURSE; s32b MELKOR_CORPSE_EXPLOSION; s32b MELKOR_MIND_STEAL; +s32b RECHARGE; +s32b SPELLBINDER; +s32b DISPERSEMAGIC; +s32b TRACKER; +s32b INERTIA_CONTROL; +timer_type *TIMER_INERTIA_CONTROL = 0; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua cares about). */ @@ -2149,3 +2156,306 @@ char *melkor_mind_steal_info() get_level_s(MELKOR_MIND_STEAL, 50)); return buf; } + +bool_ *meta_recharge() +{ + recharge(60 + get_level_s(RECHARGE, 140)); + return CAST; +} + +char *meta_recharge_info() +{ + static char buf[128]; + sprintf(buf, + "power %d", + 60 + get_level_s(RECHARGE, 140)); + return buf; +} + +static int get_spellbinder_max() +{ + int i = get_level_s(SPELLBINDER, 4); + if (i > 4) + { + i = 4; + } + return i; +} + +bool_ *meta_spellbinder() +{ + if (p_ptr->spellbinder_num != 0) + { + typedef struct trigger trigger; + struct trigger { + int idx; + cptr desc; + }; + trigger triggers[] = { + { SPELLBINDER_HP75, "75% HP", }, + { SPELLBINDER_HP50, "50% HP", }, + { SPELLBINDER_HP25, "25% HP", }, + { -1, NULL, }, + }; + int trigger_idx = -1; + int i; + + assert(p_ptr->spellbinder_trigger >= 0); + + for (trigger_idx = 0; triggers[trigger_idx].idx >= 0; trigger_idx++) + { + if (triggers[trigger_idx].idx == p_ptr->spellbinder_trigger) + { + break; + } + } + + msg_print("The spellbinder is already active."); + msg_format("It will trigger at %s.", triggers[trigger_idx].desc); + msg_print("With the spells: "); + for (i = 0; i < p_ptr->spellbinder_num; i++) + { + msg_print(school_spells[p_ptr->spellbinder[i]].name); + } + + /* Doesn't cost anything */ + return NO_CAST; + } + else + { + char c; + int i; + + if (!get_com("Trigger at [a]75% hp [b]50% hp [c]25% hp?", &c)) + { + return NO_CAST; + } + + switch (c) + { + case 'a': + p_ptr->spellbinder_trigger = SPELLBINDER_HP75; + break; + case 'b': + p_ptr->spellbinder_trigger = SPELLBINDER_HP50; + break; + case 'c': + p_ptr->spellbinder_trigger = SPELLBINDER_HP25; + break; + default: + return NO_CAST; + + } + + p_ptr->spellbinder_num = get_spellbinder_max(); + i = p_ptr->spellbinder_num; + while (i > 0) + { + s32b s = get_school_spell("bind", "is_ok_spell", 0); + if (s == -1) + { + p_ptr->spellbinder_trigger = 0; + p_ptr->spellbinder_num = 0; + return CAST; + } else { + if (school_spells[s].skill_level > 7 + get_level_s(SPELLBINDER, 35)) + { + msg_format("You are only allowed spells with a base level of %d.", (7 + get_level_s(SPELLBINDER, 35))); + return CAST; + } + } + + p_ptr->spellbinder[i] = s; + i = i - 1; + } + + p_ptr->energy = p_ptr->energy - 3100; + msg_print("Spellbinder ready."); + return CAST; + } +} + +char *meta_spellbinder_info() +{ + static char buf[128]; + sprintf(buf, + "number %d max level %d", + get_spellbinder_max(), + (7 + get_level_s(SPELLBINDER, 35))); + return buf; +} + +bool_ *meta_disperse_magic() +{ + set_blind(0); + set_lite(0); + if (get_level_s(DISPERSEMAGIC, 50) >= 5) + { + set_confused(0); + set_image(0); + } + if (get_level_s(DISPERSEMAGIC, 50) >= 10) + { + set_slow(0); + set_fast(0, 0); + set_light_speed(0); + } + if (get_level_s(DISPERSEMAGIC, 50) >= 15) + { + set_stun(0); + set_meditation(0); + set_cut(0); + } + if (get_level_s(DISPERSEMAGIC, 50) >= 20) + { + set_hero(0); + set_shero(0); + set_blessed(0); + set_shield(0, 0, 0, 0, 0); + set_afraid(0); + set_parasite(0, 0); + set_mimic(0, 0, 0); + } + return CAST; +} + +char *meta_disperse_magic_info() +{ + return ""; +} + +bool_ *meta_tracker() +{ + if ((last_teleportation_y < 0) || + (last_teleportation_x < 0)) + { + msg_print("There has not been any teleporatation here."); + } + else + { + teleport_player_to(last_teleportation_y, last_teleportation_x); + } + return CAST; +} + +char *meta_tracker_info() +{ + return ""; +} + +static void stop_inertia_controlled_spell() +{ + assert(TIMER_INERTIA_CONTROL != NULL); + + p_ptr->inertia_controlled_spell = -1; + TIMER_INERTIA_CONTROL->enabled = FALSE; + p_ptr->update = p_ptr->update | PU_MANA; +} + +void meta_inertia_control_hook_birth_objects() +{ + stop_inertia_controlled_spell(); +} + +static bool_ lua_var_is_nil(cptr var) +{ + char buf[128]; + sprintf(buf, "return (%s == nil)", var); + return exec_lua(buf); +} + +bool_ *meta_inertia_control() +{ + s32b s; + char prefix[128]; + char inertia_0_var[128]; + char inertia_1_var[128]; + int inertia_0; + int inertia_1; + + if (p_ptr->inertia_controlled_spell != -1) + { + msg_print("You cancel your inertia flow control."); + stop_inertia_controlled_spell(); + return NO_CAST; + } + + s = get_school_spell("control", "is_ok_spell", 0); + if (s == -1) + { + stop_inertia_controlled_spell(); + return NO_CAST; + } + + sprintf(prefix, "__tmp_spells[%d].inertia", (int) s); + sprintf(inertia_0_var, "__tmp_spells[%d].inertia[1]", (int) s); + sprintf(inertia_1_var, "__tmp_spells[%d].inertia[2]", (int) s); + + if (lua_var_is_nil(prefix)) + { + msg_print("This spell inertia flow can not be controlled."); + stop_inertia_controlled_spell(); + return NO_CAST; + } + + inertia_0 = get_lua_int(inertia_0_var); + if (inertia_0 > get_level_s(INERTIA_CONTROL, 10)) + { + msg_format("This spell inertia flow(%d) is too strong to be controlled by your current spell.", inertia_0); + stop_inertia_controlled_spell(); + return NO_CAST; + } + + inertia_1 = get_lua_int(inertia_1_var); + + p_ptr->inertia_controlled_spell = s; + TIMER_INERTIA_CONTROL->enabled = TRUE; + TIMER_INERTIA_CONTROL->delay = inertia_1; + TIMER_INERTIA_CONTROL->countdown = TIMER_INERTIA_CONTROL->delay; + p_ptr->update |= PU_MANA; + msg_format("Inertia flow controlling spell %s.", school_spells[s].name); + return CAST; +} + +char *meta_inertia_control_info() +{ + static char buf[128]; + sprintf(buf, + "level %d", + get_level_s(INERTIA_CONTROL, 10)); + return buf; +} + +void meta_inertia_control_timer_callback() +{ + /* Don't cast a controlled spell in wilderness mode */ + if (p_ptr->antimagic) + { + msg_print("Your anti-magic field disrupts any magic attempts."); + } + else if (p_ptr->anti_magic) + { + msg_print("Your anti-magic shell disrupts any magic attempts."); + } + else if ((p_ptr->inertia_controlled_spell != -1) && + (!p_ptr->wild_mode)) + { + char buf[128]; + sprintf(buf, + "__spell_spell[%d]()", + p_ptr->inertia_controlled_spell); + exec_lua(buf); + } +} + +void meta_inertia_control_calc_mana(int *msp) +{ + if (p_ptr->inertia_controlled_spell != -1) + { + *msp = *msp - (get_mana(p_ptr->inertia_controlled_spell) * 4); + if (*msp < 0) + { + *msp = 0; + } + } +} diff --git a/src/types.h b/src/types.h index ea66ff5f..8e06c4fd 100644 --- a/src/types.h +++ b/src/types.h @@ -1843,6 +1843,9 @@ struct player_type /* Help */ help_info help; + /* Inertia control */ + s32b inertia_controlled_spell; + /*** Temporary fields ***/ bool_ did_nothing; /* True if the last action wasnt a real action */ @@ -2487,7 +2490,8 @@ struct timer_type s32b delay; /* Delay between activations */ s32b countdown; /* The current number of turns passed, when it reaches delay it fires */ - cptr callback; /* The lua function to call upon firing(no C callback yet .. maybe) */ + cptr callback; /* The lua function to call upon firing (if any) */ + void (*callback_c)(); /* The C function to call upon firing */ }; /* diff --git a/src/util.c b/src/util.c index f1b0710e..a195cfc9 100644 --- a/src/util.c +++ b/src/util.c @@ -4417,7 +4417,7 @@ void scansubdir(cptr dir) /* * Timers */ -timer_type *new_timer(cptr callback, s32b delay) +static timer_type *new_timer_init(s32b delay) { timer_type *t_ptr; @@ -4425,7 +4425,8 @@ timer_type *new_timer(cptr callback, s32b delay) t_ptr->next = gl_timers; gl_timers = t_ptr; - t_ptr->callback = string_make(callback); + t_ptr->callback_c = NULL; + t_ptr->callback = NULL; t_ptr->delay = delay; t_ptr->countdown = delay; t_ptr->enabled = FALSE; @@ -4433,6 +4434,20 @@ timer_type *new_timer(cptr callback, s32b delay) return t_ptr; } +timer_type *new_timer(cptr callback, s32b delay) +{ + timer_type *t_ptr = new_timer_init(delay); + t_ptr->callback = string_make(callback); + return t_ptr; +} + +timer_type *new_timer_c(void (*callback)(), s32b delay) +{ + timer_type *t_ptr = new_timer_init(delay); + t_ptr->callback_c = callback; + return t_ptr; +} + void del_timer(timer_type *t_ptr) { timer_type *i, *old; diff --git a/src/xtra1.c b/src/xtra1.c index a2f64d0e..c20b9036 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -1793,6 +1793,8 @@ static void calc_mana(void) msp = process_hooks_return[0].num; } + meta_inertia_control_calc_mana(&msp); + /* Mana can never be negative */ if (msp < 0) msp = 0; -- cgit v1.2.3 From a5b78e910344f4277c110941145e9412a03039ef Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 9 May 2012 22:35:12 +0200 Subject: Lua: Move Theme's "aggravate_evil" timer to C --- lib/core/util.lua | 22 ---------------------- lib/mods/theme/core/util.lua | 22 ---------------------- lib/mods/theme/scpt/monsters.lua | 11 +---------- src/externs.h | 6 +++++- src/init2.c | 3 +++ src/lua_bind.c | 14 ++++++++++++++ src/util.c | 7 ------- src/util.pkg | 26 +++++--------------------- 8 files changed, 28 insertions(+), 83 deletions(-) diff --git a/lib/core/util.lua b/lib/core/util.lua index 048b0d0f..7729ac35 100644 --- a/lib/core/util.lua +++ b/lib/core/util.lua @@ -71,28 +71,6 @@ function msg_print(c, m) end end --- better timer add function -__timers_callback_max = 0 - -function new_timer(t) - assert(t.delay > 0, "no timer delay") - assert(t.enabled, "no timer enabled state") - assert(t.callback, "no timer callback") - - local timer - if type(t.callback) == "function" then - setglobal("__timers_callback_"..__timers_callback_max, t.callback) - timer = %new_timer("__timers_callback_"..__timers_callback_max, t.delay) - __timers_callback_max = __timers_callback_max + 1 - else - timer = %new_timer(t.callback, t.delay) - end - - timer.enabled = t.enabled - - return timer -end - -- displays a scrolling list function display_list(y, x, h, w, title, list, begin, sel, sel_color) diff --git a/lib/mods/theme/core/util.lua b/lib/mods/theme/core/util.lua index 048b0d0f..7729ac35 100644 --- a/lib/mods/theme/core/util.lua +++ b/lib/mods/theme/core/util.lua @@ -71,28 +71,6 @@ function msg_print(c, m) end end --- better timer add function -__timers_callback_max = 0 - -function new_timer(t) - assert(t.delay > 0, "no timer delay") - assert(t.enabled, "no timer enabled state") - assert(t.callback, "no timer callback") - - local timer - if type(t.callback) == "function" then - setglobal("__timers_callback_"..__timers_callback_max, t.callback) - timer = %new_timer("__timers_callback_"..__timers_callback_max, t.delay) - __timers_callback_max = __timers_callback_max + 1 - else - timer = %new_timer(t.callback, t.delay) - end - - timer.enabled = t.enabled - - return timer -end - -- displays a scrolling list function display_list(y, x, h, w, title, list, begin, sel, sel_color) diff --git a/lib/mods/theme/scpt/monsters.lua b/lib/mods/theme/scpt/monsters.lua index cbadf1d6..6c0cc197 100644 --- a/lib/mods/theme/scpt/monsters.lua +++ b/lib/mods/theme/scpt/monsters.lua @@ -62,15 +62,6 @@ end -- cast dispel evil with 0 damage every 10 turns -TIMER_AGGRAVATE_EVIL = new_timer -{ - ["enabled"] = FALSE, - ["delay"] = 10, - ["callback"] = function() - dispel_evil(0) - end, -} - add_hooks{ [HOOK_GAME_START] = function() @@ -80,7 +71,7 @@ add_hooks{ (player_has_corruption(CORRUPT_BALROG_STRENGTH) ~= TRUE) and (player_has_corruption(CORRUPT_BALROG_FORM) ~= TRUE)) then -- "Proper" Maiar aggravate evil beings - TIMER_AGGRAVATE_EVIL.enabled = TRUE + timer_aggravate_evil_enable() -- Good beings (except swans, GWoPs, Wyrm Spirits, and some joke uniques) are coaligned with Maiar monst_al_add(MSTATUS_FRIEND, {25, 29, 45, 97, 109, 147, 225, 335, 346, 443, 581, 629, 699, 853, 984, 1007, 1017}, {21}) diff --git a/src/externs.h b/src/externs.h index e89341a4..e281437e 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1737,7 +1737,6 @@ extern int test_monster_name(cptr name); extern int test_mego_name(cptr name); extern int test_item_name(cptr name); extern char msg_box(cptr text, int y, int x); -extern timer_type *new_timer(cptr callback, s32b delay); extern timer_type *new_timer_c(void (*callback)(), s32b delay); extern void del_timer(timer_type *t_ptr); extern int get_keymap_mode(); @@ -2061,6 +2060,11 @@ extern void lua_display_list(int y, int x, int h, int w, cptr title, list_type * extern void increase_mana(int delta); +extern timer_type *TIMER_AGGRAVATE_EVIL; + +void timer_aggravate_evil_enable(); +void timer_aggravate_evil_callback(); + /* skills.c */ extern void dump_skills(FILE *fff); extern s16b find_skill(cptr name); diff --git a/src/init2.c b/src/init2.c index 38de672a..b30764f9 100644 --- a/src/init2.c +++ b/src/init2.c @@ -1978,6 +1978,9 @@ static errr init_misc(void) TIMER_INERTIA_CONTROL = new_timer_c(meta_inertia_control_timer_callback, 10); + TIMER_AGGRAVATE_EVIL = + new_timer_c(timer_aggravate_evil_callback, + 10); return 0; } diff --git a/src/lua_bind.c b/src/lua_bind.c index 19fbf529..67073061 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -548,3 +548,17 @@ void increase_mana(int delta) sprintf(buf, "increase_mana(%d)", delta); exec_lua(buf); } + +timer_type *TIMER_AGGRAVATE_EVIL = 0; + +void timer_aggravate_evil_enable() +{ + TIMER_AGGRAVATE_EVIL->enabled = TRUE; +} + +void timer_aggravate_evil_callback() +{ + dispel_evil(0); +} + + diff --git a/src/util.c b/src/util.c index a195cfc9..ac060d5e 100644 --- a/src/util.c +++ b/src/util.c @@ -4434,13 +4434,6 @@ static timer_type *new_timer_init(s32b delay) return t_ptr; } -timer_type *new_timer(cptr callback, s32b delay) -{ - timer_type *t_ptr = new_timer_init(delay); - t_ptr->callback = string_make(callback); - return t_ptr; -} - timer_type *new_timer_c(void (*callback)(), s32b delay) { timer_type *t_ptr = new_timer_init(delay); diff --git a/src/util.pkg b/src/util.pkg index a730ee9a..2c6f0d87 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -2325,27 +2325,6 @@ struct timer_type cptr callback; }; -/** @fn *new_timer(cptr callback, s32b delay) - * @brief Create a timer with callback "callback" and delay "delay".\n - * @param callback String \n the callback associated with the timer. - * @brief Callback - * @param delay Number \n the delay associated with the timer. - * @brief Delay - * @return timer_type \n The new timer. - * @note - * The timer's countdown is also set to "delay". The timer is disabled. - * @note (see file util.c) - */ -extern timer_type *new_timer(cptr callback, s32b delay); - -/** @fn del_timer(timer_type *t_ptr) - * @brief Delete timer "t_ptr".\n - * @param *t_ptr timer_type \n the timer to be deleted. - * @brief Timer - * @note (see file util.c) - */ -extern void del_timer(timer_type *t_ptr); - /* * Lists */ @@ -2434,3 +2413,8 @@ extern void lite_spot(int y, int x); * Mimicry */ extern s16b resolve_mimic_name(cptr name); + +/** + * Timers + */ +void timer_aggravate_evil_enable(); -- cgit v1.2.3 From 656d66ee0e61c74f2730e2fffbea0304129d319b Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 9 May 2012 22:42:22 +0200 Subject: Lua: Remove Lua compat bits of timer_type --- src/dungeon.c | 12 ++++-------- src/externs.h | 2 +- src/init2.c | 8 ++++---- src/loadsave.c | 9 +++------ src/types.h | 3 +-- src/util.c | 16 ++++------------ src/util.pkg | 37 ------------------------------------- 7 files changed, 17 insertions(+), 70 deletions(-) diff --git a/src/dungeon.c b/src/dungeon.c index fcca8a21..fd2cc546 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -13,6 +13,8 @@ #include "angband.h" #include "lua/lua.h" #include "tolua.h" +#include + extern lua_State* L; #define TY_CURSE_CHANCE 100 @@ -1345,14 +1347,8 @@ static void process_world(void) if (!t_ptr->countdown) { t_ptr->countdown = t_ptr->delay; - if (t_ptr->callback_c) - { - t_ptr->callback_c(); - } - if (t_ptr->callback) - { - call_lua(t_ptr->callback, "()", ""); - } + assert(t_ptr->callback != NULL); + t_ptr->callback(); } } diff --git a/src/externs.h b/src/externs.h index e281437e..fa50cac8 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1737,7 +1737,7 @@ extern int test_monster_name(cptr name); extern int test_mego_name(cptr name); extern int test_item_name(cptr name); extern char msg_box(cptr text, int y, int x); -extern timer_type *new_timer_c(void (*callback)(), s32b delay); +extern timer_type *new_timer(void (*callback)(), s32b delay); extern void del_timer(timer_type *t_ptr); extern int get_keymap_mode(); diff --git a/src/init2.c b/src/init2.c index b30764f9..9e9911f8 100644 --- a/src/init2.c +++ b/src/init2.c @@ -1976,11 +1976,11 @@ static errr init_misc(void) /* Initialize timers */ TIMER_INERTIA_CONTROL = - new_timer_c(meta_inertia_control_timer_callback, - 10); + new_timer(meta_inertia_control_timer_callback, + 10); TIMER_AGGRAVATE_EVIL = - new_timer_c(timer_aggravate_evil_callback, - 10); + new_timer(timer_aggravate_evil_callback, + 10); return 0; } diff --git a/src/loadsave.c b/src/loadsave.c index 033aa3a0..ad982e8d 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -2519,12 +2519,9 @@ static void do_timers(int flag) for (t_ptr = gl_timers; t_ptr != NULL; t_ptr = t_ptr->next) { - if (t_ptr->callback_c) - { - do_bool(&t_ptr->enabled, flag); - do_s32b(&t_ptr->delay, flag); - do_s32b(&t_ptr->countdown, flag); - } + do_bool(&t_ptr->enabled, flag); + do_s32b(&t_ptr->delay, flag); + do_s32b(&t_ptr->countdown, flag); } } diff --git a/src/types.h b/src/types.h index 8e06c4fd..6066e215 100644 --- a/src/types.h +++ b/src/types.h @@ -2490,8 +2490,7 @@ struct timer_type s32b delay; /* Delay between activations */ s32b countdown; /* The current number of turns passed, when it reaches delay it fires */ - cptr callback; /* The lua function to call upon firing (if any) */ - void (*callback_c)(); /* The C function to call upon firing */ + void (*callback)(); /* The C function to call upon firing */ }; /* diff --git a/src/util.c b/src/util.c index ac060d5e..019ec6da 100644 --- a/src/util.c +++ b/src/util.c @@ -4417,16 +4417,15 @@ void scansubdir(cptr dir) /* * Timers */ -static timer_type *new_timer_init(s32b delay) +timer_type *new_timer(void (*callback)(), s32b delay) { - timer_type *t_ptr; + timer_type *t_ptr = NULL; MAKE(t_ptr, timer_type); t_ptr->next = gl_timers; gl_timers = t_ptr; - t_ptr->callback_c = NULL; - t_ptr->callback = NULL; + t_ptr->callback = callback; t_ptr->delay = delay; t_ptr->countdown = delay; t_ptr->enabled = FALSE; @@ -4434,13 +4433,6 @@ static timer_type *new_timer_init(s32b delay) return t_ptr; } -timer_type *new_timer_c(void (*callback)(), s32b delay) -{ - timer_type *t_ptr = new_timer_init(delay); - t_ptr->callback_c = callback; - return t_ptr; -} - void del_timer(timer_type *t_ptr) { timer_type *i, *old; @@ -4454,7 +4446,7 @@ void del_timer(timer_type *t_ptr) gl_timers = t_ptr->next; else old->next = t_ptr->next; - string_free(t_ptr->callback); + FREE(t_ptr, timer_type); } else diff --git a/src/util.pkg b/src/util.pkg index 2c6f0d87..e6f0294f 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -2288,43 +2288,6 @@ extern cptr game_module; */ extern int get_keymap_dir(char ch); -/* - * Timers - */ -/** @struct timer_type - */ -struct timer_type -{ - /** @structvar *next - * @brief timer_type - * @note The next timer in the list - */ - timer_type *next; - - /** @structvar enabled - * @brief Boolean - * @note Is it currently counting? - */ - bool enabled; - - /** @structvar delay - * @brief Number - * @note Delay between activations - */ - s32b delay; - /** @structvar countdown - * @brief Number - * @note The current number of turns passed, when it reaches delay it fires - */ - s32b countdown; - - /** @structvar callback - * @brief String - * @note The lua function to call upon firing(no C callback yet .. maybe) - */ - cptr callback; -}; - /* * Lists */ -- cgit v1.2.3 From 882afb262b6c01719b3c26c6b49d5ead50af84db Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 10 May 2012 03:28:52 +0200 Subject: Lua: Move "Mind" spell functions to C --- lib/scpt/s_mind.lua | 60 +++---------------- src/externs.h | 14 +++++ src/spells.pkg | 14 +++++ src/spells3.c | 165 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 201 insertions(+), 52 deletions(-) diff --git a/lib/scpt/s_mind.lua b/lib/scpt/s_mind.lua index d1b25e9e..7f24709b 100644 --- a/lib/scpt/s_mind.lua +++ b/lib/scpt/s_mind.lua @@ -18,22 +18,8 @@ CHARM = add_spell ["max_level"] = { 20, 40 }, }, }, - ["spell"] = function() - if get_level(CHARM, 50) >= 35 then - return project_los(GF_CHARM, 10 + get_level(CHARM, 150)) - elseif get_level(CHARM, 50) >= 15 then - local ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_ball(GF_CHARM, dir, 10 + get_level(CHARM, 150), 3) - else - local ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_bolt(GF_CHARM, dir, 10 + get_level(CHARM, 150)) - end - end, - ["info"] = function() - return "power "..(10 + get_level(CHARM, 150)) - end, + ["spell"] = function() return mind_charm() end, + ["info"] = function() return mind_charm_info() end, ["desc"] = { "Tries to manipulate the mind of a monster to make it friendly", "At level 15 it turns into a ball", @@ -59,22 +45,8 @@ CONFUSE = add_spell ["max_level"] = { 20, 40 }, }, }, - ["spell"] = function() - if get_level(CONFUSE, 50) >= 35 then - return project_los(GF_OLD_CONF, 10 + get_level(CONFUSE, 150)) - elseif get_level(CONFUSE, 50) >= 15 then - local ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_ball(GF_OLD_CONF, dir, 10 + get_level(CONFUSE, 150), 3) - else - local ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_bolt(GF_OLD_CONF, dir, 10 + get_level(CONFUSE, 150)) - end - end, - ["info"] = function() - return "power "..(10 + get_level(CONFUSE, 150)) - end, + ["spell"] = function() return mind_confuse() end, + ["info"] = function() return mind_confuse_info() end, ["desc"] = { "Tries to manipulate the mind of a monster to confuse it", "At level 15 it turns into a ball", @@ -91,12 +63,8 @@ ARMOROFFEAR = add_spell ["mana_max"] = 50, ["fail"] = 35, ["inertia"] = { 2, 20 }, - ["spell"] = function() - return set_shield(randint(10) + 10 + get_level(ARMOROFFEAR, 100), 10, SHIELD_FEAR, 1 + get_level(ARMOROFFEAR, 7), 5 + get_level(ARMOROFFEAR, 20)) - end, - ["info"] = function() - return "dur "..(10 + get_level(ARMOROFFEAR, 100)).." power "..(1 + get_level(ARMOROFFEAR, 7)).."d"..(5 + get_level(ARMOROFFEAR, 20)) - end, + ["spell"] = function() return mind_armor_of_fear() end, + ["info"] = function() return mind_armor_of_fear_info() end, ["desc"] = { "Creates a shield of pure fear around you. Any monster attempting to hit you", "must save or flee", @@ -111,20 +79,8 @@ STUN = add_spell ["mana"] = 10, ["mana_max"] = 90, ["fail"] = 45, - ["spell"] = function() - if get_level(STUN, 50) >= 20 then - local ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_ball(GF_STUN, dir, 10 + get_level(STUN, 150), 3) - else - local ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_bolt(GF_STUN, dir, 10 + get_level(STUN, 150)) - end - end, - ["info"] = function() - return "power "..(10 + get_level(STUN, 150)) - end, + ["spell"] = function() return mind_stun() end, + ["info"] = function() return mind_stun_info() end, ["desc"] = { "Tries to manipulate the mind of a monster to stun it", "At level 20 it turns into a ball", diff --git a/src/externs.h b/src/externs.h index fa50cac8..fdcc1562 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1627,6 +1627,20 @@ void meta_inertia_control_timer_callback(); void meta_inertia_control_calc_mana(int *msp); void meta_inertia_control_hook_birth_objects(); +extern s32b CHARM; +extern s32b CONFUSE; +extern s32b ARMOROFFEAR; +extern s32b STUN; + +bool_ *mind_charm(); +char *mind_charm_info(); +bool_ *mind_confuse(); +char *mind_confuse_info(); +bool_ *mind_armor_of_fear(); +char *mind_armor_of_fear_info(); +bool_ *mind_stun(); +char *mind_stun_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index 63e27f73..ca88202e 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2632,3 +2632,17 @@ bool_ *meta_tracker(); char *meta_tracker_info(); bool_ *meta_inertia_control(); char *meta_inertia_control_info(); + +extern s32b CHARM; +extern s32b CONFUSE; +extern s32b ARMOROFFEAR; +extern s32b STUN; + +bool_ *mind_charm(); +char *mind_charm_info(); +bool_ *mind_confuse(); +char *mind_confuse_info(); +bool_ *mind_armor_of_fear(); +char *mind_armor_of_fear_info(); +bool_ *mind_stun(); +char *mind_stun_info(); diff --git a/src/spells3.c b/src/spells3.c index 47abba72..a84f56bd 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -80,6 +80,12 @@ s32b TRACKER; s32b INERTIA_CONTROL; timer_type *TIMER_INERTIA_CONTROL = 0; +s32b CHARM; +s32b CONFUSE; +s32b ARMOROFFEAR; +s32b STUN; + + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua cares about). */ @@ -2459,3 +2465,162 @@ void meta_inertia_control_calc_mana(int *msp) } } } + +static int mind_charm_power() +{ + return 10 + get_level_s(CHARM, 150); +} + +bool_ *mind_charm() +{ + int pwr = mind_charm_power(); + int level = get_level_s(CHARM, 50); + + if (level >= 35) + { + project_hack(GF_CHARM, pwr); + } + else + { + int dir; + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + if (level >= 15) + { + fire_ball(GF_CHARM, dir, pwr, 3); + } + else + { + fire_bolt(GF_CHARM, dir, pwr); + } + } + + return CAST; +} + +char *mind_charm_info() +{ + static char buf[128]; + sprintf(buf, + "power %d", + mind_charm_power()); + return buf; +} + +static int mind_confuse_power() +{ + return 10 + get_level_s(CONFUSE, 150); +} + +bool_ *mind_confuse() +{ + int pwr = mind_confuse_power(); + int level = get_level_s(CONFUSE, 50); + + if (level >= 35) + { + project_hack(GF_OLD_CONF, pwr); + } + else + { + int dir; + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + if (level >= 15) + { + fire_ball(GF_OLD_CONF, dir, pwr, 3); + } + else + { + fire_bolt(GF_OLD_CONF, dir, pwr); + } + } + + return CAST; +} + +char *mind_confuse_info() +{ + static char buf[128]; + sprintf(buf, + "power %d", + mind_confuse_power()); + return buf; +} + +static int mind_armor_of_fear_base_duration() +{ + return 10 + get_level_s(ARMOROFFEAR, 100); +} + +static int mind_armor_of_fear_power_sides() +{ + return 1 + get_level_s(ARMOROFFEAR, 7); +} + +static int mind_armor_of_fear_power_dice() +{ + return 5 + get_level_s(ARMOROFFEAR, 20); +} + +bool_ *mind_armor_of_fear() +{ + set_shield(randint(10) + mind_armor_of_fear_base_duration(), + 10, + SHIELD_FEAR, + mind_armor_of_fear_power_sides(), + mind_armor_of_fear_power_dice()); + return CAST; +} + +char *mind_armor_of_fear_info() +{ + static char buf[128]; + sprintf(buf, + "dur %d+d10 power %dd%d", + mind_armor_of_fear_base_duration(), + mind_armor_of_fear_power_sides(), + mind_armor_of_fear_power_dice()); + return buf; +} + +static int mind_stun_power() +{ + return 10 + get_level_s(STUN, 150); +} + +bool_ *mind_stun() +{ + int dir; + + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + if (get_level_s(STUN, 50) >= 20) + { + fire_ball(GF_STUN, dir, mind_stun_power(), 3); + } + else + { + fire_bolt(GF_STUN, dir, mind_stun_power()); + } + + return CAST; +} + +char *mind_stun_info() +{ + static char buf[128]; + sprintf(buf, + "power %d", + mind_stun_power()); + return buf; +} -- cgit v1.2.3 From 50ea7fdc8af5d74a8f1d0e2d730f3b45d2d14d8e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 10 May 2012 18:00:12 +0200 Subject: Fix 32-bit warnings --- src/h-type.h | 6 +++ src/q_god.c | 2 +- src/spells3.c | 118 +++++++++++++++++++++++++++++----------------------------- 3 files changed, 66 insertions(+), 60 deletions(-) diff --git a/src/h-type.h b/src/h-type.h index 5dbb4975..27551b7f 100644 --- a/src/h-type.h +++ b/src/h-type.h @@ -109,14 +109,20 @@ typedef unsigned long huge; /* Signed/Unsigned 16 bit value */ typedef signed short s16b; typedef unsigned short u16b; +#define FMTs16b "%hd" +#define FMTu16b "%hu" /* Signed/Unsigned 32 bit value */ #ifdef L64 /* 64 bit longs */ typedef signed int s32b; typedef unsigned int u32b; +#define FMTs32b "%d" +#define FMTu32b "%u" #else typedef signed long s32b; typedef unsigned long u32b; +#define FMTs32b "%ld" +#define FMTu32b "%lu" #endif diff --git a/src/q_god.c b/src/q_god.c index ecc26d96..a01a60a9 100644 --- a/src/q_god.c +++ b/src/q_god.c @@ -285,7 +285,7 @@ bool_ quest_god_describe(FILE *fff) { if (cquest.status == QUEST_STATUS_TAKEN) { - fprintf(fff, "#####yGod quest %d!\n", cquest_quests_given); + fprintf(fff, "#####yGod quest " FMTs32b "!\n", cquest_quests_given); fprintf(fff, "Thou art to find the lost temple of thy God and\n"); fprintf(fff, "to retrieve the lost part of the relic for thy God! \n"); print_directions(FALSE, print_using_print_hook, fff); diff --git a/src/spells3.c b/src/spells3.c index a84f56bd..3c038772 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -124,7 +124,7 @@ char *air_noxious_cloud_info() { static char buf[128]; sprintf(buf, - "dam %d rad 3 dur %d", + "dam " FMTs32b " rad 3 dur " FMTs32b, (7 + get_level_s(NOXIOUSCLOUD, 150)), (5 + get_level_s(NOXIOUSCLOUD, 40))); return buf; @@ -152,7 +152,7 @@ bool_ *air_wings_of_winds() char *air_wings_of_winds_info() { static char buf[128]; - sprintf(buf, "dur %d+d10", (5 + get_level_s(AIRWINGS, 25))); + sprintf(buf, "dur " FMTs32b "+d10", (5 + get_level_s(AIRWINGS, 25))); return buf; } @@ -170,7 +170,7 @@ bool_ *air_invisibility() char *air_invisibility_info() { static char buf[128]; - sprintf(buf, "dur %d+d20 power %d", + sprintf(buf, "dur " FMTs32b "+d20 power " FMTs32b, (15 + get_level_s(INVISIBILITY, 50)), (20 + get_level_s(INVISIBILITY, 50))); return buf; @@ -200,7 +200,7 @@ char *air_poison_blood_info() { static char buf[128]; sprintf(buf, - "dur %d+d30", + "dur " FMTs32b "+d30", (25 + get_level_s(POISONBLOOD, 25))); return buf; } @@ -220,7 +220,7 @@ char *air_thunderstorm_info() { static char buf[128]; sprintf(buf, - "dam %dd%d dur %d+d10", + "dam " FMTs32b "d" FMTs32b " dur " FMTs32b "+d10", (5 + get_level_s(THUNDERSTORM, 10)), (10 + get_level_s(THUNDERSTORM, 25)), (10 + get_level_s(THUNDERSTORM, 25))); @@ -237,7 +237,7 @@ char *air_sterilize_info() { static char buf[128]; sprintf(buf, - "dur %d+d30", + "dur " FMTs32b "+d30", (20 + get_level_s(STERILIZE, 70))); return buf; } @@ -264,7 +264,7 @@ char *convey_blink_info() { static char buf[128]; sprintf(buf, - "distance %d", + "distance " FMTs32b, (10 + get_level_s(BLINK, 8))); return buf; } @@ -296,7 +296,7 @@ char *convey_teleport_info() { static char buf[128]; sprintf(buf, - "distance %d", + "distance " FMTs32b, (100 + get_level_s(TELEPORT, 100))); return buf; } @@ -407,7 +407,7 @@ char *convey_recall_info() int f = recall_get_f(); sprintf(buf, - "dur %d+d%d weight %dlb", + "dur %d+d%d weight " FMTs32b "lb", f, d, (1 + get_level_s(RECALL, 15))); return buf; } @@ -422,7 +422,7 @@ char *convey_probability_travel_info() { static char buf[128]; sprintf(buf, - "dur %d+d20", + "dur " FMTs32b "+d20", get_level_s(PROBABILITY_TRAVEL, 60)); return buf; } @@ -455,7 +455,7 @@ char *demonology_demon_blade_info() { static char buf[128]; sprintf(buf, - "dur %d+d20 dam %d/blow", + "dur " FMTs32b "+d20 dam " FMTs32b "/blow", (get_level_s(DEMON_BLADE, 80)), (4 + get_level_s(DEMON_BLADE, 40))); return buf; @@ -503,7 +503,7 @@ char *demonology_demon_madness_info() { static char buf[128]; sprintf(buf, - "dam %d rad %d", + "dam " FMTs32b " rad " FMTs32b, (20 + get_level_s(DEMON_MADNESS, 200)), (1 + get_level(DEMON_MADNESS, 4, 0))); return buf; @@ -530,7 +530,7 @@ char *demonology_demon_field_info() { static char buf[128]; sprintf(buf, - "dam %d dur %d", + "dam " FMTs32b " dur " FMTs32b, (20 + get_level_s(DEMON_FIELD, 70)), (30 + get_level_s(DEMON_FIELD, 100))); return buf; @@ -550,7 +550,7 @@ char *demonology_doom_shield_info() { static char buf[128]; sprintf(buf, - "dur %d+d10 dam %dd%d", + "dur " FMTs32b "+d10 dam " FMTs32b "d" FMTs32b, (20 + get_level_s(DOOM_SHIELD, 100)), (1 + get_level_s(DOOM_SHIELD, 14)), (10 + get_level_s(DOOM_SHIELD, 15))); @@ -618,7 +618,7 @@ char *demonology_unholy_word_info() { static char buf[128]; sprintf(buf, - "heal mhp%% of %d%%", + "heal mhp%% of " FMTs32b "%%", (30 + get_level(UNHOLY_WORD, 50, 0))); return buf; } @@ -633,7 +633,7 @@ char *demonology_demon_cloak_info() { static char buf[128]; sprintf(buf, - "dur %d+d5", + "dur " FMTs32b "+d5", (5 + get_level(DEMON_CLOAK, 15, 0))); return buf; } @@ -670,7 +670,7 @@ char *demonology_summon_demon_info() { static char buf[128]; sprintf(buf, - "level %d", + "level " FMTs32b, (5 + get_level_s(DEMON_SUMMON, 100))); return buf; } @@ -722,7 +722,7 @@ char *demonology_discharge_minion_info() { static char buf[128]; sprintf(buf, - "dam %d%% max %d", + "dam " FMTs32b "%% max " FMTs32b, (20 + get_level(DISCHARGE_MINION, 60, 0)), (100 + get_level(DISCHARGE_MINION, 500, 0))); return buf; @@ -744,7 +744,7 @@ char *demonology_control_demon_info() { static char buf[128]; sprintf(buf, - "power %d", + "power " FMTs32b, (50 + get_level_s(CONTROL_DEMON, 250))); return buf; } @@ -799,7 +799,7 @@ char *divination_identify_info() if (get_level_s(IDENTIFY, 50) >= 27) { - sprintf(buf, "rad %d", get_level_s(IDENTIFY, 3)); + sprintf(buf, "rad " FMTs32b, get_level_s(IDENTIFY, 3)); return buf; } else @@ -844,14 +844,14 @@ char *divination_sense_hidden_info() if (get_level_s(SENSEHIDDEN, 50) >= 15) { sprintf(buf, - "rad %d dur %d+d20", + "rad " FMTs32b " dur " FMTs32b "+d20", (15 + get_level_s(SENSEHIDDEN, 40)), (10 + get_level_s(SENSEHIDDEN, 40))); } else { sprintf(buf, - "rad %d", + "rad " FMTs32b, (15 + get_level_s(SENSEHIDDEN, 40))); } @@ -869,7 +869,7 @@ char *divination_reveal_ways_info() { static char buf[128]; sprintf(buf, - "rad %d", + "rad " FMTs32b, (10 + get_level_s(REVEALWAYS, 40))); return buf; } @@ -891,14 +891,14 @@ char *divination_sense_monsters_info() if (get_level_s(SENSEMONSTERS, 50) >= 30) { sprintf(buf, - "rad %d dur %d+d10", + "rad " FMTs32b " dur " FMTs32b "+d10", (10 + get_level_s(SENSEMONSTERS, 40)), (10 + get_level_s(SENSEMONSTERS, 20))); } else { sprintf(buf, - "rad %d", + "rad " FMTs32b, (10 + get_level_s(SENSEMONSTERS, 40))); } @@ -930,7 +930,7 @@ char *earth_stone_skin_info() if (get_level_s(STONESKIN, 50) >= 25) { sprintf(buf, - "dam %dd%d dur %d+d10 AC %d", + "dam " FMTs32b "d" FMTs32b " dur " FMTs32b "+d10 AC " FMTs32b, (2 + get_level_s(STONESKIN, 5)), (3 + get_level_s(STONESKIN, 5)), (10 + get_level_s(STONESKIN, 100)), @@ -939,7 +939,7 @@ char *earth_stone_skin_info() else { sprintf(buf, - "dur %d+d10 AC %d", + "dur " FMTs32b "+d10 AC " FMTs32b, (10 + get_level_s(STONESKIN, 100)), (10 + get_level_s(STONESKIN, 50))); } @@ -1052,7 +1052,7 @@ bool_ *earth_shake() char *earth_shake_info() { static char buf[128]; - sprintf(buf, "rad %d", (4 + get_level_s(SHAKE, 10))); + sprintf(buf, "rad " FMTs32b, (4 + get_level_s(SHAKE, 10))); return buf; } @@ -1081,7 +1081,7 @@ char *eru_see_the_music_info() { static char buf[128]; sprintf(buf, - "dur %d+d20", + "dur " FMTs32b "+d20", (10 + get_level_s(ERU_SEE, 100))); return buf; } @@ -1137,7 +1137,7 @@ char *eru_lay_of_protection_info() { static char buf[128]; sprintf(buf, - "rad %d", + "rad " FMTs32b, (1 + get_level(ERU_PROT, 2, 0))); return buf; } @@ -1170,7 +1170,7 @@ char *fire_globe_of_light_info() if (get_level_s(GLOBELIGHT, 50) >= 15) { - sprintf(buf, "dam %d rad %d", + sprintf(buf, "dam " FMTs32b " rad " FMTs32b, (10 + get_level_s(GLOBELIGHT, 100)), (5 + get_level_s(GLOBELIGHT, 6))); } @@ -1207,7 +1207,7 @@ char *fire_fireflash_info() { static char buf[128]; sprintf(buf, - "dam %d rad %d", + "dam " FMTs32b " rad " FMTs32b, (20 + get_level_s(FIREFLASH, 500)), (2 + get_level_s(FIREFLASH, 5))); return buf; @@ -1233,7 +1233,7 @@ char *fire_fiery_shield_info() { static char buf[128]; sprintf(buf, - "dam %dd%d dur %d+d20", + "dam " FMTs32b "d" FMTs32b " dur " FMTs32b "+d20", (5 + get_level_s(FIERYAURA, 15)), (5 + get_level_s(FIERYAURA, 7)), (10 + get_level_s(FIERYAURA, 70))); @@ -1264,7 +1264,7 @@ char *fire_firewall_info() { static char buf[128]; sprintf(buf, - "dam %d dur %d", + "dam " FMTs32b " dur " FMTs32b, (40 + get_level_s(FIREWALL, 150)), (10 + get_level_s(FIREWALL, 14))); return buf; @@ -1321,7 +1321,7 @@ char *fire_golem_info() { static char buf[128]; sprintf(buf, - "golem level %d", + "golem level " FMTs32b, (7 + get_level_s(FIREGOLEM, 70))); return buf; } @@ -1350,7 +1350,7 @@ char *geomancy_call_the_elements_info() { static char buf[128]; sprintf(buf, - "rad %d", + "rad " FMTs32b, (1 + get_level(CALL_THE_ELEMENTS, 5, 0))); return buf; } @@ -1507,7 +1507,7 @@ char *geomancy_vaporize_info() { static char buf[128]; sprintf(buf, - "rad %d dur %d", + "rad " FMTs32b " dur " FMTs32b, (1 + get_level_s(VAPORIZE, 4)), (10 + get_level_s(VAPORIZE, 20))); return buf; @@ -1532,7 +1532,7 @@ char *geomancy_geolysis_info() { static char buf[128]; sprintf(buf, - "length %d", + "length " FMTs32b, (5 + get_level_s(GEOLYSIS, 12))); return buf; } @@ -1557,7 +1557,7 @@ char *geomancy_dripping_tread_info() { static char buf[128]; sprintf(buf, - "dur %d+d15 movs", + "dur " FMTs32b "+d15 movs", (10 + get_level_s(DRIPPING_TREAD, 50))); return buf; } @@ -1712,7 +1712,7 @@ char *geomancy_elemental_minion_info() { static char buf[128]; sprintf(buf, - "min level %d", + "min level " FMTs32b, (10 + get_level_s(ELEMENTAL_MINION, 120))); return buf; } @@ -1747,7 +1747,7 @@ char *mana_manathrust_info() get_manathrust_dam(&num, &sides); sprintf(buf, - "dam %dd%d", + "dam " FMTs16b "d" FMTs16b, num, sides); return buf; @@ -1814,7 +1814,7 @@ char *mana_elemental_shield_info() { static char buf[128]; sprintf(buf, - "dur %d+d10", + "dur " FMTs32b "+d10", (15 + get_level_s(RESISTS, 50))); return buf; } @@ -1842,7 +1842,7 @@ char *mana_disruption_shield_info() { static char buf[128]; sprintf(buf, - "dur %d+d5", + "dur " FMTs32b "+d5", (3 + get_level_s(MANASHIELD, 10))); return buf; } @@ -1875,20 +1875,20 @@ char *manwe_wind_shield_info() static char buf[128]; sprintf(buf, - "dur %d+d20", + "dur " FMTs32b "+d20", (get_level_s(MANWE_SHIELD, 50) + 10)); if (get_level_s(MANWE_SHIELD, 50) >= 10) { char tmp[128]; - sprintf(tmp, " AC %d", get_level_s(MANWE_SHIELD, 30)); + sprintf(tmp, " AC " FMTs32b, get_level_s(MANWE_SHIELD, 30)); strcat(buf, tmp); } if (get_level_s(MANWE_SHIELD, 50) >= 20) { char tmp[128]; - sprintf(tmp, " dam %dd%d", + sprintf(tmp, " dam " FMTs32b "d" FMTs32b, (1 + get_level_s(MANWE_SHIELD, 2)), (1 + get_level_s(MANWE_SHIELD, 6))); strcat(buf, tmp); @@ -1912,7 +1912,7 @@ char *manwe_avatar_info() { static char buf[128]; sprintf(buf, - "dur %d+d10", + "dur " FMTs32b "+d10", get_level_s(MANWE_AVATAR, 20)); return buf; } @@ -1945,7 +1945,7 @@ char *manwe_blessing_info() { static char buf[128]; sprintf(buf, - "dur %d+d40", + "dur " FMTs32b "+d40", get_level_s(MANWE_BLESS, 70) + 30); return buf; } @@ -1974,7 +1974,7 @@ char *manwe_call_info() { static char buf[128]; sprintf(buf, - "level %d", + "level " FMTs32b, get_level_s(MANWE_CALL, 70) + 20); return buf; } @@ -2108,7 +2108,7 @@ char *melkor_corpse_explosion_info() { static char buf[128]; sprintf(buf, - "dam %d%%", + "dam " FMTs32b "%%", 20 + get_level_s(MELKOR_CORPSE_EXPLOSION, 70)); return buf; } @@ -2158,7 +2158,7 @@ char *melkor_mind_steal_info() { static char buf[128]; sprintf(buf, - "chance 1d(mlvl)<%d", + "chance 1d(mlvl)<" FMTs32b, get_level_s(MELKOR_MIND_STEAL, 50)); return buf; } @@ -2173,7 +2173,7 @@ char *meta_recharge_info() { static char buf[128]; sprintf(buf, - "power %d", + "power " FMTs32b, 60 + get_level_s(RECHARGE, 140)); return buf; } @@ -2266,7 +2266,7 @@ bool_ *meta_spellbinder() } else { if (school_spells[s].skill_level > 7 + get_level_s(SPELLBINDER, 35)) { - msg_format("You are only allowed spells with a base level of %d.", (7 + get_level_s(SPELLBINDER, 35))); + msg_format("You are only allowed spells with a base level of " FMTs32b ".", (7 + get_level_s(SPELLBINDER, 35))); return CAST; } } @@ -2285,7 +2285,7 @@ char *meta_spellbinder_info() { static char buf[128]; sprintf(buf, - "number %d max level %d", + "number %d max level " FMTs32b, get_spellbinder_max(), (7 + get_level_s(SPELLBINDER, 35))); return buf; @@ -2393,9 +2393,9 @@ bool_ *meta_inertia_control() return NO_CAST; } - sprintf(prefix, "__tmp_spells[%d].inertia", (int) s); - sprintf(inertia_0_var, "__tmp_spells[%d].inertia[1]", (int) s); - sprintf(inertia_1_var, "__tmp_spells[%d].inertia[2]", (int) s); + sprintf(prefix, "__tmp_spells[" FMTs32b "].inertia", s); + sprintf(inertia_0_var, "__tmp_spells[" FMTs32b "].inertia[1]", s); + sprintf(inertia_1_var, "__tmp_spells[" FMTs32b "].inertia[2]", s); if (lua_var_is_nil(prefix)) { @@ -2427,7 +2427,7 @@ char *meta_inertia_control_info() { static char buf[128]; sprintf(buf, - "level %d", + "level " FMTs32b, get_level_s(INERTIA_CONTROL, 10)); return buf; } @@ -2448,7 +2448,7 @@ void meta_inertia_control_timer_callback() { char buf[128]; sprintf(buf, - "__spell_spell[%d]()", + "__spell_spell[" FMTs32b "]()", p_ptr->inertia_controlled_spell); exec_lua(buf); } -- cgit v1.2.3 From 2447ebac2f0bba50c240a8edba151c59118792cc Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 10 May 2012 19:06:47 +0200 Subject: Lua: Move "Mind" spell functions to C (Theme) --- lib/mods/theme/scpt/s_mind.lua | 60 ++++++------------------------------------ 1 file changed, 8 insertions(+), 52 deletions(-) diff --git a/lib/mods/theme/scpt/s_mind.lua b/lib/mods/theme/scpt/s_mind.lua index d1b25e9e..7f24709b 100644 --- a/lib/mods/theme/scpt/s_mind.lua +++ b/lib/mods/theme/scpt/s_mind.lua @@ -18,22 +18,8 @@ CHARM = add_spell ["max_level"] = { 20, 40 }, }, }, - ["spell"] = function() - if get_level(CHARM, 50) >= 35 then - return project_los(GF_CHARM, 10 + get_level(CHARM, 150)) - elseif get_level(CHARM, 50) >= 15 then - local ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_ball(GF_CHARM, dir, 10 + get_level(CHARM, 150), 3) - else - local ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_bolt(GF_CHARM, dir, 10 + get_level(CHARM, 150)) - end - end, - ["info"] = function() - return "power "..(10 + get_level(CHARM, 150)) - end, + ["spell"] = function() return mind_charm() end, + ["info"] = function() return mind_charm_info() end, ["desc"] = { "Tries to manipulate the mind of a monster to make it friendly", "At level 15 it turns into a ball", @@ -59,22 +45,8 @@ CONFUSE = add_spell ["max_level"] = { 20, 40 }, }, }, - ["spell"] = function() - if get_level(CONFUSE, 50) >= 35 then - return project_los(GF_OLD_CONF, 10 + get_level(CONFUSE, 150)) - elseif get_level(CONFUSE, 50) >= 15 then - local ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_ball(GF_OLD_CONF, dir, 10 + get_level(CONFUSE, 150), 3) - else - local ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_bolt(GF_OLD_CONF, dir, 10 + get_level(CONFUSE, 150)) - end - end, - ["info"] = function() - return "power "..(10 + get_level(CONFUSE, 150)) - end, + ["spell"] = function() return mind_confuse() end, + ["info"] = function() return mind_confuse_info() end, ["desc"] = { "Tries to manipulate the mind of a monster to confuse it", "At level 15 it turns into a ball", @@ -91,12 +63,8 @@ ARMOROFFEAR = add_spell ["mana_max"] = 50, ["fail"] = 35, ["inertia"] = { 2, 20 }, - ["spell"] = function() - return set_shield(randint(10) + 10 + get_level(ARMOROFFEAR, 100), 10, SHIELD_FEAR, 1 + get_level(ARMOROFFEAR, 7), 5 + get_level(ARMOROFFEAR, 20)) - end, - ["info"] = function() - return "dur "..(10 + get_level(ARMOROFFEAR, 100)).." power "..(1 + get_level(ARMOROFFEAR, 7)).."d"..(5 + get_level(ARMOROFFEAR, 20)) - end, + ["spell"] = function() return mind_armor_of_fear() end, + ["info"] = function() return mind_armor_of_fear_info() end, ["desc"] = { "Creates a shield of pure fear around you. Any monster attempting to hit you", "must save or flee", @@ -111,20 +79,8 @@ STUN = add_spell ["mana"] = 10, ["mana_max"] = 90, ["fail"] = 45, - ["spell"] = function() - if get_level(STUN, 50) >= 20 then - local ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_ball(GF_STUN, dir, 10 + get_level(STUN, 150), 3) - else - local ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_bolt(GF_STUN, dir, 10 + get_level(STUN, 150)) - end - end, - ["info"] = function() - return "power "..(10 + get_level(STUN, 150)) - end, + ["spell"] = function() return mind_stun() end, + ["info"] = function() return mind_stun_info() end, ["desc"] = { "Tries to manipulate the mind of a monster to stun it", "At level 20 it turns into a ball", -- cgit v1.2.3 From 9c849217091714882ab73d03c6f11efb7f610924 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 10 May 2012 19:53:38 +0200 Subject: Lua: Move "Temporal" spell functions to C --- lib/mods/theme/scpt/s_tempo.lua | 69 +++--------------- lib/scpt/s_tempo.lua | 69 +++--------------- src/externs.h | 14 ++++ src/spells.pkg | 14 ++++ src/spells3.c | 152 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 196 insertions(+), 122 deletions(-) diff --git a/lib/mods/theme/scpt/s_tempo.lua b/lib/mods/theme/scpt/s_tempo.lua index d3d2fbb5..76026745 100644 --- a/lib/mods/theme/scpt/s_tempo.lua +++ b/lib/mods/theme/scpt/s_tempo.lua @@ -19,32 +19,8 @@ MAGELOCK = add_spell ["max_level"] = { 15, 45 }, }, }, - ["spell"] = function() - if get_level(MAGELOCK, 50) >= 30 then - local ret, x, y, c_ptr - - if get_level(MAGELOCK, 50) >= 40 then - ret, x, y = tgt_pt() - if ret == FALSE then return end - if cave_is(cave(y, x), FF1_FLOOR) == FALSE or cave_is(cave(y, x), FF1_PERMANENT) == TRUE or los(player.py, player.px, y, x) == FALSE then - msg_print("You cannot place it there.") - return TRUE - end - else - y = player.py - x = player.px - end - cave_set_feat(y, x, 3) - return TRUE - else - ret, dir = get_aim_dir() - if ret == FALSE then return end - return wizard_lock(dir) - end - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return tempo_magelock() end, + ["info"] = function() return tempo_magelock_info() end, ["desc"] = { "Magically locks a door", "At level 30 it creates a glyph of warding", @@ -70,24 +46,8 @@ SLOWMONSTER = add_spell ["max_level"] = { 20, 50 }, }, }, - ["spell"] = function() - local ret, dir - - ret, dir = get_aim_dir() - if ret == FALSE then return end - if get_level(SLOWMONSTER, 50) >= 20 then - return fire_ball(GF_OLD_SLOW, dir, 40 + get_level(SLOWMONSTER, 160), 1) - else - return fire_bolt(GF_OLD_SLOW, dir, 40 + get_level(SLOWMONSTER, 160)) - end - end, - ["info"] = function() - if get_level(SLOWMONSTER, 50) >= 20 then - return "power "..(40 + get_level(SLOWMONSTER, 160)).." rad 1" - else - return "power "..(40 + get_level(SLOWMONSTER, 160)) - end - end, + ["spell"] = function() return tempo_slow_monster() end, + ["info"] = function() return tempo_slow_monster_info() end, ["desc"] = { "Magically slows down the passing of time around a monster", "At level 20 it affects a zone" @@ -113,12 +73,8 @@ ESSENCESPEED = add_spell }, }, ["inertia"] = { 5, 20 }, - ["spell"] = function() - if player.fast == 0 then return set_fast(10 + randint(10) + get_level(ESSENCESPEED, 50), 5 + get_level(ESSENCESPEED, 20)) end - end, - ["info"] = function() - return "dur "..(10 + get_level(ESSENCESPEED, 50)).."+d10 speed "..(5 + get_level(ESSENCESPEED, 20)) - end, + ["spell"] = function() return tempo_essence_of_speed() end, + ["info"] = function() return tempo_essence_of_speed_info() end, ["desc"] = { "Magically decreases the passing of time around you, making you move faster with", "respect to the rest of the universe." @@ -144,17 +100,8 @@ BANISHMENT = add_spell }, }, ["inertia"] = { 5, 50 }, - ["spell"] = function() - local obvious - obvious = project_los(GF_AWAY_ALL, 40 + get_level(BANISHMENT, 160)) - if get_level(BANISHMENT, 50) >= 15 then - obvious = is_obvious(project_los(GF_STASIS, 20 + get_level(BANISHMENT, 120)), obvious) - end - return obvious - end, - ["info"] = function() - return "power "..(40 + get_level(BANISHMENT, 160)) - end, + ["spell"] = function() return tempo_banishment() end, + ["info"] = function() return tempo_banishment_info() end, ["desc"] = { "Disrupts the space/time continuum in your area and teleports all monsters away.", "At level 15 it may also lock them in a time bubble for a while." diff --git a/lib/scpt/s_tempo.lua b/lib/scpt/s_tempo.lua index d3d2fbb5..76026745 100644 --- a/lib/scpt/s_tempo.lua +++ b/lib/scpt/s_tempo.lua @@ -19,32 +19,8 @@ MAGELOCK = add_spell ["max_level"] = { 15, 45 }, }, }, - ["spell"] = function() - if get_level(MAGELOCK, 50) >= 30 then - local ret, x, y, c_ptr - - if get_level(MAGELOCK, 50) >= 40 then - ret, x, y = tgt_pt() - if ret == FALSE then return end - if cave_is(cave(y, x), FF1_FLOOR) == FALSE or cave_is(cave(y, x), FF1_PERMANENT) == TRUE or los(player.py, player.px, y, x) == FALSE then - msg_print("You cannot place it there.") - return TRUE - end - else - y = player.py - x = player.px - end - cave_set_feat(y, x, 3) - return TRUE - else - ret, dir = get_aim_dir() - if ret == FALSE then return end - return wizard_lock(dir) - end - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return tempo_magelock() end, + ["info"] = function() return tempo_magelock_info() end, ["desc"] = { "Magically locks a door", "At level 30 it creates a glyph of warding", @@ -70,24 +46,8 @@ SLOWMONSTER = add_spell ["max_level"] = { 20, 50 }, }, }, - ["spell"] = function() - local ret, dir - - ret, dir = get_aim_dir() - if ret == FALSE then return end - if get_level(SLOWMONSTER, 50) >= 20 then - return fire_ball(GF_OLD_SLOW, dir, 40 + get_level(SLOWMONSTER, 160), 1) - else - return fire_bolt(GF_OLD_SLOW, dir, 40 + get_level(SLOWMONSTER, 160)) - end - end, - ["info"] = function() - if get_level(SLOWMONSTER, 50) >= 20 then - return "power "..(40 + get_level(SLOWMONSTER, 160)).." rad 1" - else - return "power "..(40 + get_level(SLOWMONSTER, 160)) - end - end, + ["spell"] = function() return tempo_slow_monster() end, + ["info"] = function() return tempo_slow_monster_info() end, ["desc"] = { "Magically slows down the passing of time around a monster", "At level 20 it affects a zone" @@ -113,12 +73,8 @@ ESSENCESPEED = add_spell }, }, ["inertia"] = { 5, 20 }, - ["spell"] = function() - if player.fast == 0 then return set_fast(10 + randint(10) + get_level(ESSENCESPEED, 50), 5 + get_level(ESSENCESPEED, 20)) end - end, - ["info"] = function() - return "dur "..(10 + get_level(ESSENCESPEED, 50)).."+d10 speed "..(5 + get_level(ESSENCESPEED, 20)) - end, + ["spell"] = function() return tempo_essence_of_speed() end, + ["info"] = function() return tempo_essence_of_speed_info() end, ["desc"] = { "Magically decreases the passing of time around you, making you move faster with", "respect to the rest of the universe." @@ -144,17 +100,8 @@ BANISHMENT = add_spell }, }, ["inertia"] = { 5, 50 }, - ["spell"] = function() - local obvious - obvious = project_los(GF_AWAY_ALL, 40 + get_level(BANISHMENT, 160)) - if get_level(BANISHMENT, 50) >= 15 then - obvious = is_obvious(project_los(GF_STASIS, 20 + get_level(BANISHMENT, 120)), obvious) - end - return obvious - end, - ["info"] = function() - return "power "..(40 + get_level(BANISHMENT, 160)) - end, + ["spell"] = function() return tempo_banishment() end, + ["info"] = function() return tempo_banishment_info() end, ["desc"] = { "Disrupts the space/time continuum in your area and teleports all monsters away.", "At level 15 it may also lock them in a time bubble for a while." diff --git a/src/externs.h b/src/externs.h index fdcc1562..6db58e36 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1641,6 +1641,20 @@ char *mind_armor_of_fear_info(); bool_ *mind_stun(); char *mind_stun_info(); +extern s32b MAGELOCK; +extern s32b SLOWMONSTER; +extern s32b ESSENCESPEED; +extern s32b BANISHMENT; + +bool_ *tempo_magelock(); +char *tempo_magelock_info(); +bool_ *tempo_slow_monster(); +char *tempo_slow_monster_info(); +bool_ *tempo_essence_of_speed(); +char *tempo_essence_of_speed_info(); +bool_ *tempo_banishment(); +char *tempo_banishment_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index ca88202e..eeae6e7d 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2646,3 +2646,17 @@ bool_ *mind_armor_of_fear(); char *mind_armor_of_fear_info(); bool_ *mind_stun(); char *mind_stun_info(); + +extern s32b MAGELOCK; +extern s32b SLOWMONSTER; +extern s32b ESSENCESPEED; +extern s32b BANISHMENT; + +bool_ *tempo_magelock(); +char *tempo_magelock_info(); +bool_ *tempo_slow_monster(); +char *tempo_slow_monster_info(); +bool_ *tempo_essence_of_speed(); +char *tempo_essence_of_speed_info(); +bool_ *tempo_banishment(); +char *tempo_banishment_info(); diff --git a/src/spells3.c b/src/spells3.c index 3c038772..9cca482a 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -85,6 +85,11 @@ s32b CONFUSE; s32b ARMOROFFEAR; s32b STUN; +s32b MAGELOCK; +s32b SLOWMONSTER; +s32b ESSENCESPEED; +s32b BANISHMENT; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua @@ -2624,3 +2629,150 @@ char *mind_stun_info() mind_stun_power()); return buf; } + +bool_ *tempo_magelock() +{ + if (get_level_s(MAGELOCK, 50) >= 30) + { + int x,y; + + if (get_level_s(MAGELOCK, 50) >= 40) + { + cave_type *c_ptr = NULL; + + if (!tgt_pt(&x, &y)) + { + return NO_CAST; + } + + c_ptr = &cave[y][x]; + + if ((!(f_info[c_ptr->feat].flags1 | FF1_FLOOR)) || + (f_info[c_ptr->feat].flags1 | FF1_PERMANENT) || + (!los(p_ptr->py, p_ptr->px, y, x))) + { + msg_print("You cannot place it there."); + return NO_CAST; + } + } else { + y = p_ptr->py; + x = p_ptr->px; + } + cave_set_feat(y, x, 3); + return CAST; + } else { + int dir; + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + wizard_lock(dir); + return CAST; + } +} + +char *tempo_magelock_info() +{ + return ""; +} + +static s32b tempo_slow_monster_power() +{ + return 40 + get_level_s(SLOWMONSTER, 160); +} + +bool_ *tempo_slow_monster() +{ + int dir; + s32b pwr; + + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + pwr = tempo_slow_monster_power(); + if (get_level_s(SLOWMONSTER, 50) >= 20) + { + fire_ball(GF_OLD_SLOW, dir, pwr, 1); + } + else + { + fire_bolt(GF_OLD_SLOW, dir, pwr); + } + + return CAST; +} + +char *tempo_slow_monster_info() +{ + static char buf[128]; + s32b pwr = tempo_slow_monster_power(); + + if (get_level_s(SLOWMONSTER, 50) >= 20) + { + sprintf(buf, "power " FMTs32b " rad 1", pwr); + } + else + { + sprintf(buf, "power " FMTs32b, pwr); + } + return buf; +} + +static s32b tempo_essence_of_speed_base_duration() +{ + return 10 + get_level_s(ESSENCESPEED, 50); +} + +static s32b tempo_essence_of_speed_bonus() +{ + return 5 + get_level_s(ESSENCESPEED, 20); +} + +bool_ *tempo_essence_of_speed() +{ + if (p_ptr->fast == 0) + { + set_fast(randint(10) + tempo_essence_of_speed_base_duration(), + tempo_essence_of_speed_bonus()); + } + return CAST; +} + +char *tempo_essence_of_speed_info() +{ + static char buf[128]; + sprintf(buf, + "dur " FMTs32b "+d10 speed " FMTs32b, + tempo_essence_of_speed_base_duration(), + tempo_essence_of_speed_bonus()); + return buf; +} + +static s32b tempo_banishment_power() +{ + return 40 + get_level_s(BANISHMENT, 160); +} + +bool_ *tempo_banishment() +{ + s32b pwr = tempo_banishment_power(); + + project_hack(GF_AWAY_ALL, pwr); + if (get_level_s(BANISHMENT, 50) >= 15) + { + project_hack(GF_STASIS, 20 + get_level_s(BANISHMENT, 120)); + } + + return CAST; +} + +char *tempo_banishment_info() +{ + static char buf[128]; + sprintf(buf, + "power " FMTs32b, + tempo_banishment_power()); + return buf; +} -- cgit v1.2.3 From 226d3565889f551c00d4fccf184c98edb12c07c7 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 10 May 2012 21:07:52 +0200 Subject: Lua: Move "Tulkas" spell functions to C --- lib/mods/theme/scpt/s_tulkas.lua | 34 ++++------------------- lib/scpt/s_tulkas.lua | 34 ++++------------------- src/externs.h | 11 ++++++++ src/spells.pkg | 11 ++++++++ src/spells3.c | 59 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+), 56 deletions(-) diff --git a/lib/mods/theme/scpt/s_tulkas.lua b/lib/mods/theme/scpt/s_tulkas.lua index 4afa8082..6659aee9 100644 --- a/lib/mods/theme/scpt/s_tulkas.lua +++ b/lib/mods/theme/scpt/s_tulkas.lua @@ -12,19 +12,8 @@ TULKAS_AIM = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local dur = get_level(TULKAS_AIM, 50) + randint(10) - local obvious - - obvious = set_strike(dur) - if get_level(TULKAS_AIM) >= 20 then - obvious = is_obvious(set_tim_deadly(dur), obvious) - end - return obvious - end, - ["info"] = function() - return "dur "..(get_level(TULKAS_AIM, 50)).."+d10" - end, + ["spell"] = function() return tulkas_divine_aim() end, + ["info"] = function() return tulkas_divine_aim_info() end, ["desc"] = { "It makes you more accurate in combat", "At level 20 all your blows are critical hits", @@ -43,15 +32,8 @@ TULKAS_WAVE = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - return fire_bolt(GF_ATTACK, dir, get_level(TULKAS_WAVE, player.num_blow)) - end, - ["info"] = function() - return "blows "..(get_level(TULKAS_WAVE, player.num_blow)) - end, + ["spell"] = function() return tulkas_wave_of_power() end, + ["info"] = function() return tulkas_wave_of_power_info() end, ["desc"] = { "It allows you to project a number of melee blows across a distance", } @@ -69,12 +51,8 @@ TULKAS_SPIN = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - return fire_ball(GF_ATTACK, 0, 1, 1) - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return tulkas_whirlwind() end, + ["info"] = function() return tulkas_whirlwind_info() end, ["desc"] = { "It allows you to spin around and hit all monsters nearby", } diff --git a/lib/scpt/s_tulkas.lua b/lib/scpt/s_tulkas.lua index 4afa8082..6659aee9 100644 --- a/lib/scpt/s_tulkas.lua +++ b/lib/scpt/s_tulkas.lua @@ -12,19 +12,8 @@ TULKAS_AIM = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local dur = get_level(TULKAS_AIM, 50) + randint(10) - local obvious - - obvious = set_strike(dur) - if get_level(TULKAS_AIM) >= 20 then - obvious = is_obvious(set_tim_deadly(dur), obvious) - end - return obvious - end, - ["info"] = function() - return "dur "..(get_level(TULKAS_AIM, 50)).."+d10" - end, + ["spell"] = function() return tulkas_divine_aim() end, + ["info"] = function() return tulkas_divine_aim_info() end, ["desc"] = { "It makes you more accurate in combat", "At level 20 all your blows are critical hits", @@ -43,15 +32,8 @@ TULKAS_WAVE = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - return fire_bolt(GF_ATTACK, dir, get_level(TULKAS_WAVE, player.num_blow)) - end, - ["info"] = function() - return "blows "..(get_level(TULKAS_WAVE, player.num_blow)) - end, + ["spell"] = function() return tulkas_wave_of_power() end, + ["info"] = function() return tulkas_wave_of_power_info() end, ["desc"] = { "It allows you to project a number of melee blows across a distance", } @@ -69,12 +51,8 @@ TULKAS_SPIN = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - return fire_ball(GF_ATTACK, 0, 1, 1) - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return tulkas_whirlwind() end, + ["info"] = function() return tulkas_whirlwind_info() end, ["desc"] = { "It allows you to spin around and hit all monsters nearby", } diff --git a/src/externs.h b/src/externs.h index 6db58e36..dd83e876 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1655,6 +1655,17 @@ char *tempo_essence_of_speed_info(); bool_ *tempo_banishment(); char *tempo_banishment_info(); +extern s32b TULKAS_AIM; +extern s32b TULKAS_WAVE; +extern s32b TULKAS_SPIN; + +bool_ *tulkas_divine_aim(); +char *tulkas_divine_aim_info(); +bool_ *tulkas_wave_of_power(); +char *tulkas_wave_of_power_info(); +bool_ *tulkas_whirlwind(); +char *tulkas_whirlwind_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index eeae6e7d..3b7ce060 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2660,3 +2660,14 @@ bool_ *tempo_essence_of_speed(); char *tempo_essence_of_speed_info(); bool_ *tempo_banishment(); char *tempo_banishment_info(); + +extern s32b TULKAS_AIM; +extern s32b TULKAS_WAVE; +extern s32b TULKAS_SPIN; + +bool_ *tulkas_divine_aim(); +char *tulkas_divine_aim_info(); +bool_ *tulkas_wave_of_power(); +char *tulkas_wave_of_power_info(); +bool_ *tulkas_whirlwind(); +char *tulkas_whirlwind_info(); diff --git a/src/spells3.c b/src/spells3.c index 9cca482a..6220cd25 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -90,6 +90,10 @@ s32b SLOWMONSTER; s32b ESSENCESPEED; s32b BANISHMENT; +s32b TULKAS_AIM; +s32b TULKAS_WAVE; +s32b TULKAS_SPIN; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua @@ -2776,3 +2780,58 @@ char *tempo_banishment_info() tempo_banishment_power()); return buf; } + +bool_ *tulkas_divine_aim() +{ + s32b dur = get_level_s(TULKAS_AIM, 50) + randint(10); + + set_strike(dur); + if (get_level_s(TULKAS_AIM, 50) >= 20) + { + set_tim_deadly(dur); + } + + return CAST; +} + +char *tulkas_divine_aim_info() +{ + static char buf[128]; + sprintf(buf, + "dur " FMTs32b "+d10", + get_level_s(TULKAS_AIM, 50)); + return buf; +} + +bool_ *tulkas_wave_of_power() +{ + int dir; + + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + fire_bolt(GF_ATTACK, dir, get_level_s(TULKAS_WAVE, p_ptr->num_blow)); + return CAST; +} + +char *tulkas_wave_of_power_info() +{ + static char buf[128]; + sprintf(buf, + "blows " FMTs32b, + get_level_s(TULKAS_WAVE, p_ptr->num_blow)); + return buf; +} + +bool_ *tulkas_whirlwind() +{ + fire_ball(GF_ATTACK, 0, 1, 1); + return CAST; +} + +char *tulkas_whirlwind_info() +{ + return ""; +} -- cgit v1.2.3 From 0f3e84929038eeff1135bd7462347be64ac9fc71 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 12 May 2012 12:32:36 +0200 Subject: Lua: Move "Udun" spell functions to C --- lib/mods/theme/scpt/s_udun.lua | 83 +++------------------- lib/scpt/s_udun.lua | 83 +++------------------- src/cmd2.c | 4 +- src/externs.h | 16 +++++ src/spells.pkg | 14 ++++ src/spells3.c | 152 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 201 insertions(+), 151 deletions(-) diff --git a/lib/mods/theme/scpt/s_udun.lua b/lib/mods/theme/scpt/s_udun.lua index c4266239..3ddfeb14 100644 --- a/lib/mods/theme/scpt/s_udun.lua +++ b/lib/mods/theme/scpt/s_udun.lua @@ -8,49 +8,8 @@ DRAIN = add_spell ["mana"] = 0, ["mana_max"] = 0, ["fail"] = 20, - ["spell"] = function() - local ret, item, obj, o_name, add - - -- Ask for an item - ret, item = get_item("What item to drain?", "You have nothing you can drain", USE_INVEN, - function (obj) - if (obj.tval == TV_WAND) or (obj.tval == TV_ROD_MAIN) or (obj.tval == TV_STAFF) then - return TRUE - end - return FALSE - end - ) - - if ret == TRUE then - -- get the item - obj = get_object(item) - - add = 0 - if (obj.tval == TV_STAFF) or (obj.tval == TV_WAND) then - local kind = get_kind(obj) - - add = kind.level * obj.pval * obj.number - - -- Destroy it! - inven_item_increase(item, -99) - inven_item_describe(item) - inven_item_optimize(item) - end - if obj.tval == TV_ROD_MAIN then - add = obj.timeout - obj.timeout = 0; - - --Combine / Reorder the pack (later) - player.notice = bor(player.notice, PN_COMBINE, PN_REORDER) - player.window = bor(player.window, PW_INVEN, PW_EQUIP, PW_PLAYER) - end - increase_mana(add) - end - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return udun_drain() end, + ["info"] = function() return udun_drain_info() end, ["desc"] = { "Drains the mana contained in wands, staves and rods to increase yours", } @@ -74,26 +33,8 @@ GENOCIDE = add_spell ["max_level"] = { 5, 15 }, }, }, - ["spell"] = function() - local type - - type = 0 - if get_level(GENOCIDE) >= 10 then type = 1 end - if type == 0 then - genocide(TRUE) - return TRUE - else - if get_check("Genocide all monsters near you? ") == TRUE then - mass_genocide(TRUE) - else - genocide(TRUE) - end - return TRUE - end - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return udun_genocide() end, + ["info"] = function() return udun_genocide_info() end, ["desc"] = { "Genocides all monsters of a race on the level", "At level 10 it can genocide all monsters near you" @@ -109,12 +50,8 @@ WRAITHFORM = add_spell ["mana_max"] = 40, ["fail"] = 95, ["inertia"] = { 4, 30 }, - ["spell"] = function() - return set_shadow(randint(30) + 20 + get_level(WRAITHFORM, 40)) - end, - ["info"] = function() - return "dur "..(20 + get_level(WRAITHFORM, 40)).."+d30" - end, + ["spell"] = function() return udun_wraithform() end, + ["info"] = function() return udun_wraithform_info() end, ["desc"] = { "Turns you into an immaterial being", } @@ -129,12 +66,8 @@ FLAMEOFUDUN = add_spell ["mana_max"] = 100, ["fail"] = 95, ["inertia"] = { 7, 15 }, - ["spell"] = function() - return set_mimic(randint(15) + 5 + get_level(FLAMEOFUDUN, 30), resolve_mimic_name("Balrog"), get_level(FLAMEOFUDUN)) - end, - ["info"] = function() - return "dur "..(5 + get_level(FLAMEOFUDUN, 30)).."+d15" - end, + ["spell"] = function() return udun_flame_of_udun() end, + ["info"] = function() return udun_flame_of_udun_info() end, ["desc"] = { "Turns you into a powerful Balrog", } diff --git a/lib/scpt/s_udun.lua b/lib/scpt/s_udun.lua index c4266239..3ddfeb14 100644 --- a/lib/scpt/s_udun.lua +++ b/lib/scpt/s_udun.lua @@ -8,49 +8,8 @@ DRAIN = add_spell ["mana"] = 0, ["mana_max"] = 0, ["fail"] = 20, - ["spell"] = function() - local ret, item, obj, o_name, add - - -- Ask for an item - ret, item = get_item("What item to drain?", "You have nothing you can drain", USE_INVEN, - function (obj) - if (obj.tval == TV_WAND) or (obj.tval == TV_ROD_MAIN) or (obj.tval == TV_STAFF) then - return TRUE - end - return FALSE - end - ) - - if ret == TRUE then - -- get the item - obj = get_object(item) - - add = 0 - if (obj.tval == TV_STAFF) or (obj.tval == TV_WAND) then - local kind = get_kind(obj) - - add = kind.level * obj.pval * obj.number - - -- Destroy it! - inven_item_increase(item, -99) - inven_item_describe(item) - inven_item_optimize(item) - end - if obj.tval == TV_ROD_MAIN then - add = obj.timeout - obj.timeout = 0; - - --Combine / Reorder the pack (later) - player.notice = bor(player.notice, PN_COMBINE, PN_REORDER) - player.window = bor(player.window, PW_INVEN, PW_EQUIP, PW_PLAYER) - end - increase_mana(add) - end - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return udun_drain() end, + ["info"] = function() return udun_drain_info() end, ["desc"] = { "Drains the mana contained in wands, staves and rods to increase yours", } @@ -74,26 +33,8 @@ GENOCIDE = add_spell ["max_level"] = { 5, 15 }, }, }, - ["spell"] = function() - local type - - type = 0 - if get_level(GENOCIDE) >= 10 then type = 1 end - if type == 0 then - genocide(TRUE) - return TRUE - else - if get_check("Genocide all monsters near you? ") == TRUE then - mass_genocide(TRUE) - else - genocide(TRUE) - end - return TRUE - end - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return udun_genocide() end, + ["info"] = function() return udun_genocide_info() end, ["desc"] = { "Genocides all monsters of a race on the level", "At level 10 it can genocide all monsters near you" @@ -109,12 +50,8 @@ WRAITHFORM = add_spell ["mana_max"] = 40, ["fail"] = 95, ["inertia"] = { 4, 30 }, - ["spell"] = function() - return set_shadow(randint(30) + 20 + get_level(WRAITHFORM, 40)) - end, - ["info"] = function() - return "dur "..(20 + get_level(WRAITHFORM, 40)).."+d30" - end, + ["spell"] = function() return udun_wraithform() end, + ["info"] = function() return udun_wraithform_info() end, ["desc"] = { "Turns you into an immaterial being", } @@ -129,12 +66,8 @@ FLAMEOFUDUN = add_spell ["mana_max"] = 100, ["fail"] = 95, ["inertia"] = { 7, 15 }, - ["spell"] = function() - return set_mimic(randint(15) + 5 + get_level(FLAMEOFUDUN, 30), resolve_mimic_name("Balrog"), get_level(FLAMEOFUDUN)) - end, - ["info"] = function() - return "dur "..(5 + get_level(FLAMEOFUDUN, 30)).."+d15" - end, + ["spell"] = function() return udun_flame_of_udun() end, + ["info"] = function() return udun_flame_of_udun_info() end, ["desc"] = { "Turns you into a powerful Balrog", } diff --git a/src/cmd2.c b/src/cmd2.c index 8c602db3..828cbc35 100644 --- a/src/cmd2.c +++ b/src/cmd2.c @@ -4565,8 +4565,10 @@ static bool_ item_tester_hook_sacrifiable(object_type *o_ptr) return (TRUE); /* Books without any udun spells */ - if ((o_ptr->tval == TV_BOOK) && (exec_lua(format("return udun_in_book(%d, %d)", o_ptr->sval, o_ptr->pval)) == 0)) + if ((o_ptr->tval == TV_BOOK) && udun_in_book(o_ptr->sval, o_ptr->pval) <= 0) + { return TRUE; + } } /* Assume not */ diff --git a/src/externs.h b/src/externs.h index dd83e876..4395848e 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1666,6 +1666,22 @@ char *tulkas_wave_of_power_info(); bool_ *tulkas_whirlwind(); char *tulkas_whirlwind_info(); +extern s32b DRAIN; +extern s32b GENOCIDE; +extern s32b WRAITHFORM; +extern s32b FLAMEOFUDUN; + +int udun_in_book(s32b sval, s32b pval); + +bool_ *udun_drain(); +char *udun_drain_info(); +bool_ *udun_genocide(); +char *udun_genocide_info(); +bool_ *udun_wraithform(); +char *udun_wraithform_info(); +bool_ *udun_flame_of_udun(); +char *udun_flame_of_udun_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index 3b7ce060..034f2cd4 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2671,3 +2671,17 @@ bool_ *tulkas_wave_of_power(); char *tulkas_wave_of_power_info(); bool_ *tulkas_whirlwind(); char *tulkas_whirlwind_info(); + +extern s32b DRAIN; +extern s32b GENOCIDE; +extern s32b WRAITHFORM; +extern s32b FLAMEOFUDUN; + +bool_ *udun_drain(); +char *udun_drain_info(); +bool_ *udun_genocide(); +char *udun_genocide_info(); +bool_ *udun_wraithform(); +char *udun_wraithform_info(); +bool_ *udun_flame_of_udun(); +char *udun_flame_of_udun_info(); diff --git a/src/spells3.c b/src/spells3.c index 6220cd25..39517b5e 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -94,6 +94,11 @@ s32b TULKAS_AIM; s32b TULKAS_WAVE; s32b TULKAS_SPIN; +s32b DRAIN; +s32b GENOCIDE; +s32b WRAITHFORM; +s32b FLAMEOFUDUN; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua @@ -2835,3 +2840,150 @@ char *tulkas_whirlwind_info() { return ""; } + +/* Return the number of Udun/Melkor spells in a given book */ +int udun_in_book(s32b sval, s32b pval) +{ + char buf[128]; + sprintf(buf, "return udun_in_book(" FMTs32b "," FMTs32b ")", + sval, pval); + return exec_lua(buf); +} + +static bool_ udun_object_is_drainable(object_type *o_ptr) +{ + return ((o_ptr->tval == TV_WAND) || + (o_ptr->tval == TV_ROD_MAIN) || + (o_ptr->tval == TV_STAFF)); +} + +bool_ *udun_drain() +{ + int item; + object_type *o_ptr = NULL; + + /* Ask for an item */ + item_tester_hook = udun_object_is_drainable; + if (!get_item(&item, + "What item to drain?", + "You have nothing you can drain", + USE_INVEN)) + { + return NO_CAST; + } + + /* Drain */ + + /* get the item */ + o_ptr = get_object(item); + + switch (o_ptr->tval) + { + case TV_STAFF: + case TV_WAND: + { + object_kind *k_ptr = &k_info[o_ptr->k_idx]; + + /* Generate mana */ + increase_mana(o_ptr->pval * k_ptr->level * o_ptr->number); + + /* Destroy it */ + inc_stack_size(item, -99); + + break; + } + + case TV_ROD_MAIN: + { + /* Generate mana */ + increase_mana(o_ptr->timeout); + + /* Drain it */ + o_ptr->timeout = 0; + + /* Combine / Reorder the pack (later) */ + p_ptr->notice |= PN_COMBINE | PN_REORDER; + p_ptr->window |= PW_INVEN | PW_EQUIP | PW_PLAYER; + break; + } + + default: + assert(FALSE); + } + + return CAST; +} + +char *udun_drain_info() +{ + return ""; +} + +bool_ *udun_genocide() +{ + if (get_level_s(GENOCIDE, 50) < 10) + { + genocide(TRUE); + } + else + { + if (get_check("Genocide all monsters near you? ")) + { + mass_genocide(TRUE); + } + else + { + genocide(TRUE); + } + } + + return CAST; +} + +char *udun_genocide_info() +{ + return ""; +} + +static int udun_wraithform_base_duration() +{ + return 20 + get_level_s(WRAITHFORM, 40); +} + +bool_ *udun_wraithform() +{ + set_shadow(randint(30) + udun_wraithform_base_duration()); + return CAST; +} + +char *udun_wraithform_info() +{ + static char buf[128]; + sprintf(buf, + "dur %d+d30", + udun_wraithform_base_duration()); + return buf; +} + +static int udun_flame_of_udun_base_duration() +{ + return 5 + get_level_s(FLAMEOFUDUN, 30); +} + +bool_ *udun_flame_of_udun() +{ + set_mimic(randint(15) + udun_flame_of_udun_base_duration(), + resolve_mimic_name("Balrog"), + get_level_s(FLAMEOFUDUN, 50)); + return CAST; +} + +char *udun_flame_of_udun_info() +{ + static char buf[128]; + sprintf(buf, + "dur %d+d15", + udun_flame_of_udun_base_duration()); + return buf; +} + -- cgit v1.2.3 From 363eb2f7405a66b496641d77aaa0b8a3d6c63384 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 12 May 2012 13:09:43 +0200 Subject: Lua: Move "Water" spell functions to C --- lib/mods/theme/scpt/s_ulmo.lua | 8 +- lib/mods/theme/scpt/s_water.lua | 68 +++----------- lib/scpt/s_water.lua | 68 +++----------- src/externs.h | 17 ++++ src/spells.pkg | 17 ++++ src/spells3.c | 195 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 255 insertions(+), 118 deletions(-) diff --git a/lib/mods/theme/scpt/s_ulmo.lua b/lib/mods/theme/scpt/s_ulmo.lua index a2c24b29..81f5f739 100644 --- a/lib/mods/theme/scpt/s_ulmo.lua +++ b/lib/mods/theme/scpt/s_ulmo.lua @@ -2,6 +2,10 @@ BOOK_ULMO = 65 +function get_belegaer_damage() + return get_level(ULMO_BELEGAER, 10), 3 + get_level(ULMO_BELEGAER, 35) +end + -- "Song of Belegaer" copied from Geyser ULMO_BELEGAER = add_spell { @@ -18,11 +22,11 @@ ULMO_BELEGAER = add_spell local ret, dir ret, dir = get_aim_dir() if ret == FALSE then return end - return fire_bolt_or_beam(2 * get_level(ULMO_BELEGAER, 85), GF_WATER, dir, damroll(get_geyser_damage())) + return fire_bolt_or_beam(2 * get_level(ULMO_BELEGAER, 85), GF_WATER, dir, damroll(get_belegaer_damage())) end, ["info"] = function() local n, d - n, d = get_geyser_damage() + n, d = get_belegaer_damage() return "dam "..n.."d"..d end, ["desc"] = diff --git a/lib/mods/theme/scpt/s_water.lua b/lib/mods/theme/scpt/s_water.lua index 739b066b..46942c5d 100644 --- a/lib/mods/theme/scpt/s_water.lua +++ b/lib/mods/theme/scpt/s_water.lua @@ -19,13 +19,8 @@ TIDALWAVE = add_spell }, }, ["inertia"] = { 4, 100 }, - ["spell"] = function() - fire_wave(GF_WAVE, 0, 40 + get_level(TIDALWAVE, 200), 0, 6 + get_level(TIDALWAVE, 10), EFF_WAVE) - return TRUE - end, - ["info"] = function() - return "dam "..(40 + get_level(TIDALWAVE, 200)).." rad "..(6 + get_level(TIDALWAVE, 10)) - end, + ["spell"] = function() return water_tidal_wave() end, + ["info"] = function() return water_tidal_wave_info() end, ["desc"] = { "Summons a monstrous tidal wave that will expand and crush the", "monsters under its mighty waves." @@ -51,17 +46,8 @@ ICESTORM = add_spell }, }, ["inertia"] = { 3, 40 }, - ["spell"] = function() - local type - - if get_level(ICESTORM, 50) >= 10 then type = GF_ICE - else type = GF_COLD end - fire_wave(type, 0, 80 + get_level(ICESTORM, 200), 1 + get_level(ICESTORM, 3, 0), 20 + get_level(ICESTORM, 70), EFF_STORM) - return TRUE - end, - ["info"] = function() - return "dam "..(80 + get_level(ICESTORM, 200)).." rad "..(1 + get_level(ICESTORM, 3, 0)).." dur "..(20 + get_level(ICESTORM, 70)) - end, + ["spell"] = function() return water_ice_storm() end, + ["info"] = function() return water_ice_storm_info() end, ["desc"] = { "Engulfs you in a storm of roaring cold that strikes your foes.", "At level 10 it turns into shards of ice." @@ -77,24 +63,8 @@ ENTPOTION = add_spell ["mana_max"] = 15, ["fail"] = 35, ["inertia"] = { 1, 30 }, - ["spell"] = function() - set_food(PY_FOOD_MAX - 1) - msg_print("The Ent's Potion fills your stomach.") - if get_level(ENTPOTION, 50) >= 5 then - set_afraid(0) - end - if get_level(ENTPOTION, 50) >= 12 then - set_hero(player.hero + randint(25) + 25 + get_level(ENTPOTION, 40)) - end - return TRUE - end, - ["info"] = function() - if get_level(ENTPOTION, 50) >= 12 then - return "dur "..(25 + get_level(ENTPOTION, 40)).."+d25" - else - return "" - end - end, + ["spell"] = function() return water_ent_potion() end, + ["info"] = function() return water_ent_potion_info() end, ["desc"] = { "Fills up your stomach.", "At level 5 it boldens your heart.", @@ -111,22 +81,13 @@ VAPOR = add_spell ["mana_max"] = 12, ["fail"] = 20, ["inertia"] = { 1, 30 }, - ["spell"] = function() - fire_cloud(GF_WATER, 0, 3 + get_level(VAPOR, 20), 3 + get_level(VAPOR, 9, 0), 5) - return TRUE - end, - ["info"] = function() - return "dam "..(3 + get_level(VAPOR, 20)).." rad "..(3 + get_level(VAPOR, 9, 0)).." dur 5" - end, + ["spell"] = function() return water_vapor() end, + ["info"] = function() return water_vapor_info() end, ["desc"] = { "Fills the air with toxic moisture to eradicate annoying critters." } } -function get_geyser_damage() - return get_level(GEYSER, 10), 3 + get_level(GEYSER, 35) -end - GEYSER = add_spell { ["name"] = "Geyser", @@ -135,17 +96,8 @@ GEYSER = add_spell ["mana"] = 1, ["mana_max"] = 35, ["fail"] = 5, - ["spell"] = function() - local ret, dir - ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_bolt_or_beam(2 * get_level(GEYSER, 85), GF_WATER, dir, damroll(get_geyser_damage())) - end, - ["info"] = function() - local n, d - n, d = get_geyser_damage() - return "dam "..n.."d"..d - end, + ["spell"] = function() return water_geyser() end, + ["info"] = function() return water_geyser_info() end, ["desc"] = { "Shoots a geyser of water from your fingertips.", diff --git a/lib/scpt/s_water.lua b/lib/scpt/s_water.lua index 739b066b..46942c5d 100644 --- a/lib/scpt/s_water.lua +++ b/lib/scpt/s_water.lua @@ -19,13 +19,8 @@ TIDALWAVE = add_spell }, }, ["inertia"] = { 4, 100 }, - ["spell"] = function() - fire_wave(GF_WAVE, 0, 40 + get_level(TIDALWAVE, 200), 0, 6 + get_level(TIDALWAVE, 10), EFF_WAVE) - return TRUE - end, - ["info"] = function() - return "dam "..(40 + get_level(TIDALWAVE, 200)).." rad "..(6 + get_level(TIDALWAVE, 10)) - end, + ["spell"] = function() return water_tidal_wave() end, + ["info"] = function() return water_tidal_wave_info() end, ["desc"] = { "Summons a monstrous tidal wave that will expand and crush the", "monsters under its mighty waves." @@ -51,17 +46,8 @@ ICESTORM = add_spell }, }, ["inertia"] = { 3, 40 }, - ["spell"] = function() - local type - - if get_level(ICESTORM, 50) >= 10 then type = GF_ICE - else type = GF_COLD end - fire_wave(type, 0, 80 + get_level(ICESTORM, 200), 1 + get_level(ICESTORM, 3, 0), 20 + get_level(ICESTORM, 70), EFF_STORM) - return TRUE - end, - ["info"] = function() - return "dam "..(80 + get_level(ICESTORM, 200)).." rad "..(1 + get_level(ICESTORM, 3, 0)).." dur "..(20 + get_level(ICESTORM, 70)) - end, + ["spell"] = function() return water_ice_storm() end, + ["info"] = function() return water_ice_storm_info() end, ["desc"] = { "Engulfs you in a storm of roaring cold that strikes your foes.", "At level 10 it turns into shards of ice." @@ -77,24 +63,8 @@ ENTPOTION = add_spell ["mana_max"] = 15, ["fail"] = 35, ["inertia"] = { 1, 30 }, - ["spell"] = function() - set_food(PY_FOOD_MAX - 1) - msg_print("The Ent's Potion fills your stomach.") - if get_level(ENTPOTION, 50) >= 5 then - set_afraid(0) - end - if get_level(ENTPOTION, 50) >= 12 then - set_hero(player.hero + randint(25) + 25 + get_level(ENTPOTION, 40)) - end - return TRUE - end, - ["info"] = function() - if get_level(ENTPOTION, 50) >= 12 then - return "dur "..(25 + get_level(ENTPOTION, 40)).."+d25" - else - return "" - end - end, + ["spell"] = function() return water_ent_potion() end, + ["info"] = function() return water_ent_potion_info() end, ["desc"] = { "Fills up your stomach.", "At level 5 it boldens your heart.", @@ -111,22 +81,13 @@ VAPOR = add_spell ["mana_max"] = 12, ["fail"] = 20, ["inertia"] = { 1, 30 }, - ["spell"] = function() - fire_cloud(GF_WATER, 0, 3 + get_level(VAPOR, 20), 3 + get_level(VAPOR, 9, 0), 5) - return TRUE - end, - ["info"] = function() - return "dam "..(3 + get_level(VAPOR, 20)).." rad "..(3 + get_level(VAPOR, 9, 0)).." dur 5" - end, + ["spell"] = function() return water_vapor() end, + ["info"] = function() return water_vapor_info() end, ["desc"] = { "Fills the air with toxic moisture to eradicate annoying critters." } } -function get_geyser_damage() - return get_level(GEYSER, 10), 3 + get_level(GEYSER, 35) -end - GEYSER = add_spell { ["name"] = "Geyser", @@ -135,17 +96,8 @@ GEYSER = add_spell ["mana"] = 1, ["mana_max"] = 35, ["fail"] = 5, - ["spell"] = function() - local ret, dir - ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_bolt_or_beam(2 * get_level(GEYSER, 85), GF_WATER, dir, damroll(get_geyser_damage())) - end, - ["info"] = function() - local n, d - n, d = get_geyser_damage() - return "dam "..n.."d"..d - end, + ["spell"] = function() return water_geyser() end, + ["info"] = function() return water_geyser_info() end, ["desc"] = { "Shoots a geyser of water from your fingertips.", diff --git a/src/externs.h b/src/externs.h index 4395848e..20567d99 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1682,6 +1682,23 @@ char *udun_wraithform_info(); bool_ *udun_flame_of_udun(); char *udun_flame_of_udun_info(); +extern s32b TIDALWAVE; +extern s32b ICESTORM; +extern s32b ENTPOTION; +extern s32b VAPOR; +extern s32b GEYSER; + +bool_ *water_tidal_wave(); +char *water_tidal_wave_info(); +bool_ *water_ice_storm(); +char *water_ice_storm_info(); +bool_ *water_ent_potion(); +char *water_ent_potion_info(); +bool_ *water_vapor(); +char *water_vapor_info(); +bool_ *water_geyser(); +char *water_geyser_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index 034f2cd4..779a63d4 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2685,3 +2685,20 @@ bool_ *udun_wraithform(); char *udun_wraithform_info(); bool_ *udun_flame_of_udun(); char *udun_flame_of_udun_info(); + +extern s32b TIDALWAVE; +extern s32b ICESTORM; +extern s32b ENTPOTION; +extern s32b VAPOR; +extern s32b GEYSER; + +bool_ *water_tidal_wave(); +char *water_tidal_wave_info(); +bool_ *water_ice_storm(); +char *water_ice_storm_info(); +bool_ *water_ent_potion(); +char *water_ent_potion_info(); +bool_ *water_vapor(); +char *water_vapor_info(); +bool_ *water_geyser(); +char *water_geyser_info(); diff --git a/src/spells3.c b/src/spells3.c index 39517b5e..7fa9d728 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -99,6 +99,12 @@ s32b GENOCIDE; s32b WRAITHFORM; s32b FLAMEOFUDUN; +s32b TIDALWAVE; +s32b ICESTORM; +s32b ENTPOTION; +s32b VAPOR; +s32b GEYSER; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua @@ -2987,3 +2993,192 @@ char *udun_flame_of_udun_info() return buf; } +static int tidal_wave_damage() +{ + return 40 + get_level_s(TIDALWAVE, 200); +} + +static int tidal_wave_duration() +{ + return 6 + get_level_s(TIDALWAVE, 10); +} + +bool_ *water_tidal_wave() +{ + fire_wave(GF_WAVE, + 0, + tidal_wave_damage(), + 0, + tidal_wave_duration(), + EFF_WAVE); + return CAST; +} + +char *water_tidal_wave_info() +{ + static char buf[128]; + sprintf(buf, + "dam %d dur %d", + tidal_wave_damage(), + tidal_wave_duration()); + return buf; +} + +static int water_ice_storm_damage() +{ + return 80 + get_level_s(ICESTORM, 200); +} + +static int water_ice_storm_radius() +{ + return 1 + get_level(ICESTORM, 3, 0); +} + +static int water_ice_storm_duration() +{ + return 20 + get_level_s(ICESTORM, 70); +} + +bool_ *water_ice_storm() +{ + int type = GF_COLD; + + if (get_level_s(ICESTORM, 50) >= 10) + { + type = GF_ICE; + } + + fire_wave(type, + 0, + water_ice_storm_damage(), + water_ice_storm_radius(), + water_ice_storm_duration(), + EFF_STORM); + + return CAST; +} + +char *water_ice_storm_info() +{ + static char buf[128]; + sprintf(buf, + "dam %d rad %d dur %d", + water_ice_storm_damage(), + water_ice_storm_radius(), + water_ice_storm_duration()); + return buf; +} + +static int water_ent_potion_base_duration() +{ + return 25 + get_level_s(ENTPOTION, 40);; +} + +bool_ *water_ent_potion() +{ + set_food(PY_FOOD_MAX - 1); + msg_print("The Ent's Potion fills your stomach."); + + if (get_level_s(ENTPOTION, 50) >= 5) + { + set_afraid(0); + } + if (get_level_s(ENTPOTION, 50) >= 12) + { + set_hero(p_ptr->hero + randint(25) + water_ent_potion_base_duration()); + } + + return CAST; +} + +char *water_ent_potion_info() +{ + if (get_level_s(ENTPOTION, 50) >= 12) + { + static char buf[128]; + sprintf(buf, + "dur %d+d25", + water_ent_potion_base_duration()); + return buf; + } + else + { + return ""; + } +} + +static int water_vapor_damage() +{ + return 3 + get_level_s(VAPOR, 20); +} + +static int water_vapor_radius() +{ + return 3 + get_level(VAPOR, 9, 0); +} + +static int water_vapor_duration() +{ + return 5; +} + +bool_ *water_vapor() +{ + fire_cloud(GF_WATER, + 0, + water_vapor_damage(), + water_vapor_radius(), + water_vapor_duration()); + return CAST; +} + +char *water_vapor_info() +{ + static char buf[128]; + sprintf(buf, + "dam %d rad %d dur %d", + water_vapor_damage(), + water_vapor_radius(), + water_vapor_duration()); + return buf; +} + +static void get_geyser_damage(int *dice, int *sides) +{ + assert(dice != NULL); + assert(sides != NULL); + + *dice = get_level_s(GEYSER, 10); + *sides = 3 + get_level_s(GEYSER, 35); +} + +bool_ *water_geyser() +{ + int dir, dice, sides; + + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + get_geyser_damage(&dice, &sides); + fire_bolt_or_beam(2 * get_level_s(GEYSER, 85), + GF_WATER, + dir, + damroll(dice, sides)); + return CAST; +} + +char *water_geyser_info() +{ + static char buf[128]; + int dice, sides; + + get_geyser_damage(&dice, &sides); + + sprintf(buf, + "dam %dd%d", + dice, + sides); + return buf; +} -- cgit v1.2.3 From 2ead486354a2934f3d3e4e2ebb86e95653ee4b23 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 12 May 2012 14:55:09 +0200 Subject: Lua: Move "Yavanna" spell functions to C --- lib/mods/theme/scpt/s_yavann.lua | 77 ++-------------- lib/scpt/s_yavann.lua | 77 ++-------------- src/externs.h | 17 ++++ src/spells.pkg | 17 ++++ src/spells3.c | 192 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 246 insertions(+), 134 deletions(-) diff --git a/lib/mods/theme/scpt/s_yavann.lua b/lib/mods/theme/scpt/s_yavann.lua index 2f594e85..a2b2fe1c 100644 --- a/lib/mods/theme/scpt/s_yavann.lua +++ b/lib/mods/theme/scpt/s_yavann.lua @@ -12,15 +12,8 @@ YAVANNA_CHARM_ANIMAL = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - return fire_ball(GF_CONTROL_ANIMAL, dir, 10 + get_level(YAVANNA_CHARM_ANIMAL, 170), get_level(YAVANNA_CHARM_ANIMAL, 2)) - end, - ["info"] = function() - return "power "..(10 + get_level(YAVANNA_CHARM_ANIMAL, 170)).." rad "..(get_level(YAVANNA_CHARM_ANIMAL, 2)) - end, + ["spell"] = function() return yavanna_charm_animal() end, + ["info"] = function() return yavanna_charm_animal_info() end, ["desc"] = { "It tries to tame an animal", } @@ -38,13 +31,8 @@ YAVANNA_GROW_GRASS = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - grow_grass(get_level(YAVANNA_GROW_GRASS, 4)) - return TRUE - end, - ["info"] = function() - return "rad "..(get_level(YAVANNA_GROW_GRASS, 4)) - end, + ["spell"] = function() return yavanna_grow_grass() end, + ["info"] = function() return yavanna_grow_grass_info() end, ["desc"] = { "Create a floor of grass around you. While on grass and praying", "a worshipper of Yavanna will know a greater regeneration rate" @@ -63,12 +51,8 @@ YAVANNA_TREE_ROOTS = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - return set_roots(10 + get_level(YAVANNA_TREE_ROOTS, 30), 10 + get_level(YAVANNA_TREE_ROOTS, 60), 10 + get_level(YAVANNA_TREE_ROOTS, 20)) - end, - ["info"] = function() - return "dur "..(10 + get_level(YAVANNA_TREE_ROOTS, 30)).." AC "..(10 + get_level(YAVANNA_TREE_ROOTS, 60)).." dam "..(10 + get_level(YAVANNA_TREE_ROOTS, 20)) - end, + ["spell"] = function() return yavanna_tree_roots() end, + ["info"] = function() return yavanna_tree_roots_info() end, ["desc"] = { "Creates roots deep in the floor from your feet, making you more stable and able", "to make stronger attacks, but prevents any movement (even teleportation).", @@ -88,21 +72,8 @@ YAVANNA_WATER_BITE = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local rad - - rad = 0 - if get_level(YAVANNA_WATER_BITE) >= 25 then rad = 1 end - - return set_project(randint(30) + 30 + get_level(YAVANNA_WATER_BITE, 150), - GF_WATER, - 10 + get_level(YAVANNA_WATER_BITE), - rad, - bor(PROJECT_STOP, PROJECT_KILL)) - end, - ["info"] = function() - return "dur "..(30 + get_level(YAVANNA_WATER_BITE, 150)).."+d30 dam "..(10 + get_level(YAVANNA_WATER_BITE)).."/blow" - end, + ["spell"] = function() return yavanna_water_bite() end, + ["info"] = function() return yavanna_water_bite_info() end, ["desc"] = { "Imbues your melee weapon with a natural stream of water", "At level 25, it spreads over a 1 radius zone around your target" @@ -121,36 +92,8 @@ YAVANNA_UPROOT = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local m_idx, x, y, c_ptr, ret, dir - - ret, dir = get_rep_dir() - if ret == FALSE then return end - y, x = explode_dir(dir) - y, x = y + player.py, x + player.px - c_ptr = cave(y, x) - - if c_ptr.feat == FEAT_TREES then - cave_set_feat(y, x, FEAT_GRASS); - - -- Summon it - y, x = find_position(y, x) - m_idx = place_monster_one(y, x, test_monster_name("Ent"), 0, FALSE, MSTATUS_FRIEND) - - -- level it - if m_idx ~= 0 then - monster_set_level(m_idx, 30 + get_level(YAVANNA_UPROOT, 70)) - end - - msg_print("The tree awakes!"); - else - msg_print("There is no tree there.") - end - return TRUE - end, - ["info"] = function() - return "lev "..(30 + get_level(YAVANNA_UPROOT, 70)) - end, + ["spell"] = function() return yavanna_uproot() end, + ["info"] = function() return yavanna_uproot_info() end, ["desc"] = { "Awakes a tree to help you battle the forces of Morgoth", } diff --git a/lib/scpt/s_yavann.lua b/lib/scpt/s_yavann.lua index 2f594e85..a2b2fe1c 100644 --- a/lib/scpt/s_yavann.lua +++ b/lib/scpt/s_yavann.lua @@ -12,15 +12,8 @@ YAVANNA_CHARM_ANIMAL = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - return fire_ball(GF_CONTROL_ANIMAL, dir, 10 + get_level(YAVANNA_CHARM_ANIMAL, 170), get_level(YAVANNA_CHARM_ANIMAL, 2)) - end, - ["info"] = function() - return "power "..(10 + get_level(YAVANNA_CHARM_ANIMAL, 170)).." rad "..(get_level(YAVANNA_CHARM_ANIMAL, 2)) - end, + ["spell"] = function() return yavanna_charm_animal() end, + ["info"] = function() return yavanna_charm_animal_info() end, ["desc"] = { "It tries to tame an animal", } @@ -38,13 +31,8 @@ YAVANNA_GROW_GRASS = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - grow_grass(get_level(YAVANNA_GROW_GRASS, 4)) - return TRUE - end, - ["info"] = function() - return "rad "..(get_level(YAVANNA_GROW_GRASS, 4)) - end, + ["spell"] = function() return yavanna_grow_grass() end, + ["info"] = function() return yavanna_grow_grass_info() end, ["desc"] = { "Create a floor of grass around you. While on grass and praying", "a worshipper of Yavanna will know a greater regeneration rate" @@ -63,12 +51,8 @@ YAVANNA_TREE_ROOTS = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - return set_roots(10 + get_level(YAVANNA_TREE_ROOTS, 30), 10 + get_level(YAVANNA_TREE_ROOTS, 60), 10 + get_level(YAVANNA_TREE_ROOTS, 20)) - end, - ["info"] = function() - return "dur "..(10 + get_level(YAVANNA_TREE_ROOTS, 30)).." AC "..(10 + get_level(YAVANNA_TREE_ROOTS, 60)).." dam "..(10 + get_level(YAVANNA_TREE_ROOTS, 20)) - end, + ["spell"] = function() return yavanna_tree_roots() end, + ["info"] = function() return yavanna_tree_roots_info() end, ["desc"] = { "Creates roots deep in the floor from your feet, making you more stable and able", "to make stronger attacks, but prevents any movement (even teleportation).", @@ -88,21 +72,8 @@ YAVANNA_WATER_BITE = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local rad - - rad = 0 - if get_level(YAVANNA_WATER_BITE) >= 25 then rad = 1 end - - return set_project(randint(30) + 30 + get_level(YAVANNA_WATER_BITE, 150), - GF_WATER, - 10 + get_level(YAVANNA_WATER_BITE), - rad, - bor(PROJECT_STOP, PROJECT_KILL)) - end, - ["info"] = function() - return "dur "..(30 + get_level(YAVANNA_WATER_BITE, 150)).."+d30 dam "..(10 + get_level(YAVANNA_WATER_BITE)).."/blow" - end, + ["spell"] = function() return yavanna_water_bite() end, + ["info"] = function() return yavanna_water_bite_info() end, ["desc"] = { "Imbues your melee weapon with a natural stream of water", "At level 25, it spreads over a 1 radius zone around your target" @@ -121,36 +92,8 @@ YAVANNA_UPROOT = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local m_idx, x, y, c_ptr, ret, dir - - ret, dir = get_rep_dir() - if ret == FALSE then return end - y, x = explode_dir(dir) - y, x = y + player.py, x + player.px - c_ptr = cave(y, x) - - if c_ptr.feat == FEAT_TREES then - cave_set_feat(y, x, FEAT_GRASS); - - -- Summon it - y, x = find_position(y, x) - m_idx = place_monster_one(y, x, test_monster_name("Ent"), 0, FALSE, MSTATUS_FRIEND) - - -- level it - if m_idx ~= 0 then - monster_set_level(m_idx, 30 + get_level(YAVANNA_UPROOT, 70)) - end - - msg_print("The tree awakes!"); - else - msg_print("There is no tree there.") - end - return TRUE - end, - ["info"] = function() - return "lev "..(30 + get_level(YAVANNA_UPROOT, 70)) - end, + ["spell"] = function() return yavanna_uproot() end, + ["info"] = function() return yavanna_uproot_info() end, ["desc"] = { "Awakes a tree to help you battle the forces of Morgoth", } diff --git a/src/externs.h b/src/externs.h index 20567d99..c19a83ed 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1699,6 +1699,23 @@ char *water_vapor_info(); bool_ *water_geyser(); char *water_geyser_info(); +extern s32b YAVANNA_CHARM_ANIMAL; +extern s32b YAVANNA_GROW_GRASS; +extern s32b YAVANNA_TREE_ROOTS; +extern s32b YAVANNA_WATER_BITE; +extern s32b YAVANNA_UPROOT; + +bool_ *yavanna_charm_animal(); +char *yavanna_charm_animal_info(); +bool_ *yavanna_grow_grass(); +char *yavanna_grow_grass_info(); +bool_ *yavanna_tree_roots(); +char *yavanna_tree_roots_info(); +bool_ *yavanna_water_bite(); +char *yavanna_water_bite_info(); +bool_ *yavanna_uproot(); +char *yavanna_uproot_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index 779a63d4..73539162 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2702,3 +2702,20 @@ bool_ *water_vapor(); char *water_vapor_info(); bool_ *water_geyser(); char *water_geyser_info(); + +extern s32b YAVANNA_CHARM_ANIMAL; +extern s32b YAVANNA_GROW_GRASS; +extern s32b YAVANNA_TREE_ROOTS; +extern s32b YAVANNA_WATER_BITE; +extern s32b YAVANNA_UPROOT; + +bool_ *yavanna_charm_animal(); +char *yavanna_charm_animal_info(); +bool_ *yavanna_grow_grass(); +char *yavanna_grow_grass_info(); +bool_ *yavanna_tree_roots(); +char *yavanna_tree_roots_info(); +bool_ *yavanna_water_bite(); +char *yavanna_water_bite_info(); +bool_ *yavanna_uproot(); +char *yavanna_uproot_info(); diff --git a/src/spells3.c b/src/spells3.c index 7fa9d728..c6702151 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -105,6 +105,12 @@ s32b ENTPOTION; s32b VAPOR; s32b GEYSER; +s32b YAVANNA_CHARM_ANIMAL; +s32b YAVANNA_GROW_GRASS; +s32b YAVANNA_TREE_ROOTS; +s32b YAVANNA_WATER_BITE; +s32b YAVANNA_UPROOT; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua @@ -3182,3 +3188,189 @@ char *water_geyser_info() sides); return buf; } + +static int charm_animal_power() +{ + return 10 + get_level_s(YAVANNA_CHARM_ANIMAL, 170); +} + +static int charm_animal_radius() +{ + return get_level_s(YAVANNA_CHARM_ANIMAL, 2); +} + +bool_ *yavanna_charm_animal() +{ + int dir; + + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + fire_ball(GF_CONTROL_ANIMAL, + dir, + charm_animal_power(), + charm_animal_radius()); + return CAST; +} + +char *yavanna_charm_animal_info() +{ + static char buf[128]; + sprintf(buf, + "power %d rad %d", + charm_animal_power(), + charm_animal_radius()); + return buf; +} + +static int yavanna_grow_grass_radius() +{ + return get_level_s(YAVANNA_GROW_GRASS, 4); +} + +bool_ *yavanna_grow_grass() +{ + grow_grass(yavanna_grow_grass_radius()); + return CAST; +} + +char *yavanna_grow_grass_info() +{ + static char buf[128]; + sprintf(buf, + "rad %d", + yavanna_grow_grass_radius()); + return buf; +} + +static int tree_roots_duration() +{ + return 10 + get_level_s(YAVANNA_TREE_ROOTS, 30); +} + +static int tree_roots_ac() +{ + return 10 + get_level_s(YAVANNA_TREE_ROOTS, 60); +} + +static int tree_roots_damage() +{ + return 10 + get_level_s(YAVANNA_TREE_ROOTS, 20); +} + +bool_ *yavanna_tree_roots() +{ + set_roots(tree_roots_duration(), + tree_roots_ac(), + tree_roots_damage()); + return CAST; +} + +char *yavanna_tree_roots_info() +{ + static char buf[128]; + sprintf(buf, + "dur %d AC %d dam %d", + tree_roots_duration(), + tree_roots_ac(), + tree_roots_damage()); + return buf; +} + +static int water_bite_base_duration() +{ + return 30 + get_level_s(YAVANNA_WATER_BITE, 150); +} + +static int water_bite_damage() +{ + return 10 + get_level_s(YAVANNA_WATER_BITE, 50); +} + +bool_ *yavanna_water_bite() +{ + int rad = 0; + + if (get_level_s(YAVANNA_WATER_BITE, 50) >= 25) + { + rad = 1; + } + + set_project(randint(30) + water_bite_base_duration(), + GF_WATER, + water_bite_damage(), + rad, + PROJECT_STOP | PROJECT_KILL); + return CAST; +} + +char *yavanna_water_bite_info() +{ + static char buf[128]; + sprintf(buf, + "dur %d+d30 dam %d/blow", + water_bite_base_duration(), + water_bite_damage()); + return buf; +} + +static int uproot_mlevel() +{ + return 30 + get_level_s(YAVANNA_UPROOT, 70); +} + +bool_ *yavanna_uproot() +{ + int dir, x, y; + cave_type *c_ptr; + + if (!get_rep_dir(&dir)) + { + return NO_CAST; + } + + y = ddy[dir]; + x = ddx[dir]; + + y += p_ptr->py; + x += p_ptr->px; + + c_ptr = &cave[y][x]; + + if (c_ptr->feat == FEAT_TREES) + { + s16b m_idx; + + cave_set_feat(y, x, FEAT_GRASS); + + /* Summon it */ + find_position(y, x, &y, &x); + m_idx = place_monster_one(y, x, test_monster_name("Ent"), 0, FALSE, MSTATUS_FRIEND); + + /* level it */ + if (m_idx != 0) + { + monster_set_level(m_idx, uproot_mlevel()); + } + + msg_print("The tree awakes!"); + return CAST; + } + else + { + msg_print("There is no tree there."); + return NO_CAST; + } +} + +char *yavanna_uproot_info() +{ + static char buf[128]; + sprintf(buf, + "lev %d", + uproot_mlevel()); + return buf; +} + -- cgit v1.2.3 From 6d8f14307f6e9ad22c7b34ad7a7058537cb6b738 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 12 May 2012 18:30:39 +0200 Subject: Lua: Move "Nature" spell functions to C --- lib/mods/theme/scpt/s_nature.lua | 70 +++--------------- lib/scpt/s_nature.lua | 59 +++------------ src/externs.h | 20 +++++ src/spells.pkg | 20 +++++ src/spells3.c | 153 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 215 insertions(+), 107 deletions(-) diff --git a/lib/mods/theme/scpt/s_nature.lua b/lib/mods/theme/scpt/s_nature.lua index 3d44c569..e41a6990 100644 --- a/lib/mods/theme/scpt/s_nature.lua +++ b/lib/mods/theme/scpt/s_nature.lua @@ -9,13 +9,8 @@ GROWTREE = add_spell ["mana_max"] = 30, ["fail"] = 35, ["inertia"] = { 5, 50 }, - ["spell"] = function() - grow_trees(2 + get_level(GROWTREE, 7)) - return TRUE - end, - ["info"] = function() - return "rad "..(2 + get_level(GROWTREE, 7)) - end, + ["spell"] = function() return nature_grow_trees() end, + ["info"] = function() return nature_grow_trees_info() end, ["desc"] = { "Makes trees grow extremely quickly around you", } @@ -39,12 +34,8 @@ HEALING = add_spell ["max_level"] = { 20, 40 }, }, }, - ["spell"] = function() - return hp_player(player.mhp * (15 + get_level(HEALING, 35)) / 100) - end, - ["info"] = function() - return "heal "..(15 + get_level(HEALING, 35)).."% = "..(player.mhp * (15 + get_level(HEALING, 35)) / 100).."hp" - end, + ["spell"] = function() return nature_healing() end, + ["info"] = function() return nature_healing_info() end, ["desc"] = { "Heals a percent of hitpoints", } @@ -69,29 +60,8 @@ RECOVERY = add_spell }, }, ["inertia"] = { 2, 100 }, - ["spell"] = function() - local obvious - obvious = set_poisoned(player.poisoned / 2) - if get_level(RECOVERY, 50) >= 5 then - obvious = is_obvious(set_poisoned(0), obvious) - obvious = is_obvious(set_cut(0), obvious) - end - if get_level(RECOVERY, 50) >= 10 then - obvious = is_obvious(do_res_stat(A_STR, TRUE), obvious) - obvious = is_obvious(do_res_stat(A_CON, TRUE), obvious) - obvious = is_obvious(do_res_stat(A_DEX, TRUE), obvious) - obvious = is_obvious(do_res_stat(A_WIS, TRUE), obvious) - obvious = is_obvious(do_res_stat(A_INT, TRUE), obvious) - obvious = is_obvious(do_res_stat(A_CHR, TRUE), obvious) - end - if get_level(RECOVERY, 50) >= 15 then - obvious = is_obvious(restore_level(), obvious) - end - return obvious - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return nature_recovery() end, + ["info"] = function() return nature_recovery_info() end, ["desc"] = { "Reduces the length of time that you are poisoned", "At level 5 it cures poison and cuts", @@ -109,12 +79,8 @@ REGENERATION = add_spell ["mana_max"] = 55, ["fail"] = 70, ["inertia"] = { 4, 40 }, - ["spell"] = function() - if player.tim_regen == 0 then return set_tim_regen(randint(10) + 5 + get_level(REGENERATION, 50), 300 + get_level(REGENERATION, 700)) end - end, - ["info"] = function() - return "dur "..(5 + get_level(REGENERATION, 50)).."+d10 power "..(300 + get_level(REGENERATION, 700)) - end, + ["spell"] = function() return nature_regeneration() end, + ["info"] = function() return nature_regeneration_info() end, ["desc"] = { "Increases your body's regeneration rate", } @@ -139,13 +105,8 @@ SUMMONANNIMAL = add_spell ["max_level"] = { 15, 45 }, }, }, - ["spell"] = function() - summon_specific_level = 25 + get_level(SUMMONANNIMAL, 50) - return summon_monster(player.py, player.px, dun_level, TRUE, SUMMON_ANIMAL) - end, - ["info"] = function() - return "level "..(25 + get_level(SUMMONANNIMAL, 50)) - end, + ["spell"] = function() return nature_summon_animal() end, + ["info"] = function() return nature_summon_animal_info() end, ["desc"] = { "Summons a leveled animal to your aid", } @@ -169,15 +130,8 @@ GROW_ATHELAS = add_spell { ["max_level"] = { 15, 45 }, }, }, - ["spell"] = function() - if (player.black_breath == TRUE) then - msg_print("The hold of the Black Breath on you is broken!") - player.black_breath = FALSE - end - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return nature_grow_athelas() end, + ["info"] = function() return nature_grow_athelas_info() end, ["desc"] = { "Cures the Black Breath", } diff --git a/lib/scpt/s_nature.lua b/lib/scpt/s_nature.lua index e71a89bf..d47dbe8f 100644 --- a/lib/scpt/s_nature.lua +++ b/lib/scpt/s_nature.lua @@ -9,13 +9,8 @@ GROWTREE = add_spell ["mana_max"] = 30, ["fail"] = 35, ["inertia"] = { 5, 50 }, - ["spell"] = function() - grow_trees(2 + get_level(GROWTREE, 7)) - return TRUE - end, - ["info"] = function() - return "rad "..(2 + get_level(GROWTREE, 7)) - end, + ["spell"] = function() return nature_grow_trees() end, + ["info"] = function() return nature_grow_trees_info() end, ["desc"] = { "Makes trees grow extremely quickly around you", } @@ -39,12 +34,8 @@ HEALING = add_spell ["max_level"] = { 20, 40 }, }, }, - ["spell"] = function() - return hp_player(player.mhp * (15 + get_level(HEALING, 35)) / 100) - end, - ["info"] = function() - return "heal "..(15 + get_level(HEALING, 35)).."% = "..(player.mhp * (15 + get_level(HEALING, 35)) / 100).."hp" - end, + ["spell"] = function() return nature_healing() end, + ["info"] = function() return nature_healing_info() end, ["desc"] = { "Heals a percent of hitpoints", } @@ -69,29 +60,8 @@ RECOVERY = add_spell }, }, ["inertia"] = { 2, 100 }, - ["spell"] = function() - local obvious - obvious = set_poisoned(player.poisoned / 2) - if get_level(RECOVERY, 50) >= 5 then - obvious = is_obvious(set_poisoned(0), obvious) - obvious = is_obvious(set_cut(0), obvious) - end - if get_level(RECOVERY, 50) >= 10 then - obvious = is_obvious(do_res_stat(A_STR, TRUE), obvious) - obvious = is_obvious(do_res_stat(A_CON, TRUE), obvious) - obvious = is_obvious(do_res_stat(A_DEX, TRUE), obvious) - obvious = is_obvious(do_res_stat(A_WIS, TRUE), obvious) - obvious = is_obvious(do_res_stat(A_INT, TRUE), obvious) - obvious = is_obvious(do_res_stat(A_CHR, TRUE), obvious) - end - if get_level(RECOVERY, 50) >= 15 then - obvious = is_obvious(restore_level(), obvious) - end - return obvious - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return nature_recovery() end, + ["info"] = function() return nature_recovery_info() end, ["desc"] = { "Reduces the length of time that you are poisoned", "At level 5 it cures poison and cuts", @@ -109,12 +79,8 @@ REGENERATION = add_spell ["mana_max"] = 55, ["fail"] = 70, ["inertia"] = { 4, 40 }, - ["spell"] = function() - if player.tim_regen == 0 then return set_tim_regen(randint(10) + 5 + get_level(REGENERATION, 50), 300 + get_level(REGENERATION, 700)) end - end, - ["info"] = function() - return "dur "..(5 + get_level(REGENERATION, 50)).."+d10 power "..(300 + get_level(REGENERATION, 700)) - end, + ["spell"] = function() return nature_regeneration() end, + ["info"] = function() return nature_regeneration_info() end, ["desc"] = { "Increases your body's regeneration rate", } @@ -139,13 +105,8 @@ SUMMONANNIMAL = add_spell ["max_level"] = { 15, 45 }, }, }, - ["spell"] = function() - summon_specific_level = 25 + get_level(SUMMONANNIMAL, 50) - return summon_monster(player.py, player.px, dun_level, TRUE, SUMMON_ANIMAL) - end, - ["info"] = function() - return "level "..(25 + get_level(SUMMONANNIMAL, 50)) - end, + ["spell"] = function() return nature_summon_animal() end, + ["info"] = function() return nature_summon_animal_info() end, ["desc"] = { "Summons a leveled animal to your aid", } diff --git a/src/externs.h b/src/externs.h index c19a83ed..914cea73 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1716,6 +1716,26 @@ char *yavanna_water_bite_info(); bool_ *yavanna_uproot(); char *yavanna_uproot_info(); +extern s32b GROWTREE; +extern s32b HEALING; +extern s32b RECOVERY; +extern s32b REGENERATION; +extern s32b SUMMONANNIMAL; +extern s32b GROW_ATHELAS; + +bool_ *nature_grow_trees(); +char *nature_grow_trees_info(); +bool_ *nature_healing(); +char *nature_healing_info(); +bool_ *nature_recovery(); +char *nature_recovery_info(); +bool_ *nature_regeneration(); +char *nature_regeneration_info(); +bool_ *nature_summon_animal(); +char *nature_summon_animal_info(); +bool_ *nature_grow_athelas(); +char *nature_grow_athelas_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index 73539162..33459936 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2719,3 +2719,23 @@ bool_ *yavanna_water_bite(); char *yavanna_water_bite_info(); bool_ *yavanna_uproot(); char *yavanna_uproot_info(); + +extern s32b GROWTREE; +extern s32b HEALING; +extern s32b RECOVERY; +extern s32b REGENERATION; +extern s32b SUMMONANNIMAL; +extern s32b GROW_ATHELAS; + +bool_ *nature_grow_trees(); +char *nature_grow_trees_info(); +bool_ *nature_healing(); +char *nature_healing_info(); +bool_ *nature_recovery(); +char *nature_recovery_info(); +bool_ *nature_regeneration(); +char *nature_regeneration_info(); +bool_ *nature_summon_animal(); +char *nature_summon_animal_info(); +bool_ *nature_grow_athelas(); +char *nature_grow_athelas_info(); diff --git a/src/spells3.c b/src/spells3.c index c6702151..2bef9931 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -111,6 +111,13 @@ s32b YAVANNA_TREE_ROOTS; s32b YAVANNA_WATER_BITE; s32b YAVANNA_UPROOT; +s32b GROWTREE; +s32b HEALING; +s32b RECOVERY; +s32b REGENERATION; +s32b SUMMONANNIMAL; +s32b GROW_ATHELAS = -1; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua @@ -3374,3 +3381,149 @@ char *yavanna_uproot_info() return buf; } +static int nature_grow_trees_radius() +{ + return 2 + get_level_s(GROWTREE, 7); +} + +bool_ *nature_grow_trees() +{ + grow_trees(nature_grow_trees_radius()); + return CAST; +} + +char *nature_grow_trees_info() +{ + static char buf[128]; + sprintf(buf, + "rad %d", + nature_grow_trees_radius()); + return buf; +} + +static int nature_healing_percentage() +{ + return 15 + get_level_s(HEALING, 35); +} + +static int nature_healing_hp() +{ + return p_ptr->mhp * nature_healing_percentage() / 100; +} + +bool_ *nature_healing() +{ + hp_player(nature_healing_hp()); + return CAST; +} + +char *nature_healing_info() +{ + static char buf[128]; + sprintf(buf, + "heal %d%% = %dhp", + nature_healing_percentage(), + nature_healing_hp()); + return buf; +} + +bool_ *nature_recovery() +{ + set_poisoned(p_ptr->poisoned / 2); + if (get_level_s(RECOVERY, 50) >= 5) + { + set_poisoned(0); + set_cut(0); + } + if (get_level_s(RECOVERY, 50) >= 10) + { + do_res_stat(A_STR, TRUE); + do_res_stat(A_CON, TRUE); + do_res_stat(A_DEX, TRUE); + do_res_stat(A_WIS, TRUE); + do_res_stat(A_INT, TRUE); + do_res_stat(A_CHR, TRUE); + } + if (get_level_s(RECOVERY, 50) >= 15) + { + restore_level(); + } + return CAST; +} + +char *nature_recovery_info() +{ + return ""; +} + +static int regeneration_base_duration() +{ + return 5 + get_level_s(REGENERATION, 50); +} + +static int regeneration_power() +{ + return 300 + get_level_s(REGENERATION, 700); +} + +bool_ *nature_regeneration() +{ + if (p_ptr->tim_regen == 0) + { + set_tim_regen(randint(10) + regeneration_base_duration(), + regeneration_power()); + return CAST; + } + return NO_CAST; +} + +char *nature_regeneration_info() +{ + static char buf[128]; + sprintf(buf, + "dur %d+d10 power %d", + regeneration_base_duration(), + regeneration_power()); + return buf; +} + +static int summon_animal_level() +{ + return 25 + get_level_s(SUMMONANNIMAL, 50); +} + +bool_ *nature_summon_animal() +{ + summon_specific_level = summon_animal_level(); + summon_specific_friendly(p_ptr->py, + p_ptr->px, + dun_level, + SUMMON_ANIMAL, + TRUE); + return CAST; +} + +char *nature_summon_animal_info() +{ + static char buf[128]; + sprintf(buf, + "level %d", + summon_animal_level()); + return buf; +} + +bool_ *nature_grow_athelas() +{ + if (p_ptr->black_breath) + { + msg_print("The hold of the Black Breath on you is broken!"); + p_ptr->black_breath = FALSE; + } + + return CAST; +} + +char *nature_grow_athelas_info() +{ + return ""; +} -- cgit v1.2.3 From 2d57accf3a3c68e7eb41571eadf54ca2c7c4607f Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 13 May 2012 10:15:07 +0200 Subject: Lua: Move Demonology wield slot implementation to C --- lib/mods/theme/scpt/s_demon.lua | 30 ------------------------------ lib/scpt/s_demon.lua | 30 ------------------------------ src/object.pkg | 5 ----- src/object1.c | 19 +++++++++++++++++++ 4 files changed, 19 insertions(+), 65 deletions(-) diff --git a/lib/mods/theme/scpt/s_demon.lua b/lib/mods/theme/scpt/s_demon.lua index d8f29a60..8bf14c21 100644 --- a/lib/mods/theme/scpt/s_demon.lua +++ b/lib/mods/theme/scpt/s_demon.lua @@ -164,33 +164,3 @@ CONTROL_DEMON = add_spell "Attempts to control a demon", } } - --- ok we need to have different wield slots -add_hooks -{ - [HOOK_WIELD_SLOT] = function (obj, ideal) - if (obj.tval == TV_DAEMON_BOOK) then - local slot - if (obj.sval == SV_DEMONBLADE) then - if(ideal == TRUE) then - slot = INVEN_WIELD - else - slot = get_slot(INVEN_WIELD) - end - elseif (obj.sval == SV_DEMONSHIELD) then - if(ideal == TRUE) then - slot = INVEN_ARM - else - slot = get_slot(INVEN_ARM) - end - elseif (obj.sval == SV_DEMONHORN) then - if(ideal == TRUE) then - slot = INVEN_HEAD - else - slot = get_slot(INVEN_HEAD) - end - end - return TRUE, slot - end - end, -} diff --git a/lib/scpt/s_demon.lua b/lib/scpt/s_demon.lua index d8f29a60..8bf14c21 100644 --- a/lib/scpt/s_demon.lua +++ b/lib/scpt/s_demon.lua @@ -164,33 +164,3 @@ CONTROL_DEMON = add_spell "Attempts to control a demon", } } - --- ok we need to have different wield slots -add_hooks -{ - [HOOK_WIELD_SLOT] = function (obj, ideal) - if (obj.tval == TV_DAEMON_BOOK) then - local slot - if (obj.sval == SV_DEMONBLADE) then - if(ideal == TRUE) then - slot = INVEN_WIELD - else - slot = get_slot(INVEN_WIELD) - end - elseif (obj.sval == SV_DEMONSHIELD) then - if(ideal == TRUE) then - slot = INVEN_ARM - else - slot = get_slot(INVEN_ARM) - end - elseif (obj.sval == SV_DEMONHORN) then - if(ideal == TRUE) then - slot = INVEN_HEAD - else - slot = get_slot(INVEN_HEAD) - end - end - return TRUE, slot - end - end, -} diff --git a/src/object.pkg b/src/object.pkg index a89dad9a..1ff281c7 100644 --- a/src/object.pkg +++ b/src/object.pkg @@ -835,11 +835,6 @@ static obj_theme lua_obj_theme @ theme_forge; #define SV_CORPSE_SKULL 4 #define SV_CORPSE_MEAT 5 -/* The "sval" codes for TV_DAEMON_BOOK */ -#define SV_DEMONBLADE 55 -#define SV_DEMONSHIELD 56 -#define SV_DEMONHORN 57 - /* * Special Object Flags */ diff --git a/src/object1.c b/src/object1.c index 857deb2c..b834eb91 100644 --- a/src/object1.c +++ b/src/object1.c @@ -4145,6 +4145,25 @@ s16b wield_slot_ideal(object_type *o_ptr, bool_ ideal) } return -1; } + + case TV_DAEMON_BOOK: + { + int slot = -1; + + switch (o_ptr->sval) + { + case SV_DEMONBLADE : slot = INVEN_WIELD; break; + case SV_DEMONSHIELD: slot = INVEN_ARM; break; + case SV_DEMONHORN : slot = INVEN_HEAD; break; + } + + if ((slot >= 0) && (!ideal)) + { + slot = get_slot(slot); + } + + return slot; + } } /* No slot available */ -- cgit v1.2.3 From 806d9737befef6ca878befbcddeb30634ce62083 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 13 May 2012 10:55:44 +0200 Subject: Lua: Move "device" spell functions to C --- lib/mods/theme/scpt/s_stick.lua | 252 +++------------------------ lib/scpt/s_stick.lua | 203 +++------------------- src/externs.h | 44 +++++ src/spells.pkg | 44 +++++ src/spells3.c | 371 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 507 insertions(+), 407 deletions(-) diff --git a/lib/mods/theme/scpt/s_stick.lua b/lib/mods/theme/scpt/s_stick.lua index 9bbd641a..20d70856 100644 --- a/lib/mods/theme/scpt/s_stick.lua +++ b/lib/mods/theme/scpt/s_stick.lua @@ -19,15 +19,8 @@ DEVICE_HEAL_MONSTER = add_spell ["max_level"] = { 20, 50 }, }, }, - ["spell"] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - return fire_ball(GF_OLD_HEAL, dir, 20 + get_level(DEVICE_HEAL_MONSTER, 380), 0) - end, - ["info"] = function() - return "heal "..(20 + get_level(DEVICE_HEAL_MONSTER, 380)) - end, + ["spell"] = function() return device_heal_monster() end, + ["info"] = function() return device_heal_monster_info() end, ["desc"] = { "Heals a monster", } @@ -52,15 +45,8 @@ DEVICE_SPEED_MONSTER = add_spell ["max_level"] = { 20, 50 }, }, }, - ["spell"] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - return fire_ball(GF_OLD_SPEED, dir, 1, 0) - end, - ["info"] = function() - return "speed +10" - end, + ["spell"] = function() return device_haste_monster() end, + ["info"] = function() return device_haste_monster_info() end, ["desc"] = { "Haste a monster", } @@ -85,13 +71,8 @@ DEVICE_WISH = add_spell ["max_level"] = { 1, 1 }, }, }, - ["spell"] = function() - make_wish() - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return device_wish() end, + ["info"] = function() return device_wish_info() end, ["desc"] = { "This grants you a wish, beware of what you ask for!", } @@ -116,17 +97,8 @@ DEVICE_SUMMON = add_spell ["max_level"] = { 25, 50 }, }, }, - ["spell"] = function() - local i, obvious - obvious = nil - for i = 1, 4 + get_level(DEVICE_SUMMON, 30) do - obvious = is_obvious(summon_specific(player.py, player.px, dun_level, 0), obvious) - end - return obvious - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return device_summon_monster() end, + ["info"] = function() return device_summon_monster_info() end, ["desc"] = { "Summons hostile monsters near you", } @@ -151,13 +123,8 @@ DEVICE_MANA = add_spell ["max_level"] = { 20, 35 }, }, }, - ["spell"] = function() - increase_mana((player.msp * (20 + get_level(DEVICE_MANA, 50))) / 100) - return TRUE - end, - ["info"] = function() - return "restore "..(20 + get_level(DEVICE_MANA, 50)).."%" - end, + ["spell"] = function() return device_mana() end, + ["info"] = function() return device_mana_info() end, ["desc"] = { "Restores a part(or all) of your mana", } @@ -188,12 +155,8 @@ DEVICE_NOTHING = add_spell ["max_level"] = { 1, 1}, }, }, - ["spell"] = function() - return FALSE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return device_nothing() end, + ["info"] = function() return device_nothing_info() end, ["desc"] = { "It does nothing.", } @@ -209,14 +172,8 @@ DEVICE_MAGGOT = add_spell ["fail"] = 20, ["random"] = -1, ["activate"] = { 10, 50 }, - ["spell"] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_ball(GF_TURN_ALL, dir, 40, 2) - end, - ["info"] = function() - return "power 40 rad 2" - end, + ["spell"] = function() return device_maggot() end, + ["info"] = function() return device_maggot_info() end, ["desc"] = { "terrify", } @@ -242,12 +199,8 @@ DEVICE_HOLY_FIRE = add_spell ["max_level"] = { 35, 35 }, }, }, - ["spell"] = function() - return project_los(GF_HOLY_FIRE, 50 + get_level(DEVICE_HOLY_FIRE, 300)) - end, - ["info"] = function() - return "dam "..(50 + get_level(DEVICE_HOLY_FIRE, 250)) - end, + ["spell"] = function() return device_holy_fire() end, + ["info"] = function() return device_holy_fire_info() end, ["desc"] = { "The Holy Fire created by this staff will deeply(double damage) burn", "all that is evil.", @@ -266,84 +219,8 @@ DEVICE_ETERNAL_FLAME = add_spell ["fail"] = 0, ["random"] = -1, ["activate"] = { 0, 0 }, - ["spell"] = function(flame_item) - local ret, item, obj - - ret, item = get_item("Which object do you want to imbue?", - "You have no objects to imbue.", - bor(USE_INVEN), - function (obj) - if obj.name1 > 0 or obj.name2 > 0 then return FALSE end - if (obj.tval == TV_SWORD) and (obj.sval == SV_LONG_SWORD) then - return TRUE - elseif (obj.tval == TV_MSTAFF) and (obj.sval == SV_MSTAFF) then - return TRUE - elseif (obj.tval == TV_BOW) and (obj.sval == SV_HEAVY_XBOW) then - return TRUE - elseif (obj.tval == TV_DRAG_ARMOR) and (obj.sval == SV_DRAGON_POWER) then - return TRUE - elseif (obj.tval == TV_HAFTED) and (obj.sval == SV_LUCERN_HAMMER) then - return TRUE - elseif (obj.tval == TV_POLEARM) and (obj.sval == SV_TRIDENT) then - return TRUE - elseif (obj.tval == TV_AXE) and (obj.sval == SV_BATTLE_AXE) then - return TRUE - elseif (obj.tval == TV_BOW) and (obj.sval == SV_LONG_BOW) then - return TRUE - elseif (obj.tval == TV_BOOMERANG) and (obj.sval == SV_BOOM_METAL) then - return TRUE - elseif (obj.tval == TV_BOW) and (obj.sval == SV_SLING) then - return TRUE - elseif (obj.tval == TV_SWORD) and (obj.sval == SV_RAPIER) then - return TRUE - elseif (obj.tval == TV_AMULET) and (obj.sval == SV_AMULET_SPELL) then - return TRUE - end - return FALSE - end - ) - if ret == FALSE then return FALSE end - - obj = get_object(item) - - if (obj.tval == TV_SWORD) and (obj.sval == SV_LONG_SWORD) then - obj.name1 = 147 - elseif (obj.tval == TV_MSTAFF) and (obj.sval == SV_MSTAFF) then - obj.name1 = 127 - elseif (obj.tval == TV_BOW) and (obj.sval == SV_HEAVY_XBOW) then - obj.name1 = 152 - elseif (obj.tval == TV_DRAG_ARMOR) and (obj.sval == SV_DRAGON_POWER) then - obj.name1 = 17 - elseif (obj.tval == TV_HAFTED) and (obj.sval == SV_LUCERN_HAMMER) then - obj.name1 = 241 - elseif (obj.tval == TV_POLEARM) and (obj.sval == SV_TRIDENT) then - obj.name1 = 242 - elseif (obj.tval == TV_AXE) and (obj.sval == SV_BROAD_AXE) then - obj.name1 = 243 - elseif (obj.tval == TV_BOW) and (obj.sval == SV_LONG_BOW) then - obj.name1 = 245 - elseif (obj.tval == TV_BOOMERANG) and (obj.sval == SV_BOOM_METAL) then - obj.name1 = 247 - elseif (obj.tval == TV_BOW) and (obj.sval == SV_SLING) then - obj.name1 = 246 - elseif (obj.tval == TV_SWORD) and (obj.sval == SV_RAPIER) then - obj.name1 = 244 - elseif (obj.tval == TV_AMULET) and (obj.sval == SV_AMULET_SPELL) then - obj.name1 = 248 - end - apply_magic(obj, -1, TRUE, TRUE, TRUE) - - obj.found = OBJ_FOUND_SELFMADE - - inven_item_increase(flame_item, -1) - inven_item_describe(flame_item) - inven_item_optimize(flame_item) - - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function(flame_item) return device_eternal_flame(flame_item) end, + ["info"] = function() return "" end, ["desc"] = { "Imbuing an object with the eternal fire", } @@ -369,18 +246,8 @@ DEVICE_THUNDERLORDS = add_spell ["max_level"] = { 1, 1 }, }, }, - ["spell"] = function() - if dun_level > 0 then - msg_print("As you blow the horn, an Eagle of Manwe appears overhead.") - recall_player(0, 1) - else - msg_print("You cannot use it there.") - end - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return device_thunderlords() end, + ["info"] = function() return device_thunderlords_info() end, ["desc"] = { "An Eagle of Manwe will appear to transport you quickly to the town.", } @@ -398,42 +265,8 @@ DEVICE_RADAGAST = add_spell ["fail"] = 10, ["random"] = -1, ["activate"] = 15000, - ["spell"] = function() - msg_print(TERM_GREEN, "The staff's power cleanses you completely!") - remove_all_curse() - do_res_stat(A_STR, TRUE) - do_res_stat(A_CON, TRUE) - do_res_stat(A_DEX, TRUE) - do_res_stat(A_WIS, TRUE) - do_res_stat(A_INT, TRUE) - do_res_stat(A_CHR, TRUE) - restore_level() - clean_corruptions() - hp_player(5000) - heal_insanity(5000) - set_poisoned(0) - set_blind(0) - set_confused(0) - set_image(0) - set_stun(0) - set_cut(0) - set_parasite(0, 0) - - if (player.black_breath) == TRUE then - msg_print("The hold of the Black Breath on you is broken!") - end - player.black_breath = FALSE - - player.update = bor(player.update, PU_BONUS) - player.window = bor(player.window, PW_PLAYER) - - return TRUE - end, - - ["info"] = function() - return "" - end, - + ["spell"] = function() return device_radagast() end, + ["info"] = function() return device_radagast_info() end, ["desc"] = { "purity and health", } @@ -449,46 +282,9 @@ DEVICE_VALAROMA = add_spell ["fail"] = 25, ["random"] = -1, ["activate"] = 250, - ["spell"] = function() - local power = 5 * player.lev - banish_evil(power) - return FALSE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return device_valaroma() end, + ["info"] = function() return device_valaroma_info() end, ["desc"] = { "banish evil (level x5)", } } ---[[ Template -DEVICE_ = add_spell -{ - ["name"] = "", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 1, - ["mana"] = 2, - ["mana_max"] = 15, - ["fail"] = 10, - ["random"] = -1, - ["stick"] = - { - ["charge"] = { 10, 5 }, - [TV_STAFF] = - { - ["rarity"] = 7, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 25, 50 }, - }, - }, - ["spell"] = function() - return FALSE - end, - ["info"] = function() - return "" - end, - ["desc"] = { - "", - } -} -]] diff --git a/lib/scpt/s_stick.lua b/lib/scpt/s_stick.lua index 36647414..28abc0db 100644 --- a/lib/scpt/s_stick.lua +++ b/lib/scpt/s_stick.lua @@ -19,15 +19,8 @@ DEVICE_HEAL_MONSTER = add_spell ["max_level"] = { 20, 50 }, }, }, - ["spell"] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - return fire_ball(GF_OLD_HEAL, dir, 20 + get_level(DEVICE_HEAL_MONSTER, 380), 0) - end, - ["info"] = function() - return "heal "..(20 + get_level(DEVICE_HEAL_MONSTER, 380)) - end, + ["spell"] = function() return device_heal_monster() end, + ["info"] = function() return device_heal_monster_info() end, ["desc"] = { "Heals a monster", } @@ -52,15 +45,8 @@ DEVICE_SPEED_MONSTER = add_spell ["max_level"] = { 20, 50 }, }, }, - ["spell"] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - - return fire_ball(GF_OLD_SPEED, dir, 1, 0) - end, - ["info"] = function() - return "speed +10" - end, + ["spell"] = function() return device_haste_monster() end, + ["info"] = function() return device_haste_monster_info() end, ["desc"] = { "Haste a monster", } @@ -85,13 +71,8 @@ DEVICE_WISH = add_spell ["max_level"] = { 1, 1 }, }, }, - ["spell"] = function() - make_wish() - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return device_wish() end, + ["info"] = function() return device_wish_info() end, ["desc"] = { "This grants you a wish, beware of what you ask for!", } @@ -116,17 +97,8 @@ DEVICE_SUMMON = add_spell ["max_level"] = { 25, 50 }, }, }, - ["spell"] = function() - local i, obvious - obvious = nil - for i = 1, 4 + get_level(DEVICE_SUMMON, 30) do - obvious = is_obvious(summon_specific(player.py, player.px, dun_level, 0), obvious) - end - return obvious - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return device_summon_monster() end, + ["info"] = function() return device_summon_monster_info() end, ["desc"] = { "Summons hostile monsters near you", } @@ -151,13 +123,8 @@ DEVICE_MANA = add_spell ["max_level"] = { 20, 35 }, }, }, - ["spell"] = function() - increase_mana((player.msp * (20 + get_level(DEVICE_MANA, 50))) / 100) - return TRUE - end, - ["info"] = function() - return "restore "..(20 + get_level(DEVICE_MANA, 50)).."%" - end, + ["spell"] = function() return device_mana() end, + ["info"] = function() return device_mana_info() end, ["desc"] = { "Restores a part(or all) of your mana", } @@ -188,12 +155,8 @@ DEVICE_NOTHING = add_spell ["max_level"] = { 1, 1}, }, }, - ["spell"] = function() - return FALSE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return device_nothing() end, + ["info"] = function() return device_nothing_info() end, ["desc"] = { "It does nothing.", } @@ -209,15 +172,8 @@ DEVICE_LEBOHAUM = add_spell ["fail"] = 0, ["random"] = -1, ["activate"] = 3, - ["spell"] = function() - msg_print("You hear a little song in your head in some unknown tongue:") - msg_print("'Avec le casque Lebohaum y a jamais d'anicroches, je parcours les dongeons,") - msg_print("j'en prend plein la caboche. Avec le casque Lebohaum, tout ces monstres a la") - msg_print("con, je leur met bien profond: c'est moi le maitre du dongeon!'") - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return device_lebohaum() end, + ["info"] = function() return device_lebohaum_info() end, ["desc"] = { "sing a cheerful song", } @@ -233,14 +189,8 @@ DEVICE_MAGGOT = add_spell ["fail"] = 20, ["random"] = -1, ["activate"] = { 10, 50 }, - ["spell"] = function() - local ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_ball(GF_TURN_ALL, dir, 40, 2) - end, - ["info"] = function() - return "power 40 rad 2" - end, + ["spell"] = function() return device_maggot() end, + ["info"] = function() return device_maggot_info() end, ["desc"] = { "terrify", } @@ -266,12 +216,8 @@ DEVICE_HOLY_FIRE = add_spell ["max_level"] = { 35, 35 }, }, }, - ["spell"] = function() - return project_los(GF_HOLY_FIRE, 50 + get_level(DEVICE_HOLY_FIRE, 300)) - end, - ["info"] = function() - return "dam "..(50 + get_level(DEVICE_HOLY_FIRE, 250)) - end, + ["spell"] = function() return device_holy_fire() end, + ["info"] = function() return device_holy_fire_info() end, ["desc"] = { "The Holy Fire created by this staff will deeply(double damage) burn", "all that is evil.", @@ -290,52 +236,8 @@ DEVICE_ETERNAL_FLAME = add_spell ["fail"] = 0, ["random"] = -1, ["activate"] = { 0, 0 }, - ["spell"] = function(flame_item) - local ret, item, obj - - ret, item = get_item("Which object do you want to imbue?", - "You have no objects to imbue.", - bor(USE_INVEN), - function (obj) - if obj.name1 > 0 or obj.name2 > 0 then return FALSE end - if (obj.tval == TV_SWORD) and (obj.sval == SV_LONG_SWORD) then - return TRUE - elseif (obj.tval == TV_MSTAFF) and (obj.sval == SV_MSTAFF) then - return TRUE - elseif (obj.tval == TV_BOW) and (obj.sval == SV_HEAVY_XBOW) then - return TRUE - elseif (obj.tval == TV_DRAG_ARMOR) and (obj.sval == SV_DRAGON_POWER) then - return TRUE - end - return FALSE - end - ) - if ret == FALSE then return FALSE end - - obj = get_object(item) - - if (obj.tval == TV_SWORD) and (obj.sval == SV_LONG_SWORD) then - obj.name1 = 147 - elseif (obj.tval == TV_MSTAFF) and (obj.sval == SV_MSTAFF) then - obj.name1 = 127 - elseif (obj.tval == TV_BOW) and (obj.sval == SV_HEAVY_XBOW) then - obj.name1 = 152 - elseif (obj.tval == TV_DRAG_ARMOR) and (obj.sval == SV_DRAGON_POWER) then - obj.name1 = 17 - end - apply_magic(obj, -1, TRUE, TRUE, TRUE) - - obj.found = OBJ_FOUND_SELFMADE - - inven_item_increase(flame_item, -1) - inven_item_describe(flame_item) - inven_item_optimize(flame_item) - - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function(flame_item) return device_eternal_flame(flame_item) end, + ["info"] = function() return "" end, ["desc"] = { "Imbuing an object with the eternal fire", } @@ -352,23 +254,8 @@ DEVICE_DURANDIL = add_spell ["fail"] = 0, ["random"] = -1, ["activate"] = 3, - ["spell"] = function() - msg_print("You hear a little song in your head in some unknown tongue:") - msg_print("'Les epees Durandils sont forgees dans les mines par des nains.") - msg_print("Avec ca c'est facile de tuer un troll avec une seule main. Pas besoin") - msg_print("de super entrainement nis de niveau 28. Quand tu sors l'instrument") - msg_print("c'est l'ennemi qui prend la fuite! Avec ton epee Durandil quand tu") - msg_print("parcours les chemins, tu massacre sans peine les brigands et les gobelins,") - msg_print("les rats geants, les ogres mutants, les zombies et les liches, tu les") - msg_print("decoupe en tranches comme si c'etait des parts de quiches.") - msg_print("Les epees Durandil! Les epees Durandil!") - msg_print("Quand tu la sort dans un dongeon au moins t'as pas l'air debile.") - msg_print("C'est l'arme des bourins qui savent etre subtils.") - msg_print("Ne partez pas a l'aventure sans votre epee Durandil!'") - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return device_durandil() end, + ["info"] = function() return device_durandil_info() end, ["desc"] = { "sing a cheerful song", } @@ -394,51 +281,9 @@ DEVICE_THUNDERLORDS = add_spell ["max_level"] = { 1, 1 }, }, }, - ["spell"] = function() - if dun_level > 0 then - msg_print("As you blow the horn a thunderlord pops out of nowhere and grabs you.") - recall_player(0, 1) - else - msg_print("You cannot use it there.") - end - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return device_thunderlords() end, + ["info"] = function() return device_thunderlords_info() end, ["desc"] = { "A thunderlord will appear to transport you quickly to the surface.", } } - ---[[ Template -DEVICE_ = add_spell -{ - ["name"] = "", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 1, - ["mana"] = 2, - ["mana_max"] = 15, - ["fail"] = 10, - ["random"] = -1, - ["stick"] = - { - ["charge"] = { 10, 5 }, - [TV_STAFF] = - { - ["rarity"] = 7, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 25, 50 }, - }, - }, - ["spell"] = function() - return FALSE - end, - ["info"] = function() - return "" - end, - ["desc"] = { - "", - } -} -]] diff --git a/src/externs.h b/src/externs.h index 914cea73..5b935baa 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1736,6 +1736,50 @@ char *nature_summon_animal_info(); bool_ *nature_grow_athelas(); char *nature_grow_athelas_info(); +extern s32b DEVICE_HEAL_MONSTER; +extern s32b DEVICE_SPEED_MONSTER; +extern s32b DEVICE_WISH; +extern s32b DEVICE_SUMMON; +extern s32b DEVICE_MANA; +extern s32b DEVICE_NOTHING; +extern s32b DEVICE_LEBOHAUM; +extern s32b DEVICE_MAGGOT; +extern s32b DEVICE_HOLY_FIRE; +extern s32b DEVICE_ETERNAL_FLAME; +extern s32b DEVICE_DURANDIL; +extern s32b DEVICE_THUNDERLORDS; +extern s32b DEVICE_RADAGAST; +extern s32b DEVICE_VALAROMA; + +bool_ *device_heal_monster(); +char *device_heal_monster_info(); +bool_ *device_haste_monster(); +char *device_haste_monster_info(); +bool_ *device_wish(); +char *device_wish_info(); +bool_ *device_summon_monster(); +char *device_summon_monster_info(); +bool_ *device_mana(); +char *device_mana_info(); +bool_ *device_nothing(); +char *device_nothing_info(); +bool_ *device_lebohaum(); +char *device_lebohaum_info(); +bool_ *device_maggot(); +char *device_maggot_info(); +bool_ *device_holy_fire(); +char *device_holy_fire_info(); +bool_ *device_eternal_flame(); +char *device_eternal_flame_info(); +bool_ *device_durandil(); +char *device_durandil_info(); +bool_ *device_thunderlords(); +char *device_thunderlords_info(); +bool_ *device_radagast(); +char *device_radagast_info(); +bool_ *device_valaroma(); +char *device_valaroma_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index 33459936..b31ff65b 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2739,3 +2739,47 @@ bool_ *nature_summon_animal(); char *nature_summon_animal_info(); bool_ *nature_grow_athelas(); char *nature_grow_athelas_info(); + +extern s32b DEVICE_HEAL_MONSTER; +extern s32b DEVICE_SPEED_MONSTER; +extern s32b DEVICE_WISH; +extern s32b DEVICE_SUMMON; +extern s32b DEVICE_MANA; +extern s32b DEVICE_NOTHING; +extern s32b DEVICE_LEBOHAUM; +extern s32b DEVICE_MAGGOT; +extern s32b DEVICE_HOLY_FIRE; +extern s32b DEVICE_ETERNAL_FLAME; +extern s32b DEVICE_DURANDIL; +extern s32b DEVICE_THUNDERLORDS; +extern s32b DEVICE_RADAGAST; +extern s32b DEVICE_VALAROMA; + +bool_ *device_heal_monster(); +char *device_heal_monster_info(); +bool_ *device_haste_monster(); +char *device_haste_monster_info(); +bool_ *device_wish(); +char *device_wish_info(); +bool_ *device_summon_monster(); +char *device_summon_monster_info(); +bool_ *device_mana(); +char *device_mana_info(); +bool_ *device_nothing(); +char *device_nothing_info(); +bool_ *device_lebohaum(); +char *device_lebohaum_info(); +bool_ *device_maggot(); +char *device_maggot_info(); +bool_ *device_holy_fire(); +char *device_holy_fire_info(); +bool_ *device_eternal_flame(); +char *device_eternal_flame_info(); +bool_ *device_durandil(); +char *device_durandil_info(); +bool_ *device_thunderlords(); +char *device_thunderlords_info(); +bool_ *device_radagast(); +char *device_radagast_info(); +bool_ *device_valaroma(); +char *device_valaroma_info(); diff --git a/src/spells3.c b/src/spells3.c index 2bef9931..6a45a1a3 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -118,6 +118,21 @@ s32b REGENERATION; s32b SUMMONANNIMAL; s32b GROW_ATHELAS = -1; +s32b DEVICE_HEAL_MONSTER; +s32b DEVICE_SPEED_MONSTER; +s32b DEVICE_WISH; +s32b DEVICE_SUMMON; +s32b DEVICE_MANA; +s32b DEVICE_NOTHING; +s32b DEVICE_LEBOHAUM; +s32b DEVICE_MAGGOT; +s32b DEVICE_HOLY_FIRE; +s32b DEVICE_ETERNAL_FLAME; +s32b DEVICE_DURANDIL; +s32b DEVICE_THUNDERLORDS; +s32b DEVICE_RADAGAST = -1; +s32b DEVICE_VALAROMA = -1; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua @@ -3527,3 +3542,359 @@ char *nature_grow_athelas_info() { return ""; } + +static int device_heal_monster_hp() +{ + return 20 + get_level_s(DEVICE_HEAL_MONSTER, 380); +} + +bool_ *device_heal_monster() +{ + int dir; + + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + fire_ball(GF_OLD_HEAL, dir, device_heal_monster_hp(), 0); + return CAST; +} + +char *device_heal_monster_info() +{ + static char buf[128]; + sprintf(buf, + "heal %d", + device_heal_monster_hp()); + return buf; +} + +bool_ *device_haste_monster() +{ + int dir; + + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + fire_ball(GF_OLD_SPEED, dir, 1, 0); + return CAST; +} + +char *device_haste_monster_info() +{ + return "speed +10"; +} + +bool_ *device_wish() +{ + make_wish(); + return CAST; +} + +char *device_wish_info() +{ + return ""; +} + +bool_ *device_summon_monster() +{ + int i; + for (i = 0; i < 4 + get_level_s(DEVICE_SUMMON, 30); i++) + { + summon_specific(p_ptr->py, p_ptr->px, dun_level, 0); + } + return CAST; +} + +char *device_summon_monster_info() +{ + return ""; +} + +static int device_mana_pct() +{ + return 20 + get_level_s(DEVICE_MANA, 50); +} + +bool_ *device_mana() +{ + increase_mana((p_ptr->msp * device_mana_pct()) / 100); + return CAST; +} + +char *device_mana_info() +{ + static char buf[128]; + sprintf(buf, + "restore %d%%", + device_mana_pct()); + return buf; +} + +bool_ *device_nothing() +{ + return CAST; +} + +char *device_nothing_info() +{ + return ""; +} + +bool_ *device_lebohaum() +{ + msg_print("You hear a little song in your head in some unknown tongue:"); + msg_print("'Avec le casque Lebohaum y a jamais d'anicroches, je parcours les dongeons,"); + msg_print("j'en prend plein la caboche. Avec le casque Lebohaum, tout ces monstres a la"); + msg_print("con, je leur met bien profond: c'est moi le maitre du dongeon!'"); + return CAST; +} + +char *device_lebohaum_info() +{ + return ""; +} + +bool_ *device_maggot() +{ + int dir; + + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + fire_ball(GF_TURN_ALL, dir, 40, 2); + return CAST; +} + +char *device_maggot_info() +{ + return "power 40 rad 2"; +} + +static int holy_fire_damage() +{ + return 50 + get_level_s(DEVICE_HOLY_FIRE, 300); +} + +bool_ *device_holy_fire() +{ + project_hack(GF_HOLY_FIRE, holy_fire_damage()); + return CAST; +} + +char *device_holy_fire_info() +{ + static char buf[128]; + sprintf(buf, + "dam %d", + holy_fire_damage()); + return buf; +} + +static int get_eternal_artifact_idx(object_type *o_ptr) +{ + if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_LONG_SWORD)) { + return 147; + } else if ((o_ptr->tval == TV_MSTAFF) && (o_ptr->sval == SV_MSTAFF)) { + return 127; + } else if ((o_ptr->tval == TV_BOW) && (o_ptr->sval == SV_HEAVY_XBOW)) { + return 152; + } else if ((o_ptr->tval == TV_DRAG_ARMOR) && (o_ptr->sval == SV_DRAGON_POWER)) { + return 17; + } + + if (game_module_idx == MODULE_THEME) + { + if ((o_ptr->tval == TV_HAFTED) && (o_ptr->sval == SV_LUCERN_HAMMER)) { + return 241; + } else if ((o_ptr->tval == TV_POLEARM) && (o_ptr->sval == SV_TRIDENT)) { + return 242; + } else if ((o_ptr->tval == TV_AXE) && (o_ptr->sval == SV_BROAD_AXE)) { + return 243; + } else if ((o_ptr->tval == TV_BOW) && (o_ptr->sval == SV_LONG_BOW)) { + return 245; + } else if ((o_ptr->tval == TV_BOOMERANG) && (o_ptr->sval == SV_BOOM_METAL)) { + return 247; + } else if ((o_ptr->tval == TV_BOW) && (o_ptr->sval == SV_SLING)) { + return 246; + } else if ((o_ptr->tval == TV_SWORD) && (o_ptr->sval == SV_RAPIER)) { + return 244; + } else if ((o_ptr->tval == TV_AMULET) && (o_ptr->sval == SV_AMULET_SPELL)) { + return 248; + } + } + + /* Not usable */ + return -1; +} + +static bool_ eternal_flame_item_tester_hook(object_type *o_ptr) +{ + if ((o_ptr->name1 > 0) || + (o_ptr->name2 > 0)) + { + return FALSE; + } + + return (get_eternal_artifact_idx(o_ptr) >= 0); +} + +bool_ *device_eternal_flame(int flame_item) +{ + int item; + object_type *o_ptr = NULL; + int artifact_idx = -1; + + item_tester_hook = eternal_flame_item_tester_hook; + if (!get_item(&item, + "Which object do you want to imbue?", + "You have no objects to imbue.", + USE_INVEN)) + { + return FALSE; + } + + /* Get the artifact idx */ + artifact_idx = get_eternal_artifact_idx(o_ptr); + assert(artifact_idx >= 0); + + /* Forge the item */ + o_ptr = get_object(item); + o_ptr->name1 = artifact_idx; + + apply_magic(o_ptr, -1, TRUE, TRUE, TRUE); + + o_ptr->found = OBJ_FOUND_SELFMADE; + + inven_item_increase(flame_item, -1); + inven_item_describe(flame_item); + inven_item_optimize(flame_item); + + return CAST; +} + +char *device_eternal_flame_info() +{ + return ""; +} + +bool_ *device_durandil() +{ + msg_print("You hear a little song in your head in some unknown tongue:"); + msg_print("'Les epees Durandils sont forgees dans les mines par des nains."); + msg_print("Avec ca c'est facile de tuer un troll avec une seule main. Pas besoin"); + msg_print("de super entrainement nis de niveau 28. Quand tu sors l'instrument"); + msg_print("c'est l'ennemi qui prend la fuite! Avec ton epee Durandil quand tu"); + msg_print("parcours les chemins, tu massacre sans peine les brigands et les gobelins,"); + msg_print("les rats geants, les ogres mutants, les zombies et les liches, tu les"); + msg_print("decoupe en tranches comme si c'etait des parts de quiches."); + msg_print("Les epees Durandil! Les epees Durandil!"); + msg_print("Quand tu la sort dans un dongeon au moins t'as pas l'air debile."); + msg_print("C'est l'arme des bourins qui savent etre subtils."); + msg_print("Ne partez pas a l'aventure sans votre epee Durandil!'"); + return CAST; +} + +char *device_durandil_info() +{ + return ""; +} + +bool_ *device_thunderlords() +{ + switch (game_module_idx) + { + case MODULE_TOME: + { + if (dun_level > 0) + { + msg_print("As you blow the horn a thunderlord pops out of nowhere and grabs you."); + recall_player(0, 1); + } + else + { + msg_print("You cannot use it there."); + } + return CAST; + } + + case MODULE_THEME: + { + if (dun_level > 0) + { + msg_print("As you blow the horn, an Eagle of Manwe appears overhead."); + recall_player(0, 1); + } + else + { + msg_print("You cannot use it there."); + } + return CAST; + } + + default: + assert(FALSE); + return NO_CAST; + } +} + +char *device_thunderlords_info() +{ + return ""; +} + +bool_ *device_radagast() +{ + cmsg_print(TERM_GREEN, "The staff's power cleanses you completely!"); + remove_all_curse(); + do_res_stat(A_STR, TRUE); + do_res_stat(A_CON, TRUE); + do_res_stat(A_DEX, TRUE); + do_res_stat(A_WIS, TRUE); + do_res_stat(A_INT, TRUE); + do_res_stat(A_CHR, TRUE); + restore_level(); + // clean_corruptions(); TODO: Do we want to implement this? + hp_player(5000); + heal_insanity(5000); + set_poisoned(0); + set_blind(0); + set_confused(0); + set_image(0); + set_stun(0); + set_cut(0); + set_parasite(0, 0); + + if (p_ptr->black_breath) + { + msg_print("The hold of the Black Breath on you is broken!"); + } + p_ptr->black_breath = FALSE; + + p_ptr->update |= PU_BONUS; + p_ptr->window |= PW_PLAYER; + + return CAST; +} + +char *device_radagast_info() +{ + return ""; +} + +bool_ *device_valaroma() +{ + int power = 5 * p_ptr->lev; + banish_evil(power); + return CAST; +} + +char *device_valaroma_info() +{ + return ""; +} -- cgit v1.2.3 From 3eb4eab63e98e349f2b71ea74b2ded792f15e8d8 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 13 May 2012 18:49:33 +0200 Subject: Lua: Move "Music" spell functions to C --- lib/mods/theme/scpt/s_music.lua | 243 +++++-------------------------- lib/scpt/s_music.lua | 243 +++++-------------------------- src/defines.h | 30 ---- src/dungeon.c | 4 +- src/externs.h | 61 ++++++++ src/spells.pkg | 61 ++++++++ src/spells3.c | 310 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 502 insertions(+), 450 deletions(-) diff --git a/lib/mods/theme/scpt/s_music.lua b/lib/mods/theme/scpt/s_music.lua index 9da6393a..45255485 100644 --- a/lib/mods/theme/scpt/s_music.lua +++ b/lib/mods/theme/scpt/s_music.lua @@ -13,13 +13,8 @@ MUSIC_STOP = add_spell ["random"] = SKILL_MUSIC, ["pval"] = 1, ["blind"] = FALSE, - ["spell"] = function() - player.start_lasting_spell(0) - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return music_stop_singing_spell() end, + ["info"] = function() return music_stop_singing_info() end, ["desc"] = { "Stops the current song, if any." } @@ -38,17 +33,9 @@ MUSIC_HOLD = add_spell ["random"] = SKILL_MUSIC, ["pval"] = 1, ["blind"] = FALSE, - ["lasting"] = function() - project_los(GF_OLD_SLOW, 10 + get_level(MUSIC_HOLD, 100)) - return get_mana(MUSIC_HOLD) - end, - ["spell"] = function() - player.start_lasting_spell(MUSIC_HOLD) - return TRUE - end, - ["info"] = function() - return "power "..(10 + get_level(MUSIC_HOLD, 100)) - end, + ["lasting"] = function() return music_holding_pattern_lasting() end, + ["spell"] = function() return music_holding_pattern_spell() end, + ["info"] = function() return music_holding_pattern_info() end, ["desc"] = { "Slows down all monsters listening the song.", "Consumes the amount of mana each turn.", @@ -67,17 +54,9 @@ MUSIC_CONF = add_spell ["random"] = SKILL_MUSIC, ["pval"] = 2, ["blind"] = FALSE, - ["lasting"] = function() - project_los(GF_OLD_CONF, 10 + get_level(MUSIC_CONF, 100)) - return get_mana(MUSIC_CONF) - end, - ["spell"] = function() - player.start_lasting_spell(MUSIC_CONF) - return TRUE - end, - ["info"] = function() - return "power "..(10 + get_level(MUSIC_CONF, 100)) - end, + ["lasting"] = function() return music_illusion_pattern_lasting() end, + ["spell"] = function() return music_illusion_pattern_spell() end, + ["info"] = function() return music_illusion_pattern_info() end, ["desc"] = { "Tries to confuse all monsters listening the song.", "Consumes the amount of mana each turn.", @@ -96,17 +75,9 @@ MUSIC_STUN = add_spell ["random"] = SKILL_MUSIC, ["pval"] = 4, ["blind"] = FALSE, - ["lasting"] = function() - project_los(GF_STUN, 10 + get_level(MUSIC_STUN, 90)) - return get_mana(MUSIC_STUN) - end, - ["spell"] = function() - player.start_lasting_spell(MUSIC_STUN) - return TRUE - end, - ["info"] = function() - return "power "..(10 + get_level(MUSIC_STUN, 90)) - end, + ["lasting"] = function() return music_stun_pattern_lasting() end, + ["spell"] = function() return music_stun_pattern_spell() end, + ["info"] = function() return music_stun_pattern_info() end, ["desc"] = { "Stuns all monsters listening the song.", "Consumes the amount of mana each turn.", @@ -126,17 +97,9 @@ MUSIC_LITE = add_spell ["random"] = SKILL_MUSIC, ["blind"] = FALSE, ["pval"] = 1, - ["lasting"] = function() - set_lite(5) - return 1 - end, - ["spell"] = function() - player.start_lasting_spell(MUSIC_LITE) - return TRUE - end, - ["info"] = function() - return "" - end, + ["lasting"] = function() return music_song_of_the_sun_lasting() end, + ["spell"] = function() return music_song_of_the_sun_spell() end, + ["info"] = function() return music_song_of_the_sun_info() end, ["desc"] = { "Provides light as long as you sing.", "Consumes the amount of mana each turn.", @@ -154,17 +117,9 @@ MUSIC_HEAL = add_spell ["stat"] = A_CHR, ["random"] = SKILL_MUSIC, ["pval"] = 2, - ["lasting"] = function() - hp_player(7 + get_level(MUSIC_HEAL, 100)) - return get_mana(MUSIC_HEAL) - end, - ["spell"] = function() - player.start_lasting_spell(MUSIC_HEAL) - return TRUE - end, - ["info"] = function() - return "heal "..(7 + get_level(MUSIC_HEAL, 100)).."/turn" - end, + ["lasting"] = function() return music_flow_of_life_lasting() end, + ["spell"] = function() return music_flow_of_life_spell() end, + ["info"] = function() return music_flow_of_life_info() end, ["desc"] = { "Heals you as long as you sing.", "Consumes the amount of mana each turn.", @@ -182,26 +137,9 @@ MUSIC_HERO = add_spell ["stat"] = A_CHR, ["random"] = SKILL_MUSIC, ["pval"] = 2, - ["lasting"] = function() - set_hero(5) - if get_level(MUSIC_HERO) >= 10 then - set_shero(5) - end - if get_level(MUSIC_HERO) >= 20 then - set_strike(5) - end - if get_level(MUSIC_HERO) >= 25 then - set_oppose_cc(5) - end - return get_mana(MUSIC_HERO) - end, - ["spell"] = function() - player.start_lasting_spell(MUSIC_HERO) - return TRUE - end, - ["info"] = function() - return "" - end, + ["lasting"] = function() return music_heroic_ballad_lasting() end, + ["spell"] = function() return music_heroic_ballad_spell() end, + ["info"] = function() return music_heroic_ballad_info() end, ["desc"] = { "Increases melee accuracy", "At level 10 it increases it even more and reduces armour a bit", @@ -222,24 +160,9 @@ MUSIC_TIME = add_spell ["stat"] = A_CHR, ["random"] = SKILL_MUSIC, ["pval"] = 3, - ["lasting"] = function() - set_shield(5, 10 + get_level(MUSIC_TIME, 50), 0, 0, 0) - if get_level(MUSIC_TIME) >= 15 then - set_fast(5, 7 + get_level(MUSIC_TIME, 10)) - end - return get_mana(MUSIC_TIME) - end, - ["spell"] = function() - player.start_lasting_spell(MUSIC_TIME) - return TRUE - end, - ["info"] = function() - if get_level(MUSIC_TIME) >= 15 then - return "AC "..(10 + get_level(MUSIC_TIME, 50)).." speed "..(7 + get_level(MUSIC_TIME, 10)) - else - return "AC "..(10 + get_level(MUSIC_TIME, 50)) - end - end, + ["lasting"] = function() return music_hobbit_melodies_lasting() end, + ["spell"] = function() return music_hobbit_melodies_spell() end, + ["info"] = function() return music_hobbit_melodies_info() end, ["desc"] = { "Greatly increases your reflexes allowing you to block more melee blows.", "At level 15 it also makes you faster.", @@ -258,24 +181,9 @@ MUSIC_MIND = add_spell ["stat"] = A_CHR, ["random"] = SKILL_MUSIC, ["pval"] = 4, - ["lasting"] = function() - set_tim_esp(5) - if get_level(MUSIC_MIND) >= 10 then - fire_ball(GF_IDENTIFY, 0, 1, 1 + get_level(MUSIC_MIND, 3, 0)) - end - return get_mana(MUSIC_MIND) - end, - ["spell"] = function() - player.start_lasting_spell(MUSIC_MIND) - return TRUE - end, - ["info"] = function() - if get_level(MUSIC_MIND) >= 10 then - return "rad "..(1 + get_level(MUSIC_MIND, 3, 0)) - else - return "" - end - end, + ["lasting"] = function() return music_clairaudience_lasting() end, + ["spell"] = function() return music_clairaudience_spell() end, + ["info"] = function() return music_clairaudience_info() end, ["desc"] = { "Allows you to sense monster minds as long as you sing.", "At level 10 it identifies all objects in a radius on the floor,", @@ -297,17 +205,8 @@ MUSIC_BLOW = add_spell ["stat"] = A_CHR, ["random"] = SKILL_MUSIC, ["pval"] = 1, - ["spell"] = function() - fire_ball(GF_SOUND, - 0, - damroll(2 + get_level(MUSIC_BLOW, 10, 0), 4 + get_level(MUSIC_BLOW, 40, 0)), - 1 + get_level(MUSIC_BLOW, 12, 0) - ) - return TRUE - end, - ["info"] = function() - return "dam "..(2 + get_level(MUSIC_BLOW, 10, 0)).."d"..(4 + get_level(MUSIC_BLOW, 40, 0)).." rad "..(1 + get_level(MUSIC_BLOW, 12, 0)) - end, + ["spell"] = function() return music_blow_spell() end, + ["info"] = function() return music_blow_info() end, ["desc"] = { "Produces a powerful, blowing, sound all around you.", } @@ -324,17 +223,8 @@ MUSIC_WIND = add_spell ["stat"] = A_CHR, ["random"] = SKILL_MUSIC, ["pval"] = 2, - ["spell"] = function() - fire_ball(GF_AWAY_ALL, - 0, - 10 + get_level(MUSIC_BLOW, 40, 0), - 1 + get_level(MUSIC_BLOW, 12, 0) - ) - return TRUE - end, - ["info"] = function() - return "dist "..(10 + get_level(MUSIC_BLOW, 40, 0)).." rad "..(1 + get_level(MUSIC_BLOW, 12, 0)) - end, + ["spell"] = function() return music_gush_of_wind_spell() end, + ["info"] = function() return music_gush_of_wind_info() end, ["desc"] = { "Produces a outgoing gush of wind that sends monsters away.", } @@ -351,13 +241,8 @@ MUSIC_YLMIR = add_spell ["stat"] = A_CHR, ["random"] = SKILL_MUSIC, ["pval"] = 3, - ["spell"] = function() - earthquake(player.py, player.px, 2 + get_level(SHAKE, 10)) - return TRUE - end, - ["info"] = function() - return "rad "..(2 + get_level(SHAKE, 10)) - end, + ["spell"] = function() return music_horns_of_ylmir_spell() end, + ["info"] = function() return music_horns_of_ylmir_info() end, ["desc"] = { "Produces an earth shaking sound.", } @@ -374,70 +259,10 @@ MUSIC_AMBARKANTA = add_spell ["stat"] = A_CHR, ["random"] = SKILL_MUSIC, ["pval"] = 4, - ["spell"] = function() - alter_reality() - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return music_ambarkanta_spell() end, + ["info"] = function() return music_ambarkanta_info() end, ["desc"] = { "Produces a reality shaking sound that transports you to a nearly", "identical reality.", } } - - ---[[ -MUSIC_ = add_spell -{ - ["name"] = "(I)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 1, - ["mana"] = 0, - ["mana_max"] = 0, - ["fail"] = 20, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 1, - ["lasting"] = function() - return get_mana(MUSIC_) - end, - ["spell"] = function() - player.start_lasting_spell(MUSIC_) - return TRUE - end, - ["info"] = function() - return "" - end, - ["desc"] = { - "", - "Consumes the amount of mana each turn.", - } -} - -or - -MUSIC_ = add_spell -{ - ["name"] = "(I)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 1, - ["mana"] = 0, - ["mana_max"] = 0, - ["fail"] = 20, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 1, - ["spell"] = function() - - return TRUE - end, - ["info"] = function() - return "" - end, - ["desc"] = { - "", - } -} -]] diff --git a/lib/scpt/s_music.lua b/lib/scpt/s_music.lua index 9da6393a..45255485 100644 --- a/lib/scpt/s_music.lua +++ b/lib/scpt/s_music.lua @@ -13,13 +13,8 @@ MUSIC_STOP = add_spell ["random"] = SKILL_MUSIC, ["pval"] = 1, ["blind"] = FALSE, - ["spell"] = function() - player.start_lasting_spell(0) - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return music_stop_singing_spell() end, + ["info"] = function() return music_stop_singing_info() end, ["desc"] = { "Stops the current song, if any." } @@ -38,17 +33,9 @@ MUSIC_HOLD = add_spell ["random"] = SKILL_MUSIC, ["pval"] = 1, ["blind"] = FALSE, - ["lasting"] = function() - project_los(GF_OLD_SLOW, 10 + get_level(MUSIC_HOLD, 100)) - return get_mana(MUSIC_HOLD) - end, - ["spell"] = function() - player.start_lasting_spell(MUSIC_HOLD) - return TRUE - end, - ["info"] = function() - return "power "..(10 + get_level(MUSIC_HOLD, 100)) - end, + ["lasting"] = function() return music_holding_pattern_lasting() end, + ["spell"] = function() return music_holding_pattern_spell() end, + ["info"] = function() return music_holding_pattern_info() end, ["desc"] = { "Slows down all monsters listening the song.", "Consumes the amount of mana each turn.", @@ -67,17 +54,9 @@ MUSIC_CONF = add_spell ["random"] = SKILL_MUSIC, ["pval"] = 2, ["blind"] = FALSE, - ["lasting"] = function() - project_los(GF_OLD_CONF, 10 + get_level(MUSIC_CONF, 100)) - return get_mana(MUSIC_CONF) - end, - ["spell"] = function() - player.start_lasting_spell(MUSIC_CONF) - return TRUE - end, - ["info"] = function() - return "power "..(10 + get_level(MUSIC_CONF, 100)) - end, + ["lasting"] = function() return music_illusion_pattern_lasting() end, + ["spell"] = function() return music_illusion_pattern_spell() end, + ["info"] = function() return music_illusion_pattern_info() end, ["desc"] = { "Tries to confuse all monsters listening the song.", "Consumes the amount of mana each turn.", @@ -96,17 +75,9 @@ MUSIC_STUN = add_spell ["random"] = SKILL_MUSIC, ["pval"] = 4, ["blind"] = FALSE, - ["lasting"] = function() - project_los(GF_STUN, 10 + get_level(MUSIC_STUN, 90)) - return get_mana(MUSIC_STUN) - end, - ["spell"] = function() - player.start_lasting_spell(MUSIC_STUN) - return TRUE - end, - ["info"] = function() - return "power "..(10 + get_level(MUSIC_STUN, 90)) - end, + ["lasting"] = function() return music_stun_pattern_lasting() end, + ["spell"] = function() return music_stun_pattern_spell() end, + ["info"] = function() return music_stun_pattern_info() end, ["desc"] = { "Stuns all monsters listening the song.", "Consumes the amount of mana each turn.", @@ -126,17 +97,9 @@ MUSIC_LITE = add_spell ["random"] = SKILL_MUSIC, ["blind"] = FALSE, ["pval"] = 1, - ["lasting"] = function() - set_lite(5) - return 1 - end, - ["spell"] = function() - player.start_lasting_spell(MUSIC_LITE) - return TRUE - end, - ["info"] = function() - return "" - end, + ["lasting"] = function() return music_song_of_the_sun_lasting() end, + ["spell"] = function() return music_song_of_the_sun_spell() end, + ["info"] = function() return music_song_of_the_sun_info() end, ["desc"] = { "Provides light as long as you sing.", "Consumes the amount of mana each turn.", @@ -154,17 +117,9 @@ MUSIC_HEAL = add_spell ["stat"] = A_CHR, ["random"] = SKILL_MUSIC, ["pval"] = 2, - ["lasting"] = function() - hp_player(7 + get_level(MUSIC_HEAL, 100)) - return get_mana(MUSIC_HEAL) - end, - ["spell"] = function() - player.start_lasting_spell(MUSIC_HEAL) - return TRUE - end, - ["info"] = function() - return "heal "..(7 + get_level(MUSIC_HEAL, 100)).."/turn" - end, + ["lasting"] = function() return music_flow_of_life_lasting() end, + ["spell"] = function() return music_flow_of_life_spell() end, + ["info"] = function() return music_flow_of_life_info() end, ["desc"] = { "Heals you as long as you sing.", "Consumes the amount of mana each turn.", @@ -182,26 +137,9 @@ MUSIC_HERO = add_spell ["stat"] = A_CHR, ["random"] = SKILL_MUSIC, ["pval"] = 2, - ["lasting"] = function() - set_hero(5) - if get_level(MUSIC_HERO) >= 10 then - set_shero(5) - end - if get_level(MUSIC_HERO) >= 20 then - set_strike(5) - end - if get_level(MUSIC_HERO) >= 25 then - set_oppose_cc(5) - end - return get_mana(MUSIC_HERO) - end, - ["spell"] = function() - player.start_lasting_spell(MUSIC_HERO) - return TRUE - end, - ["info"] = function() - return "" - end, + ["lasting"] = function() return music_heroic_ballad_lasting() end, + ["spell"] = function() return music_heroic_ballad_spell() end, + ["info"] = function() return music_heroic_ballad_info() end, ["desc"] = { "Increases melee accuracy", "At level 10 it increases it even more and reduces armour a bit", @@ -222,24 +160,9 @@ MUSIC_TIME = add_spell ["stat"] = A_CHR, ["random"] = SKILL_MUSIC, ["pval"] = 3, - ["lasting"] = function() - set_shield(5, 10 + get_level(MUSIC_TIME, 50), 0, 0, 0) - if get_level(MUSIC_TIME) >= 15 then - set_fast(5, 7 + get_level(MUSIC_TIME, 10)) - end - return get_mana(MUSIC_TIME) - end, - ["spell"] = function() - player.start_lasting_spell(MUSIC_TIME) - return TRUE - end, - ["info"] = function() - if get_level(MUSIC_TIME) >= 15 then - return "AC "..(10 + get_level(MUSIC_TIME, 50)).." speed "..(7 + get_level(MUSIC_TIME, 10)) - else - return "AC "..(10 + get_level(MUSIC_TIME, 50)) - end - end, + ["lasting"] = function() return music_hobbit_melodies_lasting() end, + ["spell"] = function() return music_hobbit_melodies_spell() end, + ["info"] = function() return music_hobbit_melodies_info() end, ["desc"] = { "Greatly increases your reflexes allowing you to block more melee blows.", "At level 15 it also makes you faster.", @@ -258,24 +181,9 @@ MUSIC_MIND = add_spell ["stat"] = A_CHR, ["random"] = SKILL_MUSIC, ["pval"] = 4, - ["lasting"] = function() - set_tim_esp(5) - if get_level(MUSIC_MIND) >= 10 then - fire_ball(GF_IDENTIFY, 0, 1, 1 + get_level(MUSIC_MIND, 3, 0)) - end - return get_mana(MUSIC_MIND) - end, - ["spell"] = function() - player.start_lasting_spell(MUSIC_MIND) - return TRUE - end, - ["info"] = function() - if get_level(MUSIC_MIND) >= 10 then - return "rad "..(1 + get_level(MUSIC_MIND, 3, 0)) - else - return "" - end - end, + ["lasting"] = function() return music_clairaudience_lasting() end, + ["spell"] = function() return music_clairaudience_spell() end, + ["info"] = function() return music_clairaudience_info() end, ["desc"] = { "Allows you to sense monster minds as long as you sing.", "At level 10 it identifies all objects in a radius on the floor,", @@ -297,17 +205,8 @@ MUSIC_BLOW = add_spell ["stat"] = A_CHR, ["random"] = SKILL_MUSIC, ["pval"] = 1, - ["spell"] = function() - fire_ball(GF_SOUND, - 0, - damroll(2 + get_level(MUSIC_BLOW, 10, 0), 4 + get_level(MUSIC_BLOW, 40, 0)), - 1 + get_level(MUSIC_BLOW, 12, 0) - ) - return TRUE - end, - ["info"] = function() - return "dam "..(2 + get_level(MUSIC_BLOW, 10, 0)).."d"..(4 + get_level(MUSIC_BLOW, 40, 0)).." rad "..(1 + get_level(MUSIC_BLOW, 12, 0)) - end, + ["spell"] = function() return music_blow_spell() end, + ["info"] = function() return music_blow_info() end, ["desc"] = { "Produces a powerful, blowing, sound all around you.", } @@ -324,17 +223,8 @@ MUSIC_WIND = add_spell ["stat"] = A_CHR, ["random"] = SKILL_MUSIC, ["pval"] = 2, - ["spell"] = function() - fire_ball(GF_AWAY_ALL, - 0, - 10 + get_level(MUSIC_BLOW, 40, 0), - 1 + get_level(MUSIC_BLOW, 12, 0) - ) - return TRUE - end, - ["info"] = function() - return "dist "..(10 + get_level(MUSIC_BLOW, 40, 0)).." rad "..(1 + get_level(MUSIC_BLOW, 12, 0)) - end, + ["spell"] = function() return music_gush_of_wind_spell() end, + ["info"] = function() return music_gush_of_wind_info() end, ["desc"] = { "Produces a outgoing gush of wind that sends monsters away.", } @@ -351,13 +241,8 @@ MUSIC_YLMIR = add_spell ["stat"] = A_CHR, ["random"] = SKILL_MUSIC, ["pval"] = 3, - ["spell"] = function() - earthquake(player.py, player.px, 2 + get_level(SHAKE, 10)) - return TRUE - end, - ["info"] = function() - return "rad "..(2 + get_level(SHAKE, 10)) - end, + ["spell"] = function() return music_horns_of_ylmir_spell() end, + ["info"] = function() return music_horns_of_ylmir_info() end, ["desc"] = { "Produces an earth shaking sound.", } @@ -374,70 +259,10 @@ MUSIC_AMBARKANTA = add_spell ["stat"] = A_CHR, ["random"] = SKILL_MUSIC, ["pval"] = 4, - ["spell"] = function() - alter_reality() - return TRUE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return music_ambarkanta_spell() end, + ["info"] = function() return music_ambarkanta_info() end, ["desc"] = { "Produces a reality shaking sound that transports you to a nearly", "identical reality.", } } - - ---[[ -MUSIC_ = add_spell -{ - ["name"] = "(I)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 1, - ["mana"] = 0, - ["mana_max"] = 0, - ["fail"] = 20, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 1, - ["lasting"] = function() - return get_mana(MUSIC_) - end, - ["spell"] = function() - player.start_lasting_spell(MUSIC_) - return TRUE - end, - ["info"] = function() - return "" - end, - ["desc"] = { - "", - "Consumes the amount of mana each turn.", - } -} - -or - -MUSIC_ = add_spell -{ - ["name"] = "(I)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 1, - ["mana"] = 0, - ["mana_max"] = 0, - ["fail"] = 20, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 1, - ["spell"] = function() - - return TRUE - end, - ["info"] = function() - return "" - end, - ["desc"] = { - "", - } -} -]] diff --git a/src/defines.h b/src/defines.h index 439048e8..57c4c674 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4087,36 +4087,6 @@ #define ALCHEMIST_ENCHANT_PVAL 0x02 #define ALCHEMIST_ENCHANT_AC 0x04 -/* - * Music songs - */ -#define MUSIC_NONE 0 -#define MUSIC_SLOW 1 -#define MUSIC_CONF 2 -#define MUSIC_STUN 3 -#define MUSIC_LIFE 4 -#define MUSIC_MIND 5 -#define MUSIC_LITE 6 -#define MUSIC_FURY 7 -#define MUSIC_AWARE 8 -#define MUSIC_ID 9 -#define MUSIC_ILLUSION 10 -#define MUSIC_WALL 11 -#define MUSIC_RESIST 12 -#define MUSIC_TIME 13 -#define MUSIC_BETWEEN 14 -#define MUSIC_CHARME 15 -#define MUSIC_VIBRA 16 -#define MUSIC_HOLY 17 -#define MUSIC_HIDE 18 -#define MUSIC_LIBERTY 19 -#define MUSIC_RAISE 20 -#define MUSIC_SHADOW 21 -#define MUSIC_STAR_ID 22 - -#define MAX_MUSIC 23 -#define MAX_MUSICS 11 - /* * Fate */ diff --git a/src/dungeon.c b/src/dungeon.c index fd2cc546..b23a4829 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -950,8 +950,8 @@ static void check_music() if (p_ptr->csp < use_mana) { msg_print("You stop your spell."); - p_ptr->music_extra = MUSIC_NONE; - p_ptr->music_extra2 = MUSIC_NONE; + p_ptr->music_extra = 0; + p_ptr->music_extra2 = 0; } else { diff --git a/src/externs.h b/src/externs.h index 5b935baa..e3ec6ba0 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1780,6 +1780,67 @@ char *device_radagast_info(); bool_ *device_valaroma(); char *device_valaroma_info(); +extern s32b MUSIC_STOP; +extern s32b MUSIC_HOLD; +extern s32b MUSIC_CONF; +extern s32b MUSIC_STUN; +extern s32b MUSIC_LITE; +extern s32b MUSIC_HEAL; +extern s32b MUSIC_HERO; +extern s32b MUSIC_TIME; +extern s32b MUSIC_MIND; +extern s32b MUSIC_BLOW; +extern s32b MUSIC_WIND; +extern s32b MUSIC_YLMIR; +extern s32b MUSIC_AMBARKANTA; + +bool_ *music_stop_singing_spell(); +char *music_stop_singing_info(); + +int music_holding_pattern_lasting(); +bool_ *music_holding_pattern_spell(); +char *music_holding_pattern_info(); + +int music_illusion_pattern_lasting(); +bool_ *music_illusion_pattern_spell(); +char *music_illusion_pattern_info(); + +int music_stun_pattern_lasting(); +bool_ *music_stun_pattern_spell(); +char *music_stun_pattern_info(); + +int music_song_of_the_sun_lasting(); +bool_ *music_song_of_the_sun_spell(); +char *music_song_of_the_sun_info(); + +int music_flow_of_life_lasting(); +bool_ *music_flow_of_life_spell(); +char *music_flow_of_life_info(); + +int music_heroic_ballad_lasting(); +bool_ *music_heroic_ballad_spell(); +char *music_heroic_ballad_info(); + +int music_hobbit_melodies_lasting(); +bool_ *music_hobbit_melodies_spell(); +char *music_hobbit_melodies_info(); + +int music_clairaudience_lasting(); +bool_ *music_clairaudience_spell(); +char *music_clairaudience_info(); + +bool_ *music_blow_spell(); +char *music_blow_info(); + +bool_ *music_gush_of_wind_spell(); +char *music_gush_of_wind_info(); + +bool_ *music_horns_of_ylmir_spell(); +char *music_horns_of_ylmir_info(); + +bool_ *music_ambarkanta_spell(); +char *music_ambarkanta_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index b31ff65b..e032b220 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2783,3 +2783,64 @@ bool_ *device_radagast(); char *device_radagast_info(); bool_ *device_valaroma(); char *device_valaroma_info(); + +extern s32b MUSIC_STOP; +extern s32b MUSIC_HOLD; +extern s32b MUSIC_CONF; +extern s32b MUSIC_STUN; +extern s32b MUSIC_LITE; +extern s32b MUSIC_HEAL; +extern s32b MUSIC_HERO; +extern s32b MUSIC_TIME; +extern s32b MUSIC_MIND; +extern s32b MUSIC_BLOW; +extern s32b MUSIC_WIND; +extern s32b MUSIC_YLMIR; +extern s32b MUSIC_AMBARKANTA; + +bool_ *music_stop_singing_spell(); +char *music_stop_singing_info(); + +int music_holding_pattern_lasting(); +bool_ *music_holding_pattern_spell(); +char *music_holding_pattern_info(); + +int music_illusion_pattern_lasting(); +bool_ *music_illusion_pattern_spell(); +char *music_illusion_pattern_info(); + +int music_stun_pattern_lasting(); +bool_ *music_stun_pattern_spell(); +char *music_stun_pattern_info(); + +int music_song_of_the_sun_lasting(); +bool_ *music_song_of_the_sun_spell(); +char *music_song_of_the_sun_info(); + +int music_flow_of_life_lasting(); +bool_ *music_flow_of_life_spell(); +char *music_flow_of_life_info(); + +int music_heroic_ballad_lasting(); +bool_ *music_heroic_ballad_spell(); +char *music_heroic_ballad_info(); + +int music_hobbit_melodies_lasting(); +bool_ *music_hobbit_melodies_spell(); +char *music_hobbit_melodies_info(); + +int music_clairaudience_lasting(); +bool_ *music_clairaudience_spell(); +char *music_clairaudience_info(); + +bool_ *music_blow_spell(); +char *music_blow_info(); + +bool_ *music_gush_of_wind_spell(); +char *music_gush_of_wind_info(); + +bool_ *music_horns_of_ylmir_spell(); +char *music_horns_of_ylmir_info(); + +bool_ *music_ambarkanta_spell(); +char *music_ambarkanta_info(); diff --git a/src/spells3.c b/src/spells3.c index 6a45a1a3..1cbe0d85 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -133,6 +133,20 @@ s32b DEVICE_THUNDERLORDS; s32b DEVICE_RADAGAST = -1; s32b DEVICE_VALAROMA = -1; +s32b MUSIC_STOP; +s32b MUSIC_HOLD; +s32b MUSIC_CONF; +s32b MUSIC_STUN; +s32b MUSIC_LITE; +s32b MUSIC_HEAL; +s32b MUSIC_HERO; +s32b MUSIC_TIME; +s32b MUSIC_MIND; +s32b MUSIC_BLOW; +s32b MUSIC_WIND; +s32b MUSIC_YLMIR; +s32b MUSIC_AMBARKANTA; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua @@ -3898,3 +3912,299 @@ char *device_valaroma_info() { return ""; } + +void static start_lasting_spell(int spl) +{ + p_ptr->music_extra = -spl; +} + +bool_ *music_stop_singing_spell() +{ + start_lasting_spell(0); + return CAST; +} + +char *music_stop_singing_info() +{ + return ""; +} + +static int holding_pattern_power() +{ + return 10 + get_level_s(MUSIC_HOLD, 100); +} + +int music_holding_pattern_lasting() +{ + project_hack(GF_OLD_SLOW, holding_pattern_power()); + return get_mana(MUSIC_HOLD); +} + +bool_ *music_holding_pattern_spell() +{ + start_lasting_spell(MUSIC_HOLD); + return CAST; +} + +char *music_holding_pattern_info() +{ + static char buf[128]; + sprintf(buf, + "power %d", + holding_pattern_power()); + return buf; +} + +static int illusion_pattern_power() +{ + return 10 + get_level_s(MUSIC_CONF, 100); +} + +int music_illusion_pattern_lasting() +{ + project_hack(GF_OLD_CONF, illusion_pattern_power()); + return get_mana(MUSIC_CONF); +} + +bool_ *music_illusion_pattern_spell() +{ + start_lasting_spell(MUSIC_CONF); + return CAST; +} + +char *music_illusion_pattern_info() +{ + static char buf[128]; + sprintf(buf, + "power %d", + illusion_pattern_power()); + return buf; +} + +static int stun_pattern_power() +{ + return 10 + get_level_s(MUSIC_STUN, 90); +} + +int music_stun_pattern_lasting() +{ + project_hack(GF_STUN, stun_pattern_power()); + return get_mana(MUSIC_STUN); +} + +bool_ *music_stun_pattern_spell() +{ + start_lasting_spell(MUSIC_STUN); + return CAST; +} + +char *music_stun_pattern_info() +{ + static char buf[128]; + sprintf(buf, + "power %d", + stun_pattern_power()); + return buf; +} + +int music_song_of_the_sun_lasting() +{ + set_lite(5); + return 1; +} + +bool_ *music_song_of_the_sun_spell() +{ + start_lasting_spell(MUSIC_LITE); + return CAST; +} + +char *music_song_of_the_sun_info() +{ + return ""; +} + +int flow_of_life_hp() +{ + return 7 + get_level_s(MUSIC_HEAL, 100); +} + +int music_flow_of_life_lasting() +{ + hp_player(flow_of_life_hp()); + return get_mana(MUSIC_HEAL); +} + +bool_ *music_flow_of_life_spell() +{ + start_lasting_spell(MUSIC_HEAL); + return CAST; +} + +char *music_flow_of_life_info() +{ + static char buf[128]; + sprintf(buf, + "heal %d/turn", + flow_of_life_hp()); + return buf; +} + +int music_heroic_ballad_lasting() +{ + set_hero(5); + if (get_level_s(MUSIC_HERO, 50) >= 10) + { + set_shero(5); + } + if (get_level_s(MUSIC_HERO, 50) >= 20) + { + set_strike(5); + } + if (get_level_s(MUSIC_HERO, 50) >= 25) + { + set_oppose_cc(5); + } + return get_mana(MUSIC_HERO); +} + +bool_ *music_heroic_ballad_spell() +{ + start_lasting_spell(MUSIC_HERO); + return CAST; +} + +char *music_heroic_ballad_info() +{ + return ""; +} + +int music_hobbit_melodies_lasting() +{ + set_shield(5, 10 + get_level_s(MUSIC_TIME, 50), 0, 0, 0); + if (get_level_s(MUSIC_TIME, 50) >= 15) + { + set_fast(5, 7 + get_level_s(MUSIC_TIME, 10)); + } + return get_mana(MUSIC_TIME); +} + +bool_ *music_hobbit_melodies_spell() +{ + start_lasting_spell(MUSIC_TIME); + return CAST; +} + +char *music_hobbit_melodies_info() +{ + static char buf[128]; + if (get_level_s(MUSIC_TIME, 50) >= 15) + { + sprintf(buf, "AC " FMTs32b " speed " FMTs32b, + 10 + get_level_s(MUSIC_TIME, 50), + 7 + get_level_s(MUSIC_TIME, 10)); + } + else + { + sprintf(buf, "AC " FMTs32b, + 10 + get_level_s(MUSIC_TIME, 50)); + } + return buf; +} + +int music_clairaudience_lasting() +{ + set_tim_esp(5); + if (get_level_s(MUSIC_MIND, 50) >= 10) + { + fire_ball(GF_IDENTIFY, 0, 1, 1 + get_level(MUSIC_MIND, 3, 0)); + } + return get_mana(MUSIC_MIND); +} + +bool_ *music_clairaudience_spell() +{ + start_lasting_spell(MUSIC_MIND); + return CAST; +} + +char *music_clairaudience_info() +{ + static char buf[128]; + + if (get_level_s(MUSIC_MIND, 50) >= 10) + { + sprintf(buf, "rad " FMTs32b, + 1 + get_level(MUSIC_MIND, 3, 0)); + return buf; + } + else + { + return ""; + } +} + +bool_ *music_blow_spell() +{ + fire_ball(GF_SOUND, + 0, + damroll(2 + get_level(MUSIC_BLOW, 10, 0), 4 + get_level(MUSIC_BLOW, 40, 0)), + 1 + get_level(MUSIC_BLOW, 12, 0)); + return CAST; +} + +char *music_blow_info() +{ + static char buf[128]; + sprintf(buf, + "dam " FMTs32b "d" FMTs32b " rad " FMTs32b, + 2 + get_level(MUSIC_BLOW, 10, 0), + 4 + get_level(MUSIC_BLOW, 40, 0), + 1 + get_level(MUSIC_BLOW, 12, 0)); + return buf; +} + +bool_ *music_gush_of_wind_spell() +{ + fire_ball(GF_AWAY_ALL, + 0, + 10 + get_level(MUSIC_BLOW, 40, 0), + 1 + get_level(MUSIC_BLOW, 12, 0)); + return CAST; +} + +char *music_gush_of_wind_info() +{ + static char buf[128]; + sprintf(buf, + "dist " FMTs32b " rad " FMTs32b, + 10 + get_level(MUSIC_BLOW, 40, 0), + 1 + get_level(MUSIC_BLOW, 12, 0)); + return buf; +} + +bool_ *music_horns_of_ylmir_spell() +{ + earthquake(p_ptr->py, p_ptr->px, 2 + get_level_s(SHAKE, 10)); + return CAST; +} + +char *music_horns_of_ylmir_info() +{ + static char buf[128]; + sprintf(buf, + "rad " FMTs32b, + 2 + get_level_s(SHAKE, 10)); + return buf; +} + +bool_ *music_ambarkanta_spell() +{ + alter_reality(); + return CAST; +} + +char *music_ambarkanta_info() +{ + return ""; +} -- cgit v1.2.3 From 8ba6d76dc7179abe5cba19f422516dead2eceaf4 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 13 May 2012 20:55:29 +0200 Subject: Lua: Move "Aule" spell functions to C --- lib/mods/theme/scpt/s_aule.lua | 157 ++---------------------------- src/externs.h | 14 +++ src/spells.pkg | 14 +++ src/spells3.c | 213 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 250 insertions(+), 148 deletions(-) diff --git a/lib/mods/theme/scpt/s_aule.lua b/lib/mods/theme/scpt/s_aule.lua index d3ca4733..75a121b1 100644 --- a/lib/mods/theme/scpt/s_aule.lua +++ b/lib/mods/theme/scpt/s_aule.lua @@ -13,27 +13,8 @@ AULE_FIREBRAND = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local type, rad - local level = get_level(AULE_FIREBRAND) - type = GF_FIRE - - if (get_level(AULE_FIREBRAND) > 30) then - type = GF_HOLY_FIRE - end - - rad = 0 - if (level >= 15) then - rad = 1 - end - return set_project(level + randint(20), - type, 4 + level, rad, - bor(PROJECT_STOP, PROJECT_KILL)) - end, - ["info"] = function() - local level = get_level(AULE_FIREBRAND) - return "dur "..(level).."+d20 dam "..(4 + level).."/blow" - end, + ["spell"] = function() return aule_firebrand_spell() end, + ["info"] = function() return aule_firebrand_info() end, ["desc"] = { "Imbues your melee weapon with fire to deal more damage", "At level 15 it spreads over a 1 radius zone around your target", @@ -52,58 +33,8 @@ AULE_ENCHANT_WEAPON = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local level = get_level(AULE_ENCHANT_WEAPON) - local num_h, num_d, num_p - - local ret, item, obj - - num_h = 1 + randint(level/12) - num_d = 0 - num_p = 0 - if (level >= 5) then - num_d = 1 + randint(level/12) - end - if (level >= 45) then - num_p = 1 - end - --return enchant_spell(num_h, num_d, 0, num_p) - - ret, item = get_item("Which object do you want to enchant?", - "You have no objects to enchant.", - bor(USE_INVEN), - function (obj) - if obj.name1 > 0 then return FALSE end - if (obj.tval == TV_MSTAFF) then - return TRUE - elseif (obj.tval == TV_BOW) then - return TRUE - elseif (obj.tval == TV_HAFTED) then - return TRUE - elseif (obj.tval == TV_POLEARM) then - return TRUE - elseif (obj.tval == TV_SWORD) then - return TRUE - elseif (obj.tval == TV_AXE) then - return TRUE - end - return FALSE - end - ) - if ret == FALSE then return FALSE end - - obj = get_object(item) - - obj.to_h = obj.to_h + num_h - obj.to_d = obj.to_d + num_h - obj.pval = obj.pval + num_p - - return TRUE - - end, - ["info"] = function() - return "tries "..(1 + get_level(AULE_ENCHANT_WEAPON)/12) - end, + ["spell"] = function() return aule_enchant_weapon_spell() end, + ["info"] = function() return aule_enchant_weapon_info() end, ["desc"] = { "Tries to enchant a weapon to-hit", "At level 5 it also enchants to-dam", @@ -122,66 +53,8 @@ AULE_ENCHANT_ARMOUR = add_spell { ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local level = get_level(AULE_ENCHANT_ARMOUR) - local num_h, num_d, num_a, num_p - local ret, item, obj - - num_a = 1 + randint(level/10) - num_h = 0 - num_d = 0 - num_p = 0 - if (level >= 20) then - num_h = 1 - num_d = 1 - end - if (level >= 40) then - num_p = 1 - end - --return enchant_spell(num_h, num_d, num_a, num_p) - - ret, item = get_item("Which object do you want to enchant?", - "You have no objects to enchant.", - bor(USE_INVEN), - function (obj) - if obj.name1 > 0 then return FALSE end - if (obj.tval == TV_BOOTS) then - return TRUE - elseif (obj.tval == TV_GLOVES) then - return TRUE - elseif (obj.tval == TV_HELM) then - return TRUE - elseif (obj.tval == TV_CROWN) then - return TRUE - elseif (obj.tval == TV_SHIELD) then - return TRUE - elseif (obj.tval == TV_CLOAK) then - return TRUE - elseif (obj.tval == TV_SOFT_ARMOR) then - return TRUE - elseif (obj.tval == TV_HARD_ARMOR) then - return TRUE - elseif (obj.tval == TV_DRAG_ARMOR) then - return TRUE - end - return FALSE - end - ) - if ret == FALSE then return FALSE end - - obj = get_object(item) - - obj.to_h = obj.to_h + num_h - obj.to_d = obj.to_d + num_h - obj.pval = obj.pval + num_p - obj.to_a = obj.to_a + num_h - - return TRUE - - end, - ["info"] = function() - return "tries "..(1 + get_level(AULE_ENCHANT_ARMOUR)/10) - end, + ["spell"] = function() return aule_enchant_armour_spell() end, + ["info"] = function() return aule_enchant_armour_info() end, ["desc"] = { "Tries to enchant a piece of armour", "At level 20 it also enchants to-hit and to-dam", @@ -201,22 +74,10 @@ AULE_CHILD = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local y, x, m_idx - - y, x = find_position(player.py, player.px) - m_idx = place_monster_one(y, x, test_monster_name("Dwarven warrior"), 0, FALSE, MSTATUS_FRIEND) - - if m_idx ~= 0 then - monster_set_level(m_idx, 20 + get_level(AULE_CHILD, 70, 0)) - return TRUE - end - end, - ["info"] = function() - return "level "..(20 + get_level(AULE_CHILD, 70)) - end, + ["spell"] = function() return aule_child_spell() end, + ["info"] = function() return aule_child_info() end, ["desc"] = { "Summons a levelled Dwarven warrior to help you battle the forces", "of Morgoth" } -} \ No newline at end of file +} diff --git a/src/externs.h b/src/externs.h index e3ec6ba0..06e0ec76 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1841,6 +1841,20 @@ char *music_horns_of_ylmir_info(); bool_ *music_ambarkanta_spell(); char *music_ambarkanta_info(); +extern s32b AULE_FIREBRAND; +extern s32b AULE_ENCHANT_WEAPON; +extern s32b AULE_ENCHANT_ARMOUR; +extern s32b AULE_CHILD; + +bool_ *aule_firebrand_spell(); +char *aule_firebrand_info(); +bool_ *aule_enchant_weapon_spell(); +char *aule_enchant_weapon_info(); +bool_ *aule_enchant_armour_spell(); +char *aule_enchant_armour_info(); +bool_ *aule_child_spell(); +char *aule_child_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index e032b220..ac17116b 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2844,3 +2844,17 @@ char *music_horns_of_ylmir_info(); bool_ *music_ambarkanta_spell(); char *music_ambarkanta_info(); + +extern s32b AULE_FIREBRAND; +extern s32b AULE_ENCHANT_WEAPON; +extern s32b AULE_ENCHANT_ARMOUR; +extern s32b AULE_CHILD; + +bool_ *aule_firebrand_spell(); +char *aule_firebrand_info(); +bool_ *aule_enchant_weapon_spell(); +char *aule_enchant_weapon_info(); +bool_ *aule_enchant_armour_spell(); +char *aule_enchant_armour_info(); +bool_ *aule_child_spell(); +char *aule_child_info(); diff --git a/src/spells3.c b/src/spells3.c index 1cbe0d85..15f101de 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -147,6 +147,11 @@ s32b MUSIC_WIND; s32b MUSIC_YLMIR; s32b MUSIC_AMBARKANTA; +s32b AULE_FIREBRAND; +s32b AULE_ENCHANT_WEAPON; +s32b AULE_ENCHANT_ARMOUR; +s32b AULE_CHILD; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua @@ -4208,3 +4213,211 @@ char *music_ambarkanta_info() { return ""; } + +bool_ *aule_firebrand_spell() +{ + int rad = 0; + int type = GF_FIRE; + s32b level = get_level_s(AULE_FIREBRAND, 50); + + if (level > 30) + { + type = GF_HOLY_FIRE; + } + + if (level >= 15) + { + rad = 1; + } + + set_project(level + randint(20), + type, + 4 + level, + rad, + PROJECT_STOP | PROJECT_KILL); + return CAST; +} + +char *aule_firebrand_info() +{ + s32b level = get_level_s(AULE_FIREBRAND, 50); + static char buf[128]; + + sprintf(buf, + "dur " FMTs32b "+d20 dam " FMTs32b "/blow", + level, + 4 + level); + return buf; +} + +static bool_ aule_enchant_weapon_item_tester(object_type *o_ptr) +{ + if (o_ptr->name1 > 0) + { + return FALSE; + } + + switch (o_ptr->tval) + { + case TV_MSTAFF: + case TV_BOW: + case TV_HAFTED: + case TV_POLEARM: + case TV_SWORD: + case TV_AXE: + return TRUE; + + default: + return FALSE; + } +} + +bool_ *aule_enchant_weapon_spell() +{ + s32b level = get_level_s(AULE_ENCHANT_WEAPON, 50); + s16b num_h, num_d, num_p; + int item; + object_type *o_ptr = NULL; + + num_h = 1 + randint(level/12); + num_d = 0; + num_p = 0; + + if (level >= 5) + { + num_d = 1 + randint(level/12); + } + if (level >= 45) + { + num_p = 1; + } + + item_tester_hook = aule_enchant_weapon_item_tester; + if (!get_item(&item, + "Which object do you want to enchant?", + "You have no objects to enchant.", + USE_INVEN)) + { + return NO_CAST; + } + + o_ptr = get_object(item); + + o_ptr->to_h = o_ptr->to_h + num_h; + o_ptr->to_d = o_ptr->to_d + num_d; + o_ptr->pval = o_ptr->pval + num_p; + + return CAST; +} + +char *aule_enchant_weapon_info() +{ + static char buf[128]; + sprintf(buf, + "tries " FMTs32b, + 1 + get_level_s(AULE_ENCHANT_WEAPON, 50)/12); + return buf; +} + +bool_ aule_enchant_armor_item_tester(object_type *o_ptr) +{ + if (o_ptr->name1 > 0) + { + return FALSE; + } + + switch (o_ptr->tval) + { + case TV_BOOTS: + case TV_GLOVES: + case TV_HELM: + case TV_CROWN: + case TV_SHIELD: + case TV_CLOAK: + case TV_SOFT_ARMOR: + case TV_HARD_ARMOR: + case TV_DRAG_ARMOR: + return TRUE; + + default: + return FALSE; + } +} + +bool_ *aule_enchant_armour_spell() +{ + s32b level = get_level_s(AULE_ENCHANT_ARMOUR, 50); + s16b num_h, num_d, num_a, num_p; + int item; + object_type *o_ptr = NULL; + + num_a = 1 + randint(level/10); + num_h = 0; + num_d = 0; + num_p = 0; + if (level >= 20) + { + num_h = 1; + num_d = 1; + } + if (level >= 40) + { + num_p = 1; + } + + item_tester_hook = aule_enchant_armor_item_tester; + if (!get_item(&item, + "Which object do you want to enchant?", + "You have no objects to enchant.", + USE_INVEN)) + { + return NO_CAST; + } + + o_ptr = get_object(item); + + o_ptr->to_h = o_ptr->to_h + num_h; + o_ptr->to_d = o_ptr->to_d + num_d; + o_ptr->pval = o_ptr->pval + num_p; + o_ptr->to_a = o_ptr->to_a + num_a; + + return CAST; +} + +char *aule_enchant_armour_info() +{ + static char buf[128]; + sprintf(buf, + "tries " FMTs32b, + 1 + get_level_s(AULE_ENCHANT_ARMOUR, 50)/10); + return buf; +} + +bool_ *aule_child_spell() +{ + int y, x; + s16b m_idx; + + find_position(p_ptr->py, p_ptr->px, &y, &x); + m_idx = place_monster_one(y, x, test_monster_name("Dwarven warrior"), + 0, FALSE, MSTATUS_FRIEND); + + if (m_idx) + { + monster_set_level(m_idx, 20 + get_level(AULE_CHILD, 70, 0)); + return CAST; + } + else + { + return NO_CAST; + } +} + +char *aule_child_info() +{ + static char buf[128]; + sprintf(buf, + "level " FMTs32b, + 20 + get_level_s(AULE_CHILD, 70)); + return buf; +} -- cgit v1.2.3 From 22290738f1f65c6b11b98c6a2db13f81dacb3d28 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 14 May 2012 07:42:28 +0200 Subject: Lua: Move "Mandos" spell functions to C --- lib/mods/theme/scpt/s_mandos.lua | 111 ++++------------------------------- src/defines.h | 1 - src/dungeon.c | 9 ++- src/externs.h | 16 ++++- src/loadsave.c | 2 +- src/player.pkg | 1 - src/spells.pkg | 14 +++++ src/spells3.c | 123 +++++++++++++++++++++++++++++++++++++++ src/types.h | 1 + src/util.pkg | 6 -- src/variable.c | 5 -- src/xtra1.c | 2 +- src/xtra2.c | 11 ++++ 13 files changed, 182 insertions(+), 120 deletions(-) diff --git a/lib/mods/theme/scpt/s_mandos.lua b/lib/mods/theme/scpt/s_mandos.lua index 90876930..48b73c27 100644 --- a/lib/mods/theme/scpt/s_mandos.lua +++ b/lib/mods/theme/scpt/s_mandos.lua @@ -2,42 +2,6 @@ BOOK_MANDOS = 66 --- precognition timer for high-level spell [from T-Plus by Ingeborg S. Norden] - -function set_precognition(v) - local notice = FALSE - if (v < 0) then v = 0 end - if (v > 10000) then v = 10000 end - - -- Check if the state will change - if (v > 0) and (tim_precognition == 0) then - msg_print("You feel able to predict the future.") - notice = TRUE - elseif (v == 0) and (tim_precognition > 0) then - msg_print("You feel less able to predict the future.") - notice = TRUE - end - - -- set the new value - tim_precognition = v - - if (notice == TRUE) then - player.update = bor(player.update, PU_BONUS) - disturb(0,0) - end - return notice -end - --- related hooks - -add_hooks{ - [HOOK_PROCESS_WORLD] = function() - if (tim_precognition > 0) then - set_precognition(tim_precognition - 1) - end - end, -} - -- "Tears of Luthien" based on Holy Word from T-Plus MANDOS_TEARS_LUTHIEN = add_spell { @@ -50,25 +14,16 @@ MANDOS_TEARS_LUTHIEN = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local level = get_level(MANDOS_TEARS_LUTHIEN, 30) - local obvious = hp_player(10 * level) - obvious = is_obvious (set_stun(0), obvious) - obvious = is_obvious (set_cut(0), obvious) - obvious = is_obvious (set_afraid(0), obvious) - return obvious - end, - ["info"] = function() - local level = get_level(MANDOS_TEARS_LUTHIEN, 30) - return "heals "..(10 * level) - end, + ["spell"] = function() return mandos_tears_of_luthien_spell() end, + ["info"] = function() return mandos_tears_of_luthien_info() end, ["desc"] = { "Calls upon the spirit of Luthien to ask Mandos for healing and succour." } } -- "Spirit of the Feanturi" based on Restore Mind from T-Plus -MANDOS_SPIRIT_FEANTURI = add_spell { +MANDOS_SPIRIT_FEANTURI = add_spell +{ ["name"] = "Feanturi", ["school"] = {SCHOOL_MANDOS}, ["level"] = 10, @@ -79,33 +34,8 @@ MANDOS_SPIRIT_FEANTURI = add_spell { ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local level = get_level(MANDOS_SPIRIT_FEANTURI, 50) - local obvious - obvious = set_afraid(0) - obvious = is_obvious(set_confused(0), obvious) - - if level >= 20 then - obvious = is_obvious(do_res_stat(A_WIS, TRUE), obvious) - obvious = is_obvious(do_res_stat(A_INT, TRUE), obvious) - end - - if level >= 30 then - obvious = is_obvious(set_image(0), obvious) - obvious = is_obvious(heal_insanity(player.msane * level / 100), obvious) - end - - return obvious - end, - - ["info"] = function() - local level = get_level(MANDOS_SPIRIT_FEANTURI, 50) - if level >= 20 then - return "heals "..level.."%" - else - return "" - end - end, + ["spell"] = function() return mandos_spirit_of_the_feanturi_spell() end, + ["info"] = function() return mandos_spirit_of_the_feanturi_info() end, ["desc"] = { "Channels the power of Mandos to cure fear and confusion.", "At level 20 it restores lost INT and WIS", @@ -127,12 +57,8 @@ MANDOS_TALE_DOOM = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - return set_precognition(5 + get_level(MANDOS_TALE_DOOM,10)) - end, - ["info"] = function() - return "dur "..(5 + get_level(MANDOS_TALE_DOOM,10)) - end, + ["spell"] = function() return mandos_tale_of_doom_spell() end, + ["info"] = function() return mandos_tale_of_doom_info() end, ["desc"] = { "Allows you to predict the future for a short time." } @@ -140,7 +66,6 @@ MANDOS_TALE_DOOM = add_spell -- "Call to the Halls" based on Call Blessed Soul from T-Plus MANDOS_CALL_HALLS= add_spell - { ["name"] = "Call to the Halls", ["school"] = {SCHOOL_MANDOS}, @@ -151,24 +76,8 @@ MANDOS_CALL_HALLS= add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local y, x, m_idx - local summons = - { - test_monster_name("Experienced spirit"), - test_monster_name("Wise spirit"), - } - y, x = find_position(player.py, player.px) - m_idx = place_monster_one(y, x, summons[rand_range(1, 2)], 0, FALSE, MSTATUS_FRIEND) - if m_idx ~= 0 then - monster_set_level(m_idx, 20 + get_level(MANDOS_CALL_HALLS, 70, 0)) - return TRUE - end - end, - - ["info"] = function() - return "level "..(get_level(MANDOS_CALL_HALLS, 70)) - end, + ["spell"] = function() return mandos_call_to_the_halls_spell() end, + ["info"] = function() return mandos_call_to_the_halls_info() end, ["desc"] = { "Summons a leveled spirit from the Halls of Mandos", "to fight for you." diff --git a/src/defines.h b/src/defines.h index 57c4c674..b4a02a11 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4493,7 +4493,6 @@ #define HOOK_LEVEL_REGEN 42 #define HOOK_LEVEL_END_GEN 43 #define HOOK_BUILDING_ACTION 44 -#define HOOK_PROCESS_WORLD 45 #define HOOK_WIELD_SLOT 46 #define HOOK_STORE_STOCK 47 #define HOOK_STORE_BUY 48 diff --git a/src/dungeon.c b/src/dungeon.c index b23a4829..e60f1ef0 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -1325,9 +1325,6 @@ static void process_world(void) */ if (dun_level || (!p_ptr->wild_mode)) { - /* Let the script live! */ - process_hooks(HOOK_PROCESS_WORLD, "()"); - /* Handle corruptions */ process_world_corruptions(); @@ -2150,6 +2147,12 @@ static void process_world(void) (void)set_tim_breath(p_ptr->tim_magic_breath - 1, TRUE); } + /* Timed precognition */ + if (p_ptr->tim_precognition > 0) + { + set_tim_precognition(p_ptr->tim_precognition - 1); + } + /* Timed regen */ if (p_ptr->tim_regen) { diff --git a/src/externs.h b/src/externs.h index 06e0ec76..233f7ea3 100644 --- a/src/externs.h +++ b/src/externs.h @@ -594,7 +594,6 @@ extern s32b DUNGEON_ASTRAL_WILD_X; extern s32b DUNGEON_ASTRAL_WILD_Y; extern deity_type deity_info[MAX_GODS]; extern timer_type *gl_timers; -extern s16b tim_precognition; extern const char *get_version_string(); /* plots.c */ @@ -1855,6 +1854,20 @@ char *aule_enchant_armour_info(); bool_ *aule_child_spell(); char *aule_child_info(); +extern s32b MANDOS_TEARS_LUTHIEN; +extern s32b MANDOS_SPIRIT_FEANTURI; +extern s32b MANDOS_TALE_DOOM; +extern s32b MANDOS_CALL_HALLS; + +bool_ *mandos_tears_of_luthien_spell(); +char *mandos_tears_of_luthien_info(); +bool_ *mandos_spirit_of_the_feanturi_spell(); +char *mandos_spirit_of_the_feanturi_info(); +bool_ *mandos_tale_of_doom_spell(); +char *mandos_tale_of_doom_info(); +bool_ *mandos_call_to_the_halls_spell(); +char *mandos_call_to_the_halls_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); @@ -2021,6 +2034,7 @@ extern bool_ set_disrupt_shield(int v); extern bool_ set_prob_travel(int v); extern bool_ set_absorb_soul(int v); extern bool_ set_tim_breath(int v, bool_ magical); +extern bool_ set_tim_precognition(int v); extern bool_ set_tim_deadly(int v); extern bool_ set_tim_res_time(int v); extern bool_ set_tim_reflect(int v); diff --git a/src/loadsave.c b/src/loadsave.c index ad982e8d..40718194 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -513,7 +513,7 @@ static bool_ do_extra(int flag) do_s16b(&p_ptr->blessed, flag); do_s16b(&p_ptr->control, flag); do_byte(&p_ptr->control_dir, flag); - do_s16b(&tim_precognition, flag); + do_s16b(&p_ptr->tim_precognition, flag); do_s16b(&p_ptr->tim_thunder, flag); do_s16b(&p_ptr->tim_thunder_p1, flag); do_s16b(&p_ptr->tim_thunder_p2, flag); diff --git a/src/player.pkg b/src/player.pkg index fdde5229..9115d7cf 100644 --- a/src/player.pkg +++ b/src/player.pkg @@ -2633,7 +2633,6 @@ extern void apply_flags(u32b f1, u32b f2, u32b f3, u32b f4, u32b f5, u32b esp, s /** * Timered precognition */ -extern s16b tim_precognition; /** @fn set_tim_thunder(int v, int p1, int p2) diff --git a/src/spells.pkg b/src/spells.pkg index ac17116b..1b253e12 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2858,3 +2858,17 @@ bool_ *aule_enchant_armour_spell(); char *aule_enchant_armour_info(); bool_ *aule_child_spell(); char *aule_child_info(); + +extern s32b MANDOS_TEARS_LUTHIEN; +extern s32b MANDOS_SPIRIT_FEANTURI; +extern s32b MANDOS_TALE_DOOM; +extern s32b MANDOS_CALL_HALLS; + +bool_ *mandos_tears_of_luthien_spell(); +char *mandos_tears_of_luthien_info(); +bool_ *mandos_spirit_of_the_feanturi_spell(); +char *mandos_spirit_of_the_feanturi_info(); +bool_ *mandos_tale_of_doom_spell(); +char *mandos_tale_of_doom_info(); +bool_ *mandos_call_to_the_halls_spell(); +char *mandos_call_to_the_halls_info(); diff --git a/src/spells3.c b/src/spells3.c index 15f101de..355d94e4 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -152,6 +152,11 @@ s32b AULE_ENCHANT_WEAPON; s32b AULE_ENCHANT_ARMOUR; s32b AULE_CHILD; +s32b MANDOS_TEARS_LUTHIEN = -1; +s32b MANDOS_SPIRIT_FEANTURI = -1; +s32b MANDOS_TALE_DOOM = -1; +s32b MANDOS_CALL_HALLS = -1; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua @@ -4421,3 +4426,121 @@ char *aule_child_info() 20 + get_level_s(AULE_CHILD, 70)); return buf; } + +static int tears_of_luthien_hp() +{ + return 10 * get_level_s(MANDOS_TEARS_LUTHIEN, 30); +} + +bool_ *mandos_tears_of_luthien_spell() +{ + hp_player(tears_of_luthien_hp()); + set_stun(0); + set_cut(0); + set_afraid(0); + return CAST; +} + +char *mandos_tears_of_luthien_info() +{ + static char buf[128]; + sprintf(buf, + "heals %d", + tears_of_luthien_hp()); + return buf; +} + +bool_ *mandos_spirit_of_the_feanturi_spell() +{ + s32b level = get_level_s(MANDOS_SPIRIT_FEANTURI, 50); + + set_afraid(0); + set_confused(0); + + if (level >= 20) + { + do_res_stat(A_WIS, TRUE); + do_res_stat(A_INT, TRUE); + } + + if (level >= 30) + { + set_image(0); + heal_insanity(p_ptr->msane * level / 100); + } + + return CAST; +} + +char *mandos_spirit_of_the_feanturi_info() +{ + static char buf[128]; + s32b level = get_level_s(MANDOS_SPIRIT_FEANTURI, 50) ; + if (level >= 20) + { + sprintf(buf, "heals " FMTs32b "%%", level); + return buf; + } + else + { + return ""; + } +} + +static int tale_of_doom_duration() +{ + return 5 + get_level_s(MANDOS_TALE_DOOM,10); +} + +bool_ *mandos_tale_of_doom_spell() +{ + set_tim_precognition(tale_of_doom_duration()); + return CAST; +} + +char *mandos_tale_of_doom_info() +{ + static char buf[128]; + sprintf(buf, + "dur %d", + tale_of_doom_duration()); + return buf; +} + +int call_to_the_halls_mlev() +{ + return 20 + get_level(MANDOS_CALL_HALLS, 70, 0); +} + +bool_ *mandos_call_to_the_halls_spell() +{ +#define N_SUMMONS 2 + int y, x; + s16b m_idx, r_idx; + s16b summons[N_SUMMONS] = { + test_monster_name("Experienced spirit"), + test_monster_name("Wise spirit"), + }; + + r_idx = summons[rand_int(N_SUMMONS)]; + assert(r_idx >= 0); + + find_position(p_ptr->py, p_ptr->px, &y, &x); + m_idx = place_monster_one(y, x, r_idx, 0, FALSE, MSTATUS_FRIEND); + if (m_idx) + { + monster_set_level(m_idx, call_to_the_halls_mlev()); + return CAST; + } + return NO_CAST; +#undef N_SUMMONS +} + +char *mandos_call_to_the_halls_info() +{ + static char buf[128]; + sprintf(buf, + "level %d", + call_to_the_halls_mlev()); + return buf; +} diff --git a/src/types.h b/src/types.h index 6066e215..8d12fa68 100644 --- a/src/types.h +++ b/src/types.h @@ -1587,6 +1587,7 @@ struct player_type s16b absorb_soul; /* Timed soul absordtion */ s16b tim_magic_breath; /* Magical breathing -- can breath anywhere */ s16b tim_water_breath; /* Water breathing -- can breath underwater */ + s16b tim_precognition; /* Timed precognition */ s16b immov_cntr; /* Timed -- Last ``immovable'' command. */ diff --git a/src/util.pkg b/src/util.pkg index e6f0294f..2ec70acf 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -524,12 +524,6 @@ typedef unsigned int u32b; */ #define HOOK_BUILDING_ACTION 44 -/** @def HOOK_PROCESS_WORLD - * @brief Update world every ten turns. - * @note (see file dungeon.c) - */ -#define HOOK_PROCESS_WORLD 45 - /** @def HOOK_WIELD_SLOT * @brief Find equipment slot for object.\n * @param Object o_ptr \n the object to wield. diff --git a/src/variable.c b/src/variable.c index 11019a22..105bbc7f 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1574,11 +1574,6 @@ s32b DUNGEON_ASTRAL_WILD_Y = 19; */ timer_type *gl_timers = NULL; -/* - * Timered precognition. - */ -s16b tim_precognition = 0; - /** * Get the version string. diff --git a/src/xtra1.c b/src/xtra1.c index c20b9036..f393635f 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -3336,7 +3336,7 @@ void calc_bonuses(bool_ silent) } /* Temporary precognition */ - if (tim_precognition > 0) + if (p_ptr->tim_precognition > 0) { apply_flags(0, 0, 0, TR4_PRECOGNITION, 0, 0, 0, 0, 0, 0, 0); } diff --git a/src/xtra2.c b/src/xtra2.c index 7958827b..d78858b3 100644 --- a/src/xtra2.c +++ b/src/xtra2.c @@ -240,6 +240,17 @@ bool_ set_tim_breath(int v, bool_ magical) } } +/* + * Set timered precognition + */ +bool_ set_tim_precognition(int v) +{ + return set_simple_field( + &p_ptr->tim_precognition, v, + TERM_WHITE, "You feel able to predict the future.", + TERM_WHITE, "You feel less able to predict the future."); +} + /* * Set "p_ptr->absorb_soul" * notice observable changes -- cgit v1.2.3 From f2163c387bfb5c8746e832a1f7e72355d19b40f0 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 15 May 2012 05:57:34 +0200 Subject: Lua: Move "Ulmo" spell functions to C --- lib/mods/theme/scpt/s_ulmo.lua | 78 ++------------------ src/externs.h | 14 ++++ src/spells.pkg | 14 ++++ src/spells3.c | 163 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 199 insertions(+), 70 deletions(-) diff --git a/lib/mods/theme/scpt/s_ulmo.lua b/lib/mods/theme/scpt/s_ulmo.lua index 81f5f739..02661ca3 100644 --- a/lib/mods/theme/scpt/s_ulmo.lua +++ b/lib/mods/theme/scpt/s_ulmo.lua @@ -2,10 +2,6 @@ BOOK_ULMO = 65 -function get_belegaer_damage() - return get_level(ULMO_BELEGAER, 10), 3 + get_level(ULMO_BELEGAER, 35) -end - -- "Song of Belegaer" copied from Geyser ULMO_BELEGAER = add_spell { @@ -18,17 +14,8 @@ ULMO_BELEGAER = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local ret, dir - ret, dir = get_aim_dir() - if ret == FALSE then return end - return fire_bolt_or_beam(2 * get_level(ULMO_BELEGAER, 85), GF_WATER, dir, damroll(get_belegaer_damage())) - end, - ["info"] = function() - local n, d - n, d = get_belegaer_damage() - return "dam "..n.."d"..d - end, + ["spell"] = function() return ulmo_song_of_belegaer_spell() end, + ["info"] = function() return ulmo_song_of_belegaer_info() end, ["desc"] = { "Channels the power of the Great Sea into your fingertips.", @@ -48,28 +35,8 @@ ULMO_DRAUGHT_ULMONAN = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local level = get_level(ULMO_DRAUGHT_ULMONAN, 50) - local obvious = hp_player(5 * level) - obvious = is_obvious(set_poisoned(0), obvious) - obvious = is_obvious(set_cut(0), obvious) - obvious = is_obvious(set_stun(0), obvious) - obvious = is_obvious(set_blind(0), obvious) - if level >= 10 then - obvious = is_obvious(do_res_stat(A_STR, TRUE), obvious) - obvious = is_obvious(do_res_stat(A_CON, TRUE), obvious) - obvious = is_obvious(do_res_stat(A_DEX, TRUE), obvious) - end - if level >= 20 then - obvious = is_obvious(set_parasite(0, 0), obvious) - obvious = is_obvious(set_mimic(0, 0, 0), obvious) - end - return obvious - end, - ["info"] = function() - local level = get_level(ULMO_DRAUGHT_ULMONAN, 50) - return "cure "..(5 * level) - end, + ["spell"] = function() return ulmo_draught_of_ulmonan_spell() end, + ["info"] = function() return ulmo_draught_of_ulmonan_info() end, ["desc"] = { "Fills you with a draught with powerful curing effects,", "prepared by Ulmo himself.", @@ -92,24 +59,8 @@ ULMO_CALL_ULUMURI = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local y, x, m_idx - local summons = - { - test_monster_name("Water spirit"), - test_monster_name("Water elemental"), - } - y, x = find_position(player.py, player.px) - m_idx = place_monster_one(y, x, summons[rand_range(1, 2)], 0, FALSE, MSTATUS_FRIEND) - if m_idx ~= 0 then - monster_set_level(m_idx, 30 + get_level(ULMO_CALL_ULUMURI, 70, 0)) - return TRUE - end - end, - - ["info"] = function() - return "level "..(get_level(ULMO_CALL_ULUMURI, 70)) - end, + ["spell"] = function() return ulmo_call_of_the_ulumuri_spell() end, + ["info"] = function() return ulmo_call_of_the_ulumuri_info() end, ["desc"] = { "Summons a leveled water spirit or elemental", "to fight for you", @@ -129,21 +80,8 @@ ULMO_WRATH = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local ret, dir, type - if (get_level(ULMO_WRATH, 50) >= 30) then - type = GF_WAVE - else - type = GF_WATER - end - ret, dir = get_aim_dir() - if ret == FALSE then return end - fire_wall(type, dir, 40 + get_level(ULMO_WRATH, 150), 10 + get_level(ULMO_WRATH, 14)) - return TRUE - end, - ["info"] = function() - return "dam "..(40 + get_level(ULMO_WRATH, 150)).." dur "..(10 + get_level(ULMO_WRATH, 14)) - end, + ["spell"] = function() return ulmo_wrath_of_ulmo_spell() end, + ["info"] = function() return ulmo_wrath_of_ulmo_info() end, ["desc"] = { "Conjures up a sea storm.", "At level 30 it turns into a more forceful storm." diff --git a/src/externs.h b/src/externs.h index 233f7ea3..ac9bd360 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1868,6 +1868,20 @@ char *mandos_tale_of_doom_info(); bool_ *mandos_call_to_the_halls_spell(); char *mandos_call_to_the_halls_info(); +extern s32b ULMO_BELEGAER; +extern s32b ULMO_DRAUGHT_ULMONAN; +extern s32b ULMO_CALL_ULUMURI; +extern s32b ULMO_WRATH; + +bool_ *ulmo_song_of_belegaer_spell(); +char *ulmo_song_of_belegaer_info(); +bool_ *ulmo_draught_of_ulmonan_spell(); +char *ulmo_draught_of_ulmonan_info(); +bool_ *ulmo_call_of_the_ulumuri_spell(); +char *ulmo_call_of_the_ulumuri_info(); +bool_ *ulmo_wrath_of_ulmo_spell(); +char *ulmo_wrath_of_ulmo_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index 1b253e12..7ec49906 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2872,3 +2872,17 @@ bool_ *mandos_tale_of_doom_spell(); char *mandos_tale_of_doom_info(); bool_ *mandos_call_to_the_halls_spell(); char *mandos_call_to_the_halls_info(); + +extern s32b ULMO_BELEGAER; +extern s32b ULMO_DRAUGHT_ULMONAN; +extern s32b ULMO_CALL_ULUMURI; +extern s32b ULMO_WRATH; + +bool_ *ulmo_song_of_belegaer_spell(); +char *ulmo_song_of_belegaer_info(); +bool_ *ulmo_draught_of_ulmonan_spell(); +char *ulmo_draught_of_ulmonan_info(); +bool_ *ulmo_call_of_the_ulumuri_spell(); +char *ulmo_call_of_the_ulumuri_info(); +bool_ *ulmo_wrath_of_ulmo_spell(); +char *ulmo_wrath_of_ulmo_info(); diff --git a/src/spells3.c b/src/spells3.c index 355d94e4..cf9632b7 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -157,6 +157,11 @@ s32b MANDOS_SPIRIT_FEANTURI = -1; s32b MANDOS_TALE_DOOM = -1; s32b MANDOS_CALL_HALLS = -1; +s32b ULMO_BELEGAER; +s32b ULMO_DRAUGHT_ULMONAN; +s32b ULMO_CALL_ULUMURI; +s32b ULMO_WRATH; + /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua @@ -4544,3 +4549,161 @@ char *mandos_call_to_the_halls_info() call_to_the_halls_mlev()); return buf; } + +static void get_belegaer_damage(int *dice, int *sides) +{ + *dice = get_level_s(ULMO_BELEGAER, 10); + *sides = 3 + get_level_s(ULMO_BELEGAER, 35); +} + +bool_ *ulmo_song_of_belegaer_spell() +{ + int dir, dice, sides; + + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + get_belegaer_damage(&dice, &sides); + fire_bolt_or_beam(2 * get_level_s(ULMO_BELEGAER, 85), + GF_WATER, + dir, + damroll(dice, sides)); + return CAST; +} + +char *ulmo_song_of_belegaer_info() +{ + static char buf[128]; + int dice, sides; + + get_belegaer_damage(&dice, &sides); + sprintf(buf, + "dam %dd%d", + dice, + sides); + return buf; +} + +int draught_of_ulmonan_hp() +{ + return 5 * get_level_s(ULMO_DRAUGHT_ULMONAN, 50); +} + +bool_ *ulmo_draught_of_ulmonan_spell() +{ + s32b level = get_level_s(ULMO_DRAUGHT_ULMONAN, 50); + + hp_player(draught_of_ulmonan_hp()); + + set_poisoned(0); + set_cut(0); + set_stun(0); + set_blind(0); + + if (level >= 10) + { + do_res_stat(A_STR, TRUE); + do_res_stat(A_CON, TRUE); + do_res_stat(A_DEX, TRUE); + } + + if (level >= 20) + { + set_parasite(0, 0); + set_mimic(0, 0, 0); + } + + return CAST; +} + +char *ulmo_draught_of_ulmonan_info() +{ + static char buf[128]; + sprintf(buf, + "cure %d", + draught_of_ulmonan_hp()); + return buf; +} + +static int call_of_the_ulumuri_mlev() +{ + return 30 + get_level(ULMO_CALL_ULUMURI, 70, 0); +} + +bool_ *ulmo_call_of_the_ulumuri_spell() +{ +#define N_SUMMONS 2 + int x,y; + s16b m_idx, r_idx; + s16b summons[N_SUMMONS] = { + test_monster_name("Water spirit"), + test_monster_name("Water elemental") + }; + + r_idx = summons[rand_int(N_SUMMONS)]; + assert(r_idx >= 0); + + find_position(p_ptr->py, p_ptr->px, &y, &x); + + m_idx = place_monster_one(y, x, r_idx, 0, FALSE, MSTATUS_FRIEND); + if (m_idx) + { + monster_set_level(m_idx, call_of_the_ulumuri_mlev()); + return CAST; + } + + return NO_CAST; +#undef N_SUMMONS +} + +char *ulmo_call_of_the_ulumuri_info() +{ + static char buf[128]; + sprintf(buf, + "level %d", + call_of_the_ulumuri_mlev()); + return buf; +} + +static int wrath_of_ulmo_damage() +{ + return 40 + get_level_s(ULMO_WRATH, 150); +} + +static int wrath_of_ulmo_duration() +{ + return 10 + get_level_s(ULMO_WRATH, 14); +} + +bool_ *ulmo_wrath_of_ulmo_spell() +{ + int dir, type = GF_WATER; + + if (get_level_s(ULMO_WRATH, 50) >= 30) + { + type = GF_WAVE; + } + + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + fire_wall(type, + dir, + wrath_of_ulmo_damage(), + wrath_of_ulmo_duration()); + return CAST; +} + +char *ulmo_wrath_of_ulmo_info() +{ + static char buf[128]; + sprintf(buf, + "dam %d dur %d", + wrath_of_ulmo_damage(), + wrath_of_ulmo_duration()); + return buf; +} -- cgit v1.2.3 From 6bd3fd4881765ec278b9c3896cd4cff15fe33265 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 15 May 2012 06:19:37 +0200 Subject: Lua: Move "Varda" spell functions to C --- lib/mods/theme/scpt/s_varda.lua | 75 +++-------------------- src/externs.h | 14 +++++ src/spells.pkg | 14 +++++ src/spells3.c | 130 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 167 insertions(+), 66 deletions(-) diff --git a/lib/mods/theme/scpt/s_varda.lua b/lib/mods/theme/scpt/s_varda.lua index f4f46a83..e20ea5e9 100644 --- a/lib/mods/theme/scpt/s_varda.lua +++ b/lib/mods/theme/scpt/s_varda.lua @@ -14,26 +14,8 @@ VARDA_LIGHT_VALINOR = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local obvious - if get_level(VARDA_LIGHT_VALINOR, 50) >= 3 then - obvious = lite_area(10, 4) - else - lite_room(player.py, player.px) - obvious = TRUE - end - if get_level(VARDA_LIGHT_VALINOR, 50) >= 15 then - obvious = is_obvious(fire_ball(GF_LITE, 0, 10 + get_level(VARDA_LIGHT_VALINOR, 100), 5 + get_level(GLOBELIGHT, 6)), obvious) - end - return obvious - end, - ["info"] = function() - if get_level(VARDA_LIGHT_VALINOR, 50) >= 15 then - return "dam "..(10 + get_level(VARDA_LIGHT_VALINOR, 100)).." rad "..(5 + get_level(VARDA_LIGHT_VALINOR, 6)) - else - return "" - end - end, + ["spell"] = function() return varda_light_of_valinor_spell() end, + ["info"] = function() return varda_light_of_valinor_info() end, ["desc"] = { "Lights a room", "At level 3 it starts damaging monsters", @@ -52,18 +34,8 @@ VARDA_CALL_ALMAREN = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local power = 5 * player.lev - if (get_level(VARDA_CALL_ALMAREN) >= 20) then - dispel_evil(power) - else - banish_evil(power) - end - return FALSE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return varda_call_of_almaren_spell() end, + ["info"] = function() return varda_call_of_almaren_info() end, ["desc"] = { "Banishes evil beings", "At level 20 it dispels evil beings", @@ -81,22 +53,8 @@ VARDA_EVENSTAR = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - if (get_level(VARDA_EVENSTAR) >= 40) then - -- Enlightenment - wiz_lite_extra() - -- Identify - identify_pack() - -- Self knowledge - self_knowledge() - else - wiz_lite_extra() - end - return FALSE - end, - ["info"] = function() - return "" - end, + ["spell"] = function() return varda_evenstar_spell() end, + ["info"] = function() return varda_evenstar_info() end, ["desc"] = { "Maps and lights the whole level.", "At level 40 it maps and lights the whole level,", @@ -116,25 +74,10 @@ VARDA_STARKINDLER = add_spell ["piety"] = TRUE, ["stat"] = A_WIS, ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() - local power = player.lev / 5 - local ret, dir - - ret, dir = get_aim_dir() - - if ret == FALSE then return end - for i = 1, power do - fire_ball(GF_LITE, dir, 20 + get_level(VARDA_STARKINDLER, 100), 10) - end - - return FALSE - end, - ["info"] = function() - local power = player.lev / 5 - return "dam "..(20 + get_level(VARDA_STARKINDLER, 100)).." rad 10" - end, + ["spell"] = function() return varda_star_kindler_spell() end, + ["info"] = function() return varda_star_kindler_info() end, ["desc"] = { "Does multiple bursts of light damage.", "The damage increases with level.", } -} \ No newline at end of file +} diff --git a/src/externs.h b/src/externs.h index ac9bd360..b6c8ea88 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1882,6 +1882,20 @@ char *ulmo_call_of_the_ulumuri_info(); bool_ *ulmo_wrath_of_ulmo_spell(); char *ulmo_wrath_of_ulmo_info(); +extern s32b VARDA_LIGHT_VALINOR; +extern s32b VARDA_CALL_ALMAREN; +extern s32b VARDA_EVENSTAR; +extern s32b VARDA_STARKINDLER; + +bool_ *varda_light_of_valinor_spell(); +char *varda_light_of_valinor_info(); +bool_ *varda_call_of_almaren_spell(); +char *varda_call_of_almaren_info(); +bool_ *varda_evenstar_spell(); +char *varda_evenstar_info(); +bool_ *varda_star_kindler_spell(); +char *varda_star_kindler_info(); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/spells.pkg b/src/spells.pkg index 7ec49906..6f284a9d 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2886,3 +2886,17 @@ bool_ *ulmo_call_of_the_ulumuri_spell(); char *ulmo_call_of_the_ulumuri_info(); bool_ *ulmo_wrath_of_ulmo_spell(); char *ulmo_wrath_of_ulmo_info(); + +extern s32b VARDA_LIGHT_VALINOR; +extern s32b VARDA_CALL_ALMAREN; +extern s32b VARDA_EVENSTAR; +extern s32b VARDA_STARKINDLER; + +bool_ *varda_light_of_valinor_spell(); +char *varda_light_of_valinor_info(); +bool_ *varda_call_of_almaren_spell(); +char *varda_call_of_almaren_info(); +bool_ *varda_evenstar_spell(); +char *varda_evenstar_info(); +bool_ *varda_star_kindler_spell(); +char *varda_star_kindler_info(); diff --git a/src/spells3.c b/src/spells3.c index cf9632b7..119e128f 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -162,6 +162,10 @@ s32b ULMO_DRAUGHT_ULMONAN; s32b ULMO_CALL_ULUMURI; s32b ULMO_WRATH; +s32b VARDA_LIGHT_VALINOR; +s32b VARDA_CALL_ALMAREN; +s32b VARDA_EVENSTAR; +s32b VARDA_STARKINDLER; /* FIXME: Hackish workaround while we're still tied to Lua. This lets us return Lua's "nil" and a non-nil value (which is all the s_aux.lua @@ -4707,3 +4711,129 @@ char *ulmo_wrath_of_ulmo_info() wrath_of_ulmo_duration()); return buf; } + +static int light_of_valinor_damage() +{ + return 10 + get_level_s(VARDA_LIGHT_VALINOR, 100); +} + +static int light_of_valinor_radius() +{ + return 5 + get_level_s(VARDA_LIGHT_VALINOR, 6); +} + +bool_ *varda_light_of_valinor_spell() +{ + if (get_level_s(VARDA_LIGHT_VALINOR, 50) >= 3) + { + lite_area(10, 4); + } + else + { + lite_room(p_ptr->py, p_ptr->px); + } + + if (get_level_s(VARDA_LIGHT_VALINOR, 50) >= 15) + { + fire_ball(GF_LITE, + 0, + light_of_valinor_damage(), + light_of_valinor_radius()); + } + + return CAST; +} + +char *varda_light_of_valinor_info() +{ + static char buf[128]; + if (get_level_s(VARDA_LIGHT_VALINOR, 50) >= 15) + { + sprintf(buf, + "dam %d rad " FMTs32b, + light_of_valinor_damage(), + light_of_valinor_radius()); + return buf; + } + else + { + return ""; + } +} + +bool_ *varda_call_of_almaren_spell() +{ + int power = 5 * p_ptr->lev; + if (get_level_s(VARDA_CALL_ALMAREN, 50) >= 20) + { + dispel_evil(power); + } + else + { + banish_evil(power); + } + return CAST; +} + +char *varda_call_of_almaren_info() +{ + return ""; +} + +bool_ *varda_evenstar_spell() +{ + wiz_lite_extra(); + if (get_level_s(VARDA_EVENSTAR, 50) >= 40) + { + identify_pack(); + self_knowledge(NULL); + } + + return CAST; +} + +char *varda_evenstar_info() +{ + return ""; +} + +static int star_kindler_bursts() +{ + return p_ptr->lev / 5; +} + +static int star_kindler_damage() +{ + return 20 + get_level_s(VARDA_STARKINDLER, 100); +} + +bool_ *varda_star_kindler_spell() +{ + int dir, i, n = star_kindler_bursts(); + + if (!get_aim_dir(&dir)) + { + return NO_CAST; + } + + for (i = 0; i < n; i++) + { + fire_ball(GF_LITE, + dir, + star_kindler_damage(), + 10); + } + + return CAST; +} + +char *varda_star_kindler_info() +{ + static char buf[128]; + sprintf(buf, + "dam %d bursts %d rad 10", + star_kindler_damage(), + star_kindler_bursts()); + return buf; +} + -- cgit v1.2.3 From b446c8368b172aa29d312cf7eeca5e8547e73c81 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 15 May 2012 19:24:05 +0200 Subject: Lua: Move "bookable_spells" to C --- lib/mods/theme/scpt/init.lua | 3 ++ lib/mods/theme/scpt/library.lua | 24 --------- lib/scpt/init.lua | 3 ++ lib/scpt/library.lua | 22 --------- src/externs.h | 2 + src/q_library.c | 105 ++++++++++++++++++++++++++++++++-------- src/util.pkg | 5 ++ 7 files changed, 98 insertions(+), 66 deletions(-) diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index cf291ab2..2a24ecff 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -17,6 +17,9 @@ tome_dofile("mkeys.lua") -- Add the schools of magic tome_dofile("spells.lua") +-- Post-spell creation initialization +initialize_bookable_spells() + -- Add some quests tome_dofile("library.lua") diff --git a/lib/mods/theme/scpt/library.lua b/lib/mods/theme/scpt/library.lua index 51512de1..35f95094 100644 --- a/lib/mods/theme/scpt/library.lua +++ b/lib/mods/theme/scpt/library.lua @@ -5,30 +5,6 @@ library_quest = {} -- Book creation helpers -library_quest.bookable_spells = -{ - MANATHRUST, DELCURSES, - GLOBELIGHT, FIREGOLEM, FIREFLASH, FIREWALL, - GEYSER, VAPOR, ENTPOTION, - NOXIOUSCLOUD, POISONBLOOD, - STONESKIN, DIG, - RECHARGE, DISPERSEMAGIC, - BLINK, DISARM, TELEPORT, - SENSEMONSTERS, SENSEHIDDEN, REVEALWAYS, IDENTIFY, VISION, - MAGELOCK, SLOWMONSTER, ESSENCESPEED, - CHARM, CONFUSE, ARMOROFFEAR, STUN, - GROWTREE, HEALING, RECOVERY, - ERU_SEE, ERU_LISTEN, - MANWE_BLESS, MANWE_SHIELD, - YAVANNA_CHARM_ANIMAL, YAVANNA_GROW_GRASS, YAVANNA_TREE_ROOTS, - TULKAS_AIM, TULKAS_SPIN, - MELKOR_CURSE, MELKOR_CORPSE_EXPLOSION, DRAIN, - AULE_FIREBRAND, AULE_CHILD, - VARDA_LIGHT_VALINOR, VARDA_EVENSTAR, - ULMO_BELEGAER, ULMO_WRATH, - MANDOS_TEARS_LUTHIEN, MANDOS_TALE_DOOM -} - -- Print a spell (taken from s_aux) function library_quest.print_spell(color, y, spl) local x, index, sch, size, s diff --git a/lib/scpt/init.lua b/lib/scpt/init.lua index 5d8fb5e8..655c4bd7 100644 --- a/lib/scpt/init.lua +++ b/lib/scpt/init.lua @@ -17,6 +17,9 @@ tome_dofile("mkeys.lua") -- Add the schools of magic tome_dofile("spells.lua") +-- Post-spell creation initialization +initialize_bookable_spells() + -- Add some quests tome_dofile("library.lua") diff --git a/lib/scpt/library.lua b/lib/scpt/library.lua index b8a5ebed..7e25904e 100644 --- a/lib/scpt/library.lua +++ b/lib/scpt/library.lua @@ -4,28 +4,6 @@ library_quest = {} --- Book creation helpers -library_quest.bookable_spells = -{ - MANATHRUST, DELCURSES, - GLOBELIGHT, FIREGOLEM, FIREFLASH, FIREWALL, - GEYSER, VAPOR, ENTPOTION, - NOXIOUSCLOUD, POISONBLOOD, - STONESKIN, DIG, - RECHARGE, DISPERSEMAGIC, - BLINK, DISARM, TELEPORT, - SENSEMONSTERS, SENSEHIDDEN, REVEALWAYS, IDENTIFY, VISION, - MAGELOCK, SLOWMONSTER, ESSENCESPEED, - CHARM, CONFUSE, ARMOROFFEAR, STUN, - GROWTREE, HEALING, RECOVERY, - ERU_SEE, ERU_LISTEN, - MANWE_BLESS, MANWE_SHIELD, - YAVANNA_CHARM_ANIMAL, YAVANNA_GROW_GRASS, YAVANNA_TREE_ROOTS, - TULKAS_AIM, TULKAS_SPIN, - MELKOR_CURSE, MELKOR_CORPSE_EXPLOSION, - DRAIN -} - -- Print a spell (taken from s_aux) function library_quest.print_spell(color, y, spl) local x, index, sch, size, s diff --git a/src/externs.h b/src/externs.h index b6c8ea88..f19e2db8 100644 --- a/src/externs.h +++ b/src/externs.h @@ -612,6 +612,8 @@ extern hook_return process_hooks_return[20]; extern bool_ process_hooks_ret(int h_idx, char *ret, char *fmt, ...); extern bool_ process_hooks(int h_idx, char *fmt, ...); +extern void initialize_bookable_spells(); + /* help.c */ extern void ingame_help(bool_ enable); diff --git a/src/q_library.c b/src/q_library.c index d19b15d8..7ccbd9cf 100644 --- a/src/q_library.c +++ b/src/q_library.c @@ -10,6 +10,78 @@ #define MONSTER_IRON_GOLEM 367 #define MONSTER_MITHRIL_GOLEM 464 +#define MAX_BOOKABLE_SPELLS 128 + +static s16b bookable_spells[MAX_BOOKABLE_SPELLS]; +static s16b bookable_spells_size = 0; + +static void push_spell(s16b spell_idx) +{ + assert(bookable_spells_size < MAX_BOOKABLE_SPELLS); + bookable_spells[bookable_spells_size++] = spell_idx; +} + +void initialize_bookable_spells() +{ + push_spell(MANATHRUST); + push_spell(DELCURSES); + push_spell(GLOBELIGHT); + push_spell(FIREGOLEM); + push_spell(FIREFLASH); + push_spell(FIREWALL); + push_spell(GEYSER); + push_spell(VAPOR); + push_spell(ENTPOTION); + push_spell(NOXIOUSCLOUD); + push_spell(POISONBLOOD); + push_spell(STONESKIN); + push_spell(DIG); + push_spell(RECHARGE); + push_spell(DISPERSEMAGIC); + push_spell(BLINK); + push_spell(DISARM); + push_spell(TELEPORT); + push_spell(SENSEMONSTERS); + push_spell(SENSEHIDDEN); + push_spell(REVEALWAYS); + push_spell(IDENTIFY); + push_spell(VISION); + push_spell(MAGELOCK); + push_spell(SLOWMONSTER); + push_spell(ESSENCESPEED); + push_spell(CHARM); + push_spell(CONFUSE); + push_spell(ARMOROFFEAR); + push_spell(STUN); + push_spell(GROWTREE); + push_spell(HEALING); + push_spell(RECOVERY); + push_spell(ERU_SEE); + push_spell(ERU_LISTEN); + push_spell(MANWE_BLESS); + push_spell(MANWE_SHIELD); + push_spell(YAVANNA_CHARM_ANIMAL); + push_spell(YAVANNA_GROW_GRASS); + push_spell(YAVANNA_TREE_ROOTS); + push_spell(TULKAS_AIM); + push_spell(TULKAS_SPIN); + push_spell(MELKOR_CURSE); + push_spell(MELKOR_CORPSE_EXPLOSION); + push_spell(DRAIN); + + if (game_module_idx == MODULE_THEME) + { + push_spell(AULE_FIREBRAND); + push_spell(AULE_CHILD); + push_spell(VARDA_LIGHT_VALINOR); + push_spell(VARDA_EVENSTAR); + push_spell(ULMO_BELEGAER); + push_spell(ULMO_WRATH); + push_spell(MANDOS_TEARS_LUTHIEN); + push_spell(MANDOS_TALE_DOOM); + } +} + static s16b library_quest_place_random(int minY, int minX, int maxY, int maxX, int r_idx) { int y = randint(maxY - minY + 1) + minY; @@ -64,14 +136,6 @@ static bool_ library_quest_book_contains_spell(int spell) return FALSE; } -static int library_quest_bookable_spells_at(int i) { - return exec_lua(format("return library_quest.bookable_spells[%d]", i + 1)); -} - -static int library_quest_getn_bookable_spells() { - return exec_lua("return getn(library_quest.bookable_spells)"); -} - static int library_quest_print_spell(int color, int row, int spell) { return exec_lua(format("library_quest.print_spell(%d,%d,%d)", color, row, spell)); } @@ -117,7 +181,7 @@ static void library_quest_print_spells(int first, int current) { int width, height; int slots, row; - int nspells, index; + int index; Term_clear(); Term_get_size(&width, &height); @@ -137,9 +201,8 @@ static void library_quest_print_spells(int first, int current) row = 3; - nspells = library_quest_getn_bookable_spells(); - for (index = 0; index < nspells; index++) { - int spell = library_quest_bookable_spells_at(index); + for (index = 0; index < bookable_spells_size; index++) { + int spell = bookable_spells[index]; if (index >= first) { int color; if (index == current) { @@ -183,7 +246,7 @@ static void library_quest_fill_book() while (done == FALSE) { char ch; - int dir, total; + int dir, spell_idx; library_quest_print_spells(first, current); @@ -191,6 +254,8 @@ static void library_quest_fill_book() ch = inkey(); dir = get_keymap_dir(ch); + spell_idx = bookable_spells[current]; + if (ch == ESCAPE) { if (library_quest_book_slots_left() == 0) { flush(); @@ -205,23 +270,23 @@ static void library_quest_fill_book() } else if (ch == 'p') { current = current - height; } else if (ch == 'I') { - library_quest_print_spell_desc(library_quest_bookable_spells_at(current), 0); + library_quest_print_spell_desc(spell_idx, 0); inkey(); } else if (dir == 2) { current = current + 1; } else if (dir == 8) { current = current - 1; } else if (dir == 6) { - if (library_quest_book_contains_spell(library_quest_bookable_spells_at(current)) == FALSE) { - library_quest_add_spell(library_quest_bookable_spells_at(current)); + if (library_quest_book_contains_spell(spell_idx) == FALSE) + { + library_quest_add_spell(spell_idx); } } else if (dir == 4) { - library_quest_remove_spell(library_quest_bookable_spells_at(current)); + library_quest_remove_spell(spell_idx); } - total = library_quest_getn_bookable_spells(); - if (current >= total) { - current = total - 1; + if (current >= bookable_spells_size) { + current = bookable_spells_size - 1; } else if (current < 0) { current = 0; } diff --git a/src/util.pkg b/src/util.pkg index 2ec70acf..a32ef927 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -2375,3 +2375,8 @@ extern s16b resolve_mimic_name(cptr name); * Timers */ void timer_aggravate_evil_enable(); + +/** + * Initialize bookable spells. + */ +void initialize_bookable_spells(); -- cgit v1.2.3 From 7c95b69311bcbadb84fba499584fe721612ca144 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 15 May 2012 21:29:50 +0200 Subject: Lua: Move 'print_spell_desc' and 'spell_x' to C --- lib/core/s_aux.lua | 50 ++-------------------------------- lib/mods/theme/core/s_aux.lua | 50 ++-------------------------------- src/CMakeLists.txt | 2 +- src/cmd5.c | 20 +++++++++++--- src/externs.h | 3 +++ src/lua_bind.c | 4 ++- src/q_library.c | 6 +---- src/spells4.c | 62 +++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 91 insertions(+), 106 deletions(-) create mode 100644 src/spells4.c diff --git a/lib/core/s_aux.lua b/lib/core/s_aux.lua index 97643626..6cdcbd82 100644 --- a/lib/core/s_aux.lua +++ b/lib/core/s_aux.lua @@ -300,42 +300,12 @@ function print_book(book, spl, obj) return y end --- Output the describtion when it is used as a spell -function print_spell_desc(s, y) - local index, desc, x - - x = 0 - - if type(__spell_desc[s]) == "string" then c_prt(TERM_L_BLUE, __spell_desc[s], y, x) - else - for index, desc in __spell_desc[s] do - c_prt(TERM_L_BLUE, desc, y, x) - y = y + 1 - end - end - if check_affect(s, "piety", FALSE) then - c_prt(TERM_L_WHITE, "It uses piety to cast.", y, x) - y = y + 1 - end - if not check_affect(s, "blind") then - c_prt(TERM_ORANGE, "It is castable even while blinded.", y, x) - y = y + 1 - end - if not check_affect(s, "confusion") then - c_prt(TERM_ORANGE, "It is castable even while confused.", y, x) - y = y + 1 - end -end - -- Output the desc when sued as a device function print_device_desc(s) local index, desc - if type(__spell_desc[s]) == "string" then text_out(__spell_desc[s]) - else - for index, desc in __spell_desc[s] do - text_out("\n" .. desc) - end + for index, desc in __spell_desc[s] do + text_out("\n" .. desc) end end @@ -356,22 +326,6 @@ function book_spells_num(book) return size end -function spell_x(book, spl, s) - if book == 255 then - return spl - else - local i, x, val - - i, val = next(school_book[book], nil) - x = 0 - while x < s do - i, val = next(school_book[book], i) - x = x + 1 - end - return val - end -end - function spell_in_book(book, spell) local i, s diff --git a/lib/mods/theme/core/s_aux.lua b/lib/mods/theme/core/s_aux.lua index 97643626..6cdcbd82 100644 --- a/lib/mods/theme/core/s_aux.lua +++ b/lib/mods/theme/core/s_aux.lua @@ -300,42 +300,12 @@ function print_book(book, spl, obj) return y end --- Output the describtion when it is used as a spell -function print_spell_desc(s, y) - local index, desc, x - - x = 0 - - if type(__spell_desc[s]) == "string" then c_prt(TERM_L_BLUE, __spell_desc[s], y, x) - else - for index, desc in __spell_desc[s] do - c_prt(TERM_L_BLUE, desc, y, x) - y = y + 1 - end - end - if check_affect(s, "piety", FALSE) then - c_prt(TERM_L_WHITE, "It uses piety to cast.", y, x) - y = y + 1 - end - if not check_affect(s, "blind") then - c_prt(TERM_ORANGE, "It is castable even while blinded.", y, x) - y = y + 1 - end - if not check_affect(s, "confusion") then - c_prt(TERM_ORANGE, "It is castable even while confused.", y, x) - y = y + 1 - end -end - -- Output the desc when sued as a device function print_device_desc(s) local index, desc - if type(__spell_desc[s]) == "string" then text_out(__spell_desc[s]) - else - for index, desc in __spell_desc[s] do - text_out("\n" .. desc) - end + for index, desc in __spell_desc[s] do + text_out("\n" .. desc) end end @@ -356,22 +326,6 @@ function book_spells_num(book) return size end -function spell_x(book, spl, s) - if book == 255 then - return spl - else - local i, x, val - - i, val = next(school_book[book], nil) - x = 0 - while x < s do - i, val = next(school_book[book], i) - x = x + 1 - end - return val - end -end - function spell_in_book(book, spell) local i, s diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 18975f17..b286a477 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,7 +10,7 @@ SET(SRCS object1.c object2.c randart.c squeltch.c traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c - spells1.c spells2.c spells3.c corrupt.c mimic.c + spells1.c spells2.c spells3.c spells4.c corrupt.c mimic.c status.c files.c notes.c loadsave.c cmd1.c cmd2.c cmd3.c cmd4.c cmd5.c cmd6.c cmd7.c help.c diff --git a/src/cmd5.c b/src/cmd5.c index 57746ca0..df429a8a 100644 --- a/src/cmd5.c +++ b/src/cmd5.c @@ -17,6 +17,20 @@ extern lua_State *L; +static int spell_x(int sval, int pval, int i) +{ + if (sval == 255) + { + return pval; + } + else + { + char buf[128]; + sprintf(buf, "school_book[%d][%d]", sval, i+1); + return get_lua_int(buf); + } +} + /* Maximum number of tries for teleporting */ #define MAX_TRIES 300 @@ -2327,14 +2341,14 @@ s32b get_school_spell(cptr do_what, cptr check_fct, s16b force_book) /* Display a list of spells */ call_lua("print_book", "(d,d,O)", "d", sval, pval, o_ptr, &where); - exec_lua(format("print_spell_desc(spell_x(%d, %d, %d), %d)", sval, pval, i, where)); + print_spell_desc(spell_x(sval, pval, i), where); } else { s32b ok; /* Save the spell index */ - spell = exec_lua(format("return spell_x(%d, %d, %d)", sval, pval, i)); + spell = spell_x(sval, pval, i); /* Do we need to do some pre test */ call_lua(check_fct, "(d,O)", "d", spell, o_ptr, &ok); @@ -2479,7 +2493,7 @@ void browse_school_spell(int book, int pval, object_type *o_ptr) /* Display a list of spells */ call_lua("print_book", "(d,d,O)", "d", book, pval, o_ptr, &where); - exec_lua(format("print_spell_desc(spell_x(%d, %d, %d), %d)", book, pval, i, where)); + print_spell_desc(spell_x(book, pval, i), where); } diff --git a/src/externs.h b/src/externs.h index f19e2db8..0b7b2575 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1898,6 +1898,9 @@ char *varda_evenstar_info(); bool_ *varda_star_kindler_spell(); char *varda_star_kindler_info(); +/* spells4.c */ +void print_spell_desc(int s, int y); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/lua_bind.c b/src/lua_bind.c index 67073061..409e005d 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -539,7 +539,9 @@ void lua_display_list(int y, int x, int h, int w, cptr title, list_type* list, i int get_lua_int(cptr name) { - return exec_lua(format("return %s", name)); + char buf[128]; + sprintf(buf, "return %s", name); + return exec_lua(buf); } void increase_mana(int delta) diff --git a/src/q_library.c b/src/q_library.c index 7ccbd9cf..0c4ad5e3 100644 --- a/src/q_library.c +++ b/src/q_library.c @@ -140,10 +140,6 @@ static int library_quest_print_spell(int color, int row, int spell) { return exec_lua(format("library_quest.print_spell(%d,%d,%d)", color, row, spell)); } -static int library_quest_print_spell_desc(int s, int y) { - return exec_lua(format("print_spell_desc(%d, %d)", s, y)); -} - static void quest_library_finalize_book() { int i = 0; @@ -270,7 +266,7 @@ static void library_quest_fill_book() } else if (ch == 'p') { current = current - height; } else if (ch == 'I') { - library_quest_print_spell_desc(spell_idx, 0); + print_spell_desc(spell_idx, 0); inkey(); } else if (dir == 2) { current = current + 1; diff --git a/src/spells4.c b/src/spells4.c new file mode 100644 index 00000000..7f59d186 --- /dev/null +++ b/src/spells4.c @@ -0,0 +1,62 @@ +#include "angband.h" + +#include + +static bool_ uses_piety_to_cast(int s) +{ + char buf[128]; + sprintf(buf, "return check_affect(%d, \"piety\", FALSE)", s); + return exec_lua(buf); +} + +static bool_ castable_while_blind(int s) +{ + char buf[128]; + sprintf(buf, "return not check_affect(%d, \"blind\")", s); + return exec_lua(buf); +} + +static bool_ castable_while_confused(int s) +{ + char buf[128]; + sprintf(buf, "return not check_affect(%d, \"confusion\")", s); + return exec_lua(buf); +} + +/* Output the describtion when it is used as a spell */ +void print_spell_desc(int s, int y) +{ + int i; + + for (i=0; ; i++) + { + char buf[128]; + cptr desc = NULL; + + sprintf(buf, "return __spell_desc[%d][%d]", s, i+1); + desc = string_exec_lua(buf); + if (!desc) + { + break; + } + + c_prt(TERM_L_BLUE, desc, y, 0); + y++; + } + + if (uses_piety_to_cast(s)) + { + c_prt(TERM_L_WHITE, "It uses piety to cast.", y, 0); + y++; + } + if (castable_while_blind(s)) + { + c_prt(TERM_ORANGE, "It is castable even while blinded.", y, 0); + y++; + } + if (castable_while_confused(s)) + { + c_prt(TERM_ORANGE, "It is castable even while confused.", y, 0); + y++; + } +} -- cgit v1.2.3 From 0582181c200ef17189b6e1c3161f50860b8b1fab Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 18 May 2012 11:46:48 +0200 Subject: Corruptions: Fix off-by-one in transcription of Lua code --- src/corrupt.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/corrupt.c b/src/corrupt.c index 9c707a67..a4c579d4 100644 --- a/src/corrupt.c +++ b/src/corrupt.c @@ -40,12 +40,12 @@ static void player_gain_vampire_strength() rmp_ptr->r_mhp = rmp_ptr->r_mhp + 1; rmp_ptr->r_exp = rmp_ptr->r_exp + 100; - rmp_ptr->r_adj[A_STR + 1] = rmp_ptr->r_adj[A_STR + 1] + 3; - rmp_ptr->r_adj[A_INT + 1] = rmp_ptr->r_adj[A_INT + 1] + 2; - rmp_ptr->r_adj[A_WIS + 1] = rmp_ptr->r_adj[A_WIS + 1] - 3; - rmp_ptr->r_adj[A_DEX + 1] = rmp_ptr->r_adj[A_DEX + 1] - 2; - rmp_ptr->r_adj[A_CON + 1] = rmp_ptr->r_adj[A_CON + 1] + 1; - rmp_ptr->r_adj[A_CHR + 1] = rmp_ptr->r_adj[A_CHR + 1] - 4; + rmp_ptr->r_adj[A_STR] = rmp_ptr->r_adj[A_STR] + 3; + rmp_ptr->r_adj[A_INT] = rmp_ptr->r_adj[A_INT] + 2; + rmp_ptr->r_adj[A_WIS] = rmp_ptr->r_adj[A_WIS] - 3; + rmp_ptr->r_adj[A_DEX] = rmp_ptr->r_adj[A_DEX] - 2; + rmp_ptr->r_adj[A_CON] = rmp_ptr->r_adj[A_CON] + 1; + rmp_ptr->r_adj[A_CHR] = rmp_ptr->r_adj[A_CHR] - 4; /* be reborn! */ do_rebirth(); -- cgit v1.2.3 From ccb4ffd3033ac953c064b590709e0a88ff659003 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 17 May 2012 08:16:07 +0200 Subject: Lua: Rework get_level_school() callout --- src/externs.h | 1 + src/lua_bind.c | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/externs.h b/src/externs.h index 0b7b2575..564c0b2b 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2307,6 +2307,7 @@ extern s32b get_level_device(s32b s, s32b max, s32b min); extern int get_mana(s32b s); extern s32b spell_chance(s32b s); extern s32b get_level(s32b s, s32b max, s32b min); +extern void get_level_school(s32b s, s32b max, s32b min, s32b *level, bool_ *na); extern s32b lua_spell_chance(s32b chance, int level, int skill_level, int mana, int cur_mana, int stat); extern s32b lua_spell_device_chance(s32b chance, int level, int base_level); diff --git a/src/lua_bind.c b/src/lua_bind.c index 409e005d..a019004b 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -271,13 +271,27 @@ s32b spell_chance(s32b s) } } +void get_level_school(s32b s, s32b max, s32b min, s32b *level, bool_ *na) +{ + if (level != NULL) + { + *level = exec_lua(format("local lvl, na = get_level_school(%d, %d, %d); return lvl", s, max, min)); + } + + if (na != NULL) + { + *na = exec_lua(format("local lvl, na = get_level_school(%d, %d, %d); return (na == \"n/a\")", s, max, min)); + } +} + s32b get_level(s32b s, s32b max, s32b min) { /** Ahah shall we use Magic device instead ? */ if (get_level_use_stick > -1) { return get_level_device(s, max, min); } else { - int level = exec_lua(format("local lvl, na = get_level_school(%d, %d, %d); return lvl", s, max, min)); + s32b level; + get_level_school(s, max, min, &level, NULL); return level; } } -- cgit v1.2.3 From 159e8b3ec190d6a99c3d42e78dc2c55bdd0f6f41 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 17 May 2012 08:40:49 +0200 Subject: Lua: Separate get_spell_info() function --- src/externs.h | 2 ++ src/lua_bind.c | 5 ++++- src/object1.c | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/externs.h b/src/externs.h index 564c0b2b..386bd63c 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2341,6 +2341,8 @@ extern timer_type *TIMER_AGGRAVATE_EVIL; void timer_aggravate_evil_enable(); void timer_aggravate_evil_callback(); +cptr get_spell_info(s32b s); + /* skills.c */ extern void dump_skills(FILE *fff); extern s16b find_skill(cptr name); diff --git a/src/lua_bind.c b/src/lua_bind.c index a019004b..11f47bca 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -577,4 +577,7 @@ void timer_aggravate_evil_callback() dispel_evil(0); } - +cptr get_spell_info(s32b s) +{ + return string_exec_lua(format("return __spell_info[" FMTs32b "]()", s)); +} diff --git a/src/object1.c b/src/object1.c index b834eb91..3b418651 100644 --- a/src/object1.c +++ b/src/object1.c @@ -2847,7 +2847,7 @@ void describe_device(object_type *o_ptr) text_out_c(TERM_GREEN, string_exec_lua(format("return tostring(spell_chance(%d))", o_ptr->pval2))); text_out("\nSpell info: "); - text_out_c(TERM_YELLOW, string_exec_lua(format("return __spell_info[%d]()", o_ptr->pval2))); + text_out_c(TERM_YELLOW, get_spell_info(o_ptr->pval2)); /* Leave device mode */ unset_stick_mode(); -- cgit v1.2.3 From 1310925badf99e0832608f8844e04fa6c70017dc Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 17 May 2012 10:46:33 +0200 Subject: Lua: get_power() is no longer static --- src/externs.h | 1 + src/lua_bind.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/externs.h b/src/externs.h index 386bd63c..fbb3a9c1 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2305,6 +2305,7 @@ extern school_type *grab_school_type(s16b num); extern s32b lua_get_level(s32b s, s32b lvl, s32b max, s32b min, s32b bonus); extern s32b get_level_device(s32b s, s32b max, s32b min); extern int get_mana(s32b s); +extern int get_power(s32b s); extern s32b spell_chance(s32b s); extern s32b get_level(s32b s, s32b max, s32b min); extern void get_level_school(s32b s, s32b max, s32b min, s32b *level, bool_ *na); diff --git a/src/lua_bind.c b/src/lua_bind.c index 11f47bca..469dfddb 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -249,7 +249,7 @@ int get_mana(s32b s) { return exec_lua(format("return get_mana(%d)", s)); } -static int get_power(s32b s) { +int get_power(s32b s) { return exec_lua(format("return get_power(%d)", s)); } -- cgit v1.2.3 From bfd584db255cd99a7b094a1c06bc9bad9ec6f418 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 17 May 2012 10:08:01 +0200 Subject: Lua: Add get_lua_list_size() --- src/externs.h | 1 + src/lua_bind.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/src/externs.h b/src/externs.h index fbb3a9c1..798ab111 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2295,6 +2295,7 @@ extern bool_ lua_summon_monster(int y, int x, int lev, bool_ ffriend, char *fct) extern s16b add_new_gods(char *name); extern int get_lua_int(cptr name); +extern int get_lua_list_size(cptr list_name); extern bool_ get_com_lua(cptr promtp, int *com); diff --git a/src/lua_bind.c b/src/lua_bind.c index 469dfddb..e7870189 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -558,6 +558,13 @@ int get_lua_int(cptr name) return exec_lua(buf); } +int get_lua_list_size(cptr list_var) +{ + char buf[128]; + sprintf(buf, "return getn(%s)", list_var); + return exec_lua(buf); +} + void increase_mana(int delta) { char buf[256]; -- cgit v1.2.3 From 4dd2ffb52df44aa78719a49492db9e79b6b01215 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 18 May 2012 09:43:29 +0200 Subject: Import SGLIB 1.0.3 header --- src/include/sglib.h | 1952 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1952 insertions(+) create mode 100644 src/include/sglib.h diff --git a/src/include/sglib.h b/src/include/sglib.h new file mode 100644 index 00000000..1a4780fa --- /dev/null +++ b/src/include/sglib.h @@ -0,0 +1,1952 @@ +/* + + This is SGLIB version 1.0.3 + + (C) by Marian Vittek, Bratislava, http://www.xref-tech.com/sglib, 2003-5 + + License Conditions: You can use a verbatim copy (including this + copyright notice) of sglib freely in any project, commercial or not. + You can also use derivative forms freely under terms of Open Source + Software license or under terms of GNU Public License. If you need + to use a derivative form in a commercial project, or you need sglib + under any other license conditions, contact the author. + + + +*/ + + +#ifndef _SGLIB__h_ +#define _SGLIB__h_ + +/* the assert is used exclusively to write unexpected error messages */ +#include + + +/* ---------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------------- */ +/* - LEVEL - 0 INTERFACE - */ +/* ---------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------------- */ + + +/* ---------------------------------------------------------------------------- */ +/* ------------------------------ STATIC ARRAYS ------------------------------- */ +/* ---------------------------------------------------------------------------- */ + +/* + + Basic algorithms for sorting arrays. Multiple depending arrays can + be rearranged using user defined 'elem_exchangers' + +*/ + +/* HEAP - SORT (level 0) */ + +#define SGLIB_ARRAY_SINGLE_HEAP_SORT(type, a, max, comparator) {\ + SGLIB_ARRAY_HEAP_SORT(type, a, max, comparator, SGLIB_ARRAY_ELEMENTS_EXCHANGER);\ +} + +#define SGLIB_ARRAY_HEAP_SORT(type, a, max, comparator, elem_exchanger) {\ + int _k_;\ + for(_k_=(max)/2; _k_>=0; _k_--) {\ + SGLIB___ARRAY_HEAP_DOWN(type, a, _k_, max, comparator, elem_exchanger);\ + }\ + for(_k_=(max)-1; _k_>=0; _k_--) {\ + elem_exchanger(type, a, 0, _k_);\ + SGLIB___ARRAY_HEAP_DOWN(type, a, 0, _k_, comparator, elem_exchanger);\ + }\ +} + +#define SGLIB___ARRAY_HEAP_DOWN(type, a, ind, max, comparator, elem_exchanger) {\ + type _t_;\ + int _m_, _l_, _r_, _i_;\ + _i_ = (ind);\ + _m_ = _i_;\ + do {\ + _i_ = _m_; \ + _l_ = 2*_i_+1;\ + _r_ = _l_+1;\ + if (_l_ < (max)){\ + if (comparator(((a)[_m_]), ((a)[_l_])) < 0) _m_ = _l_;\ + if (_r_ < (max)) {\ + if (comparator(((a)[_m_]), ((a)[_r_])) < 0) _m_ = _r_;\ + }\ + }\ + if (_m_ != _i_) {\ + elem_exchanger(type, a, _i_, _m_);\ + }\ + } while (_m_ != _i_);\ +} + + +/* QUICK - SORT (level 0) */ + +#define SGLIB_ARRAY_SINGLE_QUICK_SORT(type, a, max, comparator) {\ + SGLIB_ARRAY_QUICK_SORT(type, a, max, comparator, SGLIB_ARRAY_ELEMENTS_EXCHANGER);\ +} + +#define SGLIB_ARRAY_QUICK_SORT(type, a, max, comparator, elem_exchanger) {\ + int _i_, _j_, _p_, _stacki_, _start_, _end_;\ + /* can sort up to 2^64 elements */\ + int _startStack_[64]; \ + int _endStack_[64];\ + type _tmp_;\ + _startStack_[0] = 0;\ + _endStack_[0] = (max);\ + _stacki_ = 1;\ + while (_stacki_ > 0) {\ + _stacki_ --;\ + _start_ = _startStack_[_stacki_];\ + _end_ = _endStack_[_stacki_];\ + while (_end_ - _start_ > 2) {\ + _p_ = _start_;\ + _i_ = _start_ + 1;\ + _j_ = _end_ - 1;\ + while (_i_<_j_) {\ + for(; _i_<=_j_ && comparator(((a)[_i_]),((a)[_p_]))<=0; _i_++) ;\ + if (_i_ > _j_) {\ + /* all remaining elements lesseq than pivot */\ + elem_exchanger(type, a, _j_, _p_);\ + _i_ = _j_;\ + } else {\ + for(; _i_<=_j_ && comparator(((a)[_j_]),((a)[_p_]))>=0; _j_--) ;\ + if (_i_ > _j_) {\ + /* all remaining elements greater than pivot */\ + elem_exchanger(type, a, _j_, _p_);\ + _i_ = _j_;\ + } else if (_i_ < _j_) {\ + elem_exchanger(type, a, _i_, _j_);\ + if (_i_+2 < _j_) {_i_++; _j_--;}\ + else if (_i_+1 < _j_) _i_++;\ + }\ + }\ + }\ + /* O.K. i==j and pivot is on a[i] == a[j] */\ + /* handle recursive calls without recursion */\ + if (_i_-_start_ > 1 && _end_-_j_ > 1) {\ + /* two recursive calls, use array-stack */\ + if (_i_-_start_ < _end_-_j_-1) {\ + _startStack_[_stacki_] = _j_+1;\ + _endStack_[_stacki_] = _end_;\ + _stacki_ ++;\ + _end_ = _i_;\ + } else {\ + _startStack_[_stacki_] = _start_;\ + _endStack_[_stacki_] = _i_;\ + _stacki_ ++;\ + _start_ = _j_+1;\ + }\ + } else {\ + if (_i_-_start_ > 1) {\ + _end_ = _i_;\ + } else {\ + _start_ = _j_+1;\ + }\ + }\ + }\ + if (_end_ - _start_ == 2) {\ + if (comparator(((a)[_start_]),((a)[_end_-1])) > 0) {\ + elem_exchanger(type, a, _start_, _end_-1);\ + }\ + }\ + }\ +} + +/* BINARY SEARCH (level 0) */ + +#define SGLIB_ARRAY_BINARY_SEARCH(type, a, start_index, end_index, key, comparator, found, result_index) {\ + int _kk_, _cc_, _ii_, _jj_, _ff_;\ + _ii_ = (start_index); \ + _jj_ = (end_index);\ + _ff_ = 0;\ + while (_ii_ <= _jj_ && _ff_==0) {\ + _kk_ = (_jj_+_ii_)/2;\ + _cc_ = comparator(((a)[_kk_]), (key));\ + if (_cc_ == 0) {\ + (result_index) = _kk_; \ + _ff_ = 1;\ + } else if (_cc_ < 0) {\ + _ii_ = _kk_+1;\ + } else {\ + _jj_ = _kk_-1;\ + }\ + }\ + if (_ff_ == 0) {\ + /* not found, but set its resulting place in the array */\ + (result_index) = _jj_+1;\ + }\ + (found) = _ff_;\ +} + +/* -------------------------------- queue (in an array) ------------------ */ +/* queue is a quadruple (a,i,j,dim) such that: */ +/* a is the array storing values */ +/* i is the index of the first used element in the array */ +/* j is the index of the first free element in the array */ +/* dim is the size of the array a */ +/* !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! */ + +#define SGLIB_QUEUE_INIT(type, a, i, j) { i = j = 0; } +#define SGLIB_QUEUE_IS_EMPTY(type, a, i, j) ((i)==(j)) +#define SGLIB_QUEUE_IS_FULL(type, a, i, j, dim) ((i)==((j)+1)%(dim)) +#define SGLIB_QUEUE_FIRST_ELEMENT(type, a, i, j) (a[i]) +#define SGLIB_QUEUE_ADD_NEXT(type, a, i, j, dim) {\ + if (SGLIB_QUEUE_IS_FULL(type, a, i, j, dim)) assert(0 && "the queue is full");\ + (j) = ((j)+1) % (dim);\ +} +#define SGLIB_QUEUE_ADD(type, a, elem, i, j, dim) {\ + a[j] = (elem);\ + SGLIB_QUEUE_ADD_NEXT(type, a, i, j, dim);\ +} +#define SGLIB_QUEUE_DELETE_FIRST(type, a, i, j, dim) {\ + if (SGLIB_QUEUE_IS_EMPTY(type, a, i, j)) assert(0 && "the queue is empty");\ + (i) = ((i)+1) % (dim);\ +} +#define SGLIB_QUEUE_DELETE(type, a, i, j, dim) {\ + SGLIB_QUEUE_DELETE_FIRST(type, a, i, j, dim);\ +} + +/* ----------------- priority queue (heap) (in an array) -------------------- */ +/* heap is a triple (a,i,dim) such that: */ +/* a is the array storing values */ +/* i is the index of the first free element in the array */ +/* dim is the size of the array a */ +/* !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! */ + +#define SGLIB_HEAP_INIT(type, a, i) { i = 0; } +#define SGLIB_HEAP_IS_EMPTY(type, a, i) ((i)==0) +#define SGLIB_HEAP_IS_FULL(type, a, i, dim) ((i)==(dim)) +#define SGLIB_HEAP_FIRST_ELEMENT(type, a, i) (a[0]) +#define SGLIB_HEAP_ADD_NEXT(type, a, i, dim, comparator, elem_exchanger) {\ + int _i_;\ + if (SGLIB_HEAP_IS_FULL(type, a, i, dim)) assert(0 && "the heap is full");\ + _i_ = (i)++;\ + while (_i_ > 0 && comparator(a[_i_/2], a[_i_]) < 0) {\ + elem_exchanger(type, a, (_i_/2), _i_);\ + _i_ = _i_/2;\ + }\ +} +#define SGLIB_HEAP_ADD(type, a, elem, i, dim, comparator) {\ + if (SGLIB_HEAP_IS_FULL(type, a, i, dim)) assert(0 && "the heap is full");\ + a[i] = (elem);\ + SGLIB_HEAP_ADD_NEXT(type, a, i, dim, comparator, SGLIB_ARRAY_ELEMENTS_EXCHANGER);\ +} +#define SGLIB_HEAP_DELETE_FIRST(type, a, i, dim, comparator, elem_exchanger) {\ + if (SGLIB_HEAP_IS_EMPTY(type, a, i)) assert(0 && "the heap is empty");\ + (i)--;\ + a[0] = a[i];\ + SGLIB___ARRAY_HEAP_DOWN(type, a, 0, i, comparator, elem_exchanger);\ +} +#define SGLIB_HEAP_DELETE(type, a, i, dim, comparator) {\ + SGLIB_HEAP_DELETE_FIRST(type, a, i, dim, comparator, SGLIB_ARRAY_ELEMENTS_EXCHANGER);\ +} + + +/* ----------------- hashed table of pointers (in an array) -------------------- */ + +/* + + This hashed table is storing pointers to objects (not containers). + In this table there is a one-to-one mapping between 'objects' stored + in the table and indexes where they are placed. Each index is + pointing to exactly one 'object' and each 'object' stored in the + table occurs on exactly one index. Once an object is stored in the + table, it can be represented via its index. + + In case of collision while adding an object the index shifted + by SGLIB_HASH_TAB_SHIFT_CONSTANT (constant can be redefined) + + You can NOT delete an element from such hash table. The only + justification (I can see) for this data structure is an exchange + file format, having an index table at the beginning and then + refering objects via indexes. + + !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! + +*/ + +#define SGLIB_HASH_TAB_INIT(type, table, dim) {\ + int _i_;\ + for(_i_ = 0; _i_ < (dim); _i_++) (table)[_i_] = NULL;\ +} + +#define SGLIB_HASH_TAB_ADD_IF_NOT_MEMBER(type, table, dim, elem, hash_function, comparator, member){\ + unsigned _pos_;\ + type *_elem_;\ + SGLIB_HASH_TAB_FIND_MEMBER(type, table, dim, elem, _pos_, _elem_);\ + (member) = (table)[_pos_];\ + if (_elem_ == NULL) {\ + if ((table)[_pos_] != NULL) assert(0 && "the hash table is full");\ + (table)[_pos_] = (elem);\ + }\ +} + +#define SGLIB_HASH_TAB_FIND_MEMBER(type, table, dim, elem, hash_function, comparator, resultIndex, resultMember) {\ + unsigned _i_;\ + int _count_;\ + type *_e_;\ + _count = 0;\ + _i_ = hash_function(elem);\ + _i_ %= (dim);\ + while ((_e_=(table)[_i_])!=NULL && comparator(_e_, (elem))!=0 && _count_<(dim)) {\ + _count_ ++;\ + _i_ = (_i_ + SGLIB_HASH_TAB_SHIFT_CONSTANT) % (dim);\ + }\ + (resultIndex) = _i_;\ + if (_count_ < (dim)) (resultMember) = _e_;\ + else (resultMember) = NULL;\ +} + +#define SGLIB_HASH_TAB_IS_MEMBER(type, table, dim, elem, hash_function, resultIndex) {\ + unsigned _i_;\ + int _c_;\ + type *_e_;\ + _count = 0;\ + _i_ = hash_function(elem);\ + _i_ %= (dim);\ + while ((_e_=(table)[_i_])!=NULL && _e_!=(elem) && _c_<(dim)) {\ + _c_ ++;\ + _i_ = (_i_ + SGLIB_HASH_TAB_SHIFT_CONSTANT) % (dim);\ + }\ + if (_e_==(elem)) (resultIndex) = _i_;\ + else (resultIndex) = -1;\ +} + +#define SGLIB_HASH_TAB_MAP_ON_ELEMENTS(type, table, dim, iteratedIndex, iteratedVariable, command) {\ + unsigned iteratedIndex;\ + type *iteratedVariable;\ + for(iteratedIndex=0; iteratedIndex < (dim); iteratedIndex++) {\ + iteratedVariable = (table)[iteratedIndex];\ + if (iteratedVariable != NULL) {command;}\ + }\ +} + + +/* ---------------------------------------------------------------------------- */ +/* ------------------------- DYNAMIC DATA STRUCTURES -------------------------- */ +/* ---------------------------------------------------------------------------- */ + +/* ------------------------------------ lists (level 0) --------------------- */ + +#define SGLIB_LIST_ADD(type, list, elem, next) {\ + (elem)->next = (list);\ + (list) = (elem);\ +} + +#define SGLIB_LIST_CONCAT(type, first, second, next) {\ + if ((first)==NULL) {\ + (first) = (second);\ + } else {\ + type *_p_;\ + for(_p_ = (first); _p_->next!=NULL; _p_=_p_->next) ;\ + _p_->next = (second);\ + }\ +} + +#define SGLIB_LIST_DELETE(type, list, elem, next) {\ + type **_p_;\ + for(_p_ = &(list); *_p_!=NULL && *_p_!=(elem); _p_= &(*_p_)->next) ;\ + assert(*_p_!=NULL && "element is not member of the container, use DELETE_IF_MEMBER instead"!=NULL);\ + *_p_ = (*_p_)->next;\ +} + +#define SGLIB_LIST_ADD_IF_NOT_MEMBER(type, list, elem, comparator, next, member) {\ + type *_p_;\ + for(_p_ = (list); _p_!=NULL && comparator(_p_, (elem)) != 0; _p_= _p_->next) ;\ + (member) = _p_;\ + if (_p_ == NULL) {\ + SGLIB_LIST_ADD(type, list, elem, next);\ + }\ +} + +#define SGLIB_LIST_DELETE_IF_MEMBER(type, list, elem, comparator, next, member) {\ + type **_p_;\ + for(_p_ = &(list); *_p_!=NULL && comparator((*_p_), (elem)) != 0; _p_= &(*_p_)->next) ;\ + (member) = *_p_;\ + if (*_p_ != NULL) {\ + *_p_ = (*_p_)->next;\ + }\ +} + +#define SGLIB_LIST_IS_MEMBER(type, list, elem, next, result) {\ + type *_p_;\ + for(_p_ = (list); _p_!=NULL && _p_ != (elem); _p_= _p_->next) ;\ + (result) = (_p_!=NULL);\ +} + +#define SGLIB_LIST_FIND_MEMBER(type, list, elem, comparator, next, member) {\ + type *_p_;\ + for(_p_ = (list); _p_!=NULL && comparator(_p_, (elem)) != 0; _p_= _p_->next) ;\ + (member) = _p_;\ +} + +#define SGLIB_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, next, command) {\ + type *_ne_;\ + type *iteratedVariable;\ + (iteratedVariable) = (list); \ + while ((iteratedVariable)!=NULL) {\ + _ne_ = (iteratedVariable)->next;\ + {command;};\ + (iteratedVariable) = _ne_;\ + }\ +} + +#define SGLIB_LIST_LEN(type, list, next, result) {\ + type *_ce_;\ + (result) = 0;\ + SGLIB_LIST_MAP_ON_ELEMENTS(type, list, _ce_, next, (result)++);\ +} + +#define SGLIB_LIST_REVERSE(type, list, next) {\ + type *_list_,*_tmp_,*_res_;\ + _list_ = (list);\ + _res_ = NULL;\ + while (_list_!=NULL) {\ + _tmp_ = _list_->next; _list_->next = _res_;\ + _res_ = _list_; _list_ = _tmp_;\ + }\ + (list) = _res_;\ +} + +#define SGLIB_LIST_SORT(type, list, comparator, next) {\ + /* a non-recursive merge sort on lists */\ + type *_r_;\ + type *_a_, *_b_, *_todo_, *_t_, **_restail_;\ + int _i_, _n_, _contFlag_;\ + _r_ = (list);\ + _contFlag_ = 1;\ + for(_n_ = 1; _contFlag_; _n_ = _n_+_n_) {\ + _todo_ = _r_; _r_ = NULL; _restail_ = &_r_; _contFlag_ =0;\ + while (_todo_!=NULL) {\ + _a_ = _todo_;\ + for(_i_ = 1, _t_ = _a_; _i_ < _n_ && _t_!=NULL; _i_++, _t_ = _t_->next) ;\ + if (_t_ ==NULL) {\ + *_restail_ = _a_;\ + break;\ + }\ + _b_ = _t_->next; _t_->next=NULL;\ + for(_i_ =1, _t_ = _b_; _i_<_n_ && _t_!=NULL; _i_++, _t_ = _t_->next) ;\ + if (_t_ ==NULL) {\ + _todo_ =NULL;\ + } else {\ + _todo_ = _t_->next; _t_->next=NULL;\ + }\ + /* merge */\ + while (_a_!=NULL && _b_!=NULL) {\ + if (comparator(_a_, _b_) < 0) {\ + *_restail_ = _a_; _restail_ = &(_a_->next); _a_ = _a_->next;\ + } else {\ + *_restail_ = _b_; _restail_ = &(_b_->next); _b_ = _b_->next;\ + }\ + }\ + if (_a_!=NULL) *_restail_ = _a_;\ + else *_restail_ = _b_;\ + while (*_restail_!=NULL) _restail_ = &((*_restail_)->next);\ + _contFlag_ =1;\ + }\ + }\ + (list) = _r_;\ +} + +/* --------------------------------- sorted list (level 0) --------------------- */ +/* + All operations suppose that the list is sorted and they preserve + this property. +*/ + + +#define SGLIB_SORTED_LIST_ADD(type, list, elem, comparator, next) {\ + type **_e_;\ + int _cmpres_;\ + SGLIB_SORTED_LIST_FIND_MEMBER_OR_PLACE(type, list, elem, comparator, next, _cmpres_, _e_);\ + (elem)->next = *_e_;\ + *_e_ = (elem);\ +} + +#define SGLIB_SORTED_LIST_ADD_IF_NOT_MEMBER(type, list, elem, comparator, next, member) {\ + type **_e_;\ + int _cmp_res_;\ + SGLIB_SORTED_LIST_FIND_MEMBER_OR_PLACE(type, list, elem, comparator, next, _cmp_res_, _e_);\ + if (_cmp_res_ != 0) {\ + (elem)->next = *_e_;\ + *_e_ = (elem);\ + (member) = NULL;\ + } else {\ + (member) = *_e_;\ + }\ +} + +#define SGLIB_SORTED_LIST_DELETE(type, list, elem, next) {\ + SGLIB_LIST_DELETE(type, list, elem, next);\ +} + +#define SGLIB_SORTED_LIST_DELETE_IF_MEMBER(type, list, elem, comparator, next, member) {\ + type **_e_;\ + int _cmp_res_;\ + SGLIB_SORTED_LIST_FIND_MEMBER_OR_PLACE(type, list, elem, comparator, next, _cmp_res_, _e_);\ + if (_cmp_res_ == 0) {\ + (member) = *_e_;\ + *_e_ = (*_e_)->next;\ + } else {\ + (member) = NULL;\ + }\ +} + +#define SGLIB_SORTED_LIST_FIND_MEMBER(type, list, elem, comparator, next, member) {\ + type *_p_;\ + int _cmpres_ = 1;\ + for(_p_ = (list); _p_!=NULL && (_cmpres_=comparator(_p_, (elem))) < 0; _p_=_p_->next) ;\ + if (_cmpres_ != 0) (member) = NULL;\ + else (member) = _p_;\ +} + +#define SGLIB_SORTED_LIST_IS_MEMBER(type, list, elem, comparator, next, result) {\ + type *_p_;\ + for(_p_ = (list); _p_!=NULL && comparator(_p_, (elem)) < 0; _p_=_p_->next) ;\ + while (_p_ != NULL && _p_ != (elem) && comparator(_p_, (elem)) == 0) _p_=_p_->next;\ + (result) = (_p_ == (elem));\ +} + +#define SGLIB_SORTED_LIST_FIND_MEMBER_OR_PLACE(type, list, elem, comparator, next, comparator_result, member_ptr) {\ + (comparator_result) = -1;\ + for((member_ptr) = &(list); \ + *(member_ptr)!=NULL && ((comparator_result)=comparator((*member_ptr), (elem))) < 0; \ + (member_ptr) = &(*(member_ptr))->next) ;\ +} + +#define SGLIB_SORTED_LIST_LEN(type, list, next, result) {\ + SGLIB_LIST_LEN(type, list, next, result);\ +} + +#define SGLIB_SORTED_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, next, command) {\ + SGLIB_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, next, command);\ +} + + +/* ------------------------------- double linked list (level 0) ------------------------- */ +/* + Lists with back pointer to previous element. Those lists implements deletion + of an element in a constant time. +*/ + +#define SGLIB___DL_LIST_CREATE_SINGLETON(type, list, elem, previous, next) {\ + (list) = (elem);\ + (list)->next = (list)->previous = NULL;\ +} + +#define SGLIB_DL_LIST_ADD_AFTER(type, place, elem, previous, next) {\ + if ((place) == NULL) {\ + SGLIB___DL_LIST_CREATE_SINGLETON(type, place, elem, previous, next);\ + } else {\ + (elem)->next = (place)->next;\ + (elem)->previous = (place);\ + (place)->next = (elem);\ + if ((elem)->next != NULL) (elem)->next->previous = (elem);\ + }\ +} + +#define SGLIB_DL_LIST_ADD_BEFORE(type, place, elem, previous, next) {\ + if ((place) == NULL) {\ + SGLIB___DL_LIST_CREATE_SINGLETON(type, place, elem, previous, next);\ + } else {\ + (elem)->next = (place);\ + (elem)->previous = (place)->previous;\ + (place)->previous = (elem);\ + if ((elem)->previous != NULL) (elem)->previous->next = (elem);\ + }\ +} + +#define SGLIB_DL_LIST_ADD(type, list, elem, previous, next) {\ + SGLIB_DL_LIST_ADD_BEFORE(type, list, elem, previous, next)\ +} + +#define SGLIB___DL_LIST_GENERIC_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member, the_add_operation) {\ + type *_dlp_;\ + for(_dlp_ = (list); _dlp_!=NULL && comparator(_dlp_, (elem)) != 0; _dlp_= _dlp_->previous) ;\ + if (_dlp_ == NULL && (list) != NULL) {\ + for(_dlp_ = (list)->next; _dlp_!=NULL && comparator(_dlp_, (elem)) != 0; _dlp_= _dlp_->next) ;\ + }\ + (member) = _dlp_;\ + if (_dlp_ == NULL) {\ + the_add_operation(type, list, elem, previous, next);\ + }\ +} + +#define SGLIB_DL_LIST_ADD_BEFORE_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member) {\ + SGLIB___DL_LIST_GENERIC_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member, SGLIB_DL_LIST_ADD_BEFORE);\ +} + +#define SGLIB_DL_LIST_ADD_AFTER_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member) {\ + SGLIB___DL_LIST_GENERIC_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member, SGLIB_DL_LIST_ADD_AFTER);\ +} + +#define SGLIB_DL_LIST_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member) {\ + SGLIB___DL_LIST_GENERIC_ADD_IF_NOT_MEMBER(type, list, elem, comparator, previous, next, member, SGLIB_DL_LIST_ADD);\ +} + +#define SGLIB_DL_LIST_CONCAT(type, first, second, previous, next) {\ + if ((first)==NULL) {\ + (first) = (second);\ + } else if ((second)!=NULL) {\ + type *_dlp_;\ + for(_dlp_ = (first); _dlp_->next!=NULL; _dlp_=_dlp_->next) ;\ + SGLIB_DL_LIST_ADD_AFTER(type, _dlp_, second, previous, next);\ + }\ +} + +#define SGLIB_DL_LIST_DELETE(type, list, elem, previous, next) {\ + type *_l_;\ + _l_ = (list);\ + if (_l_ == (elem)) {\ + if ((elem)->previous != NULL) _l_ = (elem)->previous;\ + else _l_ = (elem)->next;\ + }\ + if ((elem)->next != NULL) (elem)->next->previous = (elem)->previous;\ + if ((elem)->previous != NULL) (elem)->previous->next = (elem)->next;\ + (list) = _l_;\ +} + +#define SGLIB_DL_LIST_DELETE_IF_MEMBER(type, list, elem, comparator, previous, next, member) {\ + type *_dlp_;\ + for(_dlp_ = (list); _dlp_!=NULL && comparator(_dlp_, (elem)) != 0; _dlp_= _dlp_->previous) ;\ + if (_dlp_ == NULL && (list) != NULL) {\ + for(_dlp_ = (list)->next; _dlp_!=NULL && comparator(_dlp_, (elem)) != 0; _dlp_= _dlp_->next) ;\ + }\ + (member) = _dlp_;\ + if (_dlp_ != NULL) {\ + SGLIB_DL_LIST_DELETE(type, list, _dlp_, previous, next);\ + }\ +} + +#define SGLIB_DL_LIST_IS_MEMBER(type, list, elem, previous, next, result) {\ + type *_dlp_;\ + SGLIB_LIST_IS_MEMBER(type, list, elem, previous, result);\ + if (result == 0 && (list) != NULL) {\ + _dlp_ = (list)->next;\ + SGLIB_LIST_IS_MEMBER(type, _dlp_, elem, next, result);\ + }\ +} + +#define SGLIB_DL_LIST_FIND_MEMBER(type, list, elem, comparator, previous, next, member) {\ + type *_dlp_;\ + SGLIB_LIST_FIND_MEMBER(type, list, elem, comparator, previous, member);\ + if ((member) == NULL && (list) != NULL) {\ + _dlp_ = (list)->next;\ + SGLIB_LIST_FIND_MEMBER(type, _dlp_, elem, comparator, next, member);\ + }\ +} + +#define SGLIB_DL_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, previous, next, command) {\ + type *_dl_;\ + type *iteratedVariable;\ + if ((list)!=NULL) {\ + _dl_ = (list)->next;\ + SGLIB_LIST_MAP_ON_ELEMENTS(type, list, iteratedVariable, previous, command);\ + SGLIB_LIST_MAP_ON_ELEMENTS(type, _dl_, iteratedVariable, next, command);\ + }\ +} + +#define SGLIB_DL_LIST_SORT(type, list, comparator, previous, next) {\ + type *_dll_, *_dlp_, *_dlt_;\ + _dll_ = (list);\ + if (_dll_ != NULL) {\ + for(; _dll_->previous!=NULL; _dll_=_dll_->previous) ;\ + SGLIB_LIST_SORT(type, _dll_, comparator, next);\ + SGLIB___DL_LIST_CREATE_FROM_LIST(type, _dll_, previous, next);\ + (list) = _dll_;\ + }\ +} + +#define SGLIB_DL_LIST_GET_FIRST(type, list, previous, next, result) {\ + type *_dll_;\ + _dll_ = (list);\ + if (_dll_ != NULL) {\ + for(; _dll_->previous!=NULL; _dll_=_dll_->previous) ;\ + }\ + (result) = _dll_;\ +} + +#define SGLIB_DL_LIST_GET_LAST(type, list, previous, next, result) {\ + type *_dll_;\ + _dll_ = (list);\ + if (_dll_ != NULL) {\ + for(; _dll_->next!=NULL; _dll_=_dll_->next) ;\ + }\ + (result) = _dll_;\ +} + +#define SGLIB_DL_LIST_LEN(type, list, previous, next, result) {\ + type *_dl_;\ + int _r1_, _r2_;\ + if ((list)==NULL) {\ + (result) = 0;\ + } else {\ + SGLIB_LIST_LEN(type, list, previous, _r1_);\ + _dl_ = (list)->next;\ + SGLIB_LIST_LEN(type, _dl_, next, _r2_);\ + (result) = _r1_ + _r2_;\ + }\ +} + +#define SGLIB_DL_LIST_REVERSE(type, list, previous, next) {\ + type *_list_,*_nlist_,*_dlp_,*_dln_;\ + _list_ = (list);\ + if (_list_!=NULL) {\ + _nlist_ = _list_->next;\ + while (_list_!=NULL) {\ + _dln_ = _list_->next; \ + _dlp_ = _list_->previous; \ + _list_->next = _dlp_;\ + _list_->previous = _dln_;\ + _list_ = _dlp_;\ + }\ + while (_nlist_!=NULL) {\ + _dln_ = _nlist_->next; \ + _dlp_ = _nlist_->previous; \ + _nlist_->next = _dlp_;\ + _nlist_->previous = _dln_;\ + _nlist_ = _dln_;\ + }\ + }\ +} + +#define SGLIB___DL_LIST_CREATE_FROM_LIST(type, list, previous, next) {\ + type *_dlp_, *_dlt_;\ + _dlp_ = NULL;\ + for(_dlt_ = (list); _dlt_!=NULL; _dlt_ = _dlt_->next) {\ + _dlt_->previous = _dlp_;\ + _dlp_ = _dlt_;\ + }\ +} + + +/* ------------------------------- binary tree traversal (level 0) -------------------- */ + + +#define SGLIB___BIN_TREE_MAP_ON_ELEMENTS(type, tree, iteratedVariable, order, left, right, command) {\ + /* this is non-recursive implementation of tree traversal */\ + /* it maintains the path to the current node in the array '_path_' */\ + /* the _path_[0] contains the root of the tree; */\ + /* the _path_[_pathi_] contains the _current_element_ */\ + /* the macro does not use the _current_element_ after execution of command */\ + /* command can destroy it, it can free the element for example */\ + type *_path_[SGLIB_MAX_TREE_DEEP];\ + type *_right_[SGLIB_MAX_TREE_DEEP];\ + char _pass_[SGLIB_MAX_TREE_DEEP];\ + type *_cn_;\ + int _pathi_;\ + type *iteratedVariable;\ + _cn_ = (tree);\ + _pathi_ = 0;\ + while (_cn_!=NULL) {\ + /* push down to leftmost innermost element */\ + while(_cn_!=NULL) {\ + _path_[_pathi_] = _cn_;\ + _right_[_pathi_] = _cn_->right;\ + _pass_[_pathi_] = 0;\ + _cn_ = _cn_->left;\ + if (order == 0) {\ + iteratedVariable = _path_[_pathi_];\ + {command;}\ + }\ + _pathi_ ++;\ + if (_pathi_ >= SGLIB_MAX_TREE_DEEP) assert(0 && "the binary_tree is too deep");\ + }\ + do {\ + _pathi_ --;\ + if ((order==1 && _pass_[_pathi_] == 0)\ + || (order == 2 && (_pass_[_pathi_] == 1 || _right_[_pathi_]==NULL))) {\ + iteratedVariable = _path_[_pathi_];\ + {command;}\ + }\ + _pass_[_pathi_] ++;\ + } while (_pathi_>0 && _right_[_pathi_]==NULL) ;\ + _cn_ = _right_[_pathi_];\ + _right_[_pathi_] = NULL;\ + _pathi_ ++;\ + }\ +} + +#define SGLIB_BIN_TREE_MAP_ON_ELEMENTS(type, tree, _current_element_, left, right, command) {\ + SGLIB___BIN_TREE_MAP_ON_ELEMENTS(type, tree, _current_element_, 1, left, right, command);\ +} + +#define SGLIB_BIN_TREE_MAP_ON_ELEMENTS_PREORDER(type, tree, _current_element_, left, right, command) {\ + SGLIB___BIN_TREE_MAP_ON_ELEMENTS(type, tree, _current_element_, 0, left, right, command);\ +} + +#define SGLIB_BIN_TREE_MAP_ON_ELEMENTS_POSTORDER(type, tree, _current_element_, left, right, command) {\ + SGLIB___BIN_TREE_MAP_ON_ELEMENTS(type, tree, _current_element_, 2, left, right, command);\ +} + +#define SGLIB___BIN_TREE_FIND_MEMBER(type, tree, elem, left, right, comparator, res) {\ + type *_s_;\ + int _c_;\ + _s_ = (tree);\ + while (_s_!=NULL) {\ + _c_ = comparator((elem), _s_);\ + if (_c_ < 0) _s_ = _s_->left;\ + else if (_c_ > 0) _s_ = _s_->right;\ + else break;\ + }\ + (res) = _s_;\ +} + +/* ---------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------------- */ +/* - LEVEL - 1 INTERFACE - */ +/* ---------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------------- */ + + + +/* ---------------------------------------------------------------------------- */ +/* ------------------------------ STATIC ARRAYS ------------------------------- */ +/* ---------------------------------------------------------------------------- */ + +/* ----------------------------- array sorting (level 1) ---------------------- */ + +#define SGLIB_DEFINE_ARRAY_SORTING_PROTOTYPES(type, comparator) \ + extern void sglib_##type##_array_quick_sort(type *a, int max);\ + extern void sglib_##type##_array_heap_sort(type *a, int max);\ + + +#define SGLIB_DEFINE_ARRAY_SORTING_FUNCTIONS(type, comparator) \ + void sglib_##type##_array_quick_sort(type *a, int max) {\ + SGLIB_ARRAY_SINGLE_QUICK_SORT(type, a, max, comparator);\ + }\ + void sglib_##type##_array_heap_sort(type *a, int max) {\ + SGLIB_ARRAY_SINGLE_HEAP_SORT(type, a, max, comparator);\ + }\ + + +/* ----------------------------- array queue (level 1) ------------------- */ +/* sglib's queue is stored in a fixed sized array */ +/* queue_type MUST be a structure containing fields: */ +/* afield is the array storing elem_type */ +/* ifield is the index of the first element in the queue */ +/* jfield is the index of the first free element after the queue */ +/* dim is the size of the array afield */ +/* !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! */ + + +#define SGLIB_DEFINE_QUEUE_PROTOTYPES(queue_type, elem_type, afield, ifield, jfield, dim) \ + extern void sglib_##queue_type##_init(queue_type *q); \ + extern int sglib_##queue_type##_is_empty(queue_type *q); \ + extern int sglib_##queue_type##_is_full(queue_type *q); \ + extern elem_type sglib_##queue_type##_first_element(queue_type *q); \ + extern elem_type *sglib_##queue_type##_first_element_ptr(queue_type *q); \ + extern void sglib_##queue_type##_add_next(queue_type *q); \ + extern void sglib_##queue_type##_add(queue_type *q, elem_type elem); \ + extern void sglib_##queue_type##_delete_first(queue_type *q); \ + extern void sglib_##queue_type##_delete(queue_type *q); + + +#define SGLIB_DEFINE_QUEUE_FUNCTIONS(queue_type, elem_type, afield, ifield, jfield, dim) \ + void sglib_##queue_type##_init(queue_type *q) {\ + SGLIB_QUEUE_INIT(elem_type, q->afield, q->ifield, q->jfield);\ + }\ + int sglib_##queue_type##_is_empty(queue_type *q) {\ + return(SGLIB_QUEUE_IS_EMPTY(elem_type, q->afield, q->ifield, q->jfield));\ + }\ + int sglib_##queue_type##_is_full(queue_type *q) {\ + return(SGLIB_QUEUE_IS_FULL(elem_type, q->afield, q->ifield, q->jfield));\ + }\ + elem_type sglib_##queue_type##_first_element(queue_type *q) {\ + return(SGLIB_QUEUE_FIRST_ELEMENT(elem_type, q->afield, q->ifield, q->jfield));\ + }\ + elem_type *sglib_##queue_type##_first_element_ptr(queue_type *q) {\ + return(& SGLIB_QUEUE_FIRST_ELEMENT(elem_type, q->afield, q->ifield, q->jfield));\ + }\ + void sglib_##queue_type##_add_next(queue_type *q) {\ + SGLIB_QUEUE_ADD_NEXT(elem_type, q->afield, q->ifield, q->jfield, dim);\ + }\ + void sglib_##queue_type##_add(queue_type *q, elem_type elem) {\ + SGLIB_QUEUE_ADD(elem_type, q->afield, elem, q->ifield, q->jfield, dim);\ + }\ + void sglib_##queue_type##_delete_first(queue_type *q) {\ + SGLIB_QUEUE_DELETE_FIRST(elem_type, q->afield, q->ifield, q->jfield, dim);\ + }\ + void sglib_##queue_type##_delete(queue_type *q) {\ + SGLIB_QUEUE_DELETE_FIRST(elem_type, q->afield, q->ifield, q->jfield, dim);\ + } + + +/* ------------------------ array heap (level 1) ------------------------- */ +/* sglib's heap is a priority queue implemented in a fixed sized array */ +/* heap_type MUST be a structure containing fields: */ +/* afield is the array of size dim storing elem_type */ +/* ifield is the index of the first free element after the queue */ +/* !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! */ + + +#define SGLIB_DEFINE_HEAP_PROTOTYPES(heap_type, elem_type, afield, ifield, dim, comparator, elem_exchanger) \ + extern void sglib_##heap_type##_init(heap_type *q); \ + extern int sglib_##heap_type##_is_empty(heap_type *q); \ + extern int sglib_##heap_type##_is_full(heap_type *q); \ + extern elem_type sglib_##heap_type##_first_element(heap_type *q); \ + extern elem_type *sglib_##heap_type##_first_element_ptr(heap_type *q); \ + extern void sglib_##heap_type##_add_next(heap_type *q); \ + extern void sglib_##heap_type##_add(heap_type *q, elem_type elem); \ + extern void sglib_##heap_type##_delete_first(heap_type *q); \ + extern void sglib_##heap_type##_delete(heap_type *q) + +#define SGLIB_DEFINE_HEAP_FUNCTIONS(heap_type, elem_type, afield, ifield, dim, comparator, elem_exchanger) \ + void sglib_##heap_type##_init(heap_type *q) {\ + SGLIB_HEAP_INIT(elem_type, q->afield, q->ifield);\ + }\ + int sglib_##heap_type##_is_empty(heap_type *q) {\ + return(SGLIB_HEAP_IS_EMPTY(elem_type, q->afield, q->ifield));\ + }\ + int sglib_##heap_type##_is_full(heap_type *q) {\ + return(SGLIB_HEAP_IS_FULL(elem_type, q->afield, q->ifield));\ + }\ + elem_type sglib_##heap_type##_first_element(heap_type *q) {\ + return(SGLIB_HEAP_FIRST_ELEMENT(elem_type, q->afield, q->ifield));\ + }\ + elem_type *sglib_##heap_type##_first_element_ptr(heap_type *q) {\ + return(& SGLIB_HEAP_FIRST_ELEMENT(elem_type, q->afield, q->ifield));\ + }\ + void sglib_##heap_type##_add_next(heap_type *q) {\ + SGLIB_HEAP_ADD_NEXT(elem_type, q->afield, q->ifield, dim, comparator, elem_exchanger);\ + }\ + void sglib_##heap_type##_add(heap_type *q, elem_type elem) {\ + SGLIB_HEAP_ADD(elem_type, q->afield, elem, q->ifield, dim, comparator, elem_exchanger);\ + }\ + void sglib_##heap_type##_delete_first(heap_type *q) {\ + SGLIB_HEAP_DELETE_FIRST(elem_type, q->afield, q->ifield, dim, comparator, elem_exchanger);\ + }\ + void sglib_##heap_type##_delete(heap_type *q) {\ + SGLIB_HEAP_DELETE_FIRST(elem_type, q->afield, q->ifield, dim, comparator, elem_exchanger);\ + } + + +/* ------------------------ hashed table (level 1) ------------------------- */ +/* + + sglib's hash table is an array storing directly pointers to objects (not containers). + In this table there is a one-to-one mapping between 'objects' stored + in the table and indexes where they are placed. Each index is + pointing to exactly one 'object' and each 'object' stored in the + table occurs on exactly one index. Once an object is stored in the + table, it can be represented via its index. + + type - is the type of elements + dim - is the size of the hash array + hash_function - is a hashing function mapping type* to unsigned + comparator - is a comparator on elements + + !!!!!!! This data structure is NOT documented, do not use it !!!!!!!!!! +*/ + +#define SGLIB_DEFINE_HASHED_TABLE_PROTOTYPES(type, dim, hash_function, comparator) \ + struct sglib_hashed_##type##_iterator {\ + int currentIndex;\ + int (*subcomparator)(type *, type *);\ + type *equalto;\ + };\ + extern void sglib_hashed_##type##_init(type *table[dim]);\ + extern int sglib_hashed_##type##_add_if_not_member(type *table[dim], type *elem, type **member);\ + extern int sglib_hashed_##type##_is_member(type *table[dim], type *elem);\ + extern type * sglib_hashed_##type##_find_member(type *table[dim], type *elem);\ + extern type *sglib_hashed_##type##_it_init(struct sglib_hashed_##type##_iterator *it, type *table[dim]); \ + extern type *sglib_hashed_##type##_it_init_on_equal(struct sglib_hashed_##type##_iterator *it, type *table[dim], int (*subcomparator)(type *, type *), type *equalto); \ + extern type *sglib_hashed_##type##_it_current(struct sglib_hashed_##type##_iterator *it); \ + extern type *sglib_hashed_##type##_it_next(struct sglib_hashed_##type##_iterator *it); + +#define SGLIB_DEFINE_HASHED_TABLE_FUNCTIONS(type, dim, hash_function, comparator) \ + struct sglib_hashed_##type##_iterator {\ + int currentIndex;\ + type **table;\ + int (*subcomparator)(type *, type *);\ + type *equalto;\ + };\ + void sglib_hashed_##type##_init(type *table[dim]) {\ + SGLIB_HASH_TAB_INIT(type, table, dim);\ + }\ + int sglib_hashed_##type##_add_if_not_member(type *table[dim], type *elem, type **member) {\ + SGLIB_HASH_TAB_ADD_IF_NOT_MEMBER(type, table, dim, elem, hash_function, comparator, *member);\ + }\ + int sglib_hashed_##type##_is_member(type *table[dim], type *elem) {\ + int ind;\ + SGLIB_HASH_TAB_IS_MEMBER(type, table, dim, elem, hash_function, ind);\ + return(ind != -1);\ + }\ + type * sglib_hashed_##type##_find_member(type *table[dim], type *elem) {\ + type *mmb;\ + int ind;\ + SGLIB_HASH_TAB_FIND_MEMBER(type, table, dim, elem, hash_function, comparator, ind, mmb);\ + return(mmb);\ + }\ + type *sglib_hashed_##type##_it_init_on_equal(struct sglib_hashed_##type##_iterator *it, type *table[dim], int (*subcomparator)(type *, type *), type *equalto) {\ + int i;\ + it->table = table;\ + it->subcomparator = subcomparator;\ + it->equalto = equalto;\ + for(i=0; i<(dim) && table[i]==NULL; i++) ;\ + it->currentIndex = i;\ + if (i<(dim)) return(table[i]);\ + return(NULL);\ + }\ + type *sglib_hashed_##type##_it_init(struct sglib_hashed_##type##_iterator *it, type *table[dim]) {\ + sglib_hashed_##type##_it_init_on_equal(it, table, NULL, NULL);\ + }\ + type *sglib_hashed_##type##_it_current(struct sglib_hashed_##type##_iterator *it) {\ + return(table[it->currentIndex]);\ + }\ + type *sglib_hashed_##type##_it_next(struct sglib_hashed_##type##_iterator *it) {\ + i=it->currentIndex;\ + if (i<(dim)) {\ + for(i++; i<(dim) && table[i]==NULL; i++) ;\ + }\ + it->currentIndex = i;\ + if (i<(dim)) return(table[i]);\ + return(NULL);\ + } + + +/* ------------------- hashed container (only for level 1) -------------------- */ +/* + hashed container is a table of given fixed size containing another + (dynamic) base container in each cell. Once an object should be + inserted into the hashed container, a hash function is used to + determine the cell where the object belongs and the object is + inserted into the base container stored in this cell. Usually the + base container is simply a list or a sorted list, but it can be a + red-black tree as well. + + parameters: + type - the type of the container stored in each cell. + dim - the size of the hashed array + hash_function - the hashing function hashing 'type *' to unsigned. + +*/ + +#define SGLIB_DEFINE_HASHED_CONTAINER_PROTOTYPES(type, dim, hash_function) \ + struct sglib_hashed_##type##_iterator {\ + struct sglib_##type##_iterator containerIt;\ + type **table;\ + int currentIndex;\ + int (*subcomparator)(type *, type *);\ + type *equalto;\ + };\ + extern void sglib_hashed_##type##_init(type *table[dim]);\ + extern void sglib_hashed_##type##_add(type *table[dim], type *elem);\ + extern int sglib_hashed_##type##_add_if_not_member(type *table[dim], type *elem, type **member);\ + extern void sglib_hashed_##type##_delete(type *table[dim], type *elem);\ + extern int sglib_hashed_##type##_delete_if_member(type *table[dim], type *elem, type **memb);\ + extern int sglib_hashed_##type##_is_member(type *table[dim], type *elem);\ + extern type * sglib_hashed_##type##_find_member(type *table[dim], type *elem);\ + extern type *sglib_hashed_##type##_it_init(struct sglib_hashed_##type##_iterator *it, type *table[dim]); \ + extern type *sglib_hashed_##type##_it_init_on_equal(struct sglib_hashed_##type##_iterator *it, type *table[dim], int (*subcomparator)(type *, type *), type *equalto); \ + extern type *sglib_hashed_##type##_it_current(struct sglib_hashed_##type##_iterator *it); \ + extern type *sglib_hashed_##type##_it_next(struct sglib_hashed_##type##_iterator *it); + +#define SGLIB_DEFINE_HASHED_CONTAINER_FUNCTIONS(type, dim, hash_function) \ + /*extern unsigned hash_function(type *elem);*/\ + void sglib_hashed_##type##_init(type *table[dim]) {\ + unsigned i;\ + for(i=0; i<(dim); i++) table[i] = NULL;\ + }\ + void sglib_hashed_##type##_add(type *table[dim], type *elem) {\ + unsigned i;\ + i = ((unsigned)hash_function(elem)) % (dim);\ + sglib_##type##_add(&(table)[i], elem);\ + }\ + int sglib_hashed_##type##_add_if_not_member(type *table[dim], type *elem, type **member) {\ + unsigned i;\ + i = ((unsigned)hash_function(elem)) % (dim);\ + return(sglib_##type##_add_if_not_member(&(table)[i], elem, member));\ + }\ + void sglib_hashed_##type##_delete(type *table[dim], type *elem) {\ + unsigned i;\ + i = ((unsigned)hash_function(elem)) % (dim);\ + sglib_##type##_delete(&(table)[i], elem);\ + }\ + int sglib_hashed_##type##_delete_if_member(type *table[dim], type *elem, type **memb) {\ + unsigned i;\ + i = ((unsigned)hash_function(elem)) % (dim);\ + return(sglib_##type##_delete_if_member(&(table)[i], elem, memb));\ + }\ + int sglib_hashed_##type##_is_member(type *table[dim], type *elem) {\ + unsigned i;\ + i = ((unsigned)hash_function(elem)) % (dim);\ + return(sglib_##type##_is_member((table)[i], elem));\ + }\ + type * sglib_hashed_##type##_find_member(type *table[dim], type *elem) {\ + unsigned i;\ + i = ((unsigned)hash_function(elem)) % (dim);\ + return(sglib_##type##_find_member((table)[i], elem));\ + }\ + type *sglib_hashed_##type##_it_init_on_equal(struct sglib_hashed_##type##_iterator *it, type *table[dim], int (*subcomparator)(type *, type *), type *equalto) {\ + type *e;\ + it->table = table;\ + it->currentIndex = 0;\ + it->subcomparator = subcomparator;\ + it->equalto = equalto;\ + e = sglib_##type##_it_init_on_equal(&it->containerIt, table[it->currentIndex], it->subcomparator, it->equalto);\ + if (e==NULL) e = sglib_hashed_##type##_it_next(it);\ + return(e);\ + }\ + type *sglib_hashed_##type##_it_init(struct sglib_hashed_##type##_iterator *it, type *table[dim]) {\ + return(sglib_hashed_##type##_it_init_on_equal(it, table, NULL, NULL));\ + }\ + type *sglib_hashed_##type##_it_current(struct sglib_hashed_##type##_iterator *it) {\ + return(sglib_##type##_it_current(&it->containerIt));\ + }\ + type *sglib_hashed_##type##_it_next(struct sglib_hashed_##type##_iterator *it) {\ + type *e;\ + e = sglib_##type##_it_next(&it->containerIt);\ + while (e==NULL && (++(it->currentIndex))<(dim)) {\ + e = sglib_##type##_it_init_on_equal(&it->containerIt, it->table[it->currentIndex], it->subcomparator, it->equalto);\ + }\ + return(e);\ + } + + + +/* ---------------------------------------------------------------------------- */ +/* ------------------------- DYNAMIC DATA STRUCTURES -------------------------- */ +/* ---------------------------------------------------------------------------- */ + + + +/* ------------------------------------ list (level 1) -------------------------------- */ + +#define SGLIB_DEFINE_LIST_PROTOTYPES(type, comparator, next) \ + struct sglib_##type##_iterator {\ + type *currentelem;\ + type *nextelem;\ + int (*subcomparator)(type *, type *);\ + type *equalto;\ + };\ + extern void sglib_##type##_add(type **list, type *elem);\ + extern int sglib_##type##_add_if_not_member(type **list, type *elem, type **member);\ + extern void sglib_##type##_concat(type **first, type *second);\ + extern void sglib_##type##_delete(type **list, type *elem);\ + extern int sglib_##type##_delete_if_member(type **list, type *elem, type **member);\ + extern int sglib_##type##_is_member(type *list, type *elem);\ + extern type *sglib_##type##_find_member(type *list, type *elem);\ + extern void sglib_##type##_sort(type **list);\ + extern int sglib_##type##_len(type *list);\ + extern void sglib_##type##_reverse(type **list);\ + extern type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list); \ + extern type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto); \ + extern type *sglib_##type##_it_current(struct sglib_##type##_iterator *it); \ + extern type *sglib_##type##_it_next(struct sglib_##type##_iterator *it); + + +#define SGLIB_DEFINE_LIST_FUNCTIONS(type, comparator, next) \ + int sglib_##type##_is_member(type *list, type *elem) {\ + int result;\ + SGLIB_LIST_IS_MEMBER(type, list, elem, next, result);\ + return(result);\ + }\ + type *sglib_##type##_find_member(type *list, type *elem) {\ + type *result;\ + SGLIB_LIST_FIND_MEMBER(type, list, elem, comparator, next, result);\ + return(result);\ + }\ + int sglib_##type##_add_if_not_member(type **list, type *elem, type **member) {\ + SGLIB_LIST_ADD_IF_NOT_MEMBER(type, *list, elem, comparator, next, *member);\ + return(*member==NULL);\ + }\ + void sglib_##type##_add(type **list, type *elem) {\ + SGLIB_LIST_ADD(type, *list, elem, next);\ + }\ + void sglib_##type##_concat(type **first, type *second) {\ + SGLIB_LIST_CONCAT(type, *first, second, next);\ + }\ + void sglib_##type##_delete(type **list, type *elem) {\ + SGLIB_LIST_DELETE(type, *list, elem, next);\ + }\ + int sglib_##type##_delete_if_member(type **list, type *elem, type **member) {\ + SGLIB_LIST_DELETE_IF_MEMBER(type, *list, elem, comparator, next, *member);\ + return(*member!=NULL);\ + }\ + void sglib_##type##_sort(type **list) { \ + SGLIB_LIST_SORT(type, *list, comparator, next);\ + }\ + int sglib_##type##_len(type *list) {\ + int res;\ + SGLIB_LIST_LEN(type, list, next, res);\ + return(res);\ + }\ + void sglib_##type##_reverse(type **list) {\ + SGLIB_LIST_REVERSE(type, *list, next);\ + }\ + \ + type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto) {\ + it->subcomparator = subcomparator;\ + it->equalto = equalto;\ + it->nextelem = list;\ + return(sglib_##type##_it_next(it));\ + }\ + type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list) {\ + return(sglib_##type##_it_init_on_equal(it, list, NULL, NULL));\ + }\ + type *sglib_##type##_it_current(struct sglib_##type##_iterator *it) {\ + return(it->currentelem);\ + }\ + type *sglib_##type##_it_next(struct sglib_##type##_iterator *it) {\ + type *ce, *eq;\ + int (*scp)(type *, type *);\ + ce = it->nextelem;\ + it->nextelem = NULL;\ + if (it->subcomparator != NULL) {\ + eq = it->equalto; \ + scp = it->subcomparator;\ + while (ce!=NULL && scp(ce, eq)!=0) ce = ce->next;\ + }\ + it->currentelem = ce;\ + if (ce != NULL) it->nextelem = ce->next;\ + return(ce);\ + } + +/* ----------------------------- sorted list (level 1) ----------------------------------- */ + + +#define SGLIB_DEFINE_SORTED_LIST_PROTOTYPES(type, comparator, next) \ + struct sglib_##type##_iterator {\ + type *currentelem;\ + type *nextelem;\ + int (*subcomparator)(type *, type *);\ + type *equalto;\ + };\ + extern void sglib_##type##_add(type **list, type *elem);\ + extern int sglib_##type##_add_if_not_member(type **list, type *elem, type **member);\ + extern void sglib_##type##_delete(type **list, type *elem);\ + extern int sglib_##type##_delete_if_member(type **list, type *elem, type **member);\ + extern int sglib_##type##_is_member(type *list, type *elem);\ + extern type *sglib_##type##_find_member(type *list, type *elem);\ + extern int sglib_##type##_len(type *list);\ + extern void sglib_##type##_sort(type **list);\ + extern type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list); \ + extern type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto); \ + extern type *sglib_##type##_it_current(struct sglib_##type##_iterator *it); \ + extern type *sglib_##type##_it_next(struct sglib_##type##_iterator *it); + + +#define SGLIB_DEFINE_SORTED_LIST_FUNCTIONS(type, comparator, next) \ + int sglib_##type##_is_member(type *list, type *elem) {\ + int result;\ + SGLIB_SORTED_LIST_IS_MEMBER(type, list, elem, comparator, next, result);\ + return(result);\ + }\ + type *sglib_##type##_find_member(type *list, type *elem) {\ + type *result;\ + SGLIB_SORTED_LIST_FIND_MEMBER(type, list, elem, comparator, next, result);\ + return(result);\ + }\ + int sglib_##type##_add_if_not_member(type **list, type *elem, type **member) {\ + SGLIB_SORTED_LIST_ADD_IF_NOT_MEMBER(type, *list, elem, comparator, next, *member);\ + return(*member==NULL);\ + }\ + void sglib_##type##_add(type **list, type *elem) {\ + SGLIB_SORTED_LIST_ADD(type, *list, elem, comparator, next);\ + }\ + void sglib_##type##_delete(type **list, type *elem) {\ + SGLIB_SORTED_LIST_DELETE(type, *list, elem, next);\ + }\ + int sglib_##type##_delete_if_member(type **list, type *elem, type **member) {\ + SGLIB_SORTED_LIST_DELETE_IF_MEMBER(type, *list, elem, comparator, next, *member);\ + return(*member!=NULL);\ + }\ + int sglib_##type##_len(type *list) {\ + int res;\ + SGLIB_SORTED_LIST_LEN(type, list, next, res);\ + return(res);\ + }\ + void sglib_##type##_sort(type **list) { \ + SGLIB_LIST_SORT(type, *list, comparator, next);\ + }\ + \ + type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto) {\ + it->subcomparator = subcomparator;\ + it->equalto = equalto;\ + it->nextelem = list;\ + return(sglib_##type##_it_next(it));\ + }\ + type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list) {\ + return(sglib_##type##_it_init_on_equal(it, list, NULL, NULL));\ + }\ + type *sglib_##type##_it_current(struct sglib_##type##_iterator *it) {\ + return(it->currentelem);\ + }\ + type *sglib_##type##_it_next(struct sglib_##type##_iterator *it) {\ + type *ce, *eq;\ + int (*scp)(type *, type *);\ + int c;\ + ce = it->nextelem;\ + it->nextelem = NULL;\ + if (it->subcomparator != NULL) {\ + eq = it->equalto; \ + scp = it->subcomparator;\ + while (ce!=NULL && (c=scp(ce, eq)) < 0) ce = ce->next;\ + if (ce != NULL && c > 0) ce = NULL;\ + }\ + it->currentelem = ce;\ + if (ce != NULL) it->nextelem = ce->next;\ + return(ce);\ + } + + +/* ----------------------------- double linked list (level 1) ------------------------------ */ + + +#define SGLIB_DEFINE_DL_LIST_PROTOTYPES(type, comparator, previous, next) \ + struct sglib_##type##_iterator {\ + type *currentelem;\ + type *prevelem;\ + type *nextelem;\ + int (*subcomparator)(type *, type *);\ + type *equalto;\ + };\ + extern void sglib_##type##_add(type **list, type *elem);\ + extern void sglib_##type##_add_before(type **list, type *elem);\ + extern void sglib_##type##_add_after(type **list, type *elem);\ + extern int sglib_##type##_add_if_not_member(type **list, type *elem, type **member);\ + extern int sglib_##type##_add_before_if_not_member(type **list, type *elem, type **member);\ + extern int sglib_##type##_add_after_if_not_member(type **list, type *elem, type **member);\ + extern void sglib_##type##_concat(type **first, type *second);\ + extern void sglib_##type##_delete(type **list, type *elem);\ + extern int sglib_##type##_delete_if_member(type **list, type *elem, type **member);\ + extern int sglib_##type##_is_member(type *list, type *elem);\ + extern type *sglib_##type##_find_member(type *list, type *elem);\ + extern type *sglib_##type##_get_first(type *list);\ + extern type *sglib_##type##_get_last(type *list);\ + extern void sglib_##type##_sort(type **list);\ + extern int sglib_##type##_len(type *list);\ + extern void sglib_##type##_reverse(type **list);\ + extern type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list); \ + extern type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto); \ + extern type *sglib_##type##_it_current(struct sglib_##type##_iterator *it); \ + extern type *sglib_##type##_it_next(struct sglib_##type##_iterator *it); + + +#define SGLIB_DEFINE_DL_LIST_FUNCTIONS(type, comparator, previous, next) \ + void sglib_##type##_add(type **list, type *elem) {\ + SGLIB_DL_LIST_ADD(type, *list, elem, previous, next);\ + }\ + void sglib_##type##_add_after(type **list, type *elem) {\ + SGLIB_DL_LIST_ADD_AFTER(type, *list, elem, previous, next);\ + }\ + void sglib_##type##_add_before(type **list, type *elem) {\ + SGLIB_DL_LIST_ADD_BEFORE(type, *list, elem, previous, next);\ + }\ + int sglib_##type##_add_if_not_member(type **list, type *elem, type **member) {\ + SGLIB_DL_LIST_ADD_IF_NOT_MEMBER(type, *list, elem, comparator, previous, next, *member);\ + return(*member==NULL);\ + }\ + int sglib_##type##_add_after_if_not_member(type **list, type *elem, type **member) {\ + SGLIB_DL_LIST_ADD_AFTER_IF_NOT_MEMBER(type, *list, elem, comparator, previous, next, *member);\ + return(*member==NULL);\ + }\ + int sglib_##type##_add_before_if_not_member(type **list, type *elem, type **member) {\ + SGLIB_DL_LIST_ADD_BEFORE_IF_NOT_MEMBER(type, *list, elem, comparator, previous, next, *member);\ + return(*member==NULL);\ + }\ + void sglib_##type##_concat(type **first, type *second) {\ + SGLIB_DL_LIST_CONCAT(type, *first, second, previous, next);\ + }\ + void sglib_##type##_delete(type **list, type *elem) {\ + SGLIB_DL_LIST_DELETE(type, *list, elem, previous, next);\ + }\ + int sglib_##type##_delete_if_member(type **list, type *elem, type **member) {\ + SGLIB_DL_LIST_DELETE_IF_MEMBER(type, *list, elem, comparator, previous, next, *member);\ + return(*member!=NULL);\ + }\ + int sglib_##type##_is_member(type *list, type *elem) {\ + int result;\ + SGLIB_DL_LIST_IS_MEMBER(type, list, elem, previous, next, result);\ + return(result);\ + }\ + type *sglib_##type##_find_member(type *list, type *elem) {\ + type *result;\ + SGLIB_DL_LIST_FIND_MEMBER(type, list, elem, comparator, previous, next, result);\ + return(result);\ + }\ + type *sglib_##type##_get_first(type *list) {\ + type *result;\ + SGLIB_DL_LIST_GET_FIRST(type, list, previous, next, result);\ + return(result);\ + }\ + type *sglib_##type##_get_last(type *list) {\ + type *result;\ + SGLIB_DL_LIST_GET_LAST(type, list, previous, next, result);\ + return(result);\ + }\ + void sglib_##type##_sort(type **list) {\ + SGLIB_DL_LIST_SORT(type, *list, comparator, previous, next);\ + }\ + int sglib_##type##_len(type *list) {\ + int res;\ + SGLIB_DL_LIST_LEN(type, list, previous, next, res);\ + return(res);\ + }\ + void sglib_##type##_reverse(type **list) {\ + SGLIB_DL_LIST_REVERSE(type, *list, previous, next);\ + }\ + \ + type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *list, int (*subcomparator)(type *, type *), type *equalto) {\ + it->subcomparator = subcomparator;\ + it->equalto = equalto;\ + it->prevelem = list;\ + it->nextelem = list;\ + if (list != NULL) it->nextelem = list->next;\ + return(sglib_##type##_it_next(it));\ + }\ + type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *list) {\ + return(sglib_##type##_it_init_on_equal(it, list, NULL, NULL));\ + }\ + type *sglib_##type##_it_current(struct sglib_##type##_iterator *it) {\ + return(it->currentelem);\ + }\ + type *sglib_##type##_it_next(struct sglib_##type##_iterator *it) {\ + type *ce, *eq;\ + int (*scp)(type *, type *);\ + ce = it->prevelem;\ + it->prevelem = NULL;\ + if (it->subcomparator != NULL) {\ + eq = it->equalto; \ + scp = it->subcomparator;\ + while (ce!=NULL && scp(eq, ce)!=0) ce = ce->previous;\ + }\ + if (ce != NULL) {\ + it->prevelem = ce->previous;\ + } else {\ + ce = it->nextelem;\ + it->nextelem = NULL;\ + if (it->subcomparator != NULL) {\ + eq = it->equalto; \ + scp = it->subcomparator;\ + while (ce!=NULL && scp(ce, eq)!=0) ce = ce->next;\ + }\ + if (ce != NULL) it->nextelem = ce->next;\ + }\ + it->currentelem = ce;\ + return(ce);\ + } + + +/* --------------------------------- red-black trees (level 1) -------------------------------- */ + +/* + +This implementation requires pointers to left and right sons (no +parent pointer is needed) and one bit of additional information +storing the color of the node. The implementation follows discrepancy +fixing rules from: +http://www.cis.ohio-state.edu/~gurari/course/cis680/cis680Ch11.html + +*/ + +#define SGLIB___RBTREE_FIX_INSERTION_DISCREPANCY(type, tree, leftt, rightt, bits, RED, BLACK) {\ + type *t, *tl, *a, *b, *c, *ar, *bl, *br, *cl, *cr;\ + t = *tree;\ + tl = t->leftt;\ + if (t->rightt!=NULL && SGLIB___GET_VALUE(t->rightt->bits)==RED) {\ + if (SGLIB___GET_VALUE(tl->bits)==RED) {\ + if ((tl->leftt!=NULL && SGLIB___GET_VALUE(tl->leftt->bits)==RED) \ + || (tl->rightt!=NULL && SGLIB___GET_VALUE(tl->rightt->bits)==RED)) {\ + SGLIB___SET_VALUE(t->leftt->bits,BLACK);\ + SGLIB___SET_VALUE(t->rightt->bits,BLACK);\ + SGLIB___SET_VALUE(t->bits,RED);\ + }\ + }\ + } else {\ + if (SGLIB___GET_VALUE(tl->bits)==RED) {\ + if (tl->leftt!=NULL && SGLIB___GET_VALUE(tl->leftt->bits)==RED) {\ + a = t; b = tl; c = tl->leftt;\ + br = b->rightt;\ + a->leftt = br;\ + b->leftt = c; b->rightt = a;\ + SGLIB___SET_VALUE(a->bits,RED);\ + SGLIB___SET_VALUE(b->bits,BLACK);\ + *tree = b;\ + } else if (tl->rightt!=NULL && SGLIB___GET_VALUE(tl->rightt->bits)==RED) {\ + a = t; b = tl; ar=a->rightt;\ + bl=b->leftt; c=b->rightt;\ + cl=c->leftt; cr=c->rightt;\ + b->rightt = cl;\ + a->leftt = cr;\ + c->leftt = b;\ + c->rightt = a;\ + SGLIB___SET_VALUE(c->bits,BLACK);\ + SGLIB___SET_VALUE(a->bits,RED);\ + *tree = c;\ + }\ + }\ + }\ +} + +#define SGLIB___RBTREE_FIX_DELETION_DISCREPANCY(type, tree, leftt, rightt, bits, RED, BLACK, res) {\ + type *t, *a, *b, *c, *d, *ar, *bl, *br, *cl, *cr, *dl, *dr;\ + t = a = *tree;\ + assert(t!=NULL);\ + ar = a->rightt;\ + b = t->leftt;\ + if (b==NULL) {\ + assert(SGLIB___GET_VALUE(t->bits)==RED);\ + SGLIB___SET_VALUE(t->bits,BLACK);\ + res = 0;\ + } else {\ + bl = b->leftt;\ + br = b->rightt;\ + if (SGLIB___GET_VALUE(b->bits)==RED) {\ + if (br==NULL) {\ + *tree = b;\ + SGLIB___SET_VALUE(b->bits,BLACK);\ + b->rightt = a;\ + a->leftt = br;\ + res = 0;\ + } else {\ + c = br;\ + assert(c!=NULL && SGLIB___GET_VALUE(c->bits)==BLACK);\ + cl = c->leftt;\ + cr = c->rightt;\ + if ((cl==NULL||SGLIB___GET_VALUE(cl->bits)==BLACK) && (cr==NULL||SGLIB___GET_VALUE(cr->bits)==BLACK)) {\ + *tree = b;\ + b->rightt = a;\ + SGLIB___SET_VALUE(b->bits,BLACK);\ + a->leftt = c;\ + SGLIB___SET_VALUE(c->bits,RED);\ + res = 0;\ + } else if (cl!=NULL && SGLIB___GET_VALUE(cl->bits)==RED) {\ + if (cr!=NULL && SGLIB___GET_VALUE(cr->bits)==RED) {\ + d = cr;\ + dl = d->leftt;\ + dr = d->rightt;\ + *tree = d;\ + SGLIB___SET_VALUE(d->bits,BLACK);\ + d->leftt = b;\ + c->rightt = dl;\ + d->rightt = a;\ + a->leftt = dr;\ + res = 0;\ + } else {\ + *tree = c;\ + c->leftt = b;\ + c->rightt = a;\ + b->leftt = bl;\ + b->rightt = cl;\ + a->leftt = cr;\ + SGLIB___SET_VALUE(cl->bits,BLACK);\ + res = 0;\ + }\ + } else if (cr!=NULL && SGLIB___GET_VALUE(cr->bits)==RED) {\ + assert(cl==NULL || SGLIB___GET_VALUE(cl->bits)==BLACK);\ + d = cr;\ + dl = d->leftt;\ + dr = d->rightt;\ + *tree = d;\ + SGLIB___SET_VALUE(d->bits,BLACK);\ + d->leftt = b;\ + c->rightt = dl;\ + d->rightt = a;\ + a->leftt = dr;\ + res = 0;\ + } else {\ + assert(0);\ + res = 0;\ + }\ + }\ + } else {\ + if ((bl==NULL || SGLIB___GET_VALUE(bl->bits)==BLACK) && (br==NULL || SGLIB___GET_VALUE(br->bits)==BLACK)) {\ + res = (SGLIB___GET_VALUE(a->bits)==BLACK);\ + SGLIB___SET_VALUE(a->bits,BLACK);\ + SGLIB___SET_VALUE(b->bits,RED);\ + } else if (bl!=NULL && SGLIB___GET_VALUE(bl->bits)==RED) {\ + if (br==NULL || SGLIB___GET_VALUE(br->bits)==BLACK) {\ + *tree = b;\ + SGLIB___SET_VALUE(b->bits,SGLIB___GET_VALUE(a->bits));\ + SGLIB___SET_VALUE(a->bits,BLACK);\ + b->rightt = a;\ + a->leftt = br;\ + SGLIB___SET_VALUE(bl->bits,BLACK);\ + res = 0;\ + } else {\ + assert(bl!=NULL);\ + assert(br!=NULL);\ + assert(SGLIB___GET_VALUE(bl->bits)==RED);\ + assert(SGLIB___GET_VALUE(br->bits)==RED);\ + c = br;\ + cl = c->leftt;\ + cr = c->rightt;\ + *tree = c;\ + SGLIB___SET_VALUE(c->bits,SGLIB___GET_VALUE(a->bits));\ + SGLIB___SET_VALUE(a->bits,BLACK);\ + c->leftt = b;\ + c->rightt = a;\ + b->rightt = cl;\ + a->leftt = cr;\ + res = 0;\ + }\ + } else {\ + assert(br!=NULL && SGLIB___GET_VALUE(br->bits)==RED);\ + c = br;\ + cl = c->leftt;\ + cr = c->rightt;\ + *tree = c;\ + SGLIB___SET_VALUE(c->bits,SGLIB___GET_VALUE(a->bits));\ + SGLIB___SET_VALUE(a->bits,BLACK);\ + c->leftt = b;\ + c->rightt = a;\ + b->rightt = cl;\ + a->leftt = cr;\ + res = 0;\ + }\ + }\ + }\ +} + + +#define SGLIB_DEFINE_RBTREE_FUNCTIONS_GENERAL(type, left, right, bits, comparator, RED, BLACK) \ +static void sglib___##type##_fix_left_insertion_discrepancy(type **tree) {\ + SGLIB___RBTREE_FIX_INSERTION_DISCREPANCY(type, tree, left, right, bits, RED, BLACK);\ +}\ +\ +static void sglib___##type##_fix_right_insertion_discrepancy(type **tree) {\ + SGLIB___RBTREE_FIX_INSERTION_DISCREPANCY(type, tree, right, left, bits, RED, BLACK);\ +}\ +\ +static int sglib___##type##_fix_left_deletion_discrepancy(type **tree) {\ + int res;\ + SGLIB___RBTREE_FIX_DELETION_DISCREPANCY(type, tree, right, left, bits, RED, BLACK, res);\ + return(res);\ +}\ +\ +static int sglib___##type##_fix_right_deletion_discrepancy(type **tree) {\ + int res;\ + SGLIB___RBTREE_FIX_DELETION_DISCREPANCY(type, tree, left, right, bits, RED, BLACK, res);\ + return(res);\ +}\ +\ +static void sglib___##type##_add_recursive(type **tree, type *elem) {\ + int cmp;\ + type *t;\ + t = *tree;\ + if (t == NULL) {\ + SGLIB___SET_VALUE(elem->bits,RED);\ + *tree =elem;\ + } else {\ + cmp = comparator(elem, t);\ + if (cmp < 0 || (cmp==0 && elemleft, elem);\ + if (SGLIB___GET_VALUE(t->bits)==BLACK) sglib___##type##_fix_left_insertion_discrepancy(tree);\ + } else {\ + sglib___##type##_add_recursive(&t->right, elem);\ + if (SGLIB___GET_VALUE(t->bits)==BLACK) sglib___##type##_fix_right_insertion_discrepancy(tree);\ + }\ + }\ +}\ +\ +static int sglib___##type##_delete_rightmost_leaf(type **tree, type **theLeaf) {\ + type *t;\ + int res, deepDecreased;\ + t = *tree;\ + res = 0;\ + assert(t!=NULL);\ + if (t->right == NULL) {\ + *theLeaf = t;\ + if (t->left!=NULL) {\ + if (SGLIB___GET_VALUE(t->bits)==BLACK && SGLIB___GET_VALUE(t->left->bits)==BLACK) res = 1;\ + SGLIB___SET_VALUE(t->left->bits,BLACK);\ + *tree = t->left;\ + } else {\ + *tree = NULL;\ + res = (SGLIB___GET_VALUE(t->bits)==BLACK);\ + }\ + } else {\ + deepDecreased = sglib___##type##_delete_rightmost_leaf(&t->right, theLeaf);\ + if (deepDecreased) res = sglib___##type##_fix_right_deletion_discrepancy(tree);\ + }\ + return(res);\ +}\ +\ +int sglib___##type##_delete_recursive(type **tree, type *elem) {\ + type *t, *theLeaf;\ + int cmp, res, deepDecreased;\ + t = *tree;\ + res = 0;\ + if (t==NULL) {\ + assert(0 && "The element to delete not found in the tree, use 'delete_if_member'"!=NULL);\ + } else {\ + cmp = comparator(elem, t);\ + if (cmp < 0 || (cmp==0 && elemleft, elem);\ + if (deepDecreased) {\ + res = sglib___##type##_fix_left_deletion_discrepancy(tree);\ + }\ + } else if (cmp > 0 || (cmp==0 && elem>t)) {\ + deepDecreased = sglib___##type##_delete_recursive(&t->right, elem);\ + if (deepDecreased) {\ + res = sglib___##type##_fix_right_deletion_discrepancy(tree);\ + }\ + } else {\ + assert(elem==t && "Deleting an element which is non member of the tree, use 'delete_if_member'"!=NULL);\ + if (t->left == NULL) {\ + if (t->right == NULL) {\ + /* a leaf, delete, it; */\ + *tree = NULL;\ + res = (SGLIB___GET_VALUE(t->bits)==BLACK);\ + } else {\ + if (SGLIB___GET_VALUE(t->bits)==0 && SGLIB___GET_VALUE(t->right->bits)==0) res = 1;\ + SGLIB___SET_VALUE(t->right->bits,BLACK);\ + *tree = t->right;\ + }\ + } else {\ + /* propagate deletion until righmost leaf of left subtree */\ + deepDecreased = sglib___##type##_delete_rightmost_leaf(&t->left, &theLeaf);\ + theLeaf->left = t->left;\ + theLeaf->right = t->right;\ + SGLIB___SET_VALUE(theLeaf->bits,SGLIB___GET_VALUE(t->bits));\ + *tree = theLeaf;\ + if (deepDecreased) res = sglib___##type##_fix_left_deletion_discrepancy(tree);\ + }\ + }\ + }\ + return(res);\ +}\ +\ +void sglib_##type##_add(type **tree, type *elem) {\ + elem->left = elem->right = NULL;\ + sglib___##type##_add_recursive(tree, elem);\ + SGLIB___SET_VALUE((*tree)->bits,BLACK);\ +}\ +\ +void sglib_##type##_delete(type **tree, type *elem) {\ + sglib___##type##_delete_recursive(tree, elem);\ + if (*tree!=NULL) SGLIB___SET_VALUE((*tree)->bits,BLACK);\ +}\ +\ +type *sglib_##type##_find_member(type *t, type *elem) {\ + type *res;\ + SGLIB___BIN_TREE_FIND_MEMBER(type, t, elem, left, right, comparator, res);\ + return(res);\ +}\ +\ +int sglib_##type##_is_member(type *t, type *elem) {\ + int cmp;\ + while (t!=NULL) {\ + cmp = comparator(elem, t);\ + if (cmp < 0 || (cmp==0 && elemleft;\ + } else if (cmp > 0 || (cmp==0 && elem>t)) {\ + t = t->right;\ + } else {\ + assert(t == elem);\ + return(1);\ + }\ + }\ + return(0);\ +}\ +\ +int sglib_##type##_delete_if_member(type **tree, type *elem, type **memb) {\ + if ((*memb=sglib_##type##_find_member(*tree, elem))!=NULL) {\ + sglib_##type##_delete(tree, *memb);\ + return(1);\ + } else {\ + return(0);\ + }\ +}\ +int sglib_##type##_add_if_not_member(type **tree, type *elem, type **memb) {\ + if ((*memb=sglib_##type##_find_member(*tree, elem))==NULL) {\ + sglib_##type##_add(tree, elem);\ + return(1);\ + } else {\ + return(0);\ + }\ +}\ +int sglib_##type##_len(type *t) {\ + int n;\ + type *e;\ + n = 0;\ + SGLIB_BIN_TREE_MAP_ON_ELEMENTS(type, t, e, left, right, n++);\ + return(n);\ +}\ +\ +void sglib__##type##_it_compute_current_elem(struct sglib_##type##_iterator *it) {\ + int i,j,cmp;\ + type *s, *eqt;\ + int (*subcomparator)(type *, type *);\ + eqt = it->equalto;\ + subcomparator = it->subcomparator;\ + it->currentelem = NULL;\ + while(it->pathi > 0 && it->currentelem==NULL) {\ + i = it->pathi-1;\ + if (i >= 0) {\ + if (it->pass[i] >= 2) {\ + /* goto up */\ + it->pathi --;\ + } else {\ + if (it->pass[i] == 0) {\ + /* goto left */\ + s = it->path[i]->left;\ + } else {\ + /* goto right */\ + s = it->path[i]->right;\ + }\ + if (eqt != NULL) {\ + if (subcomparator == NULL) {\ + SGLIB___BIN_TREE_FIND_MEMBER(type, s, eqt, left, right, comparator, s);\ + } else {\ + SGLIB___BIN_TREE_FIND_MEMBER(type, s, eqt, left, right, subcomparator, s);\ + }\ + }\ + if (s != NULL) {\ + j = i+1;\ + it->path[j] = s;\ + it->pass[j] = 0;\ + it->pathi ++;\ + }\ + it->pass[i] ++;\ + }\ + }\ + if (it->pathi>0 && it->order == it->pass[it->pathi-1]) {\ + it->currentelem = it->path[it->pathi-1];\ + }\ + }\ +}\ +type *sglib__##type##_it_init(struct sglib_##type##_iterator *it, type *tree, int order, int (*subcomparator)(type *, type *), type *equalto) {\ + type *t;\ + assert(it!=NULL);\ + it->order = order;\ + it->equalto = equalto;\ + it->subcomparator = subcomparator;\ + if (equalto == NULL) { \ + t = tree;\ + } else {\ + if (subcomparator == NULL) {\ + SGLIB___BIN_TREE_FIND_MEMBER(type, tree, equalto, left, right, comparator, t);\ + } else {\ + SGLIB___BIN_TREE_FIND_MEMBER(type, tree, equalto, left, right, subcomparator, t);\ + }\ + }\ + if (t == NULL) {\ + it->pathi = 0;\ + it->currentelem = NULL;\ + } else {\ + it->pathi = 1;\ + it->pass[0] = 0;\ + it->path[0] = t;\ + if (order == 0) {\ + it->currentelem = t;\ + } else {\ + sglib__##type##_it_compute_current_elem(it);\ + }\ + }\ + return(it->currentelem);\ +}\ +type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *tree) {\ + return(sglib__##type##_it_init(it, tree, 2, NULL, NULL));\ +}\ +type *sglib_##type##_it_init_preorder(struct sglib_##type##_iterator *it, type *tree) {\ + return(sglib__##type##_it_init(it, tree, 0, NULL, NULL));\ +}\ +type *sglib_##type##_it_init_inorder(struct sglib_##type##_iterator *it, type *tree) {\ + return(sglib__##type##_it_init(it, tree, 1, NULL, NULL));\ +}\ +type *sglib_##type##_it_init_postorder(struct sglib_##type##_iterator *it, type *tree) {\ + return(sglib__##type##_it_init(it, tree, 2, NULL, NULL));\ +}\ +type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *tree, int (*subcomparator)(type *, type *), type *equalto) {\ + return(sglib__##type##_it_init(it, tree, 1, subcomparator, equalto));\ +}\ +type *sglib_##type##_it_current(struct sglib_##type##_iterator *it) {\ + return(it->currentelem);\ +}\ +type *sglib_##type##_it_next(struct sglib_##type##_iterator *it) {\ + sglib__##type##_it_compute_current_elem(it);\ + return(it->currentelem);\ +}\ +\ +static void sglib___##type##_consistency_check_recursive(type *t, int *pathdeep, int cdeep) {\ + if (t==NULL) {\ + if (*pathdeep < 0) *pathdeep = cdeep;\ + else assert(*pathdeep == cdeep);\ + } else {\ + if (t->left!=NULL) assert(comparator(t->left, t) <= 0);\ + if (t->right!=NULL) assert(comparator(t, t->right) <= 0);\ + if (SGLIB___GET_VALUE(t->bits) == RED) {\ + assert(t->left == NULL || SGLIB___GET_VALUE(t->left->bits)==BLACK);\ + assert(t->right == NULL || SGLIB___GET_VALUE(t->right->bits)==BLACK);\ + sglib___##type##_consistency_check_recursive(t->left, pathdeep, cdeep);\ + sglib___##type##_consistency_check_recursive(t->right, pathdeep, cdeep);\ + } else {\ + sglib___##type##_consistency_check_recursive(t->left, pathdeep, cdeep+1);\ + sglib___##type##_consistency_check_recursive(t->right, pathdeep, cdeep+1);\ + }\ + }\ +}\ +\ +void sglib___##type##_consistency_check(type *t) {\ + int pathDeep;\ + assert(t==NULL || SGLIB___GET_VALUE(t->bits) == BLACK);\ + pathDeep = -1;\ + sglib___##type##_consistency_check_recursive(t, &pathDeep, 0);\ +} + + +#define SGLIB_DEFINE_RBTREE_PROTOTYPES(type, left, right, colorbit, comparator) \ + struct sglib_##type##_iterator {\ + type *currentelem;\ + char pass[SGLIB_MAX_TREE_DEEP];\ + type *path[SGLIB_MAX_TREE_DEEP];\ + short int pathi;\ + short int order;\ + type *equalto;\ + int (*subcomparator)(type *, type *);\ + };\ + extern void sglib___##type##_consistency_check(type *t); \ + extern void sglib_##type##_add(type **tree, type *elem); \ + extern int sglib_##type##_add_if_not_member(type **tree, type *elem, type **memb); \ + extern void sglib_##type##_delete(type **tree, type *elem); \ + extern int sglib_##type##_delete_if_member(type **tree, type *elem, type **memb); \ + extern int sglib_##type##_is_member(type *t, type *elem); \ + extern type *sglib_##type##_find_member(type *t, type *elem); \ + extern int sglib_##type##_len(type *t); \ + extern type *sglib_##type##_it_init(struct sglib_##type##_iterator *it, type *tree); \ + extern type *sglib_##type##_it_init_preorder(struct sglib_##type##_iterator *it, type *tree); \ + extern type *sglib_##type##_it_init_inorder(struct sglib_##type##_iterator *it, type *tree); \ + extern type *sglib_##type##_it_init_postorder(struct sglib_##type##_iterator *it, type *tree); \ + extern type *sglib_##type##_it_init_on_equal(struct sglib_##type##_iterator *it, type *tree, int (*subcomparator)(type *, type *), type *equalto); \ + extern type *sglib_##type##_it_current(struct sglib_##type##_iterator *it); \ + extern type *sglib_##type##_it_next(struct sglib_##type##_iterator *it); \ + + +#define SGLIB_DEFINE_RBTREE_FUNCTIONS(type, left, right, colorbit, comparator) \ + SGLIB_DEFINE_RBTREE_FUNCTIONS_GENERAL(type, left, right, colorbit, comparator, 1, 0) + + + +/* ---------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------------- */ +/* - SUPPLEMENTARY DEFINITIONS - */ +/* ---------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------------- */ + + +#define SGLIB___GET_VALUE(x) (x) +#define SGLIB___SET_VALUE(x, value) {(x) = (value);} +#define SGLIB_ARRAY_ELEMENTS_EXCHANGER(type, a, i, j) {type _sgl_aee_tmp_; _sgl_aee_tmp_=(a)[(i)]; (a)[(i)]=(a)[(j)]; (a)[(j)]= _sgl_aee_tmp_;} + + +#define SGLIB_SAFE_NUMERIC_COMPARATOR(x, y) (((x)>(y)?1:((x)<(y)?-1:0))) +#define SGLIB_SAFE_REVERSE_NUMERIC_COMPARATOR(x, y) (((x)>(y)?-1:((x)<(y)?1:0))) +#define SGLIB_FAST_NUMERIC_COMPARATOR(x, y) ((int)((x) - (y))) +#define SGLIB_FAST_REVERSE_NUMERIC_COMPARATOR(x, y) ((int)((y) - (x))) +#define SGLIB_NUMERIC_COMPARATOR(x, y) SGLIB_SAFE_NUMERIC_COMPARATOR(x, y) +#define SGLIB_REVERSE_NUMERIC_COMPARATOR(x, y) SGLIB_SAFE_REVERSE_NUMERIC_COMPARATOR(x, y) + +#ifndef SGLIB_MAX_TREE_DEEP +#define SGLIB_MAX_TREE_DEEP 128 +#endif + +#ifndef SGLIB_HASH_TAB_SHIFT_CONSTANT +#define SGLIB_HASH_TAB_SHIFT_CONSTANT 16381 /* should be a prime */ +/* #define SGLIB_HASH_TAB_SHIFT_CONSTANT 536870912*/ /* for large tables :) */ +#endif + +#endif /* _SGLIB__h_ */ -- cgit v1.2.3 From c1f2b8f2d299d22be4ad3f2f176b6e106eeff6dc Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 18 May 2012 13:52:06 +0200 Subject: Lua: Move school_book[] to C --- lib/core/s_aux.lua | 65 ------ lib/mods/theme/core/s_aux.lua | 65 ------ lib/mods/theme/scpt/init.lua | 3 - lib/mods/theme/scpt/library.lua | 40 ---- lib/mods/theme/scpt/s_udun.lua | 39 ---- lib/mods/theme/scpt/spells.lua | 166 +--------------- lib/scpt/init.lua | 3 - lib/scpt/library.lua | 39 ---- lib/scpt/s_udun.lua | 39 ---- lib/scpt/spells.lua | 142 +------------- src/CMakeLists.txt | 1 + src/angband.h | 6 + src/cmd2.c | 2 +- src/cmd5.c | 45 +---- src/defines.h | 39 ++++ src/externs.h | 16 ++ src/q_library.c | 9 +- src/spells.pkg | 8 + src/spells3.c | 68 ++++++- src/spells4.c | 423 ++++++++++++++++++++++++++++++++++++++++ src/types.h | 17 ++ 21 files changed, 592 insertions(+), 643 deletions(-) delete mode 100644 lib/mods/theme/scpt/library.lua delete mode 100644 lib/scpt/library.lua diff --git a/lib/core/s_aux.lua b/lib/core/s_aux.lua index 6cdcbd82..20cf4964 100644 --- a/lib/core/s_aux.lua +++ b/lib/core/s_aux.lua @@ -81,7 +81,6 @@ __spell_spell = {} __spell_info = {} __spell_desc = {} __spell_school = {} -school_book = {} -- Find a spell by name function find_spell(name) @@ -262,44 +261,6 @@ function spell_school_name(s) return sch_str end --- Print the book and the spells -function print_book(book, spl, obj) - local x, y, index, sch, size, s - - x = 0 - y = 2 - size = 0 - - -- Hack if the book is 255 it is a random book - if book == 255 then - school_book[book] = {spl} - end - - -- Parse all spells - for index, s in school_book[book] do - local color = TERM_L_DARK - local lvl, na = get_level_school(s, 50, -50) - local xx, sch_str - - if is_ok_spell(s, obj) then - if get_mana(s) > get_power(s) then color = TERM_ORANGE - else color = TERM_L_GREEN end - end - - sch_str = spell_school_name(s) - - if na then - c_prt(color, format("%c) %-20s%-16s %3s %4s %3d%s %s", size + strbyte("a"), spell(s).name, sch_str, na, get_mana(s), spell_chance(s), "%", __spell_info[s]()), y, x) - else - c_prt(color, format("%c) %-20s%-16s %3d %4s %3d%s %s", size + strbyte("a"), spell(s).name, sch_str, lvl, get_mana(s), spell_chance(s), "%", __spell_info[s]()), y, x) - end - y = y + 1 - size = size + 1 - end - prt(format(" %-20s%-16s Level Cost Fail Info", "Name", "School"), 1, x) - return y -end - -- Output the desc when sued as a device function print_device_desc(s) local index, desc @@ -309,32 +270,6 @@ function print_device_desc(s) end end -function book_spells_num(book) - local size, index, sch - - size = 0 - - -- Hack if the book is 255 it is a random book - if book == 255 then - return 1 - end - - -- Parse all spells - for index, s in school_book[book] do - size = size + 1 - end - return size -end - -function spell_in_book(book, spell) - local i, s - - for i, s in school_book[book] do - if s == spell then return TRUE end - end - return FALSE -end - function check_affect(s, name, default) local s_ptr = __tmp_spells[s] local a diff --git a/lib/mods/theme/core/s_aux.lua b/lib/mods/theme/core/s_aux.lua index 6cdcbd82..20cf4964 100644 --- a/lib/mods/theme/core/s_aux.lua +++ b/lib/mods/theme/core/s_aux.lua @@ -81,7 +81,6 @@ __spell_spell = {} __spell_info = {} __spell_desc = {} __spell_school = {} -school_book = {} -- Find a spell by name function find_spell(name) @@ -262,44 +261,6 @@ function spell_school_name(s) return sch_str end --- Print the book and the spells -function print_book(book, spl, obj) - local x, y, index, sch, size, s - - x = 0 - y = 2 - size = 0 - - -- Hack if the book is 255 it is a random book - if book == 255 then - school_book[book] = {spl} - end - - -- Parse all spells - for index, s in school_book[book] do - local color = TERM_L_DARK - local lvl, na = get_level_school(s, 50, -50) - local xx, sch_str - - if is_ok_spell(s, obj) then - if get_mana(s) > get_power(s) then color = TERM_ORANGE - else color = TERM_L_GREEN end - end - - sch_str = spell_school_name(s) - - if na then - c_prt(color, format("%c) %-20s%-16s %3s %4s %3d%s %s", size + strbyte("a"), spell(s).name, sch_str, na, get_mana(s), spell_chance(s), "%", __spell_info[s]()), y, x) - else - c_prt(color, format("%c) %-20s%-16s %3d %4s %3d%s %s", size + strbyte("a"), spell(s).name, sch_str, lvl, get_mana(s), spell_chance(s), "%", __spell_info[s]()), y, x) - end - y = y + 1 - size = size + 1 - end - prt(format(" %-20s%-16s Level Cost Fail Info", "Name", "School"), 1, x) - return y -end - -- Output the desc when sued as a device function print_device_desc(s) local index, desc @@ -309,32 +270,6 @@ function print_device_desc(s) end end -function book_spells_num(book) - local size, index, sch - - size = 0 - - -- Hack if the book is 255 it is a random book - if book == 255 then - return 1 - end - - -- Parse all spells - for index, s in school_book[book] do - size = size + 1 - end - return size -end - -function spell_in_book(book, spell) - local i, s - - for i, s in school_book[book] do - if s == spell then return TRUE end - end - return FALSE -end - function check_affect(s, name, default) local s_ptr = __tmp_spells[s] local a diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index 2a24ecff..a65db8ac 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -20,9 +20,6 @@ tome_dofile("spells.lua") -- Post-spell creation initialization initialize_bookable_spells() --- Add some quests -tome_dofile("library.lua") - -- Add joke stuff tome_dofile("drunk.lua") tome_dofile("joke.lua") diff --git a/lib/mods/theme/scpt/library.lua b/lib/mods/theme/scpt/library.lua deleted file mode 100644 index 35f95094..00000000 --- a/lib/mods/theme/scpt/library.lua +++ /dev/null @@ -1,40 +0,0 @@ --- Library quest in Minas Anor - --- Partially based on Fireproofing quest - -library_quest = {} - --- Book creation helpers --- Print a spell (taken from s_aux) -function library_quest.print_spell(color, y, spl) - local x, index, sch, size, s - - x = 0 - size = 0 - book = 255 - obj = nil - - -- Hack if the book is 255 it is a random book - if book == 255 then - school_book[book] = {spl} - end - - -- Parse all spells - for index, s in school_book[book] do - local lvl, na = get_level_school(s, 50, -50) - local xx, sch_str - - sch_str = spell_school_name(s) - - if s == spl then - if na then - c_prt(color, format("%-20s%-16s %3s %4s %3d%s %s", spell(s).name, sch_str, na, get_mana(s), spell_chance(s), "%", __spell_info[s]()), y, x) - else - c_prt(color, format("%-20s%-16s %3d %4s %3d%s %s", spell(s).name, sch_str, lvl, get_mana(s), spell_chance(s), "%", __spell_info[s]()), y, x) - end - y = y + 1 - size = size + 1 - end - end - return y -end diff --git a/lib/mods/theme/scpt/s_udun.lua b/lib/mods/theme/scpt/s_udun.lua index 3ddfeb14..bb12ac7f 100644 --- a/lib/mods/theme/scpt/s_udun.lua +++ b/lib/mods/theme/scpt/s_udun.lua @@ -72,42 +72,3 @@ FLAMEOFUDUN = add_spell "Turns you into a powerful Balrog", } } - - --- Return the number of Udun/Melkor spells in a given book -function udun_in_book(sval, pval) - local i, y, index, sch, s - - i = 0 - - -- Hack if the book is 255 it is a random book - if sval == 255 then - school_book[sval] = {pval} - end - -- Parse all spells - for index, s in school_book[sval] do - for index, sch in __spell_school[s] do - if sch == SCHOOL_UDUN then i = i + 1 end - if sch == SCHOOL_MELKOR then i = i + 1 end - end - end - return i -end - --- Return the total level of spells -function levels_in_book(sval, pval) - local i, y, index, sch, s - - i = 0 - - -- Hack if the book is 255 it is a random book - if sval == 255 then - school_book[sval] = {pval} - end - - -- Parse all spells - for index, s in school_book[sval] do - i = i + __tmp_spells[s].level - end - return i -end diff --git a/lib/mods/theme/scpt/spells.lua b/lib/mods/theme/scpt/spells.lua index 36829356..eedd59ad 100644 --- a/lib/mods/theme/scpt/spells.lua +++ b/lib/mods/theme/scpt/spells.lua @@ -415,167 +415,5 @@ tome_dofile("s_stick.lua") -- Musics tome_dofile("s_music.lua") --- List of spellbooks - --- Create the crystal of mana -school_book[0] = { - MANATHRUST, DELCURSES, RESISTS, MANASHIELD, -} - --- The book of the eternal flame -school_book[1] = { - GLOBELIGHT, FIREGOLEM, FIREFLASH, FIREWALL, FIERYAURA, -} - --- The book of the blowing winds -school_book[2] = { - NOXIOUSCLOUD, POISONBLOOD, INVISIBILITY, STERILIZE, AIRWINGS, THUNDERSTORM, -} - --- The book of the impenetrable earth -school_book[3] = { - STONESKIN, DIG, STONEPRISON, SHAKE, STRIKE, -} - --- The book of the unstopable wave -school_book[4] = { - GEYSER, VAPOR, ENTPOTION, TIDALWAVE, ICESTORM -} - --- Create the book of translocation -school_book[5] = { - BLINK, DISARM, TELEPORT, TELEAWAY, RECALL, PROBABILITY_TRAVEL, -} - --- Create the book of the tree -school_book[6] = { - GROWTREE, HEALING, RECOVERY, REGENERATION, SUMMONANNIMAL, GROW_ATHELAS, -} - --- Create the book of Knowledge -school_book[7] = { - SENSEMONSTERS, SENSEHIDDEN, REVEALWAYS, IDENTIFY, VISION, STARIDENTIFY, -} - --- Create the book of the Time -school_book[8] = { - MAGELOCK, SLOWMONSTER, ESSENCESPEED, BANISHMENT, -} - --- Create the book of meta spells -school_book[9] = { - RECHARGE, DISPERSEMAGIC, SPELLBINDER, TRACKER, INERTIA_CONTROL, -} - --- Create the book of the mind -school_book[10] = { - CHARM, CONFUSE, ARMOROFFEAR, STUN, -} - --- Create the book of hellflame -school_book[11] = { - DRAIN, GENOCIDE, WRAITHFORM, FLAMEOFUDUN, -} - --- Create the book of eru -school_book[20] = { - ERU_SEE, ERU_LISTEN, ERU_UNDERSTAND, ERU_PROT, -} - --- Create the book of manwe -school_book[21] = { - MANWE_BLESS, MANWE_SHIELD, MANWE_CALL, MANWE_AVATAR, -} - --- Create the book of tulkas -school_book[22] = { - TULKAS_AIM, TULKAS_SPIN, TULKAS_WAVE, -} - --- Create the book of melkor -school_book[23] = { - MELKOR_CURSE, MELKOR_CORPSE_EXPLOSION, MELKOR_MIND_STEAL, -} - --- Create the book of yavanna -school_book[24] = { - YAVANNA_CHARM_ANIMAL, YAVANNA_GROW_GRASS, YAVANNA_TREE_ROOTS, YAVANNA_WATER_BITE, YAVANNA_UPROOT, -} - --- Create the book of beginner's cantrip -school_book[50] = { - MANATHRUST, GLOBELIGHT, ENTPOTION, BLINK, SENSEMONSTERS, SENSEHIDDEN, -} - --- Create the book of teleporatation -school_book[51] = { - BLINK, TELEPORT, TELEAWAY -} - --- Create the book of summoning -school_book[52] = { - FIREGOLEM, SUMMONANNIMAL -} - - --- Create the Armageddon Demonblade -school_book[55] = { - DEMON_BLADE, DEMON_MADNESS, DEMON_FIELD, -} - --- Create the Shield Demonblade -school_book[56] = { - DOOM_SHIELD, DEMON_CLOAK, UNHOLY_WORD, -} - --- Create the Control Demonblade -school_book[57] = { - DEMON_SUMMON, DISCHARGE_MINION, CONTROL_DEMON, -} - --- Create the Drums -school_book[58] = { - MUSIC_STOP, MUSIC_HOLD, MUSIC_CONF, MUSIC_STUN, -} - --- Create the Harps -school_book[59] = { - MUSIC_STOP, MUSIC_LITE, MUSIC_HERO, MUSIC_HEAL, MUSIC_TIME, MUSIC_MIND, -} - --- Create the Horns -school_book[60] = { - MUSIC_STOP, MUSIC_BLOW, MUSIC_WIND, MUSIC_YLMIR, MUSIC_AMBARKANTA, -} - --- Book of the Player, filled in by the Library Quest -school_book[61] = { } - --- Geomancy spells, not a real book -school_book[62] = { - CALL_THE_ELEMENTS, CHANNEL_ELEMENTS, ELEMENTAL_WAVE, VAPORIZE, GEOLYSIS, DRIPPING_TREAD, GROW_BARRIER, ELEMENTAL_MINION -} - --- Aule book [63] -school_book[BOOK_AULE] = -{ - AULE_FIREBRAND, AULE_ENCHANT_WEAPON, AULE_ENCHANT_ARMOUR, AULE_CHILD, -} - --- Varda book [64] -school_book[BOOK_VARDA] = -{ - VARDA_LIGHT_VALINOR, VARDA_CALL_ALMAREN, VARDA_EVENSTAR, VARDA_STARKINDLER, -} - --- Ulmo book [65] -school_book[BOOK_ULMO] = -{ - ULMO_BELEGAER, ULMO_DRAUGHT_ULMONAN, ULMO_CALL_ULUMURI, ULMO_WRATH, -} - --- Mandos book [66] -school_book[BOOK_MANDOS] = -{ - MANDOS_TEARS_LUTHIEN, MANDOS_SPIRIT_FEANTURI, MANDOS_TALE_DOOM, MANDOS_CALL_HALLS -} \ No newline at end of file +-- Initialize spellbooks +init_school_books() diff --git a/lib/scpt/init.lua b/lib/scpt/init.lua index 655c4bd7..55a6ce63 100644 --- a/lib/scpt/init.lua +++ b/lib/scpt/init.lua @@ -20,9 +20,6 @@ tome_dofile("spells.lua") -- Post-spell creation initialization initialize_bookable_spells() --- Add some quests -tome_dofile("library.lua") - -- Add joke stuff tome_dofile("drunk.lua") tome_dofile("joke.lua") diff --git a/lib/scpt/library.lua b/lib/scpt/library.lua deleted file mode 100644 index 7e25904e..00000000 --- a/lib/scpt/library.lua +++ /dev/null @@ -1,39 +0,0 @@ --- Library quest in Minas Anor - --- Partially based on Fireproofing quest - -library_quest = {} - --- Print a spell (taken from s_aux) -function library_quest.print_spell(color, y, spl) - local x, index, sch, size, s - - x = 0 - size = 0 - book = 255 - obj = nil - - -- Hack if the book is 255 it is a random book - if book == 255 then - school_book[book] = {spl} - end - - -- Parse all spells - for index, s in school_book[book] do - local lvl, na = get_level_school(s, 50, -50) - local xx, sch_str - - sch_str = spell_school_name(s) - - if s == spl then - if na then - c_prt(color, format("%-20s%-16s %3s %4s %3d%s %s", spell(s).name, sch_str, na, get_mana(s), spell_chance(s), "%", __spell_info[s]()), y, x) - else - c_prt(color, format("%-20s%-16s %3d %4s %3d%s %s", spell(s).name, sch_str, lvl, get_mana(s), spell_chance(s), "%", __spell_info[s]()), y, x) - end - y = y + 1 - size = size + 1 - end - end - return y -end diff --git a/lib/scpt/s_udun.lua b/lib/scpt/s_udun.lua index 3ddfeb14..bb12ac7f 100644 --- a/lib/scpt/s_udun.lua +++ b/lib/scpt/s_udun.lua @@ -72,42 +72,3 @@ FLAMEOFUDUN = add_spell "Turns you into a powerful Balrog", } } - - --- Return the number of Udun/Melkor spells in a given book -function udun_in_book(sval, pval) - local i, y, index, sch, s - - i = 0 - - -- Hack if the book is 255 it is a random book - if sval == 255 then - school_book[sval] = {pval} - end - -- Parse all spells - for index, s in school_book[sval] do - for index, sch in __spell_school[s] do - if sch == SCHOOL_UDUN then i = i + 1 end - if sch == SCHOOL_MELKOR then i = i + 1 end - end - end - return i -end - --- Return the total level of spells -function levels_in_book(sval, pval) - local i, y, index, sch, s - - i = 0 - - -- Hack if the book is 255 it is a random book - if sval == 255 then - school_book[sval] = {pval} - end - - -- Parse all spells - for index, s in school_book[sval] do - i = i + __tmp_spells[s].level - end - return i -end diff --git a/lib/scpt/spells.lua b/lib/scpt/spells.lua index 24b4f02b..4bd5d7ea 100644 --- a/lib/scpt/spells.lua +++ b/lib/scpt/spells.lua @@ -317,143 +317,5 @@ tome_dofile("s_stick.lua") -- Musics tome_dofile("s_music.lua") --- List of spellbooks - --- Create the crystal of mana -school_book[0] = { - MANATHRUST, DELCURSES, RESISTS, MANASHIELD, -} - --- The book of the eternal flame -school_book[1] = { - GLOBELIGHT, FIREGOLEM, FIREFLASH, FIREWALL, FIERYAURA, -} - --- The book of the blowing winds -school_book[2] = { - NOXIOUSCLOUD, POISONBLOOD, INVISIBILITY, STERILIZE, AIRWINGS, THUNDERSTORM, -} - --- The book of the impenetrable earth -school_book[3] = { - STONESKIN, DIG, STONEPRISON, SHAKE, STRIKE, -} - --- The book of the unstopable wave -school_book[4] = { - GEYSER, VAPOR, ENTPOTION, TIDALWAVE, ICESTORM -} - --- Create the book of translocation -school_book[5] = { - BLINK, DISARM, TELEPORT, TELEAWAY, RECALL, PROBABILITY_TRAVEL, -} - --- Create the book of the tree -school_book[6] = { - GROWTREE, HEALING, RECOVERY, REGENERATION, SUMMONANNIMAL, -} - --- Create the book of Knowledge -school_book[7] = { - SENSEMONSTERS, SENSEHIDDEN, REVEALWAYS, IDENTIFY, VISION, STARIDENTIFY, -} - --- Create the book of the Time -school_book[8] = { - MAGELOCK, SLOWMONSTER, ESSENCESPEED, BANISHMENT, -} - --- Create the book of meta spells -school_book[9] = { - RECHARGE, DISPERSEMAGIC, SPELLBINDER, TRACKER, INERTIA_CONTROL, -} - --- Create the book of the mind -school_book[10] = { - CHARM, CONFUSE, ARMOROFFEAR, STUN, -} - --- Create the book of hellflame -school_book[11] = { - DRAIN, GENOCIDE, WRAITHFORM, FLAMEOFUDUN, -} - --- Create the book of eru -school_book[20] = { - ERU_SEE, ERU_LISTEN, ERU_UNDERSTAND, ERU_PROT, -} - --- Create the book of manwe -school_book[21] = { - MANWE_BLESS, MANWE_SHIELD, MANWE_CALL, MANWE_AVATAR, -} - --- Create the book of tulkas -school_book[22] = { - TULKAS_AIM, TULKAS_SPIN, TULKAS_WAVE, -} - --- Create the book of melkor -school_book[23] = { - MELKOR_CURSE, MELKOR_CORPSE_EXPLOSION, MELKOR_MIND_STEAL, -} - --- Create the book of yavanna -school_book[24] = { - YAVANNA_CHARM_ANIMAL, YAVANNA_GROW_GRASS, YAVANNA_TREE_ROOTS, YAVANNA_WATER_BITE, YAVANNA_UPROOT, -} - --- Create the book of beginner's cantrip -school_book[50] = { - MANATHRUST, GLOBELIGHT, ENTPOTION, BLINK, SENSEMONSTERS, SENSEHIDDEN, -} - --- Create the book of teleporatation -school_book[51] = { - BLINK, TELEPORT, TELEAWAY -} - --- Create the book of summoning -school_book[52] = { - FIREGOLEM, SUMMONANNIMAL -} - - --- Create the Armageddon Demonblade -school_book[55] = { - DEMON_BLADE, DEMON_MADNESS, DEMON_FIELD, -} - --- Create the Shield Demonblade -school_book[56] = { - DOOM_SHIELD, DEMON_CLOAK, UNHOLY_WORD, -} - --- Create the Control Demonblade -school_book[57] = { - DEMON_SUMMON, DISCHARGE_MINION, CONTROL_DEMON, -} - --- Create the Drums -school_book[58] = { - MUSIC_STOP, MUSIC_HOLD, MUSIC_CONF, MUSIC_STUN, -} - --- Create the Harps -school_book[59] = { - MUSIC_STOP, MUSIC_LITE, MUSIC_HERO, MUSIC_HEAL, MUSIC_TIME, MUSIC_MIND, -} - --- Create the Horns -school_book[60] = { - MUSIC_STOP, MUSIC_BLOW, MUSIC_WIND, MUSIC_YLMIR, MUSIC_AMBARKANTA, -} - --- Book of the Player, filled in by the Library Quest -school_book[61] = { } - --- Geomancy spells, not a real book -school_book[62] = { - CALL_THE_ELEMENTS, CHANNEL_ELEMENTS, ELEMENTAL_WAVE, VAPORIZE, GEOLYSIS, DRIPPING_TREAD, GROW_BARRIER, ELEMENTAL_MINION -} +-- Initialize spellbooks +init_school_books() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b286a477..3a640e74 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -62,6 +62,7 @@ TOLUA_FILE(dungeon w_dun.c) # tome executable INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/lua) ADD_EXECUTABLE(tome ${EXECUTABLE_OPTIONS} ${SRCS}) TARGET_LINK_LIBRARIES(tome lua ${LIBS}) diff --git a/src/angband.h b/src/angband.h index cac38122..93e3b76e 100644 --- a/src/angband.h +++ b/src/angband.h @@ -44,6 +44,12 @@ extern "C" { #include "config.h" +/* + * SGLIB + */ +#include "sglib.h" + + /* * Now, include the define's, the type's, and the extern's */ diff --git a/src/cmd2.c b/src/cmd2.c index 828cbc35..a2dcfa0a 100644 --- a/src/cmd2.c +++ b/src/cmd2.c @@ -4696,7 +4696,7 @@ void do_cmd_sacrifice(void) /* In books it depends of the spell levels*/ if (o_ptr->tval == TV_BOOK) { - int x = exec_lua(format("return levels_in_book(%d, %d)", o_ptr->sval, o_ptr->pval)); + int x = levels_in_book(o_ptr->sval, o_ptr->pval); inc_piety(GOD_MELKOR, 2 * x); } diff --git a/src/cmd5.c b/src/cmd5.c index df429a8a..5f0201fc 100644 --- a/src/cmd5.c +++ b/src/cmd5.c @@ -15,22 +15,9 @@ #include "lua/lua.h" #include "tolua.h" -extern lua_State *L; - -static int spell_x(int sval, int pval, int i) -{ - if (sval == 255) - { - return pval; - } - else - { - char buf[128]; - sprintf(buf, "school_book[%d][%d]", sval, i+1); - return get_lua_int(buf); - } -} +#include +extern lua_State *L; /* Maximum number of tries for teleporting */ #define MAX_TRIES 300 @@ -2148,25 +2135,13 @@ bool_ get_item_hook_find_spell(int *item) } } /* A random book ? */ - else if ((o_ptr->sval == 255) && (o_ptr->pval == spell)) + else if (school_book_contains_spell(o_ptr->sval, spell)) { *item = i; hack_force_spell = spell; hack_force_spell_obj = o_ptr; return TRUE; } - /* A normal book */ - else if (o_ptr->sval != 255) - { - sprintf(buf2, "return spell_in_book(%d, %d)", o_ptr->sval, spell); - if (exec_lua(buf2)) - { - *item = i; - hack_force_spell = spell; - hack_force_spell_obj = o_ptr; - return TRUE; - } - } } return FALSE; } @@ -2258,7 +2233,7 @@ s32b get_school_spell(cptr do_what, cptr check_fct, s16b force_book) if (hack_force_spell == -1) { - num = exec_lua(format("return book_spells_num(%d)", sval)); + num = school_book_length(sval); /* Build a prompt (accept all spells) */ strnfmt(out_val, 78, "(Spells %c-%c, Descs %c-%c, *=List, ESC=exit) %^s which spell? ", @@ -2281,7 +2256,7 @@ s32b get_school_spell(cptr do_what, cptr check_fct, s16b force_book) Term_save(); /* Display a list of spells */ - call_lua("print_book", "(d,d,O)", "d", sval, pval, o_ptr, &where); + where = print_book(sval, pval, o_ptr); } /* Hide the list */ @@ -2340,7 +2315,7 @@ s32b get_school_spell(cptr do_what, cptr check_fct, s16b force_book) } /* Display a list of spells */ - call_lua("print_book", "(d,d,O)", "d", sval, pval, o_ptr, &where); + where = print_book(sval, pval, o_ptr); print_spell_desc(spell_x(sval, pval, i), where); } else @@ -2453,7 +2428,7 @@ void browse_school_spell(int book, int pval, object_type *o_ptr) window_stuff(); } - num = exec_lua(format("return book_spells_num(%d)", book)); + num = school_book_length(book); /* Build a prompt (accept all spells) */ strnfmt(out_val, 78, "(Spells %c-%c, ESC=exit) cast which spell? ", @@ -2464,13 +2439,13 @@ void browse_school_spell(int book, int pval, object_type *o_ptr) Term_save(); /* Display a list of spells */ - call_lua("print_book", "(d,d,O)", "d", book, pval, o_ptr, &where); + where = print_book(book, pval, o_ptr); /* Get a spell from the user */ while (get_com(out_val, &choice)) { /* Display a list of spells */ - call_lua("print_book", "(d,d,O)", "d", book, pval, o_ptr, &where); + where = print_book(book, pval, o_ptr); /* Note verify */ ask = (isupper(choice)); @@ -2492,7 +2467,7 @@ void browse_school_spell(int book, int pval, object_type *o_ptr) Term_load(); /* Display a list of spells */ - call_lua("print_book", "(d,d,O)", "d", book, pval, o_ptr, &where); + where = print_book(book, pval, o_ptr); print_spell_desc(spell_x(book, pval, i), where); } diff --git a/src/defines.h b/src/defines.h index b4a02a11..7457134a 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4718,3 +4718,42 @@ #define AB_FAR_REACHING 8 #define AB_TRAPPING 9 #define AB_UNDEAD_FORM 10 + +/** + * Spell school books/tomes + */ +#define TOME_MANA 0 +#define TOME_FIRE 1 +#define TOME_WINDS 2 +#define TOME_EARTH 3 +#define TOME_WATER 4 +#define TOME_TRANSLOCATION 5 +#define TOME_NATURE 6 +#define TOME_KNOWLEDGE 7 +#define TOME_TIME 8 +#define TOME_META 9 +#define TOME_MIND 10 +#define TOME_HELLFLAME 11 +#define TOME_ERU 20 +#define TOME_MANWE 21 +#define TOME_TULKAS 22 +#define TOME_MELKOR 23 +#define TOME_YAVANNA 24 +#define BOOK_CANTRIPS 50 +#define BOOK_TELEPORTATION 51 +#define BOOK_SUMMONING 52 +#define BOOK_DEMON_SWORD 55 +#define BOOK_DEMON_SHIELD 56 +#define BOOK_DEMON_HELM 57 +#define BOOK_DRUMS 58 +#define BOOK_HARPS 59 +#define BOOK_HORNS 60 +#define BOOK_PLAYER 61 +#define BOOK_GEOMANCY 62 +#define BOOK_AULE 63 +#define BOOK_VARDA 64 +#define BOOK_ULMO 65 +#define BOOK_MANDOS 66 +#define BOOK_RANDOM 255 + +#define SCHOOL_BOOKS_SIZE 256 diff --git a/src/externs.h b/src/externs.h index 798ab111..d933b2be 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1673,6 +1673,7 @@ extern s32b WRAITHFORM; extern s32b FLAMEOFUDUN; int udun_in_book(s32b sval, s32b pval); +int levels_in_book(s32b sval, s32b pval); bool_ *udun_drain(); char *udun_drain_info(); @@ -1899,7 +1900,22 @@ bool_ *varda_star_kindler_spell(); char *varda_star_kindler_info(); /* spells4.c */ + +SGLIB_DEFINE_LIST_PROTOTYPES(spell_idx_list, compare_spell_idx, next); + +extern s32b SCHOOL_UDUN; +extern s32b SCHOOL_MELKOR; + void print_spell_desc(int s, int y); +void init_school_books(); +school_book_type *school_books_at(int sval); +void school_book_add_spell(school_book_type *school_book, s32b spell_idx); +void random_book_setup(s16b sval, s32b spell_idx); +int print_spell(cptr label, byte color, int y, s32b s); +int print_book(s16b sval, s32b pval, object_type *obj); +int school_book_length(int sval); +int spell_x(int sval, int pval, int i); +bool_ school_book_contains_spell(int sval, s32b spell_idx); /* randart.c */ extern int get_activation_power(void); diff --git a/src/q_library.c b/src/q_library.c index 0c4ad5e3..bbbcae4c 100644 --- a/src/q_library.c +++ b/src/q_library.c @@ -136,16 +136,13 @@ static bool_ library_quest_book_contains_spell(int spell) return FALSE; } -static int library_quest_print_spell(int color, int row, int spell) { - return exec_lua(format("library_quest.print_spell(%d,%d,%d)", color, row, spell)); -} - static void quest_library_finalize_book() { int i = 0; for (i = 1; i <= 3; i++) { - exec_lua(format("school_book[61][%d] = %d", i, library_quest_book_get_slot(i))); + school_book_type *school_book = school_books_at(BOOK_PLAYER); + school_book_add_spell(school_book, library_quest_book_get_slot(i)); } } @@ -209,7 +206,7 @@ static void library_quest_print_spells(int first, int current) color = TERM_ORANGE; } - library_quest_print_spell(color, row, spell); + print_spell(NULL, color, row, spell); if (row == height - 1) { return; diff --git a/src/spells.pkg b/src/spells.pkg index 6f284a9d..18620ccd 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2900,3 +2900,11 @@ bool_ *varda_evenstar_spell(); char *varda_evenstar_info(); bool_ *varda_star_kindler_spell(); char *varda_star_kindler_info(); + +/** + * spells4.c + */ +void init_school_books(); + +extern s32b SCHOOL_UDUN; +extern s32b SCHOOL_MELKOR; diff --git a/src/spells3.c b/src/spells3.c index 119e128f..b7019e0f 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -2911,10 +2911,70 @@ char *tulkas_whirlwind_info() /* Return the number of Udun/Melkor spells in a given book */ int udun_in_book(s32b sval, s32b pval) { - char buf[128]; - sprintf(buf, "return udun_in_book(" FMTs32b "," FMTs32b ")", - sval, pval); - return exec_lua(buf); + int count = 0; + school_book_type *school_book; + spell_idx_list *spell_idx = NULL; + struct sglib_spell_idx_list_iterator it; + + random_book_setup(sval, pval); + + /* Get the school book */ + school_book = school_books_at(sval); + + /* Go through spells */ + for (spell_idx = sglib_spell_idx_list_it_init(&it, school_book->spell_idx_list); + spell_idx != NULL; + spell_idx = sglib_spell_idx_list_it_next(&it)) + { + int j; + int n; + char buf[128]; + + sprintf(buf, "__spell_school[" FMTs32b "+1]", spell_idx->i); + n = get_lua_list_size(buf); + + for (j = 0; j < n; j++) + { + int sch; + sprintf(buf, "__spell_school[" FMTs32b "][%d+1]", spell_idx->i, j); + sch = get_lua_int(buf); + + if ((sch == SCHOOL_UDUN) || + (sch == SCHOOL_MELKOR)) + { + count++; + } + } + } + + return count; +} + +int levels_in_book(s32b sval, s32b pval) +{ + int levels = 0; + school_book_type *school_book; + spell_idx_list *spell_idx = NULL; + struct sglib_spell_idx_list_iterator it; + + random_book_setup(sval, pval); + + /* Get the school book */ + school_book = school_books_at(sval); + + /* Parse all spells */ + for (spell_idx = sglib_spell_idx_list_it_init(&it, school_book->spell_idx_list); + spell_idx != NULL; + spell_idx = sglib_spell_idx_list_it_next(&it)) + { + char buf[128]; + s32b s = spell_idx->i; + + sprintf(buf, "__tmp_spells[" FMTs32b "].level", s); + levels += get_lua_int(buf); + } + + return levels; } static bool_ udun_object_is_drainable(object_type *o_ptr) diff --git a/src/spells4.c b/src/spells4.c index 7f59d186..0429e1c1 100644 --- a/src/spells4.c +++ b/src/spells4.c @@ -2,6 +2,18 @@ #include +school_book_type school_books[SCHOOL_BOOKS_SIZE]; + +s32b SCHOOL_UDUN; +s32b SCHOOL_MELKOR; + +static int compare_spell_idx(spell_idx_list *a, spell_idx_list *b) +{ + return SGLIB_NUMERIC_COMPARATOR(a->i, b->i); +} + +SGLIB_DEFINE_LIST_FUNCTIONS(spell_idx_list, compare_spell_idx, next); + static bool_ uses_piety_to_cast(int s) { char buf[128]; @@ -60,3 +72,414 @@ void print_spell_desc(int s, int y) y++; } } + +school_book_type *school_books_at(int i) +{ + assert(i >= 0); + assert(i < SCHOOL_BOOKS_SIZE); + return &school_books[i]; +} + +static void school_book_init(school_book_type *school_book) +{ + school_book->spell_idx_list = NULL; +} + +static void spell_idx_init(spell_idx_list *p, s32b spell_idx) +{ + assert(p != NULL); + + p->i = spell_idx; + p->next = NULL; +} + +static spell_idx_list *new_spell_idx(void *ctx, s32b spell_idx) +{ + spell_idx_list *e = malloc(sizeof(spell_idx_list)); + spell_idx_init(e, spell_idx); + return e; +} + +void school_book_add_spell(school_book_type *school_book, s32b spell_idx) +{ + spell_idx_list *e; + + assert(school_book != NULL); + + e = new_spell_idx(school_book, spell_idx); + sglib_spell_idx_list_add(&school_book->spell_idx_list, e); +} + +int school_book_length(int sval) +{ + school_book_type *school_book = school_books_at(sval); + + if (sval == BOOK_RANDOM) + { + return 1; + } + + /* Parse all spells */ + return sglib_spell_idx_list_len(school_book->spell_idx_list); +} + +int spell_x(int sval, int pval, int i) +{ + assert(i >= 0); + + if (sval == BOOK_RANDOM) + { + return pval; + } + else + { + school_book_type *school_book; + spell_idx_list *spell_idx = NULL; + struct sglib_spell_idx_list_iterator it; + + school_book = school_books_at(sval); + + for (spell_idx = sglib_spell_idx_list_it_init(&it, school_book->spell_idx_list); + (spell_idx != NULL) && (i > 0); + spell_idx = sglib_spell_idx_list_it_next(&it)) + { + i--; + } + + assert(spell_idx != NULL); /* Went off the end of the list? */ + + return spell_idx->i; + } +} + +bool_ school_book_contains_spell(int sval, s32b spell_idx) +{ + school_book_type *school_book = NULL; + spell_idx_list e; + + random_book_setup(sval, spell_idx); + + school_book = school_books_at(sval); + + spell_idx_init(&e, spell_idx); + return NULL != sglib_spell_idx_list_find_member(school_book->spell_idx_list, &e); +} + +void push_spell(int book_idx, s32b spell_idx) +{ + school_book_type *school_book = school_books_at(book_idx); + assert(school_book != NULL); + school_book_add_spell(school_book, spell_idx); +} + +void init_school_books() +{ + int i; + + /* Initialize the new school books */ + for (i = 0; ispell_idx_list != NULL); + school_book->spell_idx_list->i = spell_idx; + } +} + +static cptr spell_school_name(s32b s) +{ + return string_exec_lua(format("return spell_school_name(%d)", s)); +} + +int print_spell(cptr label_, byte color, int y, s32b s) +{ + s32b level; + bool_ na; + cptr sch_str = spell_school_name(s); + cptr spell_info = get_spell_info(s); + cptr label = (label_ == NULL) ? "" : label_; + char level_str[8] = "n/a"; + char buf[128]; + + get_level_school(s, 50, -50, &level, &na); + + if (!na) + { + sprintf(level_str, "%3d", level); + } + + sprintf(buf, "%s%-20s%-16s %s %4d %3d%% %s", + label, + school_spells[s].name, + sch_str, + level_str, + get_mana(s), + spell_chance(s), + spell_info); + c_prt(color, buf, y, 0); + + return y + 1; +} + +int print_book(s16b sval, s32b pval, object_type *obj) +{ + int y = 2; + int i; + school_book_type *school_book; + spell_idx_list *spell_idx; + struct sglib_spell_idx_list_iterator it; + + random_book_setup(sval, pval); + + school_book = school_books_at(sval); + + /* Parse all spells */ + i = 0; + for (spell_idx = sglib_spell_idx_list_it_init(&it, school_book->spell_idx_list); + spell_idx != NULL; + spell_idx = sglib_spell_idx_list_it_next(&it)) + { + s32b s = spell_idx->i; + byte color = TERM_L_DARK; + int is_ok; + char label[8]; + + call_lua("is_ok_spell", "(d,O)", "d", s, obj, &is_ok); + if (is_ok) + { + color = (get_mana(s) > get_power(s)) ? TERM_ORANGE : TERM_L_GREEN; + } + + sprintf(label, "%c) ", 'a' + i); + + y = print_spell(label, color, y, s); + i++; + } + + prt(format(" %-20s%-16s Level Cost Fail Info", "Name", "School"), 1, 0); + return y; +} diff --git a/src/types.h b/src/types.h index 8d12fa68..ea8ca019 100644 --- a/src/types.h +++ b/src/types.h @@ -2468,6 +2468,23 @@ struct school_type s16b skill; /* Skill used for that school */ }; +/* + * Spell index list. + */ +typedef struct spell_idx_list spell_idx_list; +struct spell_idx_list { + s32b i; /* Spell index */ + spell_idx_list *next; /* for list */ +}; + +/* + * School book. + */ +typedef struct school_book_type school_book_type; +struct school_book_type { + spell_idx_list *spell_idx_list; +}; + /* * Desc for GF_FOO */ -- cgit v1.2.3 From 38ab9bd955e7516cdc0279dcdcf461f975fde3ef Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 18 May 2012 06:20:20 +0200 Subject: Lua: Move cast_school_spell() to C --- lib/core/s_aux.lua | 97 ---------------------------------- lib/mods/theme/core/s_aux.lua | 97 ---------------------------------- lib/mods/theme/scpt/mkeys.lua | 2 +- lib/scpt/mkeys.lua | 2 +- src/cmd5.c | 2 +- src/externs.h | 1 + src/lua_bind.c | 4 -- src/object.pkg | 1 - src/object1.c | 5 +- src/spells.pkg | 27 +--------- src/spells1.c | 2 +- src/spells3.c | 6 +-- src/spells4.c | 120 ++++++++++++++++++++++++++++++++++++++++++ 13 files changed, 131 insertions(+), 235 deletions(-) diff --git a/lib/core/s_aux.lua b/lib/core/s_aux.lua index 20cf4964..76f01637 100644 --- a/lib/core/s_aux.lua +++ b/lib/core/s_aux.lua @@ -218,33 +218,6 @@ function get_mana(s) return spell(s).mana + get_level(s, spell(s).mana_max - spell(s).mana, 0) end --- Return the amount of power(mana, piety, whatever) for the spell -function get_power(s) - if check_affect(s, "piety", FALSE) then - return player.grace - else - return player.csp - end -end - --- Return the amount of power(mana, piety, whatever) for the spell -function get_power_name(s) - if check_affect(s, "piety", FALSE) then - return "piety" - else - return "mana" - end -end - --- Changes the amount of power(mana, piety, whatever) for the spell -function adjust_power(s, x) - if check_affect(s, "piety", FALSE) then - inc_piety(GOD_ALL, x) - else - increase_mana(x) - end -end - -- Get spell school name(s) as a /-separated string. function spell_school_name(s) local xx, sch_str @@ -292,76 +265,6 @@ function get_spell_stat(s) else return __tmp_spells[s].stat end end -function cast_school_spell(s, s_ptr, no_cost) - local use = FALSE - - -- No magic - if (player.antimagic > 0) then - msg_print("Your anti-magic field disrupts any magic attempts.") - return - end - - -- No magic - if (player.anti_magic == TRUE) then - msg_print("Your anti-magic shell disrupts any magic attempts.") - return - end - - -- if it costs something then some condition must be met - if not no_cost then - -- Require lite - if (check_affect(s, "blind")) and ((player.blind > 0) or (no_lite() == TRUE)) then - msg_print("You cannot see!") - return - end - - -- Not when confused - if (check_affect(s, "confusion")) and (player.confused > 0) then - msg_print("You are too confused!") - return - end - - -- Enough mana - if (get_mana(s) > get_power(s)) then - if (get_check("You do not have enough "..get_power_name(s)..", do you want to try anyway?") == FALSE) then return end - end - - -- Invoke the spell effect - if (magik(spell_chance(s)) == FALSE) then - if (__spell_spell[s]() ~= nil) then - use = TRUE - end - else - local index, sch - - -- added because this is *extremely* important --pelpel - if (flush_failure) then flush() end - - msg_print("You failed to get the spell off!") - for index, sch in __spell_school[s] do - if __schools[sch].fail then - __schools[sch].fail(spell_chance(s)) - end - end - use = TRUE - end - else - __spell_spell[s]() - end - - if use == TRUE then - -- Reduce mana - adjust_power(s, -get_mana(s)) - - -- Take a turn - if is_magestaff() == TRUE then energy_use = 80 - else energy_use = 100 end - end - - player.redraw = bor(player.redraw, PR_MANA) - player.window = bor(player.window, PW_PLAYER) -end - -- Can the spell be randomly found(in random books) function can_spell_random(i) diff --git a/lib/mods/theme/core/s_aux.lua b/lib/mods/theme/core/s_aux.lua index 20cf4964..76f01637 100644 --- a/lib/mods/theme/core/s_aux.lua +++ b/lib/mods/theme/core/s_aux.lua @@ -218,33 +218,6 @@ function get_mana(s) return spell(s).mana + get_level(s, spell(s).mana_max - spell(s).mana, 0) end --- Return the amount of power(mana, piety, whatever) for the spell -function get_power(s) - if check_affect(s, "piety", FALSE) then - return player.grace - else - return player.csp - end -end - --- Return the amount of power(mana, piety, whatever) for the spell -function get_power_name(s) - if check_affect(s, "piety", FALSE) then - return "piety" - else - return "mana" - end -end - --- Changes the amount of power(mana, piety, whatever) for the spell -function adjust_power(s, x) - if check_affect(s, "piety", FALSE) then - inc_piety(GOD_ALL, x) - else - increase_mana(x) - end -end - -- Get spell school name(s) as a /-separated string. function spell_school_name(s) local xx, sch_str @@ -292,76 +265,6 @@ function get_spell_stat(s) else return __tmp_spells[s].stat end end -function cast_school_spell(s, s_ptr, no_cost) - local use = FALSE - - -- No magic - if (player.antimagic > 0) then - msg_print("Your anti-magic field disrupts any magic attempts.") - return - end - - -- No magic - if (player.anti_magic == TRUE) then - msg_print("Your anti-magic shell disrupts any magic attempts.") - return - end - - -- if it costs something then some condition must be met - if not no_cost then - -- Require lite - if (check_affect(s, "blind")) and ((player.blind > 0) or (no_lite() == TRUE)) then - msg_print("You cannot see!") - return - end - - -- Not when confused - if (check_affect(s, "confusion")) and (player.confused > 0) then - msg_print("You are too confused!") - return - end - - -- Enough mana - if (get_mana(s) > get_power(s)) then - if (get_check("You do not have enough "..get_power_name(s)..", do you want to try anyway?") == FALSE) then return end - end - - -- Invoke the spell effect - if (magik(spell_chance(s)) == FALSE) then - if (__spell_spell[s]() ~= nil) then - use = TRUE - end - else - local index, sch - - -- added because this is *extremely* important --pelpel - if (flush_failure) then flush() end - - msg_print("You failed to get the spell off!") - for index, sch in __spell_school[s] do - if __schools[sch].fail then - __schools[sch].fail(spell_chance(s)) - end - end - use = TRUE - end - else - __spell_spell[s]() - end - - if use == TRUE then - -- Reduce mana - adjust_power(s, -get_mana(s)) - - -- Take a turn - if is_magestaff() == TRUE then energy_use = 80 - else energy_use = 100 end - end - - player.redraw = bor(player.redraw, PR_MANA) - player.window = bor(player.window, PW_PLAYER) -end - -- Can the spell be randomly found(in random books) function can_spell_random(i) diff --git a/lib/mods/theme/scpt/mkeys.lua b/lib/mods/theme/scpt/mkeys.lua index 96fc2934..c46cbace 100644 --- a/lib/mods/theme/scpt/mkeys.lua +++ b/lib/mods/theme/scpt/mkeys.lua @@ -39,7 +39,7 @@ add_mkey -- Actualy cast the choice if (s ~= -1) then - cast_school_spell(s, spell(s)) + cast_school_spell(s) end end, } diff --git a/lib/scpt/mkeys.lua b/lib/scpt/mkeys.lua index 96fc2934..c46cbace 100644 --- a/lib/scpt/mkeys.lua +++ b/lib/scpt/mkeys.lua @@ -39,7 +39,7 @@ add_mkey -- Actualy cast the choice if (s ~= -1) then - cast_school_spell(s, spell(s)) + cast_school_spell(s) end end, } diff --git a/src/cmd5.c b/src/cmd5.c index 5f0201fc..d0c60042 100644 --- a/src/cmd5.c +++ b/src/cmd5.c @@ -2409,7 +2409,7 @@ void cast_school_spell() /* Actualy cast the choice */ if (spell != -1) { - exec_lua(format("cast_school_spell(%d, spell(%d))", spell, spell)); + lua_cast_school_spell(spell, FALSE); } } diff --git a/src/externs.h b/src/externs.h index d933b2be..e48b99cd 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1916,6 +1916,7 @@ int print_book(s16b sval, s32b pval, object_type *obj); int school_book_length(int sval); int spell_x(int sval, int pval, int i); bool_ school_book_contains_spell(int sval, s32b spell_idx); +void lua_cast_school_spell(s32b spell_idx, bool_ no_cost); /* randart.c */ extern int get_activation_power(void); diff --git a/src/lua_bind.c b/src/lua_bind.c index e7870189..456e653d 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -249,10 +249,6 @@ int get_mana(s32b s) { return exec_lua(format("return get_mana(%d)", s)); } -int get_power(s32b s) { - return exec_lua(format("return get_power(%d)", s)); -} - static int get_spell_stat(s32b s) { return exec_lua(format("return get_spell_stat(%d)", s)); } diff --git a/src/object.pkg b/src/object.pkg index 1ff281c7..4859e35b 100644 --- a/src/object.pkg +++ b/src/object.pkg @@ -1132,7 +1132,6 @@ extern object_type *new_object(); extern void end_object(object_type *o_ptr); extern bool get_item @ get_item_aux(int *cp, cptr pmt, cptr str, int mode); extern void lua_set_item_tester(int tval, char *fct); -extern bool is_magestaff(); extern void identify_pack_fully(void); extern s16b inven_carry(object_type *o_ptr, bool final); extern s32b calc_total_weight(void); diff --git a/src/object1.c b/src/object1.c index 3b418651..2be0984c 100644 --- a/src/object1.c +++ b/src/object1.c @@ -2828,6 +2828,8 @@ void display_ammo_damage(object_type *o_ptr) */ void describe_device(object_type *o_ptr) { + char buf[128]; + /* Wands/... of shcool spell */ if (((o_ptr->tval == TV_WAND) || (o_ptr->tval == TV_STAFF)) && object_known_p(o_ptr)) { @@ -2844,7 +2846,8 @@ void describe_device(object_type *o_ptr) text_out_c(TERM_L_BLUE, format("%d", school_spells[o_ptr->pval2].skill_level)); text_out("\nSpell fail: "); - text_out_c(TERM_GREEN, string_exec_lua(format("return tostring(spell_chance(%d))", o_ptr->pval2))); + sprintf(buf, FMTs32b, spell_chance(o_ptr->pval2)); + text_out_c(TERM_GREEN, buf); text_out("\nSpell info: "); text_out_c(TERM_YELLOW, get_spell_info(o_ptr->pval2)); diff --git a/src/spells.pkg b/src/spells.pkg index 18620ccd..c259f672 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2297,36 +2297,10 @@ extern s32b lua_get_level(s32b s, s32b lvl, s32b max, s32b min, s32b bonus); /** Get level of device */ extern s32b get_level_device(s32b s, s32b max, s32b min); -/** Get change of failure for spell. */ -extern s32b spell_chance(s32b s); - /** Get level of spell */ extern s32b get_level(s32b s, s32b max, s32b min); -/** @fn lua_spell_chance(s32b chance, int level, int skill_level, int mana, int cur_mana, int stat) - * @dgonly - * @brief Get the chance a spell will fail.\n - * @param chance Number \n chance is the inital chance a spell will work. - * @brief Initial chance - * @param level Number \n level represents the level of player skill. - * @brief Player skill level - * @param skill_level Number \n *unused*. - * @brief *Unused* - * @param mana Number \n mana is the mana required by the spell. - * @brief Spell mana - * @param cur_mana Number \n cur_mana is the player's current mana. - * @brief Player mana - * @param stat Number \n stat is the required casting statistic (INT or WIS). - * @brief Casting statistic - * @return Number \n Chance of failure. - * @note - * Note: do not call this function directly.\n - * By order of DG. - * @note (see file lua_bind.c) - */ -extern s32b lua_spell_chance(s32b chance, int level, int skill_level, int mana, int cur_mana, int stat); - /** @fn lua_spell_device_chance(s32b chance, int level, int base_level) * @dgonly * @brief Get the chance a device will fail.\n @@ -2908,3 +2882,4 @@ void init_school_books(); extern s32b SCHOOL_UDUN; extern s32b SCHOOL_MELKOR; +void lua_cast_school_spell @ cast_school_spell(s32b spell_idx, bool no_cost = FALSE); diff --git a/src/spells1.c b/src/spells1.c index 477dfdb9..ccd9f489 100644 --- a/src/spells1.c +++ b/src/spells1.c @@ -1259,7 +1259,7 @@ void spellbinder_trigger() for (i = 0; i < p_ptr->spellbinder_num; i++) { msg_format("Triggering spell %s.", school_spells[p_ptr->spellbinder[i]].name); - exec_lua(format("cast_school_spell(%d, spell(%d), TRUE)", p_ptr->spellbinder[i], p_ptr->spellbinder[i])); + lua_cast_school_spell(p_ptr->spellbinder[i], TRUE); } p_ptr->spellbinder_num = 0; p_ptr->spellbinder_trigger = 0; diff --git a/src/spells3.c b/src/spells3.c index b7019e0f..f83ab513 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -2527,11 +2527,7 @@ void meta_inertia_control_timer_callback() else if ((p_ptr->inertia_controlled_spell != -1) && (!p_ptr->wild_mode)) { - char buf[128]; - sprintf(buf, - "__spell_spell[" FMTs32b "]()", - p_ptr->inertia_controlled_spell); - exec_lua(buf); + lua_cast_school_spell(p_ptr->inertia_controlled_spell, TRUE); } } diff --git a/src/spells4.c b/src/spells4.c index 0429e1c1..aa62d827 100644 --- a/src/spells4.c +++ b/src/spells4.c @@ -35,6 +35,31 @@ static bool_ castable_while_confused(int s) return exec_lua(buf); } +/** Describe what type of energy the spell uses for casting */ +cptr get_power_name(s32b s) +{ + return uses_piety_to_cast(s) ? "piety" : "mana"; +} + +/* Changes the amount of power(mana, piety, whatever) for the spell */ +void adjust_power(s32b s, s32b amount) +{ + if (uses_piety_to_cast(s)) + { + inc_piety(GOD_ALL, amount); + } + else + { + increase_mana(amount); + } +} + +/* Return the amount of power available for casting spell */ +s32b get_power(s32b s) +{ + return uses_piety_to_cast(s) ? p_ptr->grace : p_ptr->csp; +} + /* Output the describtion when it is used as a spell */ void print_spell_desc(int s, int y) { @@ -483,3 +508,98 @@ int print_book(s16b sval, s32b pval, object_type *obj) prt(format(" %-20s%-16s Level Cost Fail Info", "Name", "School"), 1, 0); return y; } + +static bool_ call_spell_function(s32b s) +{ + char buf[128]; + sprintf(buf, "return (__spell_spell[" FMTs32b "]() ~= nil)", s); + return exec_lua(buf); +} + +void lua_cast_school_spell(s32b s, bool_ no_cost) +{ + bool_ use = FALSE; + + /* No magic? */ + if (p_ptr->antimagic > 0) + { + msg_print("Your anti-magic field disrupts any magic attempts."); + return; + } + + /* No magic? */ + if (p_ptr->anti_magic) + { + msg_print("Your anti-magic shell disrupts any magic attempts."); + return; + } + + /* if it costs something then some condition must be met */ + if (!no_cost) + { + /* Require lite */ + if (!castable_while_blind(s) && ((p_ptr->blind > 0) || no_lite())) + { + msg_print("You cannot see!"); + return; + } + + /* Not when confused */ + if (!castable_while_confused(s) && (p_ptr->confused > 0)) + { + msg_print("You are too confused!"); + return; + } + + /* Enough mana */ + if (get_mana(s) > get_power(s)) + { + char buf[128]; + sprintf(buf, + "You do not have enough %s, do you want to try anyway?", + get_power_name(s)); + + if (!get_check(buf)) + { + return; + } + } + + /* Invoke the spell effect */ + if (!magik(spell_chance(s))) + { + use = call_spell_function(s); + } + else + { + use = TRUE; + + /* failures are dangerous; we'll flush the input buffer + so it isn't missed. */ + if (flush_failure) + { + flush(); + } + + msg_print("You failed to get the spell off!"); + } + } + else + { + call_spell_function(s); + } + + /* Use the mana/piety */ + if (use == TRUE) + { + /* Reduce mana */ + adjust_power(s, -get_mana(s)); + + /* Take a turn */ + energy_use = is_magestaff() ? 80 : 100; + } + + /* Refresh player */ + p_ptr->redraw |= PR_MANA; + p_ptr->window |= PW_PLAYER; +} -- cgit v1.2.3 From f7e4d1b4d9da8c42f02f79c0328477dd787fecd2 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 18 May 2012 15:07:28 +0200 Subject: Lua: Add string_list for dynamic string lists --- src/CMakeLists.txt | 2 +- src/string_list.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/types.h | 16 ++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 src/string_list.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3a640e74..f1af4895 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,7 +11,7 @@ SET(SRCS monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c spells1.c spells2.c spells3.c spells4.c corrupt.c mimic.c - status.c files.c notes.c loadsave.c + status.c files.c notes.c loadsave.c string_list.c cmd1.c cmd2.c cmd3.c cmd4.c cmd5.c cmd6.c cmd7.c help.c generate.c gen_maze.c gen_evol.c wild.c levels.c store.c bldg.c diff --git a/src/string_list.c b/src/string_list.c new file mode 100644 index 00000000..b39ecd6f --- /dev/null +++ b/src/string_list.c @@ -0,0 +1,40 @@ +#include "angband.h" + +int compare_string_list(string_list *a, string_list *b) +{ + if (a == b) + { + return 0; + } + + return strcmp(a->s, b->s); +} + +SGLIB_DEFINE_LIST_FUNCTIONS(string_list, compare_string_list, next); + +/* + * Initialize a string_list value. Copies the input string. + */ +void string_list_init(string_list *sl, cptr s) +{ + assert(sl != NULL); + + sl->s = string_make(s); + sl->next = NULL; +} + +/* + * Destroy string_value. + */ +void string_list_destroy(string_list *sl) +{ + assert(sl != NULL); + + if (sl->s) { + string_free(sl->s); + sl->s = NULL; + } + + /* We do NOT free the rest of the list. */ + sl->next = NULL; +} diff --git a/src/types.h b/src/types.h index ea8ca019..3a408ed1 100644 --- a/src/types.h +++ b/src/types.h @@ -46,6 +46,22 @@ */ +/* + * String list. + */ +typedef struct string_list string_list; +struct string_list { + /* The string list owns the string */ + cptr s; + /* Next */ + string_list *next; +}; + +int compare_string_list(string_list *a, string_list *b); +SGLIB_DEFINE_LIST_PROTOTYPES(string_list, compare_string, next); + +void string_list_init(string_list *sl, cptr s); /* Initialize element; copies string */ +void string_list_destroy(string_list *sl); /* Destroy element */ -- cgit v1.2.3 From 0b4fe745accdb743bc998e42282efb08c5b4ccd1 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 18 May 2012 15:41:45 +0200 Subject: Lua: Move handling of spell descriptions to C --- lib/core/s_aux.lua | 35 +++----------------------- lib/mods/theme/core/s_aux.lua | 35 +++----------------------- lib/mods/theme/scpt/s_stick.lua | 4 +-- lib/scpt/s_stick.lua | 4 +-- src/cmd6.c | 54 +++++++++++++++++++++++++++++++++++++++-- src/externs.h | 2 ++ src/object1.c | 19 ++++++++++++++- src/spells.pkg | 1 + src/spells4.c | 28 ++++++++++----------- src/types.h | 1 + 10 files changed, 100 insertions(+), 83 deletions(-) diff --git a/lib/core/s_aux.lua b/lib/core/s_aux.lua index 76f01637..b0c500a6 100644 --- a/lib/core/s_aux.lua +++ b/lib/core/s_aux.lua @@ -72,14 +72,16 @@ function finish_spell(must_i) spell(i).skill_level = s.level __spell_spell[i] = s.spell __spell_info[i] = s.info - __spell_desc[i] = s.desc + local j,desc + for j,desc in s.desc do + spell_description_add_line(i, desc) + end return i end -- Creates the school books array __spell_spell = {} __spell_info = {} -__spell_desc = {} __spell_school = {} -- Find a spell by name @@ -234,15 +236,6 @@ function spell_school_name(s) return sch_str end --- Output the desc when sued as a device -function print_device_desc(s) - local index, desc - - for index, desc in __spell_desc[s] do - text_out("\n" .. desc) - end -end - function check_affect(s, name, default) local s_ptr = __tmp_spells[s] local a @@ -389,26 +382,6 @@ function get_stick_charges(spl) return __tmp_spells[spl].stick.charge[1] + randint(__tmp_spells[spl].stick.charge[2]); end --- Get activation desc -function get_activation_desc(spl) - local turns - if type(__tmp_spells[spl].activate) == 'number' then - turns = __tmp_spells[spl].activate - else - turns = __tmp_spells[spl].activate[1] .. '+d' .. __tmp_spells[spl].activate[2] - end - return __tmp_spells[spl].desc[1] .. ' every ' .. turns .. ' turns' -end - --- Compute the timeout of an activation -function get_activation_timeout(spl) - if type(__tmp_spells[spl].activate) == 'number' then - return __tmp_spells[spl].activate - else - return __tmp_spells[spl].activate[1] + randint(__tmp_spells[spl].activate[2]) - end -end - -- Fire off the spell function activate_activation(spl, item) __spell_spell[spl](item) diff --git a/lib/mods/theme/core/s_aux.lua b/lib/mods/theme/core/s_aux.lua index 76f01637..b0c500a6 100644 --- a/lib/mods/theme/core/s_aux.lua +++ b/lib/mods/theme/core/s_aux.lua @@ -72,14 +72,16 @@ function finish_spell(must_i) spell(i).skill_level = s.level __spell_spell[i] = s.spell __spell_info[i] = s.info - __spell_desc[i] = s.desc + local j,desc + for j,desc in s.desc do + spell_description_add_line(i, desc) + end return i end -- Creates the school books array __spell_spell = {} __spell_info = {} -__spell_desc = {} __spell_school = {} -- Find a spell by name @@ -234,15 +236,6 @@ function spell_school_name(s) return sch_str end --- Output the desc when sued as a device -function print_device_desc(s) - local index, desc - - for index, desc in __spell_desc[s] do - text_out("\n" .. desc) - end -end - function check_affect(s, name, default) local s_ptr = __tmp_spells[s] local a @@ -389,26 +382,6 @@ function get_stick_charges(spl) return __tmp_spells[spl].stick.charge[1] + randint(__tmp_spells[spl].stick.charge[2]); end --- Get activation desc -function get_activation_desc(spl) - local turns - if type(__tmp_spells[spl].activate) == 'number' then - turns = __tmp_spells[spl].activate - else - turns = __tmp_spells[spl].activate[1] .. '+d' .. __tmp_spells[spl].activate[2] - end - return __tmp_spells[spl].desc[1] .. ' every ' .. turns .. ' turns' -end - --- Compute the timeout of an activation -function get_activation_timeout(spl) - if type(__tmp_spells[spl].activate) == 'number' then - return __tmp_spells[spl].activate - else - return __tmp_spells[spl].activate[1] + randint(__tmp_spells[spl].activate[2]) - end -end - -- Fire off the spell function activate_activation(spl, item) __spell_spell[spl](item) diff --git a/lib/mods/theme/scpt/s_stick.lua b/lib/mods/theme/scpt/s_stick.lua index 20d70856..554ca045 100644 --- a/lib/mods/theme/scpt/s_stick.lua +++ b/lib/mods/theme/scpt/s_stick.lua @@ -264,7 +264,7 @@ DEVICE_RADAGAST = add_spell ["mana_max"] = 0, ["fail"] = 10, ["random"] = -1, - ["activate"] = 15000, + ["activate"] = { 15000, 0 }, ["spell"] = function() return device_radagast() end, ["info"] = function() return device_radagast_info() end, ["desc"] = { @@ -281,7 +281,7 @@ DEVICE_VALAROMA = add_spell ["mana_max"] = 0, ["fail"] = 25, ["random"] = -1, - ["activate"] = 250, + ["activate"] = { 250, 0 }, ["spell"] = function() return device_valaroma() end, ["info"] = function() return device_valaroma_info() end, ["desc"] = { diff --git a/lib/scpt/s_stick.lua b/lib/scpt/s_stick.lua index 28abc0db..8075db2f 100644 --- a/lib/scpt/s_stick.lua +++ b/lib/scpt/s_stick.lua @@ -171,7 +171,7 @@ DEVICE_LEBOHAUM = add_spell ["mana_max"] = 0, ["fail"] = 0, ["random"] = -1, - ["activate"] = 3, + ["activate"] = { 3, 0 }, ["spell"] = function() return device_lebohaum() end, ["info"] = function() return device_lebohaum_info() end, ["desc"] = { @@ -253,7 +253,7 @@ DEVICE_DURANDIL = add_spell ["mana_max"] = 0, ["fail"] = 0, ["random"] = -1, - ["activate"] = 3, + ["activate"] = { 3, 0 }, ["spell"] = function() return device_durandil() end, ["info"] = function() return device_durandil_info() end, ["desc"] = { diff --git a/src/cmd6.c b/src/cmd6.c index 15790ca4..39483bbd 100644 --- a/src/cmd6.c +++ b/src/cmd6.c @@ -4989,9 +4989,58 @@ void do_cmd_activate(void) } +static void get_activation_duration(int spl, int *base, int *sides) +{ + assert(base != NULL); + assert(sides != NULL); + + *base = get_lua_int(format("__tmp_spells[%d].activate[1]", spl)); + if (*base <= 0) + { + base = 0; + } + + *sides = get_lua_int(format("__tmp_spells[%d].activate[2]", spl)); + if (*sides <= 0) + { + sides = 0; + } +} + +static void get_activation_desc(char *buf, int spl) +{ + spell_type *spell = &school_spells[spl]; + char turns[32]; + int base, sides; + + get_activation_duration(spl, &base, &sides); + + sprintf(turns, "%d", base); + if (sides > 0) + { + char buf[32]; + sprintf(buf, "+d%d", sides); + strcat(turns, buf); + } + + assert(spell->description != NULL); + assert(spell->description->s != NULL); + sprintf(buf, "%s every %s turns", + spell->description->s, + turns); +} + +static int get_activation_timeout(int spl) +{ + int base, sides; + get_activation_duration(spl, &base, &sides); + return base + randint(sides); +} + const char *activation_aux(object_type * o_ptr, bool_ doit, int item) { + static char buf[256]; int plev = get_skill(SKILL_DEVICE); int i = 0, ii = 0, ij = 0, k, dir, dummy = 0; @@ -5034,11 +5083,12 @@ const char *activation_aux(object_type * o_ptr, bool_ doit, int item) if (doit) { call_lua("activate_activation", "(d,d)", "", -spell, item); - o_ptr->timeout = exec_lua(format("return get_activation_timeout(%d)", -spell)); + o_ptr->timeout = get_activation_timeout(-spell); } else { - return string_exec_lua(format("return get_activation_desc(%d)", -spell)); + get_activation_desc(buf, -spell); + return buf; } } else diff --git a/src/externs.h b/src/externs.h index e48b99cd..644d30b9 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1918,6 +1918,8 @@ int spell_x(int sval, int pval, int i); bool_ school_book_contains_spell(int sval, s32b spell_idx); void lua_cast_school_spell(s32b spell_idx, bool_ no_cost); +void spell_description_add_line(s32b spell_idx, cptr line); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/object1.c b/src/object1.c index 2be0984c..dac3085e 100644 --- a/src/object1.c +++ b/src/object1.c @@ -2823,6 +2823,23 @@ void display_ammo_damage(object_type *o_ptr) } } +/* + * Describe the device spell + */ +static void print_device_desc(int s) +{ + string_list *sl; + struct sglib_string_list_iterator it; + + for (sl = sglib_string_list_it_init(&it, school_spells[s].description); + sl != NULL; + sl = sglib_string_list_it_next(&it)) + { + text_out("\n"); + text_out(sl->s); + } +} + /* * Describe a magic stick powers */ @@ -2837,7 +2854,7 @@ void describe_device(object_type *o_ptr) set_stick_mode(o_ptr); text_out("\nSpell description:"); - exec_lua(format("print_device_desc(%d)", o_ptr->pval2)); + print_device_desc(o_ptr->pval2); text_out("\nSpell level: "); text_out_c(TERM_L_BLUE, string_exec_lua(format("return tostring(get_level(%d, 50, 0))", o_ptr->pval2))); diff --git a/src/spells.pkg b/src/spells.pkg index c259f672..482708bc 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2883,3 +2883,4 @@ void init_school_books(); extern s32b SCHOOL_UDUN; extern s32b SCHOOL_MELKOR; void lua_cast_school_spell @ cast_school_spell(s32b spell_idx, bool no_cost = FALSE); +void spell_description_add_line(s32b spell_idx, cptr line); diff --git a/src/spells4.c b/src/spells4.c index aa62d827..40cca814 100644 --- a/src/spells4.c +++ b/src/spells4.c @@ -63,24 +63,17 @@ s32b get_power(s32b s) /* Output the describtion when it is used as a spell */ void print_spell_desc(int s, int y) { - int i; + string_list *sl; + struct sglib_string_list_iterator it; - for (i=0; ; i++) + for (sl = sglib_string_list_it_init(&it, school_spells[s].description); + sl != NULL; + sl = sglib_string_list_it_next(&it)) { - char buf[128]; - cptr desc = NULL; - - sprintf(buf, "return __spell_desc[%d][%d]", s, i+1); - desc = string_exec_lua(buf); - if (!desc) - { - break; - } - - c_prt(TERM_L_BLUE, desc, y, 0); + c_prt(TERM_L_BLUE, sl->s, y, 0); y++; } - + if (uses_piety_to_cast(s)) { c_prt(TERM_L_WHITE, "It uses piety to cast.", y, 0); @@ -603,3 +596,10 @@ void lua_cast_school_spell(s32b s, bool_ no_cost) p_ptr->redraw |= PR_MANA; p_ptr->window |= PW_PLAYER; } + +void spell_description_add_line(s32b spell_idx, cptr line) +{ + string_list *e = malloc(sizeof(string_list)); + string_list_init(e, line); + sglib_string_list_add(&school_spells[spell_idx].description, e); +} diff --git a/src/types.h b/src/types.h index 3a408ed1..06634be5 100644 --- a/src/types.h +++ b/src/types.h @@ -2475,6 +2475,7 @@ struct spell_type byte mana_max; /* Required mana at max lvl */ s16b fail; /* Minimum chance of failure */ s16b level; /* Spell level(0 = not learnt) */ + string_list *description; /* List of strings */ }; typedef struct school_type school_type; -- cgit v1.2.3 From 1432c854127ed05f4661b04c8e0d7e19830fd8d7 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 18 May 2012 18:35:35 +0200 Subject: Fix clang warnings --- src/loadsave.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/loadsave.c b/src/loadsave.c index 40718194..718f5858 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -579,7 +579,7 @@ static bool_ do_extra(int flag) do_s16b(&p_ptr->chaos_patron, flag); - if ((flag == LS_SAVE)) { tmp16s = CORRUPTIONS_MAX; } + if (flag == LS_SAVE) { tmp16s = CORRUPTIONS_MAX; } do_s16b(&tmp16s, flag); if (tmp16s > CORRUPTIONS_MAX) { quit("Too many corruptions"); @@ -587,12 +587,12 @@ static bool_ do_extra(int flag) for (i = 0; i < tmp16s; i++) { - if ((flag == LS_SAVE)) + if (flag == LS_SAVE) tmp8u = p_ptr->corruptions[i]; do_byte(&tmp8u, flag); - if ((flag == LS_LOAD)) + if (flag == LS_LOAD) p_ptr->corruptions[i] = tmp8u; } -- cgit v1.2.3 From c6962a534553324d1fd6d548f5a648827f762b5d Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 20 May 2012 20:49:30 +0200 Subject: Lua: Varda: Fix format string --- src/spells3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spells3.c b/src/spells3.c index f83ab513..cf839b79 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -4806,7 +4806,7 @@ char *varda_light_of_valinor_info() if (get_level_s(VARDA_LIGHT_VALINOR, 50) >= 15) { sprintf(buf, - "dam %d rad " FMTs32b, + "dam %d rad %d", light_of_valinor_damage(), light_of_valinor_radius()); return buf; -- cgit v1.2.3 From 524c0714a8d8f48ec3f693f39fac1bc1b5b316ad Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 19 May 2012 12:03:08 +0200 Subject: Lua: Move Geomancy spell dependency functions to C --- lib/mods/theme/scpt/s_geom.lua | 16 ++++------------ lib/scpt/s_geom.lua | 16 ++++------------ src/externs.h | 4 ++++ src/spells.pkg | 4 ++++ src/spells3.c | 20 ++++++++++++++++++++ 5 files changed, 36 insertions(+), 24 deletions(-) diff --git a/lib/mods/theme/scpt/s_geom.lua b/lib/mods/theme/scpt/s_geom.lua index d4ce4437..d250f38d 100644 --- a/lib/mods/theme/scpt/s_geom.lua +++ b/lib/mods/theme/scpt/s_geom.lua @@ -83,9 +83,7 @@ VAPORIZE = add_spell ["blind"] = FALSE, -- Must have at least 4 Air ["random"] = 0, - ["depend"] = function() - if get_skill(SKILL_AIR) >= 4 then return TRUE end - end, + ["depend"] = function() return geomancy_vaporize_depends() end, ["spell"] = function() return geomancy_vaporize() end, ["info"] = function() return geomancy_vaporize_info() end, ["desc"] = { @@ -105,9 +103,7 @@ GEOLYSIS = add_spell ["blind"] = FALSE, ["random"] = 0, -- Must have at least 7 Earth - ["depend"] = function() - if get_skill(SKILL_EARTH) >= 7 then return TRUE end - end, + ["depend"] = function() return geomancy_geolysis_depends() end, ["spell"] = function() return geomancy_geolysis() end, ["info"] = function() return geomancy_geolysis_info() end, ["desc"] = { @@ -128,9 +124,7 @@ DRIPPING_TREAD = add_spell ["blind"] = FALSE, ["random"] = 0, -- Must have at least 10 Water - ["depend"] = function() - if get_skill(SKILL_WATER) >= 10 then return TRUE end - end, + ["depend"] = function() return geomancy_dripping_tread_depends() end, ["spell"] = function() return geomancy_dripping_tread() end, ["info"] = function() return geomancy_dripping_tread_info() end, ["desc"] = { @@ -150,9 +144,7 @@ GROW_BARRIER = add_spell ["blind"] = FALSE, ["random"] = 0, -- Must have at least 12 Earth - ["depend"] = function() - if get_skill(SKILL_EARTH) >= 12 then return TRUE end - end, + ["depend"] = function() return geomancy_grow_barrier_depends() end, ["spell"] = function() return geomancy_grow_barrier() end, ["info"] = function() return geomancy_grow_barrier_info() end, ["desc"] = { diff --git a/lib/scpt/s_geom.lua b/lib/scpt/s_geom.lua index d4ce4437..d250f38d 100644 --- a/lib/scpt/s_geom.lua +++ b/lib/scpt/s_geom.lua @@ -83,9 +83,7 @@ VAPORIZE = add_spell ["blind"] = FALSE, -- Must have at least 4 Air ["random"] = 0, - ["depend"] = function() - if get_skill(SKILL_AIR) >= 4 then return TRUE end - end, + ["depend"] = function() return geomancy_vaporize_depends() end, ["spell"] = function() return geomancy_vaporize() end, ["info"] = function() return geomancy_vaporize_info() end, ["desc"] = { @@ -105,9 +103,7 @@ GEOLYSIS = add_spell ["blind"] = FALSE, ["random"] = 0, -- Must have at least 7 Earth - ["depend"] = function() - if get_skill(SKILL_EARTH) >= 7 then return TRUE end - end, + ["depend"] = function() return geomancy_geolysis_depends() end, ["spell"] = function() return geomancy_geolysis() end, ["info"] = function() return geomancy_geolysis_info() end, ["desc"] = { @@ -128,9 +124,7 @@ DRIPPING_TREAD = add_spell ["blind"] = FALSE, ["random"] = 0, -- Must have at least 10 Water - ["depend"] = function() - if get_skill(SKILL_WATER) >= 10 then return TRUE end - end, + ["depend"] = function() return geomancy_dripping_tread_depends() end, ["spell"] = function() return geomancy_dripping_tread() end, ["info"] = function() return geomancy_dripping_tread_info() end, ["desc"] = { @@ -150,9 +144,7 @@ GROW_BARRIER = add_spell ["blind"] = FALSE, ["random"] = 0, -- Must have at least 12 Earth - ["depend"] = function() - if get_skill(SKILL_EARTH) >= 12 then return TRUE end - end, + ["depend"] = function() return geomancy_grow_barrier_depends() end, ["spell"] = function() return geomancy_grow_barrier() end, ["info"] = function() return geomancy_grow_barrier_info() end, ["desc"] = { diff --git a/src/externs.h b/src/externs.h index 644d30b9..4da97b92 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1556,12 +1556,16 @@ bool_ *geomancy_elemental_wave(); char *geomancy_elemental_wave_info(); bool_ *geomancy_vaporize(); char *geomancy_vaporize_info(); +bool_ geomancy_vaporize_depends(); bool_ *geomancy_geolysis(); char *geomancy_geolysis_info(); +bool_ geomancy_geolysis_depends(); bool_ *geomancy_dripping_tread(); char *geomancy_dripping_tread_info(); +bool_ geomancy_dripping_tread_depends(); bool_ *geomancy_grow_barrier(); char *geomancy_grow_barrier_info(); +bool_ geomancy_grow_barrier_depends(); bool_ *geomancy_elemental_minion(); char *geomancy_elemental_minion_info(); diff --git a/src/spells.pkg b/src/spells.pkg index 482708bc..87490e4f 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2542,12 +2542,16 @@ bool_ *geomancy_elemental_wave(); char *geomancy_elemental_wave_info(); bool_ *geomancy_vaporize(); char *geomancy_vaporize_info(); +bool_ geomancy_vaporize_depends(); bool_ *geomancy_geolysis(); char *geomancy_geolysis_info(); +bool_ geomancy_geolysis_depends(); bool_ *geomancy_dripping_tread(); char *geomancy_dripping_tread_info(); +bool_ geomancy_dripping_tread_depends(); bool_ *geomancy_grow_barrier(); char *geomancy_grow_barrier_info(); +bool_ geomancy_grow_barrier_depends(); bool_ *geomancy_elemental_minion(); char *geomancy_elemental_minion_info(); diff --git a/src/spells3.c b/src/spells3.c index cf839b79..e7dabb83 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -1594,6 +1594,11 @@ char *geomancy_vaporize_info() return buf; } +bool_ geomancy_vaporize_depends() +{ + return get_skill(SKILL_AIR) >= 4; +} + bool_ *geomancy_geolysis() { int dir = 0; @@ -1618,6 +1623,11 @@ char *geomancy_geolysis_info() return buf; } +bool_ geomancy_geolysis_depends() +{ + return get_skill(SKILL_EARTH) >= 7; +} + bool_ *geomancy_dripping_tread() { if (p_ptr->dripping_tread == 0) @@ -1643,6 +1653,11 @@ char *geomancy_dripping_tread_info() return buf; } +bool_ geomancy_dripping_tread_depends() +{ + return get_skill(SKILL_WATER) >= 10; +} + bool_ *geomancy_grow_barrier() { int dir = 0; @@ -1664,6 +1679,11 @@ char *geomancy_grow_barrier_info() return ""; } +bool_ geomancy_grow_barrier_depends() +{ + return get_skill(SKILL_EARTH) >= 12; +} + typedef struct geo_summon geo_summon; struct geo_summon { s16b feat; -- cgit v1.2.3 From cfa5b41a11e8be1ef8b5d92be523d4713a445dd7 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 28 May 2012 07:23:43 +0200 Subject: Don't warn about unused variables since SGLib uses them. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c93bebd6..8714ca8a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,7 +8,7 @@ INCLUDE(FeatureSummary) # Default flags. IF(CMAKE_COMPILER_IS_GNUCC) # Let's set sensible options. - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pipe -Wall -Wno-unused-value") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pipe -Wall -Wno-unused-value -Wno-unused-variable") SET(CMAKE_C_FLAGS_RELEASE "-O2") SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") ENDIF() -- cgit v1.2.3 From 1c616215c7568b20f701ef3d5f9b15315d7f7d3a Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 27 May 2012 15:32:35 +0200 Subject: Lua: Factor out "string_list_append" function --- src/spells4.c | 4 +--- src/string_list.c | 12 ++++++++++++ src/types.h | 1 + 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/spells4.c b/src/spells4.c index 40cca814..ba97e065 100644 --- a/src/spells4.c +++ b/src/spells4.c @@ -599,7 +599,5 @@ void lua_cast_school_spell(s32b s, bool_ no_cost) void spell_description_add_line(s32b spell_idx, cptr line) { - string_list *e = malloc(sizeof(string_list)); - string_list_init(e, line); - sglib_string_list_add(&school_spells[spell_idx].description, e); + string_list_append(&school_spells[spell_idx].description, line); } diff --git a/src/string_list.c b/src/string_list.c index b39ecd6f..8a63cc3c 100644 --- a/src/string_list.c +++ b/src/string_list.c @@ -30,6 +30,7 @@ void string_list_destroy(string_list *sl) { assert(sl != NULL); + /* Free contained string */ if (sl->s) { string_free(sl->s); sl->s = NULL; @@ -38,3 +39,14 @@ void string_list_destroy(string_list *sl) /* We do NOT free the rest of the list. */ sl->next = NULL; } + +/** + * Append a string to a string_list. + */ +void string_list_append(string_list **slist, cptr s) +{ + string_list *e = malloc(sizeof(string_list)); + string_list_init(e, s); + + sglib_string_list_add(slist, e); +} diff --git a/src/types.h b/src/types.h index 06634be5..9927e7a5 100644 --- a/src/types.h +++ b/src/types.h @@ -62,6 +62,7 @@ SGLIB_DEFINE_LIST_PROTOTYPES(string_list, compare_string, next); void string_list_init(string_list *sl, cptr s); /* Initialize element; copies string */ void string_list_destroy(string_list *sl); /* Destroy element */ +void string_list_append(string_list **slist, cptr s); /* Append string */ -- cgit v1.2.3 From 1d1ff4c25315b609680c9443c96f823643b3df5d Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 26 May 2012 19:48:22 +0200 Subject: Lua: Eliminate a trivial difference between Tome/Theme DISARM --- lib/mods/theme/scpt/s_convey.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/mods/theme/scpt/s_convey.lua b/lib/mods/theme/scpt/s_convey.lua index 265218fa..d81af28b 100644 --- a/lib/mods/theme/scpt/s_convey.lua +++ b/lib/mods/theme/scpt/s_convey.lua @@ -38,8 +38,9 @@ DISARM = add_spell ["spell"] = function() return convey_disarm() end, ["info"] = function() return convey_disarm_info() end, ["desc"] = { - "Destroys doors and disarms traps", - "At level 10 it unlocks doors and disarms traps", + "Destroys doors and traps", + "At level 10 it destroys doors and traps, then reveals and unlocks any secret", + "doors" } } -- cgit v1.2.3 From 3c6ca071045f3ab2153db833c2be2b500a43880c Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 27 May 2012 17:22:21 +0200 Subject: Lua: Add "range_type" to support moving spells. --- src/CMakeLists.txt | 2 +- src/externs.h | 3 +++ src/range.c | 9 +++++++++ src/types.h | 11 +++++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 src/range.c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f1af4895..219ceb7c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,7 +13,7 @@ SET(SRCS spells1.c spells2.c spells3.c spells4.c corrupt.c mimic.c status.c files.c notes.c loadsave.c string_list.c cmd1.c cmd2.c cmd3.c cmd4.c cmd5.c cmd6.c cmd7.c - help.c + help.c range.c generate.c gen_maze.c gen_evol.c wild.c levels.c store.c bldg.c cmovie.c wizard2.c init2.c birth.c wizard1.c init1.c main.c diff --git a/src/externs.h b/src/externs.h index 4da97b92..f76709d0 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1924,6 +1924,9 @@ void lua_cast_school_spell(s32b spell_idx, bool_ no_cost); void spell_description_add_line(s32b spell_idx, cptr line); +/* range.c */ +extern void range_init(range_type *range, s32b min, s32b max); + /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/range.c b/src/range.c new file mode 100644 index 00000000..647f0576 --- /dev/null +++ b/src/range.c @@ -0,0 +1,9 @@ +#include + +void range_init(range_type *range, s32b min, s32b max) +{ + assert(range != NULL); + + range->min = min; + range->max = max; +} diff --git a/src/types.h b/src/types.h index 9927e7a5..5b349174 100644 --- a/src/types.h +++ b/src/types.h @@ -2430,6 +2430,17 @@ struct cli_comm s16b key; /* Key to convert command to. */ }; +/* + * Range + */ +typedef struct range_type range_type; +struct range_type +{ + s32b min; + s32b max; +}; + + /* * Skills ! */ -- cgit v1.2.3 From 33f06d33cc2f4cd3d36a9616f7f9e9abc7287080 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 27 May 2012 17:33:59 +0200 Subject: Lua: Add "device_allocation_type" to support moving spells --- src/externs.h | 1 + src/spells4.c | 18 ++++++++++++++++++ src/types.h | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/src/externs.h b/src/externs.h index f76709d0..e622ea4c 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1923,6 +1923,7 @@ bool_ school_book_contains_spell(int sval, s32b spell_idx); void lua_cast_school_spell(s32b spell_idx, bool_ no_cost); void spell_description_add_line(s32b spell_idx, cptr line); +void device_allocation_init(device_allocation *device_allocation, byte tval); /* range.c */ extern void range_init(range_type *range, s32b min, s32b max); diff --git a/src/spells4.c b/src/spells4.c index ba97e065..e94274a2 100644 --- a/src/spells4.c +++ b/src/spells4.c @@ -601,3 +601,21 @@ void spell_description_add_line(s32b spell_idx, cptr line) { string_list_append(&school_spells[spell_idx].description, line); } + +void device_allocation_init(device_allocation *device_allocation, byte tval) +{ + assert(device_allocation != NULL); + + device_allocation->tval = tval; + device_allocation->rarity = 0; + range_init(&device_allocation->base_level, 0, 0); + range_init(&device_allocation->max_level, 0, 0); + device_allocation->next = NULL; +} + +int compare_device_allocation(device_allocation *a, device_allocation *b) +{ + return SGLIB_NUMERIC_COMPARATOR(a->tval, b->tval); +} + +SGLIB_DEFINE_LIST_FUNCTIONS(device_allocation, compare_device_allocation, next); diff --git a/src/types.h b/src/types.h index 5b349174..23df8af5 100644 --- a/src/types.h +++ b/src/types.h @@ -2441,6 +2441,24 @@ struct range_type }; +/* + * Device allocation for skill + */ +typedef struct device_allocation device_allocation; +struct device_allocation +{ + byte tval; + s32b rarity; + range_type base_level; + range_type max_level; + /* Next device allocation in the list */ + device_allocation *next; +}; + +int compare_device_allocation(device_allocation *a, device_allocation *b); +SGLIB_DEFINE_LIST_PROTOTYPES(device_allocation, compare_device_allocation, next); + + /* * Skills ! */ -- cgit v1.2.3 From 48310612100205a13b4d743951fbc436d081d011 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 27 May 2012 17:54:26 +0200 Subject: Lua: Add "dice_type" to support moving spells to C --- src/externs.h | 6 ++++ src/spells4.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/types.h | 10 +++++++ 3 files changed, 109 insertions(+) diff --git a/src/externs.h b/src/externs.h index e622ea4c..337c503d 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1925,6 +1925,12 @@ void lua_cast_school_spell(s32b spell_idx, bool_ no_cost); void spell_description_add_line(s32b spell_idx, cptr line); void device_allocation_init(device_allocation *device_allocation, byte tval); +void dice_init(dice_type *dice, long base, long num, long sides); +bool_ dice_parse(dice_type *dice, cptr s); +void dice_parse_checked(dice_type *dice, cptr s); +long dice_roll(dice_type *dice); +void dice_print(dice_type *dice, char *buf); + /* range.c */ extern void range_init(range_type *range, s32b min, s32b max); diff --git a/src/spells4.c b/src/spells4.c index e94274a2..1cbc451c 100644 --- a/src/spells4.c +++ b/src/spells4.c @@ -619,3 +619,96 @@ int compare_device_allocation(device_allocation *a, device_allocation *b) } SGLIB_DEFINE_LIST_FUNCTIONS(device_allocation, compare_device_allocation, next); + +void dice_init(dice_type *dice, long base, long num, long sides) +{ + assert(dice != NULL); + + dice->base = base; + dice->num = num; + dice->sides = sides; +} + +bool_ dice_parse(dice_type *dice, cptr s) +{ + long base, num, sides; + + if (sscanf(s, "%ld+%ldd%ld", &base, &num, &sides) == 3) + { + dice_init(dice, base, num, sides); + return TRUE; + } + + if (sscanf(s, "%ld+d%ld", &base, &sides) == 2) + { + dice_init(dice, base, 1, sides); + return TRUE; + } + + if (sscanf(s, "d%ld", &sides) == 1) + { + dice_init(dice, 0, 1, sides); + return TRUE; + } + + if (sscanf(s, "%ldd%ld", &num, &sides) == 2) + { + dice_init(dice, 0, num, sides); + return TRUE; + } + + if (sscanf(s, "%ld", &base) == 1) + { + dice_init(dice, base, 0, 0); + return TRUE; + } + + return FALSE; +} + +void dice_parse_checked(dice_type *dice, cptr s) +{ + bool_ result = dice_parse(dice, s); + if (!result) + { + abort(); + } +} + +long dice_roll(dice_type *dice) +{ + assert(dice != NULL); + return dice->base + damroll(dice->num, dice->sides); +} + +void dice_print(dice_type *dice, char *output) +{ + char buf[16]; + + output[0] = '\0'; + + if (dice->base > 0) + { + sprintf(buf, "%ld", dice->base); + strcat(output, buf); + } + + if ((dice->num > 0) || (dice->sides > 0)) + { + if (dice->base > 0) + { + strcat(output, "+"); + } + + if (dice->num > 1) + { + sprintf(buf, "%ld", dice->num); + strcat(output, buf); + } + + strcat(output, "d"); + + sprintf(buf, "%ld", dice->sides); + strcat(output, buf); + } +} diff --git a/src/types.h b/src/types.h index 23df8af5..796ed024 100644 --- a/src/types.h +++ b/src/types.h @@ -2440,6 +2440,16 @@ struct range_type s32b max; }; +/* + * Dice + */ +typedef struct dice_type dice_type; +struct dice_type +{ + long base; /* Base value to which roll is added. */ + long num; /* Number of dice */ + long sides; /* Sides per dice */ +}; /* * Device allocation for skill -- cgit v1.2.3 From fee1fe9e253d9deb108309658edfa1bd2a1d720c Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 28 May 2012 06:27:46 +0200 Subject: Lua: Add missing SCHOOL_* variables to spells4.c --- src/externs.h | 25 ++++++++++++++++++++++++- src/spells.pkg | 26 +++++++++++++++++++++++++- src/spells4.c | 25 ++++++++++++++++++++++++- 3 files changed, 73 insertions(+), 3 deletions(-) diff --git a/src/externs.h b/src/externs.h index 337c503d..f3e5bc02 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1907,8 +1907,31 @@ char *varda_star_kindler_info(); SGLIB_DEFINE_LIST_PROTOTYPES(spell_idx_list, compare_spell_idx, next); -extern s32b SCHOOL_UDUN; +extern s32b SCHOOL_AIR; +extern s32b SCHOOL_AULE; +extern s32b SCHOOL_CONVEYANCE; +extern s32b SCHOOL_DEMON; +extern s32b SCHOOL_DEVICE; +extern s32b SCHOOL_DIVINATION; +extern s32b SCHOOL_EARTH; +extern s32b SCHOOL_ERU; +extern s32b SCHOOL_FIRE; +extern s32b SCHOOL_GEOMANCY; +extern s32b SCHOOL_MANA; +extern s32b SCHOOL_MANDOS; +extern s32b SCHOOL_MANWE; extern s32b SCHOOL_MELKOR; +extern s32b SCHOOL_META; +extern s32b SCHOOL_MIND; +extern s32b SCHOOL_MUSIC; +extern s32b SCHOOL_NATURE; +extern s32b SCHOOL_TEMPORAL; +extern s32b SCHOOL_TULKAS; +extern s32b SCHOOL_UDUN; +extern s32b SCHOOL_ULMO; +extern s32b SCHOOL_VARDA; +extern s32b SCHOOL_WATER; +extern s32b SCHOOL_YAVANNA; void print_spell_desc(int s, int y); void init_school_books(); diff --git a/src/spells.pkg b/src/spells.pkg index 87490e4f..0ea452bf 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2884,7 +2884,31 @@ char *varda_star_kindler_info(); */ void init_school_books(); -extern s32b SCHOOL_UDUN; +extern s32b SCHOOL_AIR; +extern s32b SCHOOL_AULE; +extern s32b SCHOOL_CONVEYANCE; +extern s32b SCHOOL_DEMON; +extern s32b SCHOOL_DEVICE; +extern s32b SCHOOL_DIVINATION; +extern s32b SCHOOL_EARTH; +extern s32b SCHOOL_ERU; +extern s32b SCHOOL_FIRE; +extern s32b SCHOOL_GEOMANCY; +extern s32b SCHOOL_MANA; +extern s32b SCHOOL_MANDOS; +extern s32b SCHOOL_MANWE; extern s32b SCHOOL_MELKOR; +extern s32b SCHOOL_META; +extern s32b SCHOOL_MIND; +extern s32b SCHOOL_MUSIC; +extern s32b SCHOOL_NATURE; +extern s32b SCHOOL_TEMPORAL; +extern s32b SCHOOL_TULKAS; +extern s32b SCHOOL_UDUN; +extern s32b SCHOOL_ULMO; +extern s32b SCHOOL_VARDA; +extern s32b SCHOOL_WATER; +extern s32b SCHOOL_YAVANNA; + void lua_cast_school_spell @ cast_school_spell(s32b spell_idx, bool no_cost = FALSE); void spell_description_add_line(s32b spell_idx, cptr line); diff --git a/src/spells4.c b/src/spells4.c index 1cbc451c..e270c464 100644 --- a/src/spells4.c +++ b/src/spells4.c @@ -4,8 +4,31 @@ school_book_type school_books[SCHOOL_BOOKS_SIZE]; -s32b SCHOOL_UDUN; +s32b SCHOOL_AIR; +s32b SCHOOL_AULE; +s32b SCHOOL_CONVEYANCE; +s32b SCHOOL_DEMON; +s32b SCHOOL_DEVICE; +s32b SCHOOL_DIVINATION; +s32b SCHOOL_EARTH; +s32b SCHOOL_ERU; +s32b SCHOOL_FIRE; +s32b SCHOOL_GEOMANCY; +s32b SCHOOL_MANA; +s32b SCHOOL_MANDOS; +s32b SCHOOL_MANWE; s32b SCHOOL_MELKOR; +s32b SCHOOL_META; +s32b SCHOOL_MIND; +s32b SCHOOL_MUSIC; +s32b SCHOOL_NATURE; +s32b SCHOOL_TEMPORAL; +s32b SCHOOL_TULKAS; +s32b SCHOOL_UDUN; +s32b SCHOOL_ULMO; +s32b SCHOOL_VARDA; +s32b SCHOOL_WATER; +s32b SCHOOL_YAVANNA; static int compare_spell_idx(spell_idx_list *a, spell_idx_list *b) { -- cgit v1.2.3 From 7d052a1a4b8ff944a649c4afdd277aeb30b42cb0 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 27 May 2012 19:28:12 +0200 Subject: Lua: Add "casting_type" enum to support moving spells to C --- src/types.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/types.h b/src/types.h index 796ed024..3c028d3a 100644 --- a/src/types.h +++ b/src/types.h @@ -2503,6 +2503,12 @@ struct skill_type }; +/* + * Casting type + */ +typedef enum { USE_SPELL_POINTS, USE_PIETY } casting_type; + + /* * The spell function must provide the desc */ -- cgit v1.2.3 From e272282c1451329d16fd16efbfccc234395cba6e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 28 May 2012 06:38:12 +0200 Subject: Lua: Add "school_idx" type to hold list of spell schools --- src/externs.h | 5 +++++ src/spells4.c | 33 +++++++++++++++++++++++++++++++++ src/types.h | 10 ++++++++++ 3 files changed, 48 insertions(+) diff --git a/src/externs.h b/src/externs.h index f3e5bc02..d2805f0c 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1906,6 +1906,7 @@ char *varda_star_kindler_info(); /* spells4.c */ SGLIB_DEFINE_LIST_PROTOTYPES(spell_idx_list, compare_spell_idx, next); +SGLIB_DEFINE_LIST_PROTOTYPES(school_idx, compare_school_idx, next); extern s32b SCHOOL_AIR; extern s32b SCHOOL_AULE; @@ -1933,6 +1934,10 @@ extern s32b SCHOOL_VARDA; extern s32b SCHOOL_WATER; extern s32b SCHOOL_YAVANNA; +void school_idx_init(school_idx *e, s32b i); +school_idx *school_idx_new(s32b i); +void school_idx_add_new(school_idx **list, s32b i); + void print_spell_desc(int s, int y); void init_school_books(); school_book_type *school_books_at(int sval); diff --git a/src/spells4.c b/src/spells4.c index e270c464..900121fc 100644 --- a/src/spells4.c +++ b/src/spells4.c @@ -37,6 +37,39 @@ static int compare_spell_idx(spell_idx_list *a, spell_idx_list *b) SGLIB_DEFINE_LIST_FUNCTIONS(spell_idx_list, compare_spell_idx, next); +static int compare_school_idx(school_idx *a, school_idx *b) +{ + return SGLIB_NUMERIC_COMPARATOR(a->i, b->i); +} + +SGLIB_DEFINE_LIST_FUNCTIONS(school_idx, compare_school_idx, next); + +void school_idx_init(school_idx *e, s32b i) +{ + assert(e != NULL); + + e->i = i; + e->next = NULL; +} + +school_idx *school_idx_new(s32b i) +{ + school_idx *e = malloc(sizeof(school_idx)); + assert(e != NULL); + + school_idx_init(e, i); + + return e; +} + +void school_idx_add_new(school_idx **list, s32b i) +{ + school_idx *e = school_idx_new(i); + assert(e != NULL); + + sglib_school_idx_add(list, e); +} + static bool_ uses_piety_to_cast(int s) { char buf[128]; diff --git a/src/types.h b/src/types.h index 3c028d3a..fbf049ae 100644 --- a/src/types.h +++ b/src/types.h @@ -2503,6 +2503,16 @@ struct skill_type }; +/* + * School index list. + */ +typedef struct school_idx school_idx; +struct school_idx { + s32b i; /* School index */ + school_idx *next; /* for list */ +}; + + /* * Casting type */ -- cgit v1.2.3 From 127f4d6985d998c65d958907758e474edb29ceec Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 29 May 2012 05:11:28 +0200 Subject: Lua: Use get_level_s to avoid C->Lua->C loop --- src/cmd1.c | 2 +- src/externs.h | 2 ++ src/spells3.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cmd1.c b/src/cmd1.c index ffeb6d2e..37e12f61 100644 --- a/src/cmd1.c +++ b/src/cmd1.c @@ -2466,7 +2466,7 @@ void py_attack(int y, int x, int max_blow) /* Melkor can cast curse for you*/ PRAY_GOD(GOD_MELKOR) { - int lv = exec_lua("return get_level(MELKOR_CURSE, 100)"); + int lv = get_level_s(MELKOR_CURSE, 100); if (lv >= 10) { diff --git a/src/externs.h b/src/externs.h index d2805f0c..0ebe0f04 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1402,6 +1402,8 @@ extern void geomancy_dig(int oy, int ox, int dir, int length); extern void channel_the_elements(int y, int x, int level); /* spells3.c */ +s32b get_level_s(int sp, int max); + extern s32b NOXIOUSCLOUD; extern s32b AIRWINGS; extern s32b INVISIBILITY; diff --git a/src/spells3.c b/src/spells3.c index e7dabb83..b8632bf9 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -174,7 +174,7 @@ bool_ *NO_CAST = NULL; bool_ CAST_VAL = 0xca; /* Any value will do */ bool_ *CAST = &CAST_VAL; -static s32b get_level_s(int sp, int max) +s32b get_level_s(int sp, int max) { return get_level(sp, max, 1); } -- cgit v1.2.3 From d98a999477698bb0a304c4995df44f2b7ef5389d Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 29 May 2012 06:25:07 +0200 Subject: Lua: Convert all the spell metadata to C code (Yay automated translation!) --- lib/core/s_aux.lua | 251 +--- lib/mods/theme/core/s_aux.lua | 251 +--- lib/mods/theme/scpt/mkeys.lua | 2 +- lib/mods/theme/scpt/s_air.lua | 152 --- lib/mods/theme/scpt/s_aule.lua | 83 -- lib/mods/theme/scpt/s_convey.lua | 143 --- lib/mods/theme/scpt/s_demon.lua | 166 --- lib/mods/theme/scpt/s_divin.lua | 153 --- lib/mods/theme/scpt/s_earth.lua | 123 -- lib/mods/theme/scpt/s_eru.lua | 88 -- lib/mods/theme/scpt/s_fire.lua | 134 -- lib/mods/theme/scpt/s_geom.lua | 177 --- lib/mods/theme/scpt/s_mana.lua | 89 -- lib/mods/theme/scpt/s_mandos.lua | 86 -- lib/mods/theme/scpt/s_manwe.lua | 84 -- lib/mods/theme/scpt/s_melkor.lua | 64 - lib/mods/theme/scpt/s_meta.lua | 104 -- lib/mods/theme/scpt/s_mind.lua | 88 -- lib/mods/theme/scpt/s_music.lua | 268 ---- lib/mods/theme/scpt/s_nature.lua | 138 -- lib/mods/theme/scpt/s_stick.lua | 290 ----- lib/mods/theme/scpt/s_tempo.lua | 109 -- lib/mods/theme/scpt/s_tulkas.lua | 59 - lib/mods/theme/scpt/s_udun.lua | 74 -- lib/mods/theme/scpt/s_ulmo.lua | 89 -- lib/mods/theme/scpt/s_varda.lua | 83 -- lib/mods/theme/scpt/s_water.lua | 106 -- lib/mods/theme/scpt/s_yavann.lua | 100 -- lib/mods/theme/scpt/spells.lua | 38 +- lib/scpt/mkeys.lua | 2 +- lib/scpt/s_air.lua | 152 --- lib/scpt/s_convey.lua | 143 --- lib/scpt/s_demon.lua | 166 --- lib/scpt/s_divin.lua | 153 --- lib/scpt/s_earth.lua | 123 -- lib/scpt/s_eru.lua | 88 -- lib/scpt/s_fire.lua | 134 -- lib/scpt/s_geom.lua | 177 --- lib/scpt/s_mana.lua | 89 -- lib/scpt/s_manwe.lua | 84 -- lib/scpt/s_melkor.lua | 64 - lib/scpt/s_meta.lua | 104 -- lib/scpt/s_mind.lua | 88 -- lib/scpt/s_music.lua | 268 ---- lib/scpt/s_nature.lua | 113 -- lib/scpt/s_stick.lua | 289 ----- lib/scpt/s_tempo.lua | 109 -- lib/scpt/s_tulkas.lua | 59 - lib/scpt/s_udun.lua | 74 -- lib/scpt/s_water.lua | 106 -- lib/scpt/s_yavann.lua | 100 -- lib/scpt/spells.lua | 32 +- src/CMakeLists.txt | 2 +- src/cmd5.c | 70 +- src/cmd6.c | 80 +- src/defines.h | 5 + src/dungeon.c | 26 +- src/externs.h | 297 ++--- src/init2.c | 9 - src/lua_bind.c | 37 +- src/object1.c | 3 +- src/object2.c | 125 +- src/script.c | 8 - src/spells.pkg | 583 +-------- src/spells3.c | 332 +++-- src/spells4.c | 58 +- src/spells5.c | 2605 ++++++++++++++++++++++++++++++++++++++ src/types.h | 32 +- src/variable.c | 4 +- 69 files changed, 3238 insertions(+), 7347 deletions(-) delete mode 100644 lib/mods/theme/scpt/s_air.lua delete mode 100644 lib/mods/theme/scpt/s_aule.lua delete mode 100644 lib/mods/theme/scpt/s_convey.lua delete mode 100644 lib/mods/theme/scpt/s_demon.lua delete mode 100644 lib/mods/theme/scpt/s_divin.lua delete mode 100644 lib/mods/theme/scpt/s_earth.lua delete mode 100644 lib/mods/theme/scpt/s_eru.lua delete mode 100644 lib/mods/theme/scpt/s_fire.lua delete mode 100644 lib/mods/theme/scpt/s_geom.lua delete mode 100644 lib/mods/theme/scpt/s_mana.lua delete mode 100644 lib/mods/theme/scpt/s_mandos.lua delete mode 100644 lib/mods/theme/scpt/s_manwe.lua delete mode 100644 lib/mods/theme/scpt/s_melkor.lua delete mode 100644 lib/mods/theme/scpt/s_meta.lua delete mode 100644 lib/mods/theme/scpt/s_mind.lua delete mode 100644 lib/mods/theme/scpt/s_music.lua delete mode 100644 lib/mods/theme/scpt/s_nature.lua delete mode 100644 lib/mods/theme/scpt/s_stick.lua delete mode 100644 lib/mods/theme/scpt/s_tempo.lua delete mode 100644 lib/mods/theme/scpt/s_tulkas.lua delete mode 100644 lib/mods/theme/scpt/s_udun.lua delete mode 100644 lib/mods/theme/scpt/s_ulmo.lua delete mode 100644 lib/mods/theme/scpt/s_varda.lua delete mode 100644 lib/mods/theme/scpt/s_water.lua delete mode 100644 lib/mods/theme/scpt/s_yavann.lua delete mode 100644 lib/scpt/s_air.lua delete mode 100644 lib/scpt/s_convey.lua delete mode 100644 lib/scpt/s_demon.lua delete mode 100644 lib/scpt/s_divin.lua delete mode 100644 lib/scpt/s_earth.lua delete mode 100644 lib/scpt/s_eru.lua delete mode 100644 lib/scpt/s_fire.lua delete mode 100644 lib/scpt/s_geom.lua delete mode 100644 lib/scpt/s_mana.lua delete mode 100644 lib/scpt/s_manwe.lua delete mode 100644 lib/scpt/s_melkor.lua delete mode 100644 lib/scpt/s_meta.lua delete mode 100644 lib/scpt/s_mind.lua delete mode 100644 lib/scpt/s_music.lua delete mode 100644 lib/scpt/s_nature.lua delete mode 100644 lib/scpt/s_stick.lua delete mode 100644 lib/scpt/s_tempo.lua delete mode 100644 lib/scpt/s_tulkas.lua delete mode 100644 lib/scpt/s_udun.lua delete mode 100644 lib/scpt/s_water.lua delete mode 100644 lib/scpt/s_yavann.lua create mode 100644 src/spells5.c diff --git a/lib/core/s_aux.lua b/lib/core/s_aux.lua index b0c500a6..9a39df14 100644 --- a/lib/core/s_aux.lua +++ b/lib/core/s_aux.lua @@ -3,9 +3,6 @@ __schools = {} __schools_num = 0 -__tmp_spells = {} -__tmp_spells_num = 0 - function add_school(s) __schools[__schools_num] = s @@ -28,74 +25,9 @@ function finish_school(i) new_school(i, s.name, s.skill) end -function add_spell(s) - __tmp_spells[__tmp_spells_num] = s - - __tmp_spells_num = __tmp_spells_num + 1 - return (__tmp_spells_num - 1) -end - -function finish_spell(must_i) - local i, s - - s = __tmp_spells[must_i] - assert(s.name, "No spell name!") - assert(s.school, "No spell school!") - assert(s.level, "No spell level!") - assert(s.mana, "No spell mana!") - if not s.mana_max then s.mana_max = s.mana end - assert(s.fail, "No spell failure rate!") - assert(s.spell, "No spell function!") - if not s.info then s.info = function() return "" end end - assert(s.desc, "No spell desc!") - if not s.random then s.random = SKILL_MAGIC end - if s.lasting then - assert(type(s.lasting) == "function", "Spell lasting is not function") - end - if s.stick then - local k, e - for k, e in s.stick do - if type(k) == "table" then - assert(e.base_level, "Arg no stick base level") - assert(e.max_level, "Arg no stick max level") - end - end - end - - i = new_spell(must_i, s.name) - assert(i == must_i, "ACK ! i != must_i ! please contact the maintainer") - if type(s.school) == "number" then __spell_school[i] = {s.school} - else __spell_school[i] = s.school end - spell(i).mana = s.mana - spell(i).mana_max = s.mana_max - spell(i).fail = s.fail - spell(i).skill_level = s.level - __spell_spell[i] = s.spell - __spell_info[i] = s.info - local j,desc - for j,desc in s.desc do - spell_description_add_line(i, desc) - end - return i -end - -- Creates the school books array -__spell_spell = {} -__spell_info = {} __spell_school = {} --- Find a spell by name -function find_spell(name) - local i - - i = 0 - while (i < __tmp_spells_num) do - if __tmp_spells[i].name == name then return i end - i = i + 1 - end - return -1 -end - -- Find if the school is under the influence of a god, returns nil or the level function get_god_level(sch) if __schools[sch].gods[player.pgod] then @@ -107,7 +39,7 @@ end -- Change this fct if I want to switch to learnable spells function get_level_school(s, max, min) - local lvl, sch, index, num, bonus + local lvl, sch, num, bonus local allow_spell_power = TRUE lvl = 0 @@ -123,13 +55,18 @@ function get_level_school(s, max, min) end -- Do we pass tests? - if __tmp_spells[s].depend then - if __tmp_spells[s].depend() ~= TRUE then - return min, "n/a" - end + if check_spell_depends(s) ~= TRUE then + return min, "n/a" end - for index, sch in __spell_school[s] do + local index = 0 + while 1 do + sch = spell_get_school_idx(s, index) + if sch == -1 then + break + end + index = index + 1 + local r, s, p, ok = 0, 0, 0, 0 -- Does it require we worship a specific god? @@ -208,87 +145,6 @@ function get_level(s, max, min) return %get_level(s, max, min) end --- Can we cast the spell ? -function is_ok_spell(s, obj) - if get_level(s, 50, 0) == 0 then return nil end - if __tmp_spells[s].pval and obj.pval < __tmp_spells[s].pval then return nil end - return 1 -end - --- Get the amount of mana(or power) needed -function get_mana(s) - return spell(s).mana + get_level(s, spell(s).mana_max - spell(s).mana, 0) -end - --- Get spell school name(s) as a /-separated string. -function spell_school_name(s) - local xx, sch_str - xx = nil - sch_str = "" - for index, sch in __spell_school[s] do - if xx then - sch_str = sch_str.."/"..school(sch).name - else - xx = 1 - sch_str = sch_str..school(sch).name - end - end - return sch_str -end - -function check_affect(s, name, default) - local s_ptr = __tmp_spells[s] - local a - - if type(s_ptr[name]) == "number" then - a = s_ptr[name] - else - a = default - end - if a == FALSE then - return nil - else - return TRUE - end -end - --- Returns the stat to use for the spell, INT by default -function get_spell_stat(s) - if not __tmp_spells[s].stat then return A_INT - else return __tmp_spells[s].stat end -end - - --- Can the spell be randomly found(in random books) -function can_spell_random(i) - return __tmp_spells[i].random -end - --- Find a random spell -function get_random_spell(typ, level) - local spl, tries - - tries = 1000 - while tries > 0 do - tries = tries - 1 - spl = rand_int(__tmp_spells_num) - if (can_spell_random(spl) == typ) and (rand_int(spell(spl).skill_level * 3) < level) then - break - end - end - if tries > 0 then - return spl - else - return -1 - end -end - --- Execute a lasting spell -function exec_lasting_spell(spl) - assert(__tmp_spells[spl].lasting, "No lasting effect for spell "..__tmp_spells[spl].name.." but called as such") - return __tmp_spells[spl].lasting() -end - -- Helper function for spell effect to know if they are or not obvious function is_obvious(effect, old) if old then @@ -301,88 +157,3 @@ function is_obvious(effect, old) return effect end end - --------------------------Sticks------------------------- - --- Fire off the spell -function activate_stick(spl) - local ret = __spell_spell[spl]() - local charge, obvious - if not ret then - charge = FALSE - obvious = FALSE - else - charge = TRUE - obvious = ret - end - return obvious, charge -end - ------------------------------------ Wand, Staves, Rods specific functions ---------------------------- - --- Get a spell for a given stick(wand, staff, rod) -function get_random_stick(stick, level) - local spl, tries - - tries = 1000 - while tries > 0 do - tries = tries - 1 - spl = rand_int(__tmp_spells_num) - if __tmp_spells[spl].stick and (type(__tmp_spells[spl].stick[stick]) == "table") then - if (rand_int(spell(spl).skill_level * 3) < level) and (magik(100 - __tmp_spells[spl].stick[stick].rarity) == TRUE) then - break - end - end - end - if tries > 0 then - return spl - else - return -1 - end -end - --- Get a random base level -function get_stick_base_level(stick, level, spl) - -- Paranoia - if spl < 0 or spl >= __tmp_spells_num or not __tmp_spells[spl].stick[stick] then return 0 end - - local min, max = __tmp_spells[spl].stick[stick].base_level[1], __tmp_spells[spl].stick[stick].base_level[2] - local range = max - min; - - -- Ok the basic idea is to have a max possible level of half the dungeon level - if range * 2 > level then range = level / 2 end - - -- Randomize a bit - range = m_bonus(range, dun_level) - - -- And get the result - return min + range -end - --- Get a random max level -function get_stick_max_level(stick, level, spl) - -- Paranoia - if spl < 0 or spl >= __tmp_spells_num or not __tmp_spells[spl].stick[stick] then return 0 end - - local min, max = __tmp_spells[spl].stick[stick].max_level[1], __tmp_spells[spl].stick[stick].max_level[2] - local range = max - min; - - -- Ok the basic idea is to have a max possible level of half the dungeon level - if range * 2 > level then range = level / 2 end - - -- Randomize a bit - range = m_bonus(range, dun_level) - - -- And get the result - return min + range -end - --- Get the number of desired charges -function get_stick_charges(spl) - return __tmp_spells[spl].stick.charge[1] + randint(__tmp_spells[spl].stick.charge[2]); -end - --- Fire off the spell -function activate_activation(spl, item) - __spell_spell[spl](item) -end diff --git a/lib/mods/theme/core/s_aux.lua b/lib/mods/theme/core/s_aux.lua index b0c500a6..9a39df14 100644 --- a/lib/mods/theme/core/s_aux.lua +++ b/lib/mods/theme/core/s_aux.lua @@ -3,9 +3,6 @@ __schools = {} __schools_num = 0 -__tmp_spells = {} -__tmp_spells_num = 0 - function add_school(s) __schools[__schools_num] = s @@ -28,74 +25,9 @@ function finish_school(i) new_school(i, s.name, s.skill) end -function add_spell(s) - __tmp_spells[__tmp_spells_num] = s - - __tmp_spells_num = __tmp_spells_num + 1 - return (__tmp_spells_num - 1) -end - -function finish_spell(must_i) - local i, s - - s = __tmp_spells[must_i] - assert(s.name, "No spell name!") - assert(s.school, "No spell school!") - assert(s.level, "No spell level!") - assert(s.mana, "No spell mana!") - if not s.mana_max then s.mana_max = s.mana end - assert(s.fail, "No spell failure rate!") - assert(s.spell, "No spell function!") - if not s.info then s.info = function() return "" end end - assert(s.desc, "No spell desc!") - if not s.random then s.random = SKILL_MAGIC end - if s.lasting then - assert(type(s.lasting) == "function", "Spell lasting is not function") - end - if s.stick then - local k, e - for k, e in s.stick do - if type(k) == "table" then - assert(e.base_level, "Arg no stick base level") - assert(e.max_level, "Arg no stick max level") - end - end - end - - i = new_spell(must_i, s.name) - assert(i == must_i, "ACK ! i != must_i ! please contact the maintainer") - if type(s.school) == "number" then __spell_school[i] = {s.school} - else __spell_school[i] = s.school end - spell(i).mana = s.mana - spell(i).mana_max = s.mana_max - spell(i).fail = s.fail - spell(i).skill_level = s.level - __spell_spell[i] = s.spell - __spell_info[i] = s.info - local j,desc - for j,desc in s.desc do - spell_description_add_line(i, desc) - end - return i -end - -- Creates the school books array -__spell_spell = {} -__spell_info = {} __spell_school = {} --- Find a spell by name -function find_spell(name) - local i - - i = 0 - while (i < __tmp_spells_num) do - if __tmp_spells[i].name == name then return i end - i = i + 1 - end - return -1 -end - -- Find if the school is under the influence of a god, returns nil or the level function get_god_level(sch) if __schools[sch].gods[player.pgod] then @@ -107,7 +39,7 @@ end -- Change this fct if I want to switch to learnable spells function get_level_school(s, max, min) - local lvl, sch, index, num, bonus + local lvl, sch, num, bonus local allow_spell_power = TRUE lvl = 0 @@ -123,13 +55,18 @@ function get_level_school(s, max, min) end -- Do we pass tests? - if __tmp_spells[s].depend then - if __tmp_spells[s].depend() ~= TRUE then - return min, "n/a" - end + if check_spell_depends(s) ~= TRUE then + return min, "n/a" end - for index, sch in __spell_school[s] do + local index = 0 + while 1 do + sch = spell_get_school_idx(s, index) + if sch == -1 then + break + end + index = index + 1 + local r, s, p, ok = 0, 0, 0, 0 -- Does it require we worship a specific god? @@ -208,87 +145,6 @@ function get_level(s, max, min) return %get_level(s, max, min) end --- Can we cast the spell ? -function is_ok_spell(s, obj) - if get_level(s, 50, 0) == 0 then return nil end - if __tmp_spells[s].pval and obj.pval < __tmp_spells[s].pval then return nil end - return 1 -end - --- Get the amount of mana(or power) needed -function get_mana(s) - return spell(s).mana + get_level(s, spell(s).mana_max - spell(s).mana, 0) -end - --- Get spell school name(s) as a /-separated string. -function spell_school_name(s) - local xx, sch_str - xx = nil - sch_str = "" - for index, sch in __spell_school[s] do - if xx then - sch_str = sch_str.."/"..school(sch).name - else - xx = 1 - sch_str = sch_str..school(sch).name - end - end - return sch_str -end - -function check_affect(s, name, default) - local s_ptr = __tmp_spells[s] - local a - - if type(s_ptr[name]) == "number" then - a = s_ptr[name] - else - a = default - end - if a == FALSE then - return nil - else - return TRUE - end -end - --- Returns the stat to use for the spell, INT by default -function get_spell_stat(s) - if not __tmp_spells[s].stat then return A_INT - else return __tmp_spells[s].stat end -end - - --- Can the spell be randomly found(in random books) -function can_spell_random(i) - return __tmp_spells[i].random -end - --- Find a random spell -function get_random_spell(typ, level) - local spl, tries - - tries = 1000 - while tries > 0 do - tries = tries - 1 - spl = rand_int(__tmp_spells_num) - if (can_spell_random(spl) == typ) and (rand_int(spell(spl).skill_level * 3) < level) then - break - end - end - if tries > 0 then - return spl - else - return -1 - end -end - --- Execute a lasting spell -function exec_lasting_spell(spl) - assert(__tmp_spells[spl].lasting, "No lasting effect for spell "..__tmp_spells[spl].name.." but called as such") - return __tmp_spells[spl].lasting() -end - -- Helper function for spell effect to know if they are or not obvious function is_obvious(effect, old) if old then @@ -301,88 +157,3 @@ function is_obvious(effect, old) return effect end end - --------------------------Sticks------------------------- - --- Fire off the spell -function activate_stick(spl) - local ret = __spell_spell[spl]() - local charge, obvious - if not ret then - charge = FALSE - obvious = FALSE - else - charge = TRUE - obvious = ret - end - return obvious, charge -end - ------------------------------------ Wand, Staves, Rods specific functions ---------------------------- - --- Get a spell for a given stick(wand, staff, rod) -function get_random_stick(stick, level) - local spl, tries - - tries = 1000 - while tries > 0 do - tries = tries - 1 - spl = rand_int(__tmp_spells_num) - if __tmp_spells[spl].stick and (type(__tmp_spells[spl].stick[stick]) == "table") then - if (rand_int(spell(spl).skill_level * 3) < level) and (magik(100 - __tmp_spells[spl].stick[stick].rarity) == TRUE) then - break - end - end - end - if tries > 0 then - return spl - else - return -1 - end -end - --- Get a random base level -function get_stick_base_level(stick, level, spl) - -- Paranoia - if spl < 0 or spl >= __tmp_spells_num or not __tmp_spells[spl].stick[stick] then return 0 end - - local min, max = __tmp_spells[spl].stick[stick].base_level[1], __tmp_spells[spl].stick[stick].base_level[2] - local range = max - min; - - -- Ok the basic idea is to have a max possible level of half the dungeon level - if range * 2 > level then range = level / 2 end - - -- Randomize a bit - range = m_bonus(range, dun_level) - - -- And get the result - return min + range -end - --- Get a random max level -function get_stick_max_level(stick, level, spl) - -- Paranoia - if spl < 0 or spl >= __tmp_spells_num or not __tmp_spells[spl].stick[stick] then return 0 end - - local min, max = __tmp_spells[spl].stick[stick].max_level[1], __tmp_spells[spl].stick[stick].max_level[2] - local range = max - min; - - -- Ok the basic idea is to have a max possible level of half the dungeon level - if range * 2 > level then range = level / 2 end - - -- Randomize a bit - range = m_bonus(range, dun_level) - - -- And get the result - return min + range -end - --- Get the number of desired charges -function get_stick_charges(spl) - return __tmp_spells[spl].stick.charge[1] + randint(__tmp_spells[spl].stick.charge[2]); -end - --- Fire off the spell -function activate_activation(spl, item) - __spell_spell[spl](item) -end diff --git a/lib/mods/theme/scpt/mkeys.lua b/lib/mods/theme/scpt/mkeys.lua index c46cbace..ae8ad2b1 100644 --- a/lib/mods/theme/scpt/mkeys.lua +++ b/lib/mods/theme/scpt/mkeys.lua @@ -35,7 +35,7 @@ add_mkey return end - s = get_school_spell("cast", "is_ok_spell", 62); + s = get_school_spell("cast", 62); -- Actualy cast the choice if (s ~= -1) then diff --git a/lib/mods/theme/scpt/s_air.lua b/lib/mods/theme/scpt/s_air.lua deleted file mode 100644 index 7b585317..00000000 --- a/lib/mods/theme/scpt/s_air.lua +++ /dev/null @@ -1,152 +0,0 @@ --- handle the air school - -NOXIOUSCLOUD = add_spell -{ - ["name"] = "Noxious Cloud", - ["school"] = {SCHOOL_AIR}, - ["level"] = 3, - ["mana"] = 3, - ["mana_max"] = 30, - ["fail"] = 20, - ["stick"] = - { - ["charge"] = { 5, 7 }, - [TV_WAND] = - { - ["rarity"] = 15, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 25, 50 }, - }, - }, - ["spell"] = function() return air_noxious_cloud() end, - ["info"] = function() return air_noxious_cloud_info() end, - ["desc"] = { - "Creates a cloud of poison", - "The cloud will persist for some turns, damaging all monsters passing by", - "At spell level 30 it turns into a thick gas attacking all living beings" - } -} - -AIRWINGS = add_spell -{ - ["name"] = "Wings of Winds", - ["school"] = {SCHOOL_AIR, SCHOOL_CONVEYANCE}, - ["level"] = 22, - ["mana"] = 30, - ["mana_max"] = 40, - ["fail"] = 60, - ["stick"] = - { - ["charge"] = { 7, 5 }, - [TV_STAFF] = - { - ["rarity"] = 27, - ["base_level"] = { 1, 10 }, - ["max_level"] = { 20, 50 }, - }, - }, - ["inertia"] = { 1, 10 }, - ["spell"] = function() return air_wings_of_winds() end, - ["info"] = function() return air_wings_of_winds_info() end, - ["desc"] = { - "Grants the power of levitation", - "At level 16 it grants the power of controlled flight" - } -} - -INVISIBILITY = add_spell -{ - ["name"] = "Invisibility", - ["school"] = {SCHOOL_AIR}, - ["level"] = 16, - ["mana"] = 10, - ["mana_max"] = 20, - ["fail"] = 50, - ["inertia"] = { 1, 30 }, - ["spell"] = function() return air_invisibility() end, - ["info"] = function() return air_invisibility_info() end, - ["desc"] = { - "Grants invisibility" - } -} - -POISONBLOOD = add_spell -{ - ["name"] = "Poison Blood", - ["school"] = {SCHOOL_AIR}, - ["level"] = 12, - ["mana"] = 10, - ["mana_max"] = 20, - ["fail"] = 30, - ["stick"] = - { - ["charge"] = { 10, 15 }, - [TV_WAND] = - { - ["rarity"] = 45, - ["base_level"] = { 1, 25 }, - ["max_level"] = { 35, 50 }, - }, - }, - ["inertia"] = { 1, 35 }, - ["spell"] = function() return air_poison_blood() end, - ["info"] = function() return air_poison_blood_info() end, - ["desc"] = { - "Grants resist poison", - "At level 15 it provides poison branding to wielded weapon" - } -} - -THUNDERSTORM = add_spell -{ - ["name"] = "Thunderstorm", - ["school"] = {SCHOOL_AIR, SCHOOL_NATURE}, - ["level"] = 25, - ["mana"] = 40, - ["mana_max"] = 60, - ["fail"] = 60, - ["stick"] = - { - ["charge"] = { 5, 5 }, - [TV_WAND] = - { - ["rarity"] = 85, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 25, 50 }, - }, - }, - ["inertia"] = { 2, 15 }, - ["spell"] = function() return air_thunderstorm() end, - ["info"] = function() return air_thunderstorm_info() end, - ["desc"] = { - "Charges up the air around you with electricity", - "Each turn it will throw a thunder bolt at a random monster in sight", - "The thunder does 3 types of damage, one third of lightning", - "one third of sound and one third of light" - } -} - -STERILIZE = add_spell -{ - ["name"] = "Sterilize", - ["school"] = {SCHOOL_AIR}, - ["level"] = 20, - ["mana"] = 10, - ["mana_max"] = 100, - ["fail"] = 50, - ["stick"] = - { - ["charge"] = { 7, 5 }, - [TV_STAFF] = - { - ["rarity"] = 20, - ["base_level"] = { 1, 10 }, - ["max_level"] = { 20, 50 }, - }, - }, - ["spell"] = function() return air_sterilize() end, - ["info"] = function() return air_sterilize_info() end, - ["desc"] = { - "Prevents explosive breeding for a while." - } -} diff --git a/lib/mods/theme/scpt/s_aule.lua b/lib/mods/theme/scpt/s_aule.lua deleted file mode 100644 index 75a121b1..00000000 --- a/lib/mods/theme/scpt/s_aule.lua +++ /dev/null @@ -1,83 +0,0 @@ --- Spells for Aule school - -BOOK_AULE = 63 - -AULE_FIREBRAND = add_spell -{ - ["name"] = "Firebrand", - ["school"] = {SCHOOL_AULE}, - ["level"] = 1, - ["mana"] = 10, - ["mana_max"] = 100, - ["fail"] = 20, - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return aule_firebrand_spell() end, - ["info"] = function() return aule_firebrand_info() end, - ["desc"] = { - "Imbues your melee weapon with fire to deal more damage", - "At level 15 it spreads over a 1 radius zone around your target", - "At level 30 it deals holy fire damage" - } -} - -AULE_ENCHANT_WEAPON = add_spell -{ - ["name"] = "Enchant Weapon", - ["school"] = {SCHOOL_AULE}, - ["level"] = 10, - ["mana"] = 100, - ["mana_max"] = 200, - ["fail"] = 20, - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return aule_enchant_weapon_spell() end, - ["info"] = function() return aule_enchant_weapon_info() end, - ["desc"] = { - "Tries to enchant a weapon to-hit", - "At level 5 it also enchants to-dam", - "At level 45 it enhances the special powers of magical weapons", - "The might of the enchantment increases with the level" - } -} - -AULE_ENCHANT_ARMOUR = add_spell { - ["name"] = "Enchant Armour", - ["school"] = {SCHOOL_AULE}, - ["level"] = 15, - ["mana"] = 100, - ["mana_max"] = 200, - ["fail"] = 20, - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return aule_enchant_armour_spell() end, - ["info"] = function() return aule_enchant_armour_info() end, - ["desc"] = { - "Tries to enchant a piece of armour", - "At level 20 it also enchants to-hit and to-dam", - "At level 40 it enhances the special powers of magical armour", - "The might of the enchantment increases with the level" - } -} - -AULE_CHILD = add_spell -{ - ["name"] = "Child of Aule", - ["school"] = {SCHOOL_AULE}, - ["level"] = 20, - ["mana"] = 200, - ["mana_max"] = 500, - ["fail"] = 40, - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return aule_child_spell() end, - ["info"] = function() return aule_child_info() end, - ["desc"] = { - "Summons a levelled Dwarven warrior to help you battle the forces", - "of Morgoth" - } -} diff --git a/lib/mods/theme/scpt/s_convey.lua b/lib/mods/theme/scpt/s_convey.lua deleted file mode 100644 index d81af28b..00000000 --- a/lib/mods/theme/scpt/s_convey.lua +++ /dev/null @@ -1,143 +0,0 @@ --- handle the conveyance school - -BLINK = add_spell -{ - ["name"] = "Phase Door", - ["school"] = {SCHOOL_CONVEYANCE}, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 3, - ["fail"] = 10, - ["inertia"] = { 1, 5 }, - ["spell"] = function() return convey_blink() end, - ["info"] = function() return convey_blink_info() end, - ["desc"] = { - "Teleports you on a small scale range", - "At level 30 it creates void jumpgates", - } -} - -DISARM = add_spell -{ - ["name"] = "Disarm", - ["school"] = {SCHOOL_CONVEYANCE}, - ["level"] = 3, - ["mana"] = 2, - ["mana_max"] = 4, - ["fail"] = 15, - ["stick"] = - { - ["charge"] = { 10, 15 }, - [TV_STAFF] = - { - ["rarity"] = 4, - ["base_level"] = { 1, 10 }, - ["max_level"] = { 10, 50 }, - }, - }, - ["spell"] = function() return convey_disarm() end, - ["info"] = function() return convey_disarm_info() end, - ["desc"] = { - "Destroys doors and traps", - "At level 10 it destroys doors and traps, then reveals and unlocks any secret", - "doors" - } -} - -TELEPORT = add_spell -{ - ["name"] = "Teleportation", - ["school"] = {SCHOOL_CONVEYANCE}, - ["level"] = 10, - ["mana"] = 8, - ["mana_max"] = 14, - ["fail"] = 30, - ["stick"] = - { - ["charge"] = { 7, 7 }, - [TV_STAFF] = - { - ["rarity"] = 50, - ["base_level"] = { 1, 20 }, - ["max_level"] = { 20, 50 }, - }, - }, - ["inertia"] = { 1, 10 }, - ["spell"] = function() return convey_teleport() end, - ["info"] = function() return convey_teleport_info() end, - ["desc"] = { - "Teleports you around the level. The casting time decreases with level", - } -} - -TELEAWAY = add_spell -{ - ["name"] = "Teleport Away", - ["school"] = {SCHOOL_CONVEYANCE}, - ["level"] = 23, - ["mana"] = 15, - ["mana_max"] = 40, - ["fail"] = 60, - ["stick"] = - { - ["charge"] = { 3, 5 }, - [TV_WAND] = - { - ["rarity"] = 75, - ["base_level"] = { 1, 20 }, - ["max_level"] = { 20, 50 }, - }, - }, - ["spell"] = function() return convey_teleport_away() end, - ["info"] = function() return convey_teleport_away_info() end, - ["desc"] = { - "Teleports a line of monsters away", - "At level 10 it turns into a ball", - "At level 20 it teleports all monsters in sight" - } -} - -RECALL = add_spell -{ - ["name"] = "Recall", - ["school"] = {SCHOOL_CONVEYANCE}, - ["level"] = 30, - ["mana"] = 25, - ["mana_max"] = 25, - ["fail"] = 60, - ["spell"] = function() return convey_recall() end, - ["info"] = function() return convey_recall_info() end, - ["desc"] = { - "Cast on yourself it will recall you to the surface/dungeon.", - "Cast at a monster you will swap positions with the monster.", - "Cast at an object it will fetch the object to you." - } -} - -PROBABILITY_TRAVEL = add_spell -{ - ["name"] = "Probability Travel", - ["school"] = {SCHOOL_CONVEYANCE}, - ["level"] = 35, - ["mana"] = 30, - ["mana_max"] = 50, - ["fail"] = 90, - ["stick"] = - { - ["charge"] = { 1, 2 }, - [TV_STAFF] = - { - ["rarity"] = 97, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 8, 25 }, - }, - }, - ["inertia"] = { 6, 40 }, - ["spell"] = function() return convey_probability_travel() end, - ["info"] = function() return convey_probability_travel_info() end, - ["desc"] = { - "Renders you immaterial, when you hit a wall you travel through it and", - "instantly appear on the other side of it. You can also float up and down", - "at will" - } -} diff --git a/lib/mods/theme/scpt/s_demon.lua b/lib/mods/theme/scpt/s_demon.lua deleted file mode 100644 index 8bf14c21..00000000 --- a/lib/mods/theme/scpt/s_demon.lua +++ /dev/null @@ -1,166 +0,0 @@ --- handle the demonology school - --- Demonblade -DEMON_BLADE = add_spell -{ - ["name"] = "Demon Blade", - ["school"] = {SCHOOL_DEMON}, - ["level"] = 1, - ["mana"] = 4, - ["mana_max"] = 44, - ["fail"] = 10, - ["random"] = 0, - ["stick"] = - { - ["charge"] = { 3, 7 }, - [TV_WAND] = - { - ["rarity"] = 75, - ["base_level"] = { 1, 17 }, - ["max_level"] = { 20, 40 }, - }, - }, - ["spell"] = function() return demonology_demon_blade() end, - ["info"] = function() return demonology_demon_blade_info() end, - ["desc"] = { - "Imbues your blade with fire to deal more damage", - "At level 30 it deals hellfire damage", - "At level 45 it spreads over a 1 radius zone around your target", - } -} - -DEMON_MADNESS = add_spell -{ - ["name"] = "Demon Madness", - ["school"] = {SCHOOL_DEMON}, - ["level"] = 10, - ["mana"] = 5, - ["mana_max"] = 20, - ["fail"] = 25, - ["random"] = 0, - ["spell"] = function() return demonology_demon_madness() end, - ["info"] = function() return demonology_demon_madness_info() end, - ["desc"] = { - "Fire 2 balls in opposite directions of randomly chaos, confusion or charm", - } -} - -DEMON_FIELD = add_spell -{ - ["name"] = "Demon Field", - ["school"] = {SCHOOL_DEMON}, - ["level"] = 20, - ["mana"] = 20, - ["mana_max"] = 60, - ["fail"] = 60, - ["random"] = 0, - ["spell"] = function() return demonology_demon_field() end, - ["info"] = function() return demonology_demon_field_info() end, - ["desc"] = { - "Fires a cloud of deadly nexus over a radius of 7", - } -} - --- Demonshield - -DOOM_SHIELD = add_spell -{ - ["name"] = "Doom Shield", - ["school"] = {SCHOOL_DEMON}, - ["level"] = 1, - ["mana"] = 2, - ["mana_max"] = 30, - ["fail"] = 10, - ["random"] = 0, - ["spell"] = function() return demonology_doom_shield() end, - ["info"] = function() return demonology_doom_shield_info() end, - ["desc"] = { - "Raises a mirror of pain around you, doing very high damage to your foes", - "that dare hit you, but greatly reduces your armour class", - } -} - -UNHOLY_WORD = add_spell -{ - ["name"] = "Unholy Word", - ["school"] = {SCHOOL_DEMON}, - ["level"] = 25, - ["mana"] = 15, - ["mana_max"] = 45, - ["fail"] = 55, - ["random"] = 0, - ["spell"] = function() return demonology_unholy_word() end, - ["info"] = function() return demonology_unholy_word_info() end, - ["desc"] = { - "Kills a pet to heal you", - "There is a chance that the pet won't die but will turn against you", - "it will decrease with higher level", - } -} - -DEMON_CLOAK = add_spell -{ - ["name"] = "Demon Cloak", - ["school"] = {SCHOOL_DEMON}, - ["level"] = 20, - ["mana"] = 10, - ["mana_max"] = 40, - ["fail"] = 70, - ["random"] = 0, - ["spell"] = function() return demonology_demon_cloak() end, - ["info"] = function() return demonology_demon_cloak_info() end, - ["desc"] = { - "Raises a mirror that can reflect bolts and arrows for a time", - } -} - - --- Demonhorn -DEMON_SUMMON = add_spell -{ - ["name"] = "Summon Demon", - ["school"] = {SCHOOL_DEMON}, - ["level"] = 5, - ["mana"] = 10, - ["mana_max"] = 50, - ["fail"] = 30, - ["random"] = 0, - ["spell"] = function() return demonology_summon_demon() end, - ["info"] = function() return demonology_summon_demon_info() end, - ["desc"] = { - "Summons a leveled demon to your side", - "At level 35 it summons a high demon", - } -} - -DISCHARGE_MINION = add_spell -{ - ["name"] = "Discharge Minion", - ["school"] = {SCHOOL_DEMON}, - ["level"] = 10, - ["mana"] = 20, - ["mana_max"] = 50, - ["fail"] = 30, - ["random"] = 0, - ["spell"] = function() return demonology_discharge_minion() end, - ["info"] = function() return demonology_discharge_minion_info() end, - ["desc"] = { - "The targeted pet will explode in a burst of gravity", - } -} - -CONTROL_DEMON = add_spell -{ - ["name"] = "Control Demon", - ["school"] = {SCHOOL_DEMON}, - ["level"] = 25, - ["mana"] = 30, - ["mana_max"] = 70, - ["fail"] = 55, - ["random"] = 0, - ["spell"] = function() return demonology_control_demon() end, - ["info"] = function() return demonology_control_demon_info() end, - ["desc"] = { - "Attempts to control a demon", - } -} diff --git a/lib/mods/theme/scpt/s_divin.lua b/lib/mods/theme/scpt/s_divin.lua deleted file mode 100644 index e077f1f0..00000000 --- a/lib/mods/theme/scpt/s_divin.lua +++ /dev/null @@ -1,153 +0,0 @@ --- Handles thhe divination school - - -STARIDENTIFY = add_spell -{ - ["name"] = "Greater Identify", - ["school"] = {SCHOOL_DIVINATION}, - ["level"] = 35, - ["mana"] = 30, - ["mana_max"] = 30, - ["fail"] = 80, - ["spell"] = function() return divination_greater_identify() end, - ["info"] = function() return divination_greater_identify_info() end, - ["desc"] = { - "Asks for an object and fully identify it, providing the full list of powers", - "Cast at yourself it will reveal your powers" - } -} - -IDENTIFY = add_spell -{ - ["name"] = "Identify", - ["school"] = {SCHOOL_DIVINATION}, - ["level"] = 8, - ["mana"] = 10, - ["mana_max"] = 50, - ["fail"] = 40, - ["stick"] = - { - ["charge"] = { 7, 10 }, - [TV_STAFF] = - { - ["rarity"] = 45, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 15, 40 }, - }, - }, - ["spell"] = function() return divination_identify() end, - ["info"] = function() return divination_identify_info() end, - ["desc"] = { - "Asks for an object and identifies it", - "At level 17 it identifies all objects in the inventory", - "At level 27 it identifies all objects in the inventory and in a", - "radius on the floor, as well as probing monsters in that radius" - } -} - -VISION = add_spell -{ - ["name"] = "Vision", - ["school"] = {SCHOOL_DIVINATION}, - ["level"] = 15, - ["mana"] = 7, - ["mana_max"] = 55, - ["fail"] = 45, - ["stick"] = - { - ["charge"] = { 4, 6 }, - [TV_STAFF] = - { - ["rarity"] = 60, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 10, 30 }, - }, - }, - ["inertia"] = { 2, 200 }, - ["spell"] = function() return divination_vision() end, - ["info"] = function() return divination_vision_info() end, - ["desc"] = { - "Detects the layout of the surrounding area", - "At level 25 it maps and lights the whole level", - } -} - -SENSEHIDDEN = add_spell -{ - ["name"] = "Sense Hidden", - ["school"] = {SCHOOL_DIVINATION}, - ["level"] = 5, - ["mana"] = 2, - ["mana_max"] = 10, - ["fail"] = 25, - ["stick"] = - { - ["charge"] = { 1, 15 }, - [TV_STAFF] = - { - ["rarity"] = 20, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 10, 50 }, - }, - }, - ["inertia"] = { 1, 10 }, - ["spell"] = function() return divination_sense_hidden() end, - ["info"] = function() return divination_sense_hidden_info() end, - ["desc"] = { - "Detects the traps in a certain radius around you", - "At level 15 it allows you to sense invisible for a while" - } -} - -REVEALWAYS = add_spell -{ - ["name"] = "Reveal Ways", - ["school"] = {SCHOOL_DIVINATION}, - ["level"] = 9, - ["mana"] = 3, - ["mana_max"] = 15, - ["fail"] = 20, - ["stick"] = - { - ["charge"] = { 6, 6 }, - [TV_STAFF] = - { - ["rarity"] = 35, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 25, 50 }, - }, - }, - ["inertia"] = { 1, 10 }, - ["spell"] = function() return divination_reveal_ways() end, - ["info"] = function() return divination_reveal_ways_info() end, - ["desc"] = { - "Detects the doors/stairs/ways in a certain radius around you", - } -} - -SENSEMONSTERS = add_spell -{ - ["name"] = "Sense Monsters", - ["school"] = {SCHOOL_DIVINATION}, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 20, - ["fail"] = 10, - ["stick"] = - { - ["charge"] = { 5, 10 }, - [TV_STAFF] = - { - ["rarity"] = 37, - ["base_level"] = { 1, 10 }, - ["max_level"] = { 15, 40 }, - }, - }, - ["inertia"] = { 1, 10 }, - ["spell"] = function() return divination_sense_monsters() end, - ["info"] = function() return divination_sense_monsters_info() end, - ["desc"] = { - "Detects all monsters near you", - "At level 30 it allows you to sense monster minds for a while" - } -} diff --git a/lib/mods/theme/scpt/s_earth.lua b/lib/mods/theme/scpt/s_earth.lua deleted file mode 100644 index 9825fc84..00000000 --- a/lib/mods/theme/scpt/s_earth.lua +++ /dev/null @@ -1,123 +0,0 @@ --- The earth school - -STONESKIN = add_spell -{ - ["name"] = "Stone Skin", - ["school"] = SCHOOL_EARTH, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 50, - ["fail"] = 10, - ["inertia"] = { 2, 50 }, - ["spell"] = function() return earth_stone_skin() end, - ["info"] = function() return earth_stone_skin_info() end, - ["desc"] = { - "Creates a shield of earth around you to protect you", - "At level 25 it starts dealing damage to attackers" - } -} - -DIG = add_spell -{ - ["name"] = "Dig", - ["school"] = SCHOOL_EARTH, - ["level"] = 12, - ["mana"] = 14, - ["mana_max"] = 14, - ["fail"] = 20, - ["stick"] = - { - ["charge"] = { 15, 5 }, - [TV_WAND] = - { - ["rarity"] = 25, - ["base_level"] = { 1, 1 }, - ["max_level"] = { 1, 1 }, - }, - }, - ["spell"] = function() return earth_dig() end, - ["info"] = function() return earth_dig_info() end, - ["desc"] = { - "Digs a hole in a wall much faster than any shovels", - } -} - -STONEPRISON = add_spell -{ - ["name"] = "Stone Prison", - ["school"] = SCHOOL_EARTH, - ["level"] = 25, - ["mana"] = 30, - ["mana_max"] = 50, - ["fail"] = 65, - ["stick"] = - { - ["charge"] = { 5, 3 }, - [TV_WAND] = - { - ["rarity"] = 57, - ["base_level"] = { 1, 3 }, - ["max_level"] = { 5, 20 }, - }, - }, - ["spell"] = function() return earth_stone_prison() end, - ["info"] = function() return earth_stone_prison_info() end, - ["desc"] = { - "Creates a prison of walls around you", - "At level 10 it allows you to target a monster" - } -} - -STRIKE = add_spell -{ - ["name"] = "Strike", - ["school"] = {SCHOOL_EARTH}, - ["level"] = 30, - ["mana"] = 30, - ["mana_max"] = 50, - ["fail"] = 60, - ["stick"] = - { - ["charge"] = { 2, 6 }, - [TV_WAND] = - { - ["rarity"] = 635, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 10, 50 }, - }, - }, - ["spell"] = function() return earth_strike() end, - ["info"] = function() return earth_strike_info() end, - ["desc"] = { - "Creates a micro-ball of force that will push monsters backwards", - "If the monster is caught near a wall, it'll be crushed against it", - "At level 12 it turns into a ball of radius 1" - } -} - -SHAKE = add_spell -{ - ["name"] = "Shake", - ["school"] = {SCHOOL_EARTH}, - ["level"] = 27, - ["mana"] = 25, - ["mana_max"] = 30, - ["fail"] = 60, - ["stick"] = - { - ["charge"] = { 5, 10 }, - [TV_STAFF] = - { - ["rarity"] = 75, - ["base_level"] = { 1, 3 }, - ["max_level"] = { 9, 20 }, - }, - }, - ["inertia"] = { 2, 50 }, - ["spell"] = function() return earth_shake() end, - ["info"] = function() return earth_shake_info() end, - ["desc"] = { - "Creates a localised earthquake", - "At level 10 it can be targeted at any location" - } -} diff --git a/lib/mods/theme/scpt/s_eru.lua b/lib/mods/theme/scpt/s_eru.lua deleted file mode 100644 index d61b6118..00000000 --- a/lib/mods/theme/scpt/s_eru.lua +++ /dev/null @@ -1,88 +0,0 @@ --- Handle Eru Iluvatar magic school - -ERU_SEE = add_spell -{ - ["name"] = "See the Music", - ["school"] = {SCHOOL_ERU}, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 50, - ["fail"] = 20, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - -- Unnafected by blindness - ["blind"] = FALSE, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return eru_see_the_music() end, - ["info"] = function() return eru_see_the_music_info() end, - ["desc"] = { - "Allows you to 'see' the Great Music from which the world", - "originates, allowing you to see unseen things", - "At level 10 it allows you to see your surroundings", - "At level 20 it allows you to cure blindness", - "At level 30 it allows you to fully see all the level" - } -} - -ERU_LISTEN = add_spell -{ - ["name"] = "Listen to the Music", - ["school"] = {SCHOOL_ERU}, - ["level"] = 7, - ["mana"] = 15, - ["mana_max"] = 200, - ["fail"] = 25, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return eru_listen_to_the_music() end, - ["info"] = function() return eru_listen_to_the_music_info() end, - ["desc"] = { - "Allows you to listen to the Great Music from which the world", - "originates, allowing you to understand the meaning of things", - "At level 14 it allows you to identify all your pack", - "At level 30 it allows you to identify all items on the level", - } -} - -ERU_UNDERSTAND = add_spell -{ - ["name"] = "Know the Music", - ["school"] = {SCHOOL_ERU}, - ["level"] = 30, - ["mana"] = 200, - ["mana_max"] = 600, - ["fail"] = 50, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return eru_know_the_music() end, - ["info"] = function() return eru_know_the_music_info() end, - ["desc"] = { - "Allows you to understand the Great Music from which the world", - "originates, allowing you to know the full abilities of things", - "At level 10 it allows you to *identify* all your pack", - } -} - -ERU_PROT = add_spell -{ - ["name"] = "Lay of Protection", - ["school"] = {SCHOOL_ERU}, - ["level"] = 35, - ["mana"] = 400, - ["mana_max"] = 400, - ["fail"] = 80, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return eru_lay_of_protection() end, - ["info"] = function() return eru_lay_of_protection_info() end, - ["desc"] = { - "Creates a circle of safety around you", - } -} diff --git a/lib/mods/theme/scpt/s_fire.lua b/lib/mods/theme/scpt/s_fire.lua deleted file mode 100644 index 37a75032..00000000 --- a/lib/mods/theme/scpt/s_fire.lua +++ /dev/null @@ -1,134 +0,0 @@ --- handle the fire school - -GLOBELIGHT = add_spell -{ - ["name"] = "Globe of Light", - ["school"] = {SCHOOL_FIRE}, - ["level"] = 1, - ["mana"] = 2, - ["mana_max"] = 15, - ["fail"] = 10, - ["stick"] = - { - ["charge"] = { 10, 5 }, - [TV_STAFF] = - { - ["rarity"] = 7, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 10, 45 }, - }, - }, - ["inertia"] = { 1, 40 }, - ["spell"] = function() return fire_globe_of_light() end, - ["info"] = function() return fire_globe_of_light_info() end, - ["desc"] = { - "Creates a globe of pure light", - "At level 3 it starts damaging monsters", - "At level 15 it starts creating a more powerful kind of light", - } -} - -FIREFLASH = add_spell -{ - ["name"] = "Fireflash", - ["school"] = {SCHOOL_FIRE}, - ["level"] = 10, - ["mana"] = 5, - ["mana_max"] = 70, - ["fail"] = 35, - ["stick"] = - { - ["charge"] = { 5, 5 }, - [TV_WAND] = - { - ["rarity"] = 35, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 15, 35 }, - }, - }, - ["spell"] = function() return fire_fireflash() end, - ["info"] = function() return fire_fireflash_info() end, - ["desc"] = { - "Conjures a ball of fire to burn your foes to ashes", - "At level 20 it turns into a ball of holy fire" - } -} - -FIERYAURA = add_spell -{ - ["name"] = "Fiery Shield", - ["school"] = {SCHOOL_FIRE}, - ["level"] = 20, - ["mana"] = 20, - ["mana_max"] = 60, - ["fail"] = 50, - ["stick"] = - { - ["charge"] = { 3, 5 }, - [TV_STAFF] = - { - ["rarity"] = 50, - ["base_level"] = { 1, 10 }, - ["max_level"] = { 5, 40 }, - }, - }, - ["inertia"] = { 2, 15 }, - ["spell"] = function() return fire_fiery_shield() end, - ["info"] = function() return fire_fiery_shield_info() end, - ["desc"] = { - "Creates a shield of fierce flames around you", - "At level 8 it turns into a greater kind of flame that can not be resisted" - } -} - -FIREWALL = add_spell -{ - ["name"] = "Firewall", - ["school"] = {SCHOOL_FIRE}, - ["level"] = 15, - ["mana"] = 25, - ["mana_max"] = 100, - ["fail"] = 40, - ["stick"] = - { - ["charge"] = { 4, 5 }, - [TV_WAND] = - { - ["rarity"] = 55, - ["base_level"] = { 1, 10 }, - ["max_level"] = { 5, 40 }, - }, - }, - ["spell"] = function() return fire_firewall() end, - ["info"] = function() return fire_firewall_info() end, - ["desc"] = { - "Creates a fiery wall to incinerate monsters stupid enough to attack you", - "At level 6 it turns into a wall of hell fire" - } -} - -FIREGOLEM = add_spell -{ - ["name"] = "Fire Golem", - ["school"] = {SCHOOL_FIRE, SCHOOL_MIND}, - ["level"] = 7, - ["mana"] = 16, - ["mana_max"] = 70, - ["fail"] = 40, - ["spell"] = function() return fire_golem() end, - ["info"] = function() return fire_golem_info() end, - ["desc"] = { - "Creates a fiery golem and controls it", - "During the control the available keylist is:", - "Movement keys: movement of the golem(depending on its speed", - " it can move more than one square)", - ", : pickup all items on the floor", - "d : drop all carried items", - "i : list all carried items", - "m : end the possession/use golem powers", - "Most of the other keys are disabled, you cannot interact with your", - "real body while controlling the golem", - "But to cast the spell you will need a lantern or a wooden torch to", - "Create the golem from" - } -} diff --git a/lib/mods/theme/scpt/s_geom.lua b/lib/mods/theme/scpt/s_geom.lua deleted file mode 100644 index d250f38d..00000000 --- a/lib/mods/theme/scpt/s_geom.lua +++ /dev/null @@ -1,177 +0,0 @@ --- Geomancy school - -CALL_THE_ELEMENTS = add_spell -{ - ["name"] = "Call the Elements", - ["school"] = {SCHOOL_GEOMANCY}, - ["level"] = 1, - ["mana"] = 2, - ["mana_max"] = 20, - ["fail"] = 10, - -- Unnafected by blindness - ["blind"] = FALSE, - ["random"] = 0, - ["spell"] = function() return geomancy_call_the_elements() end, - ["info"] = function() return geomancy_call_the_elements_info() end, - ["desc"] = { - "Randomly creates various elements around you", - "Each type of element chance is controlled by your level", - "in the corresponding skill", - "At level 17 it can be targeted", - } -} - -CHANNEL_ELEMENTS = add_spell -{ - ["name"] = "Channel Elements", - ["school"] = {SCHOOL_GEOMANCY}, - ["level"] = 3, - ["mana"] = 3, - ["mana_max"] = 30, - ["fail"] = 20, - -- Unnafected by blindness - ["blind"] = FALSE, - ["random"] = 0, - ["spell"] = function() return geomancy_channel_elements() end, - ["info"] = function() return geomancy_channel_elements_info() end, - ["desc"] = { - "Draws on the caster's immediate environs to form an attack or other effect.", - "Grass/Flower heals.", - "Water creates water bolt attacks.", - "Ice creates ice bolt attacks.", - "Sand creates a wall of thick, blinding, burning sand around you.", - "Lava creates fire bolt attacks.", - "Deep lava creates fire ball attacks.", - "Chasm creates darkness bolt attacks.", - "At Earth level 18, darkness becomes nether.", - "At Water level 8, water attacks become beams with a striking effect.", - "At Water level 12, ice attacks become balls of ice shards.", - "At Water level 18, water attacks push monsters back.", - "At Fire level 15, fire become hellfire.", - } -} - -ELEMENTAL_WAVE = add_spell -{ - ["name"] = "Elemental Wave", - ["school"] = {SCHOOL_GEOMANCY}, - ["level"] = 15, - ["mana"] = 15, - ["mana_max"] = 50, - ["fail"] = 20, - -- Unnafected by blindness - ["blind"] = FALSE, - ["random"] = 0, - ["spell"] = function() return geomancy_elemental_wave() end, - ["info"] = function() return geomancy_elemental_wave_info() end, - ["desc"] = { - "Draws on an adjacent special square to project a slow-moving", - "wave of that element in that direction", - "Abyss squares cannot be channeled into a wave.", - } -} - -VAPORIZE = add_spell -{ - ["name"] = "Vaporize", - ["school"] = {SCHOOL_GEOMANCY}, - ["level"] = 4, - ["mana"] = 3, - ["mana_max"] = 30, - ["fail"] = 15, - -- Unnafected by blindness - ["blind"] = FALSE, - -- Must have at least 4 Air - ["random"] = 0, - ["depend"] = function() return geomancy_vaporize_depends() end, - ["spell"] = function() return geomancy_vaporize() end, - ["info"] = function() return geomancy_vaporize_info() end, - ["desc"] = { - "Draws upon your immediate environs to form a cloud of damaging vapors", - } -} - -GEOLYSIS = add_spell -{ - ["name"] = "Geolysis", - ["school"] = {SCHOOL_GEOMANCY}, - ["level"] = 7, - ["mana"] = 15, - ["mana_max"] = 40, - ["fail"] = 15, - -- Unnafected by blindness - ["blind"] = FALSE, - ["random"] = 0, - -- Must have at least 7 Earth - ["depend"] = function() return geomancy_geolysis_depends() end, - ["spell"] = function() return geomancy_geolysis() end, - ["info"] = function() return geomancy_geolysis_info() end, - ["desc"] = { - "Burrows deeply and slightly at random into a wall,", - "leaving behind tailings of various different sorts of walls in the passage.", - } -} - -DRIPPING_TREAD = add_spell -{ - ["name"] = "Dripping Tread", - ["school"] = {SCHOOL_GEOMANCY}, - ["level"] = 10, - ["mana"] = 15, - ["mana_max"] = 25, - ["fail"] = 15, - -- Unnafected by blindness - ["blind"] = FALSE, - ["random"] = 0, - -- Must have at least 10 Water - ["depend"] = function() return geomancy_dripping_tread_depends() end, - ["spell"] = function() return geomancy_dripping_tread() end, - ["info"] = function() return geomancy_dripping_tread_info() end, - ["desc"] = { - "Causes you to leave random elemental forms behind as you walk", - } -} - -GROW_BARRIER = add_spell -{ - ["name"] = "Grow Barrier", - ["school"] = {SCHOOL_GEOMANCY}, - ["level"] = 12, - ["mana"] = 30, - ["mana_max"] = 40, - ["fail"] = 15, - -- Unnafected by blindness - ["blind"] = FALSE, - ["random"] = 0, - -- Must have at least 12 Earth - ["depend"] = function() return geomancy_grow_barrier_depends() end, - ["spell"] = function() return geomancy_grow_barrier() end, - ["info"] = function() return geomancy_grow_barrier_info() end, - ["desc"] = { - "Creates impassable terrain (walls, trees, etc.) around you.", - "At level 20 it can be projected around another area.", - } -} - -ELEMENTAL_MINION = add_spell -{ - ["name"] = "Elemental Minion", - ["school"] = {SCHOOL_GEOMANCY}, - ["level"] = 20, - ["mana"] = 40, - ["mana_max"] = 80, - ["fail"] = 25, - -- Unnafected by blindness - ["random"] = 0, - -- Must have at least 12 Earth - ["spell"] = function() return geomancy_elemental_minion() end, - ["info"] = function() return geomancy_elemental_minion_info() end, - ["desc"] = { - "Summons a minion from a nearby element.", - "Walls can summon Earth elmentals, Xorns and Xarens", - "Dark Pits can summon Air elementals, Ancient blue dragons, Great Storm Wyrms", - "and Sky Drakes", - "Sandwalls and lava can summon Fire elementals and Ancient red dragons", - "Icewall, and water can summon Water elementals, Water trolls and Water demons", - } -} diff --git a/lib/mods/theme/scpt/s_mana.lua b/lib/mods/theme/scpt/s_mana.lua deleted file mode 100644 index 67126fb2..00000000 --- a/lib/mods/theme/scpt/s_mana.lua +++ /dev/null @@ -1,89 +0,0 @@ --- The mana school - -MANATHRUST = add_spell -{ - ["name"] = "Manathrust", - ["school"] = SCHOOL_MANA, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 25, - ["fail"] = 10, - ["stick"] = - { - ["charge"] = { 7, 10 }, - [TV_WAND] = - { - ["rarity"] = 5, - ["base_level"] = { 1, 20 }, - ["max_level"] = { 15, 33 }, - }, - }, - ["spell"] = function() return mana_manathrust() end, - ["info"] = function() return mana_manathrust_info() end, - ["desc"] = { - "Conjures up mana into a powerful bolt", - "The damage is irresistible and will increase with level" - } -} - -DELCURSES = add_spell -{ - ["name"] = "Remove Curses", - ["school"] = SCHOOL_MANA, - ["level"] = 10, - ["mana"] = 20, - ["mana_max"] = 40, - ["fail"] = 30, - ["stick"] = - { - ["charge"] = { 3, 8 }, - [TV_STAFF] = - { - ["rarity"] = 70, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 15, 50 }, - }, - }, - ["inertia"] = { 1, 10 }, - ["spell"] = function() return mana_remove_curses() end, - ["info"] = function() return mana_remove_curses_info() end, - ["desc"] = { - "Remove curses of worn objects", - "At level 20 switches to *remove curses*" - } -} - -RESISTS = add_spell -{ - ["name"] = "Elemental Shield", - ["school"] = SCHOOL_MANA, - ["level"] = 20, - ["mana"] = 17, - ["mana_max"] = 20, - ["fail"] = 40, - ["inertia"] = { 2, 25 }, - ["spell"] = function() return mana_elemental_shield() end, - ["info"] = function() return mana_elemental_shield_info() end, - ["desc"] = { - "Provide resistances to the four basic elements", - } -} - -MANASHIELD = add_spell -{ - ["name"] = "Disruption Shield", - ["school"] = SCHOOL_MANA, - ["level"] = 45, - ["mana"] = 50, - ["mana_max"] = 50, - ["fail"] = 90, - ["inertia"] = { 9, 10}, - ["spell"] = function() return mana_disruption_shield() end, - ["info"] = function() return mana_disruption_shield_info() end, - ["desc"] = { - "Uses mana instead of hp to take damage", - "At level 5 switches to Globe of Invulnerability.", - "The spell breaks as soon as a melee, shooting, throwing or magical", - "skill action is attempted, and lasts only a short time." - } -} diff --git a/lib/mods/theme/scpt/s_mandos.lua b/lib/mods/theme/scpt/s_mandos.lua deleted file mode 100644 index 48b73c27..00000000 --- a/lib/mods/theme/scpt/s_mandos.lua +++ /dev/null @@ -1,86 +0,0 @@ --- Spells for the school of Mandos - -BOOK_MANDOS = 66 - --- "Tears of Luthien" based on Holy Word from T-Plus -MANDOS_TEARS_LUTHIEN = add_spell -{ - ["name"] = "Tears of Luthien", - ["school"] = {SCHOOL_MANDOS}, - ["level"] = 5, - ["mana"] = 10, - ["mana_max"] = 100, - ["fail"] = 25, - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return mandos_tears_of_luthien_spell() end, - ["info"] = function() return mandos_tears_of_luthien_info() end, - ["desc"] = { - "Calls upon the spirit of Luthien to ask Mandos for healing and succour." - } -} - --- "Spirit of the Feanturi" based on Restore Mind from T-Plus -MANDOS_SPIRIT_FEANTURI = add_spell -{ - ["name"] = "Feanturi", - ["school"] = {SCHOOL_MANDOS}, - ["level"] = 10, - ["mana"] = 40, - ["mana_max"] = 200, - ["fail"] = 50, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return mandos_spirit_of_the_feanturi_spell() end, - ["info"] = function() return mandos_spirit_of_the_feanturi_info() end, - ["desc"] = { - "Channels the power of Mandos to cure fear and confusion.", - "At level 20 it restores lost INT and WIS", - "At level 30 it cures hallucinations and restores a percentage of lost sanity" - } -} - --- "Tale of Doom" based on Foretell from T-Plus -MANDOS_TALE_DOOM = add_spell -{ - ["name"] = "Tale of Doom", - ["school"] = {SCHOOL_MANDOS}, - ["level"] = 25, - ["mana"] = 60, - ["mana_max"] = 300, - ["stat"] = A_WIS, - ["fail"] = 75, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return mandos_tale_of_doom_spell() end, - ["info"] = function() return mandos_tale_of_doom_info() end, - ["desc"] = { - "Allows you to predict the future for a short time." - } -} - --- "Call to the Halls" based on Call Blessed Soul from T-Plus -MANDOS_CALL_HALLS= add_spell -{ - ["name"] = "Call to the Halls", - ["school"] = {SCHOOL_MANDOS}, - ["level"] = 30, - ["mana"] = 80, - ["mana_max"] = 400, - ["fail"] = 95, - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return mandos_call_to_the_halls_spell() end, - ["info"] = function() return mandos_call_to_the_halls_info() end, - ["desc"] = { - "Summons a leveled spirit from the Halls of Mandos", - "to fight for you." - - } -} \ No newline at end of file diff --git a/lib/mods/theme/scpt/s_manwe.lua b/lib/mods/theme/scpt/s_manwe.lua deleted file mode 100644 index 189f50ff..00000000 --- a/lib/mods/theme/scpt/s_manwe.lua +++ /dev/null @@ -1,84 +0,0 @@ --- Handle Manwe Sulimo magic school - -MANWE_SHIELD = add_spell -{ - ["name"] = "Wind Shield", - ["school"] = {SCHOOL_MANWE}, - ["level"] = 10, - ["mana"] = 100, - ["mana_max"] = 500, - ["fail"] = 30, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return manwe_wind_shield() end, - ["info"] = function() return manwe_wind_shield_info() end, - ["desc"] = { - "It surrounds you with a shield of wind that deflects blows from evil monsters", - "At level 10 it increases your armour rating", - "At level 20 it retaliates against monsters that melee you", - } -} - -MANWE_AVATAR = add_spell -{ - ["name"] = "Avatar", - ["school"] = {SCHOOL_MANWE}, - ["level"] = 35, - ["mana"] = 1000, - ["mana_max"] = 1000, - ["fail"] = 80, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return manwe_avatar() end, - ["info"] = function() return manwe_avatar_info() end, - ["desc"] = { - "It turns you into a full grown Maia", - } -} - -MANWE_BLESS = add_spell -{ - ["name"] = "Manwe's Blessing", - ["school"] = {SCHOOL_MANWE}, - ["level"] = 1, - ["mana"] = 10, - ["mana_max"] = 100, - ["fail"] = 20, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return manwe_blessing() end, - ["info"] = function() return manwe_blessing_info() end, - ["desc"] = { - "Manwe's Blessing removes your fears, blesses you and surrounds you with", - "holy light", - "At level 10 it also grants heroism", - "At level 20 it also grants super heroism", - "At level 30 it also grants holy luck and life protection", - } -} - -MANWE_CALL = add_spell -{ - ["name"] = "Manwe's Call", - ["school"] = {SCHOOL_MANWE}, - ["level"] = 20, - ["mana"] = 200, - ["mana_max"] = 500, - ["fail"] = 40, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return manwe_call() end, - ["info"] = function() return manwe_call_info() end, - ["desc"] = { - "Manwe's Call summons a Great Eagle to help you battle the forces", - "of Morgoth" - } -} diff --git a/lib/mods/theme/scpt/s_melkor.lua b/lib/mods/theme/scpt/s_melkor.lua deleted file mode 100644 index 701dca7a..00000000 --- a/lib/mods/theme/scpt/s_melkor.lua +++ /dev/null @@ -1,64 +0,0 @@ --- handle the melkor school - -MELKOR_CURSE = add_spell -{ - ["name"] = "Curse", - ["school"] = {SCHOOL_MELKOR}, - ["level"] = 1, - ["mana"] = 50, - ["mana_max"] = 300, - ["fail"] = 20, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return melkor_curse() end, - ["info"] = function() return melkor_curse_info() end, - ["desc"] = { - "It curses a monster, reducing its melee power", - "At level 5 it can be auto-casted (with no piety cost) while fighting", - "At level 15 it also reduces armor", - "At level 25 it also reduces speed", - "At level 35 it also reduces max life (but it is never fatal)", - } -} - -MELKOR_CORPSE_EXPLOSION = add_spell -{ - ["name"] = "Corpse Explosion", - ["school"] = {SCHOOL_MELKOR}, - ["level"] = 10, - ["mana"] = 100, - ["mana_max"] = 500, - ["fail"] = 45, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return melkor_corpse_explosion() end, - ["info"] = function() return melkor_corpse_explosion_info() end, - ["desc"] = { - "It makes corpses in an area around you explode for a percent of their", - "hit points as damage", - } -} - -MELKOR_MIND_STEAL = add_spell -{ - ["name"] = "Mind Steal", - ["school"] = {SCHOOL_MELKOR}, - ["level"] = 20, - ["mana"] = 1000, - ["mana_max"] = 3000, - ["fail"] = 90, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return melkor_mind_steal() end, - ["info"] = function() return melkor_mind_steal_info() end, - ["desc"] = { - "It allows your spirit to temporarily leave your own body, which will", - "be vulnerable, to control one of your enemies body." - } -} diff --git a/lib/mods/theme/scpt/s_meta.lua b/lib/mods/theme/scpt/s_meta.lua deleted file mode 100644 index 9040e3af..00000000 --- a/lib/mods/theme/scpt/s_meta.lua +++ /dev/null @@ -1,104 +0,0 @@ --- handle the meta school - -RECHARGE = add_spell -{ - ["name"] = "Recharge", - ["school"] = {SCHOOL_META}, - ["level"] = 5, - ["mana"] = 10, - ["mana_max"] = 100, - ["fail"] = 20, - ["spell"] = function() return meta_recharge() end, - ["info"] = function() return meta_recharge_info() end, - ["desc"] = { - "Taps on the ambient mana to recharge an object's power (charges or mana)", - } -} - -SPELLBINDER = add_spell -{ - ["name"] = "Spellbinder", - ["school"] = {SCHOOL_META}, - ["level"] = 20, - ["mana"] = 100, - ["mana_max"] = 300, - ["fail"] = 85, - ["spell"] = function() return meta_spellbinder() end, - ["info"] = function() return meta_spellbinder_info() end, - ["desc"] = { - "Stores spells in a trigger.", - "When the condition is met all spells fire off at the same time", - "This spell takes a long time to cast so you are advised to prepare it", - "in a safe area.", - "Also it will use the mana for the Spellbinder and the mana for the", - "selected spells" - } -} - -DISPERSEMAGIC = add_spell -{ - ["name"] = "Disperse Magic", - ["school"] = {SCHOOL_META}, - ["level"] = 15, - ["mana"] = 30, - ["mana_max"] = 60, - ["fail"] = 40, - -- Unnafected by blindness - ["blind"] = FALSE, - -- Unnafected by confusion - ["confusion"] = FALSE, - ["stick"] = - { - ["charge"] = { 5, 5 }, - [TV_WAND] = - { - ["rarity"] = 25, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 5, 40 }, - }, - }, - ["inertia"] = { 1, 5 }, - ["spell"] = function() return meta_disperse_magic() end, - ["info"] = function() return meta_disperse_magic_info() end, - ["desc"] = { - "Dispels a lot of magic that can affect you, be it good or bad", - "Level 1: blindness and light", - "Level 5: confusion and hallucination", - "Level 10: speed (both bad or good) and light speed", - "Level 15: stunning, meditation, cuts", - "Level 20: hero, super hero, bless, shields, afraid, parasites, mimicry", - } -} - -TRACKER = add_spell -{ - ["name"] = "Tracker", - ["school"] = {SCHOOL_META, SCHOOL_CONVEYANCE}, - ["level"] = 30, - ["mana"] = 50, - ["mana_max"] = 50, - ["fail"] = 95, - ["spell"] = function() return meta_tracker() end, - ["info"] = function() return meta_tracker_info() end, - ["desc"] = { - "Tracks down the last teleportation that happened on the level and teleports", - "you to it", - } -} - -INERTIA_CONTROL = add_spell -{ - ["name"] = "Inertia Control", - ["school"] = {SCHOOL_META}, - ["level"] = 37, - ["mana"] = 300, - ["mana_max"] = 700, - ["fail"] = 95, - ["spell"] = function() return meta_inertia_control() end, - ["info"] = function() return meta_inertia_control_info() end, - ["desc"] = { - "Changes the energy flow of a spell to be continuously recasted", - "at a given interval. The inertia controlled spell reduces your", - "maximum mana by four times its cost.", - } -} diff --git a/lib/mods/theme/scpt/s_mind.lua b/lib/mods/theme/scpt/s_mind.lua deleted file mode 100644 index 7f24709b..00000000 --- a/lib/mods/theme/scpt/s_mind.lua +++ /dev/null @@ -1,88 +0,0 @@ --- handle the mind school - -CHARM = add_spell -{ - ["name"] = "Charm", - ["school"] = {SCHOOL_MIND}, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 20, - ["fail"] = 10, - ["stick"] = - { - ["charge"] = { 7, 5 }, - [TV_WAND] = - { - ["rarity"] = 35, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 20, 40 }, - }, - }, - ["spell"] = function() return mind_charm() end, - ["info"] = function() return mind_charm_info() end, - ["desc"] = { - "Tries to manipulate the mind of a monster to make it friendly", - "At level 15 it turns into a ball", - "At level 35 it affects all monsters in sight" - } -} - -CONFUSE = add_spell -{ - ["name"] = "Confuse", - ["school"] = {SCHOOL_MIND}, - ["level"] = 5, - ["mana"] = 5, - ["mana_max"] = 30, - ["fail"] = 20, - ["stick"] = - { - ["charge"] = { 3, 4 }, - [TV_WAND] = - { - ["rarity"] = 45, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 20, 40 }, - }, - }, - ["spell"] = function() return mind_confuse() end, - ["info"] = function() return mind_confuse_info() end, - ["desc"] = { - "Tries to manipulate the mind of a monster to confuse it", - "At level 15 it turns into a ball", - "At level 35 it affects all monsters in sight" - } -} - -ARMOROFFEAR = add_spell -{ - ["name"] = "Armor of Fear", - ["school"] = SCHOOL_MIND, - ["level"] = 10, - ["mana"] = 10, - ["mana_max"] = 50, - ["fail"] = 35, - ["inertia"] = { 2, 20 }, - ["spell"] = function() return mind_armor_of_fear() end, - ["info"] = function() return mind_armor_of_fear_info() end, - ["desc"] = { - "Creates a shield of pure fear around you. Any monster attempting to hit you", - "must save or flee", - } -} - -STUN = add_spell -{ - ["name"] = "Stun", - ["school"] = {SCHOOL_MIND}, - ["level"] = 15, - ["mana"] = 10, - ["mana_max"] = 90, - ["fail"] = 45, - ["spell"] = function() return mind_stun() end, - ["info"] = function() return mind_stun_info() end, - ["desc"] = { - "Tries to manipulate the mind of a monster to stun it", - "At level 20 it turns into a ball", - } -} diff --git a/lib/mods/theme/scpt/s_music.lua b/lib/mods/theme/scpt/s_music.lua deleted file mode 100644 index 45255485..00000000 --- a/lib/mods/theme/scpt/s_music.lua +++ /dev/null @@ -1,268 +0,0 @@ --- handle the music school --- *ALL* lasting spell must return the mana cost in the lasting function - -MUSIC_STOP = add_spell -{ - ["name"] = "Stop singing(I)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 1, - ["mana"] = 0, - ["mana_max"] = 0, - ["fail"] = -400, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 1, - ["blind"] = FALSE, - ["spell"] = function() return music_stop_singing_spell() end, - ["info"] = function() return music_stop_singing_info() end, - ["desc"] = { - "Stops the current song, if any." - } -} - ---- Drums -MUSIC_HOLD = add_spell -{ - ["name"] = "Holding Pattern(I)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 10, - ["fail"] = 20, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 1, - ["blind"] = FALSE, - ["lasting"] = function() return music_holding_pattern_lasting() end, - ["spell"] = function() return music_holding_pattern_spell() end, - ["info"] = function() return music_holding_pattern_info() end, - ["desc"] = { - "Slows down all monsters listening the song.", - "Consumes the amount of mana each turn.", - } -} - -MUSIC_CONF = add_spell -{ - ["name"] = "Illusion Pattern(II)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 5, - ["mana"] = 2, - ["mana_max"] = 15, - ["fail"] = 30, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 2, - ["blind"] = FALSE, - ["lasting"] = function() return music_illusion_pattern_lasting() end, - ["spell"] = function() return music_illusion_pattern_spell() end, - ["info"] = function() return music_illusion_pattern_info() end, - ["desc"] = { - "Tries to confuse all monsters listening the song.", - "Consumes the amount of mana each turn.", - } -} - -MUSIC_STUN = add_spell -{ - ["name"] = "Stun Pattern(IV)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 10, - ["mana"] = 3, - ["mana_max"] = 25, - ["fail"] = 45, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 4, - ["blind"] = FALSE, - ["lasting"] = function() return music_stun_pattern_lasting() end, - ["spell"] = function() return music_stun_pattern_spell() end, - ["info"] = function() return music_stun_pattern_info() end, - ["desc"] = { - "Stuns all monsters listening the song.", - "Consumes the amount of mana each turn.", - } -} - ---- Harps -MUSIC_LITE = add_spell -{ - ["name"] = "Song of the Sun(I)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 1, - ["fail"] = 20, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["blind"] = FALSE, - ["pval"] = 1, - ["lasting"] = function() return music_song_of_the_sun_lasting() end, - ["spell"] = function() return music_song_of_the_sun_spell() end, - ["info"] = function() return music_song_of_the_sun_info() end, - ["desc"] = { - "Provides light as long as you sing.", - "Consumes the amount of mana each turn.", - } -} - -MUSIC_HEAL = add_spell -{ - ["name"] = "Flow of Life(II)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 7, - ["mana"] = 5, - ["mana_max"] = 30, - ["fail"] = 35, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 2, - ["lasting"] = function() return music_flow_of_life_lasting() end, - ["spell"] = function() return music_flow_of_life_spell() end, - ["info"] = function() return music_flow_of_life_info() end, - ["desc"] = { - "Heals you as long as you sing.", - "Consumes the amount of mana each turn.", - } -} - -MUSIC_HERO = add_spell -{ - ["name"] = "Heroic Ballad(II)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 10, - ["mana"] = 4, - ["mana_max"] = 14, - ["fail"] = 45, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 2, - ["lasting"] = function() return music_heroic_ballad_lasting() end, - ["spell"] = function() return music_heroic_ballad_spell() end, - ["info"] = function() return music_heroic_ballad_info() end, - ["desc"] = { - "Increases melee accuracy", - "At level 10 it increases it even more and reduces armour a bit", - "At level 20 it increases it again", - "At level 25 it grants protection against chaos and confusion", - "Consumes the amount of mana each turn.", - } -} - -MUSIC_TIME = add_spell -{ - ["name"] = "Hobbit Melodies(III)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 20, - ["mana"] = 10, - ["mana_max"] = 30, - ["fail"] = 70, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 3, - ["lasting"] = function() return music_hobbit_melodies_lasting() end, - ["spell"] = function() return music_hobbit_melodies_spell() end, - ["info"] = function() return music_hobbit_melodies_info() end, - ["desc"] = { - "Greatly increases your reflexes allowing you to block more melee blows.", - "At level 15 it also makes you faster.", - "Consumes the amount of mana each turn.", - } -} - -MUSIC_MIND = add_spell -{ - ["name"] = "Clairaudience(IV)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 25, - ["mana"] = 15, - ["mana_max"] = 30, - ["fail"] = 75, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 4, - ["lasting"] = function() return music_clairaudience_lasting() end, - ["spell"] = function() return music_clairaudience_spell() end, - ["info"] = function() return music_clairaudience_info() end, - ["desc"] = { - "Allows you to sense monster minds as long as you sing.", - "At level 10 it identifies all objects in a radius on the floor,", - "as well as probing monsters in that radius.", - "Consumes the amount of mana each turn.", - } -} - ---- Horns - -MUSIC_BLOW = add_spell -{ - ["name"] = "Blow(I)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 4, - ["mana"] = 3, - ["mana_max"] = 30, - ["fail"] = 20, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 1, - ["spell"] = function() return music_blow_spell() end, - ["info"] = function() return music_blow_info() end, - ["desc"] = { - "Produces a powerful, blowing, sound all around you.", - } -} - -MUSIC_WIND = add_spell -{ - ["name"] = "Gush of Wind(II)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 14, - ["mana"] = 15, - ["mana_max"] = 45, - ["fail"] = 30, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 2, - ["spell"] = function() return music_gush_of_wind_spell() end, - ["info"] = function() return music_gush_of_wind_info() end, - ["desc"] = { - "Produces a outgoing gush of wind that sends monsters away.", - } -} - -MUSIC_YLMIR = add_spell -{ - ["name"] = "Horns of Ylmir(III)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 20, - ["mana"] = 25, - ["mana_max"] = 30, - ["fail"] = 20, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 3, - ["spell"] = function() return music_horns_of_ylmir_spell() end, - ["info"] = function() return music_horns_of_ylmir_info() end, - ["desc"] = { - "Produces an earth shaking sound.", - } -} - -MUSIC_AMBARKANTA = add_spell -{ - ["name"] = "Ambarkanta(IV)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 25, - ["mana"] = 70, - ["mana_max"] = 70, - ["fail"] = 60, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 4, - ["spell"] = function() return music_ambarkanta_spell() end, - ["info"] = function() return music_ambarkanta_info() end, - ["desc"] = { - "Produces a reality shaking sound that transports you to a nearly", - "identical reality.", - } -} diff --git a/lib/mods/theme/scpt/s_nature.lua b/lib/mods/theme/scpt/s_nature.lua deleted file mode 100644 index e41a6990..00000000 --- a/lib/mods/theme/scpt/s_nature.lua +++ /dev/null @@ -1,138 +0,0 @@ --- handle the nature school - -GROWTREE = add_spell -{ - ["name"] = "Grow Trees", - ["school"] = {SCHOOL_NATURE, SCHOOL_TEMPORAL}, - ["level"] = 6, - ["mana"] = 6, - ["mana_max"] = 30, - ["fail"] = 35, - ["inertia"] = { 5, 50 }, - ["spell"] = function() return nature_grow_trees() end, - ["info"] = function() return nature_grow_trees_info() end, - ["desc"] = { - "Makes trees grow extremely quickly around you", - } -} - -HEALING = add_spell -{ - ["name"] = "Healing", - ["school"] = {SCHOOL_NATURE}, - ["level"] = 10, - ["mana"] = 15, - ["mana_max"] = 50, - ["fail"] = 45, - ["stick"] = - { - ["charge"] = { 2, 3 }, - [TV_STAFF] = - { - ["rarity"] = 90, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 20, 40 }, - }, - }, - ["spell"] = function() return nature_healing() end, - ["info"] = function() return nature_healing_info() end, - ["desc"] = { - "Heals a percent of hitpoints", - } -} - -RECOVERY = add_spell -{ - ["name"] = "Recovery", - ["school"] = {SCHOOL_NATURE}, - ["level"] = 15, - ["mana"] = 10, - ["mana_max"] = 25, - ["fail"] = 60, - ["stick"] = - { - ["charge"] = { 5, 10 }, - [TV_STAFF] = - { - ["rarity"] = 50, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 10, 30 }, - }, - }, - ["inertia"] = { 2, 100 }, - ["spell"] = function() return nature_recovery() end, - ["info"] = function() return nature_recovery_info() end, - ["desc"] = { - "Reduces the length of time that you are poisoned", - "At level 5 it cures poison and cuts", - "At level 10 it restores drained stats", - "At level 15 it restores lost experience" - } -} - -REGENERATION = add_spell -{ - ["name"] = "Regeneration", - ["school"] = {SCHOOL_NATURE}, - ["level"] = 20, - ["mana"] = 30, - ["mana_max"] = 55, - ["fail"] = 70, - ["inertia"] = { 4, 40 }, - ["spell"] = function() return nature_regeneration() end, - ["info"] = function() return nature_regeneration_info() end, - ["desc"] = { - "Increases your body's regeneration rate", - } -} - - -SUMMONANNIMAL = add_spell -{ - ["name"] = "Summon Animal", - ["school"] = {SCHOOL_NATURE}, - ["level"] = 25, - ["mana"] = 25, - ["mana_max"] = 50, - ["fail"] = 90, - ["stick"] = - { - ["charge"] = { 1, 3 }, - [TV_WAND] = - { - ["rarity"] = 85, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 15, 45 }, - }, - }, - ["spell"] = function() return nature_summon_animal() end, - ["info"] = function() return nature_summon_animal_info() end, - ["desc"] = { - "Summons a leveled animal to your aid", - } -} - --- From T-Plus -GROW_ATHELAS = add_spell { - ["name"] = "Grow Athelas", - ["school"] = {SCHOOL_NATURE}, - ["level"] = 30, - ["mana"] = 60, - ["mana_max"] = 100, - ["fail"] = 95, - ["stick"] = - { - ["charge"] = { 1, 3 }, - [TV_WAND] = - { - ["rarity"] = 85, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 15, 45 }, - }, - }, - ["spell"] = function() return nature_grow_athelas() end, - ["info"] = function() return nature_grow_athelas_info() end, - ["desc"] = { - "Cures the Black Breath", - } -} diff --git a/lib/mods/theme/scpt/s_stick.lua b/lib/mods/theme/scpt/s_stick.lua deleted file mode 100644 index 554ca045..00000000 --- a/lib/mods/theme/scpt/s_stick.lua +++ /dev/null @@ -1,290 +0,0 @@ --- Spells that are stick or artifacts/... only - -DEVICE_HEAL_MONSTER = add_spell -{ - ["name"] = "Heal Monster", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 3, - ["mana"] = 5, - ["mana_max"] = 20, - ["fail"] = 15, - ["random"] = -1, - ["stick"] = - { - ["charge"] = { 10, 10 }, - [TV_WAND] = - { - ["rarity"] = 17, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 20, 50 }, - }, - }, - ["spell"] = function() return device_heal_monster() end, - ["info"] = function() return device_heal_monster_info() end, - ["desc"] = { - "Heals a monster", - } -} - -DEVICE_SPEED_MONSTER = add_spell -{ - ["name"] = "Haste Monster", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 10, - ["mana"] = 10, - ["mana_max"] = 10, - ["fail"] = 30, - ["random"] = -1, - ["stick"] = - { - ["charge"] = { 10, 5 }, - [TV_WAND] = - { - ["rarity"] = 7, - ["base_level"] = { 1, 1 }, - ["max_level"] = { 20, 50 }, - }, - }, - ["spell"] = function() return device_haste_monster() end, - ["info"] = function() return device_haste_monster_info() end, - ["desc"] = { - "Haste a monster", - } -} - -DEVICE_WISH = add_spell -{ - ["name"] = "Wish", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 50, - ["mana"] = 400, - ["mana_max"] = 400, - ["fail"] = 99, - ["random"] = -1, - ["stick"] = - { - ["charge"] = { 1, 2 }, - [TV_STAFF] = - { - ["rarity"] = 98, - ["base_level"] = { 1, 1 }, - ["max_level"] = { 1, 1 }, - }, - }, - ["spell"] = function() return device_wish() end, - ["info"] = function() return device_wish_info() end, - ["desc"] = { - "This grants you a wish, beware of what you ask for!", - } -} - -DEVICE_SUMMON = add_spell -{ - ["name"] = "Summon", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 5, - ["mana"] = 5, - ["mana_max"] = 25, - ["fail"] = 20, - ["random"] = -1, - ["stick"] = - { - ["charge"] = { 1, 20 }, - [TV_STAFF] = - { - ["rarity"] = 13, - ["base_level"] = { 1, 40 }, - ["max_level"] = { 25, 50 }, - }, - }, - ["spell"] = function() return device_summon_monster() end, - ["info"] = function() return device_summon_monster_info() end, - ["desc"] = { - "Summons hostile monsters near you", - } -} - -DEVICE_MANA = add_spell -{ - ["name"] = "Mana", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 30, - ["mana"] = 1, - ["mana_max"] = 1, - ["fail"] = 80, - ["random"] = -1, - ["stick"] = - { - ["charge"] = { 2, 3 }, - [TV_STAFF] = - { - ["rarity"] = 78, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 20, 35 }, - }, - }, - ["spell"] = function() return device_mana() end, - ["info"] = function() return device_mana_info() end, - ["desc"] = { - "Restores a part(or all) of your mana", - } -} - -DEVICE_NOTHING = add_spell -{ - ["name"] = "Nothing", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 1, - ["mana"] = 0, - ["mana_max"] = 0, - ["fail"] = 0, - ["random"] = -1, - ["stick"] = - { - ["charge"] = { 0, 0 }, - [TV_WAND] = - { - ["rarity"] = 3, - ["base_level"] = { 1, 1 }, - ["max_level"] = { 1, 1 }, - }, - [TV_STAFF] = - { - ["rarity"] = 3, - ["base_level"] = { 1, 1 }, - ["max_level"] = { 1, 1}, - }, - }, - ["spell"] = function() return device_nothing() end, - ["info"] = function() return device_nothing_info() end, - ["desc"] = { - "It does nothing.", - } -} - -DEVICE_MAGGOT = add_spell -{ - ["name"] = "Artifact Maggot", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 1, - ["mana"] = 7, - ["mana_max"] = 7, - ["fail"] = 20, - ["random"] = -1, - ["activate"] = { 10, 50 }, - ["spell"] = function() return device_maggot() end, - ["info"] = function() return device_maggot_info() end, - ["desc"] = { - "terrify", - } -} - -DEVICE_HOLY_FIRE = add_spell -{ - ["name"] = "Holy Fire of Mithrandir", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 30, - ["mana"] = 50, - ["mana_max"] = 150, - ["fail"] = 75, - ["random"] = -1, - ["stick"] = - { - ["charge"] = { 2, 5 }, - [TV_STAFF] = - { - -- Rarity higher than 100 to be sure to not have it generated randomly - ["rarity"] = 999, - ["base_level"] = { 1, 1 }, - ["max_level"] = { 35, 35 }, - }, - }, - ["spell"] = function() return device_holy_fire() end, - ["info"] = function() return device_holy_fire_info() end, - ["desc"] = { - "The Holy Fire created by this staff will deeply(double damage) burn", - "all that is evil.", - } -} - --- Ok the Eternal Flame, to craete one of the 4 ultimate arts --- needed to enter the last level of the Void -DEVICE_ETERNAL_FLAME = add_spell -{ - ["name"] = "Artifact Eternal Flame", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 1, - ["mana"] = 0, - ["mana_max"] = 0, - ["fail"] = 0, - ["random"] = -1, - ["activate"] = { 0, 0 }, - ["spell"] = function(flame_item) return device_eternal_flame(flame_item) end, - ["info"] = function() return "" end, - ["desc"] = { - "Imbuing an object with the eternal fire", - } -} - -DEVICE_THUNDERLORDS = add_spell -{ - ["name"] = "Artifact Thunderlords", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 1, - ["fail"] = 20, - ["random"] = -1, - ["stick"] = - { - ["charge"] = { 5, 5 }, - [TV_STAFF] = - { - -- Rarity higher than 100 to be sure to not have it generated randomly - ["rarity"] = 999, - ["base_level"] = { 1, 1 }, - ["max_level"] = { 1, 1 }, - }, - }, - ["spell"] = function() return device_thunderlords() end, - ["info"] = function() return device_thunderlords_info() end, - ["desc"] = { - "An Eagle of Manwe will appear to transport you quickly to the town.", - } -} - --- Two new spells from T-Plus by Ingeborg S. Norden, for artifact activations: - -DEVICE_RADAGAST = add_spell -{ - ["name"] = "Artifact Radagast", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 1, - ["mana"] = 0, - ["mana_max"] = 0, - ["fail"] = 10, - ["random"] = -1, - ["activate"] = { 15000, 0 }, - ["spell"] = function() return device_radagast() end, - ["info"] = function() return device_radagast_info() end, - ["desc"] = { - "purity and health", - } -} - -DEVICE_VALAROMA = add_spell -{ - ["name"] = "Artifact Valaroma", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 1, - ["mana"] = 0, - ["mana_max"] = 0, - ["fail"] = 25, - ["random"] = -1, - ["activate"] = { 250, 0 }, - ["spell"] = function() return device_valaroma() end, - ["info"] = function() return device_valaroma_info() end, - ["desc"] = { - "banish evil (level x5)", - } -} diff --git a/lib/mods/theme/scpt/s_tempo.lua b/lib/mods/theme/scpt/s_tempo.lua deleted file mode 100644 index 76026745..00000000 --- a/lib/mods/theme/scpt/s_tempo.lua +++ /dev/null @@ -1,109 +0,0 @@ --- Handles thhe temporal school - - -MAGELOCK = add_spell -{ - ["name"] = "Magelock", - ["school"] = {SCHOOL_TEMPORAL}, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 35, - ["fail"] = 10, - ["stick"] = - { - ["charge"] = { 7, 5 }, - [TV_WAND] = - { - ["rarity"] = 30, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 15, 45 }, - }, - }, - ["spell"] = function() return tempo_magelock() end, - ["info"] = function() return tempo_magelock_info() end, - ["desc"] = { - "Magically locks a door", - "At level 30 it creates a glyph of warding", - "At level 40 the glyph can be placed anywhere in the field of vision" - } -} - -SLOWMONSTER = add_spell -{ - ["name"] = "Slow Monster", - ["school"] = {SCHOOL_TEMPORAL}, - ["level"] = 10, - ["mana"] = 10, - ["mana_max"] = 15, - ["fail"] = 35, - ["stick"] = - { - ["charge"] = { 5, 5 }, - [TV_WAND] = - { - ["rarity"] = 23, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 20, 50 }, - }, - }, - ["spell"] = function() return tempo_slow_monster() end, - ["info"] = function() return tempo_slow_monster_info() end, - ["desc"] = { - "Magically slows down the passing of time around a monster", - "At level 20 it affects a zone" - } -} - -ESSENCESPEED = add_spell -{ - ["name"] = "Essence of Speed", - ["school"] = {SCHOOL_TEMPORAL}, - ["level"] = 15, - ["mana"] = 20, - ["mana_max"] = 40, - ["fail"] = 50, - ["stick"] = - { - ["charge"] = { 3, 3 }, - [TV_WAND] = - { - ["rarity"] = 80, - ["base_level"] = { 1, 1 }, - ["max_level"] = { 10, 39 }, - }, - }, - ["inertia"] = { 5, 20 }, - ["spell"] = function() return tempo_essence_of_speed() end, - ["info"] = function() return tempo_essence_of_speed_info() end, - ["desc"] = { - "Magically decreases the passing of time around you, making you move faster with", - "respect to the rest of the universe." - } -} - -BANISHMENT = add_spell -{ - ["name"] = "Banishment", - ["school"] = {SCHOOL_TEMPORAL, SCHOOL_CONVEYANCE}, - ["level"] = 30, - ["mana"] = 30, - ["mana_max"] = 40, - ["fail"] = 95, - ["stick"] = - { - ["charge"] = { 1, 3 }, - [TV_WAND] = - { - ["rarity"] = 98, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 10, 36 }, - }, - }, - ["inertia"] = { 5, 50 }, - ["spell"] = function() return tempo_banishment() end, - ["info"] = function() return tempo_banishment_info() end, - ["desc"] = { - "Disrupts the space/time continuum in your area and teleports all monsters away.", - "At level 15 it may also lock them in a time bubble for a while." - } -} diff --git a/lib/mods/theme/scpt/s_tulkas.lua b/lib/mods/theme/scpt/s_tulkas.lua deleted file mode 100644 index 6659aee9..00000000 --- a/lib/mods/theme/scpt/s_tulkas.lua +++ /dev/null @@ -1,59 +0,0 @@ --- Handle Tulkas magic school - -TULKAS_AIM = add_spell -{ - ["name"] = "Divine Aim", - ["school"] = {SCHOOL_TULKAS}, - ["level"] = 1, - ["mana"] = 30, - ["mana_max"] = 500, - ["fail"] = 20, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return tulkas_divine_aim() end, - ["info"] = function() return tulkas_divine_aim_info() end, - ["desc"] = { - "It makes you more accurate in combat", - "At level 20 all your blows are critical hits", - } -} - -TULKAS_WAVE = add_spell -{ - ["name"] = "Wave of Power", - ["school"] = {SCHOOL_TULKAS}, - ["level"] = 20, - ["mana"] = 200, - ["mana_max"] = 200, - ["fail"] = 75, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return tulkas_wave_of_power() end, - ["info"] = function() return tulkas_wave_of_power_info() end, - ["desc"] = { - "It allows you to project a number of melee blows across a distance", - } -} - -TULKAS_SPIN = add_spell -{ - ["name"] = "Whirlwind", - ["school"] = {SCHOOL_TULKAS}, - ["level"] = 10, - ["mana"] = 100, - ["mana_max"] = 100, - ["fail"] = 45, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return tulkas_whirlwind() end, - ["info"] = function() return tulkas_whirlwind_info() end, - ["desc"] = { - "It allows you to spin around and hit all monsters nearby", - } -} diff --git a/lib/mods/theme/scpt/s_udun.lua b/lib/mods/theme/scpt/s_udun.lua deleted file mode 100644 index bb12ac7f..00000000 --- a/lib/mods/theme/scpt/s_udun.lua +++ /dev/null @@ -1,74 +0,0 @@ --- handle the udun school - -DRAIN = add_spell -{ - ["name"] = "Drain", - ["school"] = {SCHOOL_UDUN, SCHOOL_MANA}, - ["level"] = 1, - ["mana"] = 0, - ["mana_max"] = 0, - ["fail"] = 20, - ["spell"] = function() return udun_drain() end, - ["info"] = function() return udun_drain_info() end, - ["desc"] = { - "Drains the mana contained in wands, staves and rods to increase yours", - } -} - -GENOCIDE = add_spell -{ - ["name"] = "Genocide", - ["school"] = {SCHOOL_UDUN, SCHOOL_NATURE}, - ["level"] = 25, - ["mana"] = 50, - ["mana_max"] = 50, - ["fail"] = 90, - ["stick"] = - { - ["charge"] = { 2, 2 }, - [TV_STAFF] = - { - ["rarity"] = 85, - ["base_level"] = { 1, 1 }, - ["max_level"] = { 5, 15 }, - }, - }, - ["spell"] = function() return udun_genocide() end, - ["info"] = function() return udun_genocide_info() end, - ["desc"] = { - "Genocides all monsters of a race on the level", - "At level 10 it can genocide all monsters near you" - } -} - -WRAITHFORM = add_spell -{ - ["name"] = "Wraithform", - ["school"] = {SCHOOL_UDUN, SCHOOL_CONVEYANCE}, - ["level"] = 30, - ["mana"] = 20, - ["mana_max"] = 40, - ["fail"] = 95, - ["inertia"] = { 4, 30 }, - ["spell"] = function() return udun_wraithform() end, - ["info"] = function() return udun_wraithform_info() end, - ["desc"] = { - "Turns you into an immaterial being", - } -} - -FLAMEOFUDUN = add_spell -{ - ["name"] = "Flame of Udun", - ["school"] = {SCHOOL_UDUN, SCHOOL_FIRE}, - ["level"] = 35, - ["mana"] = 70, - ["mana_max"] = 100, - ["fail"] = 95, - ["inertia"] = { 7, 15 }, - ["spell"] = function() return udun_flame_of_udun() end, - ["info"] = function() return udun_flame_of_udun_info() end, - ["desc"] = { - "Turns you into a powerful Balrog", - } -} diff --git a/lib/mods/theme/scpt/s_ulmo.lua b/lib/mods/theme/scpt/s_ulmo.lua deleted file mode 100644 index 02661ca3..00000000 --- a/lib/mods/theme/scpt/s_ulmo.lua +++ /dev/null @@ -1,89 +0,0 @@ --- Spells for Ulmo's school - -BOOK_ULMO = 65 - --- "Song of Belegaer" copied from Geyser -ULMO_BELEGAER = add_spell -{ - ["name"] = "Song of Belegaer", - ["school"] = SCHOOL_ULMO, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 100, - ["fail"] = 25, - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return ulmo_song_of_belegaer_spell() end, - ["info"] = function() return ulmo_song_of_belegaer_info() end, - ["desc"] = - { - "Channels the power of the Great Sea into your fingertips.", - "Sometimes it can blast through its first target." - }, -} - --- "Draught of Ulmonan" copied with tweaks from T-Plus Nature spell "Restore Body" -ULMO_DRAUGHT_ULMONAN = add_spell -{ - ["name"] = "Draught of Ulmonan", - ["school"] = {SCHOOL_ULMO}, - ["level"] = 15, - ["mana"] = 25, - ["mana_max"] = 200, - ["fail"] = 50, - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return ulmo_draught_of_ulmonan_spell() end, - ["info"] = function() return ulmo_draught_of_ulmonan_info() end, - ["desc"] = { - "Fills you with a draught with powerful curing effects,", - "prepared by Ulmo himself.", - "Level 1: blindness, poison, cuts and stunning", - "Level 10: drained STR, DEX and CON", - "Level 20: parasites and mimicry", - }, -} - --- "Call of the Ulumuri" based on Call Blessed Soul from T-Plus -ULMO_CALL_ULUMURI = add_spell - -{ - ["name"] = "Call of the Ulumuri", - ["school"] = {SCHOOL_ULMO}, - ["level"] = 20, - ["mana"] = 50, - ["mana_max"] = 300, - ["fail"] = 75, - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return ulmo_call_of_the_ulumuri_spell() end, - ["info"] = function() return ulmo_call_of_the_ulumuri_info() end, - ["desc"] = { - "Summons a leveled water spirit or elemental", - "to fight for you", - - }, -} - --- "Wrath of Ulmo" based on Firewall -ULMO_WRATH = add_spell -{ - ["name"] = "Wrath of Ulmo", - ["school"] = {SCHOOL_ULMO}, - ["level"] = 30, - ["mana"] = 100, - ["mana_max"] = 400, - ["fail"] = 95, - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return ulmo_wrath_of_ulmo_spell() end, - ["info"] = function() return ulmo_wrath_of_ulmo_info() end, - ["desc"] = { - "Conjures up a sea storm.", - "At level 30 it turns into a more forceful storm." - } -} \ No newline at end of file diff --git a/lib/mods/theme/scpt/s_varda.lua b/lib/mods/theme/scpt/s_varda.lua deleted file mode 100644 index e20ea5e9..00000000 --- a/lib/mods/theme/scpt/s_varda.lua +++ /dev/null @@ -1,83 +0,0 @@ --- Spells for Varda school (From Annals of Ea module) - -BOOK_VARDA = 64 - --- Holy light spell copied from Globe of Light -VARDA_LIGHT_VALINOR = add_spell -{ - ["name"] = "Light of Valinor", - ["school"] = {SCHOOL_VARDA}, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 100, - ["fail"] = 20, - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return varda_light_of_valinor_spell() end, - ["info"] = function() return varda_light_of_valinor_info() end, - ["desc"] = { - "Lights a room", - "At level 3 it starts damaging monsters", - "At level 15 it starts creating a more powerful kind of light", - } -} - -VARDA_CALL_ALMAREN = add_spell -{ - ["name"] = "Call of Almaren", - ["school"] = {SCHOOL_VARDA}, - ["level"] = 10, - ["mana"] = 5, - ["mana_max"] = 150, - ["fail"] = 20, - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return varda_call_of_almaren_spell() end, - ["info"] = function() return varda_call_of_almaren_info() end, - ["desc"] = { - "Banishes evil beings", - "At level 20 it dispels evil beings", - } -} - -VARDA_EVENSTAR = add_spell -{ - ["name"] = "Evenstar", - ["school"] = {SCHOOL_VARDA}, - ["level"] = 20, - ["mana"] = 20, - ["mana_max"] = 200, - ["fail"] = 20, - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return varda_evenstar_spell() end, - ["info"] = function() return varda_evenstar_info() end, - ["desc"] = { - "Maps and lights the whole level.", - "At level 40 it maps and lights the whole level,", - "in addition to letting you know yourself better", - "and identifying your whole pack.", - } -} - -VARDA_STARKINDLER = add_spell -{ - ["name"] = "Star Kindler", - ["school"] = {SCHOOL_VARDA}, - ["level"] = 30, - ["mana"] = 50, - ["mana_max"] = 250, - ["fail"] = 20, - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return varda_star_kindler_spell() end, - ["info"] = function() return varda_star_kindler_info() end, - ["desc"] = { - "Does multiple bursts of light damage.", - "The damage increases with level.", - } -} diff --git a/lib/mods/theme/scpt/s_water.lua b/lib/mods/theme/scpt/s_water.lua deleted file mode 100644 index 46942c5d..00000000 --- a/lib/mods/theme/scpt/s_water.lua +++ /dev/null @@ -1,106 +0,0 @@ --- handle the water school - -TIDALWAVE = add_spell -{ - ["name"] = "Tidal Wave", - ["school"] = {SCHOOL_WATER}, - ["level"] = 16, - ["mana"] = 16, - ["mana_max"] = 40, - ["fail"] = 65, - ["stick"] = - { - ["charge"] = { 6, 5 }, - [TV_WAND] = - { - ["rarity"] = 54, - ["base_level"] = { 1, 10 }, - ["max_level"] = { 20, 50 }, - }, - }, - ["inertia"] = { 4, 100 }, - ["spell"] = function() return water_tidal_wave() end, - ["info"] = function() return water_tidal_wave_info() end, - ["desc"] = { - "Summons a monstrous tidal wave that will expand and crush the", - "monsters under its mighty waves." - } -} - -ICESTORM = add_spell -{ - ["name"] = "Ice Storm", - ["school"] = {SCHOOL_WATER}, - ["level"] = 22, - ["mana"] = 30, - ["mana_max"] = 60, - ["fail"] = 80, - ["stick"] = - { - ["charge"] = { 3, 7 }, - [TV_WAND] = - { - ["rarity"] = 65, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 25, 45 }, - }, - }, - ["inertia"] = { 3, 40 }, - ["spell"] = function() return water_ice_storm() end, - ["info"] = function() return water_ice_storm_info() end, - ["desc"] = { - "Engulfs you in a storm of roaring cold that strikes your foes.", - "At level 10 it turns into shards of ice." - } -} - -ENTPOTION = add_spell -{ - ["name"] = "Ent's Potion", - ["school"] = {SCHOOL_WATER}, - ["level"] = 6, - ["mana"] = 7, - ["mana_max"] = 15, - ["fail"] = 35, - ["inertia"] = { 1, 30 }, - ["spell"] = function() return water_ent_potion() end, - ["info"] = function() return water_ent_potion_info() end, - ["desc"] = { - "Fills up your stomach.", - "At level 5 it boldens your heart.", - "At level 12 it makes you heroic." - } -} - -VAPOR = add_spell -{ - ["name"] = "Vapor", - ["school"] = {SCHOOL_WATER}, - ["level"] = 2, - ["mana"] = 2, - ["mana_max"] = 12, - ["fail"] = 20, - ["inertia"] = { 1, 30 }, - ["spell"] = function() return water_vapor() end, - ["info"] = function() return water_vapor_info() end, - ["desc"] = { - "Fills the air with toxic moisture to eradicate annoying critters." - } -} - -GEYSER = add_spell -{ - ["name"] = "Geyser", - ["school"] = SCHOOL_WATER, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 35, - ["fail"] = 5, - ["spell"] = function() return water_geyser() end, - ["info"] = function() return water_geyser_info() end, - ["desc"] = - { - "Shoots a geyser of water from your fingertips.", - "Sometimes it can blast through its first target." - }, -} diff --git a/lib/mods/theme/scpt/s_yavann.lua b/lib/mods/theme/scpt/s_yavann.lua deleted file mode 100644 index a2b2fe1c..00000000 --- a/lib/mods/theme/scpt/s_yavann.lua +++ /dev/null @@ -1,100 +0,0 @@ --- Handle Yavanna kementari magic school - -YAVANNA_CHARM_ANIMAL = add_spell -{ - ["name"] = "Charm Animal", - ["school"] = {SCHOOL_YAVANNA}, - ["level"] = 1, - ["mana"] = 10, - ["mana_max"] = 100, - ["fail"] = 30, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return yavanna_charm_animal() end, - ["info"] = function() return yavanna_charm_animal_info() end, - ["desc"] = { - "It tries to tame an animal", - } -} - -YAVANNA_GROW_GRASS = add_spell -{ - ["name"] = "Grow Grass", - ["school"] = {SCHOOL_YAVANNA}, - ["level"] = 10, - ["mana"] = 70, - ["mana_max"] = 150, - ["fail"] = 65, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return yavanna_grow_grass() end, - ["info"] = function() return yavanna_grow_grass_info() end, - ["desc"] = { - "Create a floor of grass around you. While on grass and praying", - "a worshipper of Yavanna will know a greater regeneration rate" - } -} - -YAVANNA_TREE_ROOTS = add_spell -{ - ["name"] = "Tree Roots", - ["school"] = {SCHOOL_YAVANNA}, - ["level"] = 15, - ["mana"] = 50, - ["mana_max"] = 1000, - ["fail"] = 70, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return yavanna_tree_roots() end, - ["info"] = function() return yavanna_tree_roots_info() end, - ["desc"] = { - "Creates roots deep in the floor from your feet, making you more stable and able", - "to make stronger attacks, but prevents any movement (even teleportation).", - "It also makes you recover from stunning almost immediately." - } -} - -YAVANNA_WATER_BITE = add_spell -{ - ["name"] = "Water Bite", - ["school"] = {SCHOOL_YAVANNA}, - ["level"] = 20, - ["mana"] = 150, - ["mana_max"] = 300, - ["fail"] = 90, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return yavanna_water_bite() end, - ["info"] = function() return yavanna_water_bite_info() end, - ["desc"] = { - "Imbues your melee weapon with a natural stream of water", - "At level 25, it spreads over a 1 radius zone around your target" - } -} - -YAVANNA_UPROOT = add_spell -{ - ["name"] = "Uproot", - ["school"] = {SCHOOL_YAVANNA}, - ["level"] = 35, - ["mana"] = 250, - ["mana_max"] = 350, - ["fail"] = 95, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return yavanna_uproot() end, - ["info"] = function() return yavanna_uproot_info() end, - ["desc"] = { - "Awakes a tree to help you battle the forces of Morgoth", - } -} diff --git a/lib/mods/theme/scpt/spells.lua b/lib/mods/theme/scpt/spells.lua index eedd59ad..e37d922f 100644 --- a/lib/mods/theme/scpt/spells.lua +++ b/lib/mods/theme/scpt/spells.lua @@ -378,42 +378,8 @@ SCHOOL_MUSIC = add_school ["skill"] = SKILL_MUSIC, } --- Put some spells -tome_dofile("s_fire.lua") -tome_dofile("s_mana.lua") -tome_dofile("s_water.lua") -tome_dofile("s_air.lua") -tome_dofile("s_earth.lua") -tome_dofile("s_convey.lua") -tome_dofile("s_nature.lua") -tome_dofile("s_divin.lua") -tome_dofile("s_tempo.lua") -tome_dofile("s_meta.lua") -tome_dofile("s_mind.lua") -tome_dofile("s_udun.lua") -tome_dofile("s_geom.lua") - --- God's specific spells -tome_dofile("s_eru.lua") -tome_dofile("s_manwe.lua") -tome_dofile("s_tulkas.lua") -tome_dofile("s_melkor.lua") -tome_dofile("s_yavann.lua") - --- New gods' spells -tome_dofile("s_aule.lua") -tome_dofile("s_varda.lua") -tome_dofile("s_ulmo.lua") -tome_dofile("s_mandos.lua") - --- Specific schools -tome_dofile("s_demon.lua") - --- Device spells -tome_dofile("s_stick.lua") - --- Musics -tome_dofile("s_music.lua") +-- Initialize school spells. +school_spells_init() -- Initialize spellbooks init_school_books() diff --git a/lib/scpt/mkeys.lua b/lib/scpt/mkeys.lua index c46cbace..ae8ad2b1 100644 --- a/lib/scpt/mkeys.lua +++ b/lib/scpt/mkeys.lua @@ -35,7 +35,7 @@ add_mkey return end - s = get_school_spell("cast", "is_ok_spell", 62); + s = get_school_spell("cast", 62); -- Actualy cast the choice if (s ~= -1) then diff --git a/lib/scpt/s_air.lua b/lib/scpt/s_air.lua deleted file mode 100644 index 7b585317..00000000 --- a/lib/scpt/s_air.lua +++ /dev/null @@ -1,152 +0,0 @@ --- handle the air school - -NOXIOUSCLOUD = add_spell -{ - ["name"] = "Noxious Cloud", - ["school"] = {SCHOOL_AIR}, - ["level"] = 3, - ["mana"] = 3, - ["mana_max"] = 30, - ["fail"] = 20, - ["stick"] = - { - ["charge"] = { 5, 7 }, - [TV_WAND] = - { - ["rarity"] = 15, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 25, 50 }, - }, - }, - ["spell"] = function() return air_noxious_cloud() end, - ["info"] = function() return air_noxious_cloud_info() end, - ["desc"] = { - "Creates a cloud of poison", - "The cloud will persist for some turns, damaging all monsters passing by", - "At spell level 30 it turns into a thick gas attacking all living beings" - } -} - -AIRWINGS = add_spell -{ - ["name"] = "Wings of Winds", - ["school"] = {SCHOOL_AIR, SCHOOL_CONVEYANCE}, - ["level"] = 22, - ["mana"] = 30, - ["mana_max"] = 40, - ["fail"] = 60, - ["stick"] = - { - ["charge"] = { 7, 5 }, - [TV_STAFF] = - { - ["rarity"] = 27, - ["base_level"] = { 1, 10 }, - ["max_level"] = { 20, 50 }, - }, - }, - ["inertia"] = { 1, 10 }, - ["spell"] = function() return air_wings_of_winds() end, - ["info"] = function() return air_wings_of_winds_info() end, - ["desc"] = { - "Grants the power of levitation", - "At level 16 it grants the power of controlled flight" - } -} - -INVISIBILITY = add_spell -{ - ["name"] = "Invisibility", - ["school"] = {SCHOOL_AIR}, - ["level"] = 16, - ["mana"] = 10, - ["mana_max"] = 20, - ["fail"] = 50, - ["inertia"] = { 1, 30 }, - ["spell"] = function() return air_invisibility() end, - ["info"] = function() return air_invisibility_info() end, - ["desc"] = { - "Grants invisibility" - } -} - -POISONBLOOD = add_spell -{ - ["name"] = "Poison Blood", - ["school"] = {SCHOOL_AIR}, - ["level"] = 12, - ["mana"] = 10, - ["mana_max"] = 20, - ["fail"] = 30, - ["stick"] = - { - ["charge"] = { 10, 15 }, - [TV_WAND] = - { - ["rarity"] = 45, - ["base_level"] = { 1, 25 }, - ["max_level"] = { 35, 50 }, - }, - }, - ["inertia"] = { 1, 35 }, - ["spell"] = function() return air_poison_blood() end, - ["info"] = function() return air_poison_blood_info() end, - ["desc"] = { - "Grants resist poison", - "At level 15 it provides poison branding to wielded weapon" - } -} - -THUNDERSTORM = add_spell -{ - ["name"] = "Thunderstorm", - ["school"] = {SCHOOL_AIR, SCHOOL_NATURE}, - ["level"] = 25, - ["mana"] = 40, - ["mana_max"] = 60, - ["fail"] = 60, - ["stick"] = - { - ["charge"] = { 5, 5 }, - [TV_WAND] = - { - ["rarity"] = 85, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 25, 50 }, - }, - }, - ["inertia"] = { 2, 15 }, - ["spell"] = function() return air_thunderstorm() end, - ["info"] = function() return air_thunderstorm_info() end, - ["desc"] = { - "Charges up the air around you with electricity", - "Each turn it will throw a thunder bolt at a random monster in sight", - "The thunder does 3 types of damage, one third of lightning", - "one third of sound and one third of light" - } -} - -STERILIZE = add_spell -{ - ["name"] = "Sterilize", - ["school"] = {SCHOOL_AIR}, - ["level"] = 20, - ["mana"] = 10, - ["mana_max"] = 100, - ["fail"] = 50, - ["stick"] = - { - ["charge"] = { 7, 5 }, - [TV_STAFF] = - { - ["rarity"] = 20, - ["base_level"] = { 1, 10 }, - ["max_level"] = { 20, 50 }, - }, - }, - ["spell"] = function() return air_sterilize() end, - ["info"] = function() return air_sterilize_info() end, - ["desc"] = { - "Prevents explosive breeding for a while." - } -} diff --git a/lib/scpt/s_convey.lua b/lib/scpt/s_convey.lua deleted file mode 100644 index d81af28b..00000000 --- a/lib/scpt/s_convey.lua +++ /dev/null @@ -1,143 +0,0 @@ --- handle the conveyance school - -BLINK = add_spell -{ - ["name"] = "Phase Door", - ["school"] = {SCHOOL_CONVEYANCE}, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 3, - ["fail"] = 10, - ["inertia"] = { 1, 5 }, - ["spell"] = function() return convey_blink() end, - ["info"] = function() return convey_blink_info() end, - ["desc"] = { - "Teleports you on a small scale range", - "At level 30 it creates void jumpgates", - } -} - -DISARM = add_spell -{ - ["name"] = "Disarm", - ["school"] = {SCHOOL_CONVEYANCE}, - ["level"] = 3, - ["mana"] = 2, - ["mana_max"] = 4, - ["fail"] = 15, - ["stick"] = - { - ["charge"] = { 10, 15 }, - [TV_STAFF] = - { - ["rarity"] = 4, - ["base_level"] = { 1, 10 }, - ["max_level"] = { 10, 50 }, - }, - }, - ["spell"] = function() return convey_disarm() end, - ["info"] = function() return convey_disarm_info() end, - ["desc"] = { - "Destroys doors and traps", - "At level 10 it destroys doors and traps, then reveals and unlocks any secret", - "doors" - } -} - -TELEPORT = add_spell -{ - ["name"] = "Teleportation", - ["school"] = {SCHOOL_CONVEYANCE}, - ["level"] = 10, - ["mana"] = 8, - ["mana_max"] = 14, - ["fail"] = 30, - ["stick"] = - { - ["charge"] = { 7, 7 }, - [TV_STAFF] = - { - ["rarity"] = 50, - ["base_level"] = { 1, 20 }, - ["max_level"] = { 20, 50 }, - }, - }, - ["inertia"] = { 1, 10 }, - ["spell"] = function() return convey_teleport() end, - ["info"] = function() return convey_teleport_info() end, - ["desc"] = { - "Teleports you around the level. The casting time decreases with level", - } -} - -TELEAWAY = add_spell -{ - ["name"] = "Teleport Away", - ["school"] = {SCHOOL_CONVEYANCE}, - ["level"] = 23, - ["mana"] = 15, - ["mana_max"] = 40, - ["fail"] = 60, - ["stick"] = - { - ["charge"] = { 3, 5 }, - [TV_WAND] = - { - ["rarity"] = 75, - ["base_level"] = { 1, 20 }, - ["max_level"] = { 20, 50 }, - }, - }, - ["spell"] = function() return convey_teleport_away() end, - ["info"] = function() return convey_teleport_away_info() end, - ["desc"] = { - "Teleports a line of monsters away", - "At level 10 it turns into a ball", - "At level 20 it teleports all monsters in sight" - } -} - -RECALL = add_spell -{ - ["name"] = "Recall", - ["school"] = {SCHOOL_CONVEYANCE}, - ["level"] = 30, - ["mana"] = 25, - ["mana_max"] = 25, - ["fail"] = 60, - ["spell"] = function() return convey_recall() end, - ["info"] = function() return convey_recall_info() end, - ["desc"] = { - "Cast on yourself it will recall you to the surface/dungeon.", - "Cast at a monster you will swap positions with the monster.", - "Cast at an object it will fetch the object to you." - } -} - -PROBABILITY_TRAVEL = add_spell -{ - ["name"] = "Probability Travel", - ["school"] = {SCHOOL_CONVEYANCE}, - ["level"] = 35, - ["mana"] = 30, - ["mana_max"] = 50, - ["fail"] = 90, - ["stick"] = - { - ["charge"] = { 1, 2 }, - [TV_STAFF] = - { - ["rarity"] = 97, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 8, 25 }, - }, - }, - ["inertia"] = { 6, 40 }, - ["spell"] = function() return convey_probability_travel() end, - ["info"] = function() return convey_probability_travel_info() end, - ["desc"] = { - "Renders you immaterial, when you hit a wall you travel through it and", - "instantly appear on the other side of it. You can also float up and down", - "at will" - } -} diff --git a/lib/scpt/s_demon.lua b/lib/scpt/s_demon.lua deleted file mode 100644 index 8bf14c21..00000000 --- a/lib/scpt/s_demon.lua +++ /dev/null @@ -1,166 +0,0 @@ --- handle the demonology school - --- Demonblade -DEMON_BLADE = add_spell -{ - ["name"] = "Demon Blade", - ["school"] = {SCHOOL_DEMON}, - ["level"] = 1, - ["mana"] = 4, - ["mana_max"] = 44, - ["fail"] = 10, - ["random"] = 0, - ["stick"] = - { - ["charge"] = { 3, 7 }, - [TV_WAND] = - { - ["rarity"] = 75, - ["base_level"] = { 1, 17 }, - ["max_level"] = { 20, 40 }, - }, - }, - ["spell"] = function() return demonology_demon_blade() end, - ["info"] = function() return demonology_demon_blade_info() end, - ["desc"] = { - "Imbues your blade with fire to deal more damage", - "At level 30 it deals hellfire damage", - "At level 45 it spreads over a 1 radius zone around your target", - } -} - -DEMON_MADNESS = add_spell -{ - ["name"] = "Demon Madness", - ["school"] = {SCHOOL_DEMON}, - ["level"] = 10, - ["mana"] = 5, - ["mana_max"] = 20, - ["fail"] = 25, - ["random"] = 0, - ["spell"] = function() return demonology_demon_madness() end, - ["info"] = function() return demonology_demon_madness_info() end, - ["desc"] = { - "Fire 2 balls in opposite directions of randomly chaos, confusion or charm", - } -} - -DEMON_FIELD = add_spell -{ - ["name"] = "Demon Field", - ["school"] = {SCHOOL_DEMON}, - ["level"] = 20, - ["mana"] = 20, - ["mana_max"] = 60, - ["fail"] = 60, - ["random"] = 0, - ["spell"] = function() return demonology_demon_field() end, - ["info"] = function() return demonology_demon_field_info() end, - ["desc"] = { - "Fires a cloud of deadly nexus over a radius of 7", - } -} - --- Demonshield - -DOOM_SHIELD = add_spell -{ - ["name"] = "Doom Shield", - ["school"] = {SCHOOL_DEMON}, - ["level"] = 1, - ["mana"] = 2, - ["mana_max"] = 30, - ["fail"] = 10, - ["random"] = 0, - ["spell"] = function() return demonology_doom_shield() end, - ["info"] = function() return demonology_doom_shield_info() end, - ["desc"] = { - "Raises a mirror of pain around you, doing very high damage to your foes", - "that dare hit you, but greatly reduces your armour class", - } -} - -UNHOLY_WORD = add_spell -{ - ["name"] = "Unholy Word", - ["school"] = {SCHOOL_DEMON}, - ["level"] = 25, - ["mana"] = 15, - ["mana_max"] = 45, - ["fail"] = 55, - ["random"] = 0, - ["spell"] = function() return demonology_unholy_word() end, - ["info"] = function() return demonology_unholy_word_info() end, - ["desc"] = { - "Kills a pet to heal you", - "There is a chance that the pet won't die but will turn against you", - "it will decrease with higher level", - } -} - -DEMON_CLOAK = add_spell -{ - ["name"] = "Demon Cloak", - ["school"] = {SCHOOL_DEMON}, - ["level"] = 20, - ["mana"] = 10, - ["mana_max"] = 40, - ["fail"] = 70, - ["random"] = 0, - ["spell"] = function() return demonology_demon_cloak() end, - ["info"] = function() return demonology_demon_cloak_info() end, - ["desc"] = { - "Raises a mirror that can reflect bolts and arrows for a time", - } -} - - --- Demonhorn -DEMON_SUMMON = add_spell -{ - ["name"] = "Summon Demon", - ["school"] = {SCHOOL_DEMON}, - ["level"] = 5, - ["mana"] = 10, - ["mana_max"] = 50, - ["fail"] = 30, - ["random"] = 0, - ["spell"] = function() return demonology_summon_demon() end, - ["info"] = function() return demonology_summon_demon_info() end, - ["desc"] = { - "Summons a leveled demon to your side", - "At level 35 it summons a high demon", - } -} - -DISCHARGE_MINION = add_spell -{ - ["name"] = "Discharge Minion", - ["school"] = {SCHOOL_DEMON}, - ["level"] = 10, - ["mana"] = 20, - ["mana_max"] = 50, - ["fail"] = 30, - ["random"] = 0, - ["spell"] = function() return demonology_discharge_minion() end, - ["info"] = function() return demonology_discharge_minion_info() end, - ["desc"] = { - "The targeted pet will explode in a burst of gravity", - } -} - -CONTROL_DEMON = add_spell -{ - ["name"] = "Control Demon", - ["school"] = {SCHOOL_DEMON}, - ["level"] = 25, - ["mana"] = 30, - ["mana_max"] = 70, - ["fail"] = 55, - ["random"] = 0, - ["spell"] = function() return demonology_control_demon() end, - ["info"] = function() return demonology_control_demon_info() end, - ["desc"] = { - "Attempts to control a demon", - } -} diff --git a/lib/scpt/s_divin.lua b/lib/scpt/s_divin.lua deleted file mode 100644 index e077f1f0..00000000 --- a/lib/scpt/s_divin.lua +++ /dev/null @@ -1,153 +0,0 @@ --- Handles thhe divination school - - -STARIDENTIFY = add_spell -{ - ["name"] = "Greater Identify", - ["school"] = {SCHOOL_DIVINATION}, - ["level"] = 35, - ["mana"] = 30, - ["mana_max"] = 30, - ["fail"] = 80, - ["spell"] = function() return divination_greater_identify() end, - ["info"] = function() return divination_greater_identify_info() end, - ["desc"] = { - "Asks for an object and fully identify it, providing the full list of powers", - "Cast at yourself it will reveal your powers" - } -} - -IDENTIFY = add_spell -{ - ["name"] = "Identify", - ["school"] = {SCHOOL_DIVINATION}, - ["level"] = 8, - ["mana"] = 10, - ["mana_max"] = 50, - ["fail"] = 40, - ["stick"] = - { - ["charge"] = { 7, 10 }, - [TV_STAFF] = - { - ["rarity"] = 45, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 15, 40 }, - }, - }, - ["spell"] = function() return divination_identify() end, - ["info"] = function() return divination_identify_info() end, - ["desc"] = { - "Asks for an object and identifies it", - "At level 17 it identifies all objects in the inventory", - "At level 27 it identifies all objects in the inventory and in a", - "radius on the floor, as well as probing monsters in that radius" - } -} - -VISION = add_spell -{ - ["name"] = "Vision", - ["school"] = {SCHOOL_DIVINATION}, - ["level"] = 15, - ["mana"] = 7, - ["mana_max"] = 55, - ["fail"] = 45, - ["stick"] = - { - ["charge"] = { 4, 6 }, - [TV_STAFF] = - { - ["rarity"] = 60, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 10, 30 }, - }, - }, - ["inertia"] = { 2, 200 }, - ["spell"] = function() return divination_vision() end, - ["info"] = function() return divination_vision_info() end, - ["desc"] = { - "Detects the layout of the surrounding area", - "At level 25 it maps and lights the whole level", - } -} - -SENSEHIDDEN = add_spell -{ - ["name"] = "Sense Hidden", - ["school"] = {SCHOOL_DIVINATION}, - ["level"] = 5, - ["mana"] = 2, - ["mana_max"] = 10, - ["fail"] = 25, - ["stick"] = - { - ["charge"] = { 1, 15 }, - [TV_STAFF] = - { - ["rarity"] = 20, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 10, 50 }, - }, - }, - ["inertia"] = { 1, 10 }, - ["spell"] = function() return divination_sense_hidden() end, - ["info"] = function() return divination_sense_hidden_info() end, - ["desc"] = { - "Detects the traps in a certain radius around you", - "At level 15 it allows you to sense invisible for a while" - } -} - -REVEALWAYS = add_spell -{ - ["name"] = "Reveal Ways", - ["school"] = {SCHOOL_DIVINATION}, - ["level"] = 9, - ["mana"] = 3, - ["mana_max"] = 15, - ["fail"] = 20, - ["stick"] = - { - ["charge"] = { 6, 6 }, - [TV_STAFF] = - { - ["rarity"] = 35, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 25, 50 }, - }, - }, - ["inertia"] = { 1, 10 }, - ["spell"] = function() return divination_reveal_ways() end, - ["info"] = function() return divination_reveal_ways_info() end, - ["desc"] = { - "Detects the doors/stairs/ways in a certain radius around you", - } -} - -SENSEMONSTERS = add_spell -{ - ["name"] = "Sense Monsters", - ["school"] = {SCHOOL_DIVINATION}, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 20, - ["fail"] = 10, - ["stick"] = - { - ["charge"] = { 5, 10 }, - [TV_STAFF] = - { - ["rarity"] = 37, - ["base_level"] = { 1, 10 }, - ["max_level"] = { 15, 40 }, - }, - }, - ["inertia"] = { 1, 10 }, - ["spell"] = function() return divination_sense_monsters() end, - ["info"] = function() return divination_sense_monsters_info() end, - ["desc"] = { - "Detects all monsters near you", - "At level 30 it allows you to sense monster minds for a while" - } -} diff --git a/lib/scpt/s_earth.lua b/lib/scpt/s_earth.lua deleted file mode 100644 index 9825fc84..00000000 --- a/lib/scpt/s_earth.lua +++ /dev/null @@ -1,123 +0,0 @@ --- The earth school - -STONESKIN = add_spell -{ - ["name"] = "Stone Skin", - ["school"] = SCHOOL_EARTH, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 50, - ["fail"] = 10, - ["inertia"] = { 2, 50 }, - ["spell"] = function() return earth_stone_skin() end, - ["info"] = function() return earth_stone_skin_info() end, - ["desc"] = { - "Creates a shield of earth around you to protect you", - "At level 25 it starts dealing damage to attackers" - } -} - -DIG = add_spell -{ - ["name"] = "Dig", - ["school"] = SCHOOL_EARTH, - ["level"] = 12, - ["mana"] = 14, - ["mana_max"] = 14, - ["fail"] = 20, - ["stick"] = - { - ["charge"] = { 15, 5 }, - [TV_WAND] = - { - ["rarity"] = 25, - ["base_level"] = { 1, 1 }, - ["max_level"] = { 1, 1 }, - }, - }, - ["spell"] = function() return earth_dig() end, - ["info"] = function() return earth_dig_info() end, - ["desc"] = { - "Digs a hole in a wall much faster than any shovels", - } -} - -STONEPRISON = add_spell -{ - ["name"] = "Stone Prison", - ["school"] = SCHOOL_EARTH, - ["level"] = 25, - ["mana"] = 30, - ["mana_max"] = 50, - ["fail"] = 65, - ["stick"] = - { - ["charge"] = { 5, 3 }, - [TV_WAND] = - { - ["rarity"] = 57, - ["base_level"] = { 1, 3 }, - ["max_level"] = { 5, 20 }, - }, - }, - ["spell"] = function() return earth_stone_prison() end, - ["info"] = function() return earth_stone_prison_info() end, - ["desc"] = { - "Creates a prison of walls around you", - "At level 10 it allows you to target a monster" - } -} - -STRIKE = add_spell -{ - ["name"] = "Strike", - ["school"] = {SCHOOL_EARTH}, - ["level"] = 30, - ["mana"] = 30, - ["mana_max"] = 50, - ["fail"] = 60, - ["stick"] = - { - ["charge"] = { 2, 6 }, - [TV_WAND] = - { - ["rarity"] = 635, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 10, 50 }, - }, - }, - ["spell"] = function() return earth_strike() end, - ["info"] = function() return earth_strike_info() end, - ["desc"] = { - "Creates a micro-ball of force that will push monsters backwards", - "If the monster is caught near a wall, it'll be crushed against it", - "At level 12 it turns into a ball of radius 1" - } -} - -SHAKE = add_spell -{ - ["name"] = "Shake", - ["school"] = {SCHOOL_EARTH}, - ["level"] = 27, - ["mana"] = 25, - ["mana_max"] = 30, - ["fail"] = 60, - ["stick"] = - { - ["charge"] = { 5, 10 }, - [TV_STAFF] = - { - ["rarity"] = 75, - ["base_level"] = { 1, 3 }, - ["max_level"] = { 9, 20 }, - }, - }, - ["inertia"] = { 2, 50 }, - ["spell"] = function() return earth_shake() end, - ["info"] = function() return earth_shake_info() end, - ["desc"] = { - "Creates a localised earthquake", - "At level 10 it can be targeted at any location" - } -} diff --git a/lib/scpt/s_eru.lua b/lib/scpt/s_eru.lua deleted file mode 100644 index d61b6118..00000000 --- a/lib/scpt/s_eru.lua +++ /dev/null @@ -1,88 +0,0 @@ --- Handle Eru Iluvatar magic school - -ERU_SEE = add_spell -{ - ["name"] = "See the Music", - ["school"] = {SCHOOL_ERU}, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 50, - ["fail"] = 20, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - -- Unnafected by blindness - ["blind"] = FALSE, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return eru_see_the_music() end, - ["info"] = function() return eru_see_the_music_info() end, - ["desc"] = { - "Allows you to 'see' the Great Music from which the world", - "originates, allowing you to see unseen things", - "At level 10 it allows you to see your surroundings", - "At level 20 it allows you to cure blindness", - "At level 30 it allows you to fully see all the level" - } -} - -ERU_LISTEN = add_spell -{ - ["name"] = "Listen to the Music", - ["school"] = {SCHOOL_ERU}, - ["level"] = 7, - ["mana"] = 15, - ["mana_max"] = 200, - ["fail"] = 25, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return eru_listen_to_the_music() end, - ["info"] = function() return eru_listen_to_the_music_info() end, - ["desc"] = { - "Allows you to listen to the Great Music from which the world", - "originates, allowing you to understand the meaning of things", - "At level 14 it allows you to identify all your pack", - "At level 30 it allows you to identify all items on the level", - } -} - -ERU_UNDERSTAND = add_spell -{ - ["name"] = "Know the Music", - ["school"] = {SCHOOL_ERU}, - ["level"] = 30, - ["mana"] = 200, - ["mana_max"] = 600, - ["fail"] = 50, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return eru_know_the_music() end, - ["info"] = function() return eru_know_the_music_info() end, - ["desc"] = { - "Allows you to understand the Great Music from which the world", - "originates, allowing you to know the full abilities of things", - "At level 10 it allows you to *identify* all your pack", - } -} - -ERU_PROT = add_spell -{ - ["name"] = "Lay of Protection", - ["school"] = {SCHOOL_ERU}, - ["level"] = 35, - ["mana"] = 400, - ["mana_max"] = 400, - ["fail"] = 80, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return eru_lay_of_protection() end, - ["info"] = function() return eru_lay_of_protection_info() end, - ["desc"] = { - "Creates a circle of safety around you", - } -} diff --git a/lib/scpt/s_fire.lua b/lib/scpt/s_fire.lua deleted file mode 100644 index 37a75032..00000000 --- a/lib/scpt/s_fire.lua +++ /dev/null @@ -1,134 +0,0 @@ --- handle the fire school - -GLOBELIGHT = add_spell -{ - ["name"] = "Globe of Light", - ["school"] = {SCHOOL_FIRE}, - ["level"] = 1, - ["mana"] = 2, - ["mana_max"] = 15, - ["fail"] = 10, - ["stick"] = - { - ["charge"] = { 10, 5 }, - [TV_STAFF] = - { - ["rarity"] = 7, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 10, 45 }, - }, - }, - ["inertia"] = { 1, 40 }, - ["spell"] = function() return fire_globe_of_light() end, - ["info"] = function() return fire_globe_of_light_info() end, - ["desc"] = { - "Creates a globe of pure light", - "At level 3 it starts damaging monsters", - "At level 15 it starts creating a more powerful kind of light", - } -} - -FIREFLASH = add_spell -{ - ["name"] = "Fireflash", - ["school"] = {SCHOOL_FIRE}, - ["level"] = 10, - ["mana"] = 5, - ["mana_max"] = 70, - ["fail"] = 35, - ["stick"] = - { - ["charge"] = { 5, 5 }, - [TV_WAND] = - { - ["rarity"] = 35, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 15, 35 }, - }, - }, - ["spell"] = function() return fire_fireflash() end, - ["info"] = function() return fire_fireflash_info() end, - ["desc"] = { - "Conjures a ball of fire to burn your foes to ashes", - "At level 20 it turns into a ball of holy fire" - } -} - -FIERYAURA = add_spell -{ - ["name"] = "Fiery Shield", - ["school"] = {SCHOOL_FIRE}, - ["level"] = 20, - ["mana"] = 20, - ["mana_max"] = 60, - ["fail"] = 50, - ["stick"] = - { - ["charge"] = { 3, 5 }, - [TV_STAFF] = - { - ["rarity"] = 50, - ["base_level"] = { 1, 10 }, - ["max_level"] = { 5, 40 }, - }, - }, - ["inertia"] = { 2, 15 }, - ["spell"] = function() return fire_fiery_shield() end, - ["info"] = function() return fire_fiery_shield_info() end, - ["desc"] = { - "Creates a shield of fierce flames around you", - "At level 8 it turns into a greater kind of flame that can not be resisted" - } -} - -FIREWALL = add_spell -{ - ["name"] = "Firewall", - ["school"] = {SCHOOL_FIRE}, - ["level"] = 15, - ["mana"] = 25, - ["mana_max"] = 100, - ["fail"] = 40, - ["stick"] = - { - ["charge"] = { 4, 5 }, - [TV_WAND] = - { - ["rarity"] = 55, - ["base_level"] = { 1, 10 }, - ["max_level"] = { 5, 40 }, - }, - }, - ["spell"] = function() return fire_firewall() end, - ["info"] = function() return fire_firewall_info() end, - ["desc"] = { - "Creates a fiery wall to incinerate monsters stupid enough to attack you", - "At level 6 it turns into a wall of hell fire" - } -} - -FIREGOLEM = add_spell -{ - ["name"] = "Fire Golem", - ["school"] = {SCHOOL_FIRE, SCHOOL_MIND}, - ["level"] = 7, - ["mana"] = 16, - ["mana_max"] = 70, - ["fail"] = 40, - ["spell"] = function() return fire_golem() end, - ["info"] = function() return fire_golem_info() end, - ["desc"] = { - "Creates a fiery golem and controls it", - "During the control the available keylist is:", - "Movement keys: movement of the golem(depending on its speed", - " it can move more than one square)", - ", : pickup all items on the floor", - "d : drop all carried items", - "i : list all carried items", - "m : end the possession/use golem powers", - "Most of the other keys are disabled, you cannot interact with your", - "real body while controlling the golem", - "But to cast the spell you will need a lantern or a wooden torch to", - "Create the golem from" - } -} diff --git a/lib/scpt/s_geom.lua b/lib/scpt/s_geom.lua deleted file mode 100644 index d250f38d..00000000 --- a/lib/scpt/s_geom.lua +++ /dev/null @@ -1,177 +0,0 @@ --- Geomancy school - -CALL_THE_ELEMENTS = add_spell -{ - ["name"] = "Call the Elements", - ["school"] = {SCHOOL_GEOMANCY}, - ["level"] = 1, - ["mana"] = 2, - ["mana_max"] = 20, - ["fail"] = 10, - -- Unnafected by blindness - ["blind"] = FALSE, - ["random"] = 0, - ["spell"] = function() return geomancy_call_the_elements() end, - ["info"] = function() return geomancy_call_the_elements_info() end, - ["desc"] = { - "Randomly creates various elements around you", - "Each type of element chance is controlled by your level", - "in the corresponding skill", - "At level 17 it can be targeted", - } -} - -CHANNEL_ELEMENTS = add_spell -{ - ["name"] = "Channel Elements", - ["school"] = {SCHOOL_GEOMANCY}, - ["level"] = 3, - ["mana"] = 3, - ["mana_max"] = 30, - ["fail"] = 20, - -- Unnafected by blindness - ["blind"] = FALSE, - ["random"] = 0, - ["spell"] = function() return geomancy_channel_elements() end, - ["info"] = function() return geomancy_channel_elements_info() end, - ["desc"] = { - "Draws on the caster's immediate environs to form an attack or other effect.", - "Grass/Flower heals.", - "Water creates water bolt attacks.", - "Ice creates ice bolt attacks.", - "Sand creates a wall of thick, blinding, burning sand around you.", - "Lava creates fire bolt attacks.", - "Deep lava creates fire ball attacks.", - "Chasm creates darkness bolt attacks.", - "At Earth level 18, darkness becomes nether.", - "At Water level 8, water attacks become beams with a striking effect.", - "At Water level 12, ice attacks become balls of ice shards.", - "At Water level 18, water attacks push monsters back.", - "At Fire level 15, fire become hellfire.", - } -} - -ELEMENTAL_WAVE = add_spell -{ - ["name"] = "Elemental Wave", - ["school"] = {SCHOOL_GEOMANCY}, - ["level"] = 15, - ["mana"] = 15, - ["mana_max"] = 50, - ["fail"] = 20, - -- Unnafected by blindness - ["blind"] = FALSE, - ["random"] = 0, - ["spell"] = function() return geomancy_elemental_wave() end, - ["info"] = function() return geomancy_elemental_wave_info() end, - ["desc"] = { - "Draws on an adjacent special square to project a slow-moving", - "wave of that element in that direction", - "Abyss squares cannot be channeled into a wave.", - } -} - -VAPORIZE = add_spell -{ - ["name"] = "Vaporize", - ["school"] = {SCHOOL_GEOMANCY}, - ["level"] = 4, - ["mana"] = 3, - ["mana_max"] = 30, - ["fail"] = 15, - -- Unnafected by blindness - ["blind"] = FALSE, - -- Must have at least 4 Air - ["random"] = 0, - ["depend"] = function() return geomancy_vaporize_depends() end, - ["spell"] = function() return geomancy_vaporize() end, - ["info"] = function() return geomancy_vaporize_info() end, - ["desc"] = { - "Draws upon your immediate environs to form a cloud of damaging vapors", - } -} - -GEOLYSIS = add_spell -{ - ["name"] = "Geolysis", - ["school"] = {SCHOOL_GEOMANCY}, - ["level"] = 7, - ["mana"] = 15, - ["mana_max"] = 40, - ["fail"] = 15, - -- Unnafected by blindness - ["blind"] = FALSE, - ["random"] = 0, - -- Must have at least 7 Earth - ["depend"] = function() return geomancy_geolysis_depends() end, - ["spell"] = function() return geomancy_geolysis() end, - ["info"] = function() return geomancy_geolysis_info() end, - ["desc"] = { - "Burrows deeply and slightly at random into a wall,", - "leaving behind tailings of various different sorts of walls in the passage.", - } -} - -DRIPPING_TREAD = add_spell -{ - ["name"] = "Dripping Tread", - ["school"] = {SCHOOL_GEOMANCY}, - ["level"] = 10, - ["mana"] = 15, - ["mana_max"] = 25, - ["fail"] = 15, - -- Unnafected by blindness - ["blind"] = FALSE, - ["random"] = 0, - -- Must have at least 10 Water - ["depend"] = function() return geomancy_dripping_tread_depends() end, - ["spell"] = function() return geomancy_dripping_tread() end, - ["info"] = function() return geomancy_dripping_tread_info() end, - ["desc"] = { - "Causes you to leave random elemental forms behind as you walk", - } -} - -GROW_BARRIER = add_spell -{ - ["name"] = "Grow Barrier", - ["school"] = {SCHOOL_GEOMANCY}, - ["level"] = 12, - ["mana"] = 30, - ["mana_max"] = 40, - ["fail"] = 15, - -- Unnafected by blindness - ["blind"] = FALSE, - ["random"] = 0, - -- Must have at least 12 Earth - ["depend"] = function() return geomancy_grow_barrier_depends() end, - ["spell"] = function() return geomancy_grow_barrier() end, - ["info"] = function() return geomancy_grow_barrier_info() end, - ["desc"] = { - "Creates impassable terrain (walls, trees, etc.) around you.", - "At level 20 it can be projected around another area.", - } -} - -ELEMENTAL_MINION = add_spell -{ - ["name"] = "Elemental Minion", - ["school"] = {SCHOOL_GEOMANCY}, - ["level"] = 20, - ["mana"] = 40, - ["mana_max"] = 80, - ["fail"] = 25, - -- Unnafected by blindness - ["random"] = 0, - -- Must have at least 12 Earth - ["spell"] = function() return geomancy_elemental_minion() end, - ["info"] = function() return geomancy_elemental_minion_info() end, - ["desc"] = { - "Summons a minion from a nearby element.", - "Walls can summon Earth elmentals, Xorns and Xarens", - "Dark Pits can summon Air elementals, Ancient blue dragons, Great Storm Wyrms", - "and Sky Drakes", - "Sandwalls and lava can summon Fire elementals and Ancient red dragons", - "Icewall, and water can summon Water elementals, Water trolls and Water demons", - } -} diff --git a/lib/scpt/s_mana.lua b/lib/scpt/s_mana.lua deleted file mode 100644 index 67126fb2..00000000 --- a/lib/scpt/s_mana.lua +++ /dev/null @@ -1,89 +0,0 @@ --- The mana school - -MANATHRUST = add_spell -{ - ["name"] = "Manathrust", - ["school"] = SCHOOL_MANA, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 25, - ["fail"] = 10, - ["stick"] = - { - ["charge"] = { 7, 10 }, - [TV_WAND] = - { - ["rarity"] = 5, - ["base_level"] = { 1, 20 }, - ["max_level"] = { 15, 33 }, - }, - }, - ["spell"] = function() return mana_manathrust() end, - ["info"] = function() return mana_manathrust_info() end, - ["desc"] = { - "Conjures up mana into a powerful bolt", - "The damage is irresistible and will increase with level" - } -} - -DELCURSES = add_spell -{ - ["name"] = "Remove Curses", - ["school"] = SCHOOL_MANA, - ["level"] = 10, - ["mana"] = 20, - ["mana_max"] = 40, - ["fail"] = 30, - ["stick"] = - { - ["charge"] = { 3, 8 }, - [TV_STAFF] = - { - ["rarity"] = 70, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 15, 50 }, - }, - }, - ["inertia"] = { 1, 10 }, - ["spell"] = function() return mana_remove_curses() end, - ["info"] = function() return mana_remove_curses_info() end, - ["desc"] = { - "Remove curses of worn objects", - "At level 20 switches to *remove curses*" - } -} - -RESISTS = add_spell -{ - ["name"] = "Elemental Shield", - ["school"] = SCHOOL_MANA, - ["level"] = 20, - ["mana"] = 17, - ["mana_max"] = 20, - ["fail"] = 40, - ["inertia"] = { 2, 25 }, - ["spell"] = function() return mana_elemental_shield() end, - ["info"] = function() return mana_elemental_shield_info() end, - ["desc"] = { - "Provide resistances to the four basic elements", - } -} - -MANASHIELD = add_spell -{ - ["name"] = "Disruption Shield", - ["school"] = SCHOOL_MANA, - ["level"] = 45, - ["mana"] = 50, - ["mana_max"] = 50, - ["fail"] = 90, - ["inertia"] = { 9, 10}, - ["spell"] = function() return mana_disruption_shield() end, - ["info"] = function() return mana_disruption_shield_info() end, - ["desc"] = { - "Uses mana instead of hp to take damage", - "At level 5 switches to Globe of Invulnerability.", - "The spell breaks as soon as a melee, shooting, throwing or magical", - "skill action is attempted, and lasts only a short time." - } -} diff --git a/lib/scpt/s_manwe.lua b/lib/scpt/s_manwe.lua deleted file mode 100644 index 189f50ff..00000000 --- a/lib/scpt/s_manwe.lua +++ /dev/null @@ -1,84 +0,0 @@ --- Handle Manwe Sulimo magic school - -MANWE_SHIELD = add_spell -{ - ["name"] = "Wind Shield", - ["school"] = {SCHOOL_MANWE}, - ["level"] = 10, - ["mana"] = 100, - ["mana_max"] = 500, - ["fail"] = 30, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return manwe_wind_shield() end, - ["info"] = function() return manwe_wind_shield_info() end, - ["desc"] = { - "It surrounds you with a shield of wind that deflects blows from evil monsters", - "At level 10 it increases your armour rating", - "At level 20 it retaliates against monsters that melee you", - } -} - -MANWE_AVATAR = add_spell -{ - ["name"] = "Avatar", - ["school"] = {SCHOOL_MANWE}, - ["level"] = 35, - ["mana"] = 1000, - ["mana_max"] = 1000, - ["fail"] = 80, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return manwe_avatar() end, - ["info"] = function() return manwe_avatar_info() end, - ["desc"] = { - "It turns you into a full grown Maia", - } -} - -MANWE_BLESS = add_spell -{ - ["name"] = "Manwe's Blessing", - ["school"] = {SCHOOL_MANWE}, - ["level"] = 1, - ["mana"] = 10, - ["mana_max"] = 100, - ["fail"] = 20, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return manwe_blessing() end, - ["info"] = function() return manwe_blessing_info() end, - ["desc"] = { - "Manwe's Blessing removes your fears, blesses you and surrounds you with", - "holy light", - "At level 10 it also grants heroism", - "At level 20 it also grants super heroism", - "At level 30 it also grants holy luck and life protection", - } -} - -MANWE_CALL = add_spell -{ - ["name"] = "Manwe's Call", - ["school"] = {SCHOOL_MANWE}, - ["level"] = 20, - ["mana"] = 200, - ["mana_max"] = 500, - ["fail"] = 40, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return manwe_call() end, - ["info"] = function() return manwe_call_info() end, - ["desc"] = { - "Manwe's Call summons a Great Eagle to help you battle the forces", - "of Morgoth" - } -} diff --git a/lib/scpt/s_melkor.lua b/lib/scpt/s_melkor.lua deleted file mode 100644 index 701dca7a..00000000 --- a/lib/scpt/s_melkor.lua +++ /dev/null @@ -1,64 +0,0 @@ --- handle the melkor school - -MELKOR_CURSE = add_spell -{ - ["name"] = "Curse", - ["school"] = {SCHOOL_MELKOR}, - ["level"] = 1, - ["mana"] = 50, - ["mana_max"] = 300, - ["fail"] = 20, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return melkor_curse() end, - ["info"] = function() return melkor_curse_info() end, - ["desc"] = { - "It curses a monster, reducing its melee power", - "At level 5 it can be auto-casted (with no piety cost) while fighting", - "At level 15 it also reduces armor", - "At level 25 it also reduces speed", - "At level 35 it also reduces max life (but it is never fatal)", - } -} - -MELKOR_CORPSE_EXPLOSION = add_spell -{ - ["name"] = "Corpse Explosion", - ["school"] = {SCHOOL_MELKOR}, - ["level"] = 10, - ["mana"] = 100, - ["mana_max"] = 500, - ["fail"] = 45, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return melkor_corpse_explosion() end, - ["info"] = function() return melkor_corpse_explosion_info() end, - ["desc"] = { - "It makes corpses in an area around you explode for a percent of their", - "hit points as damage", - } -} - -MELKOR_MIND_STEAL = add_spell -{ - ["name"] = "Mind Steal", - ["school"] = {SCHOOL_MELKOR}, - ["level"] = 20, - ["mana"] = 1000, - ["mana_max"] = 3000, - ["fail"] = 90, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return melkor_mind_steal() end, - ["info"] = function() return melkor_mind_steal_info() end, - ["desc"] = { - "It allows your spirit to temporarily leave your own body, which will", - "be vulnerable, to control one of your enemies body." - } -} diff --git a/lib/scpt/s_meta.lua b/lib/scpt/s_meta.lua deleted file mode 100644 index 9040e3af..00000000 --- a/lib/scpt/s_meta.lua +++ /dev/null @@ -1,104 +0,0 @@ --- handle the meta school - -RECHARGE = add_spell -{ - ["name"] = "Recharge", - ["school"] = {SCHOOL_META}, - ["level"] = 5, - ["mana"] = 10, - ["mana_max"] = 100, - ["fail"] = 20, - ["spell"] = function() return meta_recharge() end, - ["info"] = function() return meta_recharge_info() end, - ["desc"] = { - "Taps on the ambient mana to recharge an object's power (charges or mana)", - } -} - -SPELLBINDER = add_spell -{ - ["name"] = "Spellbinder", - ["school"] = {SCHOOL_META}, - ["level"] = 20, - ["mana"] = 100, - ["mana_max"] = 300, - ["fail"] = 85, - ["spell"] = function() return meta_spellbinder() end, - ["info"] = function() return meta_spellbinder_info() end, - ["desc"] = { - "Stores spells in a trigger.", - "When the condition is met all spells fire off at the same time", - "This spell takes a long time to cast so you are advised to prepare it", - "in a safe area.", - "Also it will use the mana for the Spellbinder and the mana for the", - "selected spells" - } -} - -DISPERSEMAGIC = add_spell -{ - ["name"] = "Disperse Magic", - ["school"] = {SCHOOL_META}, - ["level"] = 15, - ["mana"] = 30, - ["mana_max"] = 60, - ["fail"] = 40, - -- Unnafected by blindness - ["blind"] = FALSE, - -- Unnafected by confusion - ["confusion"] = FALSE, - ["stick"] = - { - ["charge"] = { 5, 5 }, - [TV_WAND] = - { - ["rarity"] = 25, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 5, 40 }, - }, - }, - ["inertia"] = { 1, 5 }, - ["spell"] = function() return meta_disperse_magic() end, - ["info"] = function() return meta_disperse_magic_info() end, - ["desc"] = { - "Dispels a lot of magic that can affect you, be it good or bad", - "Level 1: blindness and light", - "Level 5: confusion and hallucination", - "Level 10: speed (both bad or good) and light speed", - "Level 15: stunning, meditation, cuts", - "Level 20: hero, super hero, bless, shields, afraid, parasites, mimicry", - } -} - -TRACKER = add_spell -{ - ["name"] = "Tracker", - ["school"] = {SCHOOL_META, SCHOOL_CONVEYANCE}, - ["level"] = 30, - ["mana"] = 50, - ["mana_max"] = 50, - ["fail"] = 95, - ["spell"] = function() return meta_tracker() end, - ["info"] = function() return meta_tracker_info() end, - ["desc"] = { - "Tracks down the last teleportation that happened on the level and teleports", - "you to it", - } -} - -INERTIA_CONTROL = add_spell -{ - ["name"] = "Inertia Control", - ["school"] = {SCHOOL_META}, - ["level"] = 37, - ["mana"] = 300, - ["mana_max"] = 700, - ["fail"] = 95, - ["spell"] = function() return meta_inertia_control() end, - ["info"] = function() return meta_inertia_control_info() end, - ["desc"] = { - "Changes the energy flow of a spell to be continuously recasted", - "at a given interval. The inertia controlled spell reduces your", - "maximum mana by four times its cost.", - } -} diff --git a/lib/scpt/s_mind.lua b/lib/scpt/s_mind.lua deleted file mode 100644 index 7f24709b..00000000 --- a/lib/scpt/s_mind.lua +++ /dev/null @@ -1,88 +0,0 @@ --- handle the mind school - -CHARM = add_spell -{ - ["name"] = "Charm", - ["school"] = {SCHOOL_MIND}, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 20, - ["fail"] = 10, - ["stick"] = - { - ["charge"] = { 7, 5 }, - [TV_WAND] = - { - ["rarity"] = 35, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 20, 40 }, - }, - }, - ["spell"] = function() return mind_charm() end, - ["info"] = function() return mind_charm_info() end, - ["desc"] = { - "Tries to manipulate the mind of a monster to make it friendly", - "At level 15 it turns into a ball", - "At level 35 it affects all monsters in sight" - } -} - -CONFUSE = add_spell -{ - ["name"] = "Confuse", - ["school"] = {SCHOOL_MIND}, - ["level"] = 5, - ["mana"] = 5, - ["mana_max"] = 30, - ["fail"] = 20, - ["stick"] = - { - ["charge"] = { 3, 4 }, - [TV_WAND] = - { - ["rarity"] = 45, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 20, 40 }, - }, - }, - ["spell"] = function() return mind_confuse() end, - ["info"] = function() return mind_confuse_info() end, - ["desc"] = { - "Tries to manipulate the mind of a monster to confuse it", - "At level 15 it turns into a ball", - "At level 35 it affects all monsters in sight" - } -} - -ARMOROFFEAR = add_spell -{ - ["name"] = "Armor of Fear", - ["school"] = SCHOOL_MIND, - ["level"] = 10, - ["mana"] = 10, - ["mana_max"] = 50, - ["fail"] = 35, - ["inertia"] = { 2, 20 }, - ["spell"] = function() return mind_armor_of_fear() end, - ["info"] = function() return mind_armor_of_fear_info() end, - ["desc"] = { - "Creates a shield of pure fear around you. Any monster attempting to hit you", - "must save or flee", - } -} - -STUN = add_spell -{ - ["name"] = "Stun", - ["school"] = {SCHOOL_MIND}, - ["level"] = 15, - ["mana"] = 10, - ["mana_max"] = 90, - ["fail"] = 45, - ["spell"] = function() return mind_stun() end, - ["info"] = function() return mind_stun_info() end, - ["desc"] = { - "Tries to manipulate the mind of a monster to stun it", - "At level 20 it turns into a ball", - } -} diff --git a/lib/scpt/s_music.lua b/lib/scpt/s_music.lua deleted file mode 100644 index 45255485..00000000 --- a/lib/scpt/s_music.lua +++ /dev/null @@ -1,268 +0,0 @@ --- handle the music school --- *ALL* lasting spell must return the mana cost in the lasting function - -MUSIC_STOP = add_spell -{ - ["name"] = "Stop singing(I)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 1, - ["mana"] = 0, - ["mana_max"] = 0, - ["fail"] = -400, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 1, - ["blind"] = FALSE, - ["spell"] = function() return music_stop_singing_spell() end, - ["info"] = function() return music_stop_singing_info() end, - ["desc"] = { - "Stops the current song, if any." - } -} - ---- Drums -MUSIC_HOLD = add_spell -{ - ["name"] = "Holding Pattern(I)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 10, - ["fail"] = 20, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 1, - ["blind"] = FALSE, - ["lasting"] = function() return music_holding_pattern_lasting() end, - ["spell"] = function() return music_holding_pattern_spell() end, - ["info"] = function() return music_holding_pattern_info() end, - ["desc"] = { - "Slows down all monsters listening the song.", - "Consumes the amount of mana each turn.", - } -} - -MUSIC_CONF = add_spell -{ - ["name"] = "Illusion Pattern(II)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 5, - ["mana"] = 2, - ["mana_max"] = 15, - ["fail"] = 30, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 2, - ["blind"] = FALSE, - ["lasting"] = function() return music_illusion_pattern_lasting() end, - ["spell"] = function() return music_illusion_pattern_spell() end, - ["info"] = function() return music_illusion_pattern_info() end, - ["desc"] = { - "Tries to confuse all monsters listening the song.", - "Consumes the amount of mana each turn.", - } -} - -MUSIC_STUN = add_spell -{ - ["name"] = "Stun Pattern(IV)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 10, - ["mana"] = 3, - ["mana_max"] = 25, - ["fail"] = 45, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 4, - ["blind"] = FALSE, - ["lasting"] = function() return music_stun_pattern_lasting() end, - ["spell"] = function() return music_stun_pattern_spell() end, - ["info"] = function() return music_stun_pattern_info() end, - ["desc"] = { - "Stuns all monsters listening the song.", - "Consumes the amount of mana each turn.", - } -} - ---- Harps -MUSIC_LITE = add_spell -{ - ["name"] = "Song of the Sun(I)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 1, - ["fail"] = 20, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["blind"] = FALSE, - ["pval"] = 1, - ["lasting"] = function() return music_song_of_the_sun_lasting() end, - ["spell"] = function() return music_song_of_the_sun_spell() end, - ["info"] = function() return music_song_of_the_sun_info() end, - ["desc"] = { - "Provides light as long as you sing.", - "Consumes the amount of mana each turn.", - } -} - -MUSIC_HEAL = add_spell -{ - ["name"] = "Flow of Life(II)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 7, - ["mana"] = 5, - ["mana_max"] = 30, - ["fail"] = 35, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 2, - ["lasting"] = function() return music_flow_of_life_lasting() end, - ["spell"] = function() return music_flow_of_life_spell() end, - ["info"] = function() return music_flow_of_life_info() end, - ["desc"] = { - "Heals you as long as you sing.", - "Consumes the amount of mana each turn.", - } -} - -MUSIC_HERO = add_spell -{ - ["name"] = "Heroic Ballad(II)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 10, - ["mana"] = 4, - ["mana_max"] = 14, - ["fail"] = 45, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 2, - ["lasting"] = function() return music_heroic_ballad_lasting() end, - ["spell"] = function() return music_heroic_ballad_spell() end, - ["info"] = function() return music_heroic_ballad_info() end, - ["desc"] = { - "Increases melee accuracy", - "At level 10 it increases it even more and reduces armour a bit", - "At level 20 it increases it again", - "At level 25 it grants protection against chaos and confusion", - "Consumes the amount of mana each turn.", - } -} - -MUSIC_TIME = add_spell -{ - ["name"] = "Hobbit Melodies(III)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 20, - ["mana"] = 10, - ["mana_max"] = 30, - ["fail"] = 70, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 3, - ["lasting"] = function() return music_hobbit_melodies_lasting() end, - ["spell"] = function() return music_hobbit_melodies_spell() end, - ["info"] = function() return music_hobbit_melodies_info() end, - ["desc"] = { - "Greatly increases your reflexes allowing you to block more melee blows.", - "At level 15 it also makes you faster.", - "Consumes the amount of mana each turn.", - } -} - -MUSIC_MIND = add_spell -{ - ["name"] = "Clairaudience(IV)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 25, - ["mana"] = 15, - ["mana_max"] = 30, - ["fail"] = 75, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 4, - ["lasting"] = function() return music_clairaudience_lasting() end, - ["spell"] = function() return music_clairaudience_spell() end, - ["info"] = function() return music_clairaudience_info() end, - ["desc"] = { - "Allows you to sense monster minds as long as you sing.", - "At level 10 it identifies all objects in a radius on the floor,", - "as well as probing monsters in that radius.", - "Consumes the amount of mana each turn.", - } -} - ---- Horns - -MUSIC_BLOW = add_spell -{ - ["name"] = "Blow(I)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 4, - ["mana"] = 3, - ["mana_max"] = 30, - ["fail"] = 20, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 1, - ["spell"] = function() return music_blow_spell() end, - ["info"] = function() return music_blow_info() end, - ["desc"] = { - "Produces a powerful, blowing, sound all around you.", - } -} - -MUSIC_WIND = add_spell -{ - ["name"] = "Gush of Wind(II)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 14, - ["mana"] = 15, - ["mana_max"] = 45, - ["fail"] = 30, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 2, - ["spell"] = function() return music_gush_of_wind_spell() end, - ["info"] = function() return music_gush_of_wind_info() end, - ["desc"] = { - "Produces a outgoing gush of wind that sends monsters away.", - } -} - -MUSIC_YLMIR = add_spell -{ - ["name"] = "Horns of Ylmir(III)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 20, - ["mana"] = 25, - ["mana_max"] = 30, - ["fail"] = 20, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 3, - ["spell"] = function() return music_horns_of_ylmir_spell() end, - ["info"] = function() return music_horns_of_ylmir_info() end, - ["desc"] = { - "Produces an earth shaking sound.", - } -} - -MUSIC_AMBARKANTA = add_spell -{ - ["name"] = "Ambarkanta(IV)", - ["school"] = {SCHOOL_MUSIC}, - ["level"] = 25, - ["mana"] = 70, - ["mana_max"] = 70, - ["fail"] = 60, - ["stat"] = A_CHR, - ["random"] = SKILL_MUSIC, - ["pval"] = 4, - ["spell"] = function() return music_ambarkanta_spell() end, - ["info"] = function() return music_ambarkanta_info() end, - ["desc"] = { - "Produces a reality shaking sound that transports you to a nearly", - "identical reality.", - } -} diff --git a/lib/scpt/s_nature.lua b/lib/scpt/s_nature.lua deleted file mode 100644 index d47dbe8f..00000000 --- a/lib/scpt/s_nature.lua +++ /dev/null @@ -1,113 +0,0 @@ --- handle the nature school - -GROWTREE = add_spell -{ - ["name"] = "Grow Trees", - ["school"] = {SCHOOL_NATURE, SCHOOL_TEMPORAL}, - ["level"] = 6, - ["mana"] = 6, - ["mana_max"] = 30, - ["fail"] = 35, - ["inertia"] = { 5, 50 }, - ["spell"] = function() return nature_grow_trees() end, - ["info"] = function() return nature_grow_trees_info() end, - ["desc"] = { - "Makes trees grow extremely quickly around you", - } -} - -HEALING = add_spell -{ - ["name"] = "Healing", - ["school"] = {SCHOOL_NATURE}, - ["level"] = 10, - ["mana"] = 15, - ["mana_max"] = 50, - ["fail"] = 45, - ["stick"] = - { - ["charge"] = { 2, 3 }, - [TV_STAFF] = - { - ["rarity"] = 90, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 20, 40 }, - }, - }, - ["spell"] = function() return nature_healing() end, - ["info"] = function() return nature_healing_info() end, - ["desc"] = { - "Heals a percent of hitpoints", - } -} - -RECOVERY = add_spell -{ - ["name"] = "Recovery", - ["school"] = {SCHOOL_NATURE}, - ["level"] = 15, - ["mana"] = 10, - ["mana_max"] = 25, - ["fail"] = 60, - ["stick"] = - { - ["charge"] = { 5, 10 }, - [TV_STAFF] = - { - ["rarity"] = 50, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 10, 30 }, - }, - }, - ["inertia"] = { 2, 100 }, - ["spell"] = function() return nature_recovery() end, - ["info"] = function() return nature_recovery_info() end, - ["desc"] = { - "Reduces the length of time that you are poisoned", - "At level 5 it cures poison and cuts", - "At level 10 it restores drained stats", - "At level 15 it restores lost experience" - } -} - -REGENERATION = add_spell -{ - ["name"] = "Regeneration", - ["school"] = {SCHOOL_NATURE}, - ["level"] = 20, - ["mana"] = 30, - ["mana_max"] = 55, - ["fail"] = 70, - ["inertia"] = { 4, 40 }, - ["spell"] = function() return nature_regeneration() end, - ["info"] = function() return nature_regeneration_info() end, - ["desc"] = { - "Increases your body's regeneration rate", - } -} - - -SUMMONANNIMAL = add_spell -{ - ["name"] = "Summon Animal", - ["school"] = {SCHOOL_NATURE}, - ["level"] = 25, - ["mana"] = 25, - ["mana_max"] = 50, - ["fail"] = 90, - ["stick"] = - { - ["charge"] = { 1, 3 }, - [TV_WAND] = - { - ["rarity"] = 85, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 15, 45 }, - }, - }, - ["spell"] = function() return nature_summon_animal() end, - ["info"] = function() return nature_summon_animal_info() end, - ["desc"] = { - "Summons a leveled animal to your aid", - } -} diff --git a/lib/scpt/s_stick.lua b/lib/scpt/s_stick.lua deleted file mode 100644 index 8075db2f..00000000 --- a/lib/scpt/s_stick.lua +++ /dev/null @@ -1,289 +0,0 @@ --- Spells that are stick or artifacts/... only - -DEVICE_HEAL_MONSTER = add_spell -{ - ["name"] = "Heal Monster", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 3, - ["mana"] = 5, - ["mana_max"] = 20, - ["fail"] = 15, - ["random"] = -1, - ["stick"] = - { - ["charge"] = { 10, 10 }, - [TV_WAND] = - { - ["rarity"] = 17, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 20, 50 }, - }, - }, - ["spell"] = function() return device_heal_monster() end, - ["info"] = function() return device_heal_monster_info() end, - ["desc"] = { - "Heals a monster", - } -} - -DEVICE_SPEED_MONSTER = add_spell -{ - ["name"] = "Haste Monster", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 10, - ["mana"] = 10, - ["mana_max"] = 10, - ["fail"] = 30, - ["random"] = -1, - ["stick"] = - { - ["charge"] = { 10, 5 }, - [TV_WAND] = - { - ["rarity"] = 7, - ["base_level"] = { 1, 1 }, - ["max_level"] = { 20, 50 }, - }, - }, - ["spell"] = function() return device_haste_monster() end, - ["info"] = function() return device_haste_monster_info() end, - ["desc"] = { - "Haste a monster", - } -} - -DEVICE_WISH = add_spell -{ - ["name"] = "Wish", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 50, - ["mana"] = 400, - ["mana_max"] = 400, - ["fail"] = 99, - ["random"] = -1, - ["stick"] = - { - ["charge"] = { 1, 2 }, - [TV_STAFF] = - { - ["rarity"] = 98, - ["base_level"] = { 1, 1 }, - ["max_level"] = { 1, 1 }, - }, - }, - ["spell"] = function() return device_wish() end, - ["info"] = function() return device_wish_info() end, - ["desc"] = { - "This grants you a wish, beware of what you ask for!", - } -} - -DEVICE_SUMMON = add_spell -{ - ["name"] = "Summon", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 5, - ["mana"] = 5, - ["mana_max"] = 25, - ["fail"] = 20, - ["random"] = -1, - ["stick"] = - { - ["charge"] = { 1, 20 }, - [TV_STAFF] = - { - ["rarity"] = 13, - ["base_level"] = { 1, 40 }, - ["max_level"] = { 25, 50 }, - }, - }, - ["spell"] = function() return device_summon_monster() end, - ["info"] = function() return device_summon_monster_info() end, - ["desc"] = { - "Summons hostile monsters near you", - } -} - -DEVICE_MANA = add_spell -{ - ["name"] = "Mana", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 30, - ["mana"] = 1, - ["mana_max"] = 1, - ["fail"] = 80, - ["random"] = -1, - ["stick"] = - { - ["charge"] = { 2, 3 }, - [TV_STAFF] = - { - ["rarity"] = 78, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 20, 35 }, - }, - }, - ["spell"] = function() return device_mana() end, - ["info"] = function() return device_mana_info() end, - ["desc"] = { - "Restores a part(or all) of your mana", - } -} - -DEVICE_NOTHING = add_spell -{ - ["name"] = "Nothing", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 1, - ["mana"] = 0, - ["mana_max"] = 0, - ["fail"] = 0, - ["random"] = -1, - ["stick"] = - { - ["charge"] = { 0, 0 }, - [TV_WAND] = - { - ["rarity"] = 3, - ["base_level"] = { 1, 1 }, - ["max_level"] = { 1, 1 }, - }, - [TV_STAFF] = - { - ["rarity"] = 3, - ["base_level"] = { 1, 1 }, - ["max_level"] = { 1, 1}, - }, - }, - ["spell"] = function() return device_nothing() end, - ["info"] = function() return device_nothing_info() end, - ["desc"] = { - "It does nothing.", - } -} - -DEVICE_LEBOHAUM = add_spell -{ - ["name"] = "Artifact Lebauhaum", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 1, - ["mana"] = 0, - ["mana_max"] = 0, - ["fail"] = 0, - ["random"] = -1, - ["activate"] = { 3, 0 }, - ["spell"] = function() return device_lebohaum() end, - ["info"] = function() return device_lebohaum_info() end, - ["desc"] = { - "sing a cheerful song", - } -} - -DEVICE_MAGGOT = add_spell -{ - ["name"] = "Artifact Maggot", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 1, - ["mana"] = 7, - ["mana_max"] = 7, - ["fail"] = 20, - ["random"] = -1, - ["activate"] = { 10, 50 }, - ["spell"] = function() return device_maggot() end, - ["info"] = function() return device_maggot_info() end, - ["desc"] = { - "terrify", - } -} - -DEVICE_HOLY_FIRE = add_spell -{ - ["name"] = "Holy Fire of Mithrandir", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 30, - ["mana"] = 50, - ["mana_max"] = 150, - ["fail"] = 75, - ["random"] = -1, - ["stick"] = - { - ["charge"] = { 2, 5 }, - [TV_STAFF] = - { - -- Rarity higher than 100 to be sure to not have it generated randomly - ["rarity"] = 999, - ["base_level"] = { 1, 1 }, - ["max_level"] = { 35, 35 }, - }, - }, - ["spell"] = function() return device_holy_fire() end, - ["info"] = function() return device_holy_fire_info() end, - ["desc"] = { - "The Holy Fire created by this staff will deeply(double damage) burn", - "all that is evil.", - } -} - --- Ok the Eternal Flame, to craete one of the 4 ultimate arts --- needed to enter the last level of the Void -DEVICE_ETERNAL_FLAME = add_spell -{ - ["name"] = "Artifact Eternal Flame", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 1, - ["mana"] = 0, - ["mana_max"] = 0, - ["fail"] = 0, - ["random"] = -1, - ["activate"] = { 0, 0 }, - ["spell"] = function(flame_item) return device_eternal_flame(flame_item) end, - ["info"] = function() return "" end, - ["desc"] = { - "Imbuing an object with the eternal fire", - } -} - --- And one more silly activation :) -DEVICE_DURANDIL = add_spell -{ - ["name"] = "Artifact Durandil", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 1, - ["mana"] = 0, - ["mana_max"] = 0, - ["fail"] = 0, - ["random"] = -1, - ["activate"] = { 3, 0 }, - ["spell"] = function() return device_durandil() end, - ["info"] = function() return device_durandil_info() end, - ["desc"] = { - "sing a cheerful song", - } -} - -DEVICE_THUNDERLORDS = add_spell -{ - ["name"] = "Artifact Thunderlords", - ["school"] = {SCHOOL_DEVICE}, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 1, - ["fail"] = 20, - ["random"] = -1, - ["stick"] = - { - ["charge"] = { 3, 3 }, - [TV_STAFF] = - { - -- Rarity higher than 100 to be sure to not have it generated randomly - ["rarity"] = 999, - ["base_level"] = { 1, 1 }, - ["max_level"] = { 1, 1 }, - }, - }, - ["spell"] = function() return device_thunderlords() end, - ["info"] = function() return device_thunderlords_info() end, - ["desc"] = { - "A thunderlord will appear to transport you quickly to the surface.", - } -} diff --git a/lib/scpt/s_tempo.lua b/lib/scpt/s_tempo.lua deleted file mode 100644 index 76026745..00000000 --- a/lib/scpt/s_tempo.lua +++ /dev/null @@ -1,109 +0,0 @@ --- Handles thhe temporal school - - -MAGELOCK = add_spell -{ - ["name"] = "Magelock", - ["school"] = {SCHOOL_TEMPORAL}, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 35, - ["fail"] = 10, - ["stick"] = - { - ["charge"] = { 7, 5 }, - [TV_WAND] = - { - ["rarity"] = 30, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 15, 45 }, - }, - }, - ["spell"] = function() return tempo_magelock() end, - ["info"] = function() return tempo_magelock_info() end, - ["desc"] = { - "Magically locks a door", - "At level 30 it creates a glyph of warding", - "At level 40 the glyph can be placed anywhere in the field of vision" - } -} - -SLOWMONSTER = add_spell -{ - ["name"] = "Slow Monster", - ["school"] = {SCHOOL_TEMPORAL}, - ["level"] = 10, - ["mana"] = 10, - ["mana_max"] = 15, - ["fail"] = 35, - ["stick"] = - { - ["charge"] = { 5, 5 }, - [TV_WAND] = - { - ["rarity"] = 23, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 20, 50 }, - }, - }, - ["spell"] = function() return tempo_slow_monster() end, - ["info"] = function() return tempo_slow_monster_info() end, - ["desc"] = { - "Magically slows down the passing of time around a monster", - "At level 20 it affects a zone" - } -} - -ESSENCESPEED = add_spell -{ - ["name"] = "Essence of Speed", - ["school"] = {SCHOOL_TEMPORAL}, - ["level"] = 15, - ["mana"] = 20, - ["mana_max"] = 40, - ["fail"] = 50, - ["stick"] = - { - ["charge"] = { 3, 3 }, - [TV_WAND] = - { - ["rarity"] = 80, - ["base_level"] = { 1, 1 }, - ["max_level"] = { 10, 39 }, - }, - }, - ["inertia"] = { 5, 20 }, - ["spell"] = function() return tempo_essence_of_speed() end, - ["info"] = function() return tempo_essence_of_speed_info() end, - ["desc"] = { - "Magically decreases the passing of time around you, making you move faster with", - "respect to the rest of the universe." - } -} - -BANISHMENT = add_spell -{ - ["name"] = "Banishment", - ["school"] = {SCHOOL_TEMPORAL, SCHOOL_CONVEYANCE}, - ["level"] = 30, - ["mana"] = 30, - ["mana_max"] = 40, - ["fail"] = 95, - ["stick"] = - { - ["charge"] = { 1, 3 }, - [TV_WAND] = - { - ["rarity"] = 98, - ["base_level"] = { 1, 15 }, - ["max_level"] = { 10, 36 }, - }, - }, - ["inertia"] = { 5, 50 }, - ["spell"] = function() return tempo_banishment() end, - ["info"] = function() return tempo_banishment_info() end, - ["desc"] = { - "Disrupts the space/time continuum in your area and teleports all monsters away.", - "At level 15 it may also lock them in a time bubble for a while." - } -} diff --git a/lib/scpt/s_tulkas.lua b/lib/scpt/s_tulkas.lua deleted file mode 100644 index 6659aee9..00000000 --- a/lib/scpt/s_tulkas.lua +++ /dev/null @@ -1,59 +0,0 @@ --- Handle Tulkas magic school - -TULKAS_AIM = add_spell -{ - ["name"] = "Divine Aim", - ["school"] = {SCHOOL_TULKAS}, - ["level"] = 1, - ["mana"] = 30, - ["mana_max"] = 500, - ["fail"] = 20, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return tulkas_divine_aim() end, - ["info"] = function() return tulkas_divine_aim_info() end, - ["desc"] = { - "It makes you more accurate in combat", - "At level 20 all your blows are critical hits", - } -} - -TULKAS_WAVE = add_spell -{ - ["name"] = "Wave of Power", - ["school"] = {SCHOOL_TULKAS}, - ["level"] = 20, - ["mana"] = 200, - ["mana_max"] = 200, - ["fail"] = 75, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return tulkas_wave_of_power() end, - ["info"] = function() return tulkas_wave_of_power_info() end, - ["desc"] = { - "It allows you to project a number of melee blows across a distance", - } -} - -TULKAS_SPIN = add_spell -{ - ["name"] = "Whirlwind", - ["school"] = {SCHOOL_TULKAS}, - ["level"] = 10, - ["mana"] = 100, - ["mana_max"] = 100, - ["fail"] = 45, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return tulkas_whirlwind() end, - ["info"] = function() return tulkas_whirlwind_info() end, - ["desc"] = { - "It allows you to spin around and hit all monsters nearby", - } -} diff --git a/lib/scpt/s_udun.lua b/lib/scpt/s_udun.lua deleted file mode 100644 index bb12ac7f..00000000 --- a/lib/scpt/s_udun.lua +++ /dev/null @@ -1,74 +0,0 @@ --- handle the udun school - -DRAIN = add_spell -{ - ["name"] = "Drain", - ["school"] = {SCHOOL_UDUN, SCHOOL_MANA}, - ["level"] = 1, - ["mana"] = 0, - ["mana_max"] = 0, - ["fail"] = 20, - ["spell"] = function() return udun_drain() end, - ["info"] = function() return udun_drain_info() end, - ["desc"] = { - "Drains the mana contained in wands, staves and rods to increase yours", - } -} - -GENOCIDE = add_spell -{ - ["name"] = "Genocide", - ["school"] = {SCHOOL_UDUN, SCHOOL_NATURE}, - ["level"] = 25, - ["mana"] = 50, - ["mana_max"] = 50, - ["fail"] = 90, - ["stick"] = - { - ["charge"] = { 2, 2 }, - [TV_STAFF] = - { - ["rarity"] = 85, - ["base_level"] = { 1, 1 }, - ["max_level"] = { 5, 15 }, - }, - }, - ["spell"] = function() return udun_genocide() end, - ["info"] = function() return udun_genocide_info() end, - ["desc"] = { - "Genocides all monsters of a race on the level", - "At level 10 it can genocide all monsters near you" - } -} - -WRAITHFORM = add_spell -{ - ["name"] = "Wraithform", - ["school"] = {SCHOOL_UDUN, SCHOOL_CONVEYANCE}, - ["level"] = 30, - ["mana"] = 20, - ["mana_max"] = 40, - ["fail"] = 95, - ["inertia"] = { 4, 30 }, - ["spell"] = function() return udun_wraithform() end, - ["info"] = function() return udun_wraithform_info() end, - ["desc"] = { - "Turns you into an immaterial being", - } -} - -FLAMEOFUDUN = add_spell -{ - ["name"] = "Flame of Udun", - ["school"] = {SCHOOL_UDUN, SCHOOL_FIRE}, - ["level"] = 35, - ["mana"] = 70, - ["mana_max"] = 100, - ["fail"] = 95, - ["inertia"] = { 7, 15 }, - ["spell"] = function() return udun_flame_of_udun() end, - ["info"] = function() return udun_flame_of_udun_info() end, - ["desc"] = { - "Turns you into a powerful Balrog", - } -} diff --git a/lib/scpt/s_water.lua b/lib/scpt/s_water.lua deleted file mode 100644 index 46942c5d..00000000 --- a/lib/scpt/s_water.lua +++ /dev/null @@ -1,106 +0,0 @@ --- handle the water school - -TIDALWAVE = add_spell -{ - ["name"] = "Tidal Wave", - ["school"] = {SCHOOL_WATER}, - ["level"] = 16, - ["mana"] = 16, - ["mana_max"] = 40, - ["fail"] = 65, - ["stick"] = - { - ["charge"] = { 6, 5 }, - [TV_WAND] = - { - ["rarity"] = 54, - ["base_level"] = { 1, 10 }, - ["max_level"] = { 20, 50 }, - }, - }, - ["inertia"] = { 4, 100 }, - ["spell"] = function() return water_tidal_wave() end, - ["info"] = function() return water_tidal_wave_info() end, - ["desc"] = { - "Summons a monstrous tidal wave that will expand and crush the", - "monsters under its mighty waves." - } -} - -ICESTORM = add_spell -{ - ["name"] = "Ice Storm", - ["school"] = {SCHOOL_WATER}, - ["level"] = 22, - ["mana"] = 30, - ["mana_max"] = 60, - ["fail"] = 80, - ["stick"] = - { - ["charge"] = { 3, 7 }, - [TV_WAND] = - { - ["rarity"] = 65, - ["base_level"] = { 1, 5 }, - ["max_level"] = { 25, 45 }, - }, - }, - ["inertia"] = { 3, 40 }, - ["spell"] = function() return water_ice_storm() end, - ["info"] = function() return water_ice_storm_info() end, - ["desc"] = { - "Engulfs you in a storm of roaring cold that strikes your foes.", - "At level 10 it turns into shards of ice." - } -} - -ENTPOTION = add_spell -{ - ["name"] = "Ent's Potion", - ["school"] = {SCHOOL_WATER}, - ["level"] = 6, - ["mana"] = 7, - ["mana_max"] = 15, - ["fail"] = 35, - ["inertia"] = { 1, 30 }, - ["spell"] = function() return water_ent_potion() end, - ["info"] = function() return water_ent_potion_info() end, - ["desc"] = { - "Fills up your stomach.", - "At level 5 it boldens your heart.", - "At level 12 it makes you heroic." - } -} - -VAPOR = add_spell -{ - ["name"] = "Vapor", - ["school"] = {SCHOOL_WATER}, - ["level"] = 2, - ["mana"] = 2, - ["mana_max"] = 12, - ["fail"] = 20, - ["inertia"] = { 1, 30 }, - ["spell"] = function() return water_vapor() end, - ["info"] = function() return water_vapor_info() end, - ["desc"] = { - "Fills the air with toxic moisture to eradicate annoying critters." - } -} - -GEYSER = add_spell -{ - ["name"] = "Geyser", - ["school"] = SCHOOL_WATER, - ["level"] = 1, - ["mana"] = 1, - ["mana_max"] = 35, - ["fail"] = 5, - ["spell"] = function() return water_geyser() end, - ["info"] = function() return water_geyser_info() end, - ["desc"] = - { - "Shoots a geyser of water from your fingertips.", - "Sometimes it can blast through its first target." - }, -} diff --git a/lib/scpt/s_yavann.lua b/lib/scpt/s_yavann.lua deleted file mode 100644 index a2b2fe1c..00000000 --- a/lib/scpt/s_yavann.lua +++ /dev/null @@ -1,100 +0,0 @@ --- Handle Yavanna kementari magic school - -YAVANNA_CHARM_ANIMAL = add_spell -{ - ["name"] = "Charm Animal", - ["school"] = {SCHOOL_YAVANNA}, - ["level"] = 1, - ["mana"] = 10, - ["mana_max"] = 100, - ["fail"] = 30, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return yavanna_charm_animal() end, - ["info"] = function() return yavanna_charm_animal_info() end, - ["desc"] = { - "It tries to tame an animal", - } -} - -YAVANNA_GROW_GRASS = add_spell -{ - ["name"] = "Grow Grass", - ["school"] = {SCHOOL_YAVANNA}, - ["level"] = 10, - ["mana"] = 70, - ["mana_max"] = 150, - ["fail"] = 65, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return yavanna_grow_grass() end, - ["info"] = function() return yavanna_grow_grass_info() end, - ["desc"] = { - "Create a floor of grass around you. While on grass and praying", - "a worshipper of Yavanna will know a greater regeneration rate" - } -} - -YAVANNA_TREE_ROOTS = add_spell -{ - ["name"] = "Tree Roots", - ["school"] = {SCHOOL_YAVANNA}, - ["level"] = 15, - ["mana"] = 50, - ["mana_max"] = 1000, - ["fail"] = 70, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return yavanna_tree_roots() end, - ["info"] = function() return yavanna_tree_roots_info() end, - ["desc"] = { - "Creates roots deep in the floor from your feet, making you more stable and able", - "to make stronger attacks, but prevents any movement (even teleportation).", - "It also makes you recover from stunning almost immediately." - } -} - -YAVANNA_WATER_BITE = add_spell -{ - ["name"] = "Water Bite", - ["school"] = {SCHOOL_YAVANNA}, - ["level"] = 20, - ["mana"] = 150, - ["mana_max"] = 300, - ["fail"] = 90, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return yavanna_water_bite() end, - ["info"] = function() return yavanna_water_bite_info() end, - ["desc"] = { - "Imbues your melee weapon with a natural stream of water", - "At level 25, it spreads over a 1 radius zone around your target" - } -} - -YAVANNA_UPROOT = add_spell -{ - ["name"] = "Uproot", - ["school"] = {SCHOOL_YAVANNA}, - ["level"] = 35, - ["mana"] = 250, - ["mana_max"] = 350, - ["fail"] = 95, - -- Uses piety to cast - ["piety"] = TRUE, - ["stat"] = A_WIS, - ["random"] = SKILL_SPIRITUALITY, - ["spell"] = function() return yavanna_uproot() end, - ["info"] = function() return yavanna_uproot_info() end, - ["desc"] = { - "Awakes a tree to help you battle the forces of Morgoth", - } -} diff --git a/lib/scpt/spells.lua b/lib/scpt/spells.lua index 4bd5d7ea..2ce7d1f3 100644 --- a/lib/scpt/spells.lua +++ b/lib/scpt/spells.lua @@ -286,36 +286,8 @@ SCHOOL_MUSIC = add_school ["skill"] = SKILL_MUSIC, } --- Put some spells -tome_dofile("s_fire.lua") -tome_dofile("s_mana.lua") -tome_dofile("s_water.lua") -tome_dofile("s_air.lua") -tome_dofile("s_earth.lua") -tome_dofile("s_convey.lua") -tome_dofile("s_nature.lua") -tome_dofile("s_divin.lua") -tome_dofile("s_tempo.lua") -tome_dofile("s_meta.lua") -tome_dofile("s_mind.lua") -tome_dofile("s_udun.lua") -tome_dofile("s_geom.lua") - --- God's specific spells -tome_dofile("s_eru.lua") -tome_dofile("s_manwe.lua") -tome_dofile("s_tulkas.lua") -tome_dofile("s_melkor.lua") -tome_dofile("s_yavann.lua") - --- Specific schools -tome_dofile("s_demon.lua") - --- Device spells -tome_dofile("s_stick.lua") - --- Musics -tome_dofile("s_music.lua") +-- Initialize school spells. +school_spells_init() -- Initialize spellbooks init_school_books() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 219ceb7c..d1648754 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,7 +10,7 @@ SET(SRCS object1.c object2.c randart.c squeltch.c traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c - spells1.c spells2.c spells3.c spells4.c corrupt.c mimic.c + spells1.c spells2.c spells3.c spells4.c spells5.c corrupt.c mimic.c status.c files.c notes.c loadsave.c string_list.c cmd1.c cmd2.c cmd3.c cmd4.c cmd5.c cmd6.c cmd7.c help.c range.c diff --git a/src/cmd5.c b/src/cmd5.c index d0c60042..e322186b 100644 --- a/src/cmd5.c +++ b/src/cmd5.c @@ -2101,14 +2101,14 @@ bool_ get_item_hook_find_spell(int *item) { int i, spell; char buf[80]; - char buf2[100]; strcpy(buf, "Manathrust"); if (!get_string("Spell name? ", buf, 79)) return FALSE; - sprintf(buf2, "return find_spell(\"%s\")", buf); - spell = exec_lua(buf2); + + spell = find_spell(buf); if (spell == -1) return FALSE; + for (i = 0; i < INVEN_TOTAL; i++) { object_type *o_ptr = &p_ptr->inventory[i]; @@ -2146,10 +2146,32 @@ bool_ get_item_hook_find_spell(int *item) return FALSE; } +/* + * Is the spell castable? + */ +bool_ is_ok_spell(s32b spell_idx, object_type *o_ptr) +{ + spell_type *spell = spell_at(spell_idx); + assert(o_ptr != NULL); + + if (get_level(spell_idx, 50, 0) == 0) + { + return FALSE; + } + + if (o_ptr->pval < spell->minimum_pval) + { + return FALSE; + } + + return TRUE; +} + + /* * Get a spell from a book */ -s32b get_school_spell(cptr do_what, cptr check_fct, s16b force_book) +s32b get_school_spell(cptr do_what, s16b force_book) { int i, item; s32b spell = -1; @@ -2320,13 +2342,13 @@ s32b get_school_spell(cptr do_what, cptr check_fct, s16b force_book) } else { - s32b ok; + bool_ ok; /* Save the spell index */ spell = spell_x(sval, pval, i); /* Do we need to do some pre test */ - call_lua(check_fct, "(d,O)", "d", spell, o_ptr, &ok); + ok = is_ok_spell(spell, o_ptr); /* Require "okay" spells */ if (!ok) @@ -2344,10 +2366,10 @@ s32b get_school_spell(cptr do_what, cptr check_fct, s16b force_book) } else { - s32b ok; + bool_ ok; /* Require "okay" spells */ - call_lua(check_fct, "(d, O)", "d", hack_force_spell, hack_force_spell_obj, &ok); + ok = is_ok_spell(hack_force_spell, hack_force_spell_obj); if (ok) { flag = TRUE; @@ -2404,7 +2426,7 @@ void cast_school_spell() return; } - spell = get_school_spell("cast", "is_ok_spell", 0); + spell = get_school_spell("cast", 0); /* Actualy cast the choice */ if (spell != -1) @@ -2502,14 +2524,14 @@ static bool_ hook_school_can_spellable(object_type *o_ptr) */ void do_cmd_copy_spell() { - int spell = get_school_spell("copy", "is_ok_spell", 0); + int spell = get_school_spell("copy", 0); int item; object_type *o_ptr; if (spell == -1) return; /* Spells that cannot be randomly created cannot be copied */ - if (exec_lua(format("return can_spell_random(%d)", spell)) == FALSE) + if (can_spell_random(spell) <= 0) { msg_print("This spell cannot be copied."); return; @@ -2523,29 +2545,3 @@ void do_cmd_copy_spell() o_ptr->pval2 = spell; inven_item_describe(item); } - -/* - * Finds a spell by name, optimized for speed - */ -int find_spell(const char *name) -{ - int oldtop, spell; - oldtop = lua_gettop(L); - - lua_getglobal(L, "find_spell"); - tolua_pushstring(L, name); - - /* Call the function */ - if (lua_call(L, 1, 1)) - { - cmsg_format(TERM_VIOLET, "ERROR in lua_call while calling 'find_spell'."); - lua_settop(L, oldtop); - return -1; - } - - spell = tolua_getnumber(L, -(lua_gettop(L) - oldtop), -1); - - lua_settop(L, oldtop); - - return spell; -} diff --git a/src/cmd6.c b/src/cmd6.c index 39483bbd..7bd6c80a 100644 --- a/src/cmd6.c +++ b/src/cmd6.c @@ -3649,6 +3649,33 @@ void unset_stick_mode() } +/* + * Activate a device + */ +static void activate_stick(s16b s, bool_ *obvious, bool_ *use_charge) +{ + spell_type *spell = spell_at(s); + bool_ *ret; + + assert(obvious != NULL); + assert(use_charge != NULL); + assert(spell->effect_func != NULL); + + ret = spell->effect_func(-1); + + if (ret == NULL) + { + *use_charge = FALSE; + *obvious = FALSE; + } + else + { + *use_charge = TRUE; + *obvious = *ret; + } +} + + /* * Use a staff. -RAK- * @@ -3660,7 +3687,7 @@ void do_cmd_use_staff(void) { int item, ident, chance; - s32b obvious, use_charge; + bool_ obvious, use_charge; object_type *o_ptr; @@ -3754,7 +3781,7 @@ void do_cmd_use_staff(void) /* Analyze the staff */ - call_lua("activate_stick", "(d)", "dd", o_ptr->pval2, &obvious, &use_charge); + activate_stick(o_ptr->pval2, &obvious, &use_charge); /* Combine / Reorder the pack (later) */ p_ptr->notice |= (PN_COMBINE | PN_REORDER); @@ -3850,7 +3877,7 @@ void do_cmd_use_staff(void) */ void do_cmd_aim_wand(void) { - s32b obvious, use_charge; + bool_ obvious, use_charge; int item, ident, chance, sval; @@ -3945,7 +3972,7 @@ void do_cmd_aim_wand(void) sval = o_ptr->sval; /* Analyze the wand */ - call_lua("activate_stick", "(d)", "dd", o_ptr->pval2, &obvious, &use_charge); + activate_stick(o_ptr->pval2, &obvious, &use_charge); /* Combine / Reorder the pack (later) */ p_ptr->notice |= (PN_COMBINE | PN_REORDER); @@ -4989,42 +5016,16 @@ void do_cmd_activate(void) } -static void get_activation_duration(int spl, int *base, int *sides) -{ - assert(base != NULL); - assert(sides != NULL); - - *base = get_lua_int(format("__tmp_spells[%d].activate[1]", spl)); - if (*base <= 0) - { - base = 0; - } - - *sides = get_lua_int(format("__tmp_spells[%d].activate[2]", spl)); - if (*sides <= 0) - { - sides = 0; - } -} - static void get_activation_desc(char *buf, int spl) { - spell_type *spell = &school_spells[spl]; + spell_type *spell = spell_at(spl); char turns[32]; - int base, sides; - - get_activation_duration(spl, &base, &sides); - sprintf(turns, "%d", base); - if (sides > 0) - { - char buf[32]; - sprintf(buf, "+d%d", sides); - strcat(turns, buf); - } + dice_print(&spell->activation_duration, turns); assert(spell->description != NULL); assert(spell->description->s != NULL); + sprintf(buf, "%s every %s turns", spell->description->s, turns); @@ -5032,11 +5033,16 @@ static void get_activation_desc(char *buf, int spl) static int get_activation_timeout(int spl) { - int base, sides; - get_activation_duration(spl, &base, &sides); - return base + randint(sides); + spell_type *spell = spell_at(spl); + return dice_roll(&spell->activation_duration); } +static void activate_activation(long s, int item) +{ + spell_type *spell = spell_at(s); + assert(spell->effect_func != NULL); + spell->effect_func(item); +} const char *activation_aux(object_type * o_ptr, bool_ doit, int item) { @@ -5082,7 +5088,7 @@ const char *activation_aux(object_type * o_ptr, bool_ doit, int item) { if (doit) { - call_lua("activate_activation", "(d,d)", "", -spell, item); + activate_activation(-spell, item); o_ptr->timeout = get_activation_timeout(-spell); } else diff --git a/src/defines.h b/src/defines.h index 7457134a..099d3fe1 100644 --- a/src/defines.h +++ b/src/defines.h @@ -865,6 +865,11 @@ #define MAX_BETWEEN_EXITS 3 +/* + * Maximum number of school spells + */ +#define SCHOOL_SPELLS_MAX 200 + /* * Number of effects */ diff --git a/src/dungeon.c b/src/dungeon.c index e60f1ef0..342779b2 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -801,30 +801,10 @@ bool_ decays(object_type *o_ptr) static int process_lasting_spell(s16b music) { - int oldtop, use_mana; + spell_type *spell = spell_at(-music); - if (music > 0) return FALSE; - - oldtop = lua_gettop(L); - - music = -music; - - /* Push the function */ - lua_getglobal(L, "exec_lasting_spell"); - - /* Push the spell */ - tolua_pushnumber(L, music); - - /* Call the function */ - if (lua_call(L, 1, 1)) - { - cmsg_format(TERM_VIOLET, "ERROR in lua_call while calling lasting spell"); - return 0; - } - - use_mana = tolua_getnumber(L, -(lua_gettop(L) - oldtop), 0); - lua_settop(L, oldtop); - return use_mana; + assert(spell->lasting_func != NULL); + return spell->lasting_func(); } static void gere_class_special() diff --git a/src/externs.h b/src/externs.h index 0ebe0f04..897cc074 100644 --- a/src/externs.h +++ b/src/externs.h @@ -564,8 +564,8 @@ extern hist_type *bg; extern int max_bg_idx; extern s32b extra_savefile_parts; extern bool_ player_char_health; -extern s16b max_spells; -extern spell_type *school_spells; +extern s16b school_spells_count; +extern spell_type school_spells[SCHOOL_SPELLS_MAX]; extern s16b max_schools; extern school_type *schools; extern int project_time; @@ -801,7 +801,8 @@ extern void do_poly_self(void); extern void brand_weapon(int brand_type); extern cptr symbiote_name(bool_ capitalize); extern int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost); -extern s32b get_school_spell(cptr do_what, cptr check_fct, s16b force_book); +extern bool_ is_ok_spell(s32b spell_idx, object_type *o_ptr); +extern s32b get_school_spell(cptr do_what, s16b force_book); extern void do_cmd_copy_spell(void); extern void cast_school_spell(void); extern void browse_school_spell(int book, int pval, object_type *o_ptr); @@ -969,7 +970,6 @@ extern errr process_dungeon_file(cptr name, int *yval, int *xval, int ymax, int /* init2.c */ extern void init_corruptions(); -extern void init_spells(s16b new_size); extern void init_schools(s16b new_size); extern void reinit_gods(s16b new_size); extern void reinit_quests(s16b new_size); @@ -1411,17 +1411,17 @@ extern s32b POISONBLOOD; extern s32b THUNDERSTORM; extern s32b STERILIZE; -bool_ *air_noxious_cloud(); +bool_ *air_noxious_cloud(int); char *air_noxious_cloud_info(); -bool_ *air_wings_of_winds(); +bool_ *air_wings_of_winds(int); char *air_wings_of_winds_info(); -bool_ *air_invisibility(); +bool_ *air_invisibility(int); char *air_invisibility_info(); -bool_ *air_poison_blood(); +bool_ *air_poison_blood(int); char *air_poison_blood_info(); -bool_ *air_thunderstorm(); +bool_ *air_thunderstorm(int); char *air_thunderstorm_info(); -bool_ *air_sterilize(); +bool_ *air_sterilize(int); char *air_sterilize_info(); extern s32b BLINK; @@ -1431,17 +1431,17 @@ extern s32b TELEAWAY; extern s32b RECALL; extern s32b PROBABILITY_TRAVEL; -bool_ *convey_blink(); +bool_ *convey_blink(int); char *convey_blink_info(); -bool_ *convey_disarm(); +bool_ *convey_disarm(int); char *convey_disarm_info(); -bool_ *convey_teleport(); +bool_ *convey_teleport(int); char *convey_teleport_info(); -bool_ *convey_teleport_away(); +bool_ *convey_teleport_away(int); char *convey_teleport_away_info(); -bool_ *convey_recall(); +bool_ *convey_recall(int); char *convey_recall_info(); -bool_ *convey_probability_travel(); +bool_ *convey_probability_travel(int); char *convey_probability_travel_info(); extern s32b DEMON_BLADE; @@ -1454,23 +1454,23 @@ extern s32b DEMON_SUMMON; extern s32b DISCHARGE_MINION; extern s32b CONTROL_DEMON; -bool_ *demonology_demon_blade(); +bool_ *demonology_demon_blade(int); char *demonology_demon_blade_info(); -bool_ *demonology_demon_madness(); +bool_ *demonology_demon_madness(int); char *demonology_demon_madness_info(); -bool_ *demonology_demon_field(); +bool_ *demonology_demon_field(int); char *demonology_demon_field_info(); -bool_ *demonology_doom_shield(); +bool_ *demonology_doom_shield(int); char *demonology_doom_shield_info(); -bool_ *demonology_unholy_word(); +bool_ *demonology_unholy_word(int); char *demonology_unholy_word_info(); -bool_ *demonology_demon_cloak(); +bool_ *demonology_demon_cloak(int); char *demonology_demon_cloak_info(); -bool_ *demonology_summon_demon(); +bool_ *demonology_summon_demon(int); char *demonology_summon_demon_info(); -bool_ *demonology_discharge_minion(); +bool_ *demonology_discharge_minion(int); char *demonology_discharge_minion_info(); -bool_ *demonology_control_demon(); +bool_ *demonology_control_demon(int); char *demonology_control_demon_info(); extern s32b STARIDENTIFY; @@ -1480,17 +1480,17 @@ extern s32b SENSEHIDDEN; extern s32b REVEALWAYS; extern s32b SENSEMONSTERS; -bool_ *divination_greater_identify(); +bool_ *divination_greater_identify(int); char *divination_greater_identify_info(); -bool_ *divination_identify(); +bool_ *divination_identify(int); char *divination_identify_info(); -bool_ *divination_vision(); +bool_ *divination_vision(int); char *divination_vision_info(); -bool_ *divination_sense_hidden(); +bool_ *divination_sense_hidden(int); char *divination_sense_hidden_info(); -bool_ *divination_reveal_ways(); +bool_ *divination_reveal_ways(int); char *divination_reveal_ways_info(); -bool_ *divination_sense_monsters(); +bool_ *divination_sense_monsters(int); char *divination_sense_monsters_info(); extern s32b STONESKIN; @@ -1499,15 +1499,15 @@ extern s32b STONEPRISON; extern s32b STRIKE; extern s32b SHAKE; -bool_ *earth_stone_skin(); +bool_ *earth_stone_skin(int); char *earth_stone_skin_info(); -bool_ *earth_dig(); +bool_ *earth_dig(int); char *earth_dig_info(); -bool_ *earth_stone_prison(); +bool_ *earth_stone_prison(int); char *earth_stone_prison_info(); -bool_ *earth_strike(); +bool_ *earth_strike(int); char *earth_strike_info(); -bool_ *earth_shake(); +bool_ *earth_shake(int); char *earth_shake_info(); extern s32b ERU_SEE; @@ -1515,13 +1515,13 @@ extern s32b ERU_LISTEN; extern s32b ERU_UNDERSTAND; extern s32b ERU_PROT; -bool_ *eru_see_the_music(); +bool_ *eru_see_the_music(int); char *eru_see_the_music_info(); -bool_ *eru_listen_to_the_music(); +bool_ *eru_listen_to_the_music(int); char *eru_listen_to_the_music_info(); -bool_ *eru_know_the_music(); +bool_ *eru_know_the_music(int); char *eru_know_the_music_info(); -bool_ *eru_lay_of_protection(); +bool_ *eru_lay_of_protection(int); char *eru_lay_of_protection_info(); extern s32b GLOBELIGHT; @@ -1530,15 +1530,15 @@ extern s32b FIERYAURA; extern s32b FIREWALL; extern s32b FIREGOLEM; -bool_ *fire_globe_of_light(); +bool_ *fire_globe_of_light(int); char *fire_globe_of_light_info(); -bool_ *fire_fireflash(); +bool_ *fire_fireflash(int); char *fire_fireflash_info(); -bool_ *fire_fiery_shield(); +bool_ *fire_fiery_shield(int); char *fire_fiery_shield_info(); -bool_ *fire_firewall(); +bool_ *fire_firewall(int); char *fire_firewall_info(); -bool_ *fire_golem(); +bool_ *fire_golem(int); char *fire_golem_info(); extern s32b CALL_THE_ELEMENTS; @@ -1550,25 +1550,25 @@ extern s32b DRIPPING_TREAD; extern s32b GROW_BARRIER; extern s32b ELEMENTAL_MINION; -bool_ *geomancy_call_the_elements(); +bool_ *geomancy_call_the_elements(int); char *geomancy_call_the_elements_info(); -bool_ *geomancy_channel_elements(); +bool_ *geomancy_channel_elements(int); char *geomancy_channel_elements_info(); -bool_ *geomancy_elemental_wave(); +bool_ *geomancy_elemental_wave(int); char *geomancy_elemental_wave_info(); -bool_ *geomancy_vaporize(); +bool_ *geomancy_vaporize(int); char *geomancy_vaporize_info(); bool_ geomancy_vaporize_depends(); -bool_ *geomancy_geolysis(); +bool_ *geomancy_geolysis(int); char *geomancy_geolysis_info(); bool_ geomancy_geolysis_depends(); -bool_ *geomancy_dripping_tread(); +bool_ *geomancy_dripping_tread(int); char *geomancy_dripping_tread_info(); bool_ geomancy_dripping_tread_depends(); -bool_ *geomancy_grow_barrier(); +bool_ *geomancy_grow_barrier(int); char *geomancy_grow_barrier_info(); bool_ geomancy_grow_barrier_depends(); -bool_ *geomancy_elemental_minion(); +bool_ *geomancy_elemental_minion(int); char *geomancy_elemental_minion_info(); extern s32b MANATHRUST; @@ -1576,13 +1576,13 @@ extern s32b DELCURSES; extern s32b RESISTS; extern s32b MANASHIELD; -bool_ *mana_manathrust(); +bool_ *mana_manathrust(int); char *mana_manathrust_info(); -bool_ *mana_remove_curses(); +bool_ *mana_remove_curses(int); char *mana_remove_curses_info(); -bool_ *mana_elemental_shield(); +bool_ *mana_elemental_shield(int); char *mana_elemental_shield_info(); -bool_ *mana_disruption_shield(); +bool_ *mana_disruption_shield(int); char *mana_disruption_shield_info(); extern s32b MANWE_SHIELD; @@ -1590,13 +1590,13 @@ extern s32b MANWE_AVATAR; extern s32b MANWE_BLESS; extern s32b MANWE_CALL; -bool_ *manwe_wind_shield(); +bool_ *manwe_wind_shield(int); char *manwe_wind_shield_info(); -bool_ *manwe_avatar(); +bool_ *manwe_avatar(int); char *manwe_avatar_info(); -bool_ *manwe_blessing(); +bool_ *manwe_blessing(int); char *manwe_blessing_info(); -bool_ *manwe_call(); +bool_ *manwe_call(int); char *manwe_call_info(); extern s32b MELKOR_CURSE; @@ -1605,11 +1605,11 @@ extern s32b MELKOR_MIND_STEAL; void do_melkor_curse(int m_idx); -bool_ *melkor_curse(); +bool_ *melkor_curse(int); char *melkor_curse_info(); -bool_ *melkor_corpse_explosion(); +bool_ *melkor_corpse_explosion(int); char *melkor_corpse_explosion_info(); -bool_ *melkor_mind_steal(); +bool_ *melkor_mind_steal(int); char *melkor_mind_steal_info(); extern s32b RECHARGE; @@ -1619,15 +1619,15 @@ extern s32b TRACKER; extern s32b INERTIA_CONTROL; extern timer_type *TIMER_INERTIA_CONTROL; -bool_ *meta_recharge(); +bool_ *meta_recharge(int); char *meta_recharge_info(); -bool_ *meta_spellbinder(); +bool_ *meta_spellbinder(int); char *meta_spellbinder_info(); -bool_ *meta_disperse_magic(); +bool_ *meta_disperse_magic(int); char *meta_disperse_magic_info(); -bool_ *meta_tracker(); +bool_ *meta_tracker(int); char *meta_tracker_info(); -bool_ *meta_inertia_control(); +bool_ *meta_inertia_control(int); char *meta_inertia_control_info(); void meta_inertia_control_timer_callback(); @@ -1639,13 +1639,13 @@ extern s32b CONFUSE; extern s32b ARMOROFFEAR; extern s32b STUN; -bool_ *mind_charm(); +bool_ *mind_charm(int); char *mind_charm_info(); -bool_ *mind_confuse(); +bool_ *mind_confuse(int); char *mind_confuse_info(); -bool_ *mind_armor_of_fear(); +bool_ *mind_armor_of_fear(int); char *mind_armor_of_fear_info(); -bool_ *mind_stun(); +bool_ *mind_stun(int); char *mind_stun_info(); extern s32b MAGELOCK; @@ -1653,24 +1653,24 @@ extern s32b SLOWMONSTER; extern s32b ESSENCESPEED; extern s32b BANISHMENT; -bool_ *tempo_magelock(); +bool_ *tempo_magelock(int); char *tempo_magelock_info(); -bool_ *tempo_slow_monster(); +bool_ *tempo_slow_monster(int); char *tempo_slow_monster_info(); -bool_ *tempo_essence_of_speed(); +bool_ *tempo_essence_of_speed(int); char *tempo_essence_of_speed_info(); -bool_ *tempo_banishment(); +bool_ *tempo_banishment(int); char *tempo_banishment_info(); extern s32b TULKAS_AIM; extern s32b TULKAS_WAVE; extern s32b TULKAS_SPIN; -bool_ *tulkas_divine_aim(); +bool_ *tulkas_divine_aim(int); char *tulkas_divine_aim_info(); -bool_ *tulkas_wave_of_power(); +bool_ *tulkas_wave_of_power(int); char *tulkas_wave_of_power_info(); -bool_ *tulkas_whirlwind(); +bool_ *tulkas_whirlwind(int); char *tulkas_whirlwind_info(); extern s32b DRAIN; @@ -1681,13 +1681,13 @@ extern s32b FLAMEOFUDUN; int udun_in_book(s32b sval, s32b pval); int levels_in_book(s32b sval, s32b pval); -bool_ *udun_drain(); +bool_ *udun_drain(int); char *udun_drain_info(); -bool_ *udun_genocide(); +bool_ *udun_genocide(int); char *udun_genocide_info(); -bool_ *udun_wraithform(); +bool_ *udun_wraithform(int); char *udun_wraithform_info(); -bool_ *udun_flame_of_udun(); +bool_ *udun_flame_of_udun(int); char *udun_flame_of_udun_info(); extern s32b TIDALWAVE; @@ -1696,15 +1696,15 @@ extern s32b ENTPOTION; extern s32b VAPOR; extern s32b GEYSER; -bool_ *water_tidal_wave(); +bool_ *water_tidal_wave(int); char *water_tidal_wave_info(); -bool_ *water_ice_storm(); +bool_ *water_ice_storm(int); char *water_ice_storm_info(); -bool_ *water_ent_potion(); +bool_ *water_ent_potion(int); char *water_ent_potion_info(); -bool_ *water_vapor(); +bool_ *water_vapor(int); char *water_vapor_info(); -bool_ *water_geyser(); +bool_ *water_geyser(int); char *water_geyser_info(); extern s32b YAVANNA_CHARM_ANIMAL; @@ -1713,15 +1713,15 @@ extern s32b YAVANNA_TREE_ROOTS; extern s32b YAVANNA_WATER_BITE; extern s32b YAVANNA_UPROOT; -bool_ *yavanna_charm_animal(); +bool_ *yavanna_charm_animal(int); char *yavanna_charm_animal_info(); -bool_ *yavanna_grow_grass(); +bool_ *yavanna_grow_grass(int); char *yavanna_grow_grass_info(); -bool_ *yavanna_tree_roots(); +bool_ *yavanna_tree_roots(int); char *yavanna_tree_roots_info(); -bool_ *yavanna_water_bite(); +bool_ *yavanna_water_bite(int); char *yavanna_water_bite_info(); -bool_ *yavanna_uproot(); +bool_ *yavanna_uproot(int); char *yavanna_uproot_info(); extern s32b GROWTREE; @@ -1731,17 +1731,17 @@ extern s32b REGENERATION; extern s32b SUMMONANNIMAL; extern s32b GROW_ATHELAS; -bool_ *nature_grow_trees(); +bool_ *nature_grow_trees(int); char *nature_grow_trees_info(); -bool_ *nature_healing(); +bool_ *nature_healing(int); char *nature_healing_info(); -bool_ *nature_recovery(); +bool_ *nature_recovery(int); char *nature_recovery_info(); -bool_ *nature_regeneration(); +bool_ *nature_regeneration(int); char *nature_regeneration_info(); -bool_ *nature_summon_animal(); +bool_ *nature_summon_animal(int); char *nature_summon_animal_info(); -bool_ *nature_grow_athelas(); +bool_ *nature_grow_athelas(int); char *nature_grow_athelas_info(); extern s32b DEVICE_HEAL_MONSTER; @@ -1759,33 +1759,33 @@ extern s32b DEVICE_THUNDERLORDS; extern s32b DEVICE_RADAGAST; extern s32b DEVICE_VALAROMA; -bool_ *device_heal_monster(); +bool_ *device_heal_monster(int); char *device_heal_monster_info(); -bool_ *device_haste_monster(); +bool_ *device_haste_monster(int); char *device_haste_monster_info(); -bool_ *device_wish(); +bool_ *device_wish(int); char *device_wish_info(); -bool_ *device_summon_monster(); +bool_ *device_summon_monster(int); char *device_summon_monster_info(); -bool_ *device_mana(); +bool_ *device_mana(int); char *device_mana_info(); -bool_ *device_nothing(); +bool_ *device_nothing(int); char *device_nothing_info(); -bool_ *device_lebohaum(); +bool_ *device_lebohaum(int); char *device_lebohaum_info(); -bool_ *device_maggot(); +bool_ *device_maggot(int); char *device_maggot_info(); -bool_ *device_holy_fire(); +bool_ *device_holy_fire(int); char *device_holy_fire_info(); -bool_ *device_eternal_flame(); +bool_ *device_eternal_flame(int); char *device_eternal_flame_info(); -bool_ *device_durandil(); +bool_ *device_durandil(int); char *device_durandil_info(); -bool_ *device_thunderlords(); +bool_ *device_thunderlords(int); char *device_thunderlords_info(); -bool_ *device_radagast(); +bool_ *device_radagast(int); char *device_radagast_info(); -bool_ *device_valaroma(); +bool_ *device_valaroma(int); char *device_valaroma_info(); extern s32b MUSIC_STOP; @@ -1802,51 +1802,51 @@ extern s32b MUSIC_WIND; extern s32b MUSIC_YLMIR; extern s32b MUSIC_AMBARKANTA; -bool_ *music_stop_singing_spell(); +bool_ *music_stop_singing_spell(int); char *music_stop_singing_info(); int music_holding_pattern_lasting(); -bool_ *music_holding_pattern_spell(); +bool_ *music_holding_pattern_spell(int); char *music_holding_pattern_info(); int music_illusion_pattern_lasting(); -bool_ *music_illusion_pattern_spell(); +bool_ *music_illusion_pattern_spell(int); char *music_illusion_pattern_info(); int music_stun_pattern_lasting(); -bool_ *music_stun_pattern_spell(); +bool_ *music_stun_pattern_spell(int); char *music_stun_pattern_info(); int music_song_of_the_sun_lasting(); -bool_ *music_song_of_the_sun_spell(); +bool_ *music_song_of_the_sun_spell(int); char *music_song_of_the_sun_info(); int music_flow_of_life_lasting(); -bool_ *music_flow_of_life_spell(); +bool_ *music_flow_of_life_spell(int); char *music_flow_of_life_info(); int music_heroic_ballad_lasting(); -bool_ *music_heroic_ballad_spell(); +bool_ *music_heroic_ballad_spell(int); char *music_heroic_ballad_info(); int music_hobbit_melodies_lasting(); -bool_ *music_hobbit_melodies_spell(); +bool_ *music_hobbit_melodies_spell(int); char *music_hobbit_melodies_info(); int music_clairaudience_lasting(); -bool_ *music_clairaudience_spell(); +bool_ *music_clairaudience_spell(int); char *music_clairaudience_info(); -bool_ *music_blow_spell(); +bool_ *music_blow_spell(int); char *music_blow_info(); -bool_ *music_gush_of_wind_spell(); +bool_ *music_gush_of_wind_spell(int); char *music_gush_of_wind_info(); -bool_ *music_horns_of_ylmir_spell(); +bool_ *music_horns_of_ylmir_spell(int); char *music_horns_of_ylmir_info(); -bool_ *music_ambarkanta_spell(); +bool_ *music_ambarkanta_spell(int); char *music_ambarkanta_info(); extern s32b AULE_FIREBRAND; @@ -1854,13 +1854,13 @@ extern s32b AULE_ENCHANT_WEAPON; extern s32b AULE_ENCHANT_ARMOUR; extern s32b AULE_CHILD; -bool_ *aule_firebrand_spell(); +bool_ *aule_firebrand_spell(int); char *aule_firebrand_info(); -bool_ *aule_enchant_weapon_spell(); +bool_ *aule_enchant_weapon_spell(int); char *aule_enchant_weapon_info(); -bool_ *aule_enchant_armour_spell(); +bool_ *aule_enchant_armour_spell(int); char *aule_enchant_armour_info(); -bool_ *aule_child_spell(); +bool_ *aule_child_spell(int); char *aule_child_info(); extern s32b MANDOS_TEARS_LUTHIEN; @@ -1868,13 +1868,13 @@ extern s32b MANDOS_SPIRIT_FEANTURI; extern s32b MANDOS_TALE_DOOM; extern s32b MANDOS_CALL_HALLS; -bool_ *mandos_tears_of_luthien_spell(); +bool_ *mandos_tears_of_luthien_spell(int); char *mandos_tears_of_luthien_info(); -bool_ *mandos_spirit_of_the_feanturi_spell(); +bool_ *mandos_spirit_of_the_feanturi_spell(int); char *mandos_spirit_of_the_feanturi_info(); -bool_ *mandos_tale_of_doom_spell(); +bool_ *mandos_tale_of_doom_spell(int); char *mandos_tale_of_doom_info(); -bool_ *mandos_call_to_the_halls_spell(); +bool_ *mandos_call_to_the_halls_spell(int); char *mandos_call_to_the_halls_info(); extern s32b ULMO_BELEGAER; @@ -1882,13 +1882,13 @@ extern s32b ULMO_DRAUGHT_ULMONAN; extern s32b ULMO_CALL_ULUMURI; extern s32b ULMO_WRATH; -bool_ *ulmo_song_of_belegaer_spell(); +bool_ *ulmo_song_of_belegaer_spell(int); char *ulmo_song_of_belegaer_info(); -bool_ *ulmo_draught_of_ulmonan_spell(); +bool_ *ulmo_draught_of_ulmonan_spell(int); char *ulmo_draught_of_ulmonan_info(); -bool_ *ulmo_call_of_the_ulumuri_spell(); +bool_ *ulmo_call_of_the_ulumuri_spell(int); char *ulmo_call_of_the_ulumuri_info(); -bool_ *ulmo_wrath_of_ulmo_spell(); +bool_ *ulmo_wrath_of_ulmo_spell(int); char *ulmo_wrath_of_ulmo_info(); extern s32b VARDA_LIGHT_VALINOR; @@ -1896,13 +1896,13 @@ extern s32b VARDA_CALL_ALMAREN; extern s32b VARDA_EVENSTAR; extern s32b VARDA_STARKINDLER; -bool_ *varda_light_of_valinor_spell(); +bool_ *varda_light_of_valinor_spell(int); char *varda_light_of_valinor_info(); -bool_ *varda_call_of_almaren_spell(); +bool_ *varda_call_of_almaren_spell(int); char *varda_call_of_almaren_info(); -bool_ *varda_evenstar_spell(); +bool_ *varda_evenstar_spell(int); char *varda_evenstar_info(); -bool_ *varda_star_kindler_spell(); +bool_ *varda_star_kindler_spell(int); char *varda_star_kindler_info(); /* spells4.c */ @@ -1954,6 +1954,7 @@ void lua_cast_school_spell(s32b spell_idx, bool_ no_cost); void spell_description_add_line(s32b spell_idx, cptr line); void device_allocation_init(device_allocation *device_allocation, byte tval); +device_allocation *device_allocation_new(byte tval); void dice_init(dice_type *dice, long base, long num, long sides); bool_ dice_parse(dice_type *dice, cptr s); @@ -1961,6 +1962,13 @@ void dice_parse_checked(dice_type *dice, cptr s); long dice_roll(dice_type *dice); void dice_print(dice_type *dice, char *buf); +/* spells5.c */ +void school_spells_init(); +spell_type *spell_at(s32b index); +s16b get_random_spell(s16b random_type, int lev); +bool_ check_spell_depends(s16b spell_idx); +int spell_get_school_idx(s16b spell_idx, int i); + /* range.c */ extern void range_init(range_type *range, s32b min, s32b max); @@ -2341,6 +2349,7 @@ extern void theme_intro(); /* lua_bind.c */ +extern s16b can_spell_random(s16b spell_idx); extern magic_power *grab_magic_power(magic_power *m_ptr, int num); extern bool_ get_magic_power(int *sn, magic_power *powers, int max_powers, void (*power_info)(char *p, int power), int plev, int cast_stat); extern bool_ lua_spell_success(magic_power *spell, int stat, char *oups_fct); @@ -2363,8 +2372,6 @@ extern int get_lua_list_size(cptr list_name); extern bool_ get_com_lua(cptr promtp, int *com); extern s16b new_school(int i, cptr name, s16b skill); -extern s16b new_spell(int i, cptr name); -extern spell_type *grab_spell_type(s16b num); extern school_type *grab_school_type(s16b num); extern s32b lua_get_level(s32b s, s32b lvl, s32b max, s32b min, s32b bonus); extern s32b get_level_device(s32b s, s32b max, s32b min); diff --git a/src/init2.c b/src/init2.c index 9e9911f8..f195c469 100644 --- a/src/init2.c +++ b/src/init2.c @@ -1960,10 +1960,8 @@ static errr init_misc(void) message__tail = MESSAGE_BUF; /* Prepare schools */ - max_spells = 0; max_schools = 0; schools = NULL; - school_spells = NULL; process_hooks(HOOK_INIT_GAME, "(s)", "begin"); @@ -2067,13 +2065,6 @@ static errr init_wilderness(void) return 0; } -void init_spells(s16b new_size) -{ - /* allocate the extra memory */ - C_MAKE(school_spells, new_size, spell_type); - max_spells = new_size; -} - void init_schools(s16b new_size) { /* allocate the extra memory */ diff --git a/src/lua_bind.c b/src/lua_bind.c index 456e653d..0c099c00 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -17,6 +17,11 @@ #include "tolua.h" extern lua_State *L; +s16b can_spell_random(s16b spell_idx) +{ + return spell_at(spell_idx)->random_type; +} + magic_power *grab_magic_power(magic_power *m_ptr, int num) { return (&m_ptr[num]); @@ -171,19 +176,6 @@ s16b new_school(int i, cptr name, s16b skill) return (i); } -s16b new_spell(int i, cptr name) -{ - school_spells[i].name = string_make(name); - school_spells[i].level = 0; - school_spells[i].level = 0; - return (i); -} - -spell_type *grab_spell_type(s16b num) -{ - return (&school_spells[num]); -} - school_type *grab_school_type(s16b num) { return (&schools[num]); @@ -245,12 +237,10 @@ s32b get_level_device(s32b s, s32b max, s32b min) return lvl; } -int get_mana(s32b s) { - return exec_lua(format("return get_mana(%d)", s)); -} - -static int get_spell_stat(s32b s) { - return exec_lua(format("return get_spell_stat(%d)", s)); +int get_mana(s32b s) +{ + spell_type *spell = spell_at(s); + return get_level(s, spell->mana_range.max, spell->mana_range.min); } /** Returns spell chance of failure for spell */ @@ -261,9 +251,9 @@ s32b spell_chance(s32b s) /* Extract the base spell failure rate */ if (get_level_use_stick > -1) { - return lua_spell_device_chance(s_ptr->fail, level, s_ptr->skill_level); + return lua_spell_device_chance(s_ptr->failure_rate, level, s_ptr->skill_level); } else { - return lua_spell_chance(s_ptr->fail, level, s_ptr->skill_level, get_mana(s), get_power(s), get_spell_stat(s)); + return lua_spell_chance(s_ptr->failure_rate, level, s_ptr->skill_level, get_mana(s), get_power(s), s_ptr->casting_stat); } } @@ -582,5 +572,8 @@ void timer_aggravate_evil_callback() cptr get_spell_info(s32b s) { - return string_exec_lua(format("return __spell_info[" FMTs32b "]()", s)); + spell_type *spell = spell_at(s); + + assert(spell->info_func != NULL); + return spell->info_func(); } diff --git a/src/object1.c b/src/object1.c index dac3085e..a4676744 100644 --- a/src/object1.c +++ b/src/object1.c @@ -2857,7 +2857,8 @@ void describe_device(object_type *o_ptr) print_device_desc(o_ptr->pval2); text_out("\nSpell level: "); - text_out_c(TERM_L_BLUE, string_exec_lua(format("return tostring(get_level(%d, 50, 0))", o_ptr->pval2))); + sprintf(buf, FMTs32b, get_level(o_ptr->pval2, 50, 0)); + text_out_c(TERM_L_BLUE, buf); text_out("\nMinimum Magic Device level to increase spell level: "); text_out_c(TERM_L_BLUE, format("%d", school_spells[o_ptr->pval2].skill_level)); diff --git a/src/object2.c b/src/object2.c index 75fc7fa8..cf413c4c 100644 --- a/src/object2.c +++ b/src/object2.c @@ -2535,7 +2535,8 @@ static bool_ make_ego_item(object_type *o_ptr, bool_ good) */ void charge_stick(object_type *o_ptr) { - o_ptr->pval = exec_lua(format("return get_stick_charges(%d)", o_ptr->pval2)); + spell_type *spell = spell_at(o_ptr->pval2); + o_ptr->pval = dice_roll(&spell->device_charges); } /* @@ -3225,6 +3226,94 @@ static void a_m_aux_3(object_type *o_ptr, int level, int power) } +/* + * Get device allocation for a given spell and tval + */ +static device_allocation *get_device_allocation(spell_type *spell, byte tval) +{ + struct sglib_device_allocation_iterator it; + device_allocation *device_allocation; + + for (device_allocation = sglib_device_allocation_it_init(&it, spell->device_allocation); + device_allocation != NULL; + device_allocation = sglib_device_allocation_it_next(&it)) + { + if (device_allocation->tval == tval) + { + return device_allocation; + } + } + + return NULL; +} + +/* + * Get a spell for a given stick(wand, staff, rod) + */ +long get_random_stick(byte tval, int level) +{ + int tries; + + for (tries = 0; tries < 1000; tries++) + { + long spell_idx = rand_int(school_spells_count); + spell_type *spell = spell_at(spell_idx); + device_allocation *device_allocation = get_device_allocation(spell, tval); + + if ((device_allocation != NULL) && + (rand_int(spell->skill_level * 3) < level) && + (magik(100 - device_allocation->rarity))) + { + return spell_idx; + } + } + + return -1; +} + + +/* + * Randomized level + */ +static int randomized_level_in_range(range_type *range, int level) +{ + s32b r = range->max - range->min; + + /* The basic idea is to have a max possible level of half the dungeon level */ + if (r * 2 > level) + { + r = level / 2; + } + + /* Randomize a bit */ + r = m_bonus(r, dun_level); + + /* get the result */ + return range->min + r; +} + + +/* + * Get a random base level + */ +static int get_stick_base_level(byte tval, int level, int spl) +{ + spell_type *spell = spell_at(spl); + device_allocation *device_allocation = get_device_allocation(spell, tval); + return randomized_level_in_range(&device_allocation->base_level, level); +} + +/* + * Get a random max level + */ +static int get_stick_max_level(byte tval, int level, int spl) +{ + spell_type *spell = spell_at(spl); + device_allocation *device_allocation = get_device_allocation(spell, tval); + return randomized_level_in_range(&device_allocation->max_level, level); +} + + /* * Apply magic to an item known to be "boring" * @@ -3263,9 +3352,13 @@ static void a_m_aux_4(object_type *o_ptr, int level, int power) /* Only random ones */ if (magik(75)) - i = exec_lua(format("return get_random_spell(SKILL_MAGIC, %d)", level)); + { + i = get_random_spell(SKILL_MAGIC, level); + } else - i = exec_lua(format("return get_random_spell(SKILL_SPIRITUALITY, %d)", level)); + { + i = get_random_spell(SKILL_SPIRITUALITY, level); + } /* Use globe of light(or the first one) */ if (i == -1) @@ -3359,9 +3452,12 @@ static void a_m_aux_4(object_type *o_ptr, int level, int power) /* Decide the spell, pval == -1 means to bypass spell selection */ if (o_ptr->pval != -1) { - int spl = exec_lua("return get_random_stick(TV_WAND, dun_level)"); + int spl = get_random_stick(TV_WAND, dun_level); - if (spl == -1) spl = exec_lua("return find_spell('Manathrust')"); + if (spl == -1) + { + spl = MANATHRUST; + } o_ptr->pval2 = spl; } @@ -3372,8 +3468,8 @@ static void a_m_aux_4(object_type *o_ptr, int level, int power) } /* Ok now get a base level */ - call_lua("get_stick_base_level", "(d,d,d)", "d", TV_WAND, dun_level, o_ptr->pval2, &bonus_lvl); - call_lua("get_stick_max_level", "(d,d,d)", "d", TV_WAND, dun_level, o_ptr->pval2, &max_lvl); + bonus_lvl = get_stick_base_level(TV_WAND, dun_level, o_ptr->pval2); + max_lvl = get_stick_max_level(TV_WAND, dun_level, o_ptr->pval2); o_ptr->pval3 = (max_lvl << 16) + (bonus_lvl & 0xFFFF); /* Hack -- charge wands */ @@ -3387,9 +3483,12 @@ static void a_m_aux_4(object_type *o_ptr, int level, int power) /* Decide the spell, pval == -1 means to bypass spell selection */ if (o_ptr->pval != -1) { - int spl = exec_lua("return get_random_stick(TV_STAFF, dun_level)"); + int spl = get_random_stick(TV_STAFF, dun_level); - if (spl == -1) spl = exec_lua("return find_spell('Globe of Light')"); + if (spl == -1) + { + spl = GLOBELIGHT; + } o_ptr->pval2 = spl; } @@ -3400,8 +3499,8 @@ static void a_m_aux_4(object_type *o_ptr, int level, int power) } /* Ok now get a base level */ - call_lua("get_stick_base_level", "(d,d,d)", "d", TV_STAFF, dun_level, o_ptr->pval2, &bonus_lvl); - call_lua("get_stick_max_level", "(d,d,d)", "d", TV_STAFF, dun_level, o_ptr->pval2, &max_lvl); + bonus_lvl = get_stick_base_level(TV_STAFF, dun_level, o_ptr->pval2); + max_lvl = get_stick_max_level(TV_STAFF, dun_level, o_ptr->pval2); o_ptr->pval3 = (max_lvl << 16) + (bonus_lvl & 0xFFFF); /* Hack -- charge staffs */ @@ -3975,8 +4074,8 @@ void apply_magic(object_type *o_ptr, int lev, bool_ okay, bool_ good, bool_ grea } /* Determine a base and a max level */ - call_lua("get_stick_base_level", "(d,d,d)", "d", o_ptr->tval, dun_level, o_ptr->pval2, &base_lvl); - call_lua("get_stick_max_level", "(d,d,d)", "d", o_ptr->tval, dun_level, o_ptr->pval2, &max_lvl); + base_lvl = get_stick_base_level(o_ptr->tval, dun_level, o_ptr->pval2); + max_lvl = get_stick_max_level(o_ptr->tval, dun_level, o_ptr->pval2); o_ptr->pval3 = (max_lvl << 16) + (base_lvl & 0xFFFF); /* Hack -- charge wands */ diff --git a/src/script.c b/src/script.c index c9979c17..51484d3a 100644 --- a/src/script.c +++ b/src/script.c @@ -234,14 +234,6 @@ void init_lua_init() exec_lua(format("finish_school(%d)", i)); } - /* Finish up the spells */ - max = exec_lua("return __tmp_spells_num"); - init_spells(max); - for (i = 0; i < max; i++) - { - exec_lua(format("finish_spell(%d)", i)); - } - /* Finish up the corruptions */ init_corruptions(); } diff --git a/src/spells.pkg b/src/spells.pkg index 0ea452bf..6360e7d3 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2147,6 +2147,8 @@ extern magic_power *grab_magic_power @ get_magic_power(magic_power *m_ptr, int n */ extern bool lua_spell_success @ magic_power_sucess(magic_power *spell, int stat, char *oups_fct=NULL); +extern s16b can_spell_random(s16b spell_idx); + /* Schools */ /** @struct school_spell_type @@ -2166,24 +2168,6 @@ struct spell_type@school_spell_type */ byte skill_level; - /** @structvar mana - * @brief Number - * @note Required mana at lvl 1 - */ - byte mana; - - /** @structvar mana_max - * @brief Number - * @note Required mana at max lvl - */ - byte mana_max; - - /** @structvar fail - * @brief Number - * @note Minimum chance of failure - */ - s16b fail; - /** @structvar level * @brief Number * @note Spell level(0 = not learnt) @@ -2227,37 +2211,6 @@ struct school_type */ extern s16b new_school(int i, cptr name, s16b skill); -/** @fn new_spell(int i, cptr name) - * @dgonly - * @brief Add spell to array of spells for a school.\n - * @param i Number \n i is index of school spell array where spell is added. - * There is no range checking. - * @brief Index - * @param name String \n name is the name of the spell. - * @brief Name - * @return Number \ The index parameter. - * @note - * Spell level is set to zero.\n\n - * Note: do not call this function directly.\n - * By order of DG. - * @note (see file lua_bind.c) - */ -extern s16b new_spell(int i, cptr name); - -/** @fn spell(s16b num); - * @dgonly - * @brief Get spell "num" from array of spells for a school.\n - * @param num Number \n num is the index of the spell. - * There is no range checking. - * @brief Index - * @return spell_type \n The spell. - * @note - * Note: do not call this function directly.\n - * By order of DG. - * @note (see file lua_bind.c) - */ -extern spell_type *grab_spell_type @ spell(s16b num); - /** @fn school(s16b num); * @dgonly * @brief Get school "num" from array of schools.\n @@ -2338,7 +2291,7 @@ extern s32b lua_spell_device_chance(s32b chance, int level, int base_level); * If no spell is chosen, -1 is returned. * @note (see file cmd5.c) */ -extern s32b get_school_spell(cptr do_what, cptr check_fct, s16b force_book); +extern s32b get_school_spell(cptr do_what, s16b force_book); /** @fn get_pos_player(int dis, int *ny=0, int *nx=0) * @brief Get a grid near the player.\n @@ -2357,528 +2310,6 @@ extern s32b get_school_spell(cptr do_what, cptr check_fct, s16b force_book); */ extern void get_pos_player(int dis, int *ny=0, int *nx=0); -/** - * Geomancy - */ -extern void geomancy_random_floor(int y, int x, bool kill_wall); -extern void geomancy_dig(int y, int x, int dir, int length); -extern void channel_the_elements(int y, int x, int level); - -/* - * Air - */ -extern s32b NOXIOUSCLOUD; -extern s32b AIRWINGS; -extern s32b INVISIBILITY; -extern s32b POISONBLOOD; -extern s32b THUNDERSTORM; -extern s32b STERILIZE; - -bool_ *air_noxious_cloud(); -char *air_noxious_cloud_info(); -bool_ *air_wings_of_winds(); -char *air_wings_of_winds_info(); -bool_ *air_invisibility(); -char *air_invisibility_info(); -bool_ *air_poison_blood(); -char *air_poison_blood_info(); -bool_ *air_thunderstorm(); -char *air_thunderstorm_info(); -bool_ *air_sterilize(); -char *air_sterilize_info(); - -/* - * Conveyance - */ -extern s32b BLINK; -extern s32b DISARM; -extern s32b TELEPORT; -extern s32b TELEAWAY; -extern s32b RECALL; -extern s32b PROBABILITY_TRAVEL; - -bool_ *convey_blink(); -char *convey_blink_info(); -bool_ *convey_disarm(); -char *convey_disarm_info(); -bool_ *convey_teleport(); -char *convey_teleport_info(); -bool_ *convey_teleport_away(); -char *convey_teleport_away_info(); -bool_ *convey_recall(); -char *convey_recall_info(); -bool_ *convey_probability_travel(); -char *convey_probability_travel_info(); - -/* - * Demonology - */ -extern s32b DEMON_BLADE; -extern s32b DEMON_MADNESS; -extern s32b DEMON_FIELD; -extern s32b DOOM_SHIELD; -extern s32b UNHOLY_WORD; -extern s32b DEMON_CLOAK; -extern s32b DEMON_SUMMON; -extern s32b DISCHARGE_MINION; -extern s32b CONTROL_DEMON; - -bool_ *demonology_demon_blade(); -char *demonology_demon_blade_info(); -bool_ *demonology_demon_madness(); -char *demonology_demon_madness_info(); -bool_ *demonology_demon_field(); -char *demonology_demon_field_info(); -bool_ *demonology_doom_shield(); -char *demonology_doom_shield_info(); -bool_ *demonology_unholy_word(); -char *demonology_unholy_word_info(); -bool_ *demonology_demon_cloak(); -char *demonology_demon_cloak_info(); -bool_ *demonology_summon_demon(); -char *demonology_summon_demon_info(); -bool_ *demonology_discharge_minion(); -char *demonology_discharge_minion_info(); -bool_ *demonology_control_demon(); -char *demonology_control_demon_info(); - -/* - * Divination - */ -extern s32b STARIDENTIFY; -extern s32b IDENTIFY; -extern s32b VISION; -extern s32b SENSEHIDDEN; -extern s32b REVEALWAYS; -extern s32b SENSEMONSTERS; - -bool_ *divination_greater_identify(); -char *divination_greater_identify_info(); -bool_ *divination_identify(); -char *divination_identify_info(); -bool_ *divination_vision(); -char *divination_vision_info(); -bool_ *divination_sense_hidden(); -char *divination_sense_hidden_info(); -bool_ *divination_reveal_ways(); -char *divination_reveal_ways_info(); -bool_ *divination_sense_monsters(); -char *divination_sense_monsters_info(); - -/* - * Earth - */ -extern s32b STONESKIN; -extern s32b DIG; -extern s32b STONEPRISON; -extern s32b STRIKE; -extern s32b SHAKE; - -bool_ *earth_stone_skin(); -char *earth_stone_skin_info(); -bool_ *earth_dig(); -char *earth_dig_info(); -bool_ *earth_stone_prison(); -char *earth_stone_prison_info(); -bool_ *earth_strike(); -char *earth_strike_info(); -bool_ *earth_shake(); -char *earth_shake_info(); - -/* - * Eru - */ -extern s32b ERU_SEE; -extern s32b ERU_LISTEN; -extern s32b ERU_UNDERSTAND; -extern s32b ERU_PROT; - -bool_ *eru_see_the_music(); -char *eru_see_the_music_info(); -bool_ *eru_listen_to_the_music(); -char *eru_listen_to_the_music_info(); -bool_ *eru_know_the_music(); -char *eru_know_the_music_info(); -bool_ *eru_lay_of_protection(); -char *eru_lay_of_protection_info(); - -/* - * Fire - */ -extern s32b GLOBELIGHT; -extern s32b FIREFLASH; -extern s32b FIERYAURA; -extern s32b FIREWALL; -extern s32b FIREGOLEM; - -bool_ *fire_globe_of_light(); -char *fire_globe_of_light_info(); -bool_ *fire_fireflash(); -char *fire_fireflash_info(); -bool_ *fire_fiery_shield(); -char *fire_fiery_shield_info(); -bool_ *fire_firewall(); -char *fire_firewall_info(); -bool_ *fire_golem(); -char *fire_golem_info(); - -/* - * Geomancy - */ -extern s32b CALL_THE_ELEMENTS; -extern s32b CHANNEL_ELEMENTS; -extern s32b ELEMENTAL_WAVE; -extern s32b VAPORIZE; -extern s32b GEOLYSIS; -extern s32b DRIPPING_TREAD; -extern s32b GROW_BARRIER; -extern s32b ELEMENTAL_MINION; - -bool_ *geomancy_call_the_elements(); -char *geomancy_call_the_elements_info(); -bool_ *geomancy_channel_elements(); -char *geomancy_channel_elements_info(); -bool_ *geomancy_elemental_wave(); -char *geomancy_elemental_wave_info(); -bool_ *geomancy_vaporize(); -char *geomancy_vaporize_info(); -bool_ geomancy_vaporize_depends(); -bool_ *geomancy_geolysis(); -char *geomancy_geolysis_info(); -bool_ geomancy_geolysis_depends(); -bool_ *geomancy_dripping_tread(); -char *geomancy_dripping_tread_info(); -bool_ geomancy_dripping_tread_depends(); -bool_ *geomancy_grow_barrier(); -char *geomancy_grow_barrier_info(); -bool_ geomancy_grow_barrier_depends(); -bool_ *geomancy_elemental_minion(); -char *geomancy_elemental_minion_info(); - -extern s32b MANATHRUST; -extern s32b DELCURSES; -extern s32b RESISTS; -extern s32b MANASHIELD; - -bool_ *mana_manathrust(); -char *mana_manathrust_info(); -bool_ *mana_remove_curses(); -char *mana_remove_curses_info(); -bool_ *mana_elemental_shield(); -char *mana_elemental_shield_info(); -bool_ *mana_disruption_shield(); -char *mana_disruption_shield_info(); - -extern s32b MANWE_SHIELD; -extern s32b MANWE_AVATAR; -extern s32b MANWE_BLESS; -extern s32b MANWE_CALL; - -bool_ *manwe_wind_shield(); -char *manwe_wind_shield_info(); -bool_ *manwe_avatar(); -char *manwe_avatar_info(); -bool_ *manwe_blessing(); -char *manwe_blessing_info(); -bool_ *manwe_call(); -char *manwe_call_info(); - -extern s32b MELKOR_CURSE; -extern s32b MELKOR_CORPSE_EXPLOSION; -extern s32b MELKOR_MIND_STEAL; - -bool_ *melkor_curse(); -char *melkor_curse_info(); -bool_ *melkor_corpse_explosion(); -char *melkor_corpse_explosion_info(); -bool_ *melkor_mind_steal(); -char *melkor_mind_steal_info(); - -extern s32b RECHARGE; -extern s32b SPELLBINDER; -extern s32b DISPERSEMAGIC; -extern s32b TRACKER; -extern s32b INERTIA_CONTROL; - -bool_ *meta_recharge(); -char *meta_recharge_info(); -bool_ *meta_spellbinder(); -char *meta_spellbinder_info(); -bool_ *meta_disperse_magic(); -char *meta_disperse_magic_info(); -bool_ *meta_tracker(); -char *meta_tracker_info(); -bool_ *meta_inertia_control(); -char *meta_inertia_control_info(); - -extern s32b CHARM; -extern s32b CONFUSE; -extern s32b ARMOROFFEAR; -extern s32b STUN; - -bool_ *mind_charm(); -char *mind_charm_info(); -bool_ *mind_confuse(); -char *mind_confuse_info(); -bool_ *mind_armor_of_fear(); -char *mind_armor_of_fear_info(); -bool_ *mind_stun(); -char *mind_stun_info(); - -extern s32b MAGELOCK; -extern s32b SLOWMONSTER; -extern s32b ESSENCESPEED; -extern s32b BANISHMENT; - -bool_ *tempo_magelock(); -char *tempo_magelock_info(); -bool_ *tempo_slow_monster(); -char *tempo_slow_monster_info(); -bool_ *tempo_essence_of_speed(); -char *tempo_essence_of_speed_info(); -bool_ *tempo_banishment(); -char *tempo_banishment_info(); - -extern s32b TULKAS_AIM; -extern s32b TULKAS_WAVE; -extern s32b TULKAS_SPIN; - -bool_ *tulkas_divine_aim(); -char *tulkas_divine_aim_info(); -bool_ *tulkas_wave_of_power(); -char *tulkas_wave_of_power_info(); -bool_ *tulkas_whirlwind(); -char *tulkas_whirlwind_info(); - -extern s32b DRAIN; -extern s32b GENOCIDE; -extern s32b WRAITHFORM; -extern s32b FLAMEOFUDUN; - -bool_ *udun_drain(); -char *udun_drain_info(); -bool_ *udun_genocide(); -char *udun_genocide_info(); -bool_ *udun_wraithform(); -char *udun_wraithform_info(); -bool_ *udun_flame_of_udun(); -char *udun_flame_of_udun_info(); - -extern s32b TIDALWAVE; -extern s32b ICESTORM; -extern s32b ENTPOTION; -extern s32b VAPOR; -extern s32b GEYSER; - -bool_ *water_tidal_wave(); -char *water_tidal_wave_info(); -bool_ *water_ice_storm(); -char *water_ice_storm_info(); -bool_ *water_ent_potion(); -char *water_ent_potion_info(); -bool_ *water_vapor(); -char *water_vapor_info(); -bool_ *water_geyser(); -char *water_geyser_info(); - -extern s32b YAVANNA_CHARM_ANIMAL; -extern s32b YAVANNA_GROW_GRASS; -extern s32b YAVANNA_TREE_ROOTS; -extern s32b YAVANNA_WATER_BITE; -extern s32b YAVANNA_UPROOT; - -bool_ *yavanna_charm_animal(); -char *yavanna_charm_animal_info(); -bool_ *yavanna_grow_grass(); -char *yavanna_grow_grass_info(); -bool_ *yavanna_tree_roots(); -char *yavanna_tree_roots_info(); -bool_ *yavanna_water_bite(); -char *yavanna_water_bite_info(); -bool_ *yavanna_uproot(); -char *yavanna_uproot_info(); - -extern s32b GROWTREE; -extern s32b HEALING; -extern s32b RECOVERY; -extern s32b REGENERATION; -extern s32b SUMMONANNIMAL; -extern s32b GROW_ATHELAS; - -bool_ *nature_grow_trees(); -char *nature_grow_trees_info(); -bool_ *nature_healing(); -char *nature_healing_info(); -bool_ *nature_recovery(); -char *nature_recovery_info(); -bool_ *nature_regeneration(); -char *nature_regeneration_info(); -bool_ *nature_summon_animal(); -char *nature_summon_animal_info(); -bool_ *nature_grow_athelas(); -char *nature_grow_athelas_info(); - -extern s32b DEVICE_HEAL_MONSTER; -extern s32b DEVICE_SPEED_MONSTER; -extern s32b DEVICE_WISH; -extern s32b DEVICE_SUMMON; -extern s32b DEVICE_MANA; -extern s32b DEVICE_NOTHING; -extern s32b DEVICE_LEBOHAUM; -extern s32b DEVICE_MAGGOT; -extern s32b DEVICE_HOLY_FIRE; -extern s32b DEVICE_ETERNAL_FLAME; -extern s32b DEVICE_DURANDIL; -extern s32b DEVICE_THUNDERLORDS; -extern s32b DEVICE_RADAGAST; -extern s32b DEVICE_VALAROMA; - -bool_ *device_heal_monster(); -char *device_heal_monster_info(); -bool_ *device_haste_monster(); -char *device_haste_monster_info(); -bool_ *device_wish(); -char *device_wish_info(); -bool_ *device_summon_monster(); -char *device_summon_monster_info(); -bool_ *device_mana(); -char *device_mana_info(); -bool_ *device_nothing(); -char *device_nothing_info(); -bool_ *device_lebohaum(); -char *device_lebohaum_info(); -bool_ *device_maggot(); -char *device_maggot_info(); -bool_ *device_holy_fire(); -char *device_holy_fire_info(); -bool_ *device_eternal_flame(); -char *device_eternal_flame_info(); -bool_ *device_durandil(); -char *device_durandil_info(); -bool_ *device_thunderlords(); -char *device_thunderlords_info(); -bool_ *device_radagast(); -char *device_radagast_info(); -bool_ *device_valaroma(); -char *device_valaroma_info(); - -extern s32b MUSIC_STOP; -extern s32b MUSIC_HOLD; -extern s32b MUSIC_CONF; -extern s32b MUSIC_STUN; -extern s32b MUSIC_LITE; -extern s32b MUSIC_HEAL; -extern s32b MUSIC_HERO; -extern s32b MUSIC_TIME; -extern s32b MUSIC_MIND; -extern s32b MUSIC_BLOW; -extern s32b MUSIC_WIND; -extern s32b MUSIC_YLMIR; -extern s32b MUSIC_AMBARKANTA; - -bool_ *music_stop_singing_spell(); -char *music_stop_singing_info(); - -int music_holding_pattern_lasting(); -bool_ *music_holding_pattern_spell(); -char *music_holding_pattern_info(); - -int music_illusion_pattern_lasting(); -bool_ *music_illusion_pattern_spell(); -char *music_illusion_pattern_info(); - -int music_stun_pattern_lasting(); -bool_ *music_stun_pattern_spell(); -char *music_stun_pattern_info(); - -int music_song_of_the_sun_lasting(); -bool_ *music_song_of_the_sun_spell(); -char *music_song_of_the_sun_info(); - -int music_flow_of_life_lasting(); -bool_ *music_flow_of_life_spell(); -char *music_flow_of_life_info(); - -int music_heroic_ballad_lasting(); -bool_ *music_heroic_ballad_spell(); -char *music_heroic_ballad_info(); - -int music_hobbit_melodies_lasting(); -bool_ *music_hobbit_melodies_spell(); -char *music_hobbit_melodies_info(); - -int music_clairaudience_lasting(); -bool_ *music_clairaudience_spell(); -char *music_clairaudience_info(); - -bool_ *music_blow_spell(); -char *music_blow_info(); - -bool_ *music_gush_of_wind_spell(); -char *music_gush_of_wind_info(); - -bool_ *music_horns_of_ylmir_spell(); -char *music_horns_of_ylmir_info(); - -bool_ *music_ambarkanta_spell(); -char *music_ambarkanta_info(); - -extern s32b AULE_FIREBRAND; -extern s32b AULE_ENCHANT_WEAPON; -extern s32b AULE_ENCHANT_ARMOUR; -extern s32b AULE_CHILD; - -bool_ *aule_firebrand_spell(); -char *aule_firebrand_info(); -bool_ *aule_enchant_weapon_spell(); -char *aule_enchant_weapon_info(); -bool_ *aule_enchant_armour_spell(); -char *aule_enchant_armour_info(); -bool_ *aule_child_spell(); -char *aule_child_info(); - -extern s32b MANDOS_TEARS_LUTHIEN; -extern s32b MANDOS_SPIRIT_FEANTURI; -extern s32b MANDOS_TALE_DOOM; -extern s32b MANDOS_CALL_HALLS; - -bool_ *mandos_tears_of_luthien_spell(); -char *mandos_tears_of_luthien_info(); -bool_ *mandos_spirit_of_the_feanturi_spell(); -char *mandos_spirit_of_the_feanturi_info(); -bool_ *mandos_tale_of_doom_spell(); -char *mandos_tale_of_doom_info(); -bool_ *mandos_call_to_the_halls_spell(); -char *mandos_call_to_the_halls_info(); - -extern s32b ULMO_BELEGAER; -extern s32b ULMO_DRAUGHT_ULMONAN; -extern s32b ULMO_CALL_ULUMURI; -extern s32b ULMO_WRATH; - -bool_ *ulmo_song_of_belegaer_spell(); -char *ulmo_song_of_belegaer_info(); -bool_ *ulmo_draught_of_ulmonan_spell(); -char *ulmo_draught_of_ulmonan_info(); -bool_ *ulmo_call_of_the_ulumuri_spell(); -char *ulmo_call_of_the_ulumuri_info(); -bool_ *ulmo_wrath_of_ulmo_spell(); -char *ulmo_wrath_of_ulmo_info(); - -extern s32b VARDA_LIGHT_VALINOR; -extern s32b VARDA_CALL_ALMAREN; -extern s32b VARDA_EVENSTAR; -extern s32b VARDA_STARKINDLER; - -bool_ *varda_light_of_valinor_spell(); -char *varda_light_of_valinor_info(); -bool_ *varda_call_of_almaren_spell(); -char *varda_call_of_almaren_info(); -bool_ *varda_evenstar_spell(); -char *varda_evenstar_info(); -bool_ *varda_star_kindler_spell(); -char *varda_star_kindler_info(); - /** * spells4.c */ @@ -2912,3 +2343,11 @@ extern s32b SCHOOL_YAVANNA; void lua_cast_school_spell @ cast_school_spell(s32b spell_idx, bool no_cost = FALSE); void spell_description_add_line(s32b spell_idx, cptr line); + +/** + * spells5.c + */ +void school_spells_init(); +s16b get_random_spell(s16b random_type, int lev); +bool check_spell_depends(s16b spell_idx); +int spell_get_school_idx(s16b spell_idx, int i); diff --git a/src/spells3.c b/src/spells3.c index b8632bf9..07a2527b 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -179,7 +179,7 @@ s32b get_level_s(int sp, int max) return get_level(sp, max, 1); } -bool_ *air_noxious_cloud() +bool_ *air_noxious_cloud(int item) { int dir, type; @@ -211,7 +211,7 @@ char *air_noxious_cloud_info() return buf; } -bool_ *air_wings_of_winds() +bool_ *air_wings_of_winds(int item) { if (get_level_s(AIRWINGS, 50) >= 16) { @@ -237,7 +237,7 @@ char *air_wings_of_winds_info() return buf; } -bool_ *air_invisibility() +bool_ *air_invisibility(int item) { if (p_ptr->tim_invisible == 0) { @@ -257,7 +257,7 @@ char *air_invisibility_info() return buf; } -bool_ *air_poison_blood() +bool_ *air_poison_blood(int item) { bool_ *cast = NO_CAST; @@ -286,7 +286,7 @@ char *air_poison_blood_info() return buf; } -bool_ *air_thunderstorm() +bool_ *air_thunderstorm(int item) { if (p_ptr->tim_thunder == 0) { @@ -308,7 +308,7 @@ char *air_thunderstorm_info() return buf; } -bool_ *air_sterilize() +bool_ *air_sterilize(int item) { set_no_breeders((30) + 20 + get_level_s(STERILIZE, 70)); return CAST; @@ -323,7 +323,7 @@ char *air_sterilize_info() return buf; } -bool_ *convey_blink() +bool_ *convey_blink(int item) { if (get_level_s(BLINK, 50) >= 30) { @@ -350,7 +350,7 @@ char *convey_blink_info() return buf; } -bool_ *convey_disarm() +bool_ *convey_disarm(int item) { destroy_doors_touch(); if (get_level_s(DISARM, 50) >= 10) @@ -366,7 +366,7 @@ char *convey_disarm_info() return ""; } -bool_ *convey_teleport() +bool_ *convey_teleport(int item) { p_ptr->energy -= (25 - get_level_s(TELEPORT, 50)); teleport_player(100 + get_level_s(TELEPORT, 100)); @@ -382,7 +382,7 @@ char *convey_teleport_info() return buf; } -bool_ *convey_teleport_away() +bool_ *convey_teleport_away(int item) { if (get_level_s(TELEAWAY, 50) >= 20) { @@ -437,7 +437,7 @@ static int recall_get_f() return f; } -bool_ *convey_recall() +bool_ *convey_recall(int item) { int x,y; cave_type *c_ptr; @@ -493,7 +493,7 @@ char *convey_recall_info() return buf; } -bool_ *convey_probability_travel() +bool_ *convey_probability_travel(int item) { set_prob_travel(randint(20) + get_level_s(PROBABILITY_TRAVEL, 60)); return CAST; @@ -508,7 +508,7 @@ char *convey_probability_travel_info() return buf; } -bool_ *demonology_demon_blade() +bool_ *demonology_demon_blade(int item) { int rad, type; @@ -542,7 +542,7 @@ char *demonology_demon_blade_info() return buf; } -bool_ *demonology_demon_madness() +bool_ *demonology_demon_madness(int item) { int dir, type, y1, x1, y2, x2; @@ -590,7 +590,7 @@ char *demonology_demon_madness_info() return buf; } -bool_ *demonology_demon_field() +bool_ *demonology_demon_field(int item) { int dir; @@ -617,7 +617,7 @@ char *demonology_demon_field_info() return buf; } -bool_ *demonology_doom_shield() +bool_ *demonology_doom_shield(int item) { set_shield(randint(10) + 20 + get_level_s(DOOM_SHIELD, 100), -300 + get_level_s(DOOM_SHIELD, 100), @@ -638,7 +638,7 @@ char *demonology_doom_shield_info() return buf; } -bool_ *demonology_unholy_word() +bool_ *demonology_unholy_word(int item) { int x, y; cave_type *c_ptr = NULL; @@ -704,7 +704,7 @@ char *demonology_unholy_word_info() return buf; } -bool_ *demonology_demon_cloak() +bool_ *demonology_demon_cloak(int item) { set_tim_reflect(randint(5) + 5 + get_level(DEMON_CLOAK, 15, 0)); return CAST; @@ -719,7 +719,7 @@ char *demonology_demon_cloak_info() return buf; } -bool_ *demonology_summon_demon() +bool_ *demonology_summon_demon(int item) { int type, level, minlevel; @@ -756,7 +756,7 @@ char *demonology_summon_demon_info() return buf; } -bool_ *demonology_discharge_minion() +bool_ *demonology_discharge_minion(int item) { cave_type *c_ptr; int x, y; @@ -809,7 +809,7 @@ char *demonology_discharge_minion_info() return buf; } -bool_ *demonology_control_demon() +bool_ *demonology_control_demon(int item) { int dir; if (!get_aim_dir(&dir)) @@ -830,7 +830,7 @@ char *demonology_control_demon_info() return buf; } -bool_ *divination_greater_identify() +bool_ *divination_greater_identify(int item) { if (get_check("Cast on yourself?")) { @@ -848,7 +848,7 @@ char *divination_greater_identify_info() return ""; } -bool_ *divination_identify() +bool_ *divination_identify(int item) { if (get_level_s(IDENTIFY, 50) >= 27) { @@ -889,7 +889,7 @@ char *divination_identify_info() } } -bool_ *divination_vision() +bool_ *divination_vision(int item) { if (get_level_s(VISION, 50) >= 25) { @@ -908,7 +908,7 @@ char *divination_vision_info() return ""; } -bool_ *divination_sense_hidden() +bool_ *divination_sense_hidden(int item) { detect_traps(15 + get_level(SENSEHIDDEN, 40, 0)); if (get_level_s(SENSEHIDDEN, 50) >= 15) @@ -939,7 +939,7 @@ char *divination_sense_hidden_info() return buf; } -bool_ *divination_reveal_ways() +bool_ *divination_reveal_ways(int item) { detect_doors(10 + get_level(REVEALWAYS, 40, 0)); detect_stairs(10 + get_level(REVEALWAYS, 40, 0)); @@ -955,7 +955,7 @@ char *divination_reveal_ways_info() return buf; } -bool_ *divination_sense_monsters() +bool_ *divination_sense_monsters(int item) { detect_monsters_normal(10 + get_level(SENSEMONSTERS, 40, 0)); if (get_level_s(SENSEMONSTERS, 50) >= 30) @@ -986,7 +986,7 @@ char *divination_sense_monsters_info() return buf; } -bool_ *earth_stone_skin() +bool_ *earth_stone_skin(int item) { int type; @@ -1028,7 +1028,7 @@ char *earth_stone_skin_info() return buf; } -bool_ *earth_dig() +bool_ *earth_dig(int item) { int dir; if (!get_aim_dir(&dir)) @@ -1045,7 +1045,7 @@ char *earth_dig_info() return ""; } -bool_ *earth_stone_prison() +bool_ *earth_stone_prison(int item) { int x,y; @@ -1071,7 +1071,7 @@ char *earth_stone_prison_info() return ""; } -bool_ *earth_strike() +bool_ *earth_strike(int item) { int dir, dmg; @@ -1110,7 +1110,7 @@ char *earth_strike_info() return buf; } -bool_ *earth_shake() +bool_ *earth_shake(int item) { int x,y; @@ -1137,7 +1137,7 @@ char *earth_shake_info() return buf; } -bool_ *eru_see_the_music() +bool_ *eru_see_the_music(int item) { set_tim_invis(randint(20) + 10 + get_level_s(ERU_SEE, 100)); @@ -1167,7 +1167,7 @@ char *eru_see_the_music_info() return buf; } -bool_ *eru_listen_to_the_music() +bool_ *eru_listen_to_the_music(int item) { if (get_level_s(ERU_LISTEN, 50) >= 30) { @@ -1190,7 +1190,7 @@ char *eru_listen_to_the_music_info() return ""; } -bool_ *eru_know_the_music() +bool_ *eru_know_the_music(int item) { if (get_level_s(ERU_UNDERSTAND, 50) >= 10) { @@ -1208,7 +1208,7 @@ char *eru_know_the_music_info() return ""; } -bool_ *eru_lay_of_protection() +bool_ *eru_lay_of_protection(int item) { fire_ball(GF_MAKE_GLYPH, 0, 1, 1 + get_level(ERU_PROT, 2, 0)); return CAST; @@ -1223,7 +1223,7 @@ char *eru_lay_of_protection_info() return buf; } -bool_ *fire_globe_of_light() +bool_ *fire_globe_of_light(int item) { if (get_level_s(GLOBELIGHT, 50) >= 3) { @@ -1263,7 +1263,7 @@ char *fire_globe_of_light_info() return buf; } -bool_ *fire_fireflash() +bool_ *fire_fireflash(int item) { int dir; int type = GF_FIRE; @@ -1294,7 +1294,7 @@ char *fire_fireflash_info() return buf; } -bool_ *fire_fiery_shield() +bool_ *fire_fiery_shield(int item) { int type = SHIELD_FIRE; if (get_level_s(FIERYAURA, 50) >= 8) @@ -1321,7 +1321,7 @@ char *fire_fiery_shield_info() return buf; } -bool_ *fire_firewall() +bool_ *fire_firewall(int item) { int dir; int type = GF_FIRE; @@ -1358,7 +1358,7 @@ bool_ item_tester_hook_fire_golem(object_type *o_ptr) (o_ptr->sval == SV_LITE_LANTERN))); } -bool_ *fire_golem() +bool_ *fire_golem(int ignored) { int item, x, y, m_idx; @@ -1407,7 +1407,7 @@ char *fire_golem_info() return buf; } -bool_ *geomancy_call_the_elements() +bool_ *geomancy_call_the_elements(int item) { int dir = 0; @@ -1436,7 +1436,7 @@ char *geomancy_call_the_elements_info() return buf; } -bool_ *geomancy_channel_elements() +bool_ *geomancy_channel_elements(int item) { channel_the_elements(p_ptr->py, p_ptr->px, get_level_s(CHANNEL_ELEMENTS, 50)); return CAST; @@ -1469,7 +1469,7 @@ static eff_type *geomancy_find_effect(eff_type effs[], int feat) return NULL; } -bool_ *geomancy_elemental_wave() +bool_ *geomancy_elemental_wave(int item) { int dir = 0, y = 0, x = 0; eff_type *eff_ptr = NULL; @@ -1538,7 +1538,7 @@ char *geomancy_elemental_wave_info() return ""; } -bool_ *geomancy_vaporize() +bool_ *geomancy_vaporize(int item) { eff_type *eff_ptr = NULL; eff_type t[] = { @@ -1599,7 +1599,7 @@ bool_ geomancy_vaporize_depends() return get_skill(SKILL_AIR) >= 4; } -bool_ *geomancy_geolysis() +bool_ *geomancy_geolysis(int item) { int dir = 0; @@ -1628,7 +1628,7 @@ bool_ geomancy_geolysis_depends() return get_skill(SKILL_EARTH) >= 7; } -bool_ *geomancy_dripping_tread() +bool_ *geomancy_dripping_tread(int item) { if (p_ptr->dripping_tread == 0) { @@ -1658,7 +1658,7 @@ bool_ geomancy_dripping_tread_depends() return get_skill(SKILL_WATER) >= 10; } -bool_ *geomancy_grow_barrier() +bool_ *geomancy_grow_barrier(int item) { int dir = 0; @@ -1714,7 +1714,7 @@ int geomancy_count_elements(cptr *elements) return i; } -bool_ *geomancy_elemental_minion() +bool_ *geomancy_elemental_minion(int item) { int dir = 0; int x = 0, y = 0; @@ -1824,7 +1824,7 @@ static void get_manathrust_dam(s16b *num, s16b *sides) *sides = 1 + get_level_s(MANATHRUST, 20); } -bool_ *mana_manathrust() +bool_ *mana_manathrust(int item) { int dir; s16b num = 0; @@ -1854,7 +1854,7 @@ char *mana_manathrust_info() return buf; } -bool_ *mana_remove_curses() +bool_ *mana_remove_curses(int item) { bool_ done = FALSE; @@ -1880,7 +1880,7 @@ char *mana_remove_curses_info() return ""; } -bool_ *mana_elemental_shield() +bool_ *mana_elemental_shield(int item) { bool_ *res = NO_CAST; @@ -1920,7 +1920,7 @@ char *mana_elemental_shield_info() return buf; } -bool_ *mana_disruption_shield() +bool_ *mana_disruption_shield(int item) { if (get_level_s(MANASHIELD, 50) >= 5) { @@ -1948,7 +1948,7 @@ char *mana_disruption_shield_info() return buf; } -bool_ *manwe_wind_shield() +bool_ *manwe_wind_shield(int item) { s32b dur = get_level_s(MANWE_SHIELD, 50) + 10 + randint(20); @@ -1998,7 +1998,7 @@ char *manwe_wind_shield_info() return buf; } -bool_ *manwe_avatar() +bool_ *manwe_avatar(int item) { s16b mimic_idx = resolve_mimic_name("Maia"); assert(mimic_idx >= 0); @@ -2018,7 +2018,7 @@ char *manwe_avatar_info() return buf; } -bool_ *manwe_blessing() +bool_ *manwe_blessing(int item) { s32b dur = get_level_s(MANWE_BLESS, 70) + 30 + randint(40); @@ -2051,7 +2051,7 @@ char *manwe_blessing_info() return buf; } -bool_ *manwe_call() +bool_ *manwe_call(int item) { int y = 0, x = 0, m_idx = -1, r_idx = -1; @@ -2170,7 +2170,7 @@ void do_melkor_curse(int m_idx) m_ptr->csleep = 0; } -bool_ *melkor_curse() +bool_ *melkor_curse(int item) { int dir = 0; @@ -2196,7 +2196,7 @@ char *melkor_curse_info() return ""; } -bool_ *melkor_corpse_explosion() +bool_ *melkor_corpse_explosion(int item) { fire_ball(GF_CORPSE_EXPL, 0, @@ -2214,7 +2214,7 @@ char *melkor_corpse_explosion_info() return buf; } -bool_ *melkor_mind_steal() +bool_ *melkor_mind_steal(int item) { int dir = 0; @@ -2264,7 +2264,7 @@ char *melkor_mind_steal_info() return buf; } -bool_ *meta_recharge() +bool_ *meta_recharge(int item) { recharge(60 + get_level_s(RECHARGE, 140)); return CAST; @@ -2289,7 +2289,7 @@ static int get_spellbinder_max() return i; } -bool_ *meta_spellbinder() +bool_ *meta_spellbinder(int item) { if (p_ptr->spellbinder_num != 0) { @@ -2358,7 +2358,7 @@ bool_ *meta_spellbinder() i = p_ptr->spellbinder_num; while (i > 0) { - s32b s = get_school_spell("bind", "is_ok_spell", 0); + s32b s = get_school_spell("bind", 0); if (s == -1) { p_ptr->spellbinder_trigger = 0; @@ -2392,7 +2392,7 @@ char *meta_spellbinder_info() return buf; } -bool_ *meta_disperse_magic() +bool_ *meta_disperse_magic(int item) { set_blind(0); set_lite(0); @@ -2431,7 +2431,7 @@ char *meta_disperse_magic_info() return ""; } -bool_ *meta_tracker() +bool_ *meta_tracker(int item) { if ((last_teleportation_y < 0) || (last_teleportation_x < 0)) @@ -2464,21 +2464,10 @@ void meta_inertia_control_hook_birth_objects() stop_inertia_controlled_spell(); } -static bool_ lua_var_is_nil(cptr var) -{ - char buf[128]; - sprintf(buf, "return (%s == nil)", var); - return exec_lua(buf); -} - -bool_ *meta_inertia_control() +bool_ *meta_inertia_control(int item) { s32b s; - char prefix[128]; - char inertia_0_var[128]; - char inertia_1_var[128]; - int inertia_0; - int inertia_1; + spell_type *spell; if (p_ptr->inertia_controlled_spell != -1) { @@ -2487,37 +2476,33 @@ bool_ *meta_inertia_control() return NO_CAST; } - s = get_school_spell("control", "is_ok_spell", 0); + s = get_school_spell("control", 0); if (s == -1) { stop_inertia_controlled_spell(); return NO_CAST; } - sprintf(prefix, "__tmp_spells[" FMTs32b "].inertia", s); - sprintf(inertia_0_var, "__tmp_spells[" FMTs32b "].inertia[1]", s); - sprintf(inertia_1_var, "__tmp_spells[" FMTs32b "].inertia[2]", s); + spell = spell_at(s); - if (lua_var_is_nil(prefix)) + if ((spell->inertia_difficulty < 0) || + (spell->inertia_delay < 0)) { msg_print("This spell inertia flow can not be controlled."); stop_inertia_controlled_spell(); return NO_CAST; } - inertia_0 = get_lua_int(inertia_0_var); - if (inertia_0 > get_level_s(INERTIA_CONTROL, 10)) + if (spell->inertia_difficulty > get_level_s(INERTIA_CONTROL, 10)) { - msg_format("This spell inertia flow(%d) is too strong to be controlled by your current spell.", inertia_0); + msg_format("This spell inertia flow(%d) is too strong to be controlled by your current spell.", spell->inertia_difficulty); stop_inertia_controlled_spell(); return NO_CAST; } - inertia_1 = get_lua_int(inertia_1_var); - p_ptr->inertia_controlled_spell = s; TIMER_INERTIA_CONTROL->enabled = TRUE; - TIMER_INERTIA_CONTROL->delay = inertia_1; + TIMER_INERTIA_CONTROL->delay = spell->inertia_delay; TIMER_INERTIA_CONTROL->countdown = TIMER_INERTIA_CONTROL->delay; p_ptr->update |= PU_MANA; msg_format("Inertia flow controlling spell %s.", school_spells[s].name); @@ -2568,7 +2553,7 @@ static int mind_charm_power() return 10 + get_level_s(CHARM, 150); } -bool_ *mind_charm() +bool_ *mind_charm(int item) { int pwr = mind_charm_power(); int level = get_level_s(CHARM, 50); @@ -2612,7 +2597,7 @@ static int mind_confuse_power() return 10 + get_level_s(CONFUSE, 150); } -bool_ *mind_confuse() +bool_ *mind_confuse(int item) { int pwr = mind_confuse_power(); int level = get_level_s(CONFUSE, 50); @@ -2666,7 +2651,7 @@ static int mind_armor_of_fear_power_dice() return 5 + get_level_s(ARMOROFFEAR, 20); } -bool_ *mind_armor_of_fear() +bool_ *mind_armor_of_fear(int item) { set_shield(randint(10) + mind_armor_of_fear_base_duration(), 10, @@ -2692,7 +2677,7 @@ static int mind_stun_power() return 10 + get_level_s(STUN, 150); } -bool_ *mind_stun() +bool_ *mind_stun(int item) { int dir; @@ -2722,7 +2707,7 @@ char *mind_stun_info() return buf; } -bool_ *tempo_magelock() +bool_ *tempo_magelock(int item) { if (get_level_s(MAGELOCK, 50) >= 30) { @@ -2773,7 +2758,7 @@ static s32b tempo_slow_monster_power() return 40 + get_level_s(SLOWMONSTER, 160); } -bool_ *tempo_slow_monster() +bool_ *tempo_slow_monster(int item) { int dir; s32b pwr; @@ -2822,7 +2807,7 @@ static s32b tempo_essence_of_speed_bonus() return 5 + get_level_s(ESSENCESPEED, 20); } -bool_ *tempo_essence_of_speed() +bool_ *tempo_essence_of_speed(int item) { if (p_ptr->fast == 0) { @@ -2847,7 +2832,7 @@ static s32b tempo_banishment_power() return 40 + get_level_s(BANISHMENT, 160); } -bool_ *tempo_banishment() +bool_ *tempo_banishment(int item) { s32b pwr = tempo_banishment_power(); @@ -2869,7 +2854,7 @@ char *tempo_banishment_info() return buf; } -bool_ *tulkas_divine_aim() +bool_ *tulkas_divine_aim(int item) { s32b dur = get_level_s(TULKAS_AIM, 50) + randint(10); @@ -2891,7 +2876,7 @@ char *tulkas_divine_aim_info() return buf; } -bool_ *tulkas_wave_of_power() +bool_ *tulkas_wave_of_power(int item) { int dir; @@ -2913,7 +2898,7 @@ char *tulkas_wave_of_power_info() return buf; } -bool_ *tulkas_whirlwind() +bool_ *tulkas_whirlwind(int item) { fire_ball(GF_ATTACK, 0, 1, 1); return CAST; @@ -2942,19 +2927,15 @@ int udun_in_book(s32b sval, s32b pval) spell_idx != NULL; spell_idx = sglib_spell_idx_list_it_next(&it)) { - int j; - int n; - char buf[128]; - - sprintf(buf, "__spell_school[" FMTs32b "+1]", spell_idx->i); - n = get_lua_list_size(buf); + spell_type *spell = spell_at(spell_idx->i); + school_idx *school_idx = NULL; + struct sglib_school_idx_iterator sit; - for (j = 0; j < n; j++) + for (school_idx = sglib_school_idx_it_init(&sit, spell->schools); + school_idx != NULL; + school_idx = sglib_school_idx_it_next(&sit)) { - int sch; - sprintf(buf, "__spell_school[" FMTs32b "][%d+1]", spell_idx->i, j); - sch = get_lua_int(buf); - + int sch = school_idx->i; if ((sch == SCHOOL_UDUN) || (sch == SCHOOL_MELKOR)) { @@ -2983,11 +2964,10 @@ int levels_in_book(s32b sval, s32b pval) spell_idx != NULL; spell_idx = sglib_spell_idx_list_it_next(&it)) { - char buf[128]; s32b s = spell_idx->i; + spell_type *spell = spell_at(s); - sprintf(buf, "__tmp_spells[" FMTs32b "].level", s); - levels += get_lua_int(buf); + levels += spell->skill_level; } return levels; @@ -3000,7 +2980,7 @@ static bool_ udun_object_is_drainable(object_type *o_ptr) (o_ptr->tval == TV_STAFF)); } -bool_ *udun_drain() +bool_ *udun_drain(int ignored) { int item; object_type *o_ptr = NULL; @@ -3062,7 +3042,7 @@ char *udun_drain_info() return ""; } -bool_ *udun_genocide() +bool_ *udun_genocide(int item) { if (get_level_s(GENOCIDE, 50) < 10) { @@ -3093,7 +3073,7 @@ static int udun_wraithform_base_duration() return 20 + get_level_s(WRAITHFORM, 40); } -bool_ *udun_wraithform() +bool_ *udun_wraithform(int item) { set_shadow(randint(30) + udun_wraithform_base_duration()); return CAST; @@ -3113,7 +3093,7 @@ static int udun_flame_of_udun_base_duration() return 5 + get_level_s(FLAMEOFUDUN, 30); } -bool_ *udun_flame_of_udun() +bool_ *udun_flame_of_udun(int item) { set_mimic(randint(15) + udun_flame_of_udun_base_duration(), resolve_mimic_name("Balrog"), @@ -3140,7 +3120,7 @@ static int tidal_wave_duration() return 6 + get_level_s(TIDALWAVE, 10); } -bool_ *water_tidal_wave() +bool_ *water_tidal_wave(int item) { fire_wave(GF_WAVE, 0, @@ -3176,7 +3156,7 @@ static int water_ice_storm_duration() return 20 + get_level_s(ICESTORM, 70); } -bool_ *water_ice_storm() +bool_ *water_ice_storm(int item) { int type = GF_COLD; @@ -3211,7 +3191,7 @@ static int water_ent_potion_base_duration() return 25 + get_level_s(ENTPOTION, 40);; } -bool_ *water_ent_potion() +bool_ *water_ent_potion(int item) { set_food(PY_FOOD_MAX - 1); msg_print("The Ent's Potion fills your stomach."); @@ -3259,7 +3239,7 @@ static int water_vapor_duration() return 5; } -bool_ *water_vapor() +bool_ *water_vapor(int item) { fire_cloud(GF_WATER, 0, @@ -3289,7 +3269,7 @@ static void get_geyser_damage(int *dice, int *sides) *sides = 3 + get_level_s(GEYSER, 35); } -bool_ *water_geyser() +bool_ *water_geyser(int item) { int dir, dice, sides; @@ -3330,7 +3310,7 @@ static int charm_animal_radius() return get_level_s(YAVANNA_CHARM_ANIMAL, 2); } -bool_ *yavanna_charm_animal() +bool_ *yavanna_charm_animal(int item) { int dir; @@ -3361,7 +3341,7 @@ static int yavanna_grow_grass_radius() return get_level_s(YAVANNA_GROW_GRASS, 4); } -bool_ *yavanna_grow_grass() +bool_ *yavanna_grow_grass(int item) { grow_grass(yavanna_grow_grass_radius()); return CAST; @@ -3391,7 +3371,7 @@ static int tree_roots_damage() return 10 + get_level_s(YAVANNA_TREE_ROOTS, 20); } -bool_ *yavanna_tree_roots() +bool_ *yavanna_tree_roots(int item) { set_roots(tree_roots_duration(), tree_roots_ac(), @@ -3420,7 +3400,7 @@ static int water_bite_damage() return 10 + get_level_s(YAVANNA_WATER_BITE, 50); } -bool_ *yavanna_water_bite() +bool_ *yavanna_water_bite(int item) { int rad = 0; @@ -3452,7 +3432,7 @@ static int uproot_mlevel() return 30 + get_level_s(YAVANNA_UPROOT, 70); } -bool_ *yavanna_uproot() +bool_ *yavanna_uproot(int item) { int dir, x, y; cave_type *c_ptr; @@ -3510,7 +3490,7 @@ static int nature_grow_trees_radius() return 2 + get_level_s(GROWTREE, 7); } -bool_ *nature_grow_trees() +bool_ *nature_grow_trees(int item) { grow_trees(nature_grow_trees_radius()); return CAST; @@ -3535,7 +3515,7 @@ static int nature_healing_hp() return p_ptr->mhp * nature_healing_percentage() / 100; } -bool_ *nature_healing() +bool_ *nature_healing(int item) { hp_player(nature_healing_hp()); return CAST; @@ -3551,7 +3531,7 @@ char *nature_healing_info() return buf; } -bool_ *nature_recovery() +bool_ *nature_recovery(int item) { set_poisoned(p_ptr->poisoned / 2); if (get_level_s(RECOVERY, 50) >= 5) @@ -3590,7 +3570,7 @@ static int regeneration_power() return 300 + get_level_s(REGENERATION, 700); } -bool_ *nature_regeneration() +bool_ *nature_regeneration(int item) { if (p_ptr->tim_regen == 0) { @@ -3616,7 +3596,7 @@ static int summon_animal_level() return 25 + get_level_s(SUMMONANNIMAL, 50); } -bool_ *nature_summon_animal() +bool_ *nature_summon_animal(int item) { summon_specific_level = summon_animal_level(); summon_specific_friendly(p_ptr->py, @@ -3636,7 +3616,7 @@ char *nature_summon_animal_info() return buf; } -bool_ *nature_grow_athelas() +bool_ *nature_grow_athelas(int item) { if (p_ptr->black_breath) { @@ -3657,7 +3637,7 @@ static int device_heal_monster_hp() return 20 + get_level_s(DEVICE_HEAL_MONSTER, 380); } -bool_ *device_heal_monster() +bool_ *device_heal_monster(int item) { int dir; @@ -3679,7 +3659,7 @@ char *device_heal_monster_info() return buf; } -bool_ *device_haste_monster() +bool_ *device_haste_monster(int item) { int dir; @@ -3697,7 +3677,7 @@ char *device_haste_monster_info() return "speed +10"; } -bool_ *device_wish() +bool_ *device_wish(int item) { make_wish(); return CAST; @@ -3708,7 +3688,7 @@ char *device_wish_info() return ""; } -bool_ *device_summon_monster() +bool_ *device_summon_monster(int item) { int i; for (i = 0; i < 4 + get_level_s(DEVICE_SUMMON, 30); i++) @@ -3728,7 +3708,7 @@ static int device_mana_pct() return 20 + get_level_s(DEVICE_MANA, 50); } -bool_ *device_mana() +bool_ *device_mana(int item) { increase_mana((p_ptr->msp * device_mana_pct()) / 100); return CAST; @@ -3743,7 +3723,7 @@ char *device_mana_info() return buf; } -bool_ *device_nothing() +bool_ *device_nothing(int item) { return CAST; } @@ -3753,7 +3733,7 @@ char *device_nothing_info() return ""; } -bool_ *device_lebohaum() +bool_ *device_lebohaum(int item) { msg_print("You hear a little song in your head in some unknown tongue:"); msg_print("'Avec le casque Lebohaum y a jamais d'anicroches, je parcours les dongeons,"); @@ -3767,7 +3747,7 @@ char *device_lebohaum_info() return ""; } -bool_ *device_maggot() +bool_ *device_maggot(int item) { int dir; @@ -3790,7 +3770,7 @@ static int holy_fire_damage() return 50 + get_level_s(DEVICE_HOLY_FIRE, 300); } -bool_ *device_holy_fire() +bool_ *device_holy_fire(int item) { project_hack(GF_HOLY_FIRE, holy_fire_damage()); return CAST; @@ -3892,7 +3872,7 @@ char *device_eternal_flame_info() return ""; } -bool_ *device_durandil() +bool_ *device_durandil(int item) { msg_print("You hear a little song in your head in some unknown tongue:"); msg_print("'Les epees Durandils sont forgees dans les mines par des nains."); @@ -3914,7 +3894,7 @@ char *device_durandil_info() return ""; } -bool_ *device_thunderlords() +bool_ *device_thunderlords(int item) { switch (game_module_idx) { @@ -3957,7 +3937,7 @@ char *device_thunderlords_info() return ""; } -bool_ *device_radagast() +bool_ *device_radagast(int item) { cmsg_print(TERM_GREEN, "The staff's power cleanses you completely!"); remove_all_curse(); @@ -3996,7 +3976,7 @@ char *device_radagast_info() return ""; } -bool_ *device_valaroma() +bool_ *device_valaroma(int item) { int power = 5 * p_ptr->lev; banish_evil(power); @@ -4013,7 +3993,7 @@ void static start_lasting_spell(int spl) p_ptr->music_extra = -spl; } -bool_ *music_stop_singing_spell() +bool_ *music_stop_singing_spell(int item) { start_lasting_spell(0); return CAST; @@ -4035,7 +4015,7 @@ int music_holding_pattern_lasting() return get_mana(MUSIC_HOLD); } -bool_ *music_holding_pattern_spell() +bool_ *music_holding_pattern_spell(int item) { start_lasting_spell(MUSIC_HOLD); return CAST; @@ -4061,7 +4041,7 @@ int music_illusion_pattern_lasting() return get_mana(MUSIC_CONF); } -bool_ *music_illusion_pattern_spell() +bool_ *music_illusion_pattern_spell(int item) { start_lasting_spell(MUSIC_CONF); return CAST; @@ -4087,7 +4067,7 @@ int music_stun_pattern_lasting() return get_mana(MUSIC_STUN); } -bool_ *music_stun_pattern_spell() +bool_ *music_stun_pattern_spell(int item) { start_lasting_spell(MUSIC_STUN); return CAST; @@ -4108,7 +4088,7 @@ int music_song_of_the_sun_lasting() return 1; } -bool_ *music_song_of_the_sun_spell() +bool_ *music_song_of_the_sun_spell(int item) { start_lasting_spell(MUSIC_LITE); return CAST; @@ -4130,7 +4110,7 @@ int music_flow_of_life_lasting() return get_mana(MUSIC_HEAL); } -bool_ *music_flow_of_life_spell() +bool_ *music_flow_of_life_spell(int item) { start_lasting_spell(MUSIC_HEAL); return CAST; @@ -4163,7 +4143,7 @@ int music_heroic_ballad_lasting() return get_mana(MUSIC_HERO); } -bool_ *music_heroic_ballad_spell() +bool_ *music_heroic_ballad_spell(int item) { start_lasting_spell(MUSIC_HERO); return CAST; @@ -4184,7 +4164,7 @@ int music_hobbit_melodies_lasting() return get_mana(MUSIC_TIME); } -bool_ *music_hobbit_melodies_spell() +bool_ *music_hobbit_melodies_spell(int item) { start_lasting_spell(MUSIC_TIME); return CAST; @@ -4217,7 +4197,7 @@ int music_clairaudience_lasting() return get_mana(MUSIC_MIND); } -bool_ *music_clairaudience_spell() +bool_ *music_clairaudience_spell(int item) { start_lasting_spell(MUSIC_MIND); return CAST; @@ -4239,7 +4219,7 @@ char *music_clairaudience_info() } } -bool_ *music_blow_spell() +bool_ *music_blow_spell(int item) { fire_ball(GF_SOUND, 0, @@ -4259,7 +4239,7 @@ char *music_blow_info() return buf; } -bool_ *music_gush_of_wind_spell() +bool_ *music_gush_of_wind_spell(int item) { fire_ball(GF_AWAY_ALL, 0, @@ -4278,7 +4258,7 @@ char *music_gush_of_wind_info() return buf; } -bool_ *music_horns_of_ylmir_spell() +bool_ *music_horns_of_ylmir_spell(int item) { earthquake(p_ptr->py, p_ptr->px, 2 + get_level_s(SHAKE, 10)); return CAST; @@ -4293,7 +4273,7 @@ char *music_horns_of_ylmir_info() return buf; } -bool_ *music_ambarkanta_spell() +bool_ *music_ambarkanta_spell(int item) { alter_reality(); return CAST; @@ -4304,7 +4284,7 @@ char *music_ambarkanta_info() return ""; } -bool_ *aule_firebrand_spell() +bool_ *aule_firebrand_spell(int item) { int rad = 0; int type = GF_FIRE; @@ -4362,7 +4342,7 @@ static bool_ aule_enchant_weapon_item_tester(object_type *o_ptr) } } -bool_ *aule_enchant_weapon_spell() +bool_ *aule_enchant_weapon_spell(int ignored) { s32b level = get_level_s(AULE_ENCHANT_WEAPON, 50); s16b num_h, num_d, num_p; @@ -4434,7 +4414,7 @@ bool_ aule_enchant_armor_item_tester(object_type *o_ptr) } } -bool_ *aule_enchant_armour_spell() +bool_ *aule_enchant_armour_spell(int ignored) { s32b level = get_level_s(AULE_ENCHANT_ARMOUR, 50); s16b num_h, num_d, num_a, num_p; @@ -4483,7 +4463,7 @@ char *aule_enchant_armour_info() return buf; } -bool_ *aule_child_spell() +bool_ *aule_child_spell(int item) { int y, x; s16b m_idx; @@ -4517,7 +4497,7 @@ static int tears_of_luthien_hp() return 10 * get_level_s(MANDOS_TEARS_LUTHIEN, 30); } -bool_ *mandos_tears_of_luthien_spell() +bool_ *mandos_tears_of_luthien_spell(int item) { hp_player(tears_of_luthien_hp()); set_stun(0); @@ -4535,7 +4515,7 @@ char *mandos_tears_of_luthien_info() return buf; } -bool_ *mandos_spirit_of_the_feanturi_spell() +bool_ *mandos_spirit_of_the_feanturi_spell(int item) { s32b level = get_level_s(MANDOS_SPIRIT_FEANTURI, 50); @@ -4577,7 +4557,7 @@ static int tale_of_doom_duration() return 5 + get_level_s(MANDOS_TALE_DOOM,10); } -bool_ *mandos_tale_of_doom_spell() +bool_ *mandos_tale_of_doom_spell(int item) { set_tim_precognition(tale_of_doom_duration()); return CAST; @@ -4597,7 +4577,7 @@ int call_to_the_halls_mlev() return 20 + get_level(MANDOS_CALL_HALLS, 70, 0); } -bool_ *mandos_call_to_the_halls_spell() +bool_ *mandos_call_to_the_halls_spell(int item) { #define N_SUMMONS 2 int y, x; @@ -4636,7 +4616,7 @@ static void get_belegaer_damage(int *dice, int *sides) *sides = 3 + get_level_s(ULMO_BELEGAER, 35); } -bool_ *ulmo_song_of_belegaer_spell() +bool_ *ulmo_song_of_belegaer_spell(int item) { int dir, dice, sides; @@ -4671,7 +4651,7 @@ int draught_of_ulmonan_hp() return 5 * get_level_s(ULMO_DRAUGHT_ULMONAN, 50); } -bool_ *ulmo_draught_of_ulmonan_spell() +bool_ *ulmo_draught_of_ulmonan_spell(int item) { s32b level = get_level_s(ULMO_DRAUGHT_ULMONAN, 50); @@ -4712,7 +4692,7 @@ static int call_of_the_ulumuri_mlev() return 30 + get_level(ULMO_CALL_ULUMURI, 70, 0); } -bool_ *ulmo_call_of_the_ulumuri_spell() +bool_ *ulmo_call_of_the_ulumuri_spell(int item) { #define N_SUMMONS 2 int x,y; @@ -4757,7 +4737,7 @@ static int wrath_of_ulmo_duration() return 10 + get_level_s(ULMO_WRATH, 14); } -bool_ *ulmo_wrath_of_ulmo_spell() +bool_ *ulmo_wrath_of_ulmo_spell(int item) { int dir, type = GF_WATER; @@ -4798,7 +4778,7 @@ static int light_of_valinor_radius() return 5 + get_level_s(VARDA_LIGHT_VALINOR, 6); } -bool_ *varda_light_of_valinor_spell() +bool_ *varda_light_of_valinor_spell(int item) { if (get_level_s(VARDA_LIGHT_VALINOR, 50) >= 3) { @@ -4837,7 +4817,7 @@ char *varda_light_of_valinor_info() } } -bool_ *varda_call_of_almaren_spell() +bool_ *varda_call_of_almaren_spell(int item) { int power = 5 * p_ptr->lev; if (get_level_s(VARDA_CALL_ALMAREN, 50) >= 20) @@ -4856,7 +4836,7 @@ char *varda_call_of_almaren_info() return ""; } -bool_ *varda_evenstar_spell() +bool_ *varda_evenstar_spell(int item) { wiz_lite_extra(); if (get_level_s(VARDA_EVENSTAR, 50) >= 40) @@ -4883,7 +4863,7 @@ static int star_kindler_damage() return 20 + get_level_s(VARDA_STARKINDLER, 100); } -bool_ *varda_star_kindler_spell() +bool_ *varda_star_kindler_spell(int item) { int dir, i, n = star_kindler_bursts(); diff --git a/src/spells4.c b/src/spells4.c index 900121fc..8bd63bb3 100644 --- a/src/spells4.c +++ b/src/spells4.c @@ -72,23 +72,17 @@ void school_idx_add_new(school_idx **list, s32b i) static bool_ uses_piety_to_cast(int s) { - char buf[128]; - sprintf(buf, "return check_affect(%d, \"piety\", FALSE)", s); - return exec_lua(buf); + return spell_at(s)->casting_type == USE_PIETY; } static bool_ castable_while_blind(int s) { - char buf[128]; - sprintf(buf, "return not check_affect(%d, \"blind\")", s); - return exec_lua(buf); + return spell_at(s)->castable_while_blind; } static bool_ castable_while_confused(int s) { - char buf[128]; - sprintf(buf, "return not check_affect(%d, \"confusion\")", s); - return exec_lua(buf); + return spell_at(s)->castable_while_confused; } /** Describe what type of energy the spell uses for casting */ @@ -484,22 +478,45 @@ void random_book_setup(s16b sval, s32b spell_idx) } } -static cptr spell_school_name(s32b s) +static void spell_school_name(char *buf, spell_type *spell) { - return string_exec_lua(format("return spell_school_name(%d)", s)); + school_idx *school_idx = NULL; + struct sglib_school_idx_iterator sit; + bool_ first = TRUE; + + buf[0] = '\0'; + + for (school_idx = sglib_school_idx_it_init(&sit, spell->schools); + school_idx != NULL; + school_idx = sglib_school_idx_it_next(&sit)) + { + int sch = school_idx->i; + school_type *school = grab_school_type(sch); + /* Add separator? */ + if (!first) + { + strcat(buf, "/"); + } + first = FALSE; + + /* Add school name */ + strcat(buf, school->name); + } } int print_spell(cptr label_, byte color, int y, s32b s) { s32b level; bool_ na; - cptr sch_str = spell_school_name(s); + spell_type *spell = spell_at(s); + char sch_str[128]; cptr spell_info = get_spell_info(s); cptr label = (label_ == NULL) ? "" : label_; char level_str[8] = "n/a"; char buf[128]; get_level_school(s, 50, -50, &level, &na); + spell_school_name(sch_str, spell); if (!na) { @@ -539,10 +556,10 @@ int print_book(s16b sval, s32b pval, object_type *obj) { s32b s = spell_idx->i; byte color = TERM_L_DARK; - int is_ok; + bool_ is_ok; char label[8]; - call_lua("is_ok_spell", "(d,O)", "d", s, obj, &is_ok); + is_ok = is_ok_spell(s, obj); if (is_ok) { color = (get_mana(s) > get_power(s)) ? TERM_ORANGE : TERM_L_GREEN; @@ -560,9 +577,9 @@ int print_book(s16b sval, s32b pval, object_type *obj) static bool_ call_spell_function(s32b s) { - char buf[128]; - sprintf(buf, "return (__spell_spell[" FMTs32b "]() ~= nil)", s); - return exec_lua(buf); + spell_type *spell = spell_at(s); + assert(spell->effect_func != NULL); + return (spell->effect_func(-1) != NULL); } void lua_cast_school_spell(s32b s, bool_ no_cost) @@ -669,6 +686,13 @@ void device_allocation_init(device_allocation *device_allocation, byte tval) device_allocation->next = NULL; } +device_allocation *device_allocation_new(byte tval) +{ + device_allocation *d = malloc(sizeof(device_allocation)); + device_allocation_init(d, tval); + return d; +} + int compare_device_allocation(device_allocation *a, device_allocation *b) { return SGLIB_NUMERIC_COMPARATOR(a->tval, b->tval); diff --git a/src/spells5.c b/src/spells5.c new file mode 100644 index 00000000..821d4151 --- /dev/null +++ b/src/spells5.c @@ -0,0 +1,2605 @@ +#include +#include + +typedef enum { RANDOM, NO_RANDOM } random_type; + +static void spell_inertia_init(spell_type *spell, s32b diff, s32b delay) +{ + spell->inertia_difficulty = diff; + spell->inertia_delay = delay; +} + +static void spell_init(spell_type *spell) +{ + memset(spell, 0, sizeof(spell_type)); + + spell->name = NULL; + spell->description = NULL; + spell->effect_func = NULL; + spell->info_func = NULL; + spell->lasting_func = NULL; + spell->depend_func = NULL; + + spell->device_allocation = NULL; + spell->schools = NULL; + + spell->random_type = -1; + + spell_inertia_init(spell, -1, -1); + + spell->castable_while_blind = FALSE; + spell->castable_while_confused = FALSE; +} + +static spell_type *spell_new(s32b *index, cptr id, cptr name) +{ + assert(school_spells_count < SCHOOL_SPELLS_MAX); + + spell_type *spell = &school_spells[school_spells_count]; + + spell_init(spell); + spell->name = name; + + *index = school_spells_count; + school_spells_count++; + + return spell; +} + +spell_type *spell_at(s32b index) +{ + assert(index >= 0); + assert(index < school_spells_count); + + return &school_spells[index]; +} + +int find_spell(cptr name) +{ + int i; + + for (i = 0; i < school_spells_count; i++) + { + spell_type *spell = spell_at(i); + if (streq(spell->name, name)) + { + return i; + } + } + + /* Not found */ + return -1; +} + +s16b get_random_spell(s16b random_type, int level) +{ + int tries; + + for (tries = 0; tries < 1000; tries++) + { + s16b spl = rand_int(school_spells_count); + spell_type *spell = spell_at(spl); + + if ((can_spell_random(spl) == random_type) && + (rand_int(spell->skill_level * 3) < level)) + { + return spl; + } + } + + return -1; +} + +bool_ check_spell_depends(s16b spell_idx) +{ + spell_type *spell = spell_at(spell_idx); + if (spell->depend_func != NULL) { + return spell->depend_func(); + } else { + return TRUE; + } +} + +int spell_get_school_idx(s16b spell_idx, int idx) +{ + spell_type *spell = spell_at(spell_idx); + school_idx *school_idx = NULL; + struct sglib_school_idx_iterator sit; + + if (idx < 0) + { + return -1; + } + + for (school_idx = sglib_school_idx_it_init(&sit, spell->schools); + school_idx != NULL && idx > 0; + school_idx = sglib_school_idx_it_next(&sit)) + { + /* Just counting down */ + } + + if (school_idx == NULL) + { + return -1; + } + else + { + return school_idx->i; + } +} + +static void spell_init_music(spell_type *spell, s16b minimum_pval) +{ + assert(spell != NULL); + /* Use spell points, but CHR for success/failure calculations */ + spell->casting_type = USE_SPELL_POINTS; + spell->casting_stat = A_CHR; + spell->random_type = SKILL_MUSIC; + spell->minimum_pval = minimum_pval; + /* Add school */ + school_idx_add_new(&spell->schools, SCHOOL_MUSIC); +} + +static void spell_init_mage(spell_type *spell, random_type random_type) +{ + assert(spell != NULL); + + spell->casting_type = USE_SPELL_POINTS; + spell->casting_stat = A_INT; + + switch (random_type) + { + case RANDOM: + spell->random_type = SKILL_MAGIC; + break; + case NO_RANDOM: + spell->random_type = -1; + break; + default: + /* Cannot happen */ + assert(FALSE); + } +} + +static void spell_init_priest(spell_type *spell) +{ + assert(spell != NULL); + + spell->random_type = SKILL_SPIRITUALITY; + spell->casting_type = USE_PIETY; + spell->casting_stat = A_WIS; +} + +static void spells_init_tome() +{ + { + spell_type *spell = spell_new(&DEVICE_LEBOHAUM, "DEVICE_LEBOHAUM", "Artifact Lebauhaum"); + dice_parse_checked(&spell->activation_duration, "3"); + string_list_append(&spell->description, "sing a cheerful song"); + school_idx_add_new(&spell->schools, SCHOOL_DEVICE); + range_init(&spell->mana_range, 0, 0); + spell->info_func = device_lebohaum_info; + spell->effect_func = device_lebohaum; + spell->failure_rate = 0; + spell->skill_level = 1; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&DEVICE_DURANDIL, "DEVICE_DURANDIL", "Artifact Durandil"); + dice_parse_checked(&spell->activation_duration, "3"); + string_list_append(&spell->description, "sing a cheerful song"); + school_idx_add_new(&spell->schools, SCHOOL_DEVICE); + range_init(&spell->mana_range, 0, 0); + spell->info_func = device_durandil_info; + spell->effect_func = device_durandil; + spell->failure_rate = 0; + spell->skill_level = 1; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&DEVICE_THUNDERLORDS, "DEVICE_THUNDERLORDS", "Artifact Thunderlords"); + string_list_append(&spell->description, "A thunderlord will appear to transport you quickly to the surface."); + school_idx_add_new(&spell->schools, SCHOOL_DEVICE); + range_init(&spell->mana_range, 1, 1); + spell->info_func = device_thunderlords_info; + spell->effect_func = device_thunderlords; + spell->failure_rate = 20; + spell->skill_level = 1; + spell_init_mage(spell, NO_RANDOM); + + dice_parse_checked(&spell->device_charges, "3+d3"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 999; + range_init(&device_allocation->base_level, 1, 1); + range_init(&device_allocation->max_level, 1, 1); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } +} + +static void spells_init_theme() +{ + { + spell_type *spell = spell_new(&GROW_ATHELAS, "GROW_ATHELAS", "Grow Athelas"); + string_list_append(&spell->description, "Cures the Black Breath"); + school_idx_add_new(&spell->schools, SCHOOL_NATURE); + range_init(&spell->mana_range, 60, 100); + spell->info_func = nature_grow_athelas_info; + spell->effect_func = nature_grow_athelas; + spell->failure_rate = 95; + spell->skill_level = 30; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "1+d3"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 85; + range_init(&device_allocation->base_level, 1, 5); + range_init(&device_allocation->max_level, 15, 45); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&AULE_FIREBRAND, "AULE_FIREBRAND", "Firebrand"); + string_list_append(&spell->description, "Imbues your melee weapon with fire to deal more damage"); + string_list_append(&spell->description, "At level 15 it spreads over a 1 radius zone around your target"); + string_list_append(&spell->description, "At level 30 it deals holy fire damage"); + school_idx_add_new(&spell->schools, SCHOOL_AULE); + range_init(&spell->mana_range, 10, 100); + spell->info_func = aule_firebrand_info; + spell->effect_func = aule_firebrand_spell; + spell->failure_rate = 20; + spell->skill_level = 1; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&AULE_ENCHANT_WEAPON, "AULE_ENCHANT_WEAPON", "Enchant Weapon"); + string_list_append(&spell->description, "Tries to enchant a weapon to-hit"); + string_list_append(&spell->description, "At level 5 it also enchants to-dam"); + string_list_append(&spell->description, "At level 45 it enhances the special powers of magical weapons"); + string_list_append(&spell->description, "The might of the enchantment increases with the level"); + school_idx_add_new(&spell->schools, SCHOOL_AULE); + range_init(&spell->mana_range, 100, 200); + spell->info_func = aule_enchant_weapon_info; + spell->effect_func = aule_enchant_weapon_spell; + spell->failure_rate = 20; + spell->skill_level = 10; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&AULE_ENCHANT_ARMOUR, "AULE_ENCHANT_ARMOUR", "Enchant Armour"); + string_list_append(&spell->description, "Tries to enchant a piece of armour"); + string_list_append(&spell->description, "At level 20 it also enchants to-hit and to-dam"); + string_list_append(&spell->description, "At level 40 it enhances the special powers of magical armour"); + string_list_append(&spell->description, "The might of the enchantment increases with the level"); + school_idx_add_new(&spell->schools, SCHOOL_AULE); + range_init(&spell->mana_range, 100, 200); + spell->info_func = aule_enchant_armour_info; + spell->effect_func = aule_enchant_armour_spell; + spell->failure_rate = 20; + spell->skill_level = 15; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&AULE_CHILD, "AULE_CHILD", "Child of Aule"); + string_list_append(&spell->description, "Summons a levelled Dwarven warrior to help you battle the forces"); + string_list_append(&spell->description, "of Morgoth"); + school_idx_add_new(&spell->schools, SCHOOL_AULE); + range_init(&spell->mana_range, 200, 500); + spell->info_func = aule_child_info; + spell->effect_func = aule_child_spell; + spell->failure_rate = 40; + spell->skill_level = 20; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&VARDA_LIGHT_VALINOR, "VARDA_LIGHT_VALINOR", "Light of Valinor"); + string_list_append(&spell->description, "Lights a room"); + string_list_append(&spell->description, "At level 3 it starts damaging monsters"); + string_list_append(&spell->description, "At level 15 it starts creating a more powerful kind of light"); + school_idx_add_new(&spell->schools, SCHOOL_VARDA); + range_init(&spell->mana_range, 1, 100); + spell->info_func = varda_light_of_valinor_info; + spell->effect_func = varda_light_of_valinor_spell; + spell->failure_rate = 20; + spell->skill_level = 1; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&VARDA_CALL_ALMAREN, "VARDA_CALL_ALMAREN", "Call of Almaren"); + string_list_append(&spell->description, "Banishes evil beings"); + string_list_append(&spell->description, "At level 20 it dispels evil beings"); + school_idx_add_new(&spell->schools, SCHOOL_VARDA); + range_init(&spell->mana_range, 5, 150); + spell->info_func = varda_call_of_almaren_info; + spell->effect_func = varda_call_of_almaren_spell; + spell->failure_rate = 20; + spell->skill_level = 10; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&VARDA_EVENSTAR, "VARDA_EVENSTAR", "Evenstar"); + string_list_append(&spell->description, "Maps and lights the whole level."); + string_list_append(&spell->description, "At level 40 it maps and lights the whole level,"); + string_list_append(&spell->description, "in addition to letting you know yourself better"); + string_list_append(&spell->description, "and identifying your whole pack."); + school_idx_add_new(&spell->schools, SCHOOL_VARDA); + range_init(&spell->mana_range, 20, 200); + spell->info_func = varda_evenstar_info; + spell->effect_func = varda_evenstar_spell; + spell->failure_rate = 20; + spell->skill_level = 20; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&VARDA_STARKINDLER, "VARDA_STARKINDLER", "Star Kindler"); + string_list_append(&spell->description, "Does multiple bursts of light damage."); + string_list_append(&spell->description, "The damage increases with level."); + school_idx_add_new(&spell->schools, SCHOOL_VARDA); + range_init(&spell->mana_range, 50, 250); + spell->info_func = varda_star_kindler_info; + spell->effect_func = varda_star_kindler_spell; + spell->failure_rate = 20; + spell->skill_level = 30; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&ULMO_BELEGAER, "ULMO_BELEGAER", "Song of Belegaer"); + string_list_append(&spell->description, "Channels the power of the Great Sea into your fingertips."); + string_list_append(&spell->description, "Sometimes it can blast through its first target."); + school_idx_add_new(&spell->schools, SCHOOL_ULMO); + range_init(&spell->mana_range, 1, 100); + spell->info_func = ulmo_song_of_belegaer_info; + spell->effect_func = ulmo_song_of_belegaer_spell; + spell->failure_rate = 25; + spell->skill_level = 1; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&ULMO_DRAUGHT_ULMONAN, "ULMO_DRAUGHT_ULMONAN", "Draught of Ulmonan"); + string_list_append(&spell->description, "Fills you with a draught with powerful curing effects,"); + string_list_append(&spell->description, "prepared by Ulmo himself."); + string_list_append(&spell->description, "Level 1: blindness, poison, cuts and stunning"); + string_list_append(&spell->description, "Level 10: drained STR, DEX and CON"); + string_list_append(&spell->description, "Level 20: parasites and mimicry"); + school_idx_add_new(&spell->schools, SCHOOL_ULMO); + range_init(&spell->mana_range, 25, 200); + spell->info_func = ulmo_draught_of_ulmonan_info; + spell->effect_func = ulmo_draught_of_ulmonan_spell; + spell->failure_rate = 50; + spell->skill_level = 15; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&ULMO_CALL_ULUMURI, "ULMO_CALL_ULUMURI", "Call of the Ulumuri"); + string_list_append(&spell->description, "Summons a leveled water spirit or elemental"); + string_list_append(&spell->description, "to fight for you"); + school_idx_add_new(&spell->schools, SCHOOL_ULMO); + range_init(&spell->mana_range, 50, 300); + spell->info_func = ulmo_call_of_the_ulumuri_info; + spell->effect_func = ulmo_call_of_the_ulumuri_spell; + spell->failure_rate = 75; + spell->skill_level = 20; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&ULMO_WRATH, "ULMO_WRATH", "Wrath of Ulmo"); + string_list_append(&spell->description, "Conjures up a sea storm."); + string_list_append(&spell->description, "At level 30 it turns into a more forceful storm."); + school_idx_add_new(&spell->schools, SCHOOL_ULMO); + range_init(&spell->mana_range, 100, 400); + spell->info_func = ulmo_wrath_of_ulmo_info; + spell->effect_func = ulmo_wrath_of_ulmo_spell; + spell->failure_rate = 95; + spell->skill_level = 30; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&MANDOS_TEARS_LUTHIEN, "MANDOS_TEARS_LUTHIEN", "Tears of Luthien"); + string_list_append(&spell->description, "Calls upon the spirit of Luthien to ask Mandos for healing and succour."); + school_idx_add_new(&spell->schools, SCHOOL_MANDOS); + range_init(&spell->mana_range, 10, 100); + spell->info_func = mandos_tears_of_luthien_info; + spell->effect_func = mandos_tears_of_luthien_spell; + spell->failure_rate = 25; + spell->skill_level = 5; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&MANDOS_SPIRIT_FEANTURI, "MANDOS_SPIRIT_FEANTURI", "Feanturi"); + string_list_append(&spell->description, "Channels the power of Mandos to cure fear and confusion."); + string_list_append(&spell->description, "At level 20 it restores lost INT and WIS"); + string_list_append(&spell->description, "At level 30 it cures hallucinations and restores a percentage of lost sanity"); + school_idx_add_new(&spell->schools, SCHOOL_MANDOS); + range_init(&spell->mana_range, 40, 200); + spell->info_func = mandos_spirit_of_the_feanturi_info; + spell->effect_func = mandos_spirit_of_the_feanturi_spell; + spell->failure_rate = 50; + spell->skill_level = 10; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&MANDOS_TALE_DOOM, "MANDOS_TALE_DOOM", "Tale of Doom"); + string_list_append(&spell->description, "Allows you to predict the future for a short time."); + school_idx_add_new(&spell->schools, SCHOOL_MANDOS); + range_init(&spell->mana_range, 60, 300); + spell->info_func = mandos_tale_of_doom_info; + spell->effect_func = mandos_tale_of_doom_spell; + spell->failure_rate = 75; + spell->skill_level = 25; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&MANDOS_CALL_HALLS, "MANDOS_CALL_HALLS", "Call to the Halls"); + string_list_append(&spell->description, "Summons a leveled spirit from the Halls of Mandos"); + string_list_append(&spell->description, "to fight for you."); + school_idx_add_new(&spell->schools, SCHOOL_MANDOS); + range_init(&spell->mana_range, 80, 400); + spell->info_func = mandos_call_to_the_halls_info; + spell->effect_func = mandos_call_to_the_halls_spell; + spell->failure_rate = 95; + spell->skill_level = 30; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&DEVICE_THUNDERLORDS, "DEVICE_THUNDERLORDS", "Artifact Thunderlords"); + string_list_append(&spell->description, "An Eagle of Manwe will appear to transport you quickly to the town."); + school_idx_add_new(&spell->schools, SCHOOL_DEVICE); + range_init(&spell->mana_range, 1, 1); + spell->info_func = device_thunderlords_info; + spell->effect_func = device_thunderlords; + spell->failure_rate = 20; + spell->skill_level = 1; + spell_init_mage(spell, NO_RANDOM); + + dice_parse_checked(&spell->device_charges, "5+d5"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 999; + range_init(&device_allocation->base_level, 1, 1); + range_init(&device_allocation->max_level, 1, 1); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&DEVICE_RADAGAST, "DEVICE_RADAGAST", "Artifact Radagast"); + dice_parse_checked(&spell->activation_duration, "15000"); + string_list_append(&spell->description, "purity and health"); + school_idx_add_new(&spell->schools, SCHOOL_DEVICE); + range_init(&spell->mana_range, 0, 0); + spell->info_func = device_radagast_info; + spell->effect_func = device_radagast; + spell->failure_rate = 10; + spell->skill_level = 1; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&DEVICE_VALAROMA, "DEVICE_VALAROMA", "Artifact Valaroma"); + dice_parse_checked(&spell->activation_duration, "250"); + string_list_append(&spell->description, "banish evil (level x5)"); + school_idx_add_new(&spell->schools, SCHOOL_DEVICE); + range_init(&spell->mana_range, 0, 0); + spell->info_func = device_valaroma_info; + spell->effect_func = device_valaroma; + spell->failure_rate = 25; + spell->skill_level = 1; + spell_init_mage(spell, NO_RANDOM); + } +} + +void school_spells_init() +{ + { + spell_type *spell = spell_new(&GLOBELIGHT, "GLOBELIGHT", "Globe of Light"); + string_list_append(&spell->description, "Creates a globe of pure light"); + string_list_append(&spell->description, "At level 3 it starts damaging monsters"); + string_list_append(&spell->description, "At level 15 it starts creating a more powerful kind of light"); + school_idx_add_new(&spell->schools, SCHOOL_FIRE); + range_init(&spell->mana_range, 2, 15); + spell_inertia_init(spell, 1, 40); + spell->info_func = fire_globe_of_light_info; + spell->effect_func = fire_globe_of_light; + spell->failure_rate = 10; + spell->skill_level = 1; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "10+d5"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 7; + range_init(&device_allocation->base_level, 1, 15); + range_init(&device_allocation->max_level, 10, 45); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&FIREFLASH, "FIREFLASH", "Fireflash"); + string_list_append(&spell->description, "Conjures a ball of fire to burn your foes to ashes"); + string_list_append(&spell->description, "At level 20 it turns into a ball of holy fire"); + school_idx_add_new(&spell->schools, SCHOOL_FIRE); + range_init(&spell->mana_range, 5, 70); + spell->info_func = fire_fireflash_info; + spell->effect_func = fire_fireflash; + spell->failure_rate = 35; + spell->skill_level = 10; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "5+d5"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 35; + range_init(&device_allocation->base_level, 1, 15); + range_init(&device_allocation->max_level, 15, 35); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&FIERYAURA, "FIERYAURA", "Fiery Shield"); + string_list_append(&spell->description, "Creates a shield of fierce flames around you"); + string_list_append(&spell->description, "At level 8 it turns into a greater kind of flame that can not be resisted"); + school_idx_add_new(&spell->schools, SCHOOL_FIRE); + range_init(&spell->mana_range, 20, 60); + spell_inertia_init(spell, 2, 15); + spell->info_func = fire_fiery_shield_info; + spell->effect_func = fire_fiery_shield; + spell->failure_rate = 50; + spell->skill_level = 20; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "3+d5"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 50; + range_init(&device_allocation->base_level, 1, 10); + range_init(&device_allocation->max_level, 5, 40); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&FIREWALL, "FIREWALL", "Firewall"); + string_list_append(&spell->description, "Creates a fiery wall to incinerate monsters stupid enough to attack you"); + string_list_append(&spell->description, "At level 6 it turns into a wall of hell fire"); + school_idx_add_new(&spell->schools, SCHOOL_FIRE); + range_init(&spell->mana_range, 25, 100); + spell->info_func = fire_firewall_info; + spell->effect_func = fire_firewall; + spell->failure_rate = 40; + spell->skill_level = 15; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "4+d5"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 55; + range_init(&device_allocation->base_level, 1, 10); + range_init(&device_allocation->max_level, 5, 40); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&FIREGOLEM, "FIREGOLEM", "Fire Golem"); + string_list_append(&spell->description, "Creates a fiery golem and controls it"); + string_list_append(&spell->description, "During the control the available keylist is:"); + string_list_append(&spell->description, "Movement keys: movement of the golem(depending on its speed"); + string_list_append(&spell->description, " it can move more than one square)"); + string_list_append(&spell->description, ", : pickup all items on the floor"); + string_list_append(&spell->description, "d : drop all carried items"); + string_list_append(&spell->description, "i : list all carried items"); + string_list_append(&spell->description, "m : end the possession/use golem powers"); + string_list_append(&spell->description, "Most of the other keys are disabled, you cannot interact with your"); + string_list_append(&spell->description, "real body while controlling the golem"); + string_list_append(&spell->description, "But to cast the spell you will need a lantern or a wooden torch to"); + string_list_append(&spell->description, "Create the golem from"); + school_idx_add_new(&spell->schools, SCHOOL_FIRE); + school_idx_add_new(&spell->schools, SCHOOL_MIND); + range_init(&spell->mana_range, 16, 70); + spell->info_func = fire_golem_info; + spell->effect_func = fire_golem; + spell->failure_rate = 40; + spell->skill_level = 7; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&MANATHRUST, "MANATHRUST", "Manathrust"); + string_list_append(&spell->description, "Conjures up mana into a powerful bolt"); + string_list_append(&spell->description, "The damage is irresistible and will increase with level"); + school_idx_add_new(&spell->schools, SCHOOL_MANA); + range_init(&spell->mana_range, 1, 25); + spell->info_func = mana_manathrust_info; + spell->effect_func = mana_manathrust; + spell->failure_rate = 10; + spell->skill_level = 1; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "7+d10"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 5; + range_init(&device_allocation->base_level, 1, 20); + range_init(&device_allocation->max_level, 15, 33); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&DELCURSES, "DELCURSES", "Remove Curses"); + string_list_append(&spell->description, "Remove curses of worn objects"); + string_list_append(&spell->description, "At level 20 switches to *remove curses*"); + school_idx_add_new(&spell->schools, SCHOOL_MANA); + range_init(&spell->mana_range, 20, 40); + spell_inertia_init(spell, 1, 10); + spell->info_func = mana_remove_curses_info; + spell->effect_func = mana_remove_curses; + spell->failure_rate = 30; + spell->skill_level = 10; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "3+d8"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 70; + range_init(&device_allocation->base_level, 1, 5); + range_init(&device_allocation->max_level, 15, 50); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&RESISTS, "RESISTS", "Elemental Shield"); + string_list_append(&spell->description, "Provide resistances to the four basic elements"); + school_idx_add_new(&spell->schools, SCHOOL_MANA); + range_init(&spell->mana_range, 17, 20); + spell_inertia_init(spell, 2, 25); + spell->info_func = mana_elemental_shield_info; + spell->effect_func = mana_elemental_shield; + spell->failure_rate = 40; + spell->skill_level = 20; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&MANASHIELD, "MANASHIELD", "Disruption Shield"); + string_list_append(&spell->description, "Uses mana instead of hp to take damage"); + string_list_append(&spell->description, "At level 5 switches to Globe of Invulnerability."); + string_list_append(&spell->description, "The spell breaks as soon as a melee, shooting, throwing or magical"); + string_list_append(&spell->description, "skill action is attempted, and lasts only a short time."); + school_idx_add_new(&spell->schools, SCHOOL_MANA); + range_init(&spell->mana_range, 50, 50); + spell_inertia_init(spell, 9, 10); + spell->info_func = mana_disruption_shield_info; + spell->effect_func = mana_disruption_shield; + spell->failure_rate = 90; + spell->skill_level = 45; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&TIDALWAVE, "TIDALWAVE", "Tidal Wave"); + string_list_append(&spell->description, "Summons a monstrous tidal wave that will expand and crush the"); + string_list_append(&spell->description, "monsters under its mighty waves."); + school_idx_add_new(&spell->schools, SCHOOL_WATER); + range_init(&spell->mana_range, 16, 40); + spell_inertia_init(spell, 4, 100); + spell->info_func = water_tidal_wave_info; + spell->effect_func = water_tidal_wave; + spell->failure_rate = 65; + spell->skill_level = 16; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "6+d5"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 54; + range_init(&device_allocation->base_level, 1, 10); + range_init(&device_allocation->max_level, 20, 50); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&ICESTORM, "ICESTORM", "Ice Storm"); + string_list_append(&spell->description, "Engulfs you in a storm of roaring cold that strikes your foes."); + string_list_append(&spell->description, "At level 10 it turns into shards of ice."); + school_idx_add_new(&spell->schools, SCHOOL_WATER); + range_init(&spell->mana_range, 30, 60); + spell_inertia_init(spell, 3, 40); + spell->info_func = water_ice_storm_info; + spell->effect_func = water_ice_storm; + spell->failure_rate = 80; + spell->skill_level = 22; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "3+d7"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 65; + range_init(&device_allocation->base_level, 1, 5); + range_init(&device_allocation->max_level, 25, 45); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&ENTPOTION, "ENTPOTION", "Ent's Potion"); + string_list_append(&spell->description, "Fills up your stomach."); + string_list_append(&spell->description, "At level 5 it boldens your heart."); + string_list_append(&spell->description, "At level 12 it makes you heroic."); + school_idx_add_new(&spell->schools, SCHOOL_WATER); + range_init(&spell->mana_range, 7, 15); + spell_inertia_init(spell, 1, 30); + spell->info_func = water_ent_potion_info; + spell->effect_func = water_ent_potion; + spell->failure_rate = 35; + spell->skill_level = 6; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&VAPOR, "VAPOR", "Vapor"); + string_list_append(&spell->description, "Fills the air with toxic moisture to eradicate annoying critters."); + school_idx_add_new(&spell->schools, SCHOOL_WATER); + range_init(&spell->mana_range, 2, 12); + spell_inertia_init(spell, 1, 30); + spell->info_func = water_vapor_info; + spell->effect_func = water_vapor; + spell->failure_rate = 20; + spell->skill_level = 2; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&GEYSER, "GEYSER", "Geyser"); + string_list_append(&spell->description, "Shoots a geyser of water from your fingertips."); + string_list_append(&spell->description, "Sometimes it can blast through its first target."); + school_idx_add_new(&spell->schools, SCHOOL_WATER); + range_init(&spell->mana_range, 1, 35); + spell->info_func = water_geyser_info; + spell->effect_func = water_geyser; + spell->failure_rate = 5; + spell->skill_level = 1; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&NOXIOUSCLOUD, "NOXIOUSCLOUD", "Noxious Cloud"); + string_list_append(&spell->description, "Creates a cloud of poison"); + string_list_append(&spell->description, "The cloud will persist for some turns, damaging all monsters passing by"); + string_list_append(&spell->description, "At spell level 30 it turns into a thick gas attacking all living beings"); + school_idx_add_new(&spell->schools, SCHOOL_AIR); + range_init(&spell->mana_range, 3, 30); + spell->info_func = air_noxious_cloud_info; + spell->effect_func = air_noxious_cloud; + spell->failure_rate = 20; + spell->skill_level = 3; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "5+d7"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 15; + range_init(&device_allocation->base_level, 1, 15); + range_init(&device_allocation->max_level, 25, 50); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&AIRWINGS, "AIRWINGS", "Wings of Winds"); + string_list_append(&spell->description, "Grants the power of levitation"); + string_list_append(&spell->description, "At level 16 it grants the power of controlled flight"); + school_idx_add_new(&spell->schools, SCHOOL_AIR); + school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); + range_init(&spell->mana_range, 30, 40); + spell_inertia_init(spell, 1, 10); + spell->info_func = air_wings_of_winds_info; + spell->effect_func = air_wings_of_winds; + spell->failure_rate = 60; + spell->skill_level = 22; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "7+d5"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 27; + range_init(&device_allocation->base_level, 1, 10); + range_init(&device_allocation->max_level, 20, 50); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&INVISIBILITY, "INVISIBILITY", "Invisibility"); + string_list_append(&spell->description, "Grants invisibility"); + school_idx_add_new(&spell->schools, SCHOOL_AIR); + range_init(&spell->mana_range, 10, 20); + spell_inertia_init(spell, 1, 30); + spell->info_func = air_invisibility_info; + spell->effect_func = air_invisibility; + spell->failure_rate = 50; + spell->skill_level = 16; + spell_init_mage(spell, RANDOM); + + } + + { + spell_type *spell = spell_new(&POISONBLOOD, "POISONBLOOD", "Poison Blood"); + string_list_append(&spell->description, "Grants resist poison"); + string_list_append(&spell->description, "At level 15 it provides poison branding to wielded weapon"); + school_idx_add_new(&spell->schools, SCHOOL_AIR); + range_init(&spell->mana_range, 10, 20); + spell_inertia_init(spell, 1, 35); + spell->info_func = air_poison_blood_info; + spell->effect_func = air_poison_blood; + spell->failure_rate = 30; + spell->skill_level = 12; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "10+d15"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 45; + range_init(&device_allocation->base_level, 1, 25); + range_init(&device_allocation->max_level, 35, 50); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&THUNDERSTORM, "THUNDERSTORM", "Thunderstorm"); + string_list_append(&spell->description, "Charges up the air around you with electricity"); + string_list_append(&spell->description, "Each turn it will throw a thunder bolt at a random monster in sight"); + string_list_append(&spell->description, "The thunder does 3 types of damage, one third of lightning"); + string_list_append(&spell->description, "one third of sound and one third of light"); + school_idx_add_new(&spell->schools, SCHOOL_AIR); + school_idx_add_new(&spell->schools, SCHOOL_NATURE); + range_init(&spell->mana_range, 40, 60); + spell_inertia_init(spell, 2, 15); + spell->info_func = air_thunderstorm_info; + spell->effect_func = air_thunderstorm; + spell->failure_rate = 60; + spell->skill_level = 25; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "5+d5"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 85; + range_init(&device_allocation->base_level, 1, 5); + range_init(&device_allocation->max_level, 25, 50); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&STERILIZE, "STERILIZE", "Sterilize"); + string_list_append(&spell->description, "Prevents explosive breeding for a while."); + school_idx_add_new(&spell->schools, SCHOOL_AIR); + range_init(&spell->mana_range, 10, 100); + spell->info_func = air_sterilize_info; + spell->effect_func = air_sterilize; + spell->failure_rate = 50; + spell->skill_level = 20; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "7+d5"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 20; + range_init(&device_allocation->base_level, 1, 10); + range_init(&device_allocation->max_level, 20, 50); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&STONESKIN, "STONESKIN", "Stone Skin"); + string_list_append(&spell->description, "Creates a shield of earth around you to protect you"); + string_list_append(&spell->description, "At level 25 it starts dealing damage to attackers"); + school_idx_add_new(&spell->schools, SCHOOL_EARTH); + range_init(&spell->mana_range, 1, 50); + spell_inertia_init(spell, 2, 50); + spell->info_func = earth_stone_skin_info; + spell->effect_func = earth_stone_skin; + spell->failure_rate = 10; + spell->skill_level = 1; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&DIG, "DIG", "Dig"); + string_list_append(&spell->description, "Digs a hole in a wall much faster than any shovels"); + school_idx_add_new(&spell->schools, SCHOOL_EARTH); + range_init(&spell->mana_range, 14, 14); + spell->info_func = earth_dig_info; + spell->effect_func = earth_dig; + spell->failure_rate = 20; + spell->skill_level = 12; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "15+d5"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 25; + range_init(&device_allocation->base_level, 1, 1); + range_init(&device_allocation->max_level, 1, 1); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&STONEPRISON, "STONEPRISON", "Stone Prison"); + string_list_append(&spell->description, "Creates a prison of walls around you"); + string_list_append(&spell->description, "At level 10 it allows you to target a monster"); + school_idx_add_new(&spell->schools, SCHOOL_EARTH); + range_init(&spell->mana_range, 30, 50); + spell->info_func = earth_stone_prison_info; + spell->effect_func = earth_stone_prison; + spell->failure_rate = 65; + spell->skill_level = 25; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "5+d3"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 57; + range_init(&device_allocation->base_level, 1, 3); + range_init(&device_allocation->max_level, 5, 20); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&STRIKE, "STRIKE", "Strike"); + string_list_append(&spell->description, "Creates a micro-ball of force that will push monsters backwards"); + string_list_append(&spell->description, "If the monster is caught near a wall, it'll be crushed against it"); + string_list_append(&spell->description, "At level 12 it turns into a ball of radius 1"); + school_idx_add_new(&spell->schools, SCHOOL_EARTH); + range_init(&spell->mana_range, 30, 50); + spell->info_func = earth_strike_info; + spell->effect_func = earth_strike; + spell->failure_rate = 60; + spell->skill_level = 30; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "2+d6"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 635; + range_init(&device_allocation->base_level, 1, 5); + range_init(&device_allocation->max_level, 10, 50); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&SHAKE, "SHAKE", "Shake"); + string_list_append(&spell->description, "Creates a localised earthquake"); + string_list_append(&spell->description, "At level 10 it can be targeted at any location"); + school_idx_add_new(&spell->schools, SCHOOL_EARTH); + range_init(&spell->mana_range, 25, 30); + spell_inertia_init(spell, 2, 50); + spell->info_func = earth_shake_info; + spell->effect_func = earth_shake; + spell->failure_rate = 60; + spell->skill_level = 27; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "5+d10"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 75; + range_init(&device_allocation->base_level, 1, 3); + range_init(&device_allocation->max_level, 9, 20); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&BLINK, "BLINK", "Phase Door"); + string_list_append(&spell->description, "Teleports you on a small scale range"); + string_list_append(&spell->description, "At level 30 it creates void jumpgates"); + school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); + range_init(&spell->mana_range, 1, 3); + spell_inertia_init(spell, 1, 5); + spell->info_func = convey_blink_info; + spell->effect_func = convey_blink; + spell->failure_rate = 10; + spell->skill_level = 1; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&DISARM, "DISARM", "Disarm"); + string_list_append(&spell->description, "Destroys doors and traps"); + string_list_append(&spell->description, "At level 10 it destroys doors and traps, then reveals and unlocks any secret"); + string_list_append(&spell->description, "doors"); + school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); + range_init(&spell->mana_range, 2, 4); + spell->info_func = convey_disarm_info; + spell->effect_func = convey_disarm; + spell->failure_rate = 15; + spell->skill_level = 3; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "10+d15"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 4; + range_init(&device_allocation->base_level, 1, 10); + range_init(&device_allocation->max_level, 10, 50); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&TELEPORT, "TELEPORT", "Teleportation"); + string_list_append(&spell->description, "Teleports you around the level. The casting time decreases with level"); + school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); + range_init(&spell->mana_range, 8, 14); + spell_inertia_init(spell, 1, 10); + spell->info_func = convey_teleport_info; + spell->effect_func = convey_teleport; + spell->failure_rate = 30; + spell->skill_level = 10; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "7+d7"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 50; + range_init(&device_allocation->base_level, 1, 20); + range_init(&device_allocation->max_level, 20, 50); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&TELEAWAY, "TELEAWAY", "Teleport Away"); + string_list_append(&spell->description, "Teleports a line of monsters away"); + string_list_append(&spell->description, "At level 10 it turns into a ball"); + string_list_append(&spell->description, "At level 20 it teleports all monsters in sight"); + school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); + range_init(&spell->mana_range, 15, 40); + spell->info_func = convey_teleport_away_info; + spell->effect_func = convey_teleport_away; + spell->failure_rate = 60; + spell->skill_level = 23; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "3+d5"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 75; + range_init(&device_allocation->base_level, 1, 20); + range_init(&device_allocation->max_level, 20, 50); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&RECALL, "RECALL", "Recall"); + string_list_append(&spell->description, "Cast on yourself it will recall you to the surface/dungeon."); + string_list_append(&spell->description, "Cast at a monster you will swap positions with the monster."); + string_list_append(&spell->description, "Cast at an object it will fetch the object to you."); + school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); + range_init(&spell->mana_range, 25, 25); + spell->info_func = convey_recall_info; + spell->effect_func = convey_recall; + spell->failure_rate = 60; + spell->skill_level = 30; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&PROBABILITY_TRAVEL, "PROBABILITY_TRAVEL", "Probability Travel"); + string_list_append(&spell->description, "Renders you immaterial, when you hit a wall you travel through it and"); + string_list_append(&spell->description, "instantly appear on the other side of it. You can also float up and down"); + string_list_append(&spell->description, "at will"); + school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); + range_init(&spell->mana_range, 30, 50); + spell_inertia_init(spell, 6, 40); + spell->info_func = convey_probability_travel_info; + spell->effect_func = convey_probability_travel; + spell->failure_rate = 90; + spell->skill_level = 35; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "1+d2"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 97; + range_init(&device_allocation->base_level, 1, 5); + range_init(&device_allocation->max_level, 8, 25); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&GROWTREE, "GROWTREE", "Grow Trees"); + string_list_append(&spell->description, "Makes trees grow extremely quickly around you"); + school_idx_add_new(&spell->schools, SCHOOL_NATURE); + school_idx_add_new(&spell->schools, SCHOOL_TEMPORAL); + range_init(&spell->mana_range, 6, 30); + spell_inertia_init(spell, 5, 50); + spell->info_func = nature_grow_trees_info; + spell->effect_func = nature_grow_trees; + spell->failure_rate = 35; + spell->skill_level = 6; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&HEALING, "HEALING", "Healing"); + string_list_append(&spell->description, "Heals a percent of hitpoints"); + school_idx_add_new(&spell->schools, SCHOOL_NATURE); + range_init(&spell->mana_range, 15, 50); + spell->info_func = nature_healing_info; + spell->effect_func = nature_healing; + spell->failure_rate = 45; + spell->skill_level = 10; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "2+d3"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 90; + range_init(&device_allocation->base_level, 1, 5); + range_init(&device_allocation->max_level, 20, 40); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&RECOVERY, "RECOVERY", "Recovery"); + string_list_append(&spell->description, "Reduces the length of time that you are poisoned"); + string_list_append(&spell->description, "At level 5 it cures poison and cuts"); + string_list_append(&spell->description, "At level 10 it restores drained stats"); + string_list_append(&spell->description, "At level 15 it restores lost experience"); + school_idx_add_new(&spell->schools, SCHOOL_NATURE); + range_init(&spell->mana_range, 10, 25); + spell_inertia_init(spell, 2, 100); + spell->info_func = nature_recovery_info; + spell->effect_func = nature_recovery; + spell->failure_rate = 60; + spell->skill_level = 15; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "5+d10"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 50; + range_init(&device_allocation->base_level, 1, 5); + range_init(&device_allocation->max_level, 10, 30); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(®ENERATION, "REGENERATION", "Regeneration"); + string_list_append(&spell->description, "Increases your body's regeneration rate"); + school_idx_add_new(&spell->schools, SCHOOL_NATURE); + range_init(&spell->mana_range, 30, 55); + spell_inertia_init(spell, 4, 40); + spell->info_func = nature_regeneration_info; + spell->effect_func = nature_regeneration; + spell->failure_rate = 70; + spell->skill_level = 20; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&SUMMONANNIMAL, "SUMMONANNIMAL", "Summon Animal"); + string_list_append(&spell->description, "Summons a leveled animal to your aid"); + school_idx_add_new(&spell->schools, SCHOOL_NATURE); + range_init(&spell->mana_range, 25, 50); + spell->info_func = nature_summon_animal_info; + spell->effect_func = nature_summon_animal; + spell->failure_rate = 90; + spell->skill_level = 25; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "1+d3"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 85; + range_init(&device_allocation->base_level, 1, 5); + range_init(&device_allocation->max_level, 15, 45); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&STARIDENTIFY, "STARIDENTIFY", "Greater Identify"); + string_list_append(&spell->description, "Asks for an object and fully identify it, providing the full list of powers"); + string_list_append(&spell->description, "Cast at yourself it will reveal your powers"); + school_idx_add_new(&spell->schools, SCHOOL_DIVINATION); + range_init(&spell->mana_range, 30, 30); + spell->info_func = divination_greater_identify_info; + spell->effect_func = divination_greater_identify; + spell->failure_rate = 80; + spell->skill_level = 35; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&IDENTIFY, "IDENTIFY", "Identify"); + string_list_append(&spell->description, "Asks for an object and identifies it"); + string_list_append(&spell->description, "At level 17 it identifies all objects in the inventory"); + string_list_append(&spell->description, "At level 27 it identifies all objects in the inventory and in a"); + string_list_append(&spell->description, "radius on the floor, as well as probing monsters in that radius"); + school_idx_add_new(&spell->schools, SCHOOL_DIVINATION); + range_init(&spell->mana_range, 10, 50); + spell->info_func = divination_identify_info; + spell->effect_func = divination_identify; + spell->failure_rate = 40; + spell->skill_level = 8; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "7+d10"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 45; + range_init(&device_allocation->base_level, 1, 15); + range_init(&device_allocation->max_level, 15, 40); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&VISION, "VISION", "Vision"); + string_list_append(&spell->description, "Detects the layout of the surrounding area"); + string_list_append(&spell->description, "At level 25 it maps and lights the whole level"); + school_idx_add_new(&spell->schools, SCHOOL_DIVINATION); + range_init(&spell->mana_range, 7, 55); + spell_inertia_init(spell, 2, 200); + spell->info_func = divination_vision_info; + spell->effect_func = divination_vision; + spell->failure_rate = 45; + spell->skill_level = 15; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "4+d6"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 60; + range_init(&device_allocation->base_level, 1, 5); + range_init(&device_allocation->max_level, 10, 30); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&SENSEHIDDEN, "SENSEHIDDEN", "Sense Hidden"); + string_list_append(&spell->description, "Detects the traps in a certain radius around you"); + string_list_append(&spell->description, "At level 15 it allows you to sense invisible for a while"); + school_idx_add_new(&spell->schools, SCHOOL_DIVINATION); + range_init(&spell->mana_range, 2, 10); + spell_inertia_init(spell, 1, 10); + spell->info_func = divination_sense_hidden_info; + spell->effect_func = divination_sense_hidden; + spell->failure_rate = 25; + spell->skill_level = 5; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "1+d15"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 20; + range_init(&device_allocation->base_level, 1, 15); + range_init(&device_allocation->max_level, 10, 50); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&REVEALWAYS, "REVEALWAYS", "Reveal Ways"); + string_list_append(&spell->description, "Detects the doors/stairs/ways in a certain radius around you"); + school_idx_add_new(&spell->schools, SCHOOL_DIVINATION); + range_init(&spell->mana_range, 3, 15); + spell_inertia_init(spell, 1, 10); + spell->info_func = divination_reveal_ways_info; + spell->effect_func = divination_reveal_ways; + spell->failure_rate = 20; + spell->skill_level = 9; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "6+d6"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 35; + range_init(&device_allocation->base_level, 1, 15); + range_init(&device_allocation->max_level, 25, 50); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&SENSEMONSTERS, "SENSEMONSTERS", "Sense Monsters"); + string_list_append(&spell->description, "Detects all monsters near you"); + string_list_append(&spell->description, "At level 30 it allows you to sense monster minds for a while"); + school_idx_add_new(&spell->schools, SCHOOL_DIVINATION); + range_init(&spell->mana_range, 1, 20); + spell_inertia_init(spell, 1, 10); + spell->info_func = divination_sense_monsters_info; + spell->effect_func = divination_sense_monsters; + spell->failure_rate = 10; + spell->skill_level = 1; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "5+d10"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 37; + range_init(&device_allocation->base_level, 1, 10); + range_init(&device_allocation->max_level, 15, 40); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&MAGELOCK, "MAGELOCK", "Magelock"); + string_list_append(&spell->description, "Magically locks a door"); + string_list_append(&spell->description, "At level 30 it creates a glyph of warding"); + string_list_append(&spell->description, "At level 40 the glyph can be placed anywhere in the field of vision"); + school_idx_add_new(&spell->schools, SCHOOL_TEMPORAL); + range_init(&spell->mana_range, 1, 35); + spell->info_func = tempo_magelock_info; + spell->effect_func = tempo_magelock; + spell->failure_rate = 10; + spell->skill_level = 1; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "7+d5"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 30; + range_init(&device_allocation->base_level, 1, 5); + range_init(&device_allocation->max_level, 15, 45); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&SLOWMONSTER, "SLOWMONSTER", "Slow Monster"); + string_list_append(&spell->description, "Magically slows down the passing of time around a monster"); + string_list_append(&spell->description, "At level 20 it affects a zone"); + school_idx_add_new(&spell->schools, SCHOOL_TEMPORAL); + range_init(&spell->mana_range, 10, 15); + spell->info_func = tempo_slow_monster_info; + spell->effect_func = tempo_slow_monster; + spell->failure_rate = 35; + spell->skill_level = 10; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "5+d5"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 23; + range_init(&device_allocation->base_level, 1, 15); + range_init(&device_allocation->max_level, 20, 50); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&ESSENCESPEED, "ESSENCESPEED", "Essence of Speed"); + string_list_append(&spell->description, "Magically decreases the passing of time around you, making you move faster with"); + string_list_append(&spell->description, "respect to the rest of the universe."); + school_idx_add_new(&spell->schools, SCHOOL_TEMPORAL); + range_init(&spell->mana_range, 20, 40); + spell_inertia_init(spell, 5, 20); + spell->info_func = tempo_essence_of_speed_info; + spell->effect_func = tempo_essence_of_speed; + spell->failure_rate = 50; + spell->skill_level = 15; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "3+d3"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 80; + range_init(&device_allocation->base_level, 1, 1); + range_init(&device_allocation->max_level, 10, 39); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&BANISHMENT, "BANISHMENT", "Banishment"); + string_list_append(&spell->description, "Disrupts the space/time continuum in your area and teleports all monsters away."); + string_list_append(&spell->description, "At level 15 it may also lock them in a time bubble for a while."); + school_idx_add_new(&spell->schools, SCHOOL_TEMPORAL); + school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); + range_init(&spell->mana_range, 30, 40); + spell_inertia_init(spell, 5, 50); + spell->info_func = tempo_banishment_info; + spell->effect_func = tempo_banishment; + spell->failure_rate = 95; + spell->skill_level = 30; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "1+d3"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 98; + range_init(&device_allocation->base_level, 1, 15); + range_init(&device_allocation->max_level, 10, 36); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&RECHARGE, "RECHARGE", "Recharge"); + string_list_append(&spell->description, "Taps on the ambient mana to recharge an object's power (charges or mana)"); + school_idx_add_new(&spell->schools, SCHOOL_META); + range_init(&spell->mana_range, 10, 100); + spell->info_func = meta_recharge_info; + spell->effect_func = meta_recharge; + spell->failure_rate = 20; + spell->skill_level = 5; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&SPELLBINDER, "SPELLBINDER", "Spellbinder"); + string_list_append(&spell->description, "Stores spells in a trigger."); + string_list_append(&spell->description, "When the condition is met all spells fire off at the same time"); + string_list_append(&spell->description, "This spell takes a long time to cast so you are advised to prepare it"); + string_list_append(&spell->description, "in a safe area."); + string_list_append(&spell->description, "Also it will use the mana for the Spellbinder and the mana for the"); + string_list_append(&spell->description, "selected spells"); + school_idx_add_new(&spell->schools, SCHOOL_META); + range_init(&spell->mana_range, 100, 300); + spell->info_func = meta_spellbinder_info; + spell->effect_func = meta_spellbinder; + spell->failure_rate = 85; + spell->skill_level = 20; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&DISPERSEMAGIC, "DISPERSEMAGIC", "Disperse Magic"); + string_list_append(&spell->description, "Dispels a lot of magic that can affect you, be it good or bad"); + string_list_append(&spell->description, "Level 1: blindness and light"); + string_list_append(&spell->description, "Level 5: confusion and hallucination"); + string_list_append(&spell->description, "Level 10: speed (both bad or good) and light speed"); + string_list_append(&spell->description, "Level 15: stunning, meditation, cuts"); + string_list_append(&spell->description, "Level 20: hero, super hero, bless, shields, afraid, parasites, mimicry"); + school_idx_add_new(&spell->schools, SCHOOL_META); + range_init(&spell->mana_range, 30, 60); + spell_inertia_init(spell, 1, 5); + spell->info_func = meta_disperse_magic_info; + spell->effect_func = meta_disperse_magic; + spell->failure_rate = 40; + spell->skill_level = 15; + spell->castable_while_blind = TRUE; + spell->castable_while_confused = TRUE; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "5+d5"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 25; + range_init(&device_allocation->base_level, 1, 15); + range_init(&device_allocation->max_level, 5, 40); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&TRACKER, "TRACKER", "Tracker"); + string_list_append(&spell->description, "Tracks down the last teleportation that happened on the level and teleports"); + string_list_append(&spell->description, "you to it"); + school_idx_add_new(&spell->schools, SCHOOL_META); + school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); + range_init(&spell->mana_range, 50, 50); + spell->info_func = meta_tracker_info; + spell->effect_func = meta_tracker; + spell->failure_rate = 95; + spell->skill_level = 30; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&INERTIA_CONTROL, "INERTIA_CONTROL", "Inertia Control"); + string_list_append(&spell->description, "Changes the energy flow of a spell to be continuously recasted"); + string_list_append(&spell->description, "at a given interval. The inertia controlled spell reduces your"); + string_list_append(&spell->description, "maximum mana by four times its cost."); + school_idx_add_new(&spell->schools, SCHOOL_META); + range_init(&spell->mana_range, 300, 700); + spell->info_func = meta_inertia_control_info; + spell->effect_func = meta_inertia_control; + spell->failure_rate = 95; + spell->skill_level = 37; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&CHARM, "CHARM", "Charm"); + string_list_append(&spell->description, "Tries to manipulate the mind of a monster to make it friendly"); + string_list_append(&spell->description, "At level 15 it turns into a ball"); + string_list_append(&spell->description, "At level 35 it affects all monsters in sight"); + school_idx_add_new(&spell->schools, SCHOOL_MIND); + range_init(&spell->mana_range, 1, 20); + spell->info_func = mind_charm_info; + spell->effect_func = mind_charm; + spell->failure_rate = 10; + spell->skill_level = 1; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "7+d5"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 35; + range_init(&device_allocation->base_level, 1, 15); + range_init(&device_allocation->max_level, 20, 40); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&CONFUSE, "CONFUSE", "Confuse"); + string_list_append(&spell->description, "Tries to manipulate the mind of a monster to confuse it"); + string_list_append(&spell->description, "At level 15 it turns into a ball"); + string_list_append(&spell->description, "At level 35 it affects all monsters in sight"); + school_idx_add_new(&spell->schools, SCHOOL_MIND); + range_init(&spell->mana_range, 5, 30); + spell->info_func = mind_confuse_info; + spell->effect_func = mind_confuse; + spell->failure_rate = 20; + spell->skill_level = 5; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "3+d4"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 45; + range_init(&device_allocation->base_level, 1, 5); + range_init(&device_allocation->max_level, 20, 40); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&ARMOROFFEAR, "ARMOROFFEAR", "Armor of Fear"); + string_list_append(&spell->description, "Creates a shield of pure fear around you. Any monster attempting to hit you"); + string_list_append(&spell->description, "must save or flee"); + school_idx_add_new(&spell->schools, SCHOOL_MIND); + range_init(&spell->mana_range, 10, 50); + spell_inertia_init(spell, 2, 20); + spell->info_func = mind_armor_of_fear_info; + spell->effect_func = mind_armor_of_fear; + spell->failure_rate = 35; + spell->skill_level = 10; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&STUN, "STUN", "Stun"); + string_list_append(&spell->description, "Tries to manipulate the mind of a monster to stun it"); + string_list_append(&spell->description, "At level 20 it turns into a ball"); + school_idx_add_new(&spell->schools, SCHOOL_MIND); + range_init(&spell->mana_range, 10, 90); + spell->info_func = mind_stun_info; + spell->effect_func = mind_stun; + spell->failure_rate = 45; + spell->skill_level = 15; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&DRAIN, "DRAIN", "Drain"); + string_list_append(&spell->description, "Drains the mana contained in wands, staves and rods to increase yours"); + school_idx_add_new(&spell->schools, SCHOOL_UDUN); + school_idx_add_new(&spell->schools, SCHOOL_MANA); + range_init(&spell->mana_range, 0, 0); + spell->info_func = udun_drain_info; + spell->effect_func = udun_drain; + spell->failure_rate = 20; + spell->skill_level = 1; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&GENOCIDE, "GENOCIDE", "Genocide"); + string_list_append(&spell->description, "Genocides all monsters of a race on the level"); + string_list_append(&spell->description, "At level 10 it can genocide all monsters near you"); + school_idx_add_new(&spell->schools, SCHOOL_UDUN); + school_idx_add_new(&spell->schools, SCHOOL_NATURE); + range_init(&spell->mana_range, 50, 50); + spell->info_func = udun_genocide_info; + spell->effect_func = udun_genocide; + spell->failure_rate = 90; + spell->skill_level = 25; + spell_init_mage(spell, RANDOM); + + dice_parse_checked(&spell->device_charges, "2+d2"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 85; + range_init(&device_allocation->base_level, 1, 1); + range_init(&device_allocation->max_level, 5, 15); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&WRAITHFORM, "WRAITHFORM", "Wraithform"); + string_list_append(&spell->description, "Turns you into an immaterial being"); + school_idx_add_new(&spell->schools, SCHOOL_UDUN); + school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); + range_init(&spell->mana_range, 20, 40); + spell_inertia_init(spell, 4, 30); + spell->info_func = udun_wraithform_info; + spell->effect_func = udun_wraithform; + spell->failure_rate = 95; + spell->skill_level = 30; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&FLAMEOFUDUN, "FLAMEOFUDUN", "Flame of Udun"); + string_list_append(&spell->description, "Turns you into a powerful Balrog"); + school_idx_add_new(&spell->schools, SCHOOL_UDUN); + school_idx_add_new(&spell->schools, SCHOOL_FIRE); + range_init(&spell->mana_range, 70, 100); + spell_inertia_init(spell, 7, 15); + spell->info_func = udun_flame_of_udun_info; + spell->effect_func = udun_flame_of_udun; + spell->failure_rate = 95; + spell->skill_level = 35; + spell_init_mage(spell, RANDOM); + } + + { + spell_type *spell = spell_new(&CALL_THE_ELEMENTS, "CALL_THE_ELEMENTS", "Call the Elements"); + string_list_append(&spell->description, "Randomly creates various elements around you"); + string_list_append(&spell->description, "Each type of element chance is controlled by your level"); + string_list_append(&spell->description, "in the corresponding skill"); + string_list_append(&spell->description, "At level 17 it can be targeted"); + school_idx_add_new(&spell->schools, SCHOOL_GEOMANCY); + range_init(&spell->mana_range, 2, 20); + spell->info_func = geomancy_call_the_elements_info; + spell->effect_func = geomancy_call_the_elements; + spell->failure_rate = 10; + spell->skill_level = 1; + spell->castable_while_blind = TRUE; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&CHANNEL_ELEMENTS, "CHANNEL_ELEMENTS", "Channel Elements"); + string_list_append(&spell->description, "Draws on the caster's immediate environs to form an attack or other effect."); + string_list_append(&spell->description, "Grass/Flower heals."); + string_list_append(&spell->description, "Water creates water bolt attacks."); + string_list_append(&spell->description, "Ice creates ice bolt attacks."); + string_list_append(&spell->description, "Sand creates a wall of thick, blinding, burning sand around you."); + string_list_append(&spell->description, "Lava creates fire bolt attacks."); + string_list_append(&spell->description, "Deep lava creates fire ball attacks."); + string_list_append(&spell->description, "Chasm creates darkness bolt attacks."); + string_list_append(&spell->description, "At Earth level 18, darkness becomes nether."); + string_list_append(&spell->description, "At Water level 8, water attacks become beams with a striking effect."); + string_list_append(&spell->description, "At Water level 12, ice attacks become balls of ice shards."); + string_list_append(&spell->description, "At Water level 18, water attacks push monsters back."); + string_list_append(&spell->description, "At Fire level 15, fire become hellfire."); + school_idx_add_new(&spell->schools, SCHOOL_GEOMANCY); + range_init(&spell->mana_range, 3, 30); + spell->info_func = geomancy_channel_elements_info; + spell->effect_func = geomancy_channel_elements; + spell->failure_rate = 20; + spell->skill_level = 3; + spell->castable_while_blind = TRUE; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&ELEMENTAL_WAVE, "ELEMENTAL_WAVE", "Elemental Wave"); + string_list_append(&spell->description, "Draws on an adjacent special square to project a slow-moving"); + string_list_append(&spell->description, "wave of that element in that direction"); + string_list_append(&spell->description, "Abyss squares cannot be channeled into a wave."); + school_idx_add_new(&spell->schools, SCHOOL_GEOMANCY); + range_init(&spell->mana_range, 15, 50); + spell->info_func = geomancy_elemental_wave_info; + spell->effect_func = geomancy_elemental_wave; + spell->failure_rate = 20; + spell->skill_level = 15; + spell->castable_while_blind = TRUE; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&VAPORIZE, "VAPORIZE", "Vaporize"); + string_list_append(&spell->description, "Draws upon your immediate environs to form a cloud of damaging vapors"); + school_idx_add_new(&spell->schools, SCHOOL_GEOMANCY); + range_init(&spell->mana_range, 3, 30); + spell->info_func = geomancy_vaporize_info; + spell->effect_func = geomancy_vaporize; + spell->depend_func = geomancy_vaporize_depends; + spell->failure_rate = 15; + spell->skill_level = 4; + spell->castable_while_blind = TRUE; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&GEOLYSIS, "GEOLYSIS", "Geolysis"); + string_list_append(&spell->description, "Burrows deeply and slightly at random into a wall,"); + string_list_append(&spell->description, "leaving behind tailings of various different sorts of walls in the passage."); + school_idx_add_new(&spell->schools, SCHOOL_GEOMANCY); + range_init(&spell->mana_range, 15, 40); + spell->info_func = geomancy_geolysis_info; + spell->effect_func = geomancy_geolysis; + spell->depend_func = geomancy_geolysis_depends; + spell->failure_rate = 15; + spell->skill_level = 7; + spell->castable_while_blind = TRUE; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&DRIPPING_TREAD, "DRIPPING_TREAD", "Dripping Tread"); + string_list_append(&spell->description, "Causes you to leave random elemental forms behind as you walk"); + school_idx_add_new(&spell->schools, SCHOOL_GEOMANCY); + range_init(&spell->mana_range, 15, 25); + spell->info_func = geomancy_dripping_tread_info; + spell->effect_func = geomancy_dripping_tread; + spell->depend_func = geomancy_dripping_tread_depends; + spell->failure_rate = 15; + spell->skill_level = 10; + spell->castable_while_blind = TRUE; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&GROW_BARRIER, "GROW_BARRIER", "Grow Barrier"); + string_list_append(&spell->description, "Creates impassable terrain (walls, trees, etc.) around you."); + string_list_append(&spell->description, "At level 20 it can be projected around another area."); + school_idx_add_new(&spell->schools, SCHOOL_GEOMANCY); + range_init(&spell->mana_range, 30, 40); + spell->info_func = geomancy_grow_barrier_info; + spell->effect_func = geomancy_grow_barrier; + spell->depend_func = geomancy_grow_barrier_depends; + spell->failure_rate = 15; + spell->skill_level = 12; + spell->castable_while_blind = TRUE; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&ELEMENTAL_MINION, "ELEMENTAL_MINION", "Elemental Minion"); + string_list_append(&spell->description, "Summons a minion from a nearby element."); + string_list_append(&spell->description, "Walls can summon Earth elmentals, Xorns and Xarens"); + string_list_append(&spell->description, "Dark Pits can summon Air elementals, Ancient blue dragons, Great Storm Wyrms"); + string_list_append(&spell->description, "and Sky Drakes"); + string_list_append(&spell->description, "Sandwalls and lava can summon Fire elementals and Ancient red dragons"); + string_list_append(&spell->description, "Icewall, and water can summon Water elementals, Water trolls and Water demons"); + school_idx_add_new(&spell->schools, SCHOOL_GEOMANCY); + range_init(&spell->mana_range, 40, 80); + spell->info_func = geomancy_elemental_minion_info; + spell->effect_func = geomancy_elemental_minion; + spell->failure_rate = 25; + spell->skill_level = 20; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&ERU_SEE, "ERU_SEE", "See the Music"); + string_list_append(&spell->description, "Allows you to 'see' the Great Music from which the world"); + string_list_append(&spell->description, "originates, allowing you to see unseen things"); + string_list_append(&spell->description, "At level 10 it allows you to see your surroundings"); + string_list_append(&spell->description, "At level 20 it allows you to cure blindness"); + string_list_append(&spell->description, "At level 30 it allows you to fully see all the level"); + school_idx_add_new(&spell->schools, SCHOOL_ERU); + range_init(&spell->mana_range, 1, 50); + spell->info_func = eru_see_the_music_info; + spell->effect_func = eru_see_the_music; + spell->failure_rate = 20; + spell->skill_level = 1; + spell_init_priest(spell); + spell->castable_while_blind = TRUE; + } + + { + spell_type *spell = spell_new(&ERU_LISTEN, "ERU_LISTEN", "Listen to the Music"); + string_list_append(&spell->description, "Allows you to listen to the Great Music from which the world"); + string_list_append(&spell->description, "originates, allowing you to understand the meaning of things"); + string_list_append(&spell->description, "At level 14 it allows you to identify all your pack"); + string_list_append(&spell->description, "At level 30 it allows you to identify all items on the level"); + school_idx_add_new(&spell->schools, SCHOOL_ERU); + range_init(&spell->mana_range, 15, 200); + spell->info_func = eru_listen_to_the_music_info; + spell->effect_func = eru_listen_to_the_music; + spell->failure_rate = 25; + spell->skill_level = 7; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&ERU_UNDERSTAND, "ERU_UNDERSTAND", "Know the Music"); + string_list_append(&spell->description, "Allows you to understand the Great Music from which the world"); + string_list_append(&spell->description, "originates, allowing you to know the full abilities of things"); + string_list_append(&spell->description, "At level 10 it allows you to *identify* all your pack"); + school_idx_add_new(&spell->schools, SCHOOL_ERU); + range_init(&spell->mana_range, 200, 600); + spell->info_func = eru_know_the_music_info; + spell->effect_func = eru_know_the_music; + spell->failure_rate = 50; + spell->skill_level = 30; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&ERU_PROT, "ERU_PROT", "Lay of Protection"); + string_list_append(&spell->description, "Creates a circle of safety around you"); + school_idx_add_new(&spell->schools, SCHOOL_ERU); + range_init(&spell->mana_range, 400, 400); + spell->info_func = eru_lay_of_protection_info; + spell->effect_func = eru_lay_of_protection; + spell->failure_rate = 80; + spell->skill_level = 35; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&MANWE_SHIELD, "MANWE_SHIELD", "Wind Shield"); + string_list_append(&spell->description, "It surrounds you with a shield of wind that deflects blows from evil monsters"); + string_list_append(&spell->description, "At level 10 it increases your armour rating"); + string_list_append(&spell->description, "At level 20 it retaliates against monsters that melee you"); + school_idx_add_new(&spell->schools, SCHOOL_MANWE); + range_init(&spell->mana_range, 100, 500); + spell->info_func = manwe_wind_shield_info; + spell->effect_func = manwe_wind_shield; + spell->failure_rate = 30; + spell->skill_level = 10; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&MANWE_AVATAR, "MANWE_AVATAR", "Avatar"); + string_list_append(&spell->description, "It turns you into a full grown Maia"); + school_idx_add_new(&spell->schools, SCHOOL_MANWE); + range_init(&spell->mana_range, 1000, 1000); + spell->info_func = manwe_avatar_info; + spell->effect_func = manwe_avatar; + spell->failure_rate = 80; + spell->skill_level = 35; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&MANWE_BLESS, "MANWE_BLESS", "Manwe's Blessing"); + string_list_append(&spell->description, "Manwe's Blessing removes your fears, blesses you and surrounds you with"); + string_list_append(&spell->description, "holy light"); + string_list_append(&spell->description, "At level 10 it also grants heroism"); + string_list_append(&spell->description, "At level 20 it also grants super heroism"); + string_list_append(&spell->description, "At level 30 it also grants holy luck and life protection"); + school_idx_add_new(&spell->schools, SCHOOL_MANWE); + range_init(&spell->mana_range, 10, 100); + spell->info_func = manwe_blessing_info; + spell->effect_func = manwe_blessing; + spell->failure_rate = 20; + spell->skill_level = 1; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&MANWE_CALL, "MANWE_CALL", "Manwe's Call"); + string_list_append(&spell->description, "Manwe's Call summons a Great Eagle to help you battle the forces"); + string_list_append(&spell->description, "of Morgoth"); + school_idx_add_new(&spell->schools, SCHOOL_MANWE); + range_init(&spell->mana_range, 200, 500); + spell->info_func = manwe_call_info; + spell->effect_func = manwe_call; + spell->failure_rate = 40; + spell->skill_level = 20; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&TULKAS_AIM, "TULKAS_AIM", "Divine Aim"); + string_list_append(&spell->description, "It makes you more accurate in combat"); + string_list_append(&spell->description, "At level 20 all your blows are critical hits"); + school_idx_add_new(&spell->schools, SCHOOL_TULKAS); + range_init(&spell->mana_range, 30, 500); + spell->info_func = tulkas_divine_aim_info; + spell->effect_func = tulkas_divine_aim; + spell->failure_rate = 20; + spell->skill_level = 1; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&TULKAS_WAVE, "TULKAS_WAVE", "Wave of Power"); + string_list_append(&spell->description, "It allows you to project a number of melee blows across a distance"); + school_idx_add_new(&spell->schools, SCHOOL_TULKAS); + range_init(&spell->mana_range, 200, 200); + spell->info_func = tulkas_wave_of_power_info; + spell->effect_func = tulkas_wave_of_power; + spell->failure_rate = 75; + spell->skill_level = 20; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&TULKAS_SPIN, "TULKAS_SPIN", "Whirlwind"); + string_list_append(&spell->description, "It allows you to spin around and hit all monsters nearby"); + school_idx_add_new(&spell->schools, SCHOOL_TULKAS); + range_init(&spell->mana_range, 100, 100); + spell->info_func = tulkas_whirlwind_info; + spell->effect_func = tulkas_whirlwind; + spell->failure_rate = 45; + spell->skill_level = 10; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&MELKOR_CURSE, "MELKOR_CURSE", "Curse"); + string_list_append(&spell->description, "It curses a monster, reducing its melee power"); + string_list_append(&spell->description, "At level 5 it can be auto-casted (with no piety cost) while fighting"); + string_list_append(&spell->description, "At level 15 it also reduces armor"); + string_list_append(&spell->description, "At level 25 it also reduces speed"); + string_list_append(&spell->description, "At level 35 it also reduces max life (but it is never fatal)"); + school_idx_add_new(&spell->schools, SCHOOL_MELKOR); + range_init(&spell->mana_range, 50, 300); + spell->info_func = melkor_curse_info; + spell->effect_func = melkor_curse; + spell->failure_rate = 20; + spell->skill_level = 1; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&MELKOR_CORPSE_EXPLOSION, "MELKOR_CORPSE_EXPLOSION", "Corpse Explosion"); + string_list_append(&spell->description, "It makes corpses in an area around you explode for a percent of their"); + string_list_append(&spell->description, "hit points as damage"); + school_idx_add_new(&spell->schools, SCHOOL_MELKOR); + range_init(&spell->mana_range, 100, 500); + spell->info_func = melkor_corpse_explosion_info; + spell->effect_func = melkor_corpse_explosion; + spell->failure_rate = 45; + spell->skill_level = 10; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&MELKOR_MIND_STEAL, "MELKOR_MIND_STEAL", "Mind Steal"); + string_list_append(&spell->description, "It allows your spirit to temporarily leave your own body, which will"); + string_list_append(&spell->description, "be vulnerable, to control one of your enemies body."); + school_idx_add_new(&spell->schools, SCHOOL_MELKOR); + range_init(&spell->mana_range, 1000, 3000); + spell->info_func = melkor_mind_steal_info; + spell->effect_func = melkor_mind_steal; + spell->failure_rate = 90; + spell->skill_level = 20; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&YAVANNA_CHARM_ANIMAL, "YAVANNA_CHARM_ANIMAL", "Charm Animal"); + string_list_append(&spell->description, "It tries to tame an animal"); + school_idx_add_new(&spell->schools, SCHOOL_YAVANNA); + range_init(&spell->mana_range, 10, 100); + spell->info_func = yavanna_charm_animal_info; + spell->effect_func = yavanna_charm_animal; + spell->failure_rate = 30; + spell->skill_level = 1; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&YAVANNA_GROW_GRASS, "YAVANNA_GROW_GRASS", "Grow Grass"); + string_list_append(&spell->description, "Create a floor of grass around you. While on grass and praying"); + string_list_append(&spell->description, "a worshipper of Yavanna will know a greater regeneration rate"); + school_idx_add_new(&spell->schools, SCHOOL_YAVANNA); + range_init(&spell->mana_range, 70, 150); + spell->info_func = yavanna_grow_grass_info; + spell->effect_func = yavanna_grow_grass; + spell->failure_rate = 65; + spell->skill_level = 10; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&YAVANNA_TREE_ROOTS, "YAVANNA_TREE_ROOTS", "Tree Roots"); + string_list_append(&spell->description, "Creates roots deep in the floor from your feet, making you more stable and able"); + string_list_append(&spell->description, "to make stronger attacks, but prevents any movement (even teleportation)."); + string_list_append(&spell->description, "It also makes you recover from stunning almost immediately."); + school_idx_add_new(&spell->schools, SCHOOL_YAVANNA); + range_init(&spell->mana_range, 50, 1000); + spell->info_func = yavanna_tree_roots_info; + spell->effect_func = yavanna_tree_roots; + spell->failure_rate = 70; + spell->skill_level = 15; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&YAVANNA_WATER_BITE, "YAVANNA_WATER_BITE", "Water Bite"); + string_list_append(&spell->description, "Imbues your melee weapon with a natural stream of water"); + string_list_append(&spell->description, "At level 25, it spreads over a 1 radius zone around your target"); + school_idx_add_new(&spell->schools, SCHOOL_YAVANNA); + range_init(&spell->mana_range, 150, 300); + spell->info_func = yavanna_water_bite_info; + spell->effect_func = yavanna_water_bite; + spell->failure_rate = 90; + spell->skill_level = 20; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&YAVANNA_UPROOT, "YAVANNA_UPROOT", "Uproot"); + string_list_append(&spell->description, "Awakes a tree to help you battle the forces of Morgoth"); + school_idx_add_new(&spell->schools, SCHOOL_YAVANNA); + range_init(&spell->mana_range, 250, 350); + spell->info_func = yavanna_uproot_info; + spell->effect_func = yavanna_uproot; + spell->failure_rate = 95; + spell->skill_level = 35; + spell_init_priest(spell); + } + + { + spell_type *spell = spell_new(&DEMON_BLADE, "DEMON_BLADE", "Demon Blade"); + string_list_append(&spell->description, "Imbues your blade with fire to deal more damage"); + string_list_append(&spell->description, "At level 30 it deals hellfire damage"); + string_list_append(&spell->description, "At level 45 it spreads over a 1 radius zone around your target"); + school_idx_add_new(&spell->schools, SCHOOL_DEMON); + range_init(&spell->mana_range, 4, 44); + spell->info_func = demonology_demon_blade_info; + spell->effect_func = demonology_demon_blade; + spell->failure_rate = 10; + spell->skill_level = 1; + spell_init_mage(spell, NO_RANDOM); + + dice_parse_checked(&spell->device_charges, "3+d7"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 75; + range_init(&device_allocation->base_level, 1, 17); + range_init(&device_allocation->max_level, 20, 40); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&DEMON_MADNESS, "DEMON_MADNESS", "Demon Madness"); + string_list_append(&spell->description, "Fire 2 balls in opposite directions of randomly chaos, confusion or charm"); + school_idx_add_new(&spell->schools, SCHOOL_DEMON); + range_init(&spell->mana_range, 5, 20); + spell->info_func = demonology_demon_madness_info; + spell->effect_func = demonology_demon_madness; + spell->failure_rate = 25; + spell->skill_level = 10; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&DEMON_FIELD, "DEMON_FIELD", "Demon Field"); + string_list_append(&spell->description, "Fires a cloud of deadly nexus over a radius of 7"); + school_idx_add_new(&spell->schools, SCHOOL_DEMON); + range_init(&spell->mana_range, 20, 60); + spell->info_func = demonology_demon_field_info; + spell->effect_func = demonology_demon_field; + spell->failure_rate = 60; + spell->skill_level = 20; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&DOOM_SHIELD, "DOOM_SHIELD", "Doom Shield"); + string_list_append(&spell->description, "Raises a mirror of pain around you, doing very high damage to your foes"); + string_list_append(&spell->description, "that dare hit you, but greatly reduces your armour class"); + school_idx_add_new(&spell->schools, SCHOOL_DEMON); + range_init(&spell->mana_range, 2, 30); + spell->info_func = demonology_doom_shield_info; + spell->effect_func = demonology_doom_shield; + spell->failure_rate = 10; + spell->skill_level = 1; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&UNHOLY_WORD, "UNHOLY_WORD", "Unholy Word"); + string_list_append(&spell->description, "Kills a pet to heal you"); + string_list_append(&spell->description, "There is a chance that the pet won't die but will turn against you"); + string_list_append(&spell->description, "it will decrease with higher level"); + school_idx_add_new(&spell->schools, SCHOOL_DEMON); + range_init(&spell->mana_range, 15, 45); + spell->info_func = demonology_unholy_word_info; + spell->effect_func = demonology_unholy_word; + spell->failure_rate = 55; + spell->skill_level = 25; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&DEMON_CLOAK, "DEMON_CLOAK", "Demon Cloak"); + string_list_append(&spell->description, "Raises a mirror that can reflect bolts and arrows for a time"); + school_idx_add_new(&spell->schools, SCHOOL_DEMON); + range_init(&spell->mana_range, 10, 40); + spell->info_func = demonology_demon_cloak_info; + spell->effect_func = demonology_demon_cloak; + spell->failure_rate = 70; + spell->skill_level = 20; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&DEMON_SUMMON, "DEMON_SUMMON", "Summon Demon"); + string_list_append(&spell->description, "Summons a leveled demon to your side"); + string_list_append(&spell->description, "At level 35 it summons a high demon"); + school_idx_add_new(&spell->schools, SCHOOL_DEMON); + range_init(&spell->mana_range, 10, 50); + spell->info_func = demonology_summon_demon_info; + spell->effect_func = demonology_summon_demon; + spell->failure_rate = 30; + spell->skill_level = 5; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&DISCHARGE_MINION, "DISCHARGE_MINION", "Discharge Minion"); + string_list_append(&spell->description, "The targeted pet will explode in a burst of gravity"); + school_idx_add_new(&spell->schools, SCHOOL_DEMON); + range_init(&spell->mana_range, 20, 50); + spell->info_func = demonology_discharge_minion_info; + spell->effect_func = demonology_discharge_minion; + spell->failure_rate = 30; + spell->skill_level = 10; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&CONTROL_DEMON, "CONTROL_DEMON", "Control Demon"); + string_list_append(&spell->description, "Attempts to control a demon"); + school_idx_add_new(&spell->schools, SCHOOL_DEMON); + range_init(&spell->mana_range, 30, 70); + spell->info_func = demonology_control_demon_info; + spell->effect_func = demonology_control_demon; + spell->failure_rate = 55; + spell->skill_level = 25; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&DEVICE_HEAL_MONSTER, "DEVICE_HEAL_MONSTER", "Heal Monster"); + string_list_append(&spell->description, "Heals a monster"); + school_idx_add_new(&spell->schools, SCHOOL_DEVICE); + range_init(&spell->mana_range, 5, 20); + spell->info_func = device_heal_monster_info; + spell->effect_func = device_heal_monster; + spell->failure_rate = 15; + spell->skill_level = 3; + spell_init_mage(spell, NO_RANDOM); + + dice_parse_checked(&spell->device_charges, "10+d10"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 17; + range_init(&device_allocation->base_level, 1, 15); + range_init(&device_allocation->max_level, 20, 50); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&DEVICE_SPEED_MONSTER, "DEVICE_SPEED_MONSTER", "Haste Monster"); + string_list_append(&spell->description, "Haste a monster"); + school_idx_add_new(&spell->schools, SCHOOL_DEVICE); + range_init(&spell->mana_range, 10, 10); + spell->info_func = device_haste_monster_info; + spell->effect_func = device_haste_monster; + spell->failure_rate = 30; + spell->skill_level = 10; + spell_init_mage(spell, NO_RANDOM); + + dice_parse_checked(&spell->device_charges, "10+d5"); + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 7; + range_init(&device_allocation->base_level, 1, 1); + range_init(&device_allocation->max_level, 20, 50); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&DEVICE_WISH, "DEVICE_WISH", "Wish"); + string_list_append(&spell->description, "This grants you a wish, beware of what you ask for!"); + school_idx_add_new(&spell->schools, SCHOOL_DEVICE); + range_init(&spell->mana_range, 400, 400); + spell->info_func = device_wish_info; + spell->effect_func = device_wish; + spell->failure_rate = 99; + spell->skill_level = 50; + spell_init_mage(spell, NO_RANDOM); + + dice_parse_checked(&spell->device_charges, "1+d2"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 98; + range_init(&device_allocation->base_level, 1, 1); + range_init(&device_allocation->max_level, 1, 1); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&DEVICE_SUMMON, "DEVICE_SUMMON", "Summon"); + string_list_append(&spell->description, "Summons hostile monsters near you"); + school_idx_add_new(&spell->schools, SCHOOL_DEVICE); + range_init(&spell->mana_range, 5, 25); + spell->info_func = device_summon_monster_info; + spell->effect_func = device_summon_monster; + spell->failure_rate = 20; + spell->skill_level = 5; + spell_init_mage(spell, NO_RANDOM); + + dice_parse_checked(&spell->device_charges, "1+d20"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 13; + range_init(&device_allocation->base_level, 1, 40); + range_init(&device_allocation->max_level, 25, 50); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&DEVICE_MANA, "DEVICE_MANA", "Mana"); + string_list_append(&spell->description, "Restores a part(or all) of your mana"); + school_idx_add_new(&spell->schools, SCHOOL_DEVICE); + range_init(&spell->mana_range, 1, 1); + spell->info_func = device_mana_info; + spell->effect_func = device_mana; + spell->failure_rate = 80; + spell->skill_level = 30; + spell_init_mage(spell, NO_RANDOM); + + dice_parse_checked(&spell->device_charges, "2+d3"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 78; + range_init(&device_allocation->base_level, 1, 5); + range_init(&device_allocation->max_level, 20, 35); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&DEVICE_NOTHING, "DEVICE_NOTHING", "Nothing"); + string_list_append(&spell->description, "It does nothing."); + school_idx_add_new(&spell->schools, SCHOOL_DEVICE); + range_init(&spell->mana_range, 0, 0); + spell->info_func = device_nothing_info; + spell->effect_func = device_nothing; + spell->failure_rate = 0; + spell->skill_level = 1; + spell_init_mage(spell, NO_RANDOM); + + dice_parse_checked(&spell->device_charges, "0+d0"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 3; + range_init(&device_allocation->base_level, 1, 1); + range_init(&device_allocation->max_level, 1, 1); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + + { + device_allocation *device_allocation = device_allocation_new(TV_WAND); + device_allocation->rarity = 3; + range_init(&device_allocation->base_level, 1, 1); + range_init(&device_allocation->max_level, 1, 1); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&DEVICE_MAGGOT, "DEVICE_MAGGOT", "Artifact Maggot"); + dice_parse_checked(&spell->activation_duration, "10+d50"); + string_list_append(&spell->description, "terrify"); + school_idx_add_new(&spell->schools, SCHOOL_DEVICE); + range_init(&spell->mana_range, 7, 7); + spell->info_func = device_maggot_info; + spell->effect_func = device_maggot; + spell->failure_rate = 20; + spell->skill_level = 1; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&DEVICE_HOLY_FIRE, "DEVICE_HOLY_FIRE", "Holy Fire of Mithrandir"); + string_list_append(&spell->description, "The Holy Fire created by this staff will deeply(double damage) burn"); + string_list_append(&spell->description, "all that is evil."); + school_idx_add_new(&spell->schools, SCHOOL_DEVICE); + range_init(&spell->mana_range, 50, 150); + spell->info_func = device_holy_fire_info; + spell->effect_func = device_holy_fire; + spell->failure_rate = 75; + spell->skill_level = 30; + spell_init_mage(spell, NO_RANDOM); + + dice_parse_checked(&spell->device_charges, "2+d5"); + + { + device_allocation *device_allocation = device_allocation_new(TV_STAFF); + device_allocation->rarity = 999; + range_init(&device_allocation->base_level, 1, 1); + range_init(&device_allocation->max_level, 35, 35); + sglib_device_allocation_add(&spell->device_allocation, device_allocation); + } + } + + { + spell_type *spell = spell_new(&DEVICE_ETERNAL_FLAME, "DEVICE_ETERNAL_FLAME", "Artifact Eternal Flame"); + dice_parse_checked(&spell->activation_duration, "0"); + string_list_append(&spell->description, "Imbuing an object with the eternal fire"); + school_idx_add_new(&spell->schools, SCHOOL_DEVICE); + range_init(&spell->mana_range, 0, 0); + spell->info_func = device_eternal_flame_info; + spell->effect_func = device_eternal_flame; + spell->failure_rate = 0; + spell->skill_level = 1; + spell_init_mage(spell, NO_RANDOM); + } + + { + spell_type *spell = spell_new(&MUSIC_STOP, "MUSIC_STOP", "Stop singing(I)"); + string_list_append(&spell->description, "Stops the current song, if any."); + range_init(&spell->mana_range, 0, 0); + spell->info_func = music_stop_singing_info; + spell->effect_func = music_stop_singing_spell; + spell->failure_rate = -400; + spell->skill_level = 1; + spell->castable_while_blind = TRUE; + spell_init_music(spell, 1); + } + + { + spell_type *spell = spell_new(&MUSIC_HOLD, "MUSIC_HOLD", "Holding Pattern(I)"); + string_list_append(&spell->description, "Slows down all monsters listening the song."); + string_list_append(&spell->description, "Consumes the amount of mana each turn."); + range_init(&spell->mana_range, 1, 10); + spell->info_func = music_holding_pattern_info; + spell->effect_func = music_holding_pattern_spell; + spell->lasting_func = music_holding_pattern_lasting; + spell->failure_rate = 20; + spell->skill_level = 1; + spell->castable_while_blind = TRUE; + spell_init_music(spell, 1); + } + + { + spell_type *spell = spell_new(&MUSIC_CONF, "MUSIC_CONF", "Illusion Pattern(II)"); + string_list_append(&spell->description, "Tries to confuse all monsters listening the song."); + string_list_append(&spell->description, "Consumes the amount of mana each turn."); + range_init(&spell->mana_range, 2, 15); + spell->info_func = music_illusion_pattern_info; + spell->effect_func = music_illusion_pattern_spell; + spell->lasting_func = music_illusion_pattern_lasting; + spell->failure_rate = 30; + spell->skill_level = 5; + spell->castable_while_blind = TRUE; + spell_init_music(spell, 2); + } + + { + spell_type *spell = spell_new(&MUSIC_STUN, "MUSIC_STUN", "Stun Pattern(IV)"); + string_list_append(&spell->description, "Stuns all monsters listening the song."); + string_list_append(&spell->description, "Consumes the amount of mana each turn."); + range_init(&spell->mana_range, 3, 25); + spell->info_func = music_stun_pattern_info; + spell->effect_func = music_stun_pattern_spell; + spell->lasting_func = music_stun_pattern_lasting; + spell->failure_rate = 45; + spell->skill_level = 10; + spell->castable_while_blind = TRUE; + spell_init_music(spell, 4); + } + + { + spell_type *spell = spell_new(&MUSIC_LITE, "MUSIC_LITE", "Song of the Sun(I)"); + string_list_append(&spell->description, "Provides light as long as you sing."); + string_list_append(&spell->description, "Consumes the amount of mana each turn."); + range_init(&spell->mana_range, 1, 1); + spell->info_func = music_song_of_the_sun_info; + spell->effect_func = music_song_of_the_sun_spell; + spell->lasting_func = music_song_of_the_sun_lasting; + spell->failure_rate = 20; + spell->skill_level = 1; + spell->castable_while_blind = TRUE; + spell_init_music(spell, 1); + } + + { + spell_type *spell = spell_new(&MUSIC_HEAL, "MUSIC_HEAL", "Flow of Life(II)"); + string_list_append(&spell->description, "Heals you as long as you sing."); + string_list_append(&spell->description, "Consumes the amount of mana each turn."); + range_init(&spell->mana_range, 5, 30); + spell->info_func = music_flow_of_life_info; + spell->effect_func = music_flow_of_life_spell; + spell->lasting_func = music_flow_of_life_lasting; + spell->failure_rate = 35; + spell->skill_level = 7; + spell_init_music(spell, 2); + } + + { + spell_type *spell = spell_new(&MUSIC_HERO, "MUSIC_HERO", "Heroic Ballad(II)"); + string_list_append(&spell->description, "Increases melee accuracy"); + string_list_append(&spell->description, "At level 10 it increases it even more and reduces armour a bit"); + string_list_append(&spell->description, "At level 20 it increases it again"); + string_list_append(&spell->description, "At level 25 it grants protection against chaos and confusion"); + string_list_append(&spell->description, "Consumes the amount of mana each turn."); + range_init(&spell->mana_range, 4, 14); + spell->info_func = music_heroic_ballad_info; + spell->effect_func = music_heroic_ballad_spell; + spell->lasting_func = music_heroic_ballad_lasting; + spell->failure_rate = 45; + spell->skill_level = 10; + spell_init_music(spell, 2); + } + + { + spell_type *spell = spell_new(&MUSIC_TIME, "MUSIC_TIME", "Hobbit Melodies(III)"); + string_list_append(&spell->description, "Greatly increases your reflexes allowing you to block more melee blows."); + string_list_append(&spell->description, "At level 15 it also makes you faster."); + string_list_append(&spell->description, "Consumes the amount of mana each turn."); + range_init(&spell->mana_range, 10, 30); + spell->info_func = music_hobbit_melodies_info; + spell->effect_func = music_hobbit_melodies_spell; + spell->lasting_func = music_hobbit_melodies_lasting; + spell->failure_rate = 70; + spell->skill_level = 20; + spell_init_music(spell, 3); + } + + { + spell_type *spell = spell_new(&MUSIC_MIND, "MUSIC_MIND", "Clairaudience(IV)"); + string_list_append(&spell->description, "Allows you to sense monster minds as long as you sing."); + string_list_append(&spell->description, "At level 10 it identifies all objects in a radius on the floor,"); + string_list_append(&spell->description, "as well as probing monsters in that radius."); + string_list_append(&spell->description, "Consumes the amount of mana each turn."); + range_init(&spell->mana_range, 15, 30); + spell->info_func = music_clairaudience_info; + spell->effect_func = music_clairaudience_spell; + spell->lasting_func = music_clairaudience_lasting; + spell->failure_rate = 75; + spell->skill_level = 25; + spell_init_music(spell, 4); + } + + { + spell_type *spell = spell_new(&MUSIC_BLOW, "MUSIC_BLOW", "Blow(I)"); + string_list_append(&spell->description, "Produces a powerful, blowing, sound all around you."); + range_init(&spell->mana_range, 3, 30); + spell->info_func = music_blow_info; + spell->effect_func = music_blow_spell; + spell->failure_rate = 20; + spell->skill_level = 4; + spell_init_music(spell, 1); + } + + { + spell_type *spell = spell_new(&MUSIC_WIND, "MUSIC_WIND", "Gush of Wind(II)"); + string_list_append(&spell->description, "Produces a outgoing gush of wind that sends monsters away."); + range_init(&spell->mana_range, 15, 45); + spell->info_func = music_gush_of_wind_info; + spell->effect_func = music_gush_of_wind_spell; + spell->failure_rate = 30; + spell->skill_level = 14; + spell_init_music(spell, 2); + } + + { + spell_type *spell = spell_new(&MUSIC_YLMIR, "MUSIC_YLMIR", "Horns of Ylmir(III)"); + string_list_append(&spell->description, "Produces an earth shaking sound."); + range_init(&spell->mana_range, 25, 30); + spell->info_func = music_horns_of_ylmir_info; + spell->effect_func = music_horns_of_ylmir_spell; + spell->failure_rate = 20; + spell->skill_level = 20; + spell_init_music(spell, 3); + } + + { + spell_type *spell = spell_new(&MUSIC_AMBARKANTA, "MUSIC_AMBARKANTA", "Ambarkanta(IV)"); + string_list_append(&spell->description, "Produces a reality shaking sound that transports you to a nearly"); + string_list_append(&spell->description, "identical reality."); + range_init(&spell->mana_range, 70, 70); + spell->info_func = music_ambarkanta_info; + spell->effect_func = music_ambarkanta_spell; + spell->failure_rate = 60; + spell->skill_level = 25; + spell_init_music(spell, 4); + } + + /* Module-specific spells */ + switch (game_module_idx) + { + case MODULE_TOME: + spells_init_tome(); + break; + case MODULE_THEME: + spells_init_theme(); + break; + default: + assert(FALSE); + } + +} diff --git a/src/types.h b/src/types.h index fbf049ae..b00ade5c 100644 --- a/src/types.h +++ b/src/types.h @@ -2527,11 +2527,37 @@ struct spell_type { cptr name; /* Name */ byte skill_level; /* Required level (to learn) */ - byte mana; /* Required mana at lvl 1 */ - byte mana_max; /* Required mana at max lvl */ - s16b fail; /* Minimum chance of failure */ s16b level; /* Spell level(0 = not learnt) */ string_list *description; /* List of strings */ + + bool_ *(*effect_func)(int o_idx); /* Spell effect function */ + char* (*info_func)(); /* Information function */ + int (*lasting_func)(); /* Lasting effect function */ + bool_ (*depend_func)(); /* Check dependencies */ + + s16b minimum_pval; /* Minimum required pval for item-based spells */ + + casting_type casting_type; /* Type of casting required */ + s16b casting_stat; /* Stat used for casting */ + + bool_ castable_while_blind; + bool_ castable_while_confused; + + dice_type device_charges; /* Number of charges for devices */ + device_allocation *device_allocation; /* Allocation table for devices */ + + s16b random_type; /* Type of random items in which skill may appear */ + + s32b failure_rate; /* Failure rate */ + + s32b inertia_difficulty; /* Mana cost when used in Inertia Control */ + s32b inertia_delay; /* Delay between castings */ + + range_type mana_range; + + dice_type activation_duration; /* Duration for activation (if any) */ + + school_idx *schools; }; typedef struct school_type school_type; diff --git a/src/variable.c b/src/variable.c index 105bbc7f..71fb5dd8 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1498,8 +1498,8 @@ bool_ player_char_health; /* * The spell list of schools */ -s16b max_spells; -spell_type *school_spells; +s16b school_spells_count = 0; +spell_type school_spells[SCHOOL_SPELLS_MAX]; s16b max_schools; school_type *schools; -- cgit v1.2.3 From f2b27a7ab74529504da68d418fdcecabd5ee989a Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 29 May 2012 17:57:00 +0200 Subject: Lua: Remove unused spell_type.skill field. --- src/spells.pkg | 5 ----- src/types.h | 1 - 2 files changed, 6 deletions(-) diff --git a/src/spells.pkg b/src/spells.pkg index 6360e7d3..0abf480c 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2168,11 +2168,6 @@ struct spell_type@school_spell_type */ byte skill_level; - /** @structvar level - * @brief Number - * @note Spell level(0 = not learnt) - */ - s16b level; }; /** @struct school_type diff --git a/src/types.h b/src/types.h index b00ade5c..9aa3409c 100644 --- a/src/types.h +++ b/src/types.h @@ -2527,7 +2527,6 @@ struct spell_type { cptr name; /* Name */ byte skill_level; /* Required level (to learn) */ - s16b level; /* Spell level(0 = not learnt) */ string_list *description; /* List of strings */ bool_ *(*effect_func)(int o_idx); /* Spell effect function */ -- cgit v1.2.3 From 77fcd7e02c87167002b8294a47c6cc37a0c960b3 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 28 May 2012 07:55:57 +0200 Subject: Lua: Reintroduce the "obvious" flag from casting This got accidentally removed when moving the spell functions to C. --- lib/core/s_aux.lua | 12 - lib/mods/theme/core/s_aux.lua | 13 - src/cmd6.c | 19 +- src/externs.h | 574 ++++++++++----------- src/spells.pkg | 2 +- src/spells2.c | 3 +- src/spells3.c | 1120 +++++++++++++++++++++-------------------- src/spells4.c | 2 +- src/types.h | 11 +- 9 files changed, 879 insertions(+), 877 deletions(-) diff --git a/lib/core/s_aux.lua b/lib/core/s_aux.lua index 9a39df14..860892ae 100644 --- a/lib/core/s_aux.lua +++ b/lib/core/s_aux.lua @@ -145,15 +145,3 @@ function get_level(s, max, min) return %get_level(s, max, min) end --- Helper function for spell effect to know if they are or not obvious -function is_obvious(effect, old) - if old then - if old == TRUE or effect == TRUE then - return TRUE - else - return FALSE - end - else - return effect - end -end diff --git a/lib/mods/theme/core/s_aux.lua b/lib/mods/theme/core/s_aux.lua index 9a39df14..3e98ec94 100644 --- a/lib/mods/theme/core/s_aux.lua +++ b/lib/mods/theme/core/s_aux.lua @@ -144,16 +144,3 @@ function get_level(s, max, min) if not min then min = 1 end return %get_level(s, max, min) end - --- Helper function for spell effect to know if they are or not obvious -function is_obvious(effect, old) - if old then - if old == TRUE or effect == TRUE then - return TRUE - else - return FALSE - end - else - return effect - end -end diff --git a/src/cmd6.c b/src/cmd6.c index 7bd6c80a..32ad1868 100644 --- a/src/cmd6.c +++ b/src/cmd6.c @@ -3655,7 +3655,7 @@ void unset_stick_mode() static void activate_stick(s16b s, bool_ *obvious, bool_ *use_charge) { spell_type *spell = spell_at(s); - bool_ *ret; + casting_result ret; assert(obvious != NULL); assert(use_charge != NULL); @@ -3663,15 +3663,22 @@ static void activate_stick(s16b s, bool_ *obvious, bool_ *use_charge) ret = spell->effect_func(-1); - if (ret == NULL) + switch (ret) { + case NO_CAST: *use_charge = FALSE; *obvious = FALSE; - } - else - { + break; + case CAST_HIDDEN: *use_charge = TRUE; - *obvious = *ret; + *obvious = FALSE; + break; + case CAST_OBVIOUS: + *use_charge = TRUE; + *obvious = TRUE; + break; + default: + assert(FALSE); } } diff --git a/src/externs.h b/src/externs.h index 897cc074..e584b44c 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1263,7 +1263,7 @@ extern void explosive_rune(void); extern bool_ do_dec_stat(int stat, int mode); extern bool_ do_res_stat(int stat, bool_ full); extern bool_ do_inc_stat(int stat); -extern void identify_pack(void); +extern bool_ identify_pack(void); extern void identify_pack_fully(void); extern bool_ remove_curse(void); extern bool_ remove_all_curse(void); @@ -1411,18 +1411,18 @@ extern s32b POISONBLOOD; extern s32b THUNDERSTORM; extern s32b STERILIZE; -bool_ *air_noxious_cloud(int); -char *air_noxious_cloud_info(); -bool_ *air_wings_of_winds(int); -char *air_wings_of_winds_info(); -bool_ *air_invisibility(int); -char *air_invisibility_info(); -bool_ *air_poison_blood(int); -char *air_poison_blood_info(); -bool_ *air_thunderstorm(int); -char *air_thunderstorm_info(); -bool_ *air_sterilize(int); -char *air_sterilize_info(); +casting_result air_noxious_cloud(int); +char *air_noxious_cloud_info(); +casting_result air_wings_of_winds(int); +char *air_wings_of_winds_info(); +casting_result air_invisibility(int); +char *air_invisibility_info(); +casting_result air_poison_blood(int); +char *air_poison_blood_info(); +casting_result air_thunderstorm(int); +char *air_thunderstorm_info(); +casting_result air_sterilize(int); +char *air_sterilize_info(); extern s32b BLINK; extern s32b DISARM; @@ -1431,18 +1431,18 @@ extern s32b TELEAWAY; extern s32b RECALL; extern s32b PROBABILITY_TRAVEL; -bool_ *convey_blink(int); -char *convey_blink_info(); -bool_ *convey_disarm(int); -char *convey_disarm_info(); -bool_ *convey_teleport(int); -char *convey_teleport_info(); -bool_ *convey_teleport_away(int); -char *convey_teleport_away_info(); -bool_ *convey_recall(int); -char *convey_recall_info(); -bool_ *convey_probability_travel(int); -char *convey_probability_travel_info(); +casting_result convey_blink(int); +char *convey_blink_info(); +casting_result convey_disarm(int); +char *convey_disarm_info(); +casting_result convey_teleport(int); +char *convey_teleport_info(); +casting_result convey_teleport_away(int); +char *convey_teleport_away_info(); +casting_result convey_recall(int); +char *convey_recall_info(); +casting_result convey_probability_travel(int); +char *convey_probability_travel_info(); extern s32b DEMON_BLADE; extern s32b DEMON_MADNESS; @@ -1454,24 +1454,24 @@ extern s32b DEMON_SUMMON; extern s32b DISCHARGE_MINION; extern s32b CONTROL_DEMON; -bool_ *demonology_demon_blade(int); -char *demonology_demon_blade_info(); -bool_ *demonology_demon_madness(int); -char *demonology_demon_madness_info(); -bool_ *demonology_demon_field(int); -char *demonology_demon_field_info(); -bool_ *demonology_doom_shield(int); -char *demonology_doom_shield_info(); -bool_ *demonology_unholy_word(int); -char *demonology_unholy_word_info(); -bool_ *demonology_demon_cloak(int); -char *demonology_demon_cloak_info(); -bool_ *demonology_summon_demon(int); -char *demonology_summon_demon_info(); -bool_ *demonology_discharge_minion(int); -char *demonology_discharge_minion_info(); -bool_ *demonology_control_demon(int); -char *demonology_control_demon_info(); +casting_result demonology_demon_blade(int); +char *demonology_demon_blade_info(); +casting_result demonology_demon_madness(int); +char *demonology_demon_madness_info(); +casting_result demonology_demon_field(int); +char *demonology_demon_field_info(); +casting_result demonology_doom_shield(int); +char *demonology_doom_shield_info(); +casting_result demonology_unholy_word(int); +char *demonology_unholy_word_info(); +casting_result demonology_demon_cloak(int); +char *demonology_demon_cloak_info(); +casting_result demonology_summon_demon(int); +char *demonology_summon_demon_info(); +casting_result demonology_discharge_minion(int); +char *demonology_discharge_minion_info(); +casting_result demonology_control_demon(int); +char *demonology_control_demon_info(); extern s32b STARIDENTIFY; extern s32b IDENTIFY; @@ -1480,18 +1480,18 @@ extern s32b SENSEHIDDEN; extern s32b REVEALWAYS; extern s32b SENSEMONSTERS; -bool_ *divination_greater_identify(int); -char *divination_greater_identify_info(); -bool_ *divination_identify(int); -char *divination_identify_info(); -bool_ *divination_vision(int); -char *divination_vision_info(); -bool_ *divination_sense_hidden(int); -char *divination_sense_hidden_info(); -bool_ *divination_reveal_ways(int); -char *divination_reveal_ways_info(); -bool_ *divination_sense_monsters(int); -char *divination_sense_monsters_info(); +casting_result divination_greater_identify(int); +char *divination_greater_identify_info(); +casting_result divination_identify(int); +char *divination_identify_info(); +casting_result divination_vision(int); +char *divination_vision_info(); +casting_result divination_sense_hidden(int); +char *divination_sense_hidden_info(); +casting_result divination_reveal_ways(int); +char *divination_reveal_ways_info(); +casting_result divination_sense_monsters(int); +char *divination_sense_monsters_info(); extern s32b STONESKIN; extern s32b DIG; @@ -1499,30 +1499,30 @@ extern s32b STONEPRISON; extern s32b STRIKE; extern s32b SHAKE; -bool_ *earth_stone_skin(int); -char *earth_stone_skin_info(); -bool_ *earth_dig(int); -char *earth_dig_info(); -bool_ *earth_stone_prison(int); -char *earth_stone_prison_info(); -bool_ *earth_strike(int); -char *earth_strike_info(); -bool_ *earth_shake(int); -char *earth_shake_info(); +casting_result earth_stone_skin(int); +char *earth_stone_skin_info(); +casting_result earth_dig(int); +char *earth_dig_info(); +casting_result earth_stone_prison(int); +char *earth_stone_prison_info(); +casting_result earth_strike(int); +char *earth_strike_info(); +casting_result earth_shake(int); +char *earth_shake_info(); extern s32b ERU_SEE; extern s32b ERU_LISTEN; extern s32b ERU_UNDERSTAND; extern s32b ERU_PROT; -bool_ *eru_see_the_music(int); -char *eru_see_the_music_info(); -bool_ *eru_listen_to_the_music(int); -char *eru_listen_to_the_music_info(); -bool_ *eru_know_the_music(int); -char *eru_know_the_music_info(); -bool_ *eru_lay_of_protection(int); -char *eru_lay_of_protection_info(); +casting_result eru_see_the_music(int); +char *eru_see_the_music_info(); +casting_result eru_listen_to_the_music(int); +char *eru_listen_to_the_music_info(); +casting_result eru_know_the_music(int); +char *eru_know_the_music_info(); +casting_result eru_lay_of_protection(int); +char *eru_lay_of_protection_info(); extern s32b GLOBELIGHT; extern s32b FIREFLASH; @@ -1530,16 +1530,16 @@ extern s32b FIERYAURA; extern s32b FIREWALL; extern s32b FIREGOLEM; -bool_ *fire_globe_of_light(int); -char *fire_globe_of_light_info(); -bool_ *fire_fireflash(int); -char *fire_fireflash_info(); -bool_ *fire_fiery_shield(int); -char *fire_fiery_shield_info(); -bool_ *fire_firewall(int); -char *fire_firewall_info(); -bool_ *fire_golem(int); -char *fire_golem_info(); +casting_result fire_globe_of_light(int); +char *fire_globe_of_light_info(); +casting_result fire_fireflash(int); +char *fire_fireflash_info(); +casting_result fire_fiery_shield(int); +char *fire_fiery_shield_info(); +casting_result fire_firewall(int); +char *fire_firewall_info(); +casting_result fire_golem(int); +char *fire_golem_info(); extern s32b CALL_THE_ELEMENTS; extern s32b CHANNEL_ELEMENTS; @@ -1550,54 +1550,54 @@ extern s32b DRIPPING_TREAD; extern s32b GROW_BARRIER; extern s32b ELEMENTAL_MINION; -bool_ *geomancy_call_the_elements(int); -char *geomancy_call_the_elements_info(); -bool_ *geomancy_channel_elements(int); -char *geomancy_channel_elements_info(); -bool_ *geomancy_elemental_wave(int); -char *geomancy_elemental_wave_info(); -bool_ *geomancy_vaporize(int); -char *geomancy_vaporize_info(); -bool_ geomancy_vaporize_depends(); -bool_ *geomancy_geolysis(int); -char *geomancy_geolysis_info(); -bool_ geomancy_geolysis_depends(); -bool_ *geomancy_dripping_tread(int); -char *geomancy_dripping_tread_info(); -bool_ geomancy_dripping_tread_depends(); -bool_ *geomancy_grow_barrier(int); -char *geomancy_grow_barrier_info(); -bool_ geomancy_grow_barrier_depends(); -bool_ *geomancy_elemental_minion(int); -char *geomancy_elemental_minion_info(); +casting_result geomancy_call_the_elements(int); +char *geomancy_call_the_elements_info(); +casting_result geomancy_channel_elements(int); +char *geomancy_channel_elements_info(); +casting_result geomancy_elemental_wave(int); +char *geomancy_elemental_wave_info(); +casting_result geomancy_vaporize(int); +char *geomancy_vaporize_info(); +bool_ geomancy_vaporize_depends(); +casting_result geomancy_geolysis(int); +char *geomancy_geolysis_info(); +bool_ geomancy_geolysis_depends(); +casting_result geomancy_dripping_tread(int); +char *geomancy_dripping_tread_info(); +bool_ geomancy_dripping_tread_depends(); +casting_result geomancy_grow_barrier(int); +char *geomancy_grow_barrier_info(); +bool_ geomancy_grow_barrier_depends(); +casting_result geomancy_elemental_minion(int); +char *geomancy_elemental_minion_info(); extern s32b MANATHRUST; extern s32b DELCURSES; extern s32b RESISTS; extern s32b MANASHIELD; -bool_ *mana_manathrust(int); -char *mana_manathrust_info(); -bool_ *mana_remove_curses(int); -char *mana_remove_curses_info(); -bool_ *mana_elemental_shield(int); -char *mana_elemental_shield_info(); -bool_ *mana_disruption_shield(int); -char *mana_disruption_shield_info(); +casting_result mana_manathrust(int); +char *mana_manathrust_info(); +casting_result mana_remove_curses(int); +char *mana_remove_curses_info(); +casting_result mana_elemental_shield(int); +char *mana_elemental_shield_info(); +casting_result mana_disruption_shield(int); +char *mana_disruption_shield_info(); extern s32b MANWE_SHIELD; extern s32b MANWE_AVATAR; extern s32b MANWE_BLESS; extern s32b MANWE_CALL; -bool_ *manwe_wind_shield(int); -char *manwe_wind_shield_info(); -bool_ *manwe_avatar(int); -char *manwe_avatar_info(); -bool_ *manwe_blessing(int); -char *manwe_blessing_info(); -bool_ *manwe_call(int); -char *manwe_call_info(); +casting_result manwe_wind_shield(int); +char *manwe_wind_shield_info(); +casting_result manwe_avatar(int); +char *manwe_avatar_info(); +casting_result manwe_blessing(int); +char *manwe_blessing_info(); +casting_result manwe_call(int); +char *manwe_call_info(); extern s32b MELKOR_CURSE; extern s32b MELKOR_CORPSE_EXPLOSION; @@ -1605,12 +1605,12 @@ extern s32b MELKOR_MIND_STEAL; void do_melkor_curse(int m_idx); -bool_ *melkor_curse(int); -char *melkor_curse_info(); -bool_ *melkor_corpse_explosion(int); -char *melkor_corpse_explosion_info(); -bool_ *melkor_mind_steal(int); -char *melkor_mind_steal_info(); +casting_result melkor_curse(int); +char *melkor_curse_info(); +casting_result melkor_corpse_explosion(int); +char *melkor_corpse_explosion_info(); +casting_result melkor_mind_steal(int); +char *melkor_mind_steal_info(); extern s32b RECHARGE; extern s32b SPELLBINDER; @@ -1619,16 +1619,16 @@ extern s32b TRACKER; extern s32b INERTIA_CONTROL; extern timer_type *TIMER_INERTIA_CONTROL; -bool_ *meta_recharge(int); -char *meta_recharge_info(); -bool_ *meta_spellbinder(int); -char *meta_spellbinder_info(); -bool_ *meta_disperse_magic(int); -char *meta_disperse_magic_info(); -bool_ *meta_tracker(int); -char *meta_tracker_info(); -bool_ *meta_inertia_control(int); -char *meta_inertia_control_info(); +casting_result meta_recharge(int); +char *meta_recharge_info(); +casting_result meta_spellbinder(int); +char *meta_spellbinder_info(); +casting_result meta_disperse_magic(int); +char *meta_disperse_magic_info(); +casting_result meta_tracker(int); +char *meta_tracker_info(); +casting_result meta_inertia_control(int); +char *meta_inertia_control_info(); void meta_inertia_control_timer_callback(); void meta_inertia_control_calc_mana(int *msp); @@ -1639,13 +1639,13 @@ extern s32b CONFUSE; extern s32b ARMOROFFEAR; extern s32b STUN; -bool_ *mind_charm(int); +casting_result mind_charm(int); char *mind_charm_info(); -bool_ *mind_confuse(int); +casting_result mind_confuse(int); char *mind_confuse_info(); -bool_ *mind_armor_of_fear(int); +casting_result mind_armor_of_fear(int); char *mind_armor_of_fear_info(); -bool_ *mind_stun(int); +casting_result mind_stun(int); char *mind_stun_info(); extern s32b MAGELOCK; @@ -1653,25 +1653,25 @@ extern s32b SLOWMONSTER; extern s32b ESSENCESPEED; extern s32b BANISHMENT; -bool_ *tempo_magelock(int); -char *tempo_magelock_info(); -bool_ *tempo_slow_monster(int); -char *tempo_slow_monster_info(); -bool_ *tempo_essence_of_speed(int); -char *tempo_essence_of_speed_info(); -bool_ *tempo_banishment(int); -char *tempo_banishment_info(); +casting_result tempo_magelock(int); +char *tempo_magelock_info(); +casting_result tempo_slow_monster(int); +char *tempo_slow_monster_info(); +casting_result tempo_essence_of_speed(int); +char *tempo_essence_of_speed_info(); +casting_result tempo_banishment(int); +char *tempo_banishment_info(); extern s32b TULKAS_AIM; extern s32b TULKAS_WAVE; extern s32b TULKAS_SPIN; -bool_ *tulkas_divine_aim(int); -char *tulkas_divine_aim_info(); -bool_ *tulkas_wave_of_power(int); -char *tulkas_wave_of_power_info(); -bool_ *tulkas_whirlwind(int); -char *tulkas_whirlwind_info(); +casting_result tulkas_divine_aim(int); +char *tulkas_divine_aim_info(); +casting_result tulkas_wave_of_power(int); +char *tulkas_wave_of_power_info(); +casting_result tulkas_whirlwind(int); +char *tulkas_whirlwind_info(); extern s32b DRAIN; extern s32b GENOCIDE; @@ -1681,14 +1681,14 @@ extern s32b FLAMEOFUDUN; int udun_in_book(s32b sval, s32b pval); int levels_in_book(s32b sval, s32b pval); -bool_ *udun_drain(int); -char *udun_drain_info(); -bool_ *udun_genocide(int); -char *udun_genocide_info(); -bool_ *udun_wraithform(int); -char *udun_wraithform_info(); -bool_ *udun_flame_of_udun(int); -char *udun_flame_of_udun_info(); +casting_result udun_drain(int); +char *udun_drain_info(); +casting_result udun_genocide(int); +char *udun_genocide_info(); +casting_result udun_wraithform(int); +char *udun_wraithform_info(); +casting_result udun_flame_of_udun(int); +char *udun_flame_of_udun_info(); extern s32b TIDALWAVE; extern s32b ICESTORM; @@ -1696,16 +1696,16 @@ extern s32b ENTPOTION; extern s32b VAPOR; extern s32b GEYSER; -bool_ *water_tidal_wave(int); -char *water_tidal_wave_info(); -bool_ *water_ice_storm(int); -char *water_ice_storm_info(); -bool_ *water_ent_potion(int); -char *water_ent_potion_info(); -bool_ *water_vapor(int); -char *water_vapor_info(); -bool_ *water_geyser(int); -char *water_geyser_info(); +casting_result water_tidal_wave(int); +char *water_tidal_wave_info(); +casting_result water_ice_storm(int); +char *water_ice_storm_info(); +casting_result water_ent_potion(int); +char *water_ent_potion_info(); +casting_result water_vapor(int); +char *water_vapor_info(); +casting_result water_geyser(int); +char *water_geyser_info(); extern s32b YAVANNA_CHARM_ANIMAL; extern s32b YAVANNA_GROW_GRASS; @@ -1713,16 +1713,16 @@ extern s32b YAVANNA_TREE_ROOTS; extern s32b YAVANNA_WATER_BITE; extern s32b YAVANNA_UPROOT; -bool_ *yavanna_charm_animal(int); -char *yavanna_charm_animal_info(); -bool_ *yavanna_grow_grass(int); -char *yavanna_grow_grass_info(); -bool_ *yavanna_tree_roots(int); -char *yavanna_tree_roots_info(); -bool_ *yavanna_water_bite(int); -char *yavanna_water_bite_info(); -bool_ *yavanna_uproot(int); -char *yavanna_uproot_info(); +casting_result yavanna_charm_animal(int); +char *yavanna_charm_animal_info(); +casting_result yavanna_grow_grass(int); +char *yavanna_grow_grass_info(); +casting_result yavanna_tree_roots(int); +char *yavanna_tree_roots_info(); +casting_result yavanna_water_bite(int); +char *yavanna_water_bite_info(); +casting_result yavanna_uproot(int); +char *yavanna_uproot_info(); extern s32b GROWTREE; extern s32b HEALING; @@ -1731,18 +1731,18 @@ extern s32b REGENERATION; extern s32b SUMMONANNIMAL; extern s32b GROW_ATHELAS; -bool_ *nature_grow_trees(int); -char *nature_grow_trees_info(); -bool_ *nature_healing(int); -char *nature_healing_info(); -bool_ *nature_recovery(int); -char *nature_recovery_info(); -bool_ *nature_regeneration(int); -char *nature_regeneration_info(); -bool_ *nature_summon_animal(int); -char *nature_summon_animal_info(); -bool_ *nature_grow_athelas(int); -char *nature_grow_athelas_info(); +casting_result nature_grow_trees(int); +char *nature_grow_trees_info(); +casting_result nature_healing(int); +char *nature_healing_info(); +casting_result nature_recovery(int); +char *nature_recovery_info(); +casting_result nature_regeneration(int); +char *nature_regeneration_info(); +casting_result nature_summon_animal(int); +char *nature_summon_animal_info(); +casting_result nature_grow_athelas(int); +char *nature_grow_athelas_info(); extern s32b DEVICE_HEAL_MONSTER; extern s32b DEVICE_SPEED_MONSTER; @@ -1759,34 +1759,34 @@ extern s32b DEVICE_THUNDERLORDS; extern s32b DEVICE_RADAGAST; extern s32b DEVICE_VALAROMA; -bool_ *device_heal_monster(int); -char *device_heal_monster_info(); -bool_ *device_haste_monster(int); -char *device_haste_monster_info(); -bool_ *device_wish(int); -char *device_wish_info(); -bool_ *device_summon_monster(int); -char *device_summon_monster_info(); -bool_ *device_mana(int); -char *device_mana_info(); -bool_ *device_nothing(int); -char *device_nothing_info(); -bool_ *device_lebohaum(int); -char *device_lebohaum_info(); -bool_ *device_maggot(int); -char *device_maggot_info(); -bool_ *device_holy_fire(int); -char *device_holy_fire_info(); -bool_ *device_eternal_flame(int); -char *device_eternal_flame_info(); -bool_ *device_durandil(int); -char *device_durandil_info(); -bool_ *device_thunderlords(int); -char *device_thunderlords_info(); -bool_ *device_radagast(int); -char *device_radagast_info(); -bool_ *device_valaroma(int); -char *device_valaroma_info(); +casting_result device_heal_monster(int); +char *device_heal_monster_info(); +casting_result device_haste_monster(int); +char *device_haste_monster_info(); +casting_result device_wish(int); +char *device_wish_info(); +casting_result device_summon_monster(int); +char *device_summon_monster_info(); +casting_result device_mana(int); +char *device_mana_info(); +casting_result device_nothing(int); +char *device_nothing_info(); +casting_result device_lebohaum(int); +char *device_lebohaum_info(); +casting_result device_maggot(int); +char *device_maggot_info(); +casting_result device_holy_fire(int); +char *device_holy_fire_info(); +casting_result device_eternal_flame(int); +char *device_eternal_flame_info(); +casting_result device_durandil(int); +char *device_durandil_info(); +casting_result device_thunderlords(int); +char *device_thunderlords_info(); +casting_result device_radagast(int); +char *device_radagast_info(); +casting_result device_valaroma(int); +char *device_valaroma_info(); extern s32b MUSIC_STOP; extern s32b MUSIC_HOLD; @@ -1802,108 +1802,108 @@ extern s32b MUSIC_WIND; extern s32b MUSIC_YLMIR; extern s32b MUSIC_AMBARKANTA; -bool_ *music_stop_singing_spell(int); -char *music_stop_singing_info(); +casting_result music_stop_singing_spell(int); +char *music_stop_singing_info(); -int music_holding_pattern_lasting(); -bool_ *music_holding_pattern_spell(int); -char *music_holding_pattern_info(); +int music_holding_pattern_lasting(); +casting_result music_holding_pattern_spell(int); +char *music_holding_pattern_info(); -int music_illusion_pattern_lasting(); -bool_ *music_illusion_pattern_spell(int); -char *music_illusion_pattern_info(); +int music_illusion_pattern_lasting(); +casting_result music_illusion_pattern_spell(int); +char *music_illusion_pattern_info(); -int music_stun_pattern_lasting(); -bool_ *music_stun_pattern_spell(int); -char *music_stun_pattern_info(); +int music_stun_pattern_lasting(); +casting_result music_stun_pattern_spell(int); +char *music_stun_pattern_info(); -int music_song_of_the_sun_lasting(); -bool_ *music_song_of_the_sun_spell(int); -char *music_song_of_the_sun_info(); +int music_song_of_the_sun_lasting(); +casting_result music_song_of_the_sun_spell(int); +char *music_song_of_the_sun_info(); -int music_flow_of_life_lasting(); -bool_ *music_flow_of_life_spell(int); -char *music_flow_of_life_info(); +int music_flow_of_life_lasting(); +casting_result music_flow_of_life_spell(int); +char *music_flow_of_life_info(); -int music_heroic_ballad_lasting(); -bool_ *music_heroic_ballad_spell(int); -char *music_heroic_ballad_info(); +int music_heroic_ballad_lasting(); +casting_result music_heroic_ballad_spell(int); +char *music_heroic_ballad_info(); -int music_hobbit_melodies_lasting(); -bool_ *music_hobbit_melodies_spell(int); -char *music_hobbit_melodies_info(); +int music_hobbit_melodies_lasting(); +casting_result music_hobbit_melodies_spell(int); +char *music_hobbit_melodies_info(); -int music_clairaudience_lasting(); -bool_ *music_clairaudience_spell(int); -char *music_clairaudience_info(); +int music_clairaudience_lasting(); +casting_result music_clairaudience_spell(int); +char *music_clairaudience_info(); -bool_ *music_blow_spell(int); -char *music_blow_info(); +casting_result music_blow_spell(int); +char *music_blow_info(); -bool_ *music_gush_of_wind_spell(int); -char *music_gush_of_wind_info(); +casting_result music_gush_of_wind_spell(int); +char *music_gush_of_wind_info(); -bool_ *music_horns_of_ylmir_spell(int); -char *music_horns_of_ylmir_info(); +casting_result music_horns_of_ylmir_spell(int); +char *music_horns_of_ylmir_info(); -bool_ *music_ambarkanta_spell(int); -char *music_ambarkanta_info(); +casting_result music_ambarkanta_spell(int); +char *music_ambarkanta_info(); extern s32b AULE_FIREBRAND; extern s32b AULE_ENCHANT_WEAPON; extern s32b AULE_ENCHANT_ARMOUR; extern s32b AULE_CHILD; -bool_ *aule_firebrand_spell(int); -char *aule_firebrand_info(); -bool_ *aule_enchant_weapon_spell(int); -char *aule_enchant_weapon_info(); -bool_ *aule_enchant_armour_spell(int); -char *aule_enchant_armour_info(); -bool_ *aule_child_spell(int); -char *aule_child_info(); +casting_result aule_firebrand_spell(int); +char *aule_firebrand_info(); +casting_result aule_enchant_weapon_spell(int); +char *aule_enchant_weapon_info(); +casting_result aule_enchant_armour_spell(int); +char *aule_enchant_armour_info(); +casting_result aule_child_spell(int); +char *aule_child_info(); extern s32b MANDOS_TEARS_LUTHIEN; extern s32b MANDOS_SPIRIT_FEANTURI; extern s32b MANDOS_TALE_DOOM; extern s32b MANDOS_CALL_HALLS; -bool_ *mandos_tears_of_luthien_spell(int); -char *mandos_tears_of_luthien_info(); -bool_ *mandos_spirit_of_the_feanturi_spell(int); -char *mandos_spirit_of_the_feanturi_info(); -bool_ *mandos_tale_of_doom_spell(int); -char *mandos_tale_of_doom_info(); -bool_ *mandos_call_to_the_halls_spell(int); -char *mandos_call_to_the_halls_info(); +casting_result mandos_tears_of_luthien_spell(int); +char *mandos_tears_of_luthien_info(); +casting_result mandos_spirit_of_the_feanturi_spell(int); +char *mandos_spirit_of_the_feanturi_info(); +casting_result mandos_tale_of_doom_spell(int); +char *mandos_tale_of_doom_info(); +casting_result mandos_call_to_the_halls_spell(int); +char *mandos_call_to_the_halls_info(); extern s32b ULMO_BELEGAER; extern s32b ULMO_DRAUGHT_ULMONAN; extern s32b ULMO_CALL_ULUMURI; extern s32b ULMO_WRATH; -bool_ *ulmo_song_of_belegaer_spell(int); -char *ulmo_song_of_belegaer_info(); -bool_ *ulmo_draught_of_ulmonan_spell(int); -char *ulmo_draught_of_ulmonan_info(); -bool_ *ulmo_call_of_the_ulumuri_spell(int); -char *ulmo_call_of_the_ulumuri_info(); -bool_ *ulmo_wrath_of_ulmo_spell(int); -char *ulmo_wrath_of_ulmo_info(); +casting_result ulmo_song_of_belegaer_spell(int); +char *ulmo_song_of_belegaer_info(); +casting_result ulmo_draught_of_ulmonan_spell(int); +char *ulmo_draught_of_ulmonan_info(); +casting_result ulmo_call_of_the_ulumuri_spell(int); +char *ulmo_call_of_the_ulumuri_info(); +casting_result ulmo_wrath_of_ulmo_spell(int); +char *ulmo_wrath_of_ulmo_info(); extern s32b VARDA_LIGHT_VALINOR; extern s32b VARDA_CALL_ALMAREN; extern s32b VARDA_EVENSTAR; extern s32b VARDA_STARKINDLER; -bool_ *varda_light_of_valinor_spell(int); -char *varda_light_of_valinor_info(); -bool_ *varda_call_of_almaren_spell(int); -char *varda_call_of_almaren_info(); -bool_ *varda_evenstar_spell(int); -char *varda_evenstar_info(); -bool_ *varda_star_kindler_spell(int); -char *varda_star_kindler_info(); +casting_result varda_light_of_valinor_spell(int); +char *varda_light_of_valinor_info(); +casting_result varda_call_of_almaren_spell(int); +char *varda_call_of_almaren_info(); +casting_result varda_evenstar_spell(int); +char *varda_evenstar_info(); +casting_result varda_star_kindler_spell(int); +char *varda_star_kindler_info(); /* spells4.c */ diff --git a/src/spells.pkg b/src/spells.pkg index 0abf480c..d7564618 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -848,7 +848,7 @@ extern bool do_inc_stat(int stat); * Done by a potion of "self knowledge". * @note (see file spells2.c) */ -extern void identify_pack(void); +extern bool identify_pack(void); /** @fn remove_curse(void) * @brief Remove all curses except for heavy curses. diff --git a/src/spells2.c b/src/spells2.c index 4adab78a..634c69e0 100644 --- a/src/spells2.c +++ b/src/spells2.c @@ -348,7 +348,7 @@ bool_ do_inc_stat(int stat) * Identify everything being carried. * Done by a potion of "self knowledge". */ -void identify_pack(void) +bool_ identify_pack(void) { int i; @@ -370,6 +370,7 @@ void identify_pack(void) p_ptr->notice |= (PN_COMBINE | PN_REORDER); p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + return TRUE; } /* diff --git a/src/spells3.c b/src/spells3.c index 07a2527b..e6da0cf9 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -167,19 +167,35 @@ s32b VARDA_CALL_ALMAREN; s32b VARDA_EVENSTAR; s32b VARDA_STARKINDLER; -/* FIXME: Hackish workaround while we're still tied to Lua. This lets - us return Lua's "nil" and a non-nil value (which is all the s_aux.lua - cares about). */ -bool_ *NO_CAST = NULL; -bool_ CAST_VAL = 0xca; /* Any value will do */ -bool_ *CAST = &CAST_VAL; - s32b get_level_s(int sp, int max) { return get_level(sp, max, 1); } -bool_ *air_noxious_cloud(int item) +static casting_result cast(bool_ effect) +{ + return effect ? CAST_OBVIOUS : CAST_HIDDEN; +} + +static casting_result cplus(casting_result old, bool_ effect) +{ + if (old == NO_CAST) + { + return cast(effect); + } + else + { + if ((old == CAST_OBVIOUS) || (effect == TRUE)) { + return CAST_OBVIOUS; + } + else + { + return CAST_HIDDEN; + } + } +} + +casting_result air_noxious_cloud(int item) { int dir, type; @@ -198,7 +214,7 @@ bool_ *air_noxious_cloud(int item) } fire_cloud(type, dir, 7 + get_level_s(NOXIOUSCLOUD, 150), 3, 5 + get_level_s(NOXIOUSCLOUD, 40)); - return CAST; + return CAST_OBVIOUS; } char *air_noxious_cloud_info() @@ -211,23 +227,24 @@ char *air_noxious_cloud_info() return buf; } -bool_ *air_wings_of_winds(int item) +casting_result air_wings_of_winds(int item) { if (get_level_s(AIRWINGS, 50) >= 16) { if (p_ptr->tim_fly == 0) { - set_tim_fly(randint(10) + 5 + get_level_s(AIRWINGS, 25)); - return CAST; + return cast(set_tim_fly(randint(10) + 5 + get_level_s(AIRWINGS, 25))); } - else if (p_ptr->tim_ffall == 0) + } + else + { + if (p_ptr->tim_ffall == 0) { - set_tim_ffall(randint(10) + 5 + get_level_s(AIRWINGS, 25)); - return CAST; + return cast(set_tim_ffall(randint(10) + 5 + get_level_s(AIRWINGS, 25))); } } - return NO_CAST; + return CAST_HIDDEN; } char *air_wings_of_winds_info() @@ -237,15 +254,14 @@ char *air_wings_of_winds_info() return buf; } -bool_ *air_invisibility(int item) +casting_result air_invisibility(int item) { if (p_ptr->tim_invisible == 0) { - set_invis(randint(20) + 15 + get_level_s(INVISIBILITY, 50), 20 + get_level_s(INVISIBILITY, 50)); - return CAST; + return cast(set_invis(randint(20) + 15 + get_level_s(INVISIBILITY, 50), 20 + get_level_s(INVISIBILITY, 50))); } - return NO_CAST; + return CAST_HIDDEN; } char *air_invisibility_info() @@ -257,24 +273,22 @@ char *air_invisibility_info() return buf; } -bool_ *air_poison_blood(int item) +casting_result air_poison_blood(int item) { - bool_ *cast = NO_CAST; + casting_result result = NO_CAST; if (p_ptr->oppose_pois == 0) { - set_oppose_pois(randint(30) + 25 + get_level_s(POISONBLOOD, 25)); - cast = CAST; + result = cplus(result, set_oppose_pois(randint(30) + 25 + get_level_s(POISONBLOOD, 25))); } if ((p_ptr->tim_poison == 0) && (get_level_s(POISONBLOOD, 50) >= 15)) { - set_poison(randint(30) + 25 + get_level_s(POISONBLOOD, 25)); - cast = CAST; + result = cplus(result, set_poison(randint(30) + 25 + get_level_s(POISONBLOOD, 25))); } - return cast; + return result; } char *air_poison_blood_info() @@ -286,15 +300,14 @@ char *air_poison_blood_info() return buf; } -bool_ *air_thunderstorm(int item) +casting_result air_thunderstorm(int item) { if (p_ptr->tim_thunder == 0) { - set_tim_thunder(randint(10) + 10 + get_level_s(THUNDERSTORM, 25), 5 + get_level_s(THUNDERSTORM, 10), 10 + get_level_s(THUNDERSTORM, 25)); - return CAST; + return cast(set_tim_thunder(randint(10) + 10 + get_level_s(THUNDERSTORM, 25), 5 + get_level_s(THUNDERSTORM, 10), 10 + get_level_s(THUNDERSTORM, 25))); } - return NO_CAST; + return CAST_HIDDEN; } char *air_thunderstorm_info() @@ -308,10 +321,10 @@ char *air_thunderstorm_info() return buf; } -bool_ *air_sterilize(int item) +casting_result air_sterilize(int item) { set_no_breeders((30) + 20 + get_level_s(STERILIZE, 70)); - return CAST; + return CAST_OBVIOUS; } char *air_sterilize_info() @@ -323,7 +336,7 @@ char *air_sterilize_info() return buf; } -bool_ *convey_blink(int item) +casting_result convey_blink(int item) { if (get_level_s(BLINK, 50) >= 30) { @@ -332,12 +345,12 @@ bool_ *convey_blink(int item) teleport_player(10 + get_level_s(BLINK, 8)); create_between_gate(0, oy, ox); - return CAST; + return CAST_OBVIOUS; } else { teleport_player(10 + get_level_s(BLINK, 8)); - return CAST; + return CAST_OBVIOUS; } } @@ -350,15 +363,17 @@ char *convey_blink_info() return buf; } -bool_ *convey_disarm(int item) +casting_result convey_disarm(int item) { - destroy_doors_touch(); + casting_result result = NO_CAST; + + result = cplus(result, destroy_doors_touch()); if (get_level_s(DISARM, 50) >= 10) { - destroy_traps_touch(); + result = cplus(result, destroy_traps_touch()); } - return CAST; + return result; } char *convey_disarm_info() @@ -366,11 +381,11 @@ char *convey_disarm_info() return ""; } -bool_ *convey_teleport(int item) +casting_result convey_teleport(int item) { p_ptr->energy -= (25 - get_level_s(TELEPORT, 50)); teleport_player(100 + get_level_s(TELEPORT, 100)); - return CAST; + return CAST_OBVIOUS; } char *convey_teleport_info() @@ -382,12 +397,11 @@ char *convey_teleport_info() return buf; } -bool_ *convey_teleport_away(int item) +casting_result convey_teleport_away(int item) { if (get_level_s(TELEAWAY, 50) >= 20) { - project_hack(GF_AWAY_ALL, 100); - return CAST; + return cast(project_hack(GF_AWAY_ALL, 100)); } else if (get_level_s(TELEAWAY, 50) >= 10) { @@ -397,8 +411,7 @@ bool_ *convey_teleport_away(int item) return NO_CAST; } - fire_ball(GF_AWAY_ALL, dir, 100, 3 + get_level_s(TELEAWAY, 4)); - return CAST; + return cast(fire_ball(GF_AWAY_ALL, dir, 100, 3 + get_level_s(TELEAWAY, 4))); } else { @@ -407,8 +420,7 @@ bool_ *convey_teleport_away(int item) { return NO_CAST; } - teleport_monster(dir); - return CAST; + return cast(teleport_monster(dir)); } } @@ -437,7 +449,7 @@ static int recall_get_f() return f; } -bool_ *convey_recall(int item) +casting_result convey_recall(int item) { int x,y; cave_type *c_ptr; @@ -455,12 +467,12 @@ bool_ *convey_recall(int item) int d = recall_get_d(); int f = recall_get_f(); recall_player(d, f); - return CAST; + return CAST_OBVIOUS; } else if (c_ptr->m_idx > 0) { swap_position(y, x); - return CAST; + return CAST_OBVIOUS; } else if (c_ptr->o_idx > 0) { @@ -473,7 +485,7 @@ bool_ *convey_recall(int item) { fetch(5, 10 + get_level_s(RECALL, 150), TRUE); } - return CAST; + return CAST_OBVIOUS; } else { @@ -493,10 +505,9 @@ char *convey_recall_info() return buf; } -bool_ *convey_probability_travel(int item) +casting_result convey_probability_travel(int item) { - set_prob_travel(randint(20) + get_level_s(PROBABILITY_TRAVEL, 60)); - return CAST; + return cast(set_prob_travel(randint(20) + get_level_s(PROBABILITY_TRAVEL, 60))); } char *convey_probability_travel_info() @@ -508,7 +519,7 @@ char *convey_probability_travel_info() return buf; } -bool_ *demonology_demon_blade(int item) +casting_result demonology_demon_blade(int item) { int rad, type; @@ -524,12 +535,11 @@ bool_ *demonology_demon_blade(int item) rad = 1; } - set_project(randint(20) + get_level_s(DEMON_BLADE, 80), - type, - 4 + get_level_s(DEMON_BLADE, 40), - rad, - PROJECT_STOP | PROJECT_KILL); - return CAST; + return cast(set_project(randint(20) + get_level_s(DEMON_BLADE, 80), + type, + 4 + get_level_s(DEMON_BLADE, 40), + rad, + PROJECT_STOP | PROJECT_KILL)); } char *demonology_demon_blade_info() @@ -542,8 +552,9 @@ char *demonology_demon_blade_info() return buf; } -bool_ *demonology_demon_madness(int item) +casting_result demonology_demon_madness(int item) { + casting_result result = NO_CAST; int dir, type, y1, x1, y2, x2; if (!get_aim_dir(&dir)) @@ -566,18 +577,20 @@ bool_ *demonology_demon_madness(int item) y2 = p_ptr->py - (y1 - p_ptr->py); x2 = p_ptr->px - (x1 - p_ptr->px); - project(0, 1 + get_level(DEMON_MADNESS, 4, 0), - y1, x1, - 20 + get_level_s(DEMON_MADNESS, 200), - type, - PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL); - project(0, 1 + get_level(DEMON_MADNESS, 4, 0), - y2, x2, - 20 + get_level_s(DEMON_MADNESS, 200), - type, - PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL); + result = cplus(result, + project(0, 1 + get_level(DEMON_MADNESS, 4, 0), + y1, x1, + 20 + get_level_s(DEMON_MADNESS, 200), + type, + PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL)); + result = cplus(result, + project(0, 1 + get_level(DEMON_MADNESS, 4, 0), + y2, x2, + 20 + get_level_s(DEMON_MADNESS, 200), + type, + PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL)); - return CAST; + return result; } char *demonology_demon_madness_info() @@ -590,7 +603,7 @@ char *demonology_demon_madness_info() return buf; } -bool_ *demonology_demon_field(int item) +casting_result demonology_demon_field(int item) { int dir; @@ -599,12 +612,11 @@ bool_ *demonology_demon_field(int item) return NO_CAST; } - fire_cloud(GF_NEXUS, - dir, - 20 + get_level_s(DEMON_FIELD, 70), - 7, - 30 + get_level_s(DEMON_FIELD, 100)); - return CAST; + return cast(fire_cloud(GF_NEXUS, + dir, + 20 + get_level_s(DEMON_FIELD, 70), + 7, + 30 + get_level_s(DEMON_FIELD, 100))); } char *demonology_demon_field_info() @@ -617,14 +629,13 @@ char *demonology_demon_field_info() return buf; } -bool_ *demonology_doom_shield(int item) +casting_result demonology_doom_shield(int item) { - set_shield(randint(10) + 20 + get_level_s(DOOM_SHIELD, 100), - -300 + get_level_s(DOOM_SHIELD, 100), - SHIELD_COUNTER, - 1 + get_level_s(DOOM_SHIELD, 14), - 10 + get_level_s(DOOM_SHIELD, 15)); - return CAST; + return cast(set_shield(randint(10) + 20 + get_level_s(DOOM_SHIELD, 100), + -300 + get_level_s(DOOM_SHIELD, 100), + SHIELD_COUNTER, + 1 + get_level_s(DOOM_SHIELD, 14), + 10 + get_level_s(DOOM_SHIELD, 15))); } char *demonology_doom_shield_info() @@ -638,7 +649,7 @@ char *demonology_doom_shield_info() return buf; } -bool_ *demonology_unholy_word(int item) +casting_result demonology_unholy_word(int item) { int x, y; cave_type *c_ptr = NULL; @@ -687,7 +698,7 @@ bool_ *demonology_unholy_word(int item) delete_monster_idx(c_ptr->m_idx); } - return CAST; + return CAST_OBVIOUS; } else { @@ -704,10 +715,9 @@ char *demonology_unholy_word_info() return buf; } -bool_ *demonology_demon_cloak(int item) +casting_result demonology_demon_cloak(int item) { - set_tim_reflect(randint(5) + 5 + get_level(DEMON_CLOAK, 15, 0)); - return CAST; + return cast(set_tim_reflect(randint(5) + 5 + get_level(DEMON_CLOAK, 15, 0))); } char *demonology_demon_cloak_info() @@ -719,7 +729,7 @@ char *demonology_demon_cloak_info() return buf; } -bool_ *demonology_summon_demon(int item) +casting_result demonology_summon_demon(int item) { int type, level, minlevel; @@ -739,12 +749,15 @@ bool_ *demonology_summon_demon(int item) type = SUMMON_HI_DEMON; } - if (!summon_specific_friendly(p_ptr->py, p_ptr->px, level, type, TRUE)) + if (summon_specific_friendly(p_ptr->py, p_ptr->px, level, type, TRUE)) + { + return CAST_OBVIOUS; + } + else { msg_print("Something blocks your summoning!"); + return CAST_HIDDEN; } - - return CAST; } char *demonology_summon_demon_info() @@ -756,7 +769,7 @@ char *demonology_summon_demon_info() return buf; } -bool_ *demonology_discharge_minion(int item) +casting_result demonology_discharge_minion(int item) { cave_type *c_ptr; int x, y; @@ -788,10 +801,9 @@ bool_ *demonology_discharge_minion(int item) } /* We use project instead of fire_ball because we must tell it exactly where to land */ - project(0, 2, y, x, dam, - GF_GRAVITY, - PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL); - return CAST; + return cast(project(0, 2, y, x, dam, + GF_GRAVITY, + PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL)); } else { @@ -809,7 +821,7 @@ char *demonology_discharge_minion_info() return buf; } -bool_ *demonology_control_demon(int item) +casting_result demonology_control_demon(int item) { int dir; if (!get_aim_dir(&dir)) @@ -817,8 +829,7 @@ bool_ *demonology_control_demon(int item) return NO_CAST; } - fire_ball(GF_CONTROL_DEMON, dir, 50 + get_level_s(CONTROL_DEMON, 250), 0); - return CAST; + return cast(fire_ball(GF_CONTROL_DEMON, dir, 50 + get_level_s(CONTROL_DEMON, 250), 0)); } char *demonology_control_demon_info() @@ -830,7 +841,7 @@ char *demonology_control_demon_info() return buf; } -bool_ *divination_greater_identify(int item) +casting_result divination_greater_identify(int item) { if (get_check("Cast on yourself?")) { @@ -840,7 +851,7 @@ bool_ *divination_greater_identify(int item) { identify_fully(); } - return CAST; + return CAST_OBVIOUS; } char *divination_greater_identify_info() @@ -848,25 +859,25 @@ char *divination_greater_identify_info() return ""; } -bool_ *divination_identify(int item) +casting_result divination_identify(int item) { if (get_level_s(IDENTIFY, 50) >= 27) { - identify_pack(); - fire_ball(GF_IDENTIFY, 0, 1, get_level_s(IDENTIFY, 3)); - p_ptr->notice |= (PN_COMBINE | PN_REORDER); - return CAST; + casting_result result = NO_CAST; + result = cplus(result, identify_pack()); + result = cplus(result, fire_ball(GF_IDENTIFY, 0, 1, get_level_s(IDENTIFY, 3))); + return result; } else if (get_level_s(IDENTIFY, 50) >= 17) { - identify_pack(); - fire_ball(GF_IDENTIFY, 0, 1, 0); - p_ptr->notice |= (PN_COMBINE | PN_REORDER); - return CAST; + casting_result result = NO_CAST; + result = cplus(result, identify_pack()); + result = cplus(result, fire_ball(GF_IDENTIFY, 0, 1, 0)); + return result; } - else if (ident_spell() == TRUE) + else if (ident_spell()) { - return CAST; + return CAST_OBVIOUS; } else { @@ -889,7 +900,7 @@ char *divination_identify_info() } } -bool_ *divination_vision(int item) +casting_result divination_vision(int item) { if (get_level_s(VISION, 50) >= 25) { @@ -899,7 +910,7 @@ bool_ *divination_vision(int item) { map_area(); } - return CAST; + return CAST_OBVIOUS; } @@ -908,14 +919,17 @@ char *divination_vision_info() return ""; } -bool_ *divination_sense_hidden(int item) +casting_result divination_sense_hidden(int item) { - detect_traps(15 + get_level(SENSEHIDDEN, 40, 0)); + casting_result result = NO_CAST; + + result = cplus(result, detect_traps(15 + get_level(SENSEHIDDEN, 40, 0))); if (get_level_s(SENSEHIDDEN, 50) >= 15) { - set_tim_invis(10 + randint(20) + get_level_s(SENSEHIDDEN, 40)); + result = cplus(result, set_tim_invis(10 + randint(20) + get_level_s(SENSEHIDDEN, 40))); } - return CAST; + + return result; } char *divination_sense_hidden_info() @@ -939,11 +953,12 @@ char *divination_sense_hidden_info() return buf; } -bool_ *divination_reveal_ways(int item) +casting_result divination_reveal_ways(int item) { - detect_doors(10 + get_level(REVEALWAYS, 40, 0)); - detect_stairs(10 + get_level(REVEALWAYS, 40, 0)); - return CAST; + casting_result result = NO_CAST; + result = cplus(result, detect_doors(10 + get_level(REVEALWAYS, 40, 0))); + result = cplus(result, detect_stairs(10 + get_level(REVEALWAYS, 40, 0))); + return result; } char *divination_reveal_ways_info() @@ -955,14 +970,16 @@ char *divination_reveal_ways_info() return buf; } -bool_ *divination_sense_monsters(int item) +casting_result divination_sense_monsters(int item) { - detect_monsters_normal(10 + get_level(SENSEMONSTERS, 40, 0)); + casting_result result = NO_CAST; + + result = cplus(result, detect_monsters_normal(10 + get_level(SENSEMONSTERS, 40, 0))); if (get_level_s(SENSEMONSTERS, 50) >= 30) { - set_tim_esp(10 + randint(10) + get_level_s(SENSEMONSTERS, 20)); + result = cplus(result, set_tim_esp(10 + randint(10) + get_level_s(SENSEMONSTERS, 20))); } - return CAST; + return result; } char *divination_sense_monsters_info() @@ -986,7 +1003,7 @@ char *divination_sense_monsters_info() return buf; } -bool_ *earth_stone_skin(int item) +casting_result earth_stone_skin(int item) { int type; @@ -996,12 +1013,11 @@ bool_ *earth_stone_skin(int item) type = SHIELD_COUNTER; } - set_shield(randint(10) + 10 + get_level_s(STONESKIN, 100), - 10 + get_level_s(STONESKIN, 50), - type, - 2 + get_level_s(STONESKIN, 5), - 3 + get_level_s(STONESKIN, 5)); - return CAST; + return cast(set_shield(randint(10) + 10 + get_level_s(STONESKIN, 100), + 10 + get_level_s(STONESKIN, 50), + type, + 2 + get_level_s(STONESKIN, 5), + 3 + get_level_s(STONESKIN, 5))); } char *earth_stone_skin_info() @@ -1028,7 +1044,7 @@ char *earth_stone_skin_info() return buf; } -bool_ *earth_dig(int item) +casting_result earth_dig(int item) { int dir; if (!get_aim_dir(&dir)) @@ -1036,8 +1052,7 @@ bool_ *earth_dig(int item) return NO_CAST; } - wall_to_mud(dir); - return CAST; + return cast(wall_to_mud(dir)); } char *earth_dig_info() @@ -1045,7 +1060,7 @@ char *earth_dig_info() return ""; } -bool_ *earth_stone_prison(int item) +casting_result earth_stone_prison(int item) { int x,y; @@ -1063,7 +1078,7 @@ bool_ *earth_stone_prison(int item) } wall_stone(y, x); - return CAST; + return CAST_OBVIOUS; } char *earth_stone_prison_info() @@ -1071,7 +1086,7 @@ char *earth_stone_prison_info() return ""; } -bool_ *earth_strike(int item) +casting_result earth_strike(int item) { int dir, dmg; @@ -1083,14 +1098,12 @@ bool_ *earth_strike(int item) dmg = 50 + get_level_s(STRIKE, 50); if (get_level_s(STRIKE, 50) >= 12) { - fire_ball(GF_FORCE, dir, dmg, 1); + return cast(fire_ball(GF_FORCE, dir, dmg, 1)); } else { - fire_ball(GF_FORCE, dir, dmg, 0); + return cast(fire_ball(GF_FORCE, dir, dmg, 0)); } - - return CAST; } char *earth_strike_info() @@ -1110,7 +1123,7 @@ char *earth_strike_info() return buf; } -bool_ *earth_shake(int item) +casting_result earth_shake(int item) { int x,y; @@ -1127,7 +1140,7 @@ bool_ *earth_shake(int item) y = p_ptr->py; } earthquake(y, x, 4 + get_level_s(SHAKE, 10)); - return CAST; + return CAST_OBVIOUS; } char *earth_shake_info() @@ -1137,25 +1150,29 @@ char *earth_shake_info() return buf; } -bool_ *eru_see_the_music(int item) +casting_result eru_see_the_music(int item) { - set_tim_invis(randint(20) + 10 + get_level_s(ERU_SEE, 100)); + casting_result result = NO_CAST; + + result = cplus(result, set_tim_invis(randint(20) + 10 + get_level_s(ERU_SEE, 100))); if (get_level_s(ERU_SEE, 50) >= 30) { wiz_lite_extra(); + result = CAST_OBVIOUS; } else if (get_level_s(ERU_SEE, 50) >= 10) { map_area(); + result = CAST_OBVIOUS; } if (get_level_s(ERU_SEE, 50) >= 20) { - set_blind(0); + result = cplus(result, set_blind(0)); } - return CAST; + return result; } char *eru_see_the_music_info() @@ -1167,22 +1184,25 @@ char *eru_see_the_music_info() return buf; } -bool_ *eru_listen_to_the_music(int item) +casting_result eru_listen_to_the_music(int item) { + casting_result result = NO_CAST; + if (get_level_s(ERU_LISTEN, 50) >= 30) { - ident_all(); - identify_pack(); + result = cplus(result, ident_all()); + result = cplus(result, identify_pack()); } else if (get_level_s(ERU_LISTEN, 50) >= 14) { - identify_pack(); + result = cplus(result, identify_pack()); } else { - ident_spell(); + result = cplus(result, ident_spell()); } - return CAST; + + return result; } char *eru_listen_to_the_music_info() @@ -1190,17 +1210,17 @@ char *eru_listen_to_the_music_info() return ""; } -bool_ *eru_know_the_music(int item) +casting_result eru_know_the_music(int item) { if (get_level_s(ERU_UNDERSTAND, 50) >= 10) { identify_pack_fully(); + return CAST_OBVIOUS; } else { - identify_fully(); + return cast(identify_fully()); } - return CAST; } char *eru_know_the_music_info() @@ -1208,10 +1228,9 @@ char *eru_know_the_music_info() return ""; } -bool_ *eru_lay_of_protection(int item) +casting_result eru_lay_of_protection(int item) { - fire_ball(GF_MAKE_GLYPH, 0, 1, 1 + get_level(ERU_PROT, 2, 0)); - return CAST; + return cast(fire_ball(GF_MAKE_GLYPH, 0, 1, 1 + get_level(ERU_PROT, 2, 0))); } char *eru_lay_of_protection_info() @@ -1223,26 +1242,31 @@ char *eru_lay_of_protection_info() return buf; } -bool_ *fire_globe_of_light(int item) +casting_result fire_globe_of_light(int item) { + casting_result result = NO_CAST; + if (get_level_s(GLOBELIGHT, 50) >= 3) { - lite_area(10, 4); + result = cplus(result, lite_area(10, 4)); } else { lite_room(p_ptr->py, p_ptr->px); + result = CAST_OBVIOUS; } if (get_level_s(GLOBELIGHT, 50) >= 15) { - fire_ball(GF_LITE, - 0, - 10 + get_level_s(GLOBELIGHT, 100), - 5 + get_level_s(GLOBELIGHT, 6)); + result = cplus(result, + fire_ball(GF_LITE, + 0, + 10 + get_level_s(GLOBELIGHT, 100), + 5 + get_level_s(GLOBELIGHT, 6))); p_ptr->update |= PU_VIEW; } - return CAST; + + return result; } char *fire_globe_of_light_info() @@ -1263,7 +1287,7 @@ char *fire_globe_of_light_info() return buf; } -bool_ *fire_fireflash(int item) +casting_result fire_fireflash(int item) { int dir; int type = GF_FIRE; @@ -1278,10 +1302,9 @@ bool_ *fire_fireflash(int item) return NO_CAST; } - fire_ball(type, dir, - 20 + get_level_s(FIREFLASH, 500), - 2 + get_level_s(FIREFLASH, 5)); - return CAST; + return cast(fire_ball(type, dir, + 20 + get_level_s(FIREFLASH, 500), + 2 + get_level_s(FIREFLASH, 5))); } char *fire_fireflash_info() @@ -1294,7 +1317,7 @@ char *fire_fireflash_info() return buf; } -bool_ *fire_fiery_shield(int item) +casting_result fire_fiery_shield(int item) { int type = SHIELD_FIRE; if (get_level_s(FIERYAURA, 50) >= 8) @@ -1302,12 +1325,11 @@ bool_ *fire_fiery_shield(int item) type = SHIELD_GREAT_FIRE; } - set_shield(randint(20) + 10 + get_level_s(FIERYAURA, 70), - 10, - type, - 5 + get_level_s(FIERYAURA, 10), - 5 + get_level_s(FIERYAURA, 7)); - return CAST; + return cast(set_shield(randint(20) + 10 + get_level_s(FIERYAURA, 70), + 10, + type, + 5 + get_level_s(FIERYAURA, 10), + 5 + get_level_s(FIERYAURA, 7))); } char *fire_fiery_shield_info() @@ -1321,7 +1343,7 @@ char *fire_fiery_shield_info() return buf; } -bool_ *fire_firewall(int item) +casting_result fire_firewall(int item) { int dir; int type = GF_FIRE; @@ -1338,7 +1360,7 @@ bool_ *fire_firewall(int item) fire_wall(type, dir, 40 + get_level_s(FIREWALL, 150), 10 + get_level_s(FIREWALL, 14)); - return CAST; + return CAST_OBVIOUS; } char *fire_firewall_info() @@ -1358,7 +1380,7 @@ bool_ item_tester_hook_fire_golem(object_type *o_ptr) (o_ptr->sval == SV_LITE_LANTERN))); } -bool_ *fire_golem(int ignored) +casting_result fire_golem(int ignored) { int item, x, y, m_idx; @@ -1395,7 +1417,7 @@ bool_ *fire_golem(int ignored) m_list[m_idx].mflag |= MFLAG_CONTROL; } - return CAST; + return CAST_OBVIOUS; } char *fire_golem_info() @@ -1407,7 +1429,7 @@ char *fire_golem_info() return buf; } -bool_ *geomancy_call_the_elements(int item) +casting_result geomancy_call_the_elements(int item) { int dir = 0; @@ -1415,7 +1437,7 @@ bool_ *geomancy_call_the_elements(int item) { if (!get_aim_dir(&dir)) { - return FALSE; + return NO_CAST; } } @@ -1424,7 +1446,7 @@ bool_ *geomancy_call_the_elements(int item) 1, 1 + get_level(CALL_THE_ELEMENTS, 5, 0)); - return CAST; + return CAST_OBVIOUS; } char *geomancy_call_the_elements_info() @@ -1436,10 +1458,10 @@ char *geomancy_call_the_elements_info() return buf; } -bool_ *geomancy_channel_elements(int item) +casting_result geomancy_channel_elements(int item) { channel_the_elements(p_ptr->py, p_ptr->px, get_level_s(CHANNEL_ELEMENTS, 50)); - return CAST; + return CAST_OBVIOUS; } char *geomancy_channel_elements_info() @@ -1469,7 +1491,7 @@ static eff_type *geomancy_find_effect(eff_type effs[], int feat) return NULL; } -bool_ *geomancy_elemental_wave(int item) +casting_result geomancy_elemental_wave(int item) { int dir = 0, y = 0, x = 0; eff_type *eff_ptr = NULL; @@ -1493,7 +1515,7 @@ bool_ *geomancy_elemental_wave(int item) if (!get_rep_dir(&dir)) { - return FALSE; + return NO_CAST; } y = ddy[dir] + p_ptr->py; @@ -1529,7 +1551,7 @@ bool_ *geomancy_elemental_wave(int item) 6 + get_level_s(ELEMENTAL_WAVE, 20), EFF_WAVE + EFF_LAST + EFF_DIR); - return CAST; + return CAST_OBVIOUS; } } @@ -1538,7 +1560,7 @@ char *geomancy_elemental_wave_info() return ""; } -bool_ *geomancy_vaporize(int item) +casting_result geomancy_vaporize(int item) { eff_type *eff_ptr = NULL; eff_type t[] = { @@ -1580,7 +1602,7 @@ bool_ *geomancy_vaporize(int item) 1 + get_level_s(VAPORIZE, 4), 10 + get_level_s(VAPORIZE, 20)); - return CAST; + return CAST_OBVIOUS; } } @@ -1599,7 +1621,7 @@ bool_ geomancy_vaporize_depends() return get_skill(SKILL_AIR) >= 4; } -bool_ *geomancy_geolysis(int item) +casting_result geomancy_geolysis(int item) { int dir = 0; @@ -1611,7 +1633,7 @@ bool_ *geomancy_geolysis(int item) msg_print("Elements recombine before you, laying down an open path."); geomancy_dig(p_ptr->py, p_ptr->px, dir, 5 + get_level_s(GEOLYSIS, 12)); - return CAST; + return CAST_OBVIOUS; } char *geomancy_geolysis_info() @@ -1628,7 +1650,7 @@ bool_ geomancy_geolysis_depends() return get_skill(SKILL_EARTH) >= 7; } -bool_ *geomancy_dripping_tread(int item) +casting_result geomancy_dripping_tread(int item) { if (p_ptr->dripping_tread == 0) { @@ -1641,7 +1663,7 @@ bool_ *geomancy_dripping_tread(int item) msg_print("You stop dripping raw elemental energies."); } - return CAST; + return CAST_OBVIOUS; } char *geomancy_dripping_tread_info() @@ -1658,7 +1680,7 @@ bool_ geomancy_dripping_tread_depends() return get_skill(SKILL_WATER) >= 10; } -bool_ *geomancy_grow_barrier(int item) +casting_result geomancy_grow_barrier(int item) { int dir = 0; @@ -1666,12 +1688,12 @@ bool_ *geomancy_grow_barrier(int item) { if (!get_aim_dir(&dir)) { - return FALSE; + return NO_CAST; } } fire_ball(GF_ELEMENTAL_WALL, dir, 1, 1); - return CAST; + return CAST_OBVIOUS; } char *geomancy_grow_barrier_info() @@ -1714,7 +1736,7 @@ int geomancy_count_elements(cptr *elements) return i; } -bool_ *geomancy_elemental_minion(int item) +casting_result geomancy_elemental_minion(int item) { int dir = 0; int x = 0, y = 0; @@ -1805,7 +1827,7 @@ bool_ *geomancy_elemental_minion(int item) cave_set_feat(y, x, FEAT_FLOOR); - return CAST; + return CAST_OBVIOUS; } } @@ -1824,7 +1846,7 @@ static void get_manathrust_dam(s16b *num, s16b *sides) *sides = 1 + get_level_s(MANATHRUST, 20); } -bool_ *mana_manathrust(int item) +casting_result mana_manathrust(int item) { int dir; s16b num = 0; @@ -1836,8 +1858,7 @@ bool_ *mana_manathrust(int item) } get_manathrust_dam(&num, &sides); - fire_bolt(GF_MANA, dir, damroll(num, sides)); - return CAST; + return cast(fire_bolt(GF_MANA, dir, damroll(num, sides))); } char *mana_manathrust_info() @@ -1854,25 +1875,25 @@ char *mana_manathrust_info() return buf; } -bool_ *mana_remove_curses(int item) +casting_result mana_remove_curses(int item) { - bool_ done = FALSE; + casting_result result = NO_CAST; if (get_level_s(DELCURSES, 50) >= 20) { - done = remove_all_curse(); + result = cplus(result, remove_all_curse()); } else { - done = remove_curse(); + result = cplus(result, remove_curse()); } - if (done) + if (result == CAST_OBVIOUS) { msg_print("The curse is broken!"); } - return CAST; + return result; } char *mana_remove_curses_info() @@ -1880,32 +1901,28 @@ char *mana_remove_curses_info() return ""; } -bool_ *mana_elemental_shield(int item) +casting_result mana_elemental_shield(int item) { - bool_ *res = NO_CAST; + casting_result res = NO_CAST; if (p_ptr->oppose_fire == 0) { - set_oppose_fire(randint(10) + 15 + get_level_s(RESISTS, 50)); - res = CAST; + res = cplus(res, set_oppose_fire(randint(10) + 15 + get_level_s(RESISTS, 50))); } if (p_ptr->oppose_cold == 0) { - set_oppose_cold(randint(10) + 15 + get_level_s(RESISTS, 50)); - res = CAST; + res = cplus(res, set_oppose_cold(randint(10) + 15 + get_level_s(RESISTS, 50))); } if (p_ptr->oppose_elec == 0) { - set_oppose_elec(randint(10) + 15 + get_level_s(RESISTS, 50)); - res = CAST; + res = cplus(res, set_oppose_elec(randint(10) + 15 + get_level_s(RESISTS, 50))); } if (p_ptr->oppose_acid == 0) { - set_oppose_acid(randint(10) + 15 + get_level_s(RESISTS, 50)); - res = CAST; + res = cplus(res, set_oppose_acid(randint(10) + 15 + get_level_s(RESISTS, 50))); } return res; @@ -1920,20 +1937,18 @@ char *mana_elemental_shield_info() return buf; } -bool_ *mana_disruption_shield(int item) +casting_result mana_disruption_shield(int item) { if (get_level_s(MANASHIELD, 50) >= 5) { if (p_ptr->invuln == 0) { - set_invuln(randint(5) + 3 + get_level_s(MANASHIELD, 10)); - return CAST; + return cast(set_invuln(randint(5) + 3 + get_level_s(MANASHIELD, 10))); } } else if (p_ptr->disrupt_shield == 0) { - set_disrupt_shield(randint(5) + 3 + get_level_s(MANASHIELD, 10)); - return CAST; + return cast(set_disrupt_shield(randint(5) + 3 + get_level_s(MANASHIELD, 10))); } return NO_CAST; @@ -1948,11 +1963,13 @@ char *mana_disruption_shield_info() return buf; } -bool_ *manwe_wind_shield(int item) +casting_result manwe_wind_shield(int item) { + casting_result res = NO_CAST; s32b dur = get_level_s(MANWE_SHIELD, 50) + 10 + randint(20); - set_protevil(dur); + res = cplus(res, set_protevil(dur)); + if (get_level_s(MANWE_SHIELD, 50) >= 10) { int type = 0; @@ -1961,14 +1978,15 @@ bool_ *manwe_wind_shield(int item) type = SHIELD_COUNTER; } - set_shield(dur, - get_level_s(MANWE_SHIELD, 30), - type, - 1 + get_level_s(MANWE_SHIELD, 2), - 1 + get_level_s(MANWE_SHIELD, 6)); + res = cplus(res, + set_shield(dur, + get_level_s(MANWE_SHIELD, 30), + type, + 1 + get_level_s(MANWE_SHIELD, 2), + 1 + get_level_s(MANWE_SHIELD, 6))); } - return CAST; + return res; } char *manwe_wind_shield_info() @@ -1998,15 +2016,14 @@ char *manwe_wind_shield_info() return buf; } -bool_ *manwe_avatar(int item) +casting_result manwe_avatar(int item) { s16b mimic_idx = resolve_mimic_name("Maia"); assert(mimic_idx >= 0); - set_mimic(get_level_s(MANWE_AVATAR, 20) + randint(10), - mimic_idx, - p_ptr->lev); - return CAST; + return cast(set_mimic(get_level_s(MANWE_AVATAR, 20) + randint(10), + mimic_idx, + p_ptr->lev)); } char *manwe_avatar_info() @@ -2018,28 +2035,29 @@ char *manwe_avatar_info() return buf; } -bool_ *manwe_blessing(int item) +casting_result manwe_blessing(int item) { + casting_result res = NO_CAST; s32b dur = get_level_s(MANWE_BLESS, 70) + 30 + randint(40); - set_blessed(dur); - set_afraid(0); - set_lite(0); + res = cplus(res, set_blessed(dur)); + res = cplus(res, set_afraid(0)); + res = cplus(res, set_lite(0)); if (get_level_s(MANWE_BLESS, 50) >= 10) { - set_hero(dur); + res = cplus(res, set_hero(dur)); } if (get_level_s(MANWE_BLESS, 50) >= 20) { - set_shero(dur); + res = cplus(res, set_shero(dur)); } if (get_level_s(MANWE_BLESS, 50) >= 30) { - set_holy(dur); + res = cplus(res, set_holy(dur)); } - return CAST; + return res; } char *manwe_blessing_info() @@ -2051,7 +2069,7 @@ char *manwe_blessing_info() return buf; } -bool_ *manwe_call(int item) +casting_result manwe_call(int item) { int y = 0, x = 0, m_idx = -1, r_idx = -1; @@ -2065,7 +2083,7 @@ bool_ *manwe_call(int item) if (m_idx > 0) { monster_set_level(m_idx, 20 + get_level(MANWE_CALL, 70, 0)); - return CAST; + return CAST_OBVIOUS; } return NO_CAST; @@ -2170,7 +2188,7 @@ void do_melkor_curse(int m_idx) m_ptr->csleep = 0; } -bool_ *melkor_curse(int item) +casting_result melkor_curse(int item) { int dir = 0; @@ -2187,7 +2205,7 @@ bool_ *melkor_curse(int item) else { do_melkor_curse(target_who); - return CAST; + return CAST_OBVIOUS; } } @@ -2196,13 +2214,12 @@ char *melkor_curse_info() return ""; } -bool_ *melkor_corpse_explosion(int item) +casting_result melkor_corpse_explosion(int item) { - fire_ball(GF_CORPSE_EXPL, - 0, - 20 + get_level_s(MELKOR_CORPSE_EXPLOSION, 70), - 2 + get_level_s(MELKOR_CORPSE_EXPLOSION, 5)); - return CAST; + return cast(fire_ball(GF_CORPSE_EXPL, + 0, + 20 + get_level_s(MELKOR_CORPSE_EXPLOSION, 70), + 2 + get_level_s(MELKOR_CORPSE_EXPLOSION, 5))); } char *melkor_corpse_explosion_info() @@ -2214,13 +2231,13 @@ char *melkor_corpse_explosion_info() return buf; } -bool_ *melkor_mind_steal(int item) +casting_result melkor_mind_steal(int item) { int dir = 0; if (!get_aim_dir(&dir)) { - return FALSE; + return NO_CAST; } if (target_who < 0) @@ -2251,7 +2268,7 @@ bool_ *melkor_mind_steal(int item) } msg_print(buf); - return CAST; + return CAST_OBVIOUS; } } @@ -2264,10 +2281,9 @@ char *melkor_mind_steal_info() return buf; } -bool_ *meta_recharge(int item) +casting_result meta_recharge(int item) { - recharge(60 + get_level_s(RECHARGE, 140)); - return CAST; + return cast(recharge(60 + get_level_s(RECHARGE, 140))); } char *meta_recharge_info() @@ -2289,7 +2305,7 @@ static int get_spellbinder_max() return i; } -bool_ *meta_spellbinder(int item) +casting_result meta_spellbinder(int item) { if (p_ptr->spellbinder_num != 0) { @@ -2363,12 +2379,12 @@ bool_ *meta_spellbinder(int item) { p_ptr->spellbinder_trigger = 0; p_ptr->spellbinder_num = 0; - return CAST; + return CAST_OBVIOUS; } else { if (school_spells[s].skill_level > 7 + get_level_s(SPELLBINDER, 35)) { msg_format("You are only allowed spells with a base level of " FMTs32b ".", (7 + get_level_s(SPELLBINDER, 35))); - return CAST; + return CAST_OBVIOUS; } } @@ -2378,7 +2394,7 @@ bool_ *meta_spellbinder(int item) p_ptr->energy = p_ptr->energy - 3100; msg_print("Spellbinder ready."); - return CAST; + return CAST_OBVIOUS; } } @@ -2392,38 +2408,40 @@ char *meta_spellbinder_info() return buf; } -bool_ *meta_disperse_magic(int item) +casting_result meta_disperse_magic(int item) { - set_blind(0); - set_lite(0); + casting_result res = NO_CAST; + + res = cplus(res, set_blind(0)); + res = cplus(res, set_lite(0)); if (get_level_s(DISPERSEMAGIC, 50) >= 5) { - set_confused(0); - set_image(0); + res = cplus(res, set_confused(0)); + res = cplus(res, set_image(0)); } if (get_level_s(DISPERSEMAGIC, 50) >= 10) { - set_slow(0); - set_fast(0, 0); - set_light_speed(0); + res = cplus(res, set_slow(0)); + res = cplus(res, set_fast(0, 0)); + res = cplus(res, set_light_speed(0)); } if (get_level_s(DISPERSEMAGIC, 50) >= 15) { - set_stun(0); - set_meditation(0); - set_cut(0); + res = cplus(res, set_stun(0)); + res = cplus(res, set_meditation(0)); + res = cplus(res, set_cut(0)); } if (get_level_s(DISPERSEMAGIC, 50) >= 20) { - set_hero(0); - set_shero(0); - set_blessed(0); - set_shield(0, 0, 0, 0, 0); - set_afraid(0); - set_parasite(0, 0); - set_mimic(0, 0, 0); + res = cplus(res, set_hero(0)); + res = cplus(res, set_shero(0)); + res = cplus(res, set_blessed(0)); + res = cplus(res, set_shield(0, 0, 0, 0, 0)); + res = cplus(res, set_afraid(0)); + res = cplus(res, set_parasite(0, 0)); + res = cplus(res, set_mimic(0, 0, 0)); } - return CAST; + return res; } char *meta_disperse_magic_info() @@ -2431,7 +2449,7 @@ char *meta_disperse_magic_info() return ""; } -bool_ *meta_tracker(int item) +casting_result meta_tracker(int item) { if ((last_teleportation_y < 0) || (last_teleportation_x < 0)) @@ -2442,7 +2460,7 @@ bool_ *meta_tracker(int item) { teleport_player_to(last_teleportation_y, last_teleportation_x); } - return CAST; + return CAST_OBVIOUS; } char *meta_tracker_info() @@ -2464,7 +2482,7 @@ void meta_inertia_control_hook_birth_objects() stop_inertia_controlled_spell(); } -bool_ *meta_inertia_control(int item) +casting_result meta_inertia_control(int item) { s32b s; spell_type *spell; @@ -2506,7 +2524,7 @@ bool_ *meta_inertia_control(int item) TIMER_INERTIA_CONTROL->countdown = TIMER_INERTIA_CONTROL->delay; p_ptr->update |= PU_MANA; msg_format("Inertia flow controlling spell %s.", school_spells[s].name); - return CAST; + return CAST_OBVIOUS; } char *meta_inertia_control_info() @@ -2553,14 +2571,14 @@ static int mind_charm_power() return 10 + get_level_s(CHARM, 150); } -bool_ *mind_charm(int item) +casting_result mind_charm(int item) { int pwr = mind_charm_power(); int level = get_level_s(CHARM, 50); if (level >= 35) { - project_hack(GF_CHARM, pwr); + return cast(project_hack(GF_CHARM, pwr)); } else { @@ -2572,15 +2590,13 @@ bool_ *mind_charm(int item) if (level >= 15) { - fire_ball(GF_CHARM, dir, pwr, 3); + return cast(fire_ball(GF_CHARM, dir, pwr, 3)); } else { - fire_bolt(GF_CHARM, dir, pwr); + return cast(fire_bolt(GF_CHARM, dir, pwr)); } } - - return CAST; } char *mind_charm_info() @@ -2597,14 +2613,14 @@ static int mind_confuse_power() return 10 + get_level_s(CONFUSE, 150); } -bool_ *mind_confuse(int item) +casting_result mind_confuse(int item) { int pwr = mind_confuse_power(); int level = get_level_s(CONFUSE, 50); if (level >= 35) { - project_hack(GF_OLD_CONF, pwr); + return cast(project_hack(GF_OLD_CONF, pwr)); } else { @@ -2616,15 +2632,13 @@ bool_ *mind_confuse(int item) if (level >= 15) { - fire_ball(GF_OLD_CONF, dir, pwr, 3); + return cast(fire_ball(GF_OLD_CONF, dir, pwr, 3)); } else { - fire_bolt(GF_OLD_CONF, dir, pwr); + return cast(fire_bolt(GF_OLD_CONF, dir, pwr)); } } - - return CAST; } char *mind_confuse_info() @@ -2651,14 +2665,13 @@ static int mind_armor_of_fear_power_dice() return 5 + get_level_s(ARMOROFFEAR, 20); } -bool_ *mind_armor_of_fear(int item) +casting_result mind_armor_of_fear(int item) { - set_shield(randint(10) + mind_armor_of_fear_base_duration(), - 10, - SHIELD_FEAR, - mind_armor_of_fear_power_sides(), - mind_armor_of_fear_power_dice()); - return CAST; + return cast(set_shield(randint(10) + mind_armor_of_fear_base_duration(), + 10, + SHIELD_FEAR, + mind_armor_of_fear_power_sides(), + mind_armor_of_fear_power_dice())); } char *mind_armor_of_fear_info() @@ -2677,7 +2690,7 @@ static int mind_stun_power() return 10 + get_level_s(STUN, 150); } -bool_ *mind_stun(int item) +casting_result mind_stun(int item) { int dir; @@ -2688,14 +2701,12 @@ bool_ *mind_stun(int item) if (get_level_s(STUN, 50) >= 20) { - fire_ball(GF_STUN, dir, mind_stun_power(), 3); + return cast(fire_ball(GF_STUN, dir, mind_stun_power(), 3)); } else { - fire_bolt(GF_STUN, dir, mind_stun_power()); + return cast(fire_bolt(GF_STUN, dir, mind_stun_power())); } - - return CAST; } char *mind_stun_info() @@ -2707,7 +2718,7 @@ char *mind_stun_info() return buf; } -bool_ *tempo_magelock(int item) +casting_result tempo_magelock(int item) { if (get_level_s(MAGELOCK, 50) >= 30) { @@ -2736,15 +2747,14 @@ bool_ *tempo_magelock(int item) x = p_ptr->px; } cave_set_feat(y, x, 3); - return CAST; + return CAST_OBVIOUS; } else { int dir; if (!get_aim_dir(&dir)) { return NO_CAST; } - wizard_lock(dir); - return CAST; + return cast(wizard_lock(dir)); } } @@ -2758,7 +2768,7 @@ static s32b tempo_slow_monster_power() return 40 + get_level_s(SLOWMONSTER, 160); } -bool_ *tempo_slow_monster(int item) +casting_result tempo_slow_monster(int item) { int dir; s32b pwr; @@ -2771,14 +2781,12 @@ bool_ *tempo_slow_monster(int item) pwr = tempo_slow_monster_power(); if (get_level_s(SLOWMONSTER, 50) >= 20) { - fire_ball(GF_OLD_SLOW, dir, pwr, 1); + return cast(fire_ball(GF_OLD_SLOW, dir, pwr, 1)); } else { - fire_bolt(GF_OLD_SLOW, dir, pwr); + return cast(fire_bolt(GF_OLD_SLOW, dir, pwr)); } - - return CAST; } char *tempo_slow_monster_info() @@ -2807,14 +2815,14 @@ static s32b tempo_essence_of_speed_bonus() return 5 + get_level_s(ESSENCESPEED, 20); } -bool_ *tempo_essence_of_speed(int item) +casting_result tempo_essence_of_speed(int item) { if (p_ptr->fast == 0) { - set_fast(randint(10) + tempo_essence_of_speed_base_duration(), - tempo_essence_of_speed_bonus()); + return cast(set_fast(randint(10) + tempo_essence_of_speed_base_duration(), + tempo_essence_of_speed_bonus())); } - return CAST; + return NO_CAST; } char *tempo_essence_of_speed_info() @@ -2832,17 +2840,20 @@ static s32b tempo_banishment_power() return 40 + get_level_s(BANISHMENT, 160); } -bool_ *tempo_banishment(int item) +casting_result tempo_banishment(int item) { + casting_result result = NO_CAST; s32b pwr = tempo_banishment_power(); - project_hack(GF_AWAY_ALL, pwr); + result = cplus(result, project_hack(GF_AWAY_ALL, pwr)); + if (get_level_s(BANISHMENT, 50) >= 15) { - project_hack(GF_STASIS, 20 + get_level_s(BANISHMENT, 120)); + result = cplus(result, + project_hack(GF_STASIS, 20 + get_level_s(BANISHMENT, 120))); } - return CAST; + return result; } char *tempo_banishment_info() @@ -2854,17 +2865,18 @@ char *tempo_banishment_info() return buf; } -bool_ *tulkas_divine_aim(int item) +casting_result tulkas_divine_aim(int item) { + casting_result result = NO_CAST; s32b dur = get_level_s(TULKAS_AIM, 50) + randint(10); - set_strike(dur); + result = cplus(result, set_strike(dur)); if (get_level_s(TULKAS_AIM, 50) >= 20) { - set_tim_deadly(dur); + result = cplus(result, set_tim_deadly(dur)); } - return CAST; + return result; } char *tulkas_divine_aim_info() @@ -2876,7 +2888,7 @@ char *tulkas_divine_aim_info() return buf; } -bool_ *tulkas_wave_of_power(int item) +casting_result tulkas_wave_of_power(int item) { int dir; @@ -2885,8 +2897,7 @@ bool_ *tulkas_wave_of_power(int item) return NO_CAST; } - fire_bolt(GF_ATTACK, dir, get_level_s(TULKAS_WAVE, p_ptr->num_blow)); - return CAST; + return cast(fire_bolt(GF_ATTACK, dir, get_level_s(TULKAS_WAVE, p_ptr->num_blow))); } char *tulkas_wave_of_power_info() @@ -2898,10 +2909,9 @@ char *tulkas_wave_of_power_info() return buf; } -bool_ *tulkas_whirlwind(int item) +casting_result tulkas_whirlwind(int item) { - fire_ball(GF_ATTACK, 0, 1, 1); - return CAST; + return cast(fire_ball(GF_ATTACK, 0, 1, 1)); } char *tulkas_whirlwind_info() @@ -2980,7 +2990,7 @@ static bool_ udun_object_is_drainable(object_type *o_ptr) (o_ptr->tval == TV_STAFF)); } -bool_ *udun_drain(int ignored) +casting_result udun_drain(int ignored) { int item; object_type *o_ptr = NULL; @@ -3034,7 +3044,7 @@ bool_ *udun_drain(int ignored) assert(FALSE); } - return CAST; + return CAST_OBVIOUS; } char *udun_drain_info() @@ -3042,7 +3052,7 @@ char *udun_drain_info() return ""; } -bool_ *udun_genocide(int item) +casting_result udun_genocide(int item) { if (get_level_s(GENOCIDE, 50) < 10) { @@ -3060,7 +3070,7 @@ bool_ *udun_genocide(int item) } } - return CAST; + return CAST_OBVIOUS; } char *udun_genocide_info() @@ -3073,10 +3083,9 @@ static int udun_wraithform_base_duration() return 20 + get_level_s(WRAITHFORM, 40); } -bool_ *udun_wraithform(int item) +casting_result udun_wraithform(int item) { - set_shadow(randint(30) + udun_wraithform_base_duration()); - return CAST; + return cast(set_shadow(randint(30) + udun_wraithform_base_duration())); } char *udun_wraithform_info() @@ -3093,12 +3102,11 @@ static int udun_flame_of_udun_base_duration() return 5 + get_level_s(FLAMEOFUDUN, 30); } -bool_ *udun_flame_of_udun(int item) +casting_result udun_flame_of_udun(int item) { - set_mimic(randint(15) + udun_flame_of_udun_base_duration(), - resolve_mimic_name("Balrog"), - get_level_s(FLAMEOFUDUN, 50)); - return CAST; + return cast(set_mimic(randint(15) + udun_flame_of_udun_base_duration(), + resolve_mimic_name("Balrog"), + get_level_s(FLAMEOFUDUN, 50))); } char *udun_flame_of_udun_info() @@ -3120,7 +3128,7 @@ static int tidal_wave_duration() return 6 + get_level_s(TIDALWAVE, 10); } -bool_ *water_tidal_wave(int item) +casting_result water_tidal_wave(int item) { fire_wave(GF_WAVE, 0, @@ -3128,7 +3136,7 @@ bool_ *water_tidal_wave(int item) 0, tidal_wave_duration(), EFF_WAVE); - return CAST; + return CAST_OBVIOUS; } char *water_tidal_wave_info() @@ -3156,7 +3164,7 @@ static int water_ice_storm_duration() return 20 + get_level_s(ICESTORM, 70); } -bool_ *water_ice_storm(int item) +casting_result water_ice_storm(int item) { int type = GF_COLD; @@ -3172,7 +3180,7 @@ bool_ *water_ice_storm(int item) water_ice_storm_duration(), EFF_STORM); - return CAST; + return CAST_OBVIOUS; } char *water_ice_storm_info() @@ -3191,7 +3199,7 @@ static int water_ent_potion_base_duration() return 25 + get_level_s(ENTPOTION, 40);; } -bool_ *water_ent_potion(int item) +casting_result water_ent_potion(int item) { set_food(PY_FOOD_MAX - 1); msg_print("The Ent's Potion fills your stomach."); @@ -3205,7 +3213,7 @@ bool_ *water_ent_potion(int item) set_hero(p_ptr->hero + randint(25) + water_ent_potion_base_duration()); } - return CAST; + return CAST_OBVIOUS; } char *water_ent_potion_info() @@ -3239,14 +3247,14 @@ static int water_vapor_duration() return 5; } -bool_ *water_vapor(int item) +casting_result water_vapor(int item) { fire_cloud(GF_WATER, 0, water_vapor_damage(), water_vapor_radius(), water_vapor_duration()); - return CAST; + return CAST_OBVIOUS; } char *water_vapor_info() @@ -3269,7 +3277,7 @@ static void get_geyser_damage(int *dice, int *sides) *sides = 3 + get_level_s(GEYSER, 35); } -bool_ *water_geyser(int item) +casting_result water_geyser(int item) { int dir, dice, sides; @@ -3279,11 +3287,10 @@ bool_ *water_geyser(int item) } get_geyser_damage(&dice, &sides); - fire_bolt_or_beam(2 * get_level_s(GEYSER, 85), - GF_WATER, - dir, - damroll(dice, sides)); - return CAST; + return cast(fire_bolt_or_beam(2 * get_level_s(GEYSER, 85), + GF_WATER, + dir, + damroll(dice, sides))); } char *water_geyser_info() @@ -3310,7 +3317,7 @@ static int charm_animal_radius() return get_level_s(YAVANNA_CHARM_ANIMAL, 2); } -bool_ *yavanna_charm_animal(int item) +casting_result yavanna_charm_animal(int item) { int dir; @@ -3319,11 +3326,10 @@ bool_ *yavanna_charm_animal(int item) return NO_CAST; } - fire_ball(GF_CONTROL_ANIMAL, - dir, - charm_animal_power(), - charm_animal_radius()); - return CAST; + return cast(fire_ball(GF_CONTROL_ANIMAL, + dir, + charm_animal_power(), + charm_animal_radius())); } char *yavanna_charm_animal_info() @@ -3341,10 +3347,10 @@ static int yavanna_grow_grass_radius() return get_level_s(YAVANNA_GROW_GRASS, 4); } -bool_ *yavanna_grow_grass(int item) +casting_result yavanna_grow_grass(int item) { grow_grass(yavanna_grow_grass_radius()); - return CAST; + return CAST_OBVIOUS; } char *yavanna_grow_grass_info() @@ -3371,12 +3377,11 @@ static int tree_roots_damage() return 10 + get_level_s(YAVANNA_TREE_ROOTS, 20); } -bool_ *yavanna_tree_roots(int item) +casting_result yavanna_tree_roots(int item) { - set_roots(tree_roots_duration(), - tree_roots_ac(), - tree_roots_damage()); - return CAST; + return cast(set_roots(tree_roots_duration(), + tree_roots_ac(), + tree_roots_damage())); } char *yavanna_tree_roots_info() @@ -3400,7 +3405,7 @@ static int water_bite_damage() return 10 + get_level_s(YAVANNA_WATER_BITE, 50); } -bool_ *yavanna_water_bite(int item) +casting_result yavanna_water_bite(int item) { int rad = 0; @@ -3409,12 +3414,11 @@ bool_ *yavanna_water_bite(int item) rad = 1; } - set_project(randint(30) + water_bite_base_duration(), - GF_WATER, - water_bite_damage(), - rad, - PROJECT_STOP | PROJECT_KILL); - return CAST; + return cast(set_project(randint(30) + water_bite_base_duration(), + GF_WATER, + water_bite_damage(), + rad, + PROJECT_STOP | PROJECT_KILL)); } char *yavanna_water_bite_info() @@ -3432,7 +3436,7 @@ static int uproot_mlevel() return 30 + get_level_s(YAVANNA_UPROOT, 70); } -bool_ *yavanna_uproot(int item) +casting_result yavanna_uproot(int item) { int dir, x, y; cave_type *c_ptr; @@ -3467,7 +3471,7 @@ bool_ *yavanna_uproot(int item) } msg_print("The tree awakes!"); - return CAST; + return CAST_OBVIOUS; } else { @@ -3490,10 +3494,10 @@ static int nature_grow_trees_radius() return 2 + get_level_s(GROWTREE, 7); } -bool_ *nature_grow_trees(int item) +casting_result nature_grow_trees(int item) { grow_trees(nature_grow_trees_radius()); - return CAST; + return CAST_OBVIOUS; } char *nature_grow_trees_info() @@ -3515,10 +3519,9 @@ static int nature_healing_hp() return p_ptr->mhp * nature_healing_percentage() / 100; } -bool_ *nature_healing(int item) +casting_result nature_healing(int item) { - hp_player(nature_healing_hp()); - return CAST; + return cast(hp_player(nature_healing_hp())); } char *nature_healing_info() @@ -3531,28 +3534,31 @@ char *nature_healing_info() return buf; } -bool_ *nature_recovery(int item) +casting_result nature_recovery(int item) { - set_poisoned(p_ptr->poisoned / 2); + casting_result result = NO_CAST; + + result = cplus(result, set_poisoned(p_ptr->poisoned / 2)); if (get_level_s(RECOVERY, 50) >= 5) { - set_poisoned(0); - set_cut(0); + result = cplus(result, set_poisoned(0)); + result = cplus(result, set_cut(0)); } if (get_level_s(RECOVERY, 50) >= 10) { - do_res_stat(A_STR, TRUE); - do_res_stat(A_CON, TRUE); - do_res_stat(A_DEX, TRUE); - do_res_stat(A_WIS, TRUE); - do_res_stat(A_INT, TRUE); - do_res_stat(A_CHR, TRUE); + result = cplus(result, do_res_stat(A_STR, TRUE)); + result = cplus(result, do_res_stat(A_CON, TRUE)); + result = cplus(result, do_res_stat(A_DEX, TRUE)); + result = cplus(result, do_res_stat(A_WIS, TRUE)); + result = cplus(result, do_res_stat(A_INT, TRUE)); + result = cplus(result, do_res_stat(A_CHR, TRUE)); } if (get_level_s(RECOVERY, 50) >= 15) { - restore_level(); + result = cplus(result, restore_level()); } - return CAST; + + return result; } char *nature_recovery_info() @@ -3570,13 +3576,12 @@ static int regeneration_power() return 300 + get_level_s(REGENERATION, 700); } -bool_ *nature_regeneration(int item) +casting_result nature_regeneration(int item) { if (p_ptr->tim_regen == 0) { - set_tim_regen(randint(10) + regeneration_base_duration(), - regeneration_power()); - return CAST; + return cast(set_tim_regen(randint(10) + regeneration_base_duration(), + regeneration_power())); } return NO_CAST; } @@ -3596,15 +3601,14 @@ static int summon_animal_level() return 25 + get_level_s(SUMMONANNIMAL, 50); } -bool_ *nature_summon_animal(int item) +casting_result nature_summon_animal(int item) { summon_specific_level = summon_animal_level(); - summon_specific_friendly(p_ptr->py, - p_ptr->px, - dun_level, - SUMMON_ANIMAL, - TRUE); - return CAST; + return cast(summon_specific_friendly(p_ptr->py, + p_ptr->px, + dun_level, + SUMMON_ANIMAL, + TRUE)); } char *nature_summon_animal_info() @@ -3616,15 +3620,16 @@ char *nature_summon_animal_info() return buf; } -bool_ *nature_grow_athelas(int item) +casting_result nature_grow_athelas(int item) { if (p_ptr->black_breath) { msg_print("The hold of the Black Breath on you is broken!"); p_ptr->black_breath = FALSE; + return CAST_OBVIOUS; } - return CAST; + return CAST_HIDDEN; } char *nature_grow_athelas_info() @@ -3637,7 +3642,7 @@ static int device_heal_monster_hp() return 20 + get_level_s(DEVICE_HEAL_MONSTER, 380); } -bool_ *device_heal_monster(int item) +casting_result device_heal_monster(int item) { int dir; @@ -3646,8 +3651,7 @@ bool_ *device_heal_monster(int item) return NO_CAST; } - fire_ball(GF_OLD_HEAL, dir, device_heal_monster_hp(), 0); - return CAST; + return cast(fire_ball(GF_OLD_HEAL, dir, device_heal_monster_hp(), 0)); } char *device_heal_monster_info() @@ -3659,7 +3663,7 @@ char *device_heal_monster_info() return buf; } -bool_ *device_haste_monster(int item) +casting_result device_haste_monster(int item) { int dir; @@ -3668,8 +3672,7 @@ bool_ *device_haste_monster(int item) return NO_CAST; } - fire_ball(GF_OLD_SPEED, dir, 1, 0); - return CAST; + return cast(fire_ball(GF_OLD_SPEED, dir, 1, 0)); } char *device_haste_monster_info() @@ -3677,10 +3680,10 @@ char *device_haste_monster_info() return "speed +10"; } -bool_ *device_wish(int item) +casting_result device_wish(int item) { make_wish(); - return CAST; + return CAST_OBVIOUS; } char *device_wish_info() @@ -3688,14 +3691,17 @@ char *device_wish_info() return ""; } -bool_ *device_summon_monster(int item) +casting_result device_summon_monster(int item) { + casting_result result = NO_CAST; int i; + for (i = 0; i < 4 + get_level_s(DEVICE_SUMMON, 30); i++) { - summon_specific(p_ptr->py, p_ptr->px, dun_level, 0); + result = cplus(result, summon_specific(p_ptr->py, p_ptr->px, dun_level, 0)); } - return CAST; + + return result; } char *device_summon_monster_info() @@ -3708,10 +3714,10 @@ static int device_mana_pct() return 20 + get_level_s(DEVICE_MANA, 50); } -bool_ *device_mana(int item) +casting_result device_mana(int item) { increase_mana((p_ptr->msp * device_mana_pct()) / 100); - return CAST; + return CAST_OBVIOUS; } char *device_mana_info() @@ -3723,9 +3729,9 @@ char *device_mana_info() return buf; } -bool_ *device_nothing(int item) +casting_result device_nothing(int item) { - return CAST; + return CAST_HIDDEN; } char *device_nothing_info() @@ -3733,13 +3739,13 @@ char *device_nothing_info() return ""; } -bool_ *device_lebohaum(int item) +casting_result device_lebohaum(int item) { msg_print("You hear a little song in your head in some unknown tongue:"); msg_print("'Avec le casque Lebohaum y a jamais d'anicroches, je parcours les dongeons,"); msg_print("j'en prend plein la caboche. Avec le casque Lebohaum, tout ces monstres a la"); msg_print("con, je leur met bien profond: c'est moi le maitre du dongeon!'"); - return CAST; + return CAST_OBVIOUS; } char *device_lebohaum_info() @@ -3747,7 +3753,7 @@ char *device_lebohaum_info() return ""; } -bool_ *device_maggot(int item) +casting_result device_maggot(int item) { int dir; @@ -3756,8 +3762,7 @@ bool_ *device_maggot(int item) return NO_CAST; } - fire_ball(GF_TURN_ALL, dir, 40, 2); - return CAST; + return cast(fire_ball(GF_TURN_ALL, dir, 40, 2)); } char *device_maggot_info() @@ -3770,10 +3775,9 @@ static int holy_fire_damage() return 50 + get_level_s(DEVICE_HOLY_FIRE, 300); } -bool_ *device_holy_fire(int item) +casting_result device_holy_fire(int item) { - project_hack(GF_HOLY_FIRE, holy_fire_damage()); - return CAST; + return cast(project_hack(GF_HOLY_FIRE, holy_fire_damage())); } char *device_holy_fire_info() @@ -3833,7 +3837,7 @@ static bool_ eternal_flame_item_tester_hook(object_type *o_ptr) return (get_eternal_artifact_idx(o_ptr) >= 0); } -bool_ *device_eternal_flame(int flame_item) +casting_result device_eternal_flame(int flame_item) { int item; object_type *o_ptr = NULL; @@ -3845,7 +3849,7 @@ bool_ *device_eternal_flame(int flame_item) "You have no objects to imbue.", USE_INVEN)) { - return FALSE; + return NO_CAST; } /* Get the artifact idx */ @@ -3864,7 +3868,7 @@ bool_ *device_eternal_flame(int flame_item) inven_item_describe(flame_item); inven_item_optimize(flame_item); - return CAST; + return CAST_OBVIOUS; } char *device_eternal_flame_info() @@ -3872,7 +3876,7 @@ char *device_eternal_flame_info() return ""; } -bool_ *device_durandil(int item) +casting_result device_durandil(int item) { msg_print("You hear a little song in your head in some unknown tongue:"); msg_print("'Les epees Durandils sont forgees dans les mines par des nains."); @@ -3886,7 +3890,7 @@ bool_ *device_durandil(int item) msg_print("Quand tu la sort dans un dongeon au moins t'as pas l'air debile."); msg_print("C'est l'arme des bourins qui savent etre subtils."); msg_print("Ne partez pas a l'aventure sans votre epee Durandil!'"); - return CAST; + return CAST_OBVIOUS; } char *device_durandil_info() @@ -3894,7 +3898,7 @@ char *device_durandil_info() return ""; } -bool_ *device_thunderlords(int item) +casting_result device_thunderlords(int item) { switch (game_module_idx) { @@ -3909,7 +3913,7 @@ bool_ *device_thunderlords(int item) { msg_print("You cannot use it there."); } - return CAST; + return CAST_OBVIOUS; } case MODULE_THEME: @@ -3923,7 +3927,7 @@ bool_ *device_thunderlords(int item) { msg_print("You cannot use it there."); } - return CAST; + return CAST_OBVIOUS; } default: @@ -3937,7 +3941,7 @@ char *device_thunderlords_info() return ""; } -bool_ *device_radagast(int item) +casting_result device_radagast(int item) { cmsg_print(TERM_GREEN, "The staff's power cleanses you completely!"); remove_all_curse(); @@ -3968,7 +3972,7 @@ bool_ *device_radagast(int item) p_ptr->update |= PU_BONUS; p_ptr->window |= PW_PLAYER; - return CAST; + return CAST_OBVIOUS; } char *device_radagast_info() @@ -3976,11 +3980,11 @@ char *device_radagast_info() return ""; } -bool_ *device_valaroma(int item) +casting_result device_valaroma(int item) { int power = 5 * p_ptr->lev; banish_evil(power); - return CAST; + return CAST_HIDDEN; } char *device_valaroma_info() @@ -3993,10 +3997,10 @@ void static start_lasting_spell(int spl) p_ptr->music_extra = -spl; } -bool_ *music_stop_singing_spell(int item) +casting_result music_stop_singing_spell(int item) { start_lasting_spell(0); - return CAST; + return CAST_OBVIOUS; } char *music_stop_singing_info() @@ -4015,10 +4019,10 @@ int music_holding_pattern_lasting() return get_mana(MUSIC_HOLD); } -bool_ *music_holding_pattern_spell(int item) +casting_result music_holding_pattern_spell(int item) { start_lasting_spell(MUSIC_HOLD); - return CAST; + return CAST_OBVIOUS; } char *music_holding_pattern_info() @@ -4041,10 +4045,10 @@ int music_illusion_pattern_lasting() return get_mana(MUSIC_CONF); } -bool_ *music_illusion_pattern_spell(int item) +casting_result music_illusion_pattern_spell(int item) { start_lasting_spell(MUSIC_CONF); - return CAST; + return CAST_OBVIOUS; } char *music_illusion_pattern_info() @@ -4067,10 +4071,10 @@ int music_stun_pattern_lasting() return get_mana(MUSIC_STUN); } -bool_ *music_stun_pattern_spell(int item) +casting_result music_stun_pattern_spell(int item) { start_lasting_spell(MUSIC_STUN); - return CAST; + return CAST_OBVIOUS; } char *music_stun_pattern_info() @@ -4088,10 +4092,10 @@ int music_song_of_the_sun_lasting() return 1; } -bool_ *music_song_of_the_sun_spell(int item) +casting_result music_song_of_the_sun_spell(int item) { start_lasting_spell(MUSIC_LITE); - return CAST; + return CAST_OBVIOUS; } char *music_song_of_the_sun_info() @@ -4110,10 +4114,10 @@ int music_flow_of_life_lasting() return get_mana(MUSIC_HEAL); } -bool_ *music_flow_of_life_spell(int item) +casting_result music_flow_of_life_spell(int item) { start_lasting_spell(MUSIC_HEAL); - return CAST; + return CAST_OBVIOUS; } char *music_flow_of_life_info() @@ -4143,10 +4147,10 @@ int music_heroic_ballad_lasting() return get_mana(MUSIC_HERO); } -bool_ *music_heroic_ballad_spell(int item) +casting_result music_heroic_ballad_spell(int item) { start_lasting_spell(MUSIC_HERO); - return CAST; + return CAST_OBVIOUS; } char *music_heroic_ballad_info() @@ -4164,10 +4168,10 @@ int music_hobbit_melodies_lasting() return get_mana(MUSIC_TIME); } -bool_ *music_hobbit_melodies_spell(int item) +casting_result music_hobbit_melodies_spell(int item) { start_lasting_spell(MUSIC_TIME); - return CAST; + return CAST_OBVIOUS; } char *music_hobbit_melodies_info() @@ -4197,10 +4201,10 @@ int music_clairaudience_lasting() return get_mana(MUSIC_MIND); } -bool_ *music_clairaudience_spell(int item) +casting_result music_clairaudience_spell(int item) { start_lasting_spell(MUSIC_MIND); - return CAST; + return CAST_OBVIOUS; } char *music_clairaudience_info() @@ -4219,13 +4223,13 @@ char *music_clairaudience_info() } } -bool_ *music_blow_spell(int item) +casting_result music_blow_spell(int item) { fire_ball(GF_SOUND, 0, damroll(2 + get_level(MUSIC_BLOW, 10, 0), 4 + get_level(MUSIC_BLOW, 40, 0)), 1 + get_level(MUSIC_BLOW, 12, 0)); - return CAST; + return CAST_OBVIOUS; } char *music_blow_info() @@ -4239,13 +4243,13 @@ char *music_blow_info() return buf; } -bool_ *music_gush_of_wind_spell(int item) +casting_result music_gush_of_wind_spell(int item) { fire_ball(GF_AWAY_ALL, 0, 10 + get_level(MUSIC_BLOW, 40, 0), 1 + get_level(MUSIC_BLOW, 12, 0)); - return CAST; + return CAST_OBVIOUS; } char *music_gush_of_wind_info() @@ -4258,10 +4262,10 @@ char *music_gush_of_wind_info() return buf; } -bool_ *music_horns_of_ylmir_spell(int item) +casting_result music_horns_of_ylmir_spell(int item) { earthquake(p_ptr->py, p_ptr->px, 2 + get_level_s(SHAKE, 10)); - return CAST; + return CAST_OBVIOUS; } char *music_horns_of_ylmir_info() @@ -4273,10 +4277,10 @@ char *music_horns_of_ylmir_info() return buf; } -bool_ *music_ambarkanta_spell(int item) +casting_result music_ambarkanta_spell(int item) { alter_reality(); - return CAST; + return CAST_OBVIOUS; } char *music_ambarkanta_info() @@ -4284,7 +4288,7 @@ char *music_ambarkanta_info() return ""; } -bool_ *aule_firebrand_spell(int item) +casting_result aule_firebrand_spell(int item) { int rad = 0; int type = GF_FIRE; @@ -4300,12 +4304,11 @@ bool_ *aule_firebrand_spell(int item) rad = 1; } - set_project(level + randint(20), - type, - 4 + level, - rad, - PROJECT_STOP | PROJECT_KILL); - return CAST; + return cast(set_project(level + randint(20), + type, + 4 + level, + rad, + PROJECT_STOP | PROJECT_KILL)); } char *aule_firebrand_info() @@ -4342,7 +4345,7 @@ static bool_ aule_enchant_weapon_item_tester(object_type *o_ptr) } } -bool_ *aule_enchant_weapon_spell(int ignored) +casting_result aule_enchant_weapon_spell(int ignored) { s32b level = get_level_s(AULE_ENCHANT_WEAPON, 50); s16b num_h, num_d, num_p; @@ -4377,7 +4380,7 @@ bool_ *aule_enchant_weapon_spell(int ignored) o_ptr->to_d = o_ptr->to_d + num_d; o_ptr->pval = o_ptr->pval + num_p; - return CAST; + return CAST_OBVIOUS; } char *aule_enchant_weapon_info() @@ -4414,7 +4417,7 @@ bool_ aule_enchant_armor_item_tester(object_type *o_ptr) } } -bool_ *aule_enchant_armour_spell(int ignored) +casting_result aule_enchant_armour_spell(int ignored) { s32b level = get_level_s(AULE_ENCHANT_ARMOUR, 50); s16b num_h, num_d, num_a, num_p; @@ -4451,7 +4454,7 @@ bool_ *aule_enchant_armour_spell(int ignored) o_ptr->pval = o_ptr->pval + num_p; o_ptr->to_a = o_ptr->to_a + num_a; - return CAST; + return CAST_OBVIOUS; } char *aule_enchant_armour_info() @@ -4463,7 +4466,7 @@ char *aule_enchant_armour_info() return buf; } -bool_ *aule_child_spell(int item) +casting_result aule_child_spell(int item) { int y, x; s16b m_idx; @@ -4475,7 +4478,7 @@ bool_ *aule_child_spell(int item) if (m_idx) { monster_set_level(m_idx, 20 + get_level(AULE_CHILD, 70, 0)); - return CAST; + return CAST_OBVIOUS; } else { @@ -4497,13 +4500,16 @@ static int tears_of_luthien_hp() return 10 * get_level_s(MANDOS_TEARS_LUTHIEN, 30); } -bool_ *mandos_tears_of_luthien_spell(int item) +casting_result mandos_tears_of_luthien_spell(int item) { - hp_player(tears_of_luthien_hp()); - set_stun(0); - set_cut(0); - set_afraid(0); - return CAST; + casting_result result = NO_CAST; + + result = cplus(result, hp_player(tears_of_luthien_hp())); + result = cplus(result, set_stun(0)); + result = cplus(result, set_cut(0)); + result = cplus(result, set_afraid(0)); + + return result; } char *mandos_tears_of_luthien_info() @@ -4515,26 +4521,27 @@ char *mandos_tears_of_luthien_info() return buf; } -bool_ *mandos_spirit_of_the_feanturi_spell(int item) +casting_result mandos_spirit_of_the_feanturi_spell(int item) { + casting_result result = NO_CAST; s32b level = get_level_s(MANDOS_SPIRIT_FEANTURI, 50); - set_afraid(0); - set_confused(0); + result = cplus(result, set_afraid(0)); + result = cplus(result, set_confused(0)); if (level >= 20) { - do_res_stat(A_WIS, TRUE); - do_res_stat(A_INT, TRUE); + result = cplus(result, do_res_stat(A_WIS, TRUE)); + result = cplus(result, do_res_stat(A_INT, TRUE)); } if (level >= 30) { - set_image(0); - heal_insanity(p_ptr->msane * level / 100); + result = cplus(result, set_image(0)); + result = cplus(result, heal_insanity(p_ptr->msane * level / 100)); } - return CAST; + return result; } char *mandos_spirit_of_the_feanturi_info() @@ -4557,10 +4564,9 @@ static int tale_of_doom_duration() return 5 + get_level_s(MANDOS_TALE_DOOM,10); } -bool_ *mandos_tale_of_doom_spell(int item) +casting_result mandos_tale_of_doom_spell(int item) { - set_tim_precognition(tale_of_doom_duration()); - return CAST; + return cast(set_tim_precognition(tale_of_doom_duration())); } char *mandos_tale_of_doom_info() @@ -4577,7 +4583,7 @@ int call_to_the_halls_mlev() return 20 + get_level(MANDOS_CALL_HALLS, 70, 0); } -bool_ *mandos_call_to_the_halls_spell(int item) +casting_result mandos_call_to_the_halls_spell(int item) { #define N_SUMMONS 2 int y, x; @@ -4595,7 +4601,7 @@ bool_ *mandos_call_to_the_halls_spell(int item) if (m_idx) { monster_set_level(m_idx, call_to_the_halls_mlev()); - return CAST; + return CAST_OBVIOUS; } return NO_CAST; #undef N_SUMMONS @@ -4616,7 +4622,7 @@ static void get_belegaer_damage(int *dice, int *sides) *sides = 3 + get_level_s(ULMO_BELEGAER, 35); } -bool_ *ulmo_song_of_belegaer_spell(int item) +casting_result ulmo_song_of_belegaer_spell(int item) { int dir, dice, sides; @@ -4626,11 +4632,10 @@ bool_ *ulmo_song_of_belegaer_spell(int item) } get_belegaer_damage(&dice, &sides); - fire_bolt_or_beam(2 * get_level_s(ULMO_BELEGAER, 85), - GF_WATER, - dir, - damroll(dice, sides)); - return CAST; + return cast(fire_bolt_or_beam(2 * get_level_s(ULMO_BELEGAER, 85), + GF_WATER, + dir, + damroll(dice, sides))); } char *ulmo_song_of_belegaer_info() @@ -4651,31 +4656,32 @@ int draught_of_ulmonan_hp() return 5 * get_level_s(ULMO_DRAUGHT_ULMONAN, 50); } -bool_ *ulmo_draught_of_ulmonan_spell(int item) +casting_result ulmo_draught_of_ulmonan_spell(int item) { + casting_result result = NO_CAST; s32b level = get_level_s(ULMO_DRAUGHT_ULMONAN, 50); - hp_player(draught_of_ulmonan_hp()); + result = cplus(result, hp_player(draught_of_ulmonan_hp())); - set_poisoned(0); - set_cut(0); - set_stun(0); - set_blind(0); + result = cplus(result, set_poisoned(0)); + result = cplus(result, set_cut(0)); + result = cplus(result, set_stun(0)); + result = cplus(result, set_blind(0)); if (level >= 10) { - do_res_stat(A_STR, TRUE); - do_res_stat(A_CON, TRUE); - do_res_stat(A_DEX, TRUE); + result = cplus(result, do_res_stat(A_STR, TRUE)); + result = cplus(result, do_res_stat(A_CON, TRUE)); + result = cplus(result, do_res_stat(A_DEX, TRUE)); } if (level >= 20) { - set_parasite(0, 0); - set_mimic(0, 0, 0); + result = cplus(result, set_parasite(0, 0)); + result = cplus(result, set_mimic(0, 0, 0)); } - return CAST; + return result; } char *ulmo_draught_of_ulmonan_info() @@ -4692,7 +4698,7 @@ static int call_of_the_ulumuri_mlev() return 30 + get_level(ULMO_CALL_ULUMURI, 70, 0); } -bool_ *ulmo_call_of_the_ulumuri_spell(int item) +casting_result ulmo_call_of_the_ulumuri_spell(int item) { #define N_SUMMONS 2 int x,y; @@ -4711,7 +4717,7 @@ bool_ *ulmo_call_of_the_ulumuri_spell(int item) if (m_idx) { monster_set_level(m_idx, call_of_the_ulumuri_mlev()); - return CAST; + return CAST_OBVIOUS; } return NO_CAST; @@ -4737,7 +4743,7 @@ static int wrath_of_ulmo_duration() return 10 + get_level_s(ULMO_WRATH, 14); } -bool_ *ulmo_wrath_of_ulmo_spell(int item) +casting_result ulmo_wrath_of_ulmo_spell(int item) { int dir, type = GF_WATER; @@ -4755,7 +4761,7 @@ bool_ *ulmo_wrath_of_ulmo_spell(int item) dir, wrath_of_ulmo_damage(), wrath_of_ulmo_duration()); - return CAST; + return CAST_OBVIOUS; } char *ulmo_wrath_of_ulmo_info() @@ -4778,26 +4784,30 @@ static int light_of_valinor_radius() return 5 + get_level_s(VARDA_LIGHT_VALINOR, 6); } -bool_ *varda_light_of_valinor_spell(int item) +casting_result varda_light_of_valinor_spell(int item) { + casting_result result = NO_CAST; + if (get_level_s(VARDA_LIGHT_VALINOR, 50) >= 3) { - lite_area(10, 4); + result = cplus(result, lite_area(10, 4)); } else { lite_room(p_ptr->py, p_ptr->px); + result = CAST_OBVIOUS; } if (get_level_s(VARDA_LIGHT_VALINOR, 50) >= 15) { - fire_ball(GF_LITE, - 0, - light_of_valinor_damage(), - light_of_valinor_radius()); + result = cplus(result, + fire_ball(GF_LITE, + 0, + light_of_valinor_damage(), + light_of_valinor_radius())); } - return CAST; + return result; } char *varda_light_of_valinor_info() @@ -4817,7 +4827,7 @@ char *varda_light_of_valinor_info() } } -bool_ *varda_call_of_almaren_spell(int item) +casting_result varda_call_of_almaren_spell(int item) { int power = 5 * p_ptr->lev; if (get_level_s(VARDA_CALL_ALMAREN, 50) >= 20) @@ -4828,7 +4838,7 @@ bool_ *varda_call_of_almaren_spell(int item) { banish_evil(power); } - return CAST; + return CAST_OBVIOUS; } char *varda_call_of_almaren_info() @@ -4836,7 +4846,7 @@ char *varda_call_of_almaren_info() return ""; } -bool_ *varda_evenstar_spell(int item) +casting_result varda_evenstar_spell(int item) { wiz_lite_extra(); if (get_level_s(VARDA_EVENSTAR, 50) >= 40) @@ -4845,7 +4855,7 @@ bool_ *varda_evenstar_spell(int item) self_knowledge(NULL); } - return CAST; + return CAST_OBVIOUS; } char *varda_evenstar_info() @@ -4863,7 +4873,7 @@ static int star_kindler_damage() return 20 + get_level_s(VARDA_STARKINDLER, 100); } -bool_ *varda_star_kindler_spell(int item) +casting_result varda_star_kindler_spell(int item) { int dir, i, n = star_kindler_bursts(); @@ -4880,7 +4890,7 @@ bool_ *varda_star_kindler_spell(int item) 10); } - return CAST; + return CAST_OBVIOUS; } char *varda_star_kindler_info() diff --git a/src/spells4.c b/src/spells4.c index 8bd63bb3..4fd51cbe 100644 --- a/src/spells4.c +++ b/src/spells4.c @@ -579,7 +579,7 @@ static bool_ call_spell_function(s32b s) { spell_type *spell = spell_at(s); assert(spell->effect_func != NULL); - return (spell->effect_func(-1) != NULL); + return (spell->effect_func(-1) != NO_CAST); } void lua_cast_school_spell(s32b s, bool_ no_cost) diff --git a/src/types.h b/src/types.h index 9aa3409c..ed86a4af 100644 --- a/src/types.h +++ b/src/types.h @@ -2519,6 +2519,15 @@ struct school_idx { typedef enum { USE_SPELL_POINTS, USE_PIETY } casting_type; +/* + * Spell effect function result + */ +typedef enum { + NO_CAST, /* Spell not cast; user aborted */ + CAST_OBVIOUS, /* Cast; caster discovers effect (devices) */ + CAST_HIDDEN /* Cast; caster does NOT discover effect (devices) */ +} casting_result; + /* * The spell function must provide the desc */ @@ -2529,7 +2538,7 @@ struct spell_type byte skill_level; /* Required level (to learn) */ string_list *description; /* List of strings */ - bool_ *(*effect_func)(int o_idx); /* Spell effect function */ + casting_result (*effect_func)(int o_idx); /* Spell effect function */ char* (*info_func)(); /* Information function */ int (*lasting_func)(); /* Lasting effect function */ bool_ (*depend_func)(); /* Check dependencies */ -- cgit v1.2.3 From fbc40366c8a50a695fcb913c5f25d717330e9672 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 30 May 2012 07:03:38 +0200 Subject: Lua: Add god_at() for safe indexing of deity_info --- src/externs.h | 1 + src/gods.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/externs.h b/src/externs.h index e584b44c..8f55d3d8 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2447,3 +2447,4 @@ extern int wisdom_scale(int max); extern int find_god(cptr name); extern void follow_god(int god, bool_ silent); extern bool_ god_enabled(struct deity_type *deity); +extern deity_type *god_at(byte god_idx); diff --git a/src/gods.c b/src/gods.c index 170f56b3..f940e21a 100644 --- a/src/gods.c +++ b/src/gods.c @@ -146,6 +146,23 @@ int wisdom_scale(int max) return (i * max) / 37; } +/* + * Get deity info for a given god index. + * Returns NULL for the "atheist" god. + */ +deity_type *god_at(byte god_idx) +{ + assert(god_idx >= 0); + assert(god_idx < MAX_GODS); + + if (god_idx == 0) + { + return NULL; + } + + return &deity_info[god_idx]; +} + /* * Check if god is enabled for the current module */ -- cgit v1.2.3 From 1b9ce2b53e26ed2d983efb9da10eb2be89d6d705 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 30 May 2012 05:33:44 +0200 Subject: Lua: Migrate spell schools to C --- lib/core/init.lua | 1 - lib/core/s_aux.lua | 147 ---------------- lib/mods/theme/core/init.lua | 1 - lib/mods/theme/core/s_aux.lua | 146 ---------------- lib/mods/theme/scpt/init.lua | 4 +- lib/mods/theme/scpt/spells.lua | 385 ----------------------------------------- lib/scpt/init.lua | 4 +- lib/scpt/spells.lua | 293 ------------------------------- src/CMakeLists.txt | 3 +- src/defines.h | 5 + src/externs.h | 21 ++- src/init2.c | 12 +- src/lua_bind.c | 35 +--- src/script.c | 8 - src/spells.pkg | 79 +-------- src/spells4.c | 2 +- src/spells5.c | 33 +--- src/spells6.c | 380 ++++++++++++++++++++++++++++++++++++++++ src/types.h | 25 +++ src/variable.c | 4 +- src/xtra1.c | 1 + 21 files changed, 452 insertions(+), 1137 deletions(-) delete mode 100644 lib/core/s_aux.lua delete mode 100644 lib/mods/theme/core/s_aux.lua delete mode 100644 lib/mods/theme/scpt/spells.lua delete mode 100644 lib/scpt/spells.lua create mode 100644 src/spells6.c diff --git a/lib/core/init.lua b/lib/core/init.lua index 35f820d3..23c76461 100644 --- a/lib/core/init.lua +++ b/lib/core/init.lua @@ -16,7 +16,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "objects.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "building.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "s_aux.lua") -- Load the ingame contextual help tome_dofile_anywhere(ANGBAND_DIR_CORE, "help.lua") diff --git a/lib/core/s_aux.lua b/lib/core/s_aux.lua deleted file mode 100644 index 860892ae..00000000 --- a/lib/core/s_aux.lua +++ /dev/null @@ -1,147 +0,0 @@ --- Functions to help with spells, do not touch - -__schools = {} -__schools_num = 0 - -function add_school(s) - __schools[__schools_num] = s - - __schools_num = __schools_num + 1 - return (__schools_num - 1) -end - -function finish_school(i) - local s - - s = __schools[i] - assert(s.name, "No school name!") - assert(s.skill, "No school skill!") - - -- Need hooks? - if s.hooks then - add_hooks(s.hooks) - end - - new_school(i, s.name, s.skill) -end - --- Creates the school books array -__spell_school = {} - --- Find if the school is under the influence of a god, returns nil or the level -function get_god_level(sch) - if __schools[sch].gods[player.pgod] then - return (s_info[__schools[sch].gods[player.pgod].skill + 1].value * __schools[sch].gods[player.pgod].mul) / __schools[sch].gods[player.pgod].div - else - return nil - end -end - --- Change this fct if I want to switch to learnable spells -function get_level_school(s, max, min) - local lvl, sch, num, bonus - local allow_spell_power = TRUE - - lvl = 0 - num = 0 - bonus = 0 - - -- No max specified ? assume 50 - if not max then - max = 50 - end - if not min then - min = 1 - end - - -- Do we pass tests? - if check_spell_depends(s) ~= TRUE then - return min, "n/a" - end - - local index = 0 - while 1 do - sch = spell_get_school_idx(s, index) - if sch == -1 then - break - end - index = index + 1 - - local r, s, p, ok = 0, 0, 0, 0 - - -- Does it require we worship a specific god? - if __schools[sch].god then - if __schools[sch].god ~= player.pgod then - if min then return min, "n/a" - else return 1, "n/a" end - end - end - - -- Take the basic skill value - r = s_info[(school(sch).skill) + 1].value - - -- Do we pass tests? - if __schools[sch].depend then - if __schools[sch].depend() ~= TRUE then - return min, "n/a" - end - end - - -- Are we under sorcery effect ? - if __schools[sch].sorcery then - s = s_info[SKILL_SORCERY + 1].value - end - - -- Are we affected by spell power ? - -- All teh schools must allow it for it to work - if not __schools[sch].spell_power then - allow_spell_power = nil - end - - -- Are we under a god effect ? - if __schools[sch].gods then - p = get_god_level(sch) - if not p then p = 0 end - end - - -- Find the higher - ok = r - if ok < s then ok = s end - if ok < p then ok = p end - - -- Do we need to add a special bonus ? - if __schools[sch].bonus_level then - bonus = bonus + (__schools[sch].bonus_level() * (SKILL_STEP / 10)) - end - - -- All schools must be non zero to be able to use it - if ok == 0 then return min, "n/a" end - - -- Apply it - lvl = lvl + ok - num = num + 1 - end - - -- Add the Spellpower skill as a bonus - if allow_spell_power then - bonus = bonus + (get_skill_scale(SKILL_SPELL, 20) * (SKILL_STEP / 10)) - end - - -- Add bonus from objects - bonus = bonus + (player.to_s * (SKILL_STEP / 10)) - - -- / 10 because otherwise we can overflow a s32b and we can use a u32b because the value can be negative - -- The loss of information should be negligible since 1 skill = 1000 internally - lvl = (lvl / num) / 10 - lvl = lua_get_level(s, lvl, max, min, bonus) - - return lvl, nil -end - --- The real get_level, works for schooled magic and for innate powers -function get_level(s, max, min) - if not max then max = 50 end - if not min then min = 1 end - return %get_level(s, max, min) -end - diff --git a/lib/mods/theme/core/init.lua b/lib/mods/theme/core/init.lua index 35f820d3..23c76461 100644 --- a/lib/mods/theme/core/init.lua +++ b/lib/mods/theme/core/init.lua @@ -16,7 +16,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "objects.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "building.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "s_aux.lua") -- Load the ingame contextual help tome_dofile_anywhere(ANGBAND_DIR_CORE, "help.lua") diff --git a/lib/mods/theme/core/s_aux.lua b/lib/mods/theme/core/s_aux.lua deleted file mode 100644 index 3e98ec94..00000000 --- a/lib/mods/theme/core/s_aux.lua +++ /dev/null @@ -1,146 +0,0 @@ --- Functions to help with spells, do not touch - -__schools = {} -__schools_num = 0 - -function add_school(s) - __schools[__schools_num] = s - - __schools_num = __schools_num + 1 - return (__schools_num - 1) -end - -function finish_school(i) - local s - - s = __schools[i] - assert(s.name, "No school name!") - assert(s.skill, "No school skill!") - - -- Need hooks? - if s.hooks then - add_hooks(s.hooks) - end - - new_school(i, s.name, s.skill) -end - --- Creates the school books array -__spell_school = {} - --- Find if the school is under the influence of a god, returns nil or the level -function get_god_level(sch) - if __schools[sch].gods[player.pgod] then - return (s_info[__schools[sch].gods[player.pgod].skill + 1].value * __schools[sch].gods[player.pgod].mul) / __schools[sch].gods[player.pgod].div - else - return nil - end -end - --- Change this fct if I want to switch to learnable spells -function get_level_school(s, max, min) - local lvl, sch, num, bonus - local allow_spell_power = TRUE - - lvl = 0 - num = 0 - bonus = 0 - - -- No max specified ? assume 50 - if not max then - max = 50 - end - if not min then - min = 1 - end - - -- Do we pass tests? - if check_spell_depends(s) ~= TRUE then - return min, "n/a" - end - - local index = 0 - while 1 do - sch = spell_get_school_idx(s, index) - if sch == -1 then - break - end - index = index + 1 - - local r, s, p, ok = 0, 0, 0, 0 - - -- Does it require we worship a specific god? - if __schools[sch].god then - if __schools[sch].god ~= player.pgod then - if min then return min, "n/a" - else return 1, "n/a" end - end - end - - -- Take the basic skill value - r = s_info[(school(sch).skill) + 1].value - - -- Do we pass tests? - if __schools[sch].depend then - if __schools[sch].depend() ~= TRUE then - return min, "n/a" - end - end - - -- Are we under sorcery effect ? - if __schools[sch].sorcery then - s = s_info[SKILL_SORCERY + 1].value - end - - -- Are we affected by spell power ? - -- All teh schools must allow it for it to work - if not __schools[sch].spell_power then - allow_spell_power = nil - end - - -- Are we under a god effect ? - if __schools[sch].gods then - p = get_god_level(sch) - if not p then p = 0 end - end - - -- Find the higher - ok = r - if ok < s then ok = s end - if ok < p then ok = p end - - -- Do we need to add a special bonus ? - if __schools[sch].bonus_level then - bonus = bonus + (__schools[sch].bonus_level() * (SKILL_STEP / 10)) - end - - -- All schools must be non zero to be able to use it - if ok == 0 then return min, "n/a" end - - -- Apply it - lvl = lvl + ok - num = num + 1 - end - - -- Add the Spellpower skill as a bonus - if allow_spell_power then - bonus = bonus + (get_skill_scale(SKILL_SPELL, 20) * (SKILL_STEP / 10)) - end - - -- Add bonus from objects - bonus = bonus + (player.to_s * (SKILL_STEP / 10)) - - -- / 10 because otherwise we can overflow a s32b and we can use a u32b because the value can be negative - -- The loss of information should be negligible since 1 skill = 1000 internally - lvl = (lvl / num) / 10 - lvl = lua_get_level(s, lvl, max, min, bonus) - - return lvl, nil -end - --- The real get_level, works for schooled magic and for innate powers -function get_level(s, max, min) - if not max then max = 50 end - if not min then min = 1 end - return %get_level(s, max, min) -end diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index a65db8ac..af4ba3d9 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -15,7 +15,9 @@ tome_dofile("stores.lua") tome_dofile("mkeys.lua") -- Add the schools of magic -tome_dofile("spells.lua") +schools_init() +school_spells_init() +init_school_books() -- Post-spell creation initialization initialize_bookable_spells() diff --git a/lib/mods/theme/scpt/spells.lua b/lib/mods/theme/scpt/spells.lua deleted file mode 100644 index e37d922f..00000000 --- a/lib/mods/theme/scpt/spells.lua +++ /dev/null @@ -1,385 +0,0 @@ --- --- This file takes care of the schools of magic --- - --- Create the schools -SCHOOL_MANA = add_school -{ - ["name"] = "Mana", - ["skill"] = SKILL_MANA, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Varda provides the Mana school at 1/4 the prayer skill - [GOD_VARDA] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 4, - }, - -- Eru Iluvatar provides the Mana school at half the prayer skill - [GOD_ERU] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 2, - }, - }, - ["hooks"] = - { - [HOOK_CALC_MANA] = function(msp) - if get_skill(SKILL_MANA) >= 35 then - msp = msp + (msp * ((get_skill(SKILL_MANA) - 34)) / 100) - return TRUE, msp - end - end - }, -} -SCHOOL_FIRE = add_school -{ - ["name"] = "Fire", - ["skill"] = SKILL_FIRE, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Aule provides the Fire school at 3/5 the prayer skill - [GOD_AULE] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 3, - ["div"] = 5, - }, - }, -} -SCHOOL_AIR = add_school -{ - ["name"] = "Air", - ["skill"] = SKILL_AIR, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Manwe Sulimo provides the Air school at 2/3 the prayer skill - [GOD_MANWE] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 2, - ["div"] = 3, - }, - }, -} -SCHOOL_WATER = add_school -{ - ["name"] = "Water", - ["skill"] = SKILL_WATER, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Yavanna Kementari provides the Water school at 1/2 the prayer skill - [GOD_YAVANNA] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 2, - }, - -- Ulmo provides the Water school at 3/5 the prayer skill - [GOD_ULMO] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 3, - ["div"] = 5, - }, - }, -} -SCHOOL_EARTH = add_school -{ - ["name"] = "Earth", - ["skill"] = SKILL_EARTH, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Tulkas provides the Earth school at 4/5 the prayer skill - [GOD_TULKAS] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 4, - ["div"] = 5, - }, - -- Yavanna Kementari provides the Earth school at 1/2 the prayer skill - [GOD_YAVANNA] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 2, - }, - - -- Aule provides the Earth school at 1/3 the prayer skill - [GOD_AULE] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 3, - }, - }, -} -SCHOOL_CONVEYANCE = add_school -{ - ["name"] = "Conveyance", - ["skill"] = SKILL_CONVEYANCE, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Manwe Sulimo provides the Conveyance school at 1/2 the prayer skill - [GOD_MANWE] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 2, - }, - }, -} -SCHOOL_GEOMANCY = add_school -{ - ["name"] = "Geomancy", - ["skill"] = SKILL_GEOMANCY, - ["spell_power"] = TRUE, - -- Require to wield a Mage Staff, as the spells requries the caster to stomp the floor with it - ["depend"] = function() - -- Require at least one point in each school - if get_skill(SKILL_FIRE) == 0 then return end - if get_skill(SKILL_AIR) == 0 then return end - if get_skill(SKILL_EARTH) == 0 then return end - if get_skill(SKILL_WATER) == 0 then return end - - local obj = get_object(INVEN_WIELD) - if (obj.k_idx > 0) and (obj.tval == TV_MSTAFF) then return TRUE end - end, -} -SCHOOL_DIVINATION = add_school -{ - ["name"] = "Divination", - ["skill"] = SKILL_DIVINATION, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Eru Iluvatar provides the Divination school at 2/3 the prayer skill - [GOD_ERU] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 2, - ["div"] = 3, - }, - -- Mandos the Divination school at 1/3 the prayer skill - [GOD_MANDOS] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 3, - }, - }, -} -SCHOOL_TEMPORAL = add_school -{ - ["name"] = "Temporal", - ["skill"] = SKILL_TEMPORAL, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Yavanna Kementari provides the Temporal school at 1/6 the prayer skill - [GOD_YAVANNA] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 6, - }, - -- Mandos provides the Temporal school at 1/4 the prayer skill - [GOD_MANDOS] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 4, - }, - }, -} -SCHOOL_NATURE = add_school -{ - ["name"] = "Nature", - ["skill"] = SKILL_NATURE, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Yavanna Kementari provides the Nature school at 1/2 the prayer skill - [GOD_YAVANNA] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 2, - }, - -- Ulmo provides the Nature school at 1/2 the prayer skill - [GOD_ULMO] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 2, - }, - }, -} -SCHOOL_META = add_school -{ - ["name"] = "Meta", - ["skill"] = SKILL_META, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Manwe Sulimo provides the Meta school at 1/3 the prayer skill - [GOD_MANWE] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 3, - }, - -- Varda provides the Meta school at 1/2 the prayer skill - [GOD_VARDA] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 2, - }, - }, -} -SCHOOL_MIND = add_school -{ - ["name"] = "Mind", - ["skill"] = SKILL_MIND, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Eru Iluvatar provides the Mind school at 1/3 the prayer skill - [GOD_ERU] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 3, - }, - -- Melkor Bauglir provides the Mind school at 1/3 the prayer skill - [GOD_MELKOR] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 3, - }, - }, -} -SCHOOL_UDUN = add_school -{ - ["name"] = "Udun", - ["skill"] = SKILL_UDUN, - ["bonus_level"] = function() - return ((player.lev * 2) / 3) - end, -} -SCHOOL_DEMON = add_school -{ - ["name"] = "Demon", - ["skill"] = SKILL_DAEMON, - ["no_random"] = TRUE, -} - --- The God specific schools, all tied to the prayer skill -SCHOOL_ERU = add_school -{ - ["name"] = "Eru Iluvatar", - ["skill"] = SKILL_PRAY, - ["spell_power"] = TRUE, - ["god"] = GOD_ERU, -} -SCHOOL_MANWE = add_school -{ - ["name"] = "Manwe Sulimo", - ["skill"] = SKILL_PRAY, - ["spell_power"] = TRUE, - ["god"] = GOD_MANWE, -} -SCHOOL_TULKAS = add_school -{ - ["name"] = "Tulkas", - ["skill"] = SKILL_PRAY, - ["spell_power"] = TRUE, - ["god"] = GOD_TULKAS, -} -SCHOOL_MELKOR = add_school -{ - ["name"] = "Melkor Bauglir", - ["skill"] = SKILL_PRAY, - ["spell_power"] = TRUE, - ["god"] = GOD_MELKOR, -} -SCHOOL_YAVANNA = add_school -{ - ["name"] = "Yavanna Kementari", - ["skill"] = SKILL_PRAY, - ["spell_power"] = TRUE, - ["god"] = GOD_YAVANNA, -} - --- New schools -SCHOOL_AULE = add_school -{ - ["name"] = "Aule the Smith", - ["skill"] = SKILL_PRAY, - ["spell_power"] = TRUE, - ["god"] = GOD_AULE, -} -SCHOOL_VARDA = add_school -{ - ["name"] = "Varda Elentari", - ["skill"] = SKILL_PRAY, - ["spell_power"] = TRUE, - ["god"] = GOD_VARDA, -} - -SCHOOL_ULMO = add_school -{ - ["name"] = "Ulmo", - ["skill"] = SKILL_PRAY, - ["spell_power"] = TRUE, - ["god"] = GOD_ULMO, -} - -SCHOOL_MANDOS = add_school -{ - ["name"] = "Mandos", - ["skill"] = SKILL_PRAY, - ["spell_power"] = TRUE, - ["god"] = GOD_MANDOS, -} - --- Not a real school, rather a palcehodler for stick only spells -SCHOOL_DEVICE = add_school -{ - ["name"] = "Device", - ["skill"] = SKILL_DEVICE, -} - --- Music "spells" -SCHOOL_MUSIC = add_school -{ - ["name"] = "Music", - ["skill"] = SKILL_MUSIC, -} - --- Initialize school spells. -school_spells_init() - --- Initialize spellbooks -init_school_books() diff --git a/lib/scpt/init.lua b/lib/scpt/init.lua index 55a6ce63..69fca70d 100644 --- a/lib/scpt/init.lua +++ b/lib/scpt/init.lua @@ -15,7 +15,9 @@ tome_dofile("stores.lua") tome_dofile("mkeys.lua") -- Add the schools of magic -tome_dofile("spells.lua") +schools_init() +school_spells_init() +init_school_books() -- Post-spell creation initialization initialize_bookable_spells() diff --git a/lib/scpt/spells.lua b/lib/scpt/spells.lua deleted file mode 100644 index 2ce7d1f3..00000000 --- a/lib/scpt/spells.lua +++ /dev/null @@ -1,293 +0,0 @@ --- --- This file takes care of the schools of magic --- - --- Create the schools -SCHOOL_MANA = add_school -{ - ["name"] = "Mana", - ["skill"] = SKILL_MANA, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Eru Iluvatar provides the Mana school at half the prayer skill - [GOD_ERU] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 2, - }, - }, - ["hooks"] = - { - [HOOK_CALC_MANA] = function(msp) - if get_skill(SKILL_MANA) >= 35 then - msp = msp + (msp * ((get_skill(SKILL_MANA) - 34)) / 100) - return TRUE, msp - end - end - }, -} -SCHOOL_FIRE = add_school -{ - ["name"] = "Fire", - ["skill"] = SKILL_FIRE, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, -} -SCHOOL_AIR = add_school -{ - ["name"] = "Air", - ["skill"] = SKILL_AIR, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Manwe Sulimo provides the Air school at 2/3 the prayer skill - [GOD_MANWE] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 2, - ["div"] = 3, - }, - }, -} -SCHOOL_WATER = add_school -{ - ["name"] = "Water", - ["skill"] = SKILL_WATER, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Yavanna Kementari provides the Water school at 1/2 the prayer skill - [GOD_YAVANNA] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 2, - }, - }, -} -SCHOOL_EARTH = add_school -{ - ["name"] = "Earth", - ["skill"] = SKILL_EARTH, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Tulkas provides the Earth school at 4/5 the prayer skill - [GOD_TULKAS] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 4, - ["div"] = 5, - }, - -- Yavanna Kementari provides the Earth school at 1/2 the prayer skill - [GOD_YAVANNA] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 2, - }, - }, -} -SCHOOL_CONVEYANCE = add_school -{ - ["name"] = "Conveyance", - ["skill"] = SKILL_CONVEYANCE, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Manwe Sulimo provides the Conveyance school at 1/2 the prayer skill - [GOD_MANWE] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 2, - }, - }, -} -SCHOOL_GEOMANCY = add_school -{ - ["name"] = "Geomancy", - ["skill"] = SKILL_GEOMANCY, - ["spell_power"] = TRUE, - -- Require to wield a Mage Staff, as the spells requries the caster to stomp the floor with it - ["depend"] = function() - -- Require at least one point in each school - if get_skill(SKILL_FIRE) == 0 then return end - if get_skill(SKILL_AIR) == 0 then return end - if get_skill(SKILL_EARTH) == 0 then return end - if get_skill(SKILL_WATER) == 0 then return end - - local obj = get_object(INVEN_WIELD) - if (obj.k_idx > 0) and (obj.tval == TV_MSTAFF) then return TRUE end - end, -} -SCHOOL_DIVINATION = add_school -{ - ["name"] = "Divination", - ["skill"] = SKILL_DIVINATION, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Eru Iluvatar provides the Divination school at 2/3 the prayer skill - [GOD_ERU] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 2, - ["div"] = 3, - }, - }, -} -SCHOOL_TEMPORAL = add_school -{ - ["name"] = "Temporal", - ["skill"] = SKILL_TEMPORAL, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Yavanna Kementari provides the Temporal school at 1/6 the prayer skill - [GOD_YAVANNA] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 6, - }, - }, -} -SCHOOL_NATURE = add_school -{ - ["name"] = "Nature", - ["skill"] = SKILL_NATURE, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Yavanna Kementari provides the Nature school at 1/2 the prayer skill - [GOD_YAVANNA] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 2, - }, - }, -} -SCHOOL_META = add_school -{ - ["name"] = "Meta", - ["skill"] = SKILL_META, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Manwe Sulimo provides the Meta school at 1/3 the prayer skill - [GOD_MANWE] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 3, - }, - }, -} -SCHOOL_MIND = add_school -{ - ["name"] = "Mind", - ["skill"] = SKILL_MIND, - ["spell_power"] = TRUE, - ["sorcery"] = TRUE, - ["gods"] = - { - -- Eru Iluvatar provides the Mind school at 1/3 the prayer skill - [GOD_ERU] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 3, - }, - -- Melkor Bauglir provides the Mind school at 1/3 the prayer skill - [GOD_MELKOR] = - { - ["skill"] = SKILL_PRAY, - ["mul"] = 1, - ["div"] = 3, - }, - }, -} -SCHOOL_UDUN = add_school -{ - ["name"] = "Udun", - ["skill"] = SKILL_UDUN, - ["bonus_level"] = function() - return ((player.lev * 2) / 3) - end, -} -SCHOOL_DEMON = add_school -{ - ["name"] = "Demon", - ["skill"] = SKILL_DAEMON, - ["no_random"] = TRUE, -} - --- The God specific schools, all tied to the prayer skill -SCHOOL_ERU = add_school -{ - ["name"] = "Eru Iluvatar", - ["skill"] = SKILL_PRAY, - ["spell_power"] = TRUE, - ["god"] = GOD_ERU, -} -SCHOOL_MANWE = add_school -{ - ["name"] = "Manwe Sulimo", - ["skill"] = SKILL_PRAY, - ["spell_power"] = TRUE, - ["god"] = GOD_MANWE, -} -SCHOOL_TULKAS = add_school -{ - ["name"] = "Tulkas", - ["skill"] = SKILL_PRAY, - ["spell_power"] = TRUE, - ["god"] = GOD_TULKAS, -} -SCHOOL_MELKOR = add_school -{ - ["name"] = "Melkor Bauglir", - ["skill"] = SKILL_PRAY, - ["spell_power"] = TRUE, - ["god"] = GOD_MELKOR, -} -SCHOOL_YAVANNA = add_school -{ - ["name"] = "Yavanna Kementari", - ["skill"] = SKILL_PRAY, - ["spell_power"] = TRUE, - ["god"] = GOD_YAVANNA, -} - --- Not a real school, rather a palcehodler for stick only spells -SCHOOL_DEVICE = add_school -{ - ["name"] = "Device", - ["skill"] = SKILL_DEVICE, -} - --- Music "spells" -SCHOOL_MUSIC = add_school -{ - ["name"] = "Music", - ["skill"] = SKILL_MUSIC, -} - --- Initialize school spells. -school_spells_init() - --- Initialize spellbooks -init_school_books() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d1648754..d84f94ba 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,7 +10,8 @@ SET(SRCS object1.c object2.c randart.c squeltch.c traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c - spells1.c spells2.c spells3.c spells4.c spells5.c corrupt.c mimic.c + spells1.c spells2.c spells3.c spells4.c spells5.c spells6.c + corrupt.c mimic.c status.c files.c notes.c loadsave.c string_list.c cmd1.c cmd2.c cmd3.c cmd4.c cmd5.c cmd6.c cmd7.c help.c range.c diff --git a/src/defines.h b/src/defines.h index 099d3fe1..9b0a512a 100644 --- a/src/defines.h +++ b/src/defines.h @@ -870,6 +870,11 @@ */ #define SCHOOL_SPELLS_MAX 200 +/* + * Maximum number of spell schools + */ +#define SCHOOLS_MAX 50 + /* * Number of effects */ diff --git a/src/externs.h b/src/externs.h index 8f55d3d8..95a91f05 100644 --- a/src/externs.h +++ b/src/externs.h @@ -566,8 +566,8 @@ extern s32b extra_savefile_parts; extern bool_ player_char_health; extern s16b school_spells_count; extern spell_type school_spells[SCHOOL_SPELLS_MAX]; -extern s16b max_schools; -extern school_type *schools; +extern s16b schools_count; +extern school_type schools[SCHOOLS_MAX]; extern int project_time; extern s32b project_time_effect; extern effect_type effects[MAX_EFFECTS]; @@ -970,7 +970,6 @@ extern errr process_dungeon_file(cptr name, int *yval, int *xval, int ymax, int /* init2.c */ extern void init_corruptions(); -extern void init_schools(s16b new_size); extern void reinit_gods(s16b new_size); extern void reinit_quests(s16b new_size); extern void create_stores_stock(int t); @@ -1966,8 +1965,16 @@ void dice_print(dice_type *dice, char *buf); void school_spells_init(); spell_type *spell_at(s32b index); s16b get_random_spell(s16b random_type, int lev); -bool_ check_spell_depends(s16b spell_idx); -int spell_get_school_idx(s16b spell_idx, int i); +bool_ check_spell_depends(spell_type *spell); + +/* spells6.c */ + +SGLIB_DEFINE_LIST_PROTOTYPES(school_provider, compare_school_provider, next); + +void schools_init(); +school_type *school_at(int index); + +void mana_school_calc_mana(int *msp); /* range.c */ extern void range_init(range_type *range, s32b min, s32b max); @@ -2371,9 +2378,7 @@ extern int get_lua_list_size(cptr list_name); extern bool_ get_com_lua(cptr promtp, int *com); -extern s16b new_school(int i, cptr name, s16b skill); -extern school_type *grab_school_type(s16b num); -extern s32b lua_get_level(s32b s, s32b lvl, s32b max, s32b min, s32b bonus); +extern s32b lua_get_level(spell_type *spell, s32b lvl, s32b max, s32b min, s32b bonus); extern s32b get_level_device(s32b s, s32b max, s32b min); extern int get_mana(s32b s); extern int get_power(s32b s); diff --git a/src/init2.c b/src/init2.c index f195c469..0ce8c1a0 100644 --- a/src/init2.c +++ b/src/init2.c @@ -1959,10 +1959,7 @@ static errr init_misc(void) /* Hack -- No messages yet */ message__tail = MESSAGE_BUF; - /* Prepare schools */ - max_schools = 0; - schools = NULL; - + /* Initialize game */ process_hooks(HOOK_INIT_GAME, "(s)", "begin"); /* Initialise the values */ @@ -2065,13 +2062,6 @@ static errr init_wilderness(void) return 0; } -void init_schools(s16b new_size) -{ - /* allocate the extra memory */ - C_MAKE(schools, new_size, school_type); - max_schools = new_size; -} - /* * Initialise some other arrays */ diff --git a/src/lua_bind.c b/src/lua_bind.c index 0c099c00..34a89613 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -168,25 +168,17 @@ bool_ get_com_lua(cptr prompt, int *com) return (TRUE); } -/* Spell schools */ -s16b new_school(int i, cptr name, s16b skill) -{ - schools[i].name = string_make(name); - schools[i].skill = skill; - return (i); -} - school_type *grab_school_type(s16b num) { return (&schools[num]); } /* Change this fct if I want to switch to learnable spells */ -s32b lua_get_level(s32b s, s32b lvl, s32b max, s32b min, s32b bonus) +s32b lua_get_level(spell_type *spell, s32b lvl, s32b max, s32b min, s32b bonus) { s32b tmp; - tmp = lvl - ((school_spells[s].skill_level - 1) * (SKILL_STEP / 10)); + tmp = lvl - ((spell->skill_level - 1) * (SKILL_STEP / 10)); if (tmp >= (SKILL_STEP / 10)) /* We require at least one spell level */ tmp += bonus; @@ -209,6 +201,7 @@ s32b lua_get_level(s32b s, s32b lvl, s32b max, s32b min, s32b bonus) s32b get_level_device(s32b s, s32b max, s32b min) { int lvl; + spell_type *spell = spell_at(s); /* No max specified ? assume 50 */ if (max <= 0) { @@ -223,16 +216,16 @@ s32b get_level_device(s32b s, s32b max, s32b min) lvl = lvl + (get_level_use_stick * SKILL_STEP); /* Sticks are limited */ - if (lvl - ((school_spells[s].skill_level + 1) * SKILL_STEP) >= get_level_max_stick * SKILL_STEP) + if (lvl - ((spell->skill_level + 1) * SKILL_STEP) >= get_level_max_stick * SKILL_STEP) { - lvl = (get_level_max_stick + school_spells[s].skill_level - 1) * SKILL_STEP; + lvl = (get_level_max_stick + spell->skill_level - 1) * SKILL_STEP; } /* / 10 because otherwise we can overflow a s32b and we can use a u32b because the value can be negative -- The loss of information should be negligible since 1 skill = 1000 internally */ lvl = lvl / 10; - lvl = lua_get_level(s, lvl, max, min, 0); + lvl = lua_get_level(spell, lvl, max, min, 0); return lvl; } @@ -257,19 +250,6 @@ s32b spell_chance(s32b s) } } -void get_level_school(s32b s, s32b max, s32b min, s32b *level, bool_ *na) -{ - if (level != NULL) - { - *level = exec_lua(format("local lvl, na = get_level_school(%d, %d, %d); return lvl", s, max, min)); - } - - if (na != NULL) - { - *na = exec_lua(format("local lvl, na = get_level_school(%d, %d, %d); return (na == \"n/a\")", s, max, min)); - } -} - s32b get_level(s32b s, s32b max, s32b min) { /** Ahah shall we use Magic device instead ? */ @@ -277,7 +257,8 @@ s32b get_level(s32b s, s32b max, s32b min) return get_level_device(s, max, min); } else { s32b level; - get_level_school(s, max, min, &level, NULL); + bool_ notused; + get_level_school(s, max, min, &level, ¬used); return level; } } diff --git a/src/script.c b/src/script.c index 51484d3a..4d066a58 100644 --- a/src/script.c +++ b/src/script.c @@ -226,14 +226,6 @@ void init_lua_init() /* Load the first lua file */ tome_dofile_anywhere(ANGBAND_DIR_CORE, "init.lua", TRUE); - /* Finish up schools */ - max = exec_lua("return __schools_num"); - init_schools(max); - for (i = 0; i < max; i++) - { - exec_lua(format("finish_school(%d)", i)); - } - /* Finish up the corruptions */ init_corruptions(); } diff --git a/src/spells.pkg b/src/spells.pkg index d7564618..7385accc 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2170,78 +2170,6 @@ struct spell_type@school_spell_type }; -/** @struct school_type - * @brief Spell school - */ -struct school_type -{ - /** @structvar name - * @brief String - * @note Name - */ - cptr name; - /** @structvar skill - * @brief Number - * @note Skil used for that school - */ - s16b skill; -}; - -/** @fn new_school(int i, cptr name, s16b skill) - * @dgonly - * @brief Add school to array of schools.\n - * @param i Number \n i is index of school array where school is added. - * There is no range checking. - * @brief Index - * @param name String \n name is the name of the school. - * @brief Name - * @param skill Number \n skill is the skill of the school. - * @brief Skill - * @return Number \ The index parameter. - * @note - * Note: do not call this function directly.\n - * Please use add_school() in s_aux.lua instead.\n - * By order of DG. - * @note (see file lua_bind.c) - */ -extern s16b new_school(int i, cptr name, s16b skill); - -/** @fn school(s16b num); - * @dgonly - * @brief Get school "num" from array of schools.\n - * @param num Number \n num is the index of the school. - * There is no range checking. - * @brief Index - * @return school_type \n The school. - * @note - * Note: do not call this function directly.\n - * By order of DG. - * @note (see file lua_bind.c) - */ -extern school_type *grab_school_type @ school(s16b num); - -/** @fn lua_get_level(s32b s, s32b lvl, s32b max, s32b min, s32b bonus) - * @dgonly - * @brief Get the casting level of school spell "s".\n - * @param s Number \n s is the index of the spell in array of school spells. - * There is no range checking. - * @brief Spell index - * @param lvl Number \n lvl represents the level of player skill. - * @brief Player skill level - * @param max Number \n max is the maximum level for the spell. - * @brief Maximum spell level - * @param min Number \n min is the minimum level for the spell. - * @brief Minimum spell level - * @param bonus Number \n bonus is any bonus to final level. - * @brief Bonus - * @return Number \n Casting level. - * @note - * Note: do not call this function directly.\n - * By order of DG. - * @note (see file lua_bind.c) - */ -extern s32b lua_get_level(s32b s, s32b lvl, s32b max, s32b min, s32b bonus); - /** Get level of device */ extern s32b get_level_device(s32b s, s32b max, s32b min); @@ -2344,5 +2272,8 @@ void spell_description_add_line(s32b spell_idx, cptr line); */ void school_spells_init(); s16b get_random_spell(s16b random_type, int lev); -bool check_spell_depends(s16b spell_idx); -int spell_get_school_idx(s16b spell_idx, int i); + +/** + * spells6.c + */ +void schools_init(); diff --git a/src/spells4.c b/src/spells4.c index 4fd51cbe..e58ac4ea 100644 --- a/src/spells4.c +++ b/src/spells4.c @@ -491,7 +491,7 @@ static void spell_school_name(char *buf, spell_type *spell) school_idx = sglib_school_idx_it_next(&sit)) { int sch = school_idx->i; - school_type *school = grab_school_type(sch); + school_type *school = school_at(sch); /* Add separator? */ if (!first) { diff --git a/src/spells5.c b/src/spells5.c index 821d4151..d2d9eda2 100644 --- a/src/spells5.c +++ b/src/spells5.c @@ -90,9 +90,10 @@ s16b get_random_spell(s16b random_type, int level) return -1; } -bool_ check_spell_depends(s16b spell_idx) +bool_ check_spell_depends(spell_type *spell) { - spell_type *spell = spell_at(spell_idx); + assert(spell != NULL); + if (spell->depend_func != NULL) { return spell->depend_func(); } else { @@ -100,34 +101,6 @@ bool_ check_spell_depends(s16b spell_idx) } } -int spell_get_school_idx(s16b spell_idx, int idx) -{ - spell_type *spell = spell_at(spell_idx); - school_idx *school_idx = NULL; - struct sglib_school_idx_iterator sit; - - if (idx < 0) - { - return -1; - } - - for (school_idx = sglib_school_idx_it_init(&sit, spell->schools); - school_idx != NULL && idx > 0; - school_idx = sglib_school_idx_it_next(&sit)) - { - /* Just counting down */ - } - - if (school_idx == NULL) - { - return -1; - } - else - { - return school_idx->i; - } -} - static void spell_init_music(spell_type *spell, s16b minimum_pval) { assert(spell != NULL); diff --git a/src/spells6.c b/src/spells6.c new file mode 100644 index 00000000..37e4c42c --- /dev/null +++ b/src/spells6.c @@ -0,0 +1,380 @@ +#include + +#include + +static int compare_school_provider(school_provider *a, school_provider *b) +{ + return SGLIB_NUMERIC_COMPARATOR(a->deity_idx, b->deity_idx); +} + +static void school_provider_init(school_provider *p, byte deity_idx, long mul, long div) +{ + assert(p != NULL); + + p->deity_idx = deity_idx; + p->skill_idx = SKILL_PRAY; + p->mul = mul; + p->div = div; + p->next = NULL; +} + +static school_provider *school_provider_new(byte deity_idx, long mul, long div) +{ + school_provider *p = malloc(sizeof(school_provider)); + school_provider_init(p, deity_idx, mul, div); + return p; +} + +SGLIB_DEFINE_LIST_FUNCTIONS(school_provider, compare_school_provider, next); + +school_type *school_at(int index) +{ + assert(index >= 0); + assert(index < schools_count); + + return &schools[index]; +} + +static void school_init(school_type *school, cptr name, s16b skill) +{ + assert(school != NULL); + + memset(school, 0, sizeof(school_type)); + + school->name = name; + school->skill = skill; + + school->deity_idx = -1; +} + +static school_type *school_new(s32b *school_idx, cptr name, s16b skill) +{ + assert(schools_count < SCHOOLS_MAX); + + *school_idx = schools_count; + schools_count++; + + school_type *school = &schools[*school_idx]; + school_init(school, name, skill); + + return school; +} + +static school_type *sorcery_school_new(s32b *school_idx, cptr name, s16b skill) +{ + school_type *school = school_new(school_idx, name, skill); + school->spell_power = TRUE; + school->sorcery = TRUE; + return school; +} + +static school_type *god_school_new(s32b *school_idx, byte god) +{ + school_type *school = NULL; + deity_type *deity = NULL; + + /* Get the god */ + deity = god_at(god); + assert(deity != NULL); + + /* Ignore gods which aren't enabled for this module. */ + if (god_enabled(deity)) + { + school = school_new(school_idx, deity->name, SKILL_PRAY); + school->spell_power = TRUE; + school->deity_idx = god; + school->deity = deity; + return school; + } + else + { + return NULL; + } +} + +static void school_god(school_type *school, byte god, int mul, int div) +{ + deity_type *deity = god_at(god); + assert(deity != NULL); + + /* Ignore gods which aren't enabled for this module. */ + if (god_enabled(deity)) + { + school_provider *school_provider = school_provider_new(god, mul, div); + sglib_school_provider_add(&school->providers, school_provider); + } +} + +static int udun_bonus_levels() +{ + return (p_ptr->lev * 2) / 3; +} + +static bool_ geomancy_depends_satisfied() +{ + object_type *o_ptr = NULL; + + /* Require at least one point in each school */ + if ((get_skill(SKILL_FIRE) <= 0) || + (get_skill(SKILL_AIR) <= 0) || + (get_skill(SKILL_EARTH) <= 0) || + (get_skill(SKILL_WATER) <= 0)) + { + return FALSE; + } + + /* Require to wield a Mage Staff, as the spells requries the + * caster to stomp the floor with it. */ + o_ptr = get_object(INVEN_WIELD); + + return ((o_ptr != NULL) && + (o_ptr->k_idx > 0) && + (o_ptr->tval == TV_MSTAFF)); +} + +long get_provided_levels(school_type *school) +{ + school_provider *school_provider = NULL; + struct sglib_school_provider_iterator school_provider_it; + + for (school_provider = sglib_school_provider_it_init(&school_provider_it, school->providers); + school_provider != NULL; + school_provider = sglib_school_provider_it_next(&school_provider_it)) + { + if (school_provider->deity_idx == p_ptr->pgod) + { + return (s_info[school_provider->skill_idx].value * school_provider->mul) / school_provider->div; + } + } + + return 0; +} + +void get_level_school(s32b spell_idx, s32b max, s32b min, s32b *level, bool_ *na) +{ + spell_type *spell = spell_at(spell_idx); + school_idx *school_idx = NULL; + struct sglib_school_idx_iterator sit; + bool_ allow_spell_power = TRUE; + long lvl, num, bonus; + + assert(level != NULL); + assert(na != NULL); + + lvl = 0; + num = 0; + bonus = 0; + + /* Do we pass tests? */ + if (!check_spell_depends(spell)) + { + *level = min; + *na = TRUE; + return; + } + + /* Go through all the spell's schools. */ + for (school_idx = sglib_school_idx_it_init(&sit, spell->schools); + school_idx != NULL; + school_idx = sglib_school_idx_it_next(&sit)) + { + school_type *school = school_at(school_idx->i); + long r = 0, s = 0, p = 0, ok = 0; + + /* Does it require we worship a specific god? */ + if ((school->deity_idx > 0) && + (school->deity_idx != p_ptr->pgod)) + { + *level = min; + *na = TRUE; + return; + } + + /* Take the basic skill value */ + r = s_info[school->skill].value; + + /* Do we pass tests? */ + if ((school->depends_satisfied != NULL) && + (!school->depends_satisfied())) + { + *level = min; + *na = TRUE; + return; + } + + /* Include effects of Sorcery (if applicable) */ + if (school->sorcery) + { + s = s_info[SKILL_SORCERY].value; + } + + /* Include effects of Spell Power? Every school must + * allow use of Spell Power for it to apply. */ + if (!school->spell_power) + { + allow_spell_power = FALSE; + } + + /* Calculate effects of provided levels */ + p = get_provided_levels(school); + + /* Find the highest of Skill, Sorcery and Provided levels. */ + ok = r; + if (ok < s) + { + ok = s; + } + if (ok < p) + { + ok = p; + } + + /* Do we need to add a special bonus? */ + if (school->bonus_levels != NULL) + { + bonus += (school->bonus_levels() * (SKILL_STEP / 10)); + } + + /* All schools must be non-zero to be able to use it. */ + if (ok <= 0) + { + *level = min; + *na = TRUE; + return; + } + + /* Apply it */ + lvl = lvl + ok; + num = num + 1; + } + + /* Add the Spellpower skill as a bonus on top */ + if (allow_spell_power) + { + bonus += (get_skill_scale(SKILL_SPELL, 20) * (SKILL_STEP / 10)); + } + + /* Add bonus from objects */ + bonus += (p_ptr->to_s * (SKILL_STEP / 10)); + + /* We divide by 10 because otherwise we can overflow a s32b + * and we can use a u32b because the value can be negative. + * The loss of information should be negligible since 1 skill + * point is 1000 internally. */ + lvl = (lvl / num) / 10; + lvl = lua_get_level(spell, lvl, max, min, bonus); + + /* Result */ + *level = lvl; + *na = FALSE; +} + +void schools_init() +{ + { + school_type *school = sorcery_school_new(&SCHOOL_MANA, "Mana", SKILL_MANA); + school_god(school, GOD_ERU, 1, 2); + school_god(school, GOD_VARDA, 1, 4); + } + + { + school_type *school = sorcery_school_new(&SCHOOL_FIRE, "Fire", SKILL_FIRE); + school_god(school, GOD_AULE, 3, 5); + } + + { + school_type *school = sorcery_school_new(&SCHOOL_AIR, "Air", SKILL_AIR); + school_god(school, GOD_MANWE, 2, 3); + } + + { + school_type *school = sorcery_school_new(&SCHOOL_WATER, "Water", SKILL_WATER); + school_god(school, GOD_YAVANNA, 1, 2); + school_god(school, GOD_ULMO, 3, 5); + } + + { + school_type *school = sorcery_school_new(&SCHOOL_EARTH, "Earth", SKILL_EARTH); + school_god(school, GOD_TULKAS, 4, 5); + school_god(school, GOD_YAVANNA, 1, 2); + } + + { + school_type *school = sorcery_school_new(&SCHOOL_CONVEYANCE, "Conveyance", SKILL_CONVEYANCE); + school_god(school, GOD_MANWE, 1, 2); + } + + { + school_type *school = school_new(&SCHOOL_GEOMANCY, "Geomancy", SKILL_GEOMANCY); + school->spell_power = TRUE; + school->depends_satisfied = geomancy_depends_satisfied; + } + + { + school_type *school = sorcery_school_new(&SCHOOL_DIVINATION, "Divination", SKILL_DIVINATION); + school_god(school, GOD_ERU, 2, 3); + school_god(school, GOD_MANDOS, 1, 3); + } + + { + school_type *school = sorcery_school_new(&SCHOOL_TEMPORAL, "Temporal", SKILL_TEMPORAL); + school_god(school, GOD_YAVANNA, 1, 6); + school_god(school, GOD_MANDOS, 1, 4); + } + + { + school_type *school = sorcery_school_new(&SCHOOL_NATURE, "Nature", SKILL_NATURE); + school_god(school, GOD_YAVANNA, 1, 2); + school_god(school, GOD_ULMO, 1, 2); + } + + { + school_type *school = sorcery_school_new(&SCHOOL_META, "Meta", SKILL_META); + school_god(school, GOD_MANWE, 1, 3); + school_god(school, GOD_VARDA, 1, 2); + } + + { + school_type *school = sorcery_school_new(&SCHOOL_MIND, "Mind", SKILL_MIND); + school_god(school, GOD_ERU, 1, 3); + school_god(school, GOD_MELKOR, 1, 3); + } + + { + school_type *school = school_new(&SCHOOL_UDUN, "Udun", SKILL_UDUN); + school->bonus_levels = udun_bonus_levels; + } + + { + school_new(&SCHOOL_DEMON, "Demon", SKILL_DAEMON); + } + + /* God-specific schools; all with a standard setup */ + { + god_school_new(&SCHOOL_ERU, GOD_ERU); + god_school_new(&SCHOOL_MANWE, GOD_MANWE); + god_school_new(&SCHOOL_TULKAS, GOD_TULKAS); + god_school_new(&SCHOOL_MELKOR, GOD_MELKOR); + god_school_new(&SCHOOL_YAVANNA, GOD_YAVANNA); + + god_school_new(&SCHOOL_AULE, GOD_AULE); + god_school_new(&SCHOOL_VARDA, GOD_VARDA); + god_school_new(&SCHOOL_ULMO, GOD_ULMO); + god_school_new(&SCHOOL_MANDOS, GOD_MANDOS); + } + + /* Placeholder schools */ + { + school_new(&SCHOOL_DEVICE, "Device", SKILL_DEVICE); + school_new(&SCHOOL_DEVICE, "Music", SKILL_MUSIC); + } + +} + +void mana_school_calc_mana(int *msp) +{ + if (get_skill(SKILL_MANA) >= 35) + { + *msp = *msp + (*msp * ((get_skill(SKILL_MANA) - 34)) / 100); + } +} diff --git a/src/types.h b/src/types.h index ed86a4af..5173a89c 100644 --- a/src/types.h +++ b/src/types.h @@ -2568,11 +2568,36 @@ struct spell_type school_idx *schools; }; +typedef struct school_provider school_provider; +struct school_provider +{ + byte deity_idx; /* Deity which provides school levels */ + + s16b skill_idx; /* Skill used for determining the boost */ + + long mul; /* Multiplier */ + + long div; /* Divisor */ + + school_provider *next; /* Next provider in list */ +}; + typedef struct school_type school_type; struct school_type { cptr name; /* Name */ s16b skill; /* Skill used for that school */ + bool_ spell_power; /* Does spell power affect spells in this school? */ + bool_ sorcery; /* Does Sorcery affect this school? */ + + int deity_idx; /* Deity; if <=0, no deity required */ + deity_type *deity; /* Direct pointer to deity */ + + int (*bonus_levels)(); /* Calculate number of bonus levels */ + + bool_ (*depends_satisfied)(); /* Are dependendies satisfied? */ + + school_provider *providers; /* List of secondary providers of this school */ }; /* diff --git a/src/variable.c b/src/variable.c index 71fb5dd8..417fb975 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1500,8 +1500,8 @@ bool_ player_char_health; */ s16b school_spells_count = 0; spell_type school_spells[SCHOOL_SPELLS_MAX]; -s16b max_schools; -school_type *schools; +s16b schools_count = 0; +school_type schools[SCHOOLS_MAX]; /* * Lasting spell effects diff --git a/src/xtra1.c b/src/xtra1.c index f393635f..4ccdf08e 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -1793,6 +1793,7 @@ static void calc_mana(void) msp = process_hooks_return[0].num; } + mana_school_calc_mana(&msp); meta_inertia_control_calc_mana(&msp); /* Mana can never be negative */ -- cgit v1.2.3 From 3f78069df10241f1111e171ab9d1db40b33b5774 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 31 May 2012 20:23:37 +0200 Subject: Lua: Move Theme winged race armor restriction to C. --- lib/mods/theme/scpt/misc.lua | 11 ----------- src/object1.c | 18 ++++++++++++++++++ 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/lib/mods/theme/scpt/misc.lua b/lib/mods/theme/scpt/misc.lua index 17eba40f..a41f9288 100644 --- a/lib/mods/theme/scpt/misc.lua +++ b/lib/mods/theme/scpt/misc.lua @@ -54,17 +54,6 @@ end add_hook_script(HOOK_GIVE, "drunk_takes_wine", "drunk_takes_wine") --- winged races are allowed soft armor only, no cloaks (from T-Plus) -function __hook_wings_wear(obj) - local str = get_race_name() - local type = obj.tval - if (str == "Dragon" or str == "Eagle") and (type == 35 or type == 37 or type == 38) then - return TRUE, -1 - end -end - -add_hook_script(HOOK_WIELD_SLOT, "__hook_wings_wear", "__hook_wings_wear") - -- A not-too-scummy way of generating junk for ammo function food_vessel(object) if ((object.tval == 80) and (object.sval == 43)) or diff --git a/src/object1.c b/src/object1.c index a4676744..63789794 100644 --- a/src/object1.c +++ b/src/object1.c @@ -4029,6 +4029,24 @@ s16b wield_slot_ideal(object_type *o_ptr, bool_ ideal) if (process_hooks_ret(HOOK_WIELD_SLOT, "d", "(O,d)", o_ptr, ideal)) return process_hooks_return[0].num; + /* Theme has restrictions for winged races. */ + if (game_module_idx == MODULE_THEME) + { + cptr race_name = rp_ptr->title + rp_name; + + if (streq(race_name, "Dragon") || + streq(race_name, "Eagle")) + { + switch (o_ptr->tval) + { + case TV_CLOAK: + case TV_HARD_ARMOR: + case TV_DRAG_ARMOR: + return -1; + } + } + } + /* Slot for equipment */ switch (o_ptr->tval) { -- cgit v1.2.3 From 53bf1478ad25f03d6df584371b0653f83ead1b6d Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 1 Jun 2012 05:37:37 +0200 Subject: Lua: Move "Temple" and "Magic shop" hook code to C --- lib/mods/theme/scpt/stores.lua | 27 --------------------------- lib/scpt/stores.lua | 27 --------------------------- src/store.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 54 deletions(-) diff --git a/lib/mods/theme/scpt/stores.lua b/lib/mods/theme/scpt/stores.lua index 4902c4d0..61a97f5a 100644 --- a/lib/mods/theme/scpt/stores.lua +++ b/lib/mods/theme/scpt/stores.lua @@ -132,30 +132,3 @@ store_buy_list TV_INSTRUMENT, }, } - --- Take care to have Magic shop/Temple have specific spells only -add_hooks -{ - [HOOK_STORE_STOCK] = function (index, name, level) - if name == "Magic shop" then - -- Books - if magik(20) == TRUE then - object_prep(obj_forge, lookup_kind(TV_BOOK, 255)) - local spell = get_random_spell(SKILL_MAGIC, 20) - if spell > -1 then - obj_forge.pval = spell - return TRUE, obj_forge - end - end - elseif name == "Temple" then - if magik(20) == TRUE then - object_prep(obj_forge, lookup_kind(TV_BOOK, 255)) - local spell = get_random_spell(SKILL_SPIRITUALITY, 20) - if spell > -1 then - obj_forge.pval = spell - return TRUE, obj_forge - end - end - end - end, -} diff --git a/lib/scpt/stores.lua b/lib/scpt/stores.lua index 03d29e6e..d10ee5ad 100644 --- a/lib/scpt/stores.lua +++ b/lib/scpt/stores.lua @@ -103,30 +103,3 @@ store_buy_list TV_EGG, }, } - --- Take care to have Magic shop/Temple have specific spells only -add_hooks -{ - [HOOK_STORE_STOCK] = function (index, name, level) - if name == "Magic shop" then - -- Books - if magik(20) == TRUE then - object_prep(obj_forge, lookup_kind(TV_BOOK, 255)) - local spell = get_random_spell(SKILL_MAGIC, 20) - if spell > -1 then - obj_forge.pval = spell - return TRUE, obj_forge - end - end - elseif name == "Temple" then - if magik(20) == TRUE then - object_prep(obj_forge, lookup_kind(TV_BOOK, 255)) - local spell = get_random_spell(SKILL_SPIRITUALITY, 20) - if spell > -1 then - obj_forge.pval = spell - return TRUE, obj_forge - end - end - end - end, -} diff --git a/src/store.c b/src/store.c index 78120846..d290785a 100644 --- a/src/store.c +++ b/src/store.c @@ -1164,6 +1164,38 @@ static void store_create(void) q_ptr = process_hooks_return[0].o_ptr; } + /* Magic Shop */ + else if (streq(st_info[st_ptr->st_idx].name + st_name, "Magic shop") && + magik(20)) + { + s16b spell; + + object_prep(&forge, lookup_kind(TV_BOOK, BOOK_RANDOM)); + spell = get_random_spell(SKILL_MAGIC, 20); + assert (spell > -1); + forge.pval = spell; + + /* Use the forged object */ + q_ptr = &forge; + obj_all_done = TRUE; + } + + /* Temple */ + else if (streq(st_info[st_ptr->st_idx].name + st_name, "Temple") && + magik(20)) + { + s16b spell; + + object_prep(&forge, lookup_kind(TV_BOOK, BOOK_RANDOM)); + spell = get_random_spell(SKILL_SPIRITUALITY, 20); + assert(spell > -1); + forge.pval = spell; + + /* Use the forged object */ + q_ptr = &forge; + obj_all_done = TRUE; + } + /* Black Market */ else if (st_info[st_ptr->st_idx].flags1 & SF1_ALL_ITEM) { -- cgit v1.2.3 From 3756182bf99335d02f7872c105b5ae5f9b5c4e57 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 2 Jun 2012 21:46:20 +0200 Subject: Lua: Move store handling to C --- lib/core/init.lua | 3 - lib/core/stores.lua | 32 ------- lib/mods/theme/core/init.lua | 3 - lib/mods/theme/core/stores.lua | 32 ------- lib/mods/theme/scpt/init.lua | 3 - lib/mods/theme/scpt/stores.lua | 134 -------------------------- lib/scpt/init.lua | 3 - lib/scpt/stores.lua | 105 -------------------- src/defines.h | 9 -- src/store.c | 211 ++++++++++++++++++++++++++++++++++++++++- src/util.pkg | 18 ---- 11 files changed, 206 insertions(+), 347 deletions(-) delete mode 100644 lib/core/stores.lua delete mode 100644 lib/mods/theme/core/stores.lua delete mode 100644 lib/mods/theme/scpt/stores.lua delete mode 100644 lib/scpt/stores.lua diff --git a/lib/core/init.lua b/lib/core/init.lua index 23c76461..c87f9a20 100644 --- a/lib/core/init.lua +++ b/lib/core/init.lua @@ -20,9 +20,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") -- Load the ingame contextual help tome_dofile_anywhere(ANGBAND_DIR_CORE, "help.lua") --- let the store specific stuff happen! -tome_dofile_anywhere(ANGBAND_DIR_CORE, "stores.lua") - -------------------------------------------------------------- -------------------------------------------------------------- -------------------------------------------------------------- diff --git a/lib/core/stores.lua b/lib/core/stores.lua deleted file mode 100644 index d4a63168..00000000 --- a/lib/core/stores.lua +++ /dev/null @@ -1,32 +0,0 @@ --- Take care of all concerning stores -function store_buy_list(t) - assert(type(t) == "table", "store_buy_list got no table") - add_hooks - { - [HOOK_STORE_BUY] = function (index, name, obj) - local tbl = %t - local elt = tbl[index] - if not elt then - elt = tbl[name] - end - if elt then - if elt then - if type(elt) == "function" then - return TRUE, elt(obj) - elseif type(elt) == "table" then - local k, e - for k, e in elt do - if type(e) == "number" then - if obj.tval == e then return TRUE, TRUE end - else - if (obj.tval == e[1]) and (obj.sval >= e[2]) and (obj.sval <= e[3]) then return TRUE, TRUE end - end - end - elseif elt == -1 then - return TRUE, FALSE - end - end - end - end, - } -end diff --git a/lib/mods/theme/core/init.lua b/lib/mods/theme/core/init.lua index 23c76461..c87f9a20 100644 --- a/lib/mods/theme/core/init.lua +++ b/lib/mods/theme/core/init.lua @@ -20,9 +20,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") -- Load the ingame contextual help tome_dofile_anywhere(ANGBAND_DIR_CORE, "help.lua") --- let the store specific stuff happen! -tome_dofile_anywhere(ANGBAND_DIR_CORE, "stores.lua") - -------------------------------------------------------------- -------------------------------------------------------------- -------------------------------------------------------------- diff --git a/lib/mods/theme/core/stores.lua b/lib/mods/theme/core/stores.lua deleted file mode 100644 index d4a63168..00000000 --- a/lib/mods/theme/core/stores.lua +++ /dev/null @@ -1,32 +0,0 @@ --- Take care of all concerning stores -function store_buy_list(t) - assert(type(t) == "table", "store_buy_list got no table") - add_hooks - { - [HOOK_STORE_BUY] = function (index, name, obj) - local tbl = %t - local elt = tbl[index] - if not elt then - elt = tbl[name] - end - if elt then - if elt then - if type(elt) == "function" then - return TRUE, elt(obj) - elseif type(elt) == "table" then - local k, e - for k, e in elt do - if type(e) == "number" then - if obj.tval == e then return TRUE, TRUE end - else - if (obj.tval == e[1]) and (obj.sval >= e[2]) and (obj.sval <= e[3]) then return TRUE, TRUE end - end - end - elseif elt == -1 then - return TRUE, FALSE - end - end - end - end, - } -end diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index af4ba3d9..64b1c6a5 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -8,9 +8,6 @@ tome_dofile("player.lua") -- Load the ingame contextual help tome_dofile("help.lua") --- let the store specific stuff happen! -tome_dofile("stores.lua") - -- Add the mkey activations tome_dofile("mkeys.lua") diff --git a/lib/mods/theme/scpt/stores.lua b/lib/mods/theme/scpt/stores.lua deleted file mode 100644 index 61a97f5a..00000000 --- a/lib/mods/theme/scpt/stores.lua +++ /dev/null @@ -1,134 +0,0 @@ --- Whats shops can buy what -store_buy_list -{ - ["General Store"] = - { - TV_CORPSE, - TV_FOOD, - TV_LITE, - TV_FLASK, - TV_SPIKE, - TV_SHOT, - TV_ARROW, - TV_BOLT, - TV_DIGGING, - TV_CLOAK, - TV_BOTTLE, - }, - ["Armoury"] = - { - TV_BOOTS, - TV_GLOVES, - TV_CROWN, - TV_HELM, - TV_SHIELD, - TV_CLOAK, - TV_SOFT_ARMOR, - TV_HARD_ARMOR, - TV_DRAG_ARMOR, - }, - ["Weaponsmith"] = - { - TV_SHOT, - TV_BOLT, - TV_ARROW, - TV_BOOMERANG, - TV_BOW, - TV_DIGGING, - TV_HAFTED, - TV_POLEARM, - TV_SWORD, - TV_AXE, - TV_MSTAFF, - }, - -- We use a function because we want to restrict to blessed weapons and god spells - ["Temple"] = function (obj) - if obj.tval == TV_DRUID_BOOK then return TRUE - elseif obj.tval == TV_BOOK and obj.sval == 255 and (can_spell_random(obj.pval) == SKILL_SPIRITUALITY) then return TRUE - elseif obj.tval == TV_SCROLL then return TRUE - elseif obj.tval == TV_POTION2 then return TRUE - elseif obj.tval == TV_POTION then return TRUE - elseif obj.tval == TV_HAFTED then return TRUE - elseif obj.tval == TV_POLEARM and is_blessed(obj) == TRUE then return TRUE - elseif obj.tval == TV_SWORD and is_blessed(obj) == TRUE then return TRUE - elseif obj.tval == TV_AXE and is_blessed(obj) == TRUE then return TRUE - elseif obj.tval == TV_BOOMERANG and is_blessed(obj) == TRUE then return TRUE - end - end, - ["Alchemy shop"] = - { - TV_SCROLL, - TV_POTION2, - TV_POTION, - TV_BATERIE, - TV_BOTTLE, - }, - -- We use a function because we dont want god spells - ["Magic shop"] = function (obj) - local buy = - { - [TV_SYMBIOTIC_BOOK] = TRUE, - [TV_AMULET] = TRUE, - [TV_RING] = TRUE, - [TV_STAFF] = TRUE, - [TV_WAND] = TRUE, - [TV_ROD] = TRUE, - [TV_ROD_MAIN] = TRUE, - [TV_SCROLL] = TRUE, - [TV_POTION2] = TRUE, - [TV_POTION] = TRUE, - [TV_MSTAFF] = TRUE, - [TV_RANDART] = TRUE, - } - - if obj.tval == TV_BOOK and obj.sval == 255 and (can_spell_random(obj.pval) == SKILL_MAGIC) then return TRUE - elseif obj.tval == TV_BOOK and obj.sval ~= 255 then return TRUE - elseif buy[obj.tval] == TRUE then return TRUE - end - end, - -- Black markets wants ALL! - ["Black Market"] = function (obj) - return TRUE - end, - ["Book Store"] = - { - TV_BOOK, - TV_SYMBIOTIC_BOOK, - TV_MUSIC_BOOK, - TV_DAEMON_BOOK, - TV_DRUID_BOOK, - }, - ["Pet Shop"] = - { - TV_EGG, - }, --- Theme stores - - ["Hunting Supply Store"] = - { - TV_TRAPKIT, - TV_BOOMERANG, - TV_SHOT, - TV_BOLT, - TV_ARROW, - TV_BOW, - TV_POTION2, - }, - - ["Runic Magic Shop"] = - { - TV_RUNE1, - TV_RUNE2, - }, - - ["Construction Supply Store"] = - { - TV_LITE, - TV_DIGGING, - }, - - ["Music Store"] = - { - TV_INSTRUMENT, - }, -} diff --git a/lib/scpt/init.lua b/lib/scpt/init.lua index 69fca70d..079d064d 100644 --- a/lib/scpt/init.lua +++ b/lib/scpt/init.lua @@ -8,9 +8,6 @@ tome_dofile("player.lua") -- Load the ingame contextual help tome_dofile("help.lua") --- let the store specific stuff happen! -tome_dofile("stores.lua") - -- Add the mkey activations tome_dofile("mkeys.lua") diff --git a/lib/scpt/stores.lua b/lib/scpt/stores.lua deleted file mode 100644 index d10ee5ad..00000000 --- a/lib/scpt/stores.lua +++ /dev/null @@ -1,105 +0,0 @@ --- Whats shops can buy what -store_buy_list -{ - ["General Store"] = - { - TV_CORPSE, - TV_FOOD, - TV_LITE, - TV_FLASK, - TV_SPIKE, - TV_SHOT, - TV_ARROW, - TV_BOLT, - TV_DIGGING, - TV_CLOAK, - TV_BOTTLE, - }, - ["Armoury"] = - { - TV_BOOTS, - TV_GLOVES, - TV_CROWN, - TV_HELM, - TV_SHIELD, - TV_CLOAK, - TV_SOFT_ARMOR, - TV_HARD_ARMOR, - TV_DRAG_ARMOR, - }, - ["Weaponsmith"] = - { - TV_SHOT, - TV_BOLT, - TV_ARROW, - TV_BOOMERANG, - TV_BOW, - TV_DIGGING, - TV_HAFTED, - TV_POLEARM, - TV_SWORD, - TV_AXE, - TV_MSTAFF, - }, - -- We use a function because we want to restrict to blessed weapons and god spells - ["Temple"] = function (obj) - if obj.tval == TV_DRUID_BOOK then return TRUE - elseif obj.tval == TV_BOOK and obj.sval == 255 and (can_spell_random(obj.pval) == SKILL_SPIRITUALITY) then return TRUE - elseif obj.tval == TV_SCROLL then return TRUE - elseif obj.tval == TV_POTION2 then return TRUE - elseif obj.tval == TV_POTION then return TRUE - elseif obj.tval == TV_HAFTED then return TRUE - elseif obj.tval == TV_POLEARM and is_blessed(obj) == TRUE then return TRUE - elseif obj.tval == TV_SWORD and is_blessed(obj) == TRUE then return TRUE - elseif obj.tval == TV_AXE and is_blessed(obj) == TRUE then return TRUE - elseif obj.tval == TV_BOOMERANG and is_blessed(obj) == TRUE then return TRUE - end - end, - ["Alchemy shop"] = - { - TV_SCROLL, - TV_POTION2, - TV_POTION, - TV_BATERIE, - TV_BOTTLE, - }, - -- We use a function because we dont want god spells - ["Magic shop"] = function (obj) - local buy = - { - [TV_SYMBIOTIC_BOOK] = TRUE, - [TV_AMULET] = TRUE, - [TV_RING] = TRUE, - [TV_STAFF] = TRUE, - [TV_WAND] = TRUE, - [TV_ROD] = TRUE, - [TV_ROD_MAIN] = TRUE, - [TV_SCROLL] = TRUE, - [TV_POTION2] = TRUE, - [TV_POTION] = TRUE, - [TV_MSTAFF] = TRUE, - [TV_RANDART] = TRUE, - } - - if obj.tval == TV_BOOK and obj.sval == 255 and (can_spell_random(obj.pval) == SKILL_MAGIC) then return TRUE - elseif obj.tval == TV_BOOK and obj.sval ~= 255 then return TRUE - elseif buy[obj.tval] == TRUE then return TRUE - end - end, - -- Black markets wants ALL! - ["Black Market"] = function (obj) - return TRUE - end, - ["Book Store"] = - { - TV_BOOK, - TV_SYMBIOTIC_BOOK, - TV_MUSIC_BOOK, - TV_DAEMON_BOOK, - TV_DRUID_BOOK, - }, - ["Pet Shop"] = - { - TV_EGG, - }, -} diff --git a/src/defines.h b/src/defines.h index 9b0a512a..9c0ba654 100644 --- a/src/defines.h +++ b/src/defines.h @@ -142,15 +142,7 @@ * Total number of stores (see "store.c", etc) */ #define STORE_GENERAL 0 -#define STORE_ARMOURY 1 -#define STORE_WEAPON 2 -#define STORE_TEMPLE 3 -#define STORE_ALCHEMIST 4 -#define STORE_MAGIC 5 -#define STORE_BLACK 6 #define STORE_HOME 7 -#define STORE_BOOK 8 -#define STORE_PET 9 /* * Maximum number of player "sex" types (see "table.c", etc) @@ -4505,7 +4497,6 @@ #define HOOK_BUILDING_ACTION 44 #define HOOK_WIELD_SLOT 46 #define HOOK_STORE_STOCK 47 -#define HOOK_STORE_BUY 48 #define HOOK_GEN_LEVEL_BEGIN 49 #define HOOK_GET 50 #define HOOK_REDRAW 51 diff --git a/src/store.c b/src/store.c index d290785a..e62701d9 100644 --- a/src/store.c +++ b/src/store.c @@ -12,6 +12,19 @@ #include "angband.h" +#define STORE_GENERAL_STORE "General Store" +#define STORE_ARMOURY "Armoury" +#define STORE_WEAPONSMITH "Weaponsmith" +#define STORE_TEMPLE "Temple" +#define STORE_ALCHEMY "Alchemy shop" +#define STORE_MAGIC "Magic shop" +#define STORE_BLACK_MARKET "Black Market" +#define STORE_BOOKS "Book Store" +#define STORE_PETS "Pet Shop" +#define STORE_HUNTING_SUPPLIES "Hunting Supply Store" +#define STORE_RUNIC_MAGIC "Runic Magic Shop" +#define STORE_CONSTRUCTION_SUPPLIES "Construction Supply Store" +#define STORE_MUSIC "Music Store" #define RUMOR_CHANCE 8 @@ -742,6 +755,8 @@ bool_ is_blessed(object_type *o_ptr) */ static bool_ store_will_buy(object_type *o_ptr) { + cptr store_name = st_info[st_ptr->st_idx].name + st_name; + /* Hack -- The Home is simple */ if (cur_store_num == 7) return (TRUE); @@ -750,10 +765,196 @@ static bool_ store_will_buy(object_type *o_ptr) /* XXX XXX XXX Ignore "worthless" items */ if (object_value(o_ptr) <= 0) return (FALSE); - /* Lua can define things to buy */ - if (process_hooks_ret(HOOK_STORE_BUY, "d", "(d,s,O)", st_ptr->st_idx, st_info[st_ptr->st_idx].name + st_name, o_ptr)) + /* What do stores buy? */ + if (streq(store_name, STORE_GENERAL_STORE)) + { + switch (o_ptr->tval) + { + case TV_CORPSE: + case TV_FOOD: + case TV_LITE: + case TV_FLASK: + case TV_SPIKE: + case TV_SHOT: + case TV_ARROW: + case TV_BOLT: + case TV_DIGGING: + case TV_CLOAK: + case TV_BOTTLE: + return TRUE; + } + } + else if (streq(store_name, STORE_ARMOURY)) + { + switch (o_ptr->tval) + { + case TV_BOOTS: + case TV_GLOVES: + case TV_CROWN: + case TV_HELM: + case TV_SHIELD: + case TV_CLOAK: + case TV_SOFT_ARMOR: + case TV_HARD_ARMOR: + case TV_DRAG_ARMOR: + return TRUE; + } + } + else if (streq(store_name, STORE_WEAPONSMITH)) + { + switch (o_ptr->tval) + { + case TV_SHOT: + case TV_BOLT: + case TV_ARROW: + case TV_BOOMERANG: + case TV_BOW: + case TV_DIGGING: + case TV_HAFTED: + case TV_POLEARM: + case TV_SWORD: + case TV_AXE: + case TV_MSTAFF: + return TRUE; + } + } + else if (streq(store_name, STORE_TEMPLE)) + { + switch (o_ptr->tval) + { + case TV_DRUID_BOOK: + case TV_SCROLL: + case TV_POTION2: + case TV_POTION: + case TV_HAFTED: + return TRUE; + } + + if ((o_ptr->tval == TV_BOOK) && + (o_ptr->sval == BOOK_RANDOM) && + (can_spell_random(o_ptr->pval) == SKILL_SPIRITUALITY)) + { + return TRUE; + } + else if ((o_ptr->tval == TV_POLEARM) && + is_blessed(o_ptr)) + { + return TRUE; + } + else if ((o_ptr->tval == TV_SWORD) && + is_blessed(o_ptr)) + { + return TRUE; + } + else if ((o_ptr->tval == TV_AXE) && + is_blessed(o_ptr)) + { + return TRUE; + } + else if ((o_ptr->tval == TV_BOOMERANG) && + is_blessed(o_ptr)) + { + return TRUE; + } + } + else if (streq(store_name, STORE_ALCHEMY)) + { + switch (o_ptr->tval) + { + case TV_SCROLL: + case TV_POTION2: + case TV_POTION: + case TV_BATERIE: + case TV_BOTTLE: + return TRUE; + } + } + else if (streq(store_name, STORE_MAGIC)) + { + switch (o_ptr->tval) + { + case TV_SYMBIOTIC_BOOK: + case TV_AMULET: + case TV_RING: + case TV_STAFF: + case TV_WAND: + case TV_ROD: + case TV_ROD_MAIN: + case TV_SCROLL: + case TV_POTION2: + case TV_POTION: + case TV_MSTAFF: + case TV_RANDART: + return TRUE; + } + + if ((o_ptr->tval == TV_BOOK) && + (o_ptr->sval == BOOK_RANDOM) && + (can_spell_random(o_ptr->pval) == SKILL_MAGIC)) + { + return TRUE; + } + else if ((o_ptr->tval == TV_BOOK) && + (o_ptr->sval != BOOK_RANDOM)) + { + return TRUE; + } + } + else if (streq(store_name, STORE_BLACK_MARKET)) + { + return TRUE; + } + else if (streq(store_name, STORE_BOOKS)) + { + switch (o_ptr->tval) + { + case TV_BOOK: + case TV_SYMBIOTIC_BOOK: + case TV_MUSIC_BOOK: + case TV_DAEMON_BOOK: + case TV_DRUID_BOOK: + return TRUE; + } + } + else if (streq(store_name, STORE_PETS)) + { + return (o_ptr->tval == TV_EGG); + } + else if (streq(store_name, STORE_HUNTING_SUPPLIES)) + { + switch (o_ptr->tval) + { + case TV_TRAPKIT: + case TV_BOOMERANG: + case TV_SHOT: + case TV_BOLT: + case TV_ARROW: + case TV_BOW: + case TV_POTION2: + return TRUE; + } + } + else if (streq(store_name, STORE_RUNIC_MAGIC)) + { + switch (o_ptr->tval) + { + case TV_RUNE1: + case TV_RUNE2: + return TRUE; + } + } + else if (streq(store_name, STORE_CONSTRUCTION_SUPPLIES)) + { + switch (o_ptr->tval) + { + case TV_LITE: + case TV_DIGGING: + return TRUE; + } + } + else if (streq(store_name, STORE_MUSIC)) { - return process_hooks_return[0].num; + return (o_ptr->tval == TV_INSTRUMENT); } /* Assume not okay */ @@ -1165,7 +1366,7 @@ static void store_create(void) } /* Magic Shop */ - else if (streq(st_info[st_ptr->st_idx].name + st_name, "Magic shop") && + else if (streq(st_info[st_ptr->st_idx].name + st_name, STORE_MAGIC) && magik(20)) { s16b spell; @@ -1181,7 +1382,7 @@ static void store_create(void) } /* Temple */ - else if (streq(st_info[st_ptr->st_idx].name + st_name, "Temple") && + else if (streq(st_info[st_ptr->st_idx].name + st_name, STORE_TEMPLE) && magik(20)) { s16b spell; diff --git a/src/util.pkg b/src/util.pkg index a32ef927..cb49a3e3 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -556,24 +556,6 @@ typedef unsigned int u32b; */ #define HOOK_STORE_STOCK 47 -/** @def HOOK_STORE_BUY - * @brief Store buys an item.\n - * @param Number st_idx \n the index of the store in st_info array. - * @brief Store index - * @param String name \n the name of the store. - * @brief Store name - * @param Object o_ptr \n the object to buy. - * @brief Object - * @return Boolean \n TRUE if the hook has processed the object, otherwise - * FALSE. - * @return Number buy \n TRUE if the store will buy the object, otherwise - * FALSE. - * @note - * If the hook returns TRUE, store_will_buy() will return "buy". - * @note (see file store.c) - */ -#define HOOK_STORE_BUY 48 - /** @def HOOK_GEN_LEVEL_BEGIN * @brief Generate a random dungeon level. * @note (see file generate.c) -- cgit v1.2.3 From 6c7a878b3a522f554ec7b11cb1cad929676d97ff Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 7 Jun 2012 19:42:13 +0200 Subject: Lua: Add new-style hooks. --- src/defines.h | 1 + src/externs.h | 2 ++ src/plots.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ src/types.h | 2 ++ 4 files changed, 54 insertions(+) diff --git a/src/defines.h b/src/defines.h index 9c0ba654..306ace92 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4524,6 +4524,7 @@ #define HOOK_TYPE_C 0 #define HOOK_TYPE_LUA 1 +#define HOOK_TYPE_NEW 2 /* * Defines for loadsave.c diff --git a/src/externs.h b/src/externs.h index 95a91f05..3c345051 100644 --- a/src/externs.h +++ b/src/externs.h @@ -603,6 +603,7 @@ extern void wipe_hooks(void); extern void dump_hooks(int h_idx); extern void init_hooks(void); extern hooks_chain* add_hook(int h_idx, hook_type hook, cptr name); +extern void add_hook_new(int h_idx, bool_ (*hook_f)(void *, void *, void *), cptr name, void *data); extern void add_hook_script(int h_idx, char *script, cptr name); extern void del_hook(int h_idx, hook_type hook); extern void del_hook_name(int h_idx, cptr name); @@ -611,6 +612,7 @@ extern int process_hooks_restart; extern hook_return process_hooks_return[20]; extern bool_ process_hooks_ret(int h_idx, char *ret, char *fmt, ...); extern bool_ process_hooks(int h_idx, char *fmt, ...); +extern bool_ process_hooks_new(int h_idx, void *in, void *out); extern void initialize_bookable_spells(); diff --git a/src/plots.c b/src/plots.c index 6015420a..2fb592b0 100644 --- a/src/plots.c +++ b/src/plots.c @@ -109,6 +109,14 @@ hooks_chain* add_hook(int h_idx, hook_type hook, cptr name) else return (c); } +void add_hook_new(int h_idx, bool_ (*hook_f)(void *, void *, void *), cptr name, void *data) +{ + hooks_chain *c = add_hook(h_idx, NULL, name); + c->hook_f = hook_f; + c->hook_data = data; + c->type = HOOK_TYPE_NEW; +} + void add_hook_script(int h_idx, char *script, cptr name) { hooks_chain *c = add_hook(h_idx, NULL, name); @@ -387,9 +395,15 @@ static bool_ vprocess_hooks_return (int h_idx, char *ret, char *fmt, va_list *ap c = c->next; lua_settop(L, oldtop); } + else if (c->type == HOOK_TYPE_NEW) + { + /* Skip; handled in process_hooks_new */ + c = c->next; + } else { msg_format("Unkown hook type %d, name %s", c->type, c->name); + c = c->next; } } @@ -418,6 +432,41 @@ bool_ process_hooks(int h_idx, char *fmt, ...) return (ret); } +bool_ process_hooks_new(int h_idx, void *in, void *out) +{ + hooks_chain *c = hooks_heads[h_idx]; + + while (c != NULL) + { + /* Only new-style hooks; skip the rest. */ + if (c->type != HOOK_TYPE_NEW) + { + c = c->next; + continue; + } + + /* Invoke hook function; stop processing if + the hook returns TRUE */ + if (c->hook_f(c->hook_data, in, out)) + { + return TRUE; + } + + /* Should we restart processing at the beginning? */ + if (process_hooks_restart) + { + c = hooks_heads[h_idx]; + process_hooks_restart = FALSE; + } + else + { + c = c->next; + } + } + + return FALSE; +} + /******** Plots & Quest stuff ********/ static void quest_describe(int q_idx) diff --git a/src/types.h b/src/types.h index 5173a89c..da1debf9 100644 --- a/src/types.h +++ b/src/types.h @@ -2363,6 +2363,8 @@ typedef struct hooks_chain hooks_chain; struct hooks_chain { hook_type hook; + bool_ (*hook_f)(void *, void *, void *); + void *hook_data; char name[40]; char script[40]; byte type; -- cgit v1.2.3 From a11ad32d1903074f289bfea570b75ce6c6b7b7e7 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 7 Jun 2012 20:18:59 +0200 Subject: Lua: Add new-style hook support for HOOK_MOVE --- src/cmd1.c | 7 +++++++ src/types.h | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/src/cmd1.c b/src/cmd1.c index 37e12f61..ce43c008 100644 --- a/src/cmd1.c +++ b/src/cmd1.c @@ -3098,6 +3098,13 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm) /* Some hooks */ if (process_hooks(HOOK_MOVE, "(d,d)", y, x)) return; + { + hook_move_in in = { y, x }; + if (process_hooks_new(HOOK_MOVE, &in, NULL)) { + return; /* Prevent movement */ + } + } + if (p_ptr->dripping_tread > 0) { geomancy_random_floor(y, x, FALSE); diff --git a/src/types.h b/src/types.h index da1debf9..031903c0 100644 --- a/src/types.h +++ b/src/types.h @@ -2255,6 +2255,12 @@ struct power_type /* Hooks */ typedef bool_ (*hook_type)(char *fmt); +typedef struct hook_move_in hook_move_in; +struct hook_move_in { + int y; + int x; +}; + /* * Structure for the "quests" */ -- cgit v1.2.3 From 84f856b1ff1bdfad5114831fbea3fa87addc5377 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 8 Jun 2012 05:01:44 +0200 Subject: Lua: Rework C-side "help activated" flags for load/save --- src/defines.h | 6 +----- src/loadsave.c | 6 +++++- src/types.h | 5 ++--- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/defines.h b/src/defines.h index 306ace92..44537732 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4538,11 +4538,7 @@ /* * In game help */ -#define HELP1_BETWEEN 0x00000001 -#define HELP1_ALTAR 0x00000002 -#define HELP1_FOUNTAIN 0x00000004 -#define HELP1_IDENTIFY 0x00000008 -#define HELP1_WILD_MODE 0x00000010 +#define HELP_MAX 64 /* * Special weapon effects diff --git a/src/loadsave.c b/src/loadsave.c index 718f5858..349db36d 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -7,6 +7,7 @@ #include "angband.h" static void do_byte(byte *, int); +static void do_bool(bool_ *, int); static void do_u16b(u16b *, int); static void do_s16b(s16b *, int); static void do_u32b(u32b *, int); @@ -482,7 +483,10 @@ static bool_ do_extra(int flag) p_ptr->max_plv = p_ptr->lev; do_byte((byte*)&(p_ptr->help.enabled), flag); - do_u32b(&(p_ptr->help.help1), flag); + for (i = 0; i < HELP_MAX; i++) + { + do_bool(&(p_ptr->help.activated[i]), flag); + } /* More info */ tmp16s = 0; diff --git a/src/types.h b/src/types.h index 031903c0..a7d94037 100644 --- a/src/types.h +++ b/src/types.h @@ -1415,9 +1415,8 @@ struct meta_class_type typedef struct help_info help_info; struct help_info { - bool_ enabled; /* ingame help enabled */ - - u32b help1; /* help flags 1 */ + bool_ enabled; /* ingame help enabled */ + bool_ activated[HELP_MAX]; /* help item #i activated? */ }; -- cgit v1.2.3 From 1f9f122249c0828c206293ba0f757f9bfd016d8e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 7 Jun 2012 20:36:15 +0200 Subject: Lua: Move "Void Jumpgates" help to C --- lib/mods/theme/scpt/help.lua | 11 ----- lib/scpt/help.lua | 11 ----- src/cmd4.c | 3 -- src/dungeon.c | 2 +- src/externs.h | 2 +- src/help.c | 104 ++++++++++++++++++++++++++++++++++++++++--- 6 files changed, 100 insertions(+), 33 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index 4e244df6..ca6fa6c6 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -6,17 +6,6 @@ ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- -ingame_help -{ - ["hook"] = HOOK_MOVE, - ["event"] = function(y, x) if cave(y, x).feat == FEAT_BETWEEN then return TRUE end end, - ["desc"] = - { - "Void Jumpgates can be entered by pressing the > key. They will transport", - "you to another jumpgate, but beware of the cold damage that might kill you.", - } -} - ingame_help { ["hook"] = HOOK_MOVE, diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index 5350fec8..293de713 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -6,17 +6,6 @@ ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- -ingame_help -{ - ["hook"] = HOOK_MOVE, - ["event"] = function(y, x) if cave(y, x).feat == FEAT_BETWEEN then return TRUE end end, - ["desc"] = - { - "Void Jumpgates can be entered by pressing the > key. They will transport", - "you to another jumpgate, but beware of the cold damage that might kill you.", - } -} - ingame_help { ["hook"] = HOOK_MOVE, diff --git a/src/cmd4.c b/src/cmd4.c index d0099360..fd57a9b5 100644 --- a/src/cmd4.c +++ b/src/cmd4.c @@ -1442,9 +1442,6 @@ void do_cmd_options(void) /* Restore the screen */ screen_load(); - - /* Set the ingame help */ - ingame_help(p_ptr->help.enabled); } diff --git a/src/dungeon.c b/src/dungeon.c index 342779b2..840094c1 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -5625,7 +5625,7 @@ void play_game(bool_ new_game) /* Initialize hooks */ init_hooks(); - ingame_help(p_ptr->help.enabled); + init_hooks_help(); /* React to changes */ Term_xtra(TERM_XTRA_REACT, 0); diff --git a/src/externs.h b/src/externs.h index 3c345051..3b952681 100644 --- a/src/externs.h +++ b/src/externs.h @@ -617,7 +617,7 @@ extern bool_ process_hooks_new(int h_idx, void *in, void *out); extern void initialize_bookable_spells(); /* help.c */ -extern void ingame_help(bool_ enable); +extern void init_hooks_help(); /* birth.c */ extern void print_desc_aux(cptr txt, int y, int x); diff --git a/src/help.c b/src/help.c index d0bdbedf..a87a146a 100644 --- a/src/help.c +++ b/src/help.c @@ -1,13 +1,10 @@ /* File: help.c */ /* Purpose: ingame help */ -/* - * Actually this is now handled by lua, - * I'll remove this file when I feel un-lazy - */ /* * Copyright (c) 2001 DarkGod + * Copyright (c) 2012 Bardur Arantsson * * This software may be copied and distributed for educational, research, and * not for profit purposes provided that this copyright and statement are @@ -16,8 +13,103 @@ #include "angband.h" +#define DESC_MAX 10 +#define TRIGGERED_HELP_MAX 1 + +#define HELP_VOID_JUMPGATE 0 + +/** + * Struct for help triggered by a boolean condition + */ +typedef struct triggered_help_type triggered_help_type; +struct triggered_help_type +{ + /* Help item index; see HELP_* constants above */ + int help_index; + /* Hook type */ + int hook_type; + /* Trigger function */ + bool_ (*trigger_func)(void *in, void *out); + /* Description; NULL terminated */ + cptr desc[DESC_MAX]; +}; + +/** + * Trigger functions + */ +static bool_ trigger_void_jumpgate(void *in, void *out) { + hook_move_in *p = (hook_move_in *) in; + return cave[p->y][p->x].feat == FEAT_BETWEEN; +} + +/** + * Trigger-based help items + */ +static triggered_help_type triggered_help[TRIGGERED_HELP_MAX] = +{ + { HELP_VOID_JUMPGATE, + HOOK_MOVE, + trigger_void_jumpgate, + { "Void Jumpgates can be entered by pressing the > key. They will transport", + "you to another jumpgate, but beware of the cold damage that might kill you.", + NULL } + } +}; + +static bool_ triggered_help_hook(void *data, void *in, void *out) +{ + triggered_help_type *triggered_help = (triggered_help_type *) data; + /* Not triggered before and trigger now? */ + if ((option_ingame_help) && + (!p_ptr->help.activated[triggered_help->help_index]) && + triggered_help->trigger_func(in,out)) + { + int i; + + /* Triggered */ + p_ptr->help.activated[triggered_help->help_index] = TRUE; + + /* Show the description */ + for (i = 0; (i < DESC_MAX) && (triggered_help->desc[i] != NULL); i++) + { + cmsg_print(TERM_YELLOW, triggered_help->desc[i]); + } + } + /* Don't stop processing */ + return FALSE; +} + +static void setup_triggered_help_hook(int i) +{ + static int counter = 0; + char name[40]; + triggered_help_type *h = &triggered_help[i]; + + /* Build name */ + sprintf(name, "help_trigger_%d", counter); + counter++; + + /* Add the hook */ + add_hook_new(h->hook_type, + triggered_help_hook, + name, + h); +} + +static void setup_triggered_help_hooks() +{ + int i; + + for (i = 0; i < TRIGGERED_HELP_MAX; i++) + { + setup_triggered_help_hook(i); + } +} + /* * Driver for the context-sensitive help system */ -void ingame_help(bool_ enable) -{} +void init_hooks_help() +{ + setup_triggered_help_hooks(); +} -- cgit v1.2.3 From f1f703a9bec43282c25f93e97dab3706efe265fa Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 8 Jun 2012 06:15:15 +0200 Subject: Lua: Move "Fountain" help to C --- lib/mods/theme/scpt/help.lua | 11 ----------- lib/scpt/help.lua | 11 ----------- src/help.c | 15 ++++++++++++++- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index ca6fa6c6..e1feea19 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -6,17 +6,6 @@ ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- -ingame_help -{ - ["hook"] = HOOK_MOVE, - ["event"] = function(y, x) if cave(y, x).feat == FEAT_FOUNTAIN then return TRUE end end, - ["desc"] = - { - "Fountains are always magical. You can quaff from them by pressing H.", - "Beware that unlike potions they cannot be identified.", - } -} - ingame_help { ["hook"] = HOOK_MOVE, diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index 293de713..42fb9eeb 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -6,17 +6,6 @@ ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- -ingame_help -{ - ["hook"] = HOOK_MOVE, - ["event"] = function(y, x) if cave(y, x).feat == FEAT_FOUNTAIN then return TRUE end end, - ["desc"] = - { - "Fountains are always magical. You can quaff from them by pressing H.", - "Beware that unlike potions they cannot be identified.", - } -} - ingame_help { ["hook"] = HOOK_MOVE, diff --git a/src/help.c b/src/help.c index a87a146a..edc61e53 100644 --- a/src/help.c +++ b/src/help.c @@ -14,9 +14,10 @@ #include "angband.h" #define DESC_MAX 10 -#define TRIGGERED_HELP_MAX 1 +#define TRIGGERED_HELP_MAX 2 #define HELP_VOID_JUMPGATE 0 +#define HELP_FOUNTAIN 1 /** * Struct for help triggered by a boolean condition @@ -42,6 +43,11 @@ static bool_ trigger_void_jumpgate(void *in, void *out) { return cave[p->y][p->x].feat == FEAT_BETWEEN; } +static bool_ trigger_fountain(void *in, void *out) { + hook_move_in *p = (hook_move_in *) in; + return cave[p->y][p->x].feat == FEAT_FOUNTAIN; +} + /** * Trigger-based help items */ @@ -53,6 +59,13 @@ static triggered_help_type triggered_help[TRIGGERED_HELP_MAX] = { "Void Jumpgates can be entered by pressing the > key. They will transport", "you to another jumpgate, but beware of the cold damage that might kill you.", NULL } + }, + { HELP_FOUNTAIN, + HOOK_MOVE, + trigger_fountain, + { "Fountains are always magical. You can quaff from them by pressing H.", + "Beware that unlike potions they cannot be identified.", + NULL } } }; -- cgit v1.2.3 From 4401b0bd2e85f491faf9971da4015a254b45366b Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 8 Jun 2012 16:25:56 +0200 Subject: Lua: Move "Found Object" help to C --- lib/mods/theme/scpt/help.lua | 14 -------------- lib/scpt/help.lua | 14 -------------- src/help.c | 18 +++++++++++++++++- 3 files changed, 17 insertions(+), 29 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index e1feea19..ff901650 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -6,20 +6,6 @@ ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- -ingame_help -{ - ["hook"] = HOOK_MOVE, - ["event"] = function(y, x) if cave(y, x).o_idx ~= 0 then return TRUE end end, - ["desc"] = - { - "So you found your first item! Nice, eh? Now when you stumble across", - "objects, you can pick them up by pressing g, and if you are wondering", - "what they do, press I (then *, then the letter for the item) to get", - "some basic information. You may also want to identify them with scrolls,", - "staves, rods or spells.", - } -} - ingame_help { ["hook"] = HOOK_MOVE, diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index 42fb9eeb..8c8ffd8d 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -6,20 +6,6 @@ ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- -ingame_help -{ - ["hook"] = HOOK_MOVE, - ["event"] = function(y, x) if cave(y, x).o_idx ~= 0 then return TRUE end end, - ["desc"] = - { - "So you found your first item! Nice, eh? Now when you stumble across", - "objects, you can pick them up by pressing g, and if you are wondering", - "what they do, press I (then *, then the letter for the item) to get", - "some basic information. You may also want to identify them with scrolls,", - "staves, rods or spells.", - } -} - ingame_help { ["hook"] = HOOK_MOVE, diff --git a/src/help.c b/src/help.c index edc61e53..356228fb 100644 --- a/src/help.c +++ b/src/help.c @@ -14,10 +14,11 @@ #include "angband.h" #define DESC_MAX 10 -#define TRIGGERED_HELP_MAX 2 +#define TRIGGERED_HELP_MAX 3 #define HELP_VOID_JUMPGATE 0 #define HELP_FOUNTAIN 1 +#define HELP_FOUND_OBJECT 2 /** * Struct for help triggered by a boolean condition @@ -48,6 +49,11 @@ static bool_ trigger_fountain(void *in, void *out) { return cave[p->y][p->x].feat == FEAT_FOUNTAIN; } +static bool_ trigger_found_object(void *in, void *out) { + hook_move_in *p = (hook_move_in *) in; + return cave[p->y][p->x].o_idx != 0; +} + /** * Trigger-based help items */ @@ -66,6 +72,16 @@ static triggered_help_type triggered_help[TRIGGERED_HELP_MAX] = { "Fountains are always magical. You can quaff from them by pressing H.", "Beware that unlike potions they cannot be identified.", NULL } + }, + { HELP_FOUND_OBJECT, + HOOK_MOVE, + trigger_found_object, + { "So you found your first item! Nice, eh? Now when you stumble across", + "objects, you can pick them up by pressing g, and if you are wondering", + "what they do, press I (then *, then the letter for the item) to get", + "some basic information. You may also want to identify them with scrolls,", + "staves, rods or spells.", + NULL } } }; -- cgit v1.2.3 From ac8ef5f15e948e351ff4e92a4150ff6602dd680e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 8 Jun 2012 16:34:39 +0200 Subject: Lua: Move "Found Altar" help to C --- lib/mods/theme/scpt/help.lua | 13 ------------- lib/scpt/help.lua | 13 ------------- src/help.c | 18 +++++++++++++++++- 3 files changed, 17 insertions(+), 27 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index ff901650..1f260a96 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -6,19 +6,6 @@ ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- -ingame_help -{ - ["hook"] = HOOK_MOVE, - ["event"] = function(y, x) if (cave(y, x).feat >= FEAT_ALTAR_HEAD) and (cave(y, x).feat <= FEAT_ALTAR_TAIL) then return TRUE end end, - ["desc"] = - { - "Altars are the way to reach the Valar, powers of the world,", - "usualy called Gods. You can press O to become a follower.", - "Beware that once you follow a god, you are not allowed to change.", - "For an exact description of what gods do and want, read the documentation." - } -} - -- Beware this one, if Bree is moved from 21, 34 (y, x) on the wilderness map it will break ingame_help { diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index 8c8ffd8d..aa6d11f5 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -6,19 +6,6 @@ ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- -ingame_help -{ - ["hook"] = HOOK_MOVE, - ["event"] = function(y, x) if (cave(y, x).feat >= FEAT_ALTAR_HEAD) and (cave(y, x).feat <= FEAT_ALTAR_TAIL) then return TRUE end end, - ["desc"] = - { - "Altars are the way to reach the Valar, powers of the world,", - "usualy called Gods. You can press O to become a follower.", - "Beware that once you follow a god, you are not allowed to change.", - "For an exact description of what gods do and want, read the documentation." - } -} - -- Beware this one, if Bree is moved from 21, 34 (y, x) on the wilderness map it will break ingame_help { diff --git a/src/help.c b/src/help.c index 356228fb..db31e5e2 100644 --- a/src/help.c +++ b/src/help.c @@ -14,11 +14,12 @@ #include "angband.h" #define DESC_MAX 10 -#define TRIGGERED_HELP_MAX 3 +#define TRIGGERED_HELP_MAX 4 #define HELP_VOID_JUMPGATE 0 #define HELP_FOUNTAIN 1 #define HELP_FOUND_OBJECT 2 +#define HELP_FOUND_ALTAR 3 /** * Struct for help triggered by a boolean condition @@ -54,6 +55,12 @@ static bool_ trigger_found_object(void *in, void *out) { return cave[p->y][p->x].o_idx != 0; } +static bool_ trigger_found_altar(void *in, void *out) { + hook_move_in *p = (hook_move_in *) in; + return ((cave[p->y][p->x].feat >= FEAT_ALTAR_HEAD) && + (cave[p->y][p->x].feat <= FEAT_ALTAR_TAIL)); +} + /** * Trigger-based help items */ @@ -82,6 +89,15 @@ static triggered_help_type triggered_help[TRIGGERED_HELP_MAX] = "some basic information. You may also want to identify them with scrolls,", "staves, rods or spells.", NULL } + }, + { HELP_FOUND_ALTAR, + HOOK_MOVE, + trigger_found_altar, + { "Altars are the way to reach the Valar, powers of the world,", + "usualy called Gods. You can press O to become a follower.", + "Beware that once you follow a god, you are not allowed to change.", + "For an exact description of what gods do and want, read the documentation.", + NULL } } }; -- cgit v1.2.3 From 41d157bccff5ae75117ea056915099981e338918 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 8 Jun 2012 16:45:21 +0200 Subject: Lua: Move "Found Stairs" help to C --- lib/mods/theme/scpt/help.lua | 11 ----------- lib/scpt/help.lua | 11 ----------- src/help.c | 15 ++++++++++++++- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index 1f260a96..decad717 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -34,17 +34,6 @@ ingame_help } } -ingame_help -{ - ["hook"] = HOOK_MOVE, - ["event"] = function(y, x) if cave(y, x).feat == FEAT_MORE then return TRUE end end, - ["desc"] = - { - "Ah, this is a stair, or a way into something. Press > to enter it.", - "But be ready to fight what lies within, for it might not be too friendly.", - } -} - ingame_help { ["callback"] = "monster_chat", diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index aa6d11f5..eb4bfa1a 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -34,17 +34,6 @@ ingame_help } } -ingame_help -{ - ["hook"] = HOOK_MOVE, - ["event"] = function(y, x) if cave(y, x).feat == FEAT_MORE then return TRUE end end, - ["desc"] = - { - "Ah, this is a stair, or a way into something. Press > to enter it.", - "But be ready to fight what lies within, for it might not be too friendly.", - } -} - ingame_help { ["callback"] = "monster_chat", diff --git a/src/help.c b/src/help.c index db31e5e2..21013a24 100644 --- a/src/help.c +++ b/src/help.c @@ -14,12 +14,13 @@ #include "angband.h" #define DESC_MAX 10 -#define TRIGGERED_HELP_MAX 4 +#define TRIGGERED_HELP_MAX 5 #define HELP_VOID_JUMPGATE 0 #define HELP_FOUNTAIN 1 #define HELP_FOUND_OBJECT 2 #define HELP_FOUND_ALTAR 3 +#define HELP_FOUND_STAIR 4 /** * Struct for help triggered by a boolean condition @@ -61,6 +62,11 @@ static bool_ trigger_found_altar(void *in, void *out) { (cave[p->y][p->x].feat <= FEAT_ALTAR_TAIL)); } +static bool_ trigger_found_stairs(void *in, void *out) { + hook_move_in *p = (hook_move_in *) in; + return (cave[p->y][p->x].feat == FEAT_MORE); +} + /** * Trigger-based help items */ @@ -98,6 +104,13 @@ static triggered_help_type triggered_help[TRIGGERED_HELP_MAX] = "Beware that once you follow a god, you are not allowed to change.", "For an exact description of what gods do and want, read the documentation.", NULL } + }, + { HELP_FOUND_STAIR, + HOOK_MOVE, + trigger_found_stairs, + { "Ah, this is a stair, or a way into something. Press > to enter it.", + "But be ready to fight what lies within, for it might not be too friendly.", + NULL } } }; -- cgit v1.2.3 From 7573056e431112f1f1c0e513fae36efa06ffaac9 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 8 Jun 2012 17:17:02 +0200 Subject: Lua: Implement new-style HOOK_GET --- src/object1.c | 9 +++++++++ src/types.h | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/src/object1.c b/src/object1.c index 63789794..7d40a8c3 100644 --- a/src/object1.c +++ b/src/object1.c @@ -6193,6 +6193,15 @@ void object_pickup(int this_o_idx) if (process_hooks(HOOK_GET, "(O,d)", o_ptr, this_o_idx)) return; + /* Hooks */ + { + hook_get_in in = { o_ptr, this_o_idx }; + if (process_hooks_new(HOOK_GET, &in, NULL)) + { + return; + } + } + q_ptr = &p_ptr->inventory[INVEN_AMMO]; /* Carry the item */ diff --git a/src/types.h b/src/types.h index a7d94037..3bbbb270 100644 --- a/src/types.h +++ b/src/types.h @@ -2260,6 +2260,12 @@ struct hook_move_in { int x; }; +typedef struct hook_get_in hook_get_in; +struct hook_get_in { + object_type *o_ptr; + int o_idx; +}; + /* * Structure for the "quests" */ -- cgit v1.2.3 From 0bad18e026e1fd9254191aa8d41f2d4c1b5ce19b Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 8 Jun 2012 17:25:11 +0200 Subject: Lua: Move "pick up essence" help to C --- lib/mods/theme/scpt/help.lua | 11 ----------- lib/scpt/help.lua | 11 ----------- src/help.c | 15 ++++++++++++++- 3 files changed, 14 insertions(+), 23 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index decad717..98f3c9a9 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -288,17 +288,6 @@ ingame_help } } -ingame_help -{ - ["hook"] = HOOK_GET, - ["event"] = function(obj, idx) if obj.tval == TV_BATERIE then return TRUE end end, - ["desc"] = - { - "Ah, an essence! Those magical containers stores energies. They are used", - "with the Alchemy skill to create or modify the powers of items.", - } -} - ingame_help { ["hook"] = HOOK_GET, diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index eb4bfa1a..c49eed97 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -254,17 +254,6 @@ ingame_help } } -ingame_help -{ - ["hook"] = HOOK_GET, - ["event"] = function(obj, idx) if obj.tval == TV_BATERIE then return TRUE end end, - ["desc"] = - { - "Ah, an essence! Those magical containers stores energies. They are used", - "with the Alchemy skill to create or modify the powers of items.", - } -} - ingame_help { ["hook"] = HOOK_GET, diff --git a/src/help.c b/src/help.c index 21013a24..cb73025b 100644 --- a/src/help.c +++ b/src/help.c @@ -14,13 +14,14 @@ #include "angband.h" #define DESC_MAX 10 -#define TRIGGERED_HELP_MAX 5 +#define TRIGGERED_HELP_MAX 6 #define HELP_VOID_JUMPGATE 0 #define HELP_FOUNTAIN 1 #define HELP_FOUND_OBJECT 2 #define HELP_FOUND_ALTAR 3 #define HELP_FOUND_STAIR 4 +#define HELP_GET_ESSENCE 5 /** * Struct for help triggered by a boolean condition @@ -67,6 +68,11 @@ static bool_ trigger_found_stairs(void *in, void *out) { return (cave[p->y][p->x].feat == FEAT_MORE); } +static bool_ trigger_get_essence(void *in, void *out) { + hook_get_in *g = (hook_get_in *) in; + return (g->o_ptr->tval == TV_BATERIE); +} + /** * Trigger-based help items */ @@ -111,6 +117,13 @@ static triggered_help_type triggered_help[TRIGGERED_HELP_MAX] = { "Ah, this is a stair, or a way into something. Press > to enter it.", "But be ready to fight what lies within, for it might not be too friendly.", NULL } + }, + { HELP_GET_ESSENCE, + HOOK_GET, + trigger_get_essence, + { "Ah, an essence! Those magical containers stores energies. They are used", + "with the Alchemy skill to create or modify the powers of items.", + NULL } } }; -- cgit v1.2.3 From 0ade661fe361dae2f733587f1934e078fd4559fb Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 8 Jun 2012 17:36:02 +0200 Subject: Lua: Move "pick up rune" help to C --- lib/mods/theme/scpt/help.lua | 11 ----------- lib/scpt/help.lua | 11 ----------- src/help.c | 17 ++++++++++++++++- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index 98f3c9a9..7ab4871f 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -288,17 +288,6 @@ ingame_help } } -ingame_help -{ - ["hook"] = HOOK_GET, - ["event"] = function(obj, idx) if obj.tval == TV_RUNE1 or obj.tval == TV_RUNE2 then return TRUE end end, - ["desc"] = - { - "Ah, a rune! Runes are used with the Runecraft skill to allow you to", - "create spells on your own.", - } -} - ingame_help { ["hook"] = HOOK_GET, diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index c49eed97..c6597521 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -254,17 +254,6 @@ ingame_help } } -ingame_help -{ - ["hook"] = HOOK_GET, - ["event"] = function(obj, idx) if obj.tval == TV_RUNE1 or obj.tval == TV_RUNE2 then return TRUE end end, - ["desc"] = - { - "Ah, a rune! Runes are used with the Runecraft skill to allow you to", - "create spells on your own.", - } -} - ingame_help { ["hook"] = HOOK_GET, diff --git a/src/help.c b/src/help.c index cb73025b..a0ad3612 100644 --- a/src/help.c +++ b/src/help.c @@ -14,7 +14,7 @@ #include "angband.h" #define DESC_MAX 10 -#define TRIGGERED_HELP_MAX 6 +#define TRIGGERED_HELP_MAX 7 #define HELP_VOID_JUMPGATE 0 #define HELP_FOUNTAIN 1 @@ -22,6 +22,7 @@ #define HELP_FOUND_ALTAR 3 #define HELP_FOUND_STAIR 4 #define HELP_GET_ESSENCE 5 +#define HELP_GET_RUNE 6 /** * Struct for help triggered by a boolean condition @@ -73,6 +74,12 @@ static bool_ trigger_get_essence(void *in, void *out) { return (g->o_ptr->tval == TV_BATERIE); } +static bool_ trigger_get_rune(void *in, void *out) { + hook_get_in *g = (hook_get_in *) in; + return ((g->o_ptr->tval == TV_RUNE1) || + (g->o_ptr->tval == TV_RUNE2)); +} + /** * Trigger-based help items */ @@ -124,6 +131,14 @@ static triggered_help_type triggered_help[TRIGGERED_HELP_MAX] = { "Ah, an essence! Those magical containers stores energies. They are used", "with the Alchemy skill to create or modify the powers of items.", NULL } + }, + { HELP_GET_RUNE, + HOOK_GET, + trigger_get_rune, + { "Ah, a rune! Runes are used with the Runecraft skill to allow you to", + "create spells on your own.", + NULL + } } }; -- cgit v1.2.3 From e0e4d2216c5763e318e4b321aef63cf67924f8d0 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 8 Jun 2012 17:39:28 +0200 Subject: Lua: Move "pick up rod" help to C --- lib/mods/theme/scpt/help.lua | 12 ------------ lib/scpt/help.lua | 12 ------------ src/help.c | 17 ++++++++++++++++- 3 files changed, 16 insertions(+), 25 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index 7ab4871f..1273eab4 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -288,18 +288,6 @@ ingame_help } } -ingame_help -{ - ["hook"] = HOOK_GET, - ["event"] = function(obj, idx) if obj.tval == TV_ROD_MAIN then return TRUE end end, - ["desc"] = - { - "This is a rod. You will need to attach a rod tip to it before you", - "can use it. This main part of the rod may give the rod bonuses", - "like quicker charging time, or a larger capacity for charges.", - } -} - ingame_help { ["hook"] = HOOK_GET, diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index c6597521..189805fb 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -254,18 +254,6 @@ ingame_help } } -ingame_help -{ - ["hook"] = HOOK_GET, - ["event"] = function(obj, idx) if obj.tval == TV_ROD_MAIN then return TRUE end end, - ["desc"] = - { - "This is a rod. You will need to attach a rod tip to it before you", - "can use it. This main part of the rod may give the rod bonuses", - "like quicker charging time, or a larger capacity for charges.", - } -} - ingame_help { ["hook"] = HOOK_GET, diff --git a/src/help.c b/src/help.c index a0ad3612..d08299a1 100644 --- a/src/help.c +++ b/src/help.c @@ -14,7 +14,7 @@ #include "angband.h" #define DESC_MAX 10 -#define TRIGGERED_HELP_MAX 7 +#define TRIGGERED_HELP_MAX 8 #define HELP_VOID_JUMPGATE 0 #define HELP_FOUNTAIN 1 @@ -23,6 +23,7 @@ #define HELP_FOUND_STAIR 4 #define HELP_GET_ESSENCE 5 #define HELP_GET_RUNE 6 +#define HELP_GET_ROD 7 /** * Struct for help triggered by a boolean condition @@ -80,6 +81,11 @@ static bool_ trigger_get_rune(void *in, void *out) { (g->o_ptr->tval == TV_RUNE2)); } +static bool_ trigger_get_rod(void *in, void *out) { + hook_get_in *g = (hook_get_in *) in; + return (g->o_ptr->tval == TV_ROD_MAIN); +} + /** * Trigger-based help items */ @@ -139,6 +145,15 @@ static triggered_help_type triggered_help[TRIGGERED_HELP_MAX] = "create spells on your own.", NULL } + }, + { HELP_GET_ROD, + HOOK_GET, + trigger_get_rod, + { "This is a rod. You will need to attach a rod tip to it before you", + "can use it. This main part of the rod may give the rod bonuses", + "like quicker charging time, or a larger capacity for charges.", + NULL + } } }; -- cgit v1.2.3 From 6daf34377e6c0c1e1861d65c55d2df18e9e491d4 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 8 Jun 2012 17:51:57 +0200 Subject: Lua: Move "pick up rod tip" help to C --- lib/mods/theme/scpt/help.lua | 13 ------------- lib/scpt/help.lua | 13 ------------- src/help.c | 18 +++++++++++++++++- 3 files changed, 17 insertions(+), 27 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index 1273eab4..339a5d17 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -288,19 +288,6 @@ ingame_help } } -ingame_help -{ - ["hook"] = HOOK_GET, - ["event"] = function(obj, idx) if obj.tval == TV_ROD then return TRUE end end, - ["desc"] = - { - "You've found a rod-tip! You will need to attach it to a rod base", - "before you can use it. Once it has been attatched (use the 'z' key)", - "you cannot unattach it! The rod tip will determine the effect of", - "the rod. To use your rod, 'z'ap it once it has been assembled.", - } -} - ingame_help { ["hook"] = HOOK_GET, diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index 189805fb..e7b9a662 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -254,19 +254,6 @@ ingame_help } } -ingame_help -{ - ["hook"] = HOOK_GET, - ["event"] = function(obj, idx) if obj.tval == TV_ROD then return TRUE end end, - ["desc"] = - { - "You've found a rod-tip! You will need to attach it to a rod base", - "before you can use it. Once it has been attatched (use the 'z' key)", - "you cannot unattach it! The rod tip will determine the effect of", - "the rod. To use your rod, 'z'ap it once it has been assembled.", - } -} - ingame_help { ["hook"] = HOOK_GET, diff --git a/src/help.c b/src/help.c index d08299a1..6e93db92 100644 --- a/src/help.c +++ b/src/help.c @@ -14,7 +14,7 @@ #include "angband.h" #define DESC_MAX 10 -#define TRIGGERED_HELP_MAX 8 +#define TRIGGERED_HELP_MAX 9 #define HELP_VOID_JUMPGATE 0 #define HELP_FOUNTAIN 1 @@ -24,6 +24,7 @@ #define HELP_GET_ESSENCE 5 #define HELP_GET_RUNE 6 #define HELP_GET_ROD 7 +#define HELP_GET_ROD_TIP 8 /** * Struct for help triggered by a boolean condition @@ -86,6 +87,11 @@ static bool_ trigger_get_rod(void *in, void *out) { return (g->o_ptr->tval == TV_ROD_MAIN); } +static bool_ trigger_get_rod_tip(void *in, void *out) { + hook_get_in *g = (hook_get_in *) in; + return (g->o_ptr->tval == TV_ROD); +} + /** * Trigger-based help items */ @@ -154,6 +160,16 @@ static triggered_help_type triggered_help[TRIGGERED_HELP_MAX] = "like quicker charging time, or a larger capacity for charges.", NULL } + }, + { HELP_GET_ROD_TIP, + HOOK_GET, + trigger_get_rod_tip, + { "You've found a rod-tip! You will need to attach it to a rod base", + "before you can use it. Once it has been attatched (use the 'z' key)", + "you cannot unattach it! The rod tip will determine the effect of", + "the rod. To use your rod, 'z'ap it once it has been assembled.", + NULL + } } }; -- cgit v1.2.3 From 01b96520e44540b08ce221253248307492bf6383 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 8 Jun 2012 17:59:43 +0200 Subject: Lua: Move "pick up trap kit" help to C --- lib/mods/theme/scpt/help.lua | 13 ------------- lib/scpt/help.lua | 13 ------------- src/help.c | 18 +++++++++++++++++- 3 files changed, 17 insertions(+), 27 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index 339a5d17..5f1a9d2d 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -288,19 +288,6 @@ ingame_help } } -ingame_help -{ - ["hook"] = HOOK_GET, - ["event"] = function(obj, idx) if obj.tval == TV_TRAPKIT then return TRUE end end, - ["desc"] = - { - "Ooooh, a trapping kit. If you have ability in the trapping skill,", - "you can lay this trap (via the 'm' key) to harm unsuspecting foes.", - "You'll generally need either some ammo or magic device depending", - "on the exact type of trap kit.", - } -} - ingame_help { ["hook"] = HOOK_RECALC_SKILLS, diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index e7b9a662..1481a997 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -254,19 +254,6 @@ ingame_help } } -ingame_help -{ - ["hook"] = HOOK_GET, - ["event"] = function(obj, idx) if obj.tval == TV_TRAPKIT then return TRUE end end, - ["desc"] = - { - "Ooooh, a trapping kit. If you have ability in the trapping skill,", - "you can lay this trap (via the 'm' key) to harm unsuspecting foes.", - "You'll generally need either some ammo or magic device depending", - "on the exact type of trap kit.", - } -} - ingame_help { ["hook"] = HOOK_RECALC_SKILLS, diff --git a/src/help.c b/src/help.c index 6e93db92..3bd0c05d 100644 --- a/src/help.c +++ b/src/help.c @@ -14,7 +14,7 @@ #include "angband.h" #define DESC_MAX 10 -#define TRIGGERED_HELP_MAX 9 +#define TRIGGERED_HELP_MAX 10 #define HELP_VOID_JUMPGATE 0 #define HELP_FOUNTAIN 1 @@ -25,6 +25,7 @@ #define HELP_GET_RUNE 6 #define HELP_GET_ROD 7 #define HELP_GET_ROD_TIP 8 +#define HELP_GET_TRAP_KIT 9 /** * Struct for help triggered by a boolean condition @@ -92,6 +93,11 @@ static bool_ trigger_get_rod_tip(void *in, void *out) { return (g->o_ptr->tval == TV_ROD); } +static bool_ trigger_get_trap_kit(void *in, void *out) { + hook_get_in *g = (hook_get_in *) in; + return (g->o_ptr->tval == TV_TRAPKIT); +} + /** * Trigger-based help items */ @@ -170,6 +176,16 @@ static triggered_help_type triggered_help[TRIGGERED_HELP_MAX] = "the rod. To use your rod, 'z'ap it once it has been assembled.", NULL } + }, + { HELP_GET_TRAP_KIT, + HOOK_GET, + trigger_get_trap_kit, + { "Ooooh, a trapping kit. If you have ability in the trapping skill,", + "you can lay this trap (via the 'm' key) to harm unsuspecting foes.", + "You'll generally need either some ammo or magic device depending", + "on the exact type of trap kit.", + NULL + } } }; -- cgit v1.2.3 From 8a94b839d00267e7be1664f521de1c0033921b8c Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 8 Jun 2012 18:07:38 +0200 Subject: Lua: Move "pick up staff/wand" help to C --- lib/mods/theme/scpt/help.lua | 13 ------------- lib/scpt/help.lua | 13 ------------- src/help.c | 19 ++++++++++++++++++- 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index 5f1a9d2d..e6f3a8b1 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -299,19 +299,6 @@ ingame_help } } -ingame_help -{ - ["hook"] = HOOK_GET, - ["event"] = function(obj, idx) if obj.tval == TV_WAND or obj.tval == TV_STAFF then return TRUE end end, - ["desc"] = - { - "You've found a magical device, either a staff or a wand. Each staff", - "contains a spell, often from one of the primary magic schools. There", - "is a lot of information you can find about this object if you identify", - "it and 'I'nspect it. Check the help file on Magic for more about these.", - } -} - ingame_help { ["hook"] = HOOK_PLAYER_LEVEL, diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index 1481a997..b03e8d9d 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -265,19 +265,6 @@ ingame_help } } -ingame_help -{ - ["hook"] = HOOK_GET, - ["event"] = function(obj, idx) if obj.tval == TV_WAND or obj.tval == TV_STAFF then return TRUE end end, - ["desc"] = - { - "You've found a magical device, either a staff or a wand. Each staff", - "contains a spell, often from one of the primary magic schools. There", - "is a lot of information you can find about this object if you identify", - "it and 'I'nspect it. Check the help file on Magic for more about these.", - } -} - ingame_help { ["hook"] = HOOK_PLAYER_LEVEL, diff --git a/src/help.c b/src/help.c index 3bd0c05d..d77f6935 100644 --- a/src/help.c +++ b/src/help.c @@ -14,7 +14,7 @@ #include "angband.h" #define DESC_MAX 10 -#define TRIGGERED_HELP_MAX 10 +#define TRIGGERED_HELP_MAX 11 #define HELP_VOID_JUMPGATE 0 #define HELP_FOUNTAIN 1 @@ -26,6 +26,7 @@ #define HELP_GET_ROD 7 #define HELP_GET_ROD_TIP 8 #define HELP_GET_TRAP_KIT 9 +#define HELP_GET_DEVICE 10 /** * Struct for help triggered by a boolean condition @@ -98,6 +99,12 @@ static bool_ trigger_get_trap_kit(void *in, void *out) { return (g->o_ptr->tval == TV_TRAPKIT); } +static bool_ trigger_get_magic_device(void *in, void *out) { + hook_get_in *g = (hook_get_in *) in; + return ((g->o_ptr->tval == TV_WAND) || + (g->o_ptr->tval == TV_STAFF)); +} + /** * Trigger-based help items */ @@ -186,6 +193,16 @@ static triggered_help_type triggered_help[TRIGGERED_HELP_MAX] = "on the exact type of trap kit.", NULL } + }, + { HELP_GET_DEVICE, + HOOK_GET, + trigger_get_magic_device, + { "You've found a magical device, either a staff or a wand. Each staff", + "contains a spell, often from one of the primary magic schools. There", + "is a lot of information you can find about this object if you identify", + "it and 'I'nspect it. Check the help file on Magic for more about these.", + NULL + } } }; -- cgit v1.2.3 From c1e4d667aaa5b99f87a99dc32131b8e941cebd35 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 8 Jun 2012 18:39:56 +0200 Subject: Lua: Add new-style handling for HOOK_END_TURN --- src/dungeon.c | 5 +++++ src/types.h | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/dungeon.c b/src/dungeon.c index 840094c1..ff3cbdb9 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -5321,6 +5321,11 @@ static void dungeon(void) /* Process the appropriate hooks */ process_hooks(HOOK_END_TURN, "(d)", is_quest(dun_level)); + { + hook_end_turn_in in = { is_quest(dun_level) }; + process_hooks_new(HOOK_END_TURN, &in, NULL); + } + /* Make it pulsate and live !!!! */ if ((dungeon_flags1 & DF1_EVOLVE) && dun_level) { diff --git a/src/types.h b/src/types.h index 3bbbb270..c9727518 100644 --- a/src/types.h +++ b/src/types.h @@ -2266,6 +2266,11 @@ struct hook_get_in { int o_idx; }; +typedef struct hook_end_turn_in hook_end_turn_in; +struct hook_end_turn_in { + bool_ is_quest; +}; + /* * Structure for the "quests" */ -- cgit v1.2.3 From 5867e77c9fd84033ec54c565e0d0759860c2a2c1 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 8 Jun 2012 18:40:12 +0200 Subject: Lua: Move wilderness help to C --- lib/mods/theme/scpt/help.lua | 16 ---------------- lib/scpt/help.lua | 16 ---------------- src/help.c | 19 ++++++++++++++++++- 3 files changed, 18 insertions(+), 33 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index e6f3a8b1..ffe7bc06 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -6,22 +6,6 @@ ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- --- Beware this one, if Bree is moved from 21, 34 (y, x) on the wilderness map it will break -ingame_help -{ - ["hook"] = HOOK_END_TURN, - ["event"] = function(y, x) - if ((player.wilderness_x ~= 34) or (player.wilderness_y ~= 21) and (player.astral == FALSE)) then return TRUE end - end, - ["desc"] = - { - "Ahh wilderness travel... The overview mode will allow you to travel", - "fast, but that comes to the cost of GREATLY increased food consumption.", - "So you should bring lots of food and really watch your hunger status.", - "To enter the overview mode, press < while in the wilderness.", - } -} - ingame_help { ["hook"] = HOOK_PLAYER_LEVEL, diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index b03e8d9d..87121baf 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -6,22 +6,6 @@ ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- --- Beware this one, if Bree is moved from 21, 34 (y, x) on the wilderness map it will break -ingame_help -{ - ["hook"] = HOOK_END_TURN, - ["event"] = function(y, x) - if ((player.wilderness_x ~= 34) or (player.wilderness_y ~= 21) and (player.astral == FALSE)) then return TRUE end - end, - ["desc"] = - { - "Ahh wilderness travel... The overview mode will allow you to travel", - "fast, but that comes to the cost of GREATLY increased food consumption.", - "So you should bring lots of food and really watch your hunger status.", - "To enter the overview mode, press < while in the wilderness.", - } -} - ingame_help { ["hook"] = HOOK_PLAYER_LEVEL, diff --git a/src/help.c b/src/help.c index d77f6935..7e9b110f 100644 --- a/src/help.c +++ b/src/help.c @@ -14,7 +14,7 @@ #include "angband.h" #define DESC_MAX 10 -#define TRIGGERED_HELP_MAX 11 +#define TRIGGERED_HELP_MAX 12 #define HELP_VOID_JUMPGATE 0 #define HELP_FOUNTAIN 1 @@ -27,6 +27,7 @@ #define HELP_GET_ROD_TIP 8 #define HELP_GET_TRAP_KIT 9 #define HELP_GET_DEVICE 10 +#define HELP_WILDERNESS 11 /** * Struct for help triggered by a boolean condition @@ -105,6 +106,12 @@ static bool_ trigger_get_magic_device(void *in, void *out) { (g->o_ptr->tval == TV_STAFF)); } +static bool_ trigger_end_turn_wilderness(void *in, void *out) { + return (((p_ptr->wilderness_x != 34) || + (p_ptr->wilderness_y != 21)) && + (!p_ptr->astral)); +} + /** * Trigger-based help items */ @@ -203,6 +210,16 @@ static triggered_help_type triggered_help[TRIGGERED_HELP_MAX] = "it and 'I'nspect it. Check the help file on Magic for more about these.", NULL } + }, + { HELP_WILDERNESS, + HOOK_END_TURN, + trigger_end_turn_wilderness, + { "Ahh wilderness travel... The overview mode will allow you to travel", + "fast, but that comes to the cost of GREATLY increased food consumption.", + "So you should bring lots of food and really watch your hunger status.", + "To enter the overview mode, press < while in the wilderness.", + NULL + } } }; -- cgit v1.2.3 From e88d49b8c45f429589018b84b219b80caa66d44b Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 8 Jun 2012 19:01:19 +0200 Subject: Lua: Move "game start" help to C --- lib/mods/theme/scpt/help.lua | 22 ------------------- lib/scpt/help.lua | 22 ------------------- src/help.c | 52 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 50 insertions(+), 46 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index ffe7bc06..0773e879 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -28,28 +28,6 @@ ingame_help } } -ingame_help -{ - ["hook"] = HOOK_END_TURN, - ["event"] = function(y, x) return TRUE end, - ["desc"] = - { - "Welcome to Theme! I am the spirit of knowledge and my task is to help you", - "to get used to how to play. I have prepared a #vparchment#y for you to #vread#y.", - "Press r, then space then select it. You can also check the documentation", - "by pressing ? at (nearly) any time.", - "The first place you can explore is Barrow-downs. Go to the west of town", - "and you should see a #v>#y there.", - "If you miss any of this you can press ctrl+p to see your message log.", - "Now I must reveal your task here. You are on a quest to investigate", - "the dreadful tower of Dol Guldur in the Mirkwood forest to see what evil", - "lurks there, but beware, you are not yet ready.", - "If you do not want me to bother you any more with tips, press = then go", - "into the ToME options and deactivate the ingame_help option.", - "You can see your quest log by pressing ctrl+q. Now go to your destiny!", - } -} - ingame_help { ["no_test"] = TRUE, diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index 87121baf..e6bb6a34 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -28,28 +28,6 @@ ingame_help } } -ingame_help -{ - ["hook"] = HOOK_END_TURN, - ["event"] = function(y, x) return TRUE end, - ["desc"] = - { - "Welcome to ToME! I am the spirit of knowledge and my task is to help you", - "to get used to how to play. I have prepared a #vparchment#y for you to #vread#y.", - "Press r, then space then select it. You can also check the documentation", - "by pressing ? at (nearly) any time.", - "The first place you can explore is Barrow-downs. Go to the west of town", - "and you should see a #v>#y there.", - "If you miss any of this you can press ctrl+p to see your message log.", - "Now I must reveal your task here. You are on a quest to investigate", - "the dreadful tower of Dol Guldur in the Mirkwood forest to see what evil", - "lurks there, but beware, you are not yet ready.", - "If you do not want me to bother you any more with tips, press = then go", - "into the ToME options and deactivate the ingame_help option.", - "You can see your quest log by pressing ctrl+q. Now go to your destiny!", - } -} - ingame_help { ["no_test"] = TRUE, diff --git a/src/help.c b/src/help.c index 7e9b110f..d90ffe58 100644 --- a/src/help.c +++ b/src/help.c @@ -13,8 +13,8 @@ #include "angband.h" -#define DESC_MAX 10 -#define TRIGGERED_HELP_MAX 12 +#define DESC_MAX 14 +#define TRIGGERED_HELP_MAX 14 #define HELP_VOID_JUMPGATE 0 #define HELP_FOUNTAIN 1 @@ -28,6 +28,8 @@ #define HELP_GET_TRAP_KIT 9 #define HELP_GET_DEVICE 10 #define HELP_WILDERNESS 11 +#define HELP_GAME_TOME 12 +#define HELP_GAME_THEME 13 /** * Struct for help triggered by a boolean condition @@ -112,6 +114,14 @@ static bool_ trigger_end_turn_wilderness(void *in, void *out) { (!p_ptr->astral)); } +static bool_ trigger_game_theme(void *in, void *out) { + return (game_module_idx == MODULE_THEME); +} + +static bool_ trigger_game_tome(void *in, void *out) { + return (game_module_idx == MODULE_TOME); +} + /** * Trigger-based help items */ @@ -220,6 +230,44 @@ static triggered_help_type triggered_help[TRIGGERED_HELP_MAX] = "To enter the overview mode, press < while in the wilderness.", NULL } + }, + { HELP_GAME_TOME, + HOOK_END_TURN, + trigger_game_tome, + { "Welcome to ToME! I am the spirit of knowledge and my task is to help you", + "to get used to how to play. I have prepared a #vparchment#y for you to #vread#y.", + "Press r, then space then select it. You can also check the documentation", + "by pressing ? at (nearly) any time.", + "The first place you can explore is Barrow-downs. Go to the west of town", + "and you should see a #v>#y there.", + "If you miss any of this you can press ctrl+p to see your message log.", + "Now I must reveal your task here. You are on a quest to investigate", + "the dreadful tower of Dol Guldur in the Mirkwood forest to see what evil", + "lurks there, but beware, you are not yet ready.", + "If you do not want me to bother you any more with tips, press = then go", + "into the ToME options and deactivate the ingame_help option.", + "You can see your quest log by pressing ctrl+q. Now go to your destiny!", + NULL + } + }, + { HELP_GAME_THEME, + HOOK_END_TURN, + trigger_game_theme, + { "Welcome to Theme! I am the spirit of knowledge and my task is to help you", + "to get used to how to play. I have prepared a #vparchment#y for you to #vread#y.", + "Press r, then space then select it. You can also check the documentation", + "by pressing ? at (nearly) any time.", + "The first place you can explore is Barrow-downs. Go to the west of town", + "and you should see a #v>#y there.", + "If you miss any of this you can press ctrl+p to see your message log.", + "Now I must reveal your task here. You are on a quest to investigate", + "the dreadful tower of Dol Guldur in the Mirkwood forest to see what evil", + "lurks there, but beware, you are not yet ready.", + "If you do not want me to bother you any more with tips, press = then go", + "into the ToME options and deactivate the ingame_help option.", + "You can see your quest log by pressing ctrl+q. Now go to your destiny!", + NULL + } } }; -- cgit v1.2.3 From 4abf66423998e520ea81b6b4e7544a21e313d36b Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 8 Jun 2012 19:36:07 +0200 Subject: Lua: Implement new-style HOOK_PLAYER_LEVEL --- src/types.h | 5 +++++ src/xtra2.c | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/src/types.h b/src/types.h index c9727518..82b4890e 100644 --- a/src/types.h +++ b/src/types.h @@ -2271,6 +2271,11 @@ struct hook_end_turn_in { bool_ is_quest; }; +typedef struct hook_player_level_in hook_player_level_in; +struct hook_player_level_in { + int gained_levels; +}; + /* * Structure for the "quests" */ diff --git a/src/xtra2.c b/src/xtra2.c index d78858b3..1569f442 100644 --- a/src/xtra2.c +++ b/src/xtra2.c @@ -2099,7 +2099,13 @@ void check_experience(void) /* Hook it! */ process_hooks(HOOK_PLAYER_LEVEL, "(d)", gained); + + { + hook_player_level_in in = { gained }; + process_hooks_new(HOOK_PLAYER_LEVEL, &in, NULL); + } } + /* * Advance experience levels and print experience */ -- cgit v1.2.3 From 3e79a19e687364bf7022ca91ee02978e504093fd Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 8 Jun 2012 19:40:49 +0200 Subject: Lua: Move level-triggered help to C --- lib/mods/theme/scpt/help.lua | 24 ------------------------ lib/scpt/help.lua | 24 ------------------------ src/help.c | 30 +++++++++++++++++++++++++++++- 3 files changed, 29 insertions(+), 49 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index 0773e879..d827e5dc 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -6,18 +6,6 @@ ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- -ingame_help -{ - ["hook"] = HOOK_PLAYER_LEVEL, - ["event"] = function(y, x) if player.lev > 1 then return TRUE end end, - ["desc"] = - { - "Ok, so you now gained a level, and you have skill points to spend.", - "To do so simply press G to learn skills. Reading the documentation", - "about skills and abilities is also strongly recommended.", - } -} - ingame_help { ["callback"] = "monster_chat", @@ -260,15 +248,3 @@ ingame_help "and select the switch melee type option.", } } - -ingame_help -{ - ["hook"] = HOOK_PLAYER_LEVEL, - ["event"] = function(y, x) if player.lev >= 20 then return TRUE end end, - ["desc"] = - { - "I see you are now at least level 20. Nice! If you want to gloat about your", - "character you could press 'C' then 'f' to make a character dump and post it to", - "http://angband.oook.cz/ where it will end up in the ladder.", - } -} diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index e6bb6a34..bbda148d 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -6,18 +6,6 @@ ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- -ingame_help -{ - ["hook"] = HOOK_PLAYER_LEVEL, - ["event"] = function(y, x) if player.lev > 1 then return TRUE end end, - ["desc"] = - { - "Ok, so you now gained a level, and you have skill points to spend.", - "To do so simply press G to learn skills. Reading the documentation", - "about skills and abilities is also strongly recommended.", - } -} - ingame_help { ["callback"] = "monster_chat", @@ -226,15 +214,3 @@ ingame_help "and select the switch melee type option.", } } - -ingame_help -{ - ["hook"] = HOOK_PLAYER_LEVEL, - ["event"] = function(y, x) if player.lev >= 20 then return TRUE end end, - ["desc"] = - { - "I see you are now at least level 20. Nice! If you want to gloat about your", - "character you could press 'C' then 'f' to make a character dump and post it to", - "http://angband.oook.cz/ where it will end up in the ladder.", - } -} diff --git a/src/help.c b/src/help.c index d90ffe58..73892ff7 100644 --- a/src/help.c +++ b/src/help.c @@ -14,7 +14,7 @@ #include "angband.h" #define DESC_MAX 14 -#define TRIGGERED_HELP_MAX 14 +#define TRIGGERED_HELP_MAX 16 #define HELP_VOID_JUMPGATE 0 #define HELP_FOUNTAIN 1 @@ -30,6 +30,8 @@ #define HELP_WILDERNESS 11 #define HELP_GAME_TOME 12 #define HELP_GAME_THEME 13 +#define HELP_1ST_LEVEL 14 +#define HELP_20TH_LEVEL 15 /** * Struct for help triggered by a boolean condition @@ -122,6 +124,14 @@ static bool_ trigger_game_tome(void *in, void *out) { return (game_module_idx == MODULE_TOME); } +static bool_ trigger_1st_level(void *in, void *out) { + return (p_ptr->lev > 1); +} + +static bool_ trigger_20th_level(void *in, void *out) { + return (p_ptr->lev >= 20); +} + /** * Trigger-based help items */ @@ -268,6 +278,24 @@ static triggered_help_type triggered_help[TRIGGERED_HELP_MAX] = "You can see your quest log by pressing ctrl+q. Now go to your destiny!", NULL } + }, + { HELP_1ST_LEVEL, + HOOK_PLAYER_LEVEL, + trigger_1st_level, + { "Ok, so you now gained a level, and you have skill points to spend.", + "To do so simply press G to learn skills. Reading the documentation", + "about skills and abilities is also strongly recommended.", + NULL + } + }, + { HELP_20TH_LEVEL, + HOOK_PLAYER_LEVEL, + trigger_20th_level, + { "I see you are now at least level 20. Nice! If you want to gloat about your", + "character you could press 'C' then 'f' to make a character dump and post it to", + "http://angband.oook.cz/ where it will end up in the ladder.", + NULL + } } }; -- cgit v1.2.3 From 6763d205ca391d8a4c1544afbcfceddf5ec54c77 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 09:13:17 +0200 Subject: Lua: Add new-style hook support for HOOK_IDENTIFY --- src/externs.h | 1 + src/spells1.c | 4 ++-- src/spells2.c | 38 +++++++++++++++++++++++++++++++++----- src/types.h | 8 ++++++++ 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/externs.h b/src/externs.h index 3b952681..f727da82 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1264,6 +1264,7 @@ extern void explosive_rune(void); extern bool_ do_dec_stat(int stat, int mode); extern bool_ do_res_stat(int stat, bool_ full); extern bool_ do_inc_stat(int stat); +extern void identify_hooks(int i, object_type *o_ptr, identify_mode type); extern bool_ identify_pack(void); extern void identify_pack_fully(void); extern bool_ remove_curse(void); diff --git a/src/spells1.c b/src/spells1.c index ccd9f489..e82d708a 100644 --- a/src/spells1.c +++ b/src/spells1.c @@ -4151,7 +4151,7 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ) o_ptr->ident |= (IDENT_MENTAL); /* Process the appropriate hooks */ - process_hooks(HOOK_IDENTIFY, "(d,s)", 0 - this_o_idx, "full"); + identify_hooks(0 - this_o_idx, o_ptr, IDENT_FULL); /* Squelch ! */ squeltch_grid(); @@ -4164,7 +4164,7 @@ static bool_ project_o(int who, int r, int y, int x, int dam, int typ) object_known(o_ptr); /* Process the appropriate hooks */ - process_hooks(HOOK_IDENTIFY, "(d,s)", 0 - this_o_idx, "normal"); + identify_hooks(0 - this_o_idx, o_ptr, IDENT_NORMAL); /* Squelch ! */ squeltch_grid(); diff --git a/src/spells2.c b/src/spells2.c index 634c69e0..8df782a4 100644 --- a/src/spells2.c +++ b/src/spells2.c @@ -343,6 +343,34 @@ bool_ do_inc_stat(int stat) } +/* + * Process all identify hooks + */ +void identify_hooks(int i, object_type *o_ptr, identify_mode mode) +{ + cptr mode_s = NULL; + + switch (mode) + { + case IDENT_NORMAL: + mode_s = "normal"; + break; + case IDENT_FULL: + mode_s = "full"; + break; + default: + assert(FALSE); + } + + /* Process the appropriate hooks */ + process_hooks(HOOK_IDENTIFY, "(d,s)", i, mode_s); + + { + hook_identify_in in = { o_ptr, mode }; + process_hooks_new(HOOK_IDENTIFY, &in, NULL); + } +} + /* * Identify everything being carried. @@ -365,7 +393,7 @@ bool_ identify_pack(void) object_known(o_ptr); /* Process the appropriate hooks */ - process_hooks(HOOK_IDENTIFY, "(d,s)", i, "normal"); + identify_hooks(i, o_ptr, IDENT_NORMAL); } p_ptr->notice |= (PN_COMBINE | PN_REORDER); @@ -408,7 +436,7 @@ void identify_pack_fully(void) make_item_fully_identified(o_ptr); /* Process the appropriate hooks */ - process_hooks(HOOK_IDENTIFY, "(d,s)", i, "full"); + identify_hooks(i, o_ptr, IDENT_FULL); } p_ptr->update |= (PU_BONUS); @@ -4294,7 +4322,7 @@ bool_ ident_spell(void) add_note(note, 'A'); } /* Process the appropriate hooks */ - process_hooks(HOOK_IDENTIFY, "(d,s)", item, "normal"); + identify_hooks(item, o_ptr, IDENT_NORMAL); /* Something happened */ return (TRUE); @@ -4330,7 +4358,7 @@ bool_ ident_all(void) add_note(note, 'A'); } /* Process the appropriate hooks */ - process_hooks(HOOK_IDENTIFY, "(d,s)", -i, "normal"); + identify_hooks(-i, o_ptr, IDENT_NORMAL); } /* Something happened */ @@ -4416,7 +4444,7 @@ bool_ identify_fully(void) object_out_desc(o_ptr, NULL, FALSE, TRUE); /* Process the appropriate hooks */ - process_hooks(HOOK_IDENTIFY, "(d,s)", item, "full"); + identify_hooks(item, o_ptr, IDENT_FULL); /* Success */ return (TRUE); diff --git a/src/types.h b/src/types.h index 82b4890e..3e634beb 100644 --- a/src/types.h +++ b/src/types.h @@ -2276,6 +2276,14 @@ struct hook_player_level_in { int gained_levels; }; +typedef enum { IDENT_NORMAL, IDENT_FULL } identify_mode; + +typedef struct hook_identify_in hook_identify_in; +struct hook_identify_in { + object_type *o_ptr; + identify_mode mode; +}; + /* * Structure for the "quests" */ -- cgit v1.2.3 From 6987232c337535eb3b7f7de14ae0637d6f4b3d1d Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 09:29:06 +0200 Subject: Lua: Move "identify object with spell slot" help to C --- lib/mods/theme/scpt/help.lua | 19 ------------------- lib/scpt/help.lua | 19 ------------------- src/help.c | 28 +++++++++++++++++++++++++++- 3 files changed, 27 insertions(+), 39 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index d827e5dc..d9f637bd 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -219,25 +219,6 @@ ingame_help end, } -ingame_help -{ - ["hook"] = HOOK_IDENTIFY, - ["event"] = function(i, mode) - if mode == "full" then - local obj = get_object(i) - local f1, f2, f3, f4, f5, esp = object_flags(obj) - if band(f5, TR5_SPELL_CONTAIN) ~= 0 then return TRUE end - end - end, - ["desc"] = - { - "Ah, an item that can contain a spell. To use it you must have some levels of", - "Magic skill and then you get the option to copy a spell when pressing m.", - "Then just select which spell to copy and to which object. Note that doing so", - "is permanent; the spell cannot be removed or changed later.", - } -} - ingame_help { ["hook"] = HOOK_RECALC_SKILLS, diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index bbda148d..0ee307cb 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -185,25 +185,6 @@ ingame_help end, } -ingame_help -{ - ["hook"] = HOOK_IDENTIFY, - ["event"] = function(i, mode) - if mode == "full" then - local obj = get_object(i) - local f1, f2, f3, f4, f5, esp = object_flags(obj) - if band(f5, TR5_SPELL_CONTAIN) ~= 0 then return TRUE end - end - end, - ["desc"] = - { - "Ah, an item that can contain a spell. To use it you must have some levels of", - "Magic skill and then you get the option to copy a spell when pressing m.", - "Then just select which spell to copy and to which object. Note that doing so", - "is permanent; the spell cannot be removed or changed later.", - } -} - ingame_help { ["hook"] = HOOK_RECALC_SKILLS, diff --git a/src/help.c b/src/help.c index 73892ff7..bee5c480 100644 --- a/src/help.c +++ b/src/help.c @@ -14,7 +14,7 @@ #include "angband.h" #define DESC_MAX 14 -#define TRIGGERED_HELP_MAX 16 +#define TRIGGERED_HELP_MAX 17 #define HELP_VOID_JUMPGATE 0 #define HELP_FOUNTAIN 1 @@ -32,6 +32,7 @@ #define HELP_GAME_THEME 13 #define HELP_1ST_LEVEL 14 #define HELP_20TH_LEVEL 15 +#define HELP_ID_SPELL_ITM 16 /** * Struct for help triggered by a boolean condition @@ -132,6 +133,21 @@ static bool_ trigger_20th_level(void *in, void *out) { return (p_ptr->lev >= 20); } +static bool_ trigger_identify_spell_item(void *in_, void *out) { + hook_identify_in *in = (hook_identify_in *) in_; + + if (in->mode == IDENT_FULL) + { + u32b f1, f2, f3, f4, f5, esp; + object_flags(in->o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + if (f5 & TR5_SPELL_CONTAIN) + { + return TRUE; + } + } + return FALSE; +} + /** * Trigger-based help items */ @@ -296,6 +312,16 @@ static triggered_help_type triggered_help[TRIGGERED_HELP_MAX] = "http://angband.oook.cz/ where it will end up in the ladder.", NULL } + }, + { HELP_ID_SPELL_ITM, + HOOK_IDENTIFY, + trigger_identify_spell_item, + { "Ah, an item that can contain a spell. To use it you must have some levels of", + "Magic skill and then you get the option to copy a spell when pressing m.", + "Then just select which spell to copy and to which object. Note that doing so", + "is permanent; the spell cannot be removed or changed later.", + NULL + } } }; -- cgit v1.2.3 From 87a8ec741d6f099939499054b83a76a43fa4ad89 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 09:36:04 +0200 Subject: Lua: Add new-style hook support for HOOK_RECALC_SKILLS --- src/skills.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/skills.c b/src/skills.c index 253eff3f..acb63999 100644 --- a/src/skills.c +++ b/src/skills.c @@ -375,6 +375,7 @@ void recalc_skills(bool_ init) } process_hooks(HOOK_RECALC_SKILLS, "()"); + process_hooks_new(HOOK_RECALC_SKILLS, NULL, NULL); /* Update stuffs */ p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS | PU_POWERS | -- cgit v1.2.3 From 625f73559675c8bc7e627cd6dc5ab924aa10a068 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 09:49:52 +0200 Subject: Lua: Add new-style hook support for HOOK_GAME_START --- src/dungeon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/dungeon.c b/src/dungeon.c index ff3cbdb9..f4803e3b 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -5653,6 +5653,7 @@ void play_game(bool_ new_game) /* Ok tell the scripts that the game is about to start */ process_hooks(HOOK_GAME_START, "()"); + process_hooks_new(HOOK_GAME_START, NULL, NULL); /* Character is now "complete" */ character_generated = TRUE; -- cgit v1.2.3 From 8f7682e6fbd636e3172290f0adc9e8b45c5dd0a2 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 09:55:18 +0200 Subject: Lua: Move "gained two melee skills" help to C --- lib/core/util.lua | 9 --------- lib/mods/theme/core/util.lua | 9 --------- lib/mods/theme/scpt/help.lua | 11 ----------- lib/scpt/help.lua | 11 ----------- src/help.c | 31 ++++++++++++++++++++++++++++++- 5 files changed, 30 insertions(+), 41 deletions(-) diff --git a/lib/core/util.lua b/lib/core/util.lua index 7729ac35..2d437d61 100644 --- a/lib/core/util.lua +++ b/lib/core/util.lua @@ -118,12 +118,3 @@ end function msg_format(...) msg_print(call(format, arg)) end - --- A way to check if the game is now running(as opposed to initialization/character gen) -game = {} -add_hooks -{ - [HOOK_GAME_START] = function () - game.started = TRUE - end -} diff --git a/lib/mods/theme/core/util.lua b/lib/mods/theme/core/util.lua index 7729ac35..2d437d61 100644 --- a/lib/mods/theme/core/util.lua +++ b/lib/mods/theme/core/util.lua @@ -118,12 +118,3 @@ end function msg_format(...) msg_print(call(format, arg)) end - --- A way to check if the game is now running(as opposed to initialization/character gen) -game = {} -add_hooks -{ - [HOOK_GAME_START] = function () - game.started = TRUE - end -} diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index d9f637bd..d8900d6c 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -218,14 +218,3 @@ ingame_help end end, } - -ingame_help -{ - ["hook"] = HOOK_RECALC_SKILLS, - ["event"] = function() if game.started and (get_melee_skills() > 1) then return TRUE end end, - ["desc"] = - { - "Ah, you now possess more than one melee type. To switch between them press m", - "and select the switch melee type option.", - } -} diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index 0ee307cb..734747ed 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -184,14 +184,3 @@ ingame_help end end, } - -ingame_help -{ - ["hook"] = HOOK_RECALC_SKILLS, - ["event"] = function() if game.started and (get_melee_skills() > 1) then return TRUE end end, - ["desc"] = - { - "Ah, you now possess more than one melee type. To switch between them press m", - "and select the switch melee type option.", - } -} diff --git a/src/help.c b/src/help.c index bee5c480..a80d1a33 100644 --- a/src/help.c +++ b/src/help.c @@ -14,7 +14,7 @@ #include "angband.h" #define DESC_MAX 14 -#define TRIGGERED_HELP_MAX 17 +#define TRIGGERED_HELP_MAX 18 #define HELP_VOID_JUMPGATE 0 #define HELP_FOUNTAIN 1 @@ -33,6 +33,12 @@ #define HELP_1ST_LEVEL 14 #define HELP_20TH_LEVEL 15 #define HELP_ID_SPELL_ITM 16 +#define HELP_MELEE_SKILLS 17 + +/** + * Game started? + */ +static bool_ game_started = FALSE; /** * Struct for help triggered by a boolean condition @@ -148,6 +154,10 @@ static bool_ trigger_identify_spell_item(void *in_, void *out) { return FALSE; } +static bool_ trigger_melee_skills(void *in, void *out) { + return (game_started && (get_melee_skills() > 1)); +} + /** * Trigger-based help items */ @@ -322,6 +332,14 @@ static triggered_help_type triggered_help[TRIGGERED_HELP_MAX] = "is permanent; the spell cannot be removed or changed later.", NULL } + }, + { HELP_MELEE_SKILLS, + HOOK_RECALC_SKILLS, + trigger_melee_skills, + { "Ah, you now possess more than one melee type. To switch between them press m", + "and select the switch melee type option.", + NULL + } } }; @@ -348,6 +366,12 @@ static bool_ triggered_help_hook(void *data, void *in, void *out) return FALSE; } +static bool_ hook_game_start(void *data, void *in, void *out) +{ + game_started = TRUE; + return FALSE; +} + static void setup_triggered_help_hook(int i) { static int counter = 0; @@ -373,6 +397,11 @@ static void setup_triggered_help_hooks() { setup_triggered_help_hook(i); } + + add_hook_new(HOOK_GAME_START, + hook_game_start, + "help_game_start", + NULL); } /* -- cgit v1.2.3 From cd9c9db64bff40addbbbf5834f8839e93717cfba Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 12:29:04 +0200 Subject: Lua: Move "race" help to C --- lib/mods/theme/scpt/help.lua | 27 ------------- lib/scpt/help.lua | 25 ------------ src/birth.c | 5 ++- src/externs.h | 1 + src/help.c | 94 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 99 insertions(+), 53 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index d8900d6c..3d4450b5 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -24,33 +24,6 @@ ingame_help -- list of files for classes, { filename, anchor } local t = { - ["race"] = - { - ["Beorning"] = { "r_beorn.txt", 0 }, - ["Dragon"] = { "r_dragon.txt", 0 }, - ["Dark-Elf"] = { "r_drkelf.txt", 0 }, - ["Dunadan"] = { "r_dunad.txt", 0 }, - ["Dwarf"] = { "r_dwarf.txt", 0 }, - ["Elf"] = { "r_elf.txt", 0 }, - ["Ent"] = { "r_ent.txt", 0 }, - ["Gnome"] = { "r_gnome.txt", 0 }, - ["Half-Elf"] = { "r_hafelf.txt", 0 }, - ["Half-Ogre"] = { "r_hafogr.txt", 0 }, - ["High-Elf"] = { "r_hielf.txt", 0 }, - ["Hobbit"] = { "r_hobbit.txt", 0 }, - ["Human"] = { "r_human.txt", 0 }, - ["Druadan"] = { "r_druadan.txt", 0 }, - ["Maia"] = { "r_maia.txt", 0 }, - ["Orc"] = { "r_orc.txt", 0 }, - ["Petty-Dwarf"] = { "r_pettyd.txt", 0 }, - ["RohanKnight"] = { "r_rohank.txt", 0 }, - ["Eagle"] = { "r_eagle.txt", 0 }, - ["Troll"] = { "r_troll.txt", 0 }, - ["Wood-Elf"] = { "r_wodelf.txt", 0 }, - ["Yeek"] = { "r_yeek.txt", 0 }, - ["Easterling"] = { "r_easterl.txt", 0 }, - ["Demon"] = { "r_demon.txt", 0}, - }, ["subrace"] = { ["Barbarian"] = { "rm_barb.txt", 0 }, diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index 734747ed..694fefeb 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -24,31 +24,6 @@ ingame_help -- list of files for classes, { filename, anchor } local t = { - ["race"] = - { - ["Beorning"] = { "r_beorn.txt", 0 }, - ["DeathMold"] = { "r_deathm.txt", 0 }, - ["Dark-Elf"] = { "r_drkelf.txt", 0 }, - ["Dunadan"] = { "r_dunad.txt", 0 }, - ["Dwarf"] = { "r_dwarf.txt", 0 }, - ["Elf"] = { "r_elf.txt", 0 }, - ["Ent"] = { "r_ent.txt", 0 }, - ["Gnome"] = { "r_gnome.txt", 0 }, - ["Half-Elf"] = { "r_hafelf.txt", 0 }, - ["Half-Ogre"] = { "r_hafogr.txt", 0 }, - ["High-Elf"] = { "r_hielf.txt", 0 }, - ["Hobbit"] = { "r_hobbit.txt", 0 }, - ["Human"] = { "r_human.txt", 0 }, - ["Kobold"] = { "r_kobold.txt", 0 }, - ["Maia"] = { "r_maia.txt", 0 }, - ["Orc"] = { "r_orc.txt", 0 }, - ["Petty-Dwarf"] = { "r_pettyd.txt", 0 }, - ["RohanKnight"] = { "r_rohank.txt", 0 }, - ["Thunderlord"] = { "r_thlord.txt", 0 }, - ["Troll"] = { "r_troll.txt", 0 }, - ["Wood-Elf"] = { "r_wodelf.txt", 0 }, - ["Yeek"] = { "r_yeek.txt", 0 }, - }, ["subrace"] = { ["Barbarian"] = { "rm_barb.txt", 0 }, diff --git a/src/birth.c b/src/birth.c index aaef998c..0192abc3 100644 --- a/src/birth.c +++ b/src/birth.c @@ -1924,7 +1924,10 @@ static bool_ player_birth_aux_ask() } k = (islower(c) ? A2I(c) : -1); if ((k >= 0) && (k < n)) break; - if (c == '?') exec_lua(format("ingame_help('select_context', 'race', '%s')", race_info[sel].title + rp_name)); + if (c == '?') + { + help_race(race_info[sel].title + rp_name); + } else if (c == '=') { screen_save(); diff --git a/src/externs.h b/src/externs.h index f727da82..87489bcc 100644 --- a/src/externs.h +++ b/src/externs.h @@ -618,6 +618,7 @@ extern void initialize_bookable_spells(); /* help.c */ extern void init_hooks_help(); +extern void help_race(cptr race); /* birth.c */ extern void print_desc_aux(cptr txt, int y, int x); diff --git a/src/help.c b/src/help.c index a80d1a33..689e1d1b 100644 --- a/src/help.c +++ b/src/help.c @@ -56,6 +56,55 @@ struct triggered_help_type cptr desc[DESC_MAX]; }; +/** + * Struct for context-sensitive help + */ +typedef struct context_help_type context_help_type; +struct context_help_type +{ + cptr key; /* Lookup key */ + cptr file_name; /* Name of help file */ + int anchor; /* Anchor in file */ +}; + +/** + * Race help files. + */ +context_help_type race_table[] = +{ + /* ToME */ + { "Beorning", "r_beorn.txt", 0 }, + { "DeathMold", "r_deathm.txt", 0 }, + { "Dark-Elf", "r_drkelf.txt", 0 }, + { "Dunadan", "r_dunad.txt", 0 }, + { "Dwarf", "r_dwarf.txt", 0 }, + { "Elf", "r_elf.txt", 0 }, + { "Ent", "r_ent.txt", 0 }, + { "Gnome", "r_gnome.txt", 0 }, + { "Half-Elf", "r_hafelf.txt", 0 }, + { "Half-Ogre", "r_hafogr.txt", 0 }, + { "High-Elf", "r_hielf.txt", 0 }, + { "Hobbit", "r_hobbit.txt", 0 }, + { "Human", "r_human.txt", 0 }, + { "Kobold", "r_kobold.txt", 0 }, + { "Maia", "r_maia.txt", 0 }, + { "Orc", "r_orc.txt", 0 }, + { "Petty-Dwarf", "r_pettyd.txt", 0 }, + { "RohanKnight", "r_rohank.txt", 0 }, + { "Thunderlord", "r_thlord.txt", 0 }, + { "Troll", "r_troll.txt", 0 }, + { "Wood-Elf", "r_wodelf.txt", 0 }, + { "Yeek", "r_yeek.txt", 0 }, + /* Theme */ + { "Dragon", "r_dragon.txt", 0 }, + { "Druadan", "r_druadan.txt", 0 }, + { "Eagle", "r_eagle.txt", 0 }, + { "Easterling", "r_easterl.txt", 0 }, + { "Demon", "r_demon.txt", 0 }, + /* End of list */ + { NULL, NULL, 0 }, +}; + /** * Trigger functions */ @@ -411,3 +460,48 @@ void init_hooks_help() { setup_triggered_help_hooks(); } + +/* + * Show help file + */ +static void show_context_help(context_help_type *context_help) +{ + assert(context_help != NULL); + + screen_save(); + + show_file(context_help->file_name, 0, -context_help->anchor, 0); + + screen_load(); +} + +/* + * Find context help + */ +static context_help_type *find_context_help(context_help_type table[], cptr key) +{ + int i; + + for (i = 0; ; i++) + { + context_help_type *context_help = &table[i]; + + if (context_help->key == NULL) + { + return NULL; /* End of list */ + } + + if (streq(key, context_help->key)) + { + return context_help; + } + } +} + +/* + * Racial help + */ +void help_race(cptr race) +{ + show_context_help(find_context_help(race_table, race)); +} -- cgit v1.2.3 From 0bd0bab14018806a9fafe8db624323ce4699fe9b Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 16:34:40 +0200 Subject: Lua: Move "subrace" help to C --- lib/mods/theme/scpt/help.lua | 28 ---------------------------- lib/scpt/help.lua | 12 ------------ src/birth.c | 5 ++++- src/externs.h | 1 + src/help.c | 41 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 46 insertions(+), 41 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index 3d4450b5..4f9c1521 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -24,34 +24,6 @@ ingame_help -- list of files for classes, { filename, anchor } local t = { - ["subrace"] = - { - ["Barbarian"] = { "rm_barb.txt", 0 }, - ["Classical"] = { "rm_class.txt", 0 }, - ["Corrupted"] = { "rm_corru.txt", 0 }, - ["Hermit"] = { "rm_herm.txt", 0 }, - ["LostSoul"] = { "rm_lsoul.txt", 0 }, - ["Skeleton"] = { "rm_skel.txt", 0 }, - ["Spectre"] = { "rm_spec.txt", 0 }, - ["Vampire"] = { "rm_vamp.txt", 0 }, - ["Zombie"] = { "rm_zomb.txt", 0 }, - ["Red"] = {"rm_red.txt", 0 }, - ["Black"] = {"rm_black.txt", 0 }, - ["Green"] = {"rm_green.txt", 0 }, - ["Blue"] = {"rm_blue.txt", 0 }, - ["White"] = {"rm_white.txt", 0 }, - ["Ethereal"] = {"rm_ether.txt", 0 }, - ["(Narrog)"] = {"rm_narrog.txt", 0 }, - ["(Aewrog)"] = {"rm_aewrog.txt", 0 }, - ["(Hurog)"] = {"rm_hurog.txt", 0 }, - ["(Sarnrog)"] = {"rm_sarnrog.txt", 0 }, - ["(Caborrog)"] = {"rm_cabrog.txt", 0 }, - ["(Draugrog)"] = {"rm_drarog.txt", 0 }, - ["(Lygrog)"] = {"rm_lygrog.txt", 0 }, - ["(Limrog)"] = {"rm_limrog.txt", 0 }, - ["(Rawrog)"] = {"rm_rawrog.txt", 0 }, - ["(Adanrog)"] = {"rm_adanrog.txt", 0 }, - }, ["class"] = { ["Archer"] = { "c_archer.txt", 0 }, diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index 694fefeb..daff0ed6 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -24,18 +24,6 @@ ingame_help -- list of files for classes, { filename, anchor } local t = { - ["subrace"] = - { - ["Barbarian"] = { "rm_barb.txt", 0 }, - ["Classical"] = { "rm_class.txt", 0 }, - ["Corrupted"] = { "rm_corru.txt", 0 }, - ["Hermit"] = { "rm_herm.txt", 0 }, - ["LostSoul"] = { "rm_lsoul.txt", 0 }, - ["Skeleton"] = { "rm_skel.txt", 0 }, - ["Spectre"] = { "rm_spec.txt", 0 }, - ["Vampire"] = { "rm_vamp.txt", 0 }, - ["Zombie"] = { "rm_zomb.txt", 0 }, - }, ["class"] = { ["Alchemist"] = { "c_alchem.txt", 0 }, diff --git a/src/birth.c b/src/birth.c index 0192abc3..595a8dfa 100644 --- a/src/birth.c +++ b/src/birth.c @@ -2050,7 +2050,10 @@ static bool_ player_birth_aux_ask() while (!(BIT(racem[k]) & rmp_ptr->choice[racem[k] / 32])); break; } - else if (c == '?') exec_lua(format("ingame_help('select_context', 'subrace', '%s')", race_mod_info[racem[sel]].title + rmp_name)); + else if (c == '?') + { + help_subrace(race_mod_info[racem[sel]].title + rmp_name); + } k = (islower(c) ? A2I(c) : -1); if ((k >= 0) && (k < max_racem) && diff --git a/src/externs.h b/src/externs.h index 87489bcc..6be9776b 100644 --- a/src/externs.h +++ b/src/externs.h @@ -619,6 +619,7 @@ extern void initialize_bookable_spells(); /* help.c */ extern void init_hooks_help(); extern void help_race(cptr race); +extern void help_subrace(cptr subrace); /* birth.c */ extern void print_desc_aux(cptr txt, int y, int x); diff --git a/src/help.c b/src/help.c index 689e1d1b..b924017d 100644 --- a/src/help.c +++ b/src/help.c @@ -105,6 +105,42 @@ context_help_type race_table[] = { NULL, NULL, 0 }, }; +/** + * Subrace help files. + */ +context_help_type subrace_table[] = +{ + /* ToME */ + { "Barbarian", "rm_barb.txt", 0 }, + { "Classical", "rm_class.txt", 0 }, + { "Corrupted", "rm_corru.txt", 0 }, + { "Hermit", "rm_herm.txt", 0 }, + { "LostSoul", "rm_lsoul.txt", 0 }, + { "Skeleton", "rm_skel.txt", 0 }, + { "Spectre", "rm_spec.txt", 0 }, + { "Vampire", "rm_vamp.txt", 0 }, + { "Zombie", "rm_zomb.txt", 0 }, + /* Theme */ + { "Red", "rm_red.txt", 0 }, + { "Black", "rm_black.txt", 0 }, + { "Green", "rm_green.txt", 0 }, + { "Blue", "rm_blue.txt", 0 }, + { "White", "rm_white.txt", 0 }, + { "Ethereal", "rm_ether.txt", 0 }, + { "(Narrog)", "rm_narrog.txt", 0 }, + { "(Aewrog)", "rm_aewrog.txt", 0 }, + { "(Hurog)", "rm_hurog.txt", 0 }, + { "(Sarnrog)", "rm_sarnrog.txt", 0 }, + { "(Caborrog)", "rm_cabrog.txt", 0 }, + { "(Draugrog)", "rm_drarog.txt", 0 }, + { "(Lygrog)", "rm_lygrog.txt", 0 }, + { "(Limrog)", "rm_limrog.txt", 0 }, + { "(Rawrog)", "rm_rawrog.txt", 0 }, + { "(Adanrog)", "rm_adanrog.txt", 0 }, + /* End of list */ + { NULL, NULL, 0 }, +}; + /** * Trigger functions */ @@ -505,3 +541,8 @@ void help_race(cptr race) { show_context_help(find_context_help(race_table, race)); } + +void help_subrace(cptr subrace) +{ + show_context_help(find_context_help(subrace_table, subrace)); +} -- cgit v1.2.3 From 5ccc3347038709ba87f5b04d19d800aca459158e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 16:54:02 +0200 Subject: Lua: Move "class" help to C --- lib/mods/theme/scpt/help.lua | 48 ---------------------------------- lib/scpt/help.lua | 36 ------------------------- src/birth.c | 10 +++++-- src/externs.h | 1 + src/help.c | 62 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 86 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index 4f9c1521..7046e846 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -24,54 +24,6 @@ ingame_help -- list of files for classes, { filename, anchor } local t = { - ["class"] = - { - ["Archer"] = { "c_archer.txt", 0 }, - ["Ascetic"] = { "c_ascet.txt", 0 }, - ["Assassin"] = { "c_assass.txt", 0 }, - ["Axemaster"] = { "c_axemas.txt", 0 }, - ["Bard"] = { "c_bard.txt", 0 }, - ["Clairvoyant"] = {"c_clairv.txt", 0}, - ["Dark-Priest"] = { "c_pr_drk.txt", 0 }, - ["Demonologist"] = { "c_demono.txt", 0 }, - ["Druid"] = { "c_druid.txt", 0 }, - ["Geomancer"] = { "c_geoman.txt", 0 }, - ["Haftedmaster"] = { "c_hafted.txt", 0 }, - ["Loremaster"] = { "c_lorema.txt", 0 }, - ["Mage"] = { "c_mage.txt", 0 }, - ["Mercenary"] = { "c_mercen.txt", 0 }, - ["Mimic"] = { "c_mimic.txt", 0 }, - ["Mindcrafter"] = { "c_mindcr.txt", 0 }, - ["Monk"] = { "c_monk.txt", 0 }, - ["Necromancer"] = { "c_necro.txt", 0 }, - ["Pacifist"] = { "c_pacif.txt", 0 }, - ["Paladin"] = { "c_palad.txt", 0 }, - ["Peace-mage"] = { "c_peacemag.txt", 0 }, - ["Polearmmaster"] = { "c_polear.txt", 0 }, - ["Possessor"] = { "c_posses.txt", 0 }, - ["Priest"] = { "c_priest.txt", 0 }, - ["Priest(Eru)"] = { "c_pr_eru.txt", 0 }, - ["Priest(Mandos)"] = { "c_pr_mand.txt", 0 }, - ["Priest(Manwe)"] = { "c_pr_man.txt", 0 }, - ["Priest(Ulmo)"] = { "c_pr_ulmo.txt", 0 }, - ["Priest(Varda)"] = { "c_pr_varda.txt", 0 }, - ["Ranger"] = { "c_ranger.txt", 0 }, - ["Rogue"] = { "c_rogue.txt", 0 }, - ["Runecrafter"] = { "c_runecr.txt", 0 }, - ["Sniper"] = {"c_sniper.txt", 0 }, - ["Sorceror"] = { "c_sorcer.txt", 0 }, - ["Stonewright"] = { "c_stonewr.txt", 0 }, - ["Summoner"] = { "c_summon.txt", 0 }, - ["Swordmaster"] = { "c_swordm.txt", 0 }, - ["Symbiant"] = { "c_symbia.txt", 0 }, - ["Thaumaturgist"] = { "c_thaum.txt", 0 }, - ["Trapper"] = { "c_trapper.txt", 0 }, - ["Unbeliever"] = { "c_unbel.txt", 0 }, - ["Wainrider"] = { "c_wainrid.txt", 0 }, - ["War-mage"] = { "c_warmage.txt", 0 }, - ["Warper"] = { "c_warper.txt", 0 }, - ["Warrior"] = { "c_warrio.txt", 0 }, - }, ["god"] = { ["Aule the Smith"] = { "g_aule.txt", 0 }, diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index daff0ed6..9e94606f 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -24,42 +24,6 @@ ingame_help -- list of files for classes, { filename, anchor } local t = { - ["class"] = - { - ["Alchemist"] = { "c_alchem.txt", 0 }, - ["Archer"] = { "c_archer.txt", 0 }, - ["Assassin"] = { "c_assass.txt", 0 }, - ["Axemaster"] = { "c_axemas.txt", 0 }, - ["Bard"] = { "c_bard.txt", 0 }, - ["Dark-Priest"] = { "c_pr_drk.txt", 0 }, - ["Demonologist"] = { "c_demono.txt", 0 }, - ["Druid"] = { "c_druid.txt", 0 }, - ["Geomancer"] = { "c_geoman.txt", 0 }, - ["Haftedmaster"] = { "c_hafted.txt", 0 }, - ["Loremaster"] = { "c_lorema.txt", 0 }, - ["Mage"] = { "c_mage.txt", 0 }, - ["Mimic"] = { "c_mimic.txt", 0 }, - ["Mindcrafter"] = { "c_mindcr.txt", 0 }, - ["Monk"] = { "c_monk.txt", 0 }, - ["Necromancer"] = { "c_necro.txt", 0 }, - ["Paladin"] = { "c_palad.txt", 0 }, - ["Polearmmaster"] = { "c_polear.txt", 0 }, - ["Possessor"] = { "c_posses.txt", 0 }, - ["Priest"] = { "c_priest.txt", 0 }, - ["Priest(Eru)"] = { "c_pr_eru.txt", 0 }, - ["Priest(Manwe)"] = { "c_pr_man.txt", 0 }, - ["Ranger"] = { "c_ranger.txt", 0 }, - ["Rogue"] = { "c_rogue.txt", 0 }, - ["Runecrafter"] = { "c_runecr.txt", 0 }, - ["Sorceror"] = { "c_sorcer.txt", 0 }, - ["Summoner"] = { "c_summon.txt", 0 }, - ["Swordmaster"] = { "c_swordm.txt", 0 }, - ["Symbiant"] = { "c_symbia.txt", 0 }, - ["Thaumaturgist"] = { "c_thaum.txt", 0 }, - ["Unbeliever"] = { "c_unbel.txt", 0 }, - ["Warper"] = { "c_warper.txt", 0 }, - ["Warrior"] = { "c_warrio.txt", 0 }, - }, ["god"] = { ["Eru Iluvatar"] = { "g_eru.txt", 0 }, diff --git a/src/birth.c b/src/birth.c index 595a8dfa..58debca0 100644 --- a/src/birth.c +++ b/src/birth.c @@ -2196,7 +2196,10 @@ static bool_ player_birth_aux_ask() } k = (islower(c) ? A2I(c) : (D2I(c) + 26)); if ((k >= 0) && (k < n)) break; - if (c == '?') exec_lua(format("ingame_help('select_context', 'class', '%s')", class_info[class_types[sel]].title + c_name)); + if (c == '?') + { + help_class(class_info[class_types[sel]].title + c_name); + } else if (c == '=') { screen_save(); @@ -2275,7 +2278,10 @@ static bool_ player_birth_aux_ask() } k = (islower(c) ? A2I(c) : (D2I(c) + 26)); if ((k >= 0) && (k < n)) break; - if (c == '?') exec_lua(format("ingame_help('select_context', 'class', '%s')", class_info[p_ptr->pclass].spec[sel].title + c_name)); + if (c == '?') + { + help_class(class_info[p_ptr->pclass].spec[sel].title + c_name); + } else if (c == '=') { screen_save(); diff --git a/src/externs.h b/src/externs.h index 6be9776b..3ea6d2d6 100644 --- a/src/externs.h +++ b/src/externs.h @@ -620,6 +620,7 @@ extern void initialize_bookable_spells(); extern void init_hooks_help(); extern void help_race(cptr race); extern void help_subrace(cptr subrace); +extern void help_class(cptr klass); /* birth.c */ extern void print_desc_aux(cptr txt, int y, int x); diff --git a/src/help.c b/src/help.c index b924017d..4d894044 100644 --- a/src/help.c +++ b/src/help.c @@ -141,6 +141,63 @@ context_help_type subrace_table[] = { NULL, NULL, 0 }, }; +/** + * Class help files + */ +context_help_type class_table[] = +{ + /* ToME */ + { "Alchemist", "c_alchem.txt", 0 }, + { "Archer", "c_archer.txt", 0 }, + { "Assassin", "c_assass.txt", 0 }, + { "Axemaster", "c_axemas.txt", 0 }, + { "Bard", "c_bard.txt", 0 }, + { "Dark-Priest", "c_pr_drk.txt", 0 }, + { "Demonologist", "c_demono.txt", 0 }, + { "Druid", "c_druid.txt", 0 }, + { "Geomancer", "c_geoman.txt", 0 }, + { "Haftedmaster", "c_hafted.txt", 0 }, + { "Loremaster", "c_lorema.txt", 0 }, + { "Mage", "c_mage.txt", 0 }, + { "Mimic", "c_mimic.txt", 0 }, + { "Mindcrafter", "c_mindcr.txt", 0 }, + { "Monk", "c_monk.txt", 0 }, + { "Necromancer", "c_necro.txt", 0 }, + { "Paladin", "c_palad.txt", 0 }, + { "Polearmmaster", "c_polear.txt", 0 }, + { "Possessor", "c_posses.txt", 0 }, + { "Priest", "c_priest.txt", 0 }, + { "Priest(Eru)", "c_pr_eru.txt", 0 }, + { "Priest(Manwe)", "c_pr_man.txt", 0 }, + { "Ranger", "c_ranger.txt", 0 }, + { "Rogue", "c_rogue.txt", 0 }, + { "Runecrafter", "c_runecr.txt", 0 }, + { "Sorceror", "c_sorcer.txt", 0 }, + { "Summoner", "c_summon.txt", 0 }, + { "Swordmaster", "c_swordm.txt", 0 }, + { "Symbiant", "c_symbia.txt", 0 }, + { "Thaumaturgist", "c_thaum.txt", 0 }, + { "Unbeliever", "c_unbel.txt", 0 }, + { "Warper", "c_warper.txt", 0 }, + { "Warrior", "c_warrio.txt", 0 }, + /* Theme */ + { "Ascetic", "c_ascet.txt", 0 }, + { "Clairvoyant", "c_clairv.txt", 0 }, + { "Mercenary", "c_mercen.txt", 0 }, + { "Pacifist", "c_pacif.txt", 0 }, + { "Peace-mage", "c_peacemag.txt", 0 }, + { "Priest(Mandos)", "c_pr_mand.txt", 0 }, + { "Priest(Ulmo)", "c_pr_ulmo.txt", 0 }, + { "Priest(Varda)", "c_pr_varda.txt", 0 }, + { "Sniper", "c_sniper.txt", 0 }, + { "Stonewright", "c_stonewr.txt", 0 }, + { "Trapper", "c_trapper.txt", 0 }, + { "Wainrider", "c_wainrid.txt", 0 }, + { "War-mage", "c_warmage.txt", 0 }, + /* End of list */ + { NULL, NULL, 0 }, +}; + /** * Trigger functions */ @@ -546,3 +603,8 @@ void help_subrace(cptr subrace) { show_context_help(find_context_help(subrace_table, subrace)); } + +void help_class(cptr klass) +{ + show_context_help(find_context_help(class_table, klass)); +} -- cgit v1.2.3 From 76085d3681e4c42b75fddad7be88006c3d97d0d8 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 17:02:58 +0200 Subject: Lua: Move "god" help to C --- lib/mods/theme/scpt/help.lua | 12 ------------ lib/scpt/help.lua | 8 -------- src/birth.c | 5 ++++- src/externs.h | 1 + src/help.c | 31 +++++++++++++++++++++++++++++++ 5 files changed, 36 insertions(+), 21 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index 7046e846..189cd687 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -24,18 +24,6 @@ ingame_help -- list of files for classes, { filename, anchor } local t = { - ["god"] = - { - ["Aule the Smith"] = { "g_aule.txt", 0 }, - ["Eru Iluvatar"] = { "g_eru.txt", 0 }, - ["Mandos"] = { "g_mandos.txt", 0 }, - ["Manwe Sulimo"] = { "g_manwe.txt", 0 }, - ["Melkor Bauglir"] = { "g_melkor.txt", 0 }, - ["Tulkas"] = { "g_tulkas.txt", 0 }, - ["Ulmo"] = { "g_ulmo.txt", 0 }, - ["Varda Elentari"] = { "g_varda.txt", 0 }, - ["Yavanna Kementari"] = { "g_yavann.txt", 0 }, - }, ["skill"] = { ["Air"] = { "skills.txt", 27 }, diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index 9e94606f..189cd687 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -24,14 +24,6 @@ ingame_help -- list of files for classes, { filename, anchor } local t = { - ["god"] = - { - ["Eru Iluvatar"] = { "g_eru.txt", 0 }, - ["Manwe Sulimo"] = { "g_manwe.txt", 0 }, - ["Tulkas"] = { "g_tulkas.txt", 0 }, - ["Melkor Bauglir"] = { "g_melkor.txt", 0 }, - ["Yavanna Kementari"] = { "g_yavann.txt", 0 }, - }, ["skill"] = { ["Air"] = { "skills.txt", 27 }, diff --git a/src/birth.c b/src/birth.c index 58debca0..14c0b44f 100644 --- a/src/birth.c +++ b/src/birth.c @@ -2398,7 +2398,10 @@ static bool_ player_birth_aux_ask() k = choice[k]; break; } - if (c == '?') exec_lua(format("ingame_help('select_context', 'god', '%s')", deity_info[choice[sel]].name)); + if (c == '?') + { + help_god(deity_info[choice[sel]].name); + } else if (c == '=') { screen_save(); diff --git a/src/externs.h b/src/externs.h index 3ea6d2d6..d2ff11c2 100644 --- a/src/externs.h +++ b/src/externs.h @@ -621,6 +621,7 @@ extern void init_hooks_help(); extern void help_race(cptr race); extern void help_subrace(cptr subrace); extern void help_class(cptr klass); +extern void help_god(cptr god); /* birth.c */ extern void print_desc_aux(cptr txt, int y, int x); diff --git a/src/help.c b/src/help.c index 4d894044..874f0f45 100644 --- a/src/help.c +++ b/src/help.c @@ -198,6 +198,26 @@ context_help_type class_table[] = { NULL, NULL, 0 }, }; +/** + * God help files + */ +context_help_type god_table[] = +{ + /* ToME */ + { "Eru Iluvatar", "g_eru.txt", 0 }, + { "Manwe Sulimo", "g_manwe.txt", 0 }, + { "Tulkas", "g_tulkas.txt", 0 }, + { "Melkor Bauglir", "g_melkor.txt", 0 }, + { "Yavanna Kementari", "g_yavann.txt", 0 }, + /* Theme */ + { "Aule the Smith", "g_aule.txt", 0 }, + { "Mandos", "g_mandos.txt", 0 }, + { "Ulmo", "g_ulmo.txt", 0 }, + { "Varda Elentari", "g_varda.txt", 0 }, + /* End of list */ + { NULL, NULL, 0 }, +}; + /** * Trigger functions */ @@ -608,3 +628,14 @@ void help_class(cptr klass) { show_context_help(find_context_help(class_table, klass)); } + +void help_god(cptr god) +{ + context_help_type *context_help = + find_context_help(god_table, god); + + if (context_help != NULL) + { + show_context_help(context_help); + } +} -- cgit v1.2.3 From 4da2e8d9545698b9fc7936e5f6d9a137d0b7c930 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 17:14:22 +0200 Subject: Lua: Move "skill" help to C --- lib/mods/theme/scpt/help.lua | 58 ------------------------------------- lib/scpt/help.lua | 58 ------------------------------------- src/externs.h | 1 + src/help.c | 68 ++++++++++++++++++++++++++++++++++++++++++++ src/skills.c | 6 ++-- 5 files changed, 73 insertions(+), 118 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index 189cd687..421cdb11 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -24,64 +24,6 @@ ingame_help -- list of files for classes, { filename, anchor } local t = { - ["skill"] = - { - ["Air"] = { "skills.txt", 27 }, - ["Alchemy"] = { "skills.txt", 49 }, - ["Antimagic"] = { "skills.txt", 50 }, - ["Archery"] = { "skills.txt", 08 }, - ["Axe-mastery"] = { "skills.txt", 05 }, - ["Backstab"] = { "skills.txt", 18 }, - ["Barehand-combat"] = { "skills.txt", 13 }, - ["Boomerang-mastery"] = { "skills.txt", 12 }, - ["Boulder-throwing"] = { "skills.txt", 58 }, - ["Bow-mastery"] = { "skills.txt", 10 }, - ["Combat"] = { "skills.txt", 01 }, - ["Conveyance"] = { "skills.txt", 30 }, - ["Corpse-preservation"] = { "skills.txt", 44 }, - ["Critical-hits"] = { "skills.txt", 04 }, - ["Crossbow-mastery"] = { "skills.txt", 11 }, - ["Demonology"] = { "skills.txt", 52 }, - ["Disarming"] = { "skills.txt", 16 }, - ["Divination"] = { "skills.txt", 31 }, - ["Dodging"] = { "skills.txt", 20 }, - ["Druidistic"] = { "skills.txt", 40 }, - ["Earth"] = { "skills.txt", 28 }, - ["Fire"] = { "skills.txt", 25 }, - ["Geomancy"] = { "skills.txt", 60 }, - ["Hafted-mastery"] = { "skills.txt", 06 }, - ["Magic"] = { "skills.txt", 21 }, - ["Magic-Device"] = { "skills.txt", 54 }, - ["Mana"] = { "skills.txt", 24 }, - ["Meta"] = { "skills.txt", 29 }, - ["Mimicry"] = { "skills.txt", 47 }, - ["Mind"] = { "skills.txt", 33 }, - ["Mindcraft"] = { "skills.txt", 41 }, - ["Monster-lore"] = { "skills.txt", 42 }, - ["Music"] = { "skills.txt", 59 }, - ["Nature"] = { "skills.txt", 34 }, - ["Necromancy"] = { "skills.txt", 35 }, - ["Polearm-mastery"] = { "skills.txt", 07 }, - ["Possession"] = { "skills.txt", 45 }, - ["Prayer"] = { "skills.txt", 39 }, - ["Runecraft"] = { "skills.txt", 36 }, - ["Sling-mastery"] = { "skills.txt", 09 }, - ["Sneakiness"] = { "skills.txt", 14 }, - ["Spell-power"] = { "skills.txt", 22 }, - ["Spirituality"] = { "skills.txt", 38 }, - ["Sorcery"] = { "skills.txt", 23 }, - ["Stealing"] = { "skills.txt", 19 }, - ["Stealth"] = { "skills.txt", 15 }, - ["Stunning-blows"] = { "skills.txt", 53 }, - ["Summoning"] = { "skills.txt", 43 }, - ["Sword-mastery"] = { "skills.txt", 03 }, - ["Symbiosis"] = { "skills.txt", 46 }, - ["Temporal"] = { "skills.txt", 32 }, - ["Thaumaturgy"] = { "skills.txt", 37 }, - ["Udun"] = { "skills.txt", 48 }, - ["Weaponmastery"] = { "skills.txt", 02 }, - ["Water"] = { "skills.txt", 26 }, - }, ["ability"] = { ["Spread blows"] = { "ability.txt", 02 }, diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index 189cd687..421cdb11 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -24,64 +24,6 @@ ingame_help -- list of files for classes, { filename, anchor } local t = { - ["skill"] = - { - ["Air"] = { "skills.txt", 27 }, - ["Alchemy"] = { "skills.txt", 49 }, - ["Antimagic"] = { "skills.txt", 50 }, - ["Archery"] = { "skills.txt", 08 }, - ["Axe-mastery"] = { "skills.txt", 05 }, - ["Backstab"] = { "skills.txt", 18 }, - ["Barehand-combat"] = { "skills.txt", 13 }, - ["Boomerang-mastery"] = { "skills.txt", 12 }, - ["Boulder-throwing"] = { "skills.txt", 58 }, - ["Bow-mastery"] = { "skills.txt", 10 }, - ["Combat"] = { "skills.txt", 01 }, - ["Conveyance"] = { "skills.txt", 30 }, - ["Corpse-preservation"] = { "skills.txt", 44 }, - ["Critical-hits"] = { "skills.txt", 04 }, - ["Crossbow-mastery"] = { "skills.txt", 11 }, - ["Demonology"] = { "skills.txt", 52 }, - ["Disarming"] = { "skills.txt", 16 }, - ["Divination"] = { "skills.txt", 31 }, - ["Dodging"] = { "skills.txt", 20 }, - ["Druidistic"] = { "skills.txt", 40 }, - ["Earth"] = { "skills.txt", 28 }, - ["Fire"] = { "skills.txt", 25 }, - ["Geomancy"] = { "skills.txt", 60 }, - ["Hafted-mastery"] = { "skills.txt", 06 }, - ["Magic"] = { "skills.txt", 21 }, - ["Magic-Device"] = { "skills.txt", 54 }, - ["Mana"] = { "skills.txt", 24 }, - ["Meta"] = { "skills.txt", 29 }, - ["Mimicry"] = { "skills.txt", 47 }, - ["Mind"] = { "skills.txt", 33 }, - ["Mindcraft"] = { "skills.txt", 41 }, - ["Monster-lore"] = { "skills.txt", 42 }, - ["Music"] = { "skills.txt", 59 }, - ["Nature"] = { "skills.txt", 34 }, - ["Necromancy"] = { "skills.txt", 35 }, - ["Polearm-mastery"] = { "skills.txt", 07 }, - ["Possession"] = { "skills.txt", 45 }, - ["Prayer"] = { "skills.txt", 39 }, - ["Runecraft"] = { "skills.txt", 36 }, - ["Sling-mastery"] = { "skills.txt", 09 }, - ["Sneakiness"] = { "skills.txt", 14 }, - ["Spell-power"] = { "skills.txt", 22 }, - ["Spirituality"] = { "skills.txt", 38 }, - ["Sorcery"] = { "skills.txt", 23 }, - ["Stealing"] = { "skills.txt", 19 }, - ["Stealth"] = { "skills.txt", 15 }, - ["Stunning-blows"] = { "skills.txt", 53 }, - ["Summoning"] = { "skills.txt", 43 }, - ["Sword-mastery"] = { "skills.txt", 03 }, - ["Symbiosis"] = { "skills.txt", 46 }, - ["Temporal"] = { "skills.txt", 32 }, - ["Thaumaturgy"] = { "skills.txt", 37 }, - ["Udun"] = { "skills.txt", 48 }, - ["Weaponmastery"] = { "skills.txt", 02 }, - ["Water"] = { "skills.txt", 26 }, - }, ["ability"] = { ["Spread blows"] = { "ability.txt", 02 }, diff --git a/src/externs.h b/src/externs.h index d2ff11c2..6b416e7e 100644 --- a/src/externs.h +++ b/src/externs.h @@ -622,6 +622,7 @@ extern void help_race(cptr race); extern void help_subrace(cptr subrace); extern void help_class(cptr klass); extern void help_god(cptr god); +extern void help_skill(cptr skill); /* birth.c */ extern void print_desc_aux(cptr txt, int y, int x); diff --git a/src/help.c b/src/help.c index 874f0f45..510fe2dd 100644 --- a/src/help.c +++ b/src/help.c @@ -218,6 +218,69 @@ context_help_type god_table[] = { NULL, NULL, 0 }, }; +/** + * Skill help files + */ +context_help_type skill_table[] = +{ + { "Air", "skills.txt", 27 }, + { "Alchemy", "skills.txt", 49 }, + { "Antimagic", "skills.txt", 50 }, + { "Archery", "skills.txt", 8 }, + { "Axe-mastery", "skills.txt", 5 }, + { "Backstab", "skills.txt", 18 }, + { "Barehand-combat", "skills.txt", 13 }, + { "Boomerang-mastery", "skills.txt", 12 }, + { "Boulder-throwing", "skills.txt", 58 }, + { "Bow-mastery", "skills.txt", 10 }, + { "Combat", "skills.txt", 1 }, + { "Conveyance", "skills.txt", 30 }, + { "Corpse-preservation", "skills.txt", 44 }, + { "Critical-hits", "skills.txt", 4 }, + { "Crossbow-mastery", "skills.txt", 11 }, + { "Demonology", "skills.txt", 52 }, + { "Disarming", "skills.txt", 16 }, + { "Divination", "skills.txt", 31 }, + { "Dodging", "skills.txt", 20 }, + { "Druidistic", "skills.txt", 40 }, + { "Earth", "skills.txt", 28 }, + { "Fire", "skills.txt", 25 }, + { "Geomancy", "skills.txt", 60 }, + { "Hafted-mastery", "skills.txt", 6 }, + { "Magic", "skills.txt", 21 }, + { "Magic-Device", "skills.txt", 54 }, + { "Mana", "skills.txt", 24 }, + { "Meta", "skills.txt", 29 }, + { "Mimicry", "skills.txt", 47 }, + { "Mind", "skills.txt", 33 }, + { "Mindcraft", "skills.txt", 41 }, + { "Monster-lore", "skills.txt", 42 }, + { "Music", "skills.txt", 59 }, + { "Nature", "skills.txt", 34 }, + { "Necromancy", "skills.txt", 35 }, + { "Polearm-mastery", "skills.txt", 7 }, + { "Possession", "skills.txt", 45 }, + { "Prayer", "skills.txt", 39 }, + { "Runecraft", "skills.txt", 36 }, + { "Sling-mastery", "skills.txt", 9 }, + { "Sneakiness", "skills.txt", 14 }, + { "Spell-power", "skills.txt", 22 }, + { "Spirituality", "skills.txt", 38 }, + { "Sorcery", "skills.txt", 23 }, + { "Stealing", "skills.txt", 19 }, + { "Stealth", "skills.txt", 15 }, + { "Stunning-blows", "skills.txt", 53 }, + { "Summoning", "skills.txt", 43 }, + { "Sword-mastery", "skills.txt", 3 }, + { "Symbiosis", "skills.txt", 46 }, + { "Temporal", "skills.txt", 32 }, + { "Thaumaturgy", "skills.txt", 37 }, + { "Udun", "skills.txt", 48 }, + { "Weaponmastery", "skills.txt", 2 }, + { "Water", "skills.txt", 26 }, + { NULL, NULL, 0 }, +}; + /** * Trigger functions */ @@ -639,3 +702,8 @@ void help_god(cptr god) show_context_help(context_help); } } + +void help_skill(cptr skill) +{ + show_context_help(find_context_help(skill_table, skill)); +} diff --git a/src/skills.c b/src/skills.c index acb63999..2a0a4f18 100644 --- a/src/skills.c +++ b/src/skills.c @@ -553,8 +553,10 @@ void do_cmd_skill() if (wizard && (c == '-')) skill_bonus[table[sel][0]] -= SKILL_STEP; /* Contextual help */ - if (c == '?') exec_lua(format("ingame_help('select_context', 'skill', '%s')", s_info[table[sel][0]].name + s_name)); - ; + if (c == '?') + { + help_skill(s_info[table[sel][0]].name + s_name); + } /* Handle boundaries and scrolling */ if (sel < 0) sel = max - 1; -- cgit v1.2.3 From cbe5a2de1592e402808e962de8d346829aa5aba4 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 17:18:46 +0200 Subject: Lua: Move "ability" help to C --- lib/mods/theme/scpt/help.lua | 14 -------------- lib/scpt/help.lua | 14 -------------- src/externs.h | 1 + src/help.c | 24 ++++++++++++++++++++++++ src/skills.c | 6 ++++-- 5 files changed, 29 insertions(+), 30 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index 421cdb11..9d53ba40 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -24,20 +24,6 @@ ingame_help -- list of files for classes, { filename, anchor } local t = { - ["ability"] = - { - ["Spread blows"] = { "ability.txt", 02 }, - ["Tree walking"] = { "ability.txt", 03 }, - ["Perfect casting"] = { "ability.txt", 04 }, - ["Extra Max Blow(1)"] = { "ability.txt", 05 }, - ["Extra Max Blow(2)"] = { "ability.txt", 06 }, - ["Ammo creation"] = { "ability.txt", 07 }, - ["Touch of death"] = { "ability.txt", 08 }, - ["Artifact Creation"] = { "ability.txt", 09 }, - ["Far reaching attack"] = { "ability.txt", 10 }, - ["Trapping"] = { "ability.txt", 11 }, - ["Undead Form"] = { "ability.txt", 12 }, - }, } if t[typ][name] then ingame_help_doc(t[typ][name][1], t[typ][name][2]) diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index 421cdb11..9d53ba40 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -24,20 +24,6 @@ ingame_help -- list of files for classes, { filename, anchor } local t = { - ["ability"] = - { - ["Spread blows"] = { "ability.txt", 02 }, - ["Tree walking"] = { "ability.txt", 03 }, - ["Perfect casting"] = { "ability.txt", 04 }, - ["Extra Max Blow(1)"] = { "ability.txt", 05 }, - ["Extra Max Blow(2)"] = { "ability.txt", 06 }, - ["Ammo creation"] = { "ability.txt", 07 }, - ["Touch of death"] = { "ability.txt", 08 }, - ["Artifact Creation"] = { "ability.txt", 09 }, - ["Far reaching attack"] = { "ability.txt", 10 }, - ["Trapping"] = { "ability.txt", 11 }, - ["Undead Form"] = { "ability.txt", 12 }, - }, } if t[typ][name] then ingame_help_doc(t[typ][name][1], t[typ][name][2]) diff --git a/src/externs.h b/src/externs.h index 6b416e7e..e1f77bc1 100644 --- a/src/externs.h +++ b/src/externs.h @@ -623,6 +623,7 @@ extern void help_subrace(cptr subrace); extern void help_class(cptr klass); extern void help_god(cptr god); extern void help_skill(cptr skill); +extern void help_ability(cptr ability); /* birth.c */ extern void print_desc_aux(cptr txt, int y, int x); diff --git a/src/help.c b/src/help.c index 510fe2dd..a19b7b27 100644 --- a/src/help.c +++ b/src/help.c @@ -281,6 +281,25 @@ context_help_type skill_table[] = { NULL, NULL, 0 }, }; +/** + * Ability help files + */ +context_help_type ability_table[] = +{ + { "Spread blows", "ability.txt", 2 }, + { "Tree walking", "ability.txt", 3 }, + { "Perfect casting", "ability.txt", 4 }, + { "Extra Max Blow(1)", "ability.txt", 5 }, + { "Extra Max Blow(2)", "ability.txt", 6 }, + { "Ammo creation", "ability.txt", 7 }, + { "Touch of death", "ability.txt", 8 }, + { "Artifact Creation", "ability.txt", 9 }, + { "Far reaching attack", "ability.txt", 10 }, + { "Trapping", "ability.txt", 11 }, + { "Undead Form", "ability.txt", 12 }, + { NULL, NULL, 0 }, +}; + /** * Trigger functions */ @@ -707,3 +726,8 @@ void help_skill(cptr skill) { show_context_help(find_context_help(skill_table, skill)); } + +void help_ability(cptr ability) +{ + show_context_help(find_context_help(ability_table, ability)); +} diff --git a/src/skills.c b/src/skills.c index 2a0a4f18..aba838be 100644 --- a/src/skills.c +++ b/src/skills.c @@ -1611,8 +1611,10 @@ if (ab_info[i].name) if (wizard && (c == '-')) ab_info[table[sel]].acquired = FALSE; /* Contextual help */ - if (c == '?') exec_lua(format("ingame_help('select_context', 'ability', '%s')", ab_info[table[sel]].name + ab_name)); - ; + if (c == '?') + { + help_ability(ab_info[table[sel]].name + ab_name); + } /* Handle boundaries and scrolling */ if (sel < 0) sel = max - 1; -- cgit v1.2.3 From 45f32f85eecbdaca1108542adc9733e9b633d9e5 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 17:22:52 +0200 Subject: Lua: Remove dead help code --- lib/mods/theme/scpt/help.lua | 16 ---------------- lib/scpt/help.lua | 16 ---------------- 2 files changed, 32 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index 9d53ba40..6a153933 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -15,19 +15,3 @@ ingame_help "This can lead to quests. You can also give items to 'monsters' with the y key.", } } - -ingame_help -{ - ["no_test"] = TRUE, - ["callback"] = "select_context", - ["fct"] = function(typ, name) - -- list of files for classes, { filename, anchor } - local t = - { - } - - if t[typ][name] then ingame_help_doc(t[typ][name][1], t[typ][name][2]) - else ingame_help_doc("help.hlp", 0) - end - end, -} diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index 9d53ba40..6a153933 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -15,19 +15,3 @@ ingame_help "This can lead to quests. You can also give items to 'monsters' with the y key.", } } - -ingame_help -{ - ["no_test"] = TRUE, - ["callback"] = "select_context", - ["fct"] = function(typ, name) - -- list of files for classes, { filename, anchor } - local t = - { - } - - if t[typ][name] then ingame_help_doc(t[typ][name][1], t[typ][name][2]) - else ingame_help_doc("help.hlp", 0) - end - end, -} -- cgit v1.2.3 From 465063bdf50bdf30b110bb2c37ab114fb68e4662 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 17:56:15 +0200 Subject: Lua: Move the "monster asked for help" help to C --- lib/mods/theme/scpt/help.lua | 10 ---------- lib/scpt/help.lua | 10 ---------- src/defines.h | 1 + src/help.c | 15 ++++++++++++++- src/q_shroom.c | 2 +- 5 files changed, 16 insertions(+), 22 deletions(-) diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua index 6a153933..e17d1723 100644 --- a/lib/mods/theme/scpt/help.lua +++ b/lib/mods/theme/scpt/help.lua @@ -5,13 +5,3 @@ -----------------------Here comes the definition of help----------------------- ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- - -ingame_help -{ - ["callback"] = "monster_chat", - ["desc"] = - { - "Somebody is speaking to you it seems. You can talk back with the Y key.", - "This can lead to quests. You can also give items to 'monsters' with the y key.", - } -} diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua index 6a153933..e17d1723 100644 --- a/lib/scpt/help.lua +++ b/lib/scpt/help.lua @@ -5,13 +5,3 @@ -----------------------Here comes the definition of help----------------------- ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- - -ingame_help -{ - ["callback"] = "monster_chat", - ["desc"] = - { - "Somebody is speaking to you it seems. You can talk back with the Y key.", - "This can lead to quests. You can also give items to 'monsters' with the y key.", - } -} diff --git a/src/defines.h b/src/defines.h index 44537732..8a340a4c 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4513,6 +4513,7 @@ #define HOOK_APPLY_MAGIC 66 #define HOOK_PLAYER_EXP 67 #define HOOK_BIRTH 68 +#define HOOK_MON_ASK_HELP 69 #define HOOK_LEARN_ABILITY 70 #define HOOK_MOVED 71 #define HOOK_GAME_START 72 diff --git a/src/help.c b/src/help.c index a19b7b27..6d196060 100644 --- a/src/help.c +++ b/src/help.c @@ -14,7 +14,7 @@ #include "angband.h" #define DESC_MAX 14 -#define TRIGGERED_HELP_MAX 18 +#define TRIGGERED_HELP_MAX 19 #define HELP_VOID_JUMPGATE 0 #define HELP_FOUNTAIN 1 @@ -34,6 +34,7 @@ #define HELP_20TH_LEVEL 15 #define HELP_ID_SPELL_ITM 16 #define HELP_MELEE_SKILLS 17 +#define HELP_MON_ASK_HELP 18 /** * Game started? @@ -402,6 +403,10 @@ static bool_ trigger_melee_skills(void *in, void *out) { return (game_started && (get_melee_skills() > 1)); } +static bool_ trigger_always(void *in, void *out) { + return TRUE; +} + /** * Trigger-based help items */ @@ -584,6 +589,14 @@ static triggered_help_type triggered_help[TRIGGERED_HELP_MAX] = "and select the switch melee type option.", NULL } + }, + { HELP_MON_ASK_HELP, + HOOK_MON_ASK_HELP, + trigger_always, + { "Somebody is speaking to you it seems. You can talk back with the Y key.", + "This can lead to quests. You can also give items to 'monsters' with the y key.", + NULL + } } }; diff --git a/src/q_shroom.c b/src/q_shroom.c index b6e26cdf..4d4d7494 100644 --- a/src/q_shroom.c +++ b/src/q_shroom.c @@ -196,7 +196,7 @@ bool_ quest_shroom_speak_hook(char *fmt) m_name = get_next_arg_str(fmt); msg_format("%^s asks your help.", m_name); - exec_lua("ingame_help('monster_chat')"); + process_hooks_new(HOOK_MON_ASK_HELP, NULL, NULL); } else { -- cgit v1.2.3 From 4d77bc8053e1fda66f1e3f805f0a2cb74fba6201 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 17:59:12 +0200 Subject: Lua: Remove Lua help code --- lib/core/help.lua | 141 ------------------------------------------- lib/core/init.lua | 3 - lib/mods/theme/core/help.lua | 141 ------------------------------------------- lib/mods/theme/core/init.lua | 3 - lib/mods/theme/scpt/help.lua | 7 --- lib/mods/theme/scpt/init.lua | 3 - lib/scpt/help.lua | 7 --- lib/scpt/init.lua | 3 - src/util.pkg | 6 -- 9 files changed, 314 deletions(-) delete mode 100644 lib/core/help.lua delete mode 100644 lib/mods/theme/core/help.lua delete mode 100644 lib/mods/theme/scpt/help.lua delete mode 100644 lib/scpt/help.lua diff --git a/lib/core/help.lua b/lib/core/help.lua deleted file mode 100644 index a581fe63..00000000 --- a/lib/core/help.lua +++ /dev/null @@ -1,141 +0,0 @@ --- Ingame contextual help - --- We use our own hook list as to not overburn the hook proccessor --- with many hooks that would slow down things --- It would be very meaningless if the option is not even on -__ingame_hooks = {} - -__ingame_help_max = 0 - -function ingame_help(t, ...) - -- This function can also be used to call the callbacks - if type(t) == "string" then - local f = getglobal("__ingame_help_fct_"..t) - call(f, arg) - return - end - - assert(t.desc or t.fct, "no ingame help desc/fct") - assert(t.hook or t.callback, "no ingame help hook/callback") - if t.hook then assert(t.event, "no ingame hepl event needed by hook") end - - -- Set it to only trigger once - setglobal("__ingame_help_activated_"..__ingame_help_max, FALSE) - -- Save/load it - add_loadsave("__ingame_help_activated_"..__ingame_help_max, FALSE) - - if t.hook then - -- If the hok list didnt exist yet, add it - if not __ingame_hooks[t.hook] then - -- Set it to empty, we'll fill it later - __ingame_hooks[t.hook] = {} - -- Add the global hook - add_hooks - { - [t.hook] = function (...) - if option_ingame_help ~= TRUE then return end - local k, e - for k, e in __ingame_hooks[%t.hook] do - if k ~= "n" then - call(e, arg) - end - end - end - } - end - if t.desc then - tinsert(__ingame_hooks[t.hook], - function (...) - local tbl = %t - if getglobal("__ingame_help_activated_"..%__ingame_help_max) == FALSE then - if call(tbl.event, arg) == TRUE then - local k, e - for k, e in tbl.desc do - msg_print(TERM_YELLOW, e) - end - setglobal("__ingame_help_activated_"..%__ingame_help_max, TRUE) - end - end - end - ) - elseif t.fct then - tinsert(__ingame_hooks[t.hook], - function (...) - local tbl = %t - if getglobal("__ingame_help_activated_"..%__ingame_help_max) == FALSE then - if call(tbl.event, arg) == TRUE then - if tbl.fct() == TRUE then - setglobal("__ingame_help_activated_"..%__ingame_help_max, TRUE) - end - end - end - end - ) - end - else - local no_test = FALSE - if t.no_test == TRUE then no_test = TRUE end - if t.desc then - setglobal - ( - "__ingame_help_fct_"..(t.callback), - function (...) - local tbl = %t - if ((option_ingame_help == TRUE) or (%no_test == TRUE)) and (getglobal("__ingame_help_activated_"..%__ingame_help_max) == FALSE) then - local k, e - for k, e in tbl.desc do - msg_print(TERM_YELLOW, e) - end - setglobal("__ingame_help_activated_"..%__ingame_help_max, TRUE) - end - end - ) - elseif t.fct then - setglobal - ( - "__ingame_help_fct_"..(t.callback), - function (...) - local tbl = %t - if ((option_ingame_help == TRUE) or (%no_test == TRUE)) and (getglobal("__ingame_help_activated_"..%__ingame_help_max) == FALSE) then - if call(tbl.fct, arg) == TRUE then - setglobal("__ingame_help_activated_"..%__ingame_help_max, TRUE) - end - end - end - ) - end - end - - __ingame_help_max = __ingame_help_max + 1 -end - --- Clean up the ingame help seen at birth -add_hooks -{ - [HOOK_BIRTH_OBJECTS] = function() - local i - for i = 0, __ingame_help_max - 1 do - setglobal("__ingame_help_activated_"..i, FALSE) - end - end -} - -function ingame_clean() - local i - for i = 0, __ingame_help_max - 1 do - setglobal("__ingame_help_activated_"..i, FALSE) - end -end - --- helper function, brings up a doc -function ingame_help_doc(name, anchor) - -- Save screen - screen_save(); - - -- Peruse the help file - if not anchor then anchor = 0 end - show_file(name, 0, -anchor, 0) - - -- Load screen - screen_load() -end diff --git a/lib/core/init.lua b/lib/core/init.lua index c87f9a20..5abc1571 100644 --- a/lib/core/init.lua +++ b/lib/core/init.lua @@ -17,9 +17,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "building.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") --- Load the ingame contextual help -tome_dofile_anywhere(ANGBAND_DIR_CORE, "help.lua") - -------------------------------------------------------------- -------------------------------------------------------------- -------------------------------------------------------------- diff --git a/lib/mods/theme/core/help.lua b/lib/mods/theme/core/help.lua deleted file mode 100644 index a581fe63..00000000 --- a/lib/mods/theme/core/help.lua +++ /dev/null @@ -1,141 +0,0 @@ --- Ingame contextual help - --- We use our own hook list as to not overburn the hook proccessor --- with many hooks that would slow down things --- It would be very meaningless if the option is not even on -__ingame_hooks = {} - -__ingame_help_max = 0 - -function ingame_help(t, ...) - -- This function can also be used to call the callbacks - if type(t) == "string" then - local f = getglobal("__ingame_help_fct_"..t) - call(f, arg) - return - end - - assert(t.desc or t.fct, "no ingame help desc/fct") - assert(t.hook or t.callback, "no ingame help hook/callback") - if t.hook then assert(t.event, "no ingame hepl event needed by hook") end - - -- Set it to only trigger once - setglobal("__ingame_help_activated_"..__ingame_help_max, FALSE) - -- Save/load it - add_loadsave("__ingame_help_activated_"..__ingame_help_max, FALSE) - - if t.hook then - -- If the hok list didnt exist yet, add it - if not __ingame_hooks[t.hook] then - -- Set it to empty, we'll fill it later - __ingame_hooks[t.hook] = {} - -- Add the global hook - add_hooks - { - [t.hook] = function (...) - if option_ingame_help ~= TRUE then return end - local k, e - for k, e in __ingame_hooks[%t.hook] do - if k ~= "n" then - call(e, arg) - end - end - end - } - end - if t.desc then - tinsert(__ingame_hooks[t.hook], - function (...) - local tbl = %t - if getglobal("__ingame_help_activated_"..%__ingame_help_max) == FALSE then - if call(tbl.event, arg) == TRUE then - local k, e - for k, e in tbl.desc do - msg_print(TERM_YELLOW, e) - end - setglobal("__ingame_help_activated_"..%__ingame_help_max, TRUE) - end - end - end - ) - elseif t.fct then - tinsert(__ingame_hooks[t.hook], - function (...) - local tbl = %t - if getglobal("__ingame_help_activated_"..%__ingame_help_max) == FALSE then - if call(tbl.event, arg) == TRUE then - if tbl.fct() == TRUE then - setglobal("__ingame_help_activated_"..%__ingame_help_max, TRUE) - end - end - end - end - ) - end - else - local no_test = FALSE - if t.no_test == TRUE then no_test = TRUE end - if t.desc then - setglobal - ( - "__ingame_help_fct_"..(t.callback), - function (...) - local tbl = %t - if ((option_ingame_help == TRUE) or (%no_test == TRUE)) and (getglobal("__ingame_help_activated_"..%__ingame_help_max) == FALSE) then - local k, e - for k, e in tbl.desc do - msg_print(TERM_YELLOW, e) - end - setglobal("__ingame_help_activated_"..%__ingame_help_max, TRUE) - end - end - ) - elseif t.fct then - setglobal - ( - "__ingame_help_fct_"..(t.callback), - function (...) - local tbl = %t - if ((option_ingame_help == TRUE) or (%no_test == TRUE)) and (getglobal("__ingame_help_activated_"..%__ingame_help_max) == FALSE) then - if call(tbl.fct, arg) == TRUE then - setglobal("__ingame_help_activated_"..%__ingame_help_max, TRUE) - end - end - end - ) - end - end - - __ingame_help_max = __ingame_help_max + 1 -end - --- Clean up the ingame help seen at birth -add_hooks -{ - [HOOK_BIRTH_OBJECTS] = function() - local i - for i = 0, __ingame_help_max - 1 do - setglobal("__ingame_help_activated_"..i, FALSE) - end - end -} - -function ingame_clean() - local i - for i = 0, __ingame_help_max - 1 do - setglobal("__ingame_help_activated_"..i, FALSE) - end -end - --- helper function, brings up a doc -function ingame_help_doc(name, anchor) - -- Save screen - screen_save(); - - -- Peruse the help file - if not anchor then anchor = 0 end - show_file(name, 0, -anchor, 0) - - -- Load screen - screen_load() -end diff --git a/lib/mods/theme/core/init.lua b/lib/mods/theme/core/init.lua index c87f9a20..5abc1571 100644 --- a/lib/mods/theme/core/init.lua +++ b/lib/mods/theme/core/init.lua @@ -17,9 +17,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "building.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") --- Load the ingame contextual help -tome_dofile_anywhere(ANGBAND_DIR_CORE, "help.lua") - -------------------------------------------------------------- -------------------------------------------------------------- -------------------------------------------------------------- diff --git a/lib/mods/theme/scpt/help.lua b/lib/mods/theme/scpt/help.lua deleted file mode 100644 index e17d1723..00000000 --- a/lib/mods/theme/scpt/help.lua +++ /dev/null @@ -1,7 +0,0 @@ --- Ingame contextual help - -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- ------------------------Here comes the definition of help----------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index 64b1c6a5..85099e19 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -5,9 +5,6 @@ -- Load the class specific stuff tome_dofile("player.lua") --- Load the ingame contextual help -tome_dofile("help.lua") - -- Add the mkey activations tome_dofile("mkeys.lua") diff --git a/lib/scpt/help.lua b/lib/scpt/help.lua deleted file mode 100644 index e17d1723..00000000 --- a/lib/scpt/help.lua +++ /dev/null @@ -1,7 +0,0 @@ --- Ingame contextual help - -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- ------------------------Here comes the definition of help----------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- diff --git a/lib/scpt/init.lua b/lib/scpt/init.lua index 079d064d..3be0887c 100644 --- a/lib/scpt/init.lua +++ b/lib/scpt/init.lua @@ -5,9 +5,6 @@ -- Load the class specific stuff tome_dofile("player.lua") --- Load the ingame contextual help -tome_dofile("help.lua") - -- Add the mkey activations tome_dofile("mkeys.lua") diff --git a/src/util.pkg b/src/util.pkg index cb49a3e3..4e3b6117 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -2120,12 +2120,6 @@ extern void load_map(char *name, int *y = 2, int *x = 2); */ extern bool alloc_room(int by0, int bx0, int ysize, int xsize, int *y1 = 0, int *x1 = 0, int *y2 = 0, int *x2 = 0); -/** @var option_ingame_help - * @brief Boolean - * @note Ingame contextual help flag - */ -extern bool option_ingame_help; - /* Misc stuff */ /** @fn input_box(cptr title, int max); * @brief Create an input box and ask the user a question.\n -- cgit v1.2.3 From 24778733a4fd919a7646750ebb0211dca689b245 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 18:45:33 +0200 Subject: Lua: Move "Death Touch" ability to C --- lib/mods/theme/scpt/mkeys.lua | 16 ---------------- lib/scpt/mkeys.lua | 16 ---------------- src/defines.h | 1 + src/skills.c | 18 ++++++++++++++++++ 4 files changed, 19 insertions(+), 32 deletions(-) diff --git a/lib/mods/theme/scpt/mkeys.lua b/lib/mods/theme/scpt/mkeys.lua index ae8ad2b1..8bdc83bc 100644 --- a/lib/mods/theme/scpt/mkeys.lua +++ b/lib/mods/theme/scpt/mkeys.lua @@ -1,21 +1,5 @@ -- Mkeys for skills & abilities --- Death touch ability -add_mkey -{ - ["mkey"] = 100, - ["fct"] = function() - if player.csp > 40 then - increase_mana(-40) - set_project(randint(30) + 10, GF_INSTA_DEATH, 1, 0, bor(PROJECT_STOP, PROJECT_KILL)) - energy_use = 100 - else - msg_print("You need at least 40 mana.") - end - end, -} - - -- Geomancy skill add_mkey { diff --git a/lib/scpt/mkeys.lua b/lib/scpt/mkeys.lua index ae8ad2b1..8bdc83bc 100644 --- a/lib/scpt/mkeys.lua +++ b/lib/scpt/mkeys.lua @@ -1,21 +1,5 @@ -- Mkeys for skills & abilities --- Death touch ability -add_mkey -{ - ["mkey"] = 100, - ["fct"] = function() - if player.csp > 40 then - increase_mana(-40) - set_project(randint(30) + 10, GF_INSTA_DEATH, 1, 0, bor(PROJECT_STOP, PROJECT_KILL)) - energy_use = 100 - else - msg_print("You need at least 40 mana.") - end - end, -} - - -- Geomancy skill add_mkey { diff --git a/src/defines.h b/src/defines.h index 8a340a4c..fe689725 100644 --- a/src/defines.h +++ b/src/defines.h @@ -609,6 +609,7 @@ #define MKEY_BOULDER 21 #define MKEY_COMPANION 22 #define MKEY_PIERCING 23 +#define MKEY_DEATH_TOUCH 100 /*** Screen Locations ***/ diff --git a/src/skills.c b/src/skills.c index aba838be..fd6c37a2 100644 --- a/src/skills.c +++ b/src/skills.c @@ -1056,6 +1056,24 @@ void do_cmd_activate_skill() case MKEY_PIERCING: do_cmd_set_piercing(); break; + case MKEY_DEATH_TOUCH: + { + if (p_ptr->csp > 40) + { + increase_mana(-40); + set_project(randint(30) + 10, + GF_INSTA_DEATH, + 1, + 0, + PROJECT_STOP | PROJECT_KILL); + energy_use = 100; + } + else + { + msg_print("You need at least 40 mana."); + } + break; + } default: process_hooks(HOOK_MKEY, "(d)", x_idx); break; -- cgit v1.2.3 From ca63c6bf6fa6d72b93b53cc48d06cc69b3bebe9e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 19:26:34 +0200 Subject: Lua: Move "Geomancy" ability to C --- lib/mods/theme/scpt/mkeys.lua | 28 ---------------------------- lib/scpt/mkeys.lua | 28 ---------------------------- src/defines.h | 1 + src/skills.c | 28 ++++++++++++++++++++++++++++ 4 files changed, 29 insertions(+), 56 deletions(-) diff --git a/lib/mods/theme/scpt/mkeys.lua b/lib/mods/theme/scpt/mkeys.lua index 8bdc83bc..82fe4ede 100644 --- a/lib/mods/theme/scpt/mkeys.lua +++ b/lib/mods/theme/scpt/mkeys.lua @@ -1,33 +1,5 @@ -- Mkeys for skills & abilities --- Geomancy skill -add_mkey -{ - ["mkey"] = 101, - ["fct"] = function() - local s - - -- No magic - if (player.antimagic > 0) then - msg_print("Your anti-magic field disrupts any magic attempts.") - return - end - - local obj = get_object(INVEN_WIELD) - if (obj.k_idx <= 0) or (obj.tval ~= TV_MSTAFF) then - msg_print('You must wield a magestaff to use Geomancy.') - return - end - - s = get_school_spell("cast", 62); - - -- Actualy cast the choice - if (s ~= -1) then - cast_school_spell(s) - end - end, -} - -- Far reaching attack of polearms add_mkey { diff --git a/lib/scpt/mkeys.lua b/lib/scpt/mkeys.lua index 8bdc83bc..82fe4ede 100644 --- a/lib/scpt/mkeys.lua +++ b/lib/scpt/mkeys.lua @@ -1,33 +1,5 @@ -- Mkeys for skills & abilities --- Geomancy skill -add_mkey -{ - ["mkey"] = 101, - ["fct"] = function() - local s - - -- No magic - if (player.antimagic > 0) then - msg_print("Your anti-magic field disrupts any magic attempts.") - return - end - - local obj = get_object(INVEN_WIELD) - if (obj.k_idx <= 0) or (obj.tval ~= TV_MSTAFF) then - msg_print('You must wield a magestaff to use Geomancy.') - return - end - - s = get_school_spell("cast", 62); - - -- Actualy cast the choice - if (s ~= -1) then - cast_school_spell(s) - end - end, -} - -- Far reaching attack of polearms add_mkey { diff --git a/src/defines.h b/src/defines.h index fe689725..c1dafdf4 100644 --- a/src/defines.h +++ b/src/defines.h @@ -610,6 +610,7 @@ #define MKEY_COMPANION 22 #define MKEY_PIERCING 23 #define MKEY_DEATH_TOUCH 100 +#define MKEY_GEOMANCY 101 /*** Screen Locations ***/ diff --git a/src/skills.c b/src/skills.c index fd6c37a2..1dc65fea 100644 --- a/src/skills.c +++ b/src/skills.c @@ -1074,6 +1074,34 @@ void do_cmd_activate_skill() } break; } + case MKEY_GEOMANCY: + { + s32b s = -1; + object_type *o_ptr = NULL; + + /* No magic */ + if (p_ptr->antimagic > 0) + { + msg_print("Your anti-magic field disrupts any magic attempts."); + break; + } + + o_ptr = get_object(INVEN_WIELD); + if ((o_ptr->k_idx <= 0) || + (o_ptr->tval != TV_MSTAFF)) + { + msg_print("You must wield a magestaff to use Geomancy."); + break; + } + + s = get_school_spell("cast", BOOK_GEOMANCY); + if (s >= 0) + { + lua_cast_school_spell(s, FALSE); + } + + break; + } default: process_hooks(HOOK_MKEY, "(d)", x_idx); break; -- cgit v1.2.3 From d69d91b33a2e833e8b32baa29af22809ade406ba Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 19:47:10 +0200 Subject: Lua: Move "Far Reaching Attack" ability to C --- lib/core/player.lua | 26 ------------------------- lib/mods/theme/core/player.lua | 26 ------------------------- lib/mods/theme/scpt/init.lua | 3 --- lib/mods/theme/scpt/mkeys.lua | 35 --------------------------------- lib/scpt/init.lua | 3 --- lib/scpt/mkeys.lua | 35 --------------------------------- src/defines.h | 2 +- src/skills.c | 44 +++++++++++++++++++++++++++++++++++++++++- src/util.pkg | 8 -------- 9 files changed, 44 insertions(+), 138 deletions(-) delete mode 100644 lib/mods/theme/scpt/mkeys.lua delete mode 100644 lib/scpt/mkeys.lua diff --git a/lib/core/player.lua b/lib/core/player.lua index cb1b5cab..f5c7c13b 100644 --- a/lib/core/player.lua +++ b/lib/core/player.lua @@ -56,32 +56,6 @@ function player.get_wild_coord() end ---- Mkeys - --- Create a new power -__mkey_fct = {} -function add_mkey(p) - local i - - assert(p.mkey, "No mkey mkey!") - assert(p.fct, "No mkeey fct!") - - __mkey_fct[p.mkey] = p.fct -end - -function __mkey_fct_activate(power) - if __mkey_fct[power] then - __mkey_fct[power]() - return TRUE - else - return FALSE - end -end - --- Register in the hook list -add_hook_script(HOOK_MKEY, "__mkey_fct_activate", "__mkey_fct_activate") - - -- Subraces function subrace(racem) return race_mod_info[racem + 1] diff --git a/lib/mods/theme/core/player.lua b/lib/mods/theme/core/player.lua index cb1b5cab..f5c7c13b 100644 --- a/lib/mods/theme/core/player.lua +++ b/lib/mods/theme/core/player.lua @@ -56,32 +56,6 @@ function player.get_wild_coord() end ---- Mkeys - --- Create a new power -__mkey_fct = {} -function add_mkey(p) - local i - - assert(p.mkey, "No mkey mkey!") - assert(p.fct, "No mkeey fct!") - - __mkey_fct[p.mkey] = p.fct -end - -function __mkey_fct_activate(power) - if __mkey_fct[power] then - __mkey_fct[power]() - return TRUE - else - return FALSE - end -end - --- Register in the hook list -add_hook_script(HOOK_MKEY, "__mkey_fct_activate", "__mkey_fct_activate") - - -- Subraces function subrace(racem) return race_mod_info[racem + 1] diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index 85099e19..0d59bfd2 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -5,9 +5,6 @@ -- Load the class specific stuff tome_dofile("player.lua") --- Add the mkey activations -tome_dofile("mkeys.lua") - -- Add the schools of magic schools_init() school_spells_init() diff --git a/lib/mods/theme/scpt/mkeys.lua b/lib/mods/theme/scpt/mkeys.lua deleted file mode 100644 index 82fe4ede..00000000 --- a/lib/mods/theme/scpt/mkeys.lua +++ /dev/null @@ -1,35 +0,0 @@ --- Mkeys for skills & abilities - --- Far reaching attack of polearms -add_mkey -{ - ["mkey"] = 102, - ["fct"] = function() - local weapon = get_object(INVEN_WIELD); - if weapon.tval == TV_POLEARM then - else - msg_print("You will need a long polearm for this!") - return - end - - ret, dir = get_rep_dir() - if ret == FALSE then return end - - local dy, dx = explode_dir(dir) - dy = dy * 2 - dx = dx * 2 - targety = player.py + dy - targetx = player.px + dx - - local max_blows = get_skill_scale(SKILL_POLEARM, player.num_blow / 2) - if max_blows == 0 then max_blows = 1 end - - if get_skill(SKILL_POLEARM) >= 40 then - energy_use = energy_use + 200 - return project(0, 0, targety, targetx, max_blows, GF_ATTACK, bor(PROJECT_BEAM, PROJECT_KILL)) - else - energy_use = energy_use + 200 - return project(0, 0, targety, targetx, max_blows, GF_ATTACK, bor(PROJECT_BEAM, PROJECT_STOP, PROJECT_KILL)) - end - end, -} diff --git a/lib/scpt/init.lua b/lib/scpt/init.lua index 3be0887c..b3c73304 100644 --- a/lib/scpt/init.lua +++ b/lib/scpt/init.lua @@ -5,9 +5,6 @@ -- Load the class specific stuff tome_dofile("player.lua") --- Add the mkey activations -tome_dofile("mkeys.lua") - -- Add the schools of magic schools_init() school_spells_init() diff --git a/lib/scpt/mkeys.lua b/lib/scpt/mkeys.lua deleted file mode 100644 index 82fe4ede..00000000 --- a/lib/scpt/mkeys.lua +++ /dev/null @@ -1,35 +0,0 @@ --- Mkeys for skills & abilities - --- Far reaching attack of polearms -add_mkey -{ - ["mkey"] = 102, - ["fct"] = function() - local weapon = get_object(INVEN_WIELD); - if weapon.tval == TV_POLEARM then - else - msg_print("You will need a long polearm for this!") - return - end - - ret, dir = get_rep_dir() - if ret == FALSE then return end - - local dy, dx = explode_dir(dir) - dy = dy * 2 - dx = dx * 2 - targety = player.py + dy - targetx = player.px + dx - - local max_blows = get_skill_scale(SKILL_POLEARM, player.num_blow / 2) - if max_blows == 0 then max_blows = 1 end - - if get_skill(SKILL_POLEARM) >= 40 then - energy_use = energy_use + 200 - return project(0, 0, targety, targetx, max_blows, GF_ATTACK, bor(PROJECT_BEAM, PROJECT_KILL)) - else - energy_use = energy_use + 200 - return project(0, 0, targety, targetx, max_blows, GF_ATTACK, bor(PROJECT_BEAM, PROJECT_STOP, PROJECT_KILL)) - end - end, -} diff --git a/src/defines.h b/src/defines.h index c1dafdf4..2907d2a2 100644 --- a/src/defines.h +++ b/src/defines.h @@ -611,6 +611,7 @@ #define MKEY_PIERCING 23 #define MKEY_DEATH_TOUCH 100 #define MKEY_GEOMANCY 101 +#define MKEY_REACH_ATTACK 102 /*** Screen Locations ***/ @@ -4486,7 +4487,6 @@ #define HOOK_KEYPRESS 31 #define HOOK_CHAT 32 #define HOOK_MON_SPEAK 33 -#define HOOK_MKEY 34 #define HOOK_BIRTH_OBJECTS 35 #define HOOK_ACTIVATE_DESC 36 #define HOOK_INIT_GAME 37 diff --git a/src/skills.c b/src/skills.c index 1dc65fea..4de0b047 100644 --- a/src/skills.c +++ b/src/skills.c @@ -1102,8 +1102,50 @@ void do_cmd_activate_skill() break; } + case MKEY_REACH_ATTACK: + { + object_type *o_ptr = NULL; + int dir, dy, dx, targetx, targety, max_blows, flags; + + o_ptr = get_object(INVEN_WIELD); + if (o_ptr->tval == TV_POLEARM) + { + msg_print("You will need a long polearm for this!"); + return; + } + + if (!get_rep_dir(&dir)) + { + return; + } + + dy = ddy[dir]; + dx = ddx[dir]; + dy = dy * 2; + dx = dx * 2; + targety = p_ptr->py + dy; + targetx = p_ptr->px + dx; + + max_blows = get_skill_scale(SKILL_POLEARM, p_ptr->num_blow / 2); + if (max_blows == 0) + { + max_blows = 1; + } + + energy_use = energy_use + 200; + + flags = PROJECT_BEAM | PROJECT_KILL; + if (get_skill(SKILL_POLEARM) < 40) + { + flags |= PROJECT_STOP; + } + + project(0, 0, targety, targetx, + max_blows, GF_ATTACK, flags); + + break; + } default: - process_hooks(HOOK_MKEY, "(d)", x_idx); break; } } diff --git a/src/util.pkg b/src/util.pkg index 4e3b6117..33f60a59 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -426,14 +426,6 @@ typedef unsigned int u32b; */ #define HOOK_MON_SPEAK 33 -/** @def HOOK_MKEY - * @brief Player uses skill.\n - * @param Number x_idx \n the skill to execute. - * @brief Skill index - * @note (see file skills.c) - */ -#define HOOK_MKEY 34 - /** @def HOOK_BIRTH_OBJECTS * @brief Player receives objects at birth. * @note (see file birth.c) -- cgit v1.2.3 From a0107d942872735f1faa0e857174a6c467180d75 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 20:54:07 +0200 Subject: Lua: Move automatic stat gain to C --- lib/mods/theme/scpt/misc.lua | 30 ------------------------------ src/birth.c | 3 +++ src/dungeon.c | 1 + src/externs.h | 1 + src/loadsave.c | 1 + src/modules.c | 41 +++++++++++++++++++++++++++++++++++++++++ src/types.h | 3 +++ 7 files changed, 50 insertions(+), 30 deletions(-) diff --git a/lib/mods/theme/scpt/misc.lua b/lib/mods/theme/scpt/misc.lua index a41f9288..726574d2 100644 --- a/lib/mods/theme/scpt/misc.lua +++ b/lib/mods/theme/scpt/misc.lua @@ -1,33 +1,3 @@ --- Neil's automagic statgain script - -player.last_rewarded_level = 1 -add_loadsave("player.last_rewarded_level", 1) - -add_hooks - { - [HOOK_PLAYER_LEVEL] = function() - while player.last_rewarded_level * 5 <= player.lev do - do_inc_stat(A_STR) - do_inc_stat(A_INT) - do_inc_stat(A_WIS) - do_inc_stat(A_DEX) - do_inc_stat(A_CON) - do_inc_stat(A_CHR) - player.last_rewarded_level = player.last_rewarded_level + 1 - end - end, - } - -add_hooks -{ - [HOOK_BIRTH_OBJECTS] = function() - if player.last_rewarded_level >= 1 - then player.last_rewarded_level = 1 - else - end - end -} - -- silly function that allows a drunk to take a bottle of wine/ale from the player function drunk_takes_wine(m_idx, item) diff --git a/src/birth.c b/src/birth.c index 14c0b44f..41abe3ad 100644 --- a/src/birth.c +++ b/src/birth.c @@ -1041,6 +1041,9 @@ static void player_wipe(void) /* Inertia control */ p_ptr->inertia_controlled_spell = -1; + + /* Automatic stat-gain */ + p_ptr->last_rewarded_level = 1; } diff --git a/src/dungeon.c b/src/dungeon.c index f4803e3b..af46976d 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -5631,6 +5631,7 @@ void play_game(bool_ new_game) /* Initialize hooks */ init_hooks(); init_hooks_help(); + init_hooks_module(); /* React to changes */ Term_xtra(TERM_XTRA_REACT, 0); diff --git a/src/externs.h b/src/externs.h index e1f77bc1..38511e48 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2362,6 +2362,7 @@ extern bool_ select_module(void); extern bool_ module_savefile_loadable(cptr savefile_mod); extern void tome_intro(); extern void theme_intro(); +extern void init_hooks_module(); /* lua_bind.c */ diff --git a/src/loadsave.c b/src/loadsave.c index 349db36d..65d72d9c 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -580,6 +580,7 @@ static bool_ do_extra(int flag) do_s32b(&p_ptr->loan_time, flag); do_s16b(&p_ptr->absorb_soul, flag); do_s32b(&p_ptr->inertia_controlled_spell, flag); + do_s16b(&p_ptr->last_rewarded_level, flag); do_s16b(&p_ptr->chaos_patron, flag); diff --git a/src/modules.c b/src/modules.c index 8a4c5644..ff8a24fb 100644 --- a/src/modules.c +++ b/src/modules.c @@ -495,3 +495,44 @@ void theme_intro() exit: screen_load(); } + +static bool_ auto_stat_gain_hook(void *data, void *in, void *out) +{ + while (p_ptr->last_rewarded_level * 5 <= p_ptr->lev) + { + do_inc_stat(A_STR); + do_inc_stat(A_INT); + do_inc_stat(A_WIS); + do_inc_stat(A_DEX); + do_inc_stat(A_CON); + do_inc_stat(A_CHR); + + p_ptr->last_rewarded_level += 1; + } + + return FALSE; +} + +void init_hooks_module() +{ + switch (game_module_idx) + { + case MODULE_TOME: + { + break; + } + + case MODULE_THEME: + { + add_hook_new(HOOK_PLAYER_LEVEL, + auto_stat_gain_hook, + "auto_stat_gain", + NULL); + + break; + } + + default: + assert(FALSE); + } +} diff --git a/src/types.h b/src/types.h index 3e634beb..44ffd67a 100644 --- a/src/types.h +++ b/src/types.h @@ -1863,6 +1863,9 @@ struct player_type /* Inertia control */ s32b inertia_controlled_spell; + /* For automatic stat-gain */ + s16b last_rewarded_level; + /*** Temporary fields ***/ bool_ did_nothing; /* True if the last action wasnt a real action */ -- cgit v1.2.3 From abd9ab4c46bab7ccd3475a31b542873130682b81 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 21:34:30 +0200 Subject: Lua: Move "Drunk takes wine" code to C --- lib/mods/theme/scpt/drunk.lua | 21 --------------------- lib/mods/theme/scpt/init.lua | 1 - lib/mods/theme/scpt/misc.lua | 26 -------------------------- lib/scpt/drunk.lua | 21 --------------------- lib/scpt/init.lua | 1 - src/cmd2.c | 6 +++++- src/modules.c | 41 +++++++++++++++++++++++++++++++++++++++++ src/types.h | 6 ++++++ 8 files changed, 52 insertions(+), 71 deletions(-) delete mode 100644 lib/mods/theme/scpt/drunk.lua delete mode 100644 lib/scpt/drunk.lua diff --git a/lib/mods/theme/scpt/drunk.lua b/lib/mods/theme/scpt/drunk.lua deleted file mode 100644 index 7d90af8d..00000000 --- a/lib/mods/theme/scpt/drunk.lua +++ /dev/null @@ -1,21 +0,0 @@ --- silly function that allows a drunk to take a bottle of wine/ale from the player - -function drunk_takes_wine(m_idx, item) - - m_ptr = monster(m_idx) - o_ptr = get_object(item) - - if (m_ptr.r_idx == test_monster_name("Singing, happy drunk")) - and (o_ptr.tval == TV_FOOD) and ((o_ptr.sval == 38) or (o_ptr.sval == 39)) then - - cmsg_print(TERM_YELLOW, "'Hic!'") - - inven_item_increase(item, -1) - inven_item_optimize(item) - return TRUE - else - return FALSE - end -end - -add_hook_script(HOOK_GIVE, "drunk_takes_wine", "drunk_takes_wine") diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index 0d59bfd2..8cd2094a 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -14,7 +14,6 @@ init_school_books() initialize_bookable_spells() -- Add joke stuff -tome_dofile("drunk.lua") tome_dofile("joke.lua") -- Some tests, if the file is not present, this is fine diff --git a/lib/mods/theme/scpt/misc.lua b/lib/mods/theme/scpt/misc.lua index 726574d2..21a81f83 100644 --- a/lib/mods/theme/scpt/misc.lua +++ b/lib/mods/theme/scpt/misc.lua @@ -1,29 +1,3 @@ --- silly function that allows a drunk to take a bottle of wine/ale from the player - -function drunk_takes_wine(m_idx, item) - - m_ptr = monster(m_idx) - o_ptr = get_object(item) - - if (m_ptr.r_idx == test_monster_name("Singing, happy drunk")) - and (o_ptr.tval == TV_FOOD) and ((o_ptr.sval == 38) or (o_ptr.sval == 39)) then - - cmsg_print(TERM_YELLOW, "'Hic!'") - - inven_item_increase(item, -1) - inven_item_optimize(item) - --- HackSmurf: the drunk may drop an empty bottle - bottle = create_object(TV_BOTTLE,1) - drop_near(bottle, 50, player.py, player.px) - return TRUE - else - return FALSE - end -end - -add_hook_script(HOOK_GIVE, "drunk_takes_wine", "drunk_takes_wine") - -- A not-too-scummy way of generating junk for ammo function food_vessel(object) if ((object.tval == 80) and (object.sval == 43)) or diff --git a/lib/scpt/drunk.lua b/lib/scpt/drunk.lua deleted file mode 100644 index 7d90af8d..00000000 --- a/lib/scpt/drunk.lua +++ /dev/null @@ -1,21 +0,0 @@ --- silly function that allows a drunk to take a bottle of wine/ale from the player - -function drunk_takes_wine(m_idx, item) - - m_ptr = monster(m_idx) - o_ptr = get_object(item) - - if (m_ptr.r_idx == test_monster_name("Singing, happy drunk")) - and (o_ptr.tval == TV_FOOD) and ((o_ptr.sval == 38) or (o_ptr.sval == 39)) then - - cmsg_print(TERM_YELLOW, "'Hic!'") - - inven_item_increase(item, -1) - inven_item_optimize(item) - return TRUE - else - return FALSE - end -end - -add_hook_script(HOOK_GIVE, "drunk_takes_wine", "drunk_takes_wine") diff --git a/lib/scpt/init.lua b/lib/scpt/init.lua index b3c73304..d27ce23c 100644 --- a/lib/scpt/init.lua +++ b/lib/scpt/init.lua @@ -14,7 +14,6 @@ init_school_books() initialize_bookable_spells() -- Add joke stuff -tome_dofile("drunk.lua") tome_dofile("joke.lua") -- Some tests, if the file is not present, this is fine diff --git a/src/cmd2.c b/src/cmd2.c index a2dcfa0a..7689f46a 100644 --- a/src/cmd2.c +++ b/src/cmd2.c @@ -5103,7 +5103,11 @@ void do_cmd_give() /* Process hooks if there are any */ if (!process_hooks(HOOK_GIVE, "(d,d)", c_ptr->m_idx, item)) { - msg_print("The monster does not want your item."); + hook_give_in in = { c_ptr->m_idx, item }; + if (!process_hooks_new(HOOK_GIVE, &in, NULL)) + { + msg_print("The monster does not want your item."); + } } /* Take a turn, even if the offer is declined */ diff --git a/src/modules.c b/src/modules.c index ff8a24fb..bd2a1acb 100644 --- a/src/modules.c +++ b/src/modules.c @@ -513,8 +513,49 @@ static bool_ auto_stat_gain_hook(void *data, void *in, void *out) return FALSE; } +static bool_ drunk_takes_wine(void *data, void *in_, void *out) +{ + hook_give_in *in = (hook_give_in *) in_; + monster_type *m_ptr = &m_list[in->m_idx]; + object_type *o_ptr = get_object(in->item); + + if ((m_ptr->r_idx == test_monster_name("Singing, happy drunk")) && + (o_ptr->tval == TV_FOOD) && + ((o_ptr->sval == 38) || + (o_ptr->sval == 39))) + { + cmsg_print(TERM_YELLOW, "'Hic!'"); + + /* Destroy item */ + inc_stack_size_ex(in->item, -1, OPTIMIZE, NO_DESCRIBE); + + /* Create empty bottle */ + { + object_type forge; + object_prep(&forge, lookup_kind(TV_BOTTLE,1)); + drop_near(&forge, 50, p_ptr->py, p_ptr->px); + return TRUE; + } + } + else + { + return FALSE; + } +} + void init_hooks_module() { + /* + * Common hooks + */ + add_hook_new(HOOK_GIVE, + drunk_takes_wine, + "drunk_takes_wine", + NULL); + + /* + * Module-specific hooks + */ switch (game_module_idx) { case MODULE_TOME: diff --git a/src/types.h b/src/types.h index 44ffd67a..ae1adcae 100644 --- a/src/types.h +++ b/src/types.h @@ -2287,6 +2287,12 @@ struct hook_identify_in { identify_mode mode; }; +typedef struct hook_give_in hook_give_in; +struct hook_give_in { + int m_idx; + int item; +}; + /* * Structure for the "quests" */ -- cgit v1.2.3 From f586b932a44f06bc17336cd8332bec43f17d3d88 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 22:01:58 +0200 Subject: Lua: Move "Hobbits like food" code to C --- lib/mods/theme/scpt/misc.lua | 19 ------------------- src/modules.c | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/lib/mods/theme/scpt/misc.lua b/lib/mods/theme/scpt/misc.lua index 21a81f83..3658b528 100644 --- a/lib/mods/theme/scpt/misc.lua +++ b/lib/mods/theme/scpt/misc.lua @@ -22,25 +22,6 @@ function longbottom_leaf(object) end add_hook_script(HOOK_EAT, "longbottom_leaf", "longbottom_leaf") --- Hobbits like food -function hobbit_food(m_idx, item) - - m_ptr = monster(m_idx) - o_ptr = get_object(item) - - if (m_ptr.r_idx == test_monster_name("Scruffy-looking hobbit")) - and (o_ptr.tval == TV_FOOD) then - cmsg_print(TERM_YELLOW, "'Yum!'") - inven_item_increase(item, -1) - inven_item_optimize(item) - return TRUE - else - return FALSE - end -end - -add_hook_script(HOOK_GIVE, "hobbit_food", "hobbit_food") - -- Smeagol likes rings function smeagol_ring(m_idx, item) diff --git a/src/modules.c b/src/modules.c index bd2a1acb..6b476fd2 100644 --- a/src/modules.c +++ b/src/modules.c @@ -543,6 +543,27 @@ static bool_ drunk_takes_wine(void *data, void *in_, void *out) } } +static bool_ hobbit_food(void *data, void *in_, void *out) +{ + hook_give_in *in = (hook_give_in *) in_; + monster_type *m_ptr = &m_list[in->m_idx]; + object_type *o_ptr = get_object(in->item); + + if ((m_ptr->r_idx == test_monster_name("Scruffy-looking hobbit")) && + (o_ptr->tval == TV_FOOD)) + { + cmsg_print(TERM_YELLOW, "'Yum!'"); + + inc_stack_size_ex(in->item, -1, OPTIMIZE, NO_DESCRIBE); + + return TRUE; + } + else + { + return FALSE; + } +} + void init_hooks_module() { /* @@ -570,6 +591,11 @@ void init_hooks_module() "auto_stat_gain", NULL); + add_hook_new(HOOK_GIVE, + hobbit_food, + "hobbit_food", + NULL); + break; } -- cgit v1.2.3 From 83d2d89462f4b03419019e23d73665f0472b687b Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 9 Jun 2012 21:55:59 +0200 Subject: Lua: Move "Smeagol takes RoI" code to C --- lib/mods/theme/scpt/misc.lua | 21 --------------------- src/modules.c | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/lib/mods/theme/scpt/misc.lua b/lib/mods/theme/scpt/misc.lua index 3658b528..9a3c37bb 100644 --- a/lib/mods/theme/scpt/misc.lua +++ b/lib/mods/theme/scpt/misc.lua @@ -22,27 +22,6 @@ function longbottom_leaf(object) end add_hook_script(HOOK_EAT, "longbottom_leaf", "longbottom_leaf") --- Smeagol likes rings -function smeagol_ring(m_idx, item) - - m_ptr = monster(m_idx) - o_ptr = get_object(item) - - if (m_ptr.r_idx == test_monster_name("Smeagol")) - and (o_ptr.tval == TV_RING) then - - cmsg_print(TERM_YELLOW, "'MY... PRECIOUSSSSS!!!'") - - inven_item_increase(item, -1) - inven_item_optimize(item) - return TRUE - else - return FALSE - end -end - -add_hook_script(HOOK_GIVE, "smeagol_ring", "smeagol_ring") - -- functions to check for Map and Key of Thror before proceeding in Erebor -- Thank you, Massimiliano Marangio :-) add_hooks diff --git a/src/modules.c b/src/modules.c index 6b476fd2..552bc876 100644 --- a/src/modules.c +++ b/src/modules.c @@ -564,6 +564,27 @@ static bool_ hobbit_food(void *data, void *in_, void *out) } } +static bool_ smeagol_ring(void *data, void *in_, void *out) +{ + hook_give_in *in = (hook_give_in *) in_; + monster_type *m_ptr = &m_list[in->m_idx]; + object_type *o_ptr = get_object(in->item); + + if ((m_ptr->r_idx == test_monster_name("Smeagol")) && + (o_ptr->tval == TV_RING)) + { + cmsg_print(TERM_YELLOW, "'MY... PRECIOUSSSSS!!!'"); + + inc_stack_size_ex(in->item, -1, OPTIMIZE, NO_DESCRIBE); + + return TRUE; + } + else + { + return FALSE; + } +} + void init_hooks_module() { /* @@ -596,6 +617,11 @@ void init_hooks_module() "hobbit_food", NULL); + add_hook_new(HOOK_GIVE, + smeagol_ring, + "smeagol_ring", + NULL); + break; } -- cgit v1.2.3 From e8a7753c88541e45a1b9d1b80be2ad227b179e20 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 10 Jun 2012 05:22:10 +0200 Subject: Lua: Move Vampire corruption handling to C --- lib/mods/theme/scpt/init.lua | 3 --- lib/mods/theme/scpt/player.lua | 16 ---------------- lib/scpt/init.lua | 3 --- lib/scpt/player.lua | 15 --------------- src/birth.c | 7 +++++++ 5 files changed, 7 insertions(+), 37 deletions(-) delete mode 100644 lib/mods/theme/scpt/player.lua delete mode 100644 lib/scpt/player.lua diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index 8cd2094a..64d2cabc 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -2,9 +2,6 @@ -- This file is loaded at the initialisation of ToME -- --- Load the class specific stuff -tome_dofile("player.lua") - -- Add the schools of magic schools_init() school_spells_init() diff --git a/lib/mods/theme/scpt/player.lua b/lib/mods/theme/scpt/player.lua deleted file mode 100644 index e2920642..00000000 --- a/lib/mods/theme/scpt/player.lua +++ /dev/null @@ -1,16 +0,0 @@ ------------------------------------------------------------------------------- ------------------------ Hook to create birth objects ------------------------- ------------------------------------------------------------------------------- -function __birth_hook_objects() - - -- Start the undeads, as undeads with the corruptions - if get_subrace_name() == "Vampire" then - player_gain_corruption(CORRUPT_VAMPIRE_TEETH) - player_gain_corruption(CORRUPT_VAMPIRE_STRENGTH) - player_gain_corruption(CORRUPT_VAMPIRE_VAMPIRE) - end - -end - --- Register in the hook list -add_hook_script(HOOK_BIRTH_OBJECTS, "__birth_hook_objects", "__birth_hook_objects") diff --git a/lib/scpt/init.lua b/lib/scpt/init.lua index d27ce23c..8434f6dd 100644 --- a/lib/scpt/init.lua +++ b/lib/scpt/init.lua @@ -2,9 +2,6 @@ -- This file is loaded at the initialisation of ToME -- --- Load the class specific stuff -tome_dofile("player.lua") - -- Add the schools of magic schools_init() school_spells_init() diff --git a/lib/scpt/player.lua b/lib/scpt/player.lua deleted file mode 100644 index 1c8da791..00000000 --- a/lib/scpt/player.lua +++ /dev/null @@ -1,15 +0,0 @@ ------------------------------------------------------------------------------- ------------------------ Hook to create birth objects ------------------------- ------------------------------------------------------------------------------- -function __birth_hook_objects() - - -- Start the undeads, as undeads with the corruptions - if get_subrace_name() == "Vampire" then - player_gain_corruption(CORRUPT_VAMPIRE_TEETH) - player_gain_corruption(CORRUPT_VAMPIRE_STRENGTH) - player_gain_corruption(CORRUPT_VAMPIRE_VAMPIRE) - end -end - --- Register in the hook list -add_hook_script(HOOK_BIRTH_OBJECTS, "__birth_hook_objects", "__birth_hook_objects") diff --git a/src/birth.c b/src/birth.c index 41abe3ad..4734a189 100644 --- a/src/birth.c +++ b/src/birth.c @@ -1246,6 +1246,13 @@ static void player_outfit(void) identify_pack_fully(); } + if (streq(rmp_ptr->title + rmp_name, "Vampire")) + { + player_gain_corruption(CORRUPT_VAMPIRE_TEETH); + player_gain_corruption(CORRUPT_VAMPIRE_STRENGTH); + player_gain_corruption(CORRUPT_VAMPIRE_VAMPIRE); + } + process_hooks(HOOK_BIRTH_OBJECTS, "()"); meta_inertia_control_hook_birth_objects(); -- cgit v1.2.3 From 9d06a4324a7f5daac169c0b2b1640696578aee08 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 10 Jun 2012 06:06:04 +0200 Subject: Lua: Move Theme's Longbottom Leaf code to C --- lib/mods/theme/scpt/misc.lua | 10 ---------- src/cmd6.c | 7 +++++++ src/modules.c | 20 ++++++++++++++++++++ src/types.h | 10 ++++++++++ 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/lib/mods/theme/scpt/misc.lua b/lib/mods/theme/scpt/misc.lua index 9a3c37bb..6205678a 100644 --- a/lib/mods/theme/scpt/misc.lua +++ b/lib/mods/theme/scpt/misc.lua @@ -12,16 +12,6 @@ end add_hook_script(HOOK_EAT, "food_vessel", "food_vessel") --- Longbottom Leaf *is* a great stress reliever: -function longbottom_leaf(object) - if (object.tval == 80) and (object.sval == 45) then - msg_print("What a stress reliever!") - heal_insanity(1000) - return FALSE - end -end -add_hook_script(HOOK_EAT, "longbottom_leaf", "longbottom_leaf") - -- functions to check for Map and Key of Thror before proceeding in Erebor -- Thank you, Massimiliano Marangio :-) add_hooks diff --git a/src/cmd6.c b/src/cmd6.c index 32ad1868..5377ef38 100644 --- a/src/cmd6.c +++ b/src/cmd6.c @@ -963,10 +963,17 @@ void do_cmd_eat_food(void) lev = k_info[o_ptr->k_idx].level; /* Scripted foods */ + hook_eat_in in = { o_ptr }; + hook_eat_out out = { FALSE }; + if (process_hooks_ret(HOOK_EAT, "d", "(O)", o_ptr)) { ident = process_hooks_return[0].num; } + else if (process_hooks_new(HOOK_EAT, &in, &out)) + { + ident = out.ident; + } /* (not quite) Normal foods */ else if (o_ptr->tval == TV_FOOD) { diff --git a/src/modules.c b/src/modules.c index 552bc876..4d139397 100644 --- a/src/modules.c +++ b/src/modules.c @@ -585,6 +585,21 @@ static bool_ smeagol_ring(void *data, void *in_, void *out) } } +static bool_ longbottom_leaf(void *data, void *in_, void *out_) +{ + hook_eat_in *in = (hook_eat_in *) in_; + + if ((in->o_ptr->tval == TV_FOOD) && + (in->o_ptr->sval == 45)) + { + msg_print("What a stress reliever!"); + heal_insanity(1000); + return TRUE; + } + + return FALSE; +} + void init_hooks_module() { /* @@ -622,6 +637,11 @@ void init_hooks_module() "smeagol_ring", NULL); + add_hook_new(HOOK_EAT, + longbottom_leaf, + "longbottom_leaf", + NULL); + break; } diff --git a/src/types.h b/src/types.h index ae1adcae..f7dd6d40 100644 --- a/src/types.h +++ b/src/types.h @@ -2293,6 +2293,16 @@ struct hook_give_in { int item; }; +typedef struct hook_eat_in hook_eat_in; +struct hook_eat_in { + object_type *o_ptr; +}; + +typedef struct hook_eat_out hook_eat_out; +struct hook_eat_out { + bool_ ident; +}; + /* * Structure for the "quests" */ -- cgit v1.2.3 From 6f98f68a44ce9a24efe3ff2722d63ad327772f1b Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 10 Jun 2012 06:19:16 +0200 Subject: Lua: Move Theme's non-scummy junk creation to C --- lib/mods/theme/scpt/misc.lua | 14 -------------- src/modules.c | 25 +++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/lib/mods/theme/scpt/misc.lua b/lib/mods/theme/scpt/misc.lua index 6205678a..15f9e4eb 100644 --- a/lib/mods/theme/scpt/misc.lua +++ b/lib/mods/theme/scpt/misc.lua @@ -1,17 +1,3 @@ --- A not-too-scummy way of generating junk for ammo -function food_vessel(object) - if ((object.tval == 80) and (object.sval == 43)) or - ((object.tval == 80) and (object.sval == 44)) then - local obj = create_object(TV_JUNK, 3) - obj.ident = bor(obj.ident, IDENT_MENTAL, IDENT_KNOWN) - inven_carry(obj, FALSE) - end_object(obj) - return FALSE - end -end - -add_hook_script(HOOK_EAT, "food_vessel", "food_vessel") - -- functions to check for Map and Key of Thror before proceeding in Erebor -- Thank you, Massimiliano Marangio :-) add_hooks diff --git a/src/modules.c b/src/modules.c index 4d139397..72274003 100644 --- a/src/modules.c +++ b/src/modules.c @@ -600,6 +600,26 @@ static bool_ longbottom_leaf(void *data, void *in_, void *out_) return FALSE; } +static bool_ food_vessel(void *data, void *in_, void *out) +{ + hook_eat_in *in = (hook_eat_in *) in_; + + if (((in->o_ptr->tval == TV_FOOD) && (in->o_ptr->sval == 43)) || + ((in->o_ptr->tval == TV_FOOD) && (in->o_ptr->sval == 44))) + { + object_type forge; + + object_prep(&forge, lookup_kind(TV_JUNK, 3)); + + forge.ident |= IDENT_MENTAL | IDENT_KNOWN; + inven_carry(&forge, FALSE); + + return TRUE; + } + + return FALSE; +} + void init_hooks_module() { /* @@ -642,6 +662,11 @@ void init_hooks_module() "longbottom_leaf", NULL); + add_hook_new(HOOK_EAT, + food_vessel, + "food_vessel", + NULL); + break; } -- cgit v1.2.3 From 01382b9ad17cf77a7f2867b8efce4ceb619392f7 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 10 Jun 2012 06:47:09 +0200 Subject: Lua: Move Theme's stair handling to C --- lib/mods/theme/scpt/init.lua | 3 -- lib/mods/theme/scpt/misc.lua | 59 ----------------------------- src/bldg.c | 8 ++++ src/cmd2.c | 34 ++++++++++++++++- src/defines.h | 1 + src/modules.c | 89 ++++++++++++++++++++++++++++++++++++++++++++ src/types.h | 12 ++++++ 7 files changed, 142 insertions(+), 64 deletions(-) delete mode 100644 lib/mods/theme/scpt/misc.lua diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index 64d2cabc..477a5d90 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -18,6 +18,3 @@ tome_dofile_anywhere(ANGBAND_DIR_SCPT, "dg_test.lua", FALSE) -- Add monster interaction tome_dofile("monsters.lua") - --- Add miscellaneous stuff -tome_dofile("misc.lua") diff --git a/lib/mods/theme/scpt/misc.lua b/lib/mods/theme/scpt/misc.lua deleted file mode 100644 index 15f9e4eb..00000000 --- a/lib/mods/theme/scpt/misc.lua +++ /dev/null @@ -1,59 +0,0 @@ --- functions to check for Map and Key of Thror before proceeding in Erebor --- Thank you, Massimiliano Marangio :-) -add_hooks -{ - [HOOK_STAIR] = function(direction) - if ((current_dungeon_idx == 20) and (dun_level == 60) and (direction == "down")) then - local i - local mapkey = 0 - for i = 0, INVEN_TOTAL - 1 do - if ((player.inventory(i).name1 == 209) or (player.inventory(i).name1 == 210)) then - mapkey = mapkey + 1 - end - end - - if (mapkey == 2) then - msg_print("The moon-letters on the map show you the keyhole! You use the key to enter.") - return FALSE - else - msg_print("You have found a door, but you cannot find a way to enter. Ask in Dale, perhaps?") - return TRUE - end - end - return FALSE - end, -} - --- function to make the Dale mayor tell you about how to get to Erebor 61 -add_building_action -{ - ["index"] = 66, - ["action"] = function() - msg_print("You will need Thorin's Key and Thrain's Map to get anywhere in Erebor. One may be found in the Barrow-Downs. The other, in Mirkwood.") - end -} - --- function to check for Key of Orthanc before proceeding to the final level in Isengard -add_hooks -{ - [HOOK_STAIR] = function(direction) - if ((current_dungeon_idx == 36) and (dun_level == 39) and (direction == "down")) then - local i - local orthkey = 0 - for i = 0, INVEN_TOTAL - 1 do - if (player.inventory(i).name1 == 15) then - orthkey = orthkey + 1 - end - end - - if (orthkey == 1) then - msg_print("#BYou have the key to the tower of Orthanc! You may proceed.#w") - return FALSE - else - msg_print("#yYou may not enter Orthanc without the key to the gates!#w Rumours say the key was lost in the Mines of Moria...") - return TRUE - end - end - return FALSE - end, -} \ No newline at end of file diff --git a/src/bldg.c b/src/bldg.c index e35cc023..6b785d2a 100644 --- a/src/bldg.c +++ b/src/bldg.c @@ -2054,6 +2054,14 @@ bool_ bldg_process_command(store_type *s_ptr, int i) break; } + case BACT_EREBOR_KEY: + { + msg_print("You will need Thorin's Key and Thrain's Map" + " to get anywhere in Erebor. One may be found" + " in the Barrow-Downs. The other, in Mirkwood."); + break; + } + default: { if (process_hooks_ret(HOOK_BUILDING_ACTION, "dd", "(d)", bact)) diff --git a/src/cmd2.c b/src/cmd2.c index 7689f46a..9149e76b 100644 --- a/src/cmd2.c +++ b/src/cmd2.c @@ -74,6 +74,30 @@ static bool_ do_cmd_bash_fountain(int y, int x) return (more); } +/* + * Stair hooks + */ +static bool_ stair_hooks(stairs_direction direction) +{ + cptr direction_s = (direction == STAIRS_UP) ? "up" : "down"; + + /* Old-style hooks */ + if (process_hooks(HOOK_STAIR, "(s)", direction_s)) + { + return TRUE; /* Prevent movement */ + } + + /* New-style hooks */ + { + hook_stair_in in = { direction }; + hook_stair_out out = { TRUE }; /* Allow by default */ + + process_hooks_new(HOOK_STAIR, &in, &out); + + return (!out.allow); + } +} + /* * Go up one level @@ -93,7 +117,10 @@ void do_cmd_go_up(void) c_ptr = &cave[p_ptr->py][p_ptr->px]; /* Can we ? */ - if (process_hooks(HOOK_STAIR, "(s)", "up")) return; + if (stair_hooks(STAIRS_UP)) + { + return; + } /* Normal up stairs */ if ((c_ptr->feat == FEAT_LESS) || (c_ptr->feat == FEAT_WAY_LESS)) @@ -318,7 +345,10 @@ void do_cmd_go_down(void) } /* Can we ? */ - if (process_hooks(HOOK_STAIR, "(s)", "down")) return; + if (stair_hooks(STAIRS_DOWN)) + { + return; + } /* Normal up stairs */ if (c_ptr->feat == FEAT_SHAFT_DOWN) diff --git a/src/defines.h b/src/defines.h index 2907d2a2..aad4614e 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4053,6 +4053,7 @@ #define BACT_GET_ITEM 55 #define BACT_FIREPROOF_QUEST 56 #define BACT_LIBRARY_QUEST 61 +#define BACT_EREBOR_KEY 66 /* If one adds new BACT_ do NOT forget to increase max_bact in variables.c */ diff --git a/src/modules.c b/src/modules.c index 72274003..d9c599d1 100644 --- a/src/modules.c +++ b/src/modules.c @@ -620,6 +620,85 @@ static bool_ food_vessel(void *data, void *in_, void *out) return FALSE; } +/* + * Player must have appropriate keys to enter Erebor. + */ +static bool_ erebor_stair(void *data, void *in_, void *out_) +{ + hook_stair_in *in = (hook_stair_in *) in_; + hook_stair_out *out = (hook_stair_out *) out_; + + if ((dungeon_type == 20) && + (dun_level == 60) && + (in->direction == STAIRS_DOWN)) + { + int i, keys; + + keys = 0; + for (i = 0; i < INVEN_TOTAL - 1; i++) + { + if ((p_ptr->inventory[i].name1 == 209) || + (p_ptr->inventory[i].name1 == 210)) + { + keys += 1; + } + } + + if (keys >= 2) + { + msg_print("The moon-letters on the map show you " + "the keyhole! You use the key to enter."); + out->allow = TRUE; + } + else + { + msg_print("You have found a door, but you cannot " + "find a way to enter. Ask in Dale, perhaps?"); + out->allow = FALSE; + } + } + + return FALSE; +} + +/* + * Orthanc requires a key. + */ +static bool_ orthanc_stair(void *data, void *in_, void *out_) +{ + hook_stair_in *in = (hook_stair_in *) in_; + hook_stair_out *out = (hook_stair_out *) out_; + + if ((dungeon_type == 36) && + (dun_level == 39) && + (in->direction == STAIRS_DOWN)) + { + int i, keys; + + keys = 0; + for (i = 0; i < INVEN_TOTAL - 1; i++) + { + if (p_ptr->inventory[i].name1 == 15) + { + keys += 1; + } + } + + if (keys >= 1) + { + msg_print("#BYou have the key to the tower of Orthanc! You may proceed.#w"); + out->allow = TRUE; + } + else + { + msg_print("#yYou may not enter Orthanc without the key to the gates!#w Rumours say the key was lost in the Mines of Moria..."); + out->allow = FALSE; + } + } + + return FALSE; +} + void init_hooks_module() { /* @@ -667,6 +746,16 @@ void init_hooks_module() "food_vessel", NULL); + add_hook_new(HOOK_STAIR, + erebor_stair, + "erebor_stair", + NULL); + + add_hook_new(HOOK_STAIR, + orthanc_stair, + "orthanc_stair", + NULL); + break; } diff --git a/src/types.h b/src/types.h index f7dd6d40..ea383ff7 100644 --- a/src/types.h +++ b/src/types.h @@ -2303,6 +2303,18 @@ struct hook_eat_out { bool_ ident; }; +typedef enum { STAIRS_UP, STAIRS_DOWN } stairs_direction; + +typedef struct hook_stair_in hook_stair_in; +struct hook_stair_in { + stairs_direction direction; +}; + +typedef struct hook_stair_out hook_stair_out; +struct hook_stair_out { + bool_ allow; +}; + /* * Structure for the "quests" */ -- cgit v1.2.3 From c40dff568a06733793a2351c9c172c180f7be542 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 10 Jun 2012 09:04:54 +0200 Subject: Lua: Move Theme's movement hook to C --- lib/mods/theme/scpt/monsters.lua | 37 ----------------------------- src/modules.c | 50 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 37 deletions(-) diff --git a/lib/mods/theme/scpt/monsters.lua b/lib/mods/theme/scpt/monsters.lua index 6c0cc197..df9c641d 100644 --- a/lib/mods/theme/scpt/monsters.lua +++ b/lib/mods/theme/scpt/monsters.lua @@ -1,42 +1,5 @@ -- This file holds various things that govern monster behaviour with respect to the player --- Enables player to push past any monster who is >= MSTATUS_NEUTRAL. --- Written by BauMog for the Intets Hevn module; permission granted to use in the Theme module - --- Adapted from defines.h -function cave_floor_bold(y, x) - local c_ptr = cave(y, x); - if(cave_is(c_ptr, FF1_FLOOR) == TRUE) and (c_ptr.feat ~= FEAT_MON_TRAP) then - return TRUE - else - return FALSE - end -end - --- Adapted from cmd1.c -function __hook_push_past(y, x) - local c_ptr = cave(y, x); - - if(c_ptr.m_idx > 0) then - m_ptr = monster(c_ptr.m_idx); - if(m_ptr.status >= MSTATUS_NEUTRAL) then - if(cave_floor_bold(y, x) == TRUE) or (m_ptr.flags2 == RF2_PASS_WALL) then - msg_print(format("You push past %s.", monster_desc(m_ptr, 0))); - m_ptr.fy = player.py; - m_ptr.fx = player.px; - cave(player.py, player.px).m_idx = c_ptr.m_idx; - c_ptr.m_idx = 0; - else - msg_print(format("%s is in your way!", monster_desc(m_ptr, 0))); - energy_use = 0; - end - end - end - -end - -add_hook_script(HOOK_MOVE, "__hook_push_past", "__hook_push_past"); - -- Monster vs. Player Race alignment script -- From T-Plus by Ingeborg S. Norden diff --git a/src/modules.c b/src/modules.c index d9c599d1..3368691a 100644 --- a/src/modules.c +++ b/src/modules.c @@ -699,6 +699,51 @@ static bool_ orthanc_stair(void *data, void *in_, void *out_) return FALSE; } +/* + * Movement from Theme + */ +bool_ theme_push_past(void *data, void *in_, void *out_) +{ + hook_move_in *p = (hook_move_in *) in_; + cave_type *c_ptr = &cave[p->y][p->x]; + + if (c_ptr->m_idx > 0) + { + monster_type *m_ptr = &m_list[c_ptr->m_idx]; + monster_race *mr_ptr = race_inf(m_ptr); + + if (m_ptr->status >= MSTATUS_NEUTRAL) + { + if ((cave_floor_bold(p->y, p->x) == TRUE) || + (mr_ptr->flags2 == RF2_PASS_WALL)) + { + char buf[128]; + + monster_desc(buf, m_ptr, 0); + msg_print(format("You push past %s.", buf)); + + m_ptr->fy = p_ptr->py; + m_ptr->fx = p_ptr->px; + cave[p_ptr->py][p_ptr->px].m_idx = c_ptr->m_idx; + c_ptr->m_idx = 0; + } + else + { + char buf[128]; + + monster_desc(buf, m_ptr, 0); + msg_print(format("%s is in your way!", buf)); + energy_use = 0; + + return TRUE; + } + } + } + + return FALSE; +} + + void init_hooks_module() { /* @@ -756,6 +801,11 @@ void init_hooks_module() "orthanc_stair", NULL); + add_hook_new(HOOK_MOVE, + theme_push_past, + "__hook_push_past", + NULL); + break; } -- cgit v1.2.3 From c44efd43a83a5e6b2b696471fd46277cfd860518 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 11 Jun 2012 06:22:17 +0200 Subject: Lua: Move Theme's racial alignment to C --- lib/mods/theme/scpt/monsters.lua | 125 +------------ src/defines.h | 32 ++++ src/generate.c | 1 + src/modules.c | 391 +++++++++++++++++++++++++++++++++++++++ src/monster2.c | 6 + src/types.h | 5 + 6 files changed, 437 insertions(+), 123 deletions(-) diff --git a/lib/mods/theme/scpt/monsters.lua b/lib/mods/theme/scpt/monsters.lua index df9c641d..0f4c8cda 100644 --- a/lib/mods/theme/scpt/monsters.lua +++ b/lib/mods/theme/scpt/monsters.lua @@ -1,30 +1,5 @@ -- This file holds various things that govern monster behaviour with respect to the player --- Monster vs. Player Race alignment script --- From T-Plus by Ingeborg S. Norden - -monst_al = {} - -function monst_al_add(status, mrs, prs) -for i,v in mrs do --- added end -if not monst_al[v] then monst_al[v] = {} end -for j, w in prs do -monst_al[v][w] = status -end -end -end - -function monst_al_get(mr,pr) - if monst_al[mr] then return monst_al[mr][pr] - else return end -end - --- Maia aggravation for evil beings (provided that no demonic corruptions are present) --- Based on parts of angel.lua from T-Plus by Ingeborg S. Norden - --- cast dispel evil with 0 damage every 10 turns - add_hooks{ [HOOK_GAME_START] = function() @@ -35,102 +10,6 @@ add_hooks{ (player_has_corruption(CORRUPT_BALROG_FORM) ~= TRUE)) then -- "Proper" Maiar aggravate evil beings timer_aggravate_evil_enable() - -- Good beings (except swans, GWoPs, Wyrm Spirits, and some joke uniques) are coaligned with Maiar - - monst_al_add(MSTATUS_FRIEND, {25, 29, 45, 97, 109, 147, 225, 335, 346, 443, 581, 629, 699, 853, 984, 1007, 1017}, {21}) - - -- Non-evil humanoids are neutral to Humans, Dunedain, Druedain, Rohirrim - elseif ((get_race_name() == "Human") or - (get_race_name() == "Dunadan") or - (get_race_name() == "Druadan") or - (get_race_name() == "RohanKnight")) then - monst_al_add(MSTATUS_NEUTRAL, {43, 45, 46, 83, 93, 97, 109, 110, 142, 147, 216, 225, 293, 345, 346, 693, 699, 937, 988, 997, 998, 1000},{0, 8, 12, 16}) - - -- Non-evil sentient (and non-animal) creatures are neutral to Hobbits, Elves, Wood-Elves - elseif ((get_race_name() == "Hobbit") or - (get_race_name() == "Elf") or - (get_race_name() == "Wood-Elf")) then - monst_al_add(MSTATUS_NEUTRAL, {43, 45, 46, 83, 93, 97, 109, 110, 142, 147, 216, 225, 293, 345, 346, 693, 699, 937, 988, 997, 998, 1000, 74, 103, 882, 1017},{2, 3, 20}) - - -- Gnome monsters are neutral to Gnomes - elseif get_race_name() == "Gnome" then - monst_al_add(MSTATUS_NEUTRAL, {103, 281, 680, 984, 1001, 1003, 1007, 1011, 1014, 1016},{4}) - - -- Dwarven monsters are neutral to Petty-dwarves and Dwarves - elseif ((get_race_name() == "Dwarf") or - (get_race_name() == "Petty-Dwarf")) then - monst_al_add(MSTATUS_NEUTRAL, {111, 112, 179, 180, 181, 182},{5, 13}) - - -- If an Orc character worships Melkor, lower-level Orcs are neutral (not Uruk-hai, however) - elseif ((get_race_name() == "Orc") and - (player.pgod == GOD_MELKOR)) then - monst_al_add(MSTATUS_FRIEND, {87, 118, 126, 149, 244, 251, 264},{6}) - - -- If a Troll character worships Melkor, Trolls are neutral (not Eldraks, Ettins, and War trolls, though) - elseif ((get_race_name() == "Troll") and - (player.pgod == GOD_MELKOR)) then - monst_al_add(MSTATUS_NEUTRAL, {297, 401, 403, 424, 454, 491, 496, 509, 538},{7}) - - -- Ogres are neutral to Half-Ogres - elseif get_race_name() == "Half-Ogre" then - monst_al_add(MSTATUS_NEUTRAL, {262, 285, 415, 430, 479, 745, 918},{10}) - - -- Bears are neutral to Beornings, except werebears. - elseif get_race_name() == "Beorning" then - monst_al_add(MSTATUS_NEUTRAL, {160, 173, 191, 854, 855, 867, 873},{11}) - - -- Dark elven monsters are coaligned with Dark Elves - elseif get_race_name() == "Dark-Elf" then - monst_al_add(MSTATUS_FRIEND, {122, 178, 183, 226, 348, 375, 400, 657},{14}) - - -- Plants are coaligned with Ents - elseif get_race_name() == "Ent" then - monst_al_add(MSTATUS_FRIEND, {248, 266, 317, 329, 396},{15}) - - -- And since the above is largely useless except out in the wild... - -- If an Ent worships Yavanna, lower-level animals are coaligned - -- should make the early game a bit easier for Ents. - elseif ((get_race_name() == "Ent") and - (player.pgod == GOD_YAVANNA)) then - monst_al_add(MSTATUS_FRIEND, {21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33, 35, 36, 37, 38, 39, 41, 49, 50, 52, 56, 57, 58, 59, 60, 61, 62, 69, 70, 75, 77, 78, 79, 86, 88, 89, 90, 95, 96, 105, 106, 114, 119, 120, 121, 123, 127, 134, 141, 143, 151, 154, 155, 156, 160, 161, 168, 171, 173, 174, 175, 176, 187, 191, 196, 197, 198, 210, 211, 213, 230, 236, 250, 259},{15}) - - -- All non-evil non-neutral birds are coaligned with Eagles - elseif get_race_name() == "Eagle" then - monst_al_add(MSTATUS_FRIEND, {61, 141, 151, 279},{17}) - - -- Hatchling dragons are coaligned with Dragons - elseif get_race_name() == "Dragon" then - monst_al_add(MSTATUS_FRIEND, {163, 164, 165, 166, 167, 204, 218, 219, 911},{18}) - - -- Yeeks are neutral to Yeeks - elseif get_race_name() == "Yeek" then - monst_al_add(MSTATUS_NEUTRAL, {580, 583, 594, 653, 655, 659, 661},{19}) - - -- Oathbreakers are coaligned if player is wielding Anduril - -- It's dirty, but it works, and it doesn't bother checking demons and the races who can't wield weapons. - elseif get_object(INVEN_WIELD).name1 == 83 then - monst_al_add(MSTATUS_FRIEND, {731},{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 19, 20, 21, 22, 23}) - end + end end, - -[HOOK_LEVEL_END_GEN] = function() - -for i=0,m_max-1 do - local monst = monster(i) - local s = monst_al_get(monst.r_idx, player.prace) - if s then monst.status = s end -end - -end, - -[HOOK_NEW_MONSTER] = function() - -for i=0,m_max-1 do - local monst = monster(i) - local s = monst_al_get(monst.r_idx, player.prace) - if s then monst.status = s end -end - -end, - -} \ No newline at end of file +} diff --git a/src/defines.h b/src/defines.h index aad4614e..7e4321a1 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4455,6 +4455,37 @@ #define MUT1_EARTHQUAKE 33 #define CORRUPTIONS_MAX 34 +/* + * Races + */ +#define RACE_HUMAN 0 +#define RACE_HALF_ELF 1 +#define RACE_ELF 2 +#define RACE_HOBBIT 3 +#define RACE_GNOME 4 +#define RACE_DWARF 5 +#define RACE_ORC 6 +#define RACE_TROLL 7 +#define RACE_DUNADAN 8 +#define RACE_HIGH_ELF 9 +#define RACE_HALF_OGRE 10 +#define RACE_BEORNING 11 +#define RACE_KOBOLD 12 /* ToME */ +#define RACE_DRUADAN 12 /* Theme */ +#define RACE_PETTY_DWARF 13 +#define RACE_DARK_ELF 14 +#define RACE_ENT 15 +#define RACE_ROHANKNIGHT 16 +#define RACE_THUNDERLORD 17 /* ToME */ +#define RACE_EAGLE 17 /* Theme */ +#define RACE_DEATHMOLD 18 /* ToME */ +#define RACE_DRAGON 18 /* Theme */ +#define RACE_YEEK 19 +#define RACE_WOOD_ELF 20 +#define RACE_MAIA 21 +#define RACE_EASTERLING 22 /* Theme */ +#define RACE_DEMON 23 /* Theme */ + /* * Hooks */ @@ -4480,6 +4511,7 @@ #define HOOK_MONSTER_AI 19 #define HOOK_PLAYER_LEVEL 20 #define HOOK_WIELD 21 +#define HOOK_NEW_MONSTER_END 22 #define HOOK_AIM 24 #define HOOK_USE 25 #define HOOK_ACTIVATE 26 diff --git a/src/generate.c b/src/generate.c index 6d83c321..bedd169d 100644 --- a/src/generate.c +++ b/src/generate.c @@ -8347,6 +8347,7 @@ static void finalise_special_level(void) if (!dun_level) return; process_hooks(HOOK_LEVEL_END_GEN, "()"); + process_hooks_new(HOOK_LEVEL_END_GEN, NULL, NULL); /* Calculate relative depth */ level = dun_level - d_info[dungeon_type].mindepth; diff --git a/src/modules.c b/src/modules.c index 3368691a..98839d34 100644 --- a/src/modules.c +++ b/src/modules.c @@ -743,6 +743,387 @@ bool_ theme_push_past(void *data, void *in_, void *out_) return FALSE; } +/* + * Check if monster race is in list. The list is terminated + * with a -1. + */ +static bool_ race_in_list(int r_idx, int race_idxs[]) +{ + int i; + + for (i = 0; race_idxs[i] >= 0; i++) + { + if (r_idx == race_idxs[i]) + { + return TRUE; + } + } + + return FALSE; +} + +/* + * Monster racial alignment from Theme. + */ +static s16b *compute_monster_status(int r_idx) +{ + static s16b FRIEND_ = MSTATUS_FRIEND; + static s16b *FRIEND = &FRIEND_; + static s16b NEUTRAL_ = MSTATUS_NEUTRAL; + static s16b *NEUTRAL = &NEUTRAL_; + + object_type *o_ptr = NULL; + + switch (p_ptr->prace) + { + case RACE_MAIA: + { + int good_race_idxs[] = { + 25, 29, 45, 97, 109, + 147, 225, 335, 346, 443, + 581, 629, 699, 853, 984, + 1007, 1017, -1 + }; + + if (!(player_has_corruption(CORRUPT_BALROG_AURA)) && + !(player_has_corruption(CORRUPT_BALROG_WINGS)) && + !(player_has_corruption(CORRUPT_BALROG_STRENGTH)) && + !(player_has_corruption(CORRUPT_BALROG_FORM)) && + race_in_list(r_idx, good_race_idxs)) + { + /* Good beings (except swans, GWoPs, Wyrm + * Spirits, and some joke uniques) are + * coaligned with Maiar */ + return FRIEND; + } + + break; + } + + case RACE_HUMAN: + case RACE_DUNADAN: + case RACE_DRUADAN: + case RACE_ROHANKNIGHT: + { + int nonevil_humanoid_race_idxs[] = { + 43, 45, 46, 83, 93, + 97, 109, 110, 142, 147, + 216, 225, 293, 345, 346, + 693, 699, 937, 988, 997, + 998, 1000, -1 + }; + + if (race_in_list(r_idx, nonevil_humanoid_race_idxs)) + { + return NEUTRAL; + } + + break; + } + + case RACE_ELF: + case RACE_HOBBIT: + case RACE_WOOD_ELF: + { + int nonevil_sentient_race_idxs[] = { + 43, 45, 46, 83, 93, + 97, 109, 110, 142, 147, + 216, 225, 293, 345, 346, + 693, 699, 937, 988, 997, + 998, 1000, 74, 103, 882, + 1017, -1 + }; + + if (race_in_list(r_idx, nonevil_sentient_race_idxs)) + { + return NEUTRAL; + } + + break; + } + + case RACE_GNOME: + { + int gnomish_race_idxs[] = { + 103, 281, 680, 984, 1001, + 1003, 1007, 1011, 1014, 1016, + -1 + }; + + if (race_in_list(r_idx, gnomish_race_idxs)) + { + return NEUTRAL; + } + + break; + } + + case RACE_DWARF: + case RACE_PETTY_DWARF: + { + int dwarvish_race_idxs[] = { + 111, 112, 179, 180, 181, + 182, -1 + }; + + if (race_in_list(r_idx, dwarvish_race_idxs)) + { + return NEUTRAL; + } + + break; + } + + case RACE_ORC: + { + int low_orc_race_idxs[] = { + 87, 118, 126, 149, 244, + 251, 264, -1 + }; + + if ((p_ptr->pgod == GOD_MELKOR) && + race_in_list(r_idx, low_orc_race_idxs)) + { + return FRIEND; + } + + break; + } + + case RACE_TROLL: + { + int low_troll_race_idxs[] = { + 297, 401, 403, 424, 454, + 491, 496, 509, 538, -1 + }; + + if ((p_ptr->pgod == GOD_MELKOR) && + race_in_list(r_idx, low_troll_race_idxs)) + { + return NEUTRAL; + } + + break; + } + + case RACE_HALF_OGRE: + { + int ogre_race_idxs[] = { + 262, 285, 415, 430, 479, + 745, 918, -1 + }; + + if (race_in_list(r_idx, ogre_race_idxs)) + { + return NEUTRAL; + } + + break; + } + + case RACE_BEORNING: + { + /* Bears; not werebears. */ + int bear_race_idxs[] = { + 160, 173, 191, 854, + 855, 867, 873, -1 + }; + + if (race_in_list(r_idx, bear_race_idxs)) + { + return NEUTRAL; + } + + break; + } + + case RACE_DARK_ELF: + { + int dark_elven_race_idxs[] = { + 122, 178, 183, 226, 348, + 375, 400, 657, -1 + }; + + if (race_in_list(r_idx, dark_elven_race_idxs)) + { + return FRIEND; + } + + break; + } + + case RACE_ENT: + { + int plant_race_idxs[] = { + 248, 266, 317, 329, 396, + -1 + }; + + if (race_in_list(r_idx, plant_race_idxs)) + { + return FRIEND; + } + + /* And since the above is largely useless except out + in the wild... If an Ent worships Yavanna, + lower-level animals are coaligned should make the + early game a bit easier for Ents. */ + + if (p_ptr->pgod == GOD_YAVANNA) + { + int lower_animal_race_idxs[] = { + 21, 23, 24, 25, 26, + 27, 28, 29, 30, 31, + 33, 35, 36, 37, 38, + 39, 41, 49, 50, 52, + 56, 57, 58, 59, 60, + 61, 62, 69, 70, 75, + 77, 78, 79, 86, 88, + 89, 90, 95, 96, 105, + 106, 114, 119, 120, 121, + 123, 127, 134, 141, 143, + 151, 154, 155, 156, 160, + 161, 168, 171, 173, 174, + 175, 176, 187, 191, 196, + 197, 198, 210, 211, 213, + 230, 236, 250, 259, -1 + }; + + if (race_in_list(r_idx, lower_animal_race_idxs)) + { + return FRIEND; + } + } + + break; + } + + case RACE_EAGLE: + { + int nonevil_nonneurtal_bird_race_idxs[] = { + 61, 141, 151, 279, -1 + }; + + if (race_in_list(r_idx, nonevil_nonneurtal_bird_race_idxs)) + { + return FRIEND; + } + + break; + } + + case RACE_DRAGON: + { + int hatchling_dragon_race_idxs[] = { + 163, 164, 165, 166, 167, + 204, 218, 219, 911, -1 + }; + + if (race_in_list(r_idx, hatchling_dragon_race_idxs)) + { + return FRIEND; + } + + break; + } + + case RACE_YEEK: + { + int yeek_race_idxs[] = { + 580, 583, 594, 653, 655, + 659, 661, -1 + }; + + if (race_in_list(r_idx, yeek_race_idxs)) + { + return NEUTRAL; + } + + break; + } + + }; + + /* Oathbreakers are coaligned if player is wielding Anduril. + It's dirty, but it works, and it doesn't bother checking + demons and the races who can't wield weapons. */ + o_ptr = get_object(INVEN_WIELD); + if (o_ptr != NULL && + o_ptr->name1 == ART_ANDURIL) + { + switch (p_ptr->prace) + { + case RACE_HUMAN: + case RACE_HALF_ELF: + case RACE_ELF: + case RACE_HOBBIT: + case RACE_GNOME: + case RACE_DWARF: + case RACE_ORC: + case RACE_TROLL: + case RACE_DUNADAN: + case RACE_HIGH_ELF: + case RACE_HALF_OGRE: + case RACE_BEORNING: + case RACE_DRUADAN: + case RACE_PETTY_DWARF: + case RACE_DARK_ELF: + case RACE_ENT: + case RACE_ROHANKNIGHT: + case RACE_YEEK: + case RACE_WOOD_ELF: + case RACE_MAIA: + case RACE_EASTERLING: + case RACE_DEMON: + { + int oathbreaker_race_idxs[] = { + 731, -1 + }; + + if (race_in_list(r_idx, oathbreaker_race_idxs)) + { + return FRIEND; + } + + break; + } + } + } + + /* No status override */ + return NULL; +} + +static bool_ theme_level_end_gen(void *data, void *in, void *out) +{ + int i = 0; + + for (i = 0; i < m_max; i++) + { + monster_type *m_ptr = &m_list[i]; + int r_idx = m_ptr->r_idx; + s16b *status = compute_monster_status(r_idx); + if (status) + { + m_ptr->status = *status; + } + } + + return FALSE; +} + +static bool_ theme_new_monster_end(void *data, void *in_, void *out) +{ + hook_new_monster_end_in *in = (hook_new_monster_end_in *) in_; + s16b *status = compute_monster_status(in->m_ptr->r_idx); + + if (status) + { + in->m_ptr->status = *status; + } + + return FALSE; +} void init_hooks_module() { @@ -806,6 +1187,16 @@ void init_hooks_module() "__hook_push_past", NULL); + add_hook_new(HOOK_LEVEL_END_GEN, + theme_level_end_gen, + "theme_level_end_gen", + NULL); + + add_hook_new(HOOK_NEW_MONSTER_END, + theme_new_monster_end, + "theme_new_monster_end", + NULL); + break; } diff --git a/src/monster2.c b/src/monster2.c index b0753244..cdef75d4 100644 --- a/src/monster2.c +++ b/src/monster2.c @@ -2657,6 +2657,12 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status) place_monster_one_race = NULL; + /* Processs hooks */ + { + hook_new_monster_end_in in = { m_ptr }; + process_hooks_new(HOOK_NEW_MONSTER_END, &in, NULL); + } + /* Success */ place_monster_result = c_ptr->m_idx; return c_ptr->m_idx; diff --git a/src/types.h b/src/types.h index ea383ff7..cb6d8e73 100644 --- a/src/types.h +++ b/src/types.h @@ -2315,6 +2315,11 @@ struct hook_stair_out { bool_ allow; }; +typedef struct hook_new_monster_end_in hook_new_monster_end_in; +struct hook_new_monster_end_in { + monster_type *m_ptr; +}; + /* * Structure for the "quests" */ -- cgit v1.2.3 From 7833f2577399f212be5c107611f291be1b47ce8f Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 11 Jun 2012 19:06:24 +0200 Subject: Lua: Move joke monster code to C --- lib/mods/theme/scpt/init.lua | 3 --- lib/mods/theme/scpt/joke.lua | 31 ------------------------------- lib/scpt/init.lua | 3 --- lib/scpt/joke.lua | 31 ------------------------------- src/CMakeLists.txt | 2 +- src/externs.h | 3 +++ src/joke.c | 34 ++++++++++++++++++++++++++++++++++ src/modules.c | 5 +++++ 8 files changed, 43 insertions(+), 69 deletions(-) delete mode 100644 lib/mods/theme/scpt/joke.lua delete mode 100644 lib/scpt/joke.lua create mode 100644 src/joke.c diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index 477a5d90..af299f2c 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -10,9 +10,6 @@ init_school_books() -- Post-spell creation initialization initialize_bookable_spells() --- Add joke stuff -tome_dofile("joke.lua") - -- Some tests, if the file is not present, this is fine tome_dofile_anywhere(ANGBAND_DIR_SCPT, "dg_test.lua", FALSE) diff --git a/lib/mods/theme/scpt/joke.lua b/lib/mods/theme/scpt/joke.lua deleted file mode 100644 index 2d87b651..00000000 --- a/lib/mods/theme/scpt/joke.lua +++ /dev/null @@ -1,31 +0,0 @@ --- Place a monster in a good spot -function gen_joke_place_monster(r_idx) - local try = 1000 - local x - local y - while try > 0 do - x = randint(cur_hgt - 4) + 2 - y = randint(cur_wid - 4) + 2 - if not (0 == place_monster_one(y, x, r_idx, 0, FALSE, MSTATUS_ENEMY)) then - return - end - try = try - 1 - end -end - --- Check if a special joke monster can be generated here -function gen_joke_monsters() - if joke_monsters == FALSE then - return - end - - -- Neil - if (current_dungeon_idx == 20) and (dun_level == 72) then - neil = test_monster_name("Neil, the Sorceror") - m_allow_special[neil + 1] = TRUE - gen_joke_place_monster(neil) - m_allow_special[neil + 1] = FALSE - end -end - -add_hook_script(HOOK_LEVEL_END_GEN, "gen_joke_monsters", "gen_joke_monsters") diff --git a/lib/scpt/init.lua b/lib/scpt/init.lua index 8434f6dd..edc82fe1 100644 --- a/lib/scpt/init.lua +++ b/lib/scpt/init.lua @@ -10,8 +10,5 @@ init_school_books() -- Post-spell creation initialization initialize_bookable_spells() --- Add joke stuff -tome_dofile("joke.lua") - -- Some tests, if the file is not present, this is fine tome_dofile_anywhere(ANGBAND_DIR_SCPT, "dg_test.lua", FALSE) diff --git a/lib/scpt/joke.lua b/lib/scpt/joke.lua deleted file mode 100644 index 2d87b651..00000000 --- a/lib/scpt/joke.lua +++ /dev/null @@ -1,31 +0,0 @@ --- Place a monster in a good spot -function gen_joke_place_monster(r_idx) - local try = 1000 - local x - local y - while try > 0 do - x = randint(cur_hgt - 4) + 2 - y = randint(cur_wid - 4) + 2 - if not (0 == place_monster_one(y, x, r_idx, 0, FALSE, MSTATUS_ENEMY)) then - return - end - try = try - 1 - end -end - --- Check if a special joke monster can be generated here -function gen_joke_monsters() - if joke_monsters == FALSE then - return - end - - -- Neil - if (current_dungeon_idx == 20) and (dun_level == 72) then - neil = test_monster_name("Neil, the Sorceror") - m_allow_special[neil + 1] = TRUE - gen_joke_place_monster(neil) - m_allow_special[neil + 1] = FALSE - end -end - -add_hook_script(HOOK_LEVEL_END_GEN, "gen_joke_monsters", "gen_joke_monsters") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d84f94ba..0e1b21da 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,7 +11,7 @@ SET(SRCS monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c spells1.c spells2.c spells3.c spells4.c spells5.c spells6.c - corrupt.c mimic.c + corrupt.c joke.c mimic.c status.c files.c notes.c loadsave.c string_list.c cmd1.c cmd2.c cmd3.c cmd4.c cmd5.c cmd6.c cmd7.c help.c range.c diff --git a/src/externs.h b/src/externs.h index 38511e48..dc449cb1 100644 --- a/src/externs.h +++ b/src/externs.h @@ -990,6 +990,9 @@ extern s16b error_line; extern u32b fake_name_size; extern u32b fake_text_size; +/* joke.c */ +extern bool_ gen_joke_monsters(void *data, void *in, void *out); + /* loadsave.c */ extern void register_savefile(int num); extern bool_ file_exist(char *buf); diff --git a/src/joke.c b/src/joke.c new file mode 100644 index 00000000..0ff01557 --- /dev/null +++ b/src/joke.c @@ -0,0 +1,34 @@ +#include "angband.h" + +static void gen_joke_place_monster(r_idx) +{ + int try; + + for (try = 0; try < 1000; try++) + { + int x = randint(cur_hgt - 4) + 2; + int y = randint(cur_wid - 4) + 2; + + if (place_monster_one(y, x, r_idx, 0, FALSE, MSTATUS_ENEMY)) + { + return; + } + } +} + +bool_ gen_joke_monsters(void *data, void *in, void *out) +{ + if (joke_monsters) + { + if ((dungeon_type == 20) && + (dun_level == 72)) + { + int r_idx = test_monster_name("Neil, the Sorceror"); + m_allow_special[r_idx + 1] = TRUE; + gen_joke_place_monster(r_idx); + m_allow_special[r_idx + 1] = FALSE; + } + } + + return FALSE; +} diff --git a/src/modules.c b/src/modules.c index 98839d34..01f1be00 100644 --- a/src/modules.c +++ b/src/modules.c @@ -1135,6 +1135,11 @@ void init_hooks_module() "drunk_takes_wine", NULL); + add_hook_new(HOOK_LEVEL_END_GEN, + gen_joke_monsters, + "gen_joke_monsters", + NULL); + /* * Module-specific hooks */ -- cgit v1.2.3 From cd328f56d295a6e8c17cd12110368a489cf82b58 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 11 Jun 2012 19:50:10 +0200 Subject: Lua: Move activation of Theme's Maia "aggravation" to C --- lib/mods/theme/scpt/init.lua | 3 --- lib/mods/theme/scpt/monsters.lua | 15 --------------- src/lua_bind.c | 9 ++++++++- src/modules.c | 2 ++ 4 files changed, 10 insertions(+), 19 deletions(-) delete mode 100644 lib/mods/theme/scpt/monsters.lua diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua index af299f2c..edc82fe1 100644 --- a/lib/mods/theme/scpt/init.lua +++ b/lib/mods/theme/scpt/init.lua @@ -12,6 +12,3 @@ initialize_bookable_spells() -- Some tests, if the file is not present, this is fine tome_dofile_anywhere(ANGBAND_DIR_SCPT, "dg_test.lua", FALSE) - --- Add monster interaction -tome_dofile("monsters.lua") diff --git a/lib/mods/theme/scpt/monsters.lua b/lib/mods/theme/scpt/monsters.lua deleted file mode 100644 index 0f4c8cda..00000000 --- a/lib/mods/theme/scpt/monsters.lua +++ /dev/null @@ -1,15 +0,0 @@ --- This file holds various things that govern monster behaviour with respect to the player - -add_hooks{ -[HOOK_GAME_START] = function() - - if ((get_race_name() == "Maia") and - (player_has_corruption(CORRUPT_BALROG_AURA) ~= TRUE) and - (player_has_corruption(CORRUPT_BALROG_WINGS) ~= TRUE) and - (player_has_corruption(CORRUPT_BALROG_STRENGTH) ~= TRUE) and - (player_has_corruption(CORRUPT_BALROG_FORM) ~= TRUE)) then - -- "Proper" Maiar aggravate evil beings - timer_aggravate_evil_enable() - end -end, -} diff --git a/src/lua_bind.c b/src/lua_bind.c index 34a89613..ab1a19c8 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -548,7 +548,14 @@ void timer_aggravate_evil_enable() void timer_aggravate_evil_callback() { - dispel_evil(0); + if ((p_ptr->prace == RACE_MAIA) && + (!player_has_corruption(CORRUPT_BALROG_AURA)) && + (!player_has_corruption(CORRUPT_BALROG_WINGS)) && + (!player_has_corruption(CORRUPT_BALROG_STRENGTH)) && + (!player_has_corruption(CORRUPT_BALROG_FORM))) + { + dispel_evil(0); + } } cptr get_spell_info(s32b s) diff --git a/src/modules.c b/src/modules.c index 01f1be00..c4bea6eb 100644 --- a/src/modules.c +++ b/src/modules.c @@ -1152,6 +1152,8 @@ void init_hooks_module() case MODULE_THEME: { + timer_aggravate_evil_enable(); + add_hook_new(HOOK_PLAYER_LEVEL, auto_stat_gain_hook, "auto_stat_gain", -- cgit v1.2.3 From a00ed11376064353475b29c23b6deebc1cc1dfc9 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 11 Jun 2012 20:08:36 +0200 Subject: Lua: Move the last game-specific scripting files to C --- lib/CMakeLists.txt | 1 - lib/core/init.lua | 9 --------- lib/mods/theme/core/init.lua | 9 --------- lib/mods/theme/scpt/init.lua | 14 -------------- lib/scpt/init.lua | 14 -------------- src/script.c | 8 ++++++++ 6 files changed, 8 insertions(+), 47 deletions(-) delete mode 100644 lib/mods/theme/scpt/init.lua delete mode 100644 lib/scpt/init.lua diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index acb87b25..245d98f8 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -17,7 +17,6 @@ INSTALL(DIRECTORY plot pref save - scpt user xtra DESTINATION ${DEFAULT_PATH} diff --git a/lib/core/init.lua b/lib/core/init.lua index 5abc1571..de104e52 100644 --- a/lib/core/init.lua +++ b/lib/core/init.lua @@ -17,15 +17,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "building.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") --------------------------------------------------------------- --------------------------------------------------------------- --------------------------------------------------------------- --------------Here we load the non vital scripts--------------- ------------------------from lib/scpt-------------------------- --------------------------------------------------------------- --------------------------------------------------------------- -tome_dofile("init.lua") - -- The dofile functions for each patch patch_dofile = {} diff --git a/lib/mods/theme/core/init.lua b/lib/mods/theme/core/init.lua index 5abc1571..de104e52 100644 --- a/lib/mods/theme/core/init.lua +++ b/lib/mods/theme/core/init.lua @@ -17,15 +17,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "building.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") --------------------------------------------------------------- --------------------------------------------------------------- --------------------------------------------------------------- --------------Here we load the non vital scripts--------------- ------------------------from lib/scpt-------------------------- --------------------------------------------------------------- --------------------------------------------------------------- -tome_dofile("init.lua") - -- The dofile functions for each patch patch_dofile = {} diff --git a/lib/mods/theme/scpt/init.lua b/lib/mods/theme/scpt/init.lua deleted file mode 100644 index edc82fe1..00000000 --- a/lib/mods/theme/scpt/init.lua +++ /dev/null @@ -1,14 +0,0 @@ --- --- This file is loaded at the initialisation of ToME --- - --- Add the schools of magic -schools_init() -school_spells_init() -init_school_books() - --- Post-spell creation initialization -initialize_bookable_spells() - --- Some tests, if the file is not present, this is fine -tome_dofile_anywhere(ANGBAND_DIR_SCPT, "dg_test.lua", FALSE) diff --git a/lib/scpt/init.lua b/lib/scpt/init.lua deleted file mode 100644 index edc82fe1..00000000 --- a/lib/scpt/init.lua +++ /dev/null @@ -1,14 +0,0 @@ --- --- This file is loaded at the initialisation of ToME --- - --- Add the schools of magic -schools_init() -school_spells_init() -init_school_books() - --- Post-spell creation initialization -initialize_bookable_spells() - --- Some tests, if the file is not present, this is fine -tome_dofile_anywhere(ANGBAND_DIR_SCPT, "dg_test.lua", FALSE) diff --git a/src/script.c b/src/script.c index 4d066a58..9a863146 100644 --- a/src/script.c +++ b/src/script.c @@ -226,6 +226,14 @@ void init_lua_init() /* Load the first lua file */ tome_dofile_anywhere(ANGBAND_DIR_CORE, "init.lua", TRUE); + /* Initialize schooled spells */ + schools_init(); + school_spells_init(); + init_school_books(); + + /* Post-spell creation initialization */ + initialize_bookable_spells(); + /* Finish up the corruptions */ init_corruptions(); } -- cgit v1.2.3 From 4b70bb3c271fc00a4e2246f31747a5020e72a9b2 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 11 Jun 2012 20:12:00 +0200 Subject: Lua: Remove dead building.lua --- lib/core/building.lua | 15 --------------- lib/core/init.lua | 1 - lib/mods/theme/core/building.lua | 15 --------------- lib/mods/theme/core/init.lua | 1 - 4 files changed, 32 deletions(-) delete mode 100644 lib/core/building.lua delete mode 100644 lib/mods/theme/core/building.lua diff --git a/lib/core/building.lua b/lib/core/building.lua deleted file mode 100644 index 8e88888a..00000000 --- a/lib/core/building.lua +++ /dev/null @@ -1,15 +0,0 @@ -__building_actions = {} - -function add_building_action(a) - assert(a.index, "No building action index") - assert(a.action, "No building action action") - __building_actions[a.index] = a.action -end - -function __bact_activate(bact) - if __building_actions[bact] then - return __building_actions[bact]() - end -end - -add_hook_script(HOOK_BUILDING_ACTION, "__bact_activate", "__bact_activate") diff --git a/lib/core/init.lua b/lib/core/init.lua index de104e52..230a07a7 100644 --- a/lib/core/init.lua +++ b/lib/core/init.lua @@ -14,7 +14,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "util.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "player.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "objects.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "building.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") -- The dofile functions for each patch diff --git a/lib/mods/theme/core/building.lua b/lib/mods/theme/core/building.lua deleted file mode 100644 index 8e88888a..00000000 --- a/lib/mods/theme/core/building.lua +++ /dev/null @@ -1,15 +0,0 @@ -__building_actions = {} - -function add_building_action(a) - assert(a.index, "No building action index") - assert(a.action, "No building action action") - __building_actions[a.index] = a.action -end - -function __bact_activate(bact) - if __building_actions[bact] then - return __building_actions[bact]() - end -end - -add_hook_script(HOOK_BUILDING_ACTION, "__bact_activate", "__bact_activate") diff --git a/lib/mods/theme/core/init.lua b/lib/mods/theme/core/init.lua index de104e52..230a07a7 100644 --- a/lib/mods/theme/core/init.lua +++ b/lib/mods/theme/core/init.lua @@ -14,7 +14,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "util.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "player.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "objects.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "building.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") -- The dofile functions for each patch -- cgit v1.2.3 From fe752bb67a2a43c49c3f1b6d25eb646b1f7d9847 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 11 Jun 2012 20:16:03 +0200 Subject: Lua: Remove dead "patches" code --- lib/core/init.lua | 37 ------------------------------------- lib/core/util.lua | 26 -------------------------- lib/mods/theme/core/init.lua | 37 ------------------------------------- lib/mods/theme/core/util.lua | 26 -------------------------- src/cmd4.c | 1 - src/files.c | 1 - 6 files changed, 128 deletions(-) diff --git a/lib/core/init.lua b/lib/core/init.lua index 230a07a7..74486ba2 100644 --- a/lib/core/init.lua +++ b/lib/core/init.lua @@ -16,43 +16,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "objects.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") --- The dofile functions for each patch -patch_dofile = {} - --- Now load patches -function load_patches() - scansubdir(ANGBAND_DIR_PATCH) - for i = 0, scansubdir_max - 1 do - if (scansubdir_result[i + 1] ~= ".") and (scansubdir_result[i + 1] ~= "..") then - local dir = path_build(ANGBAND_DIR_PATCH, scansubdir_result[i + 1]) - local file = path_build(dir, "patch.lua") - if file_exist(file) == TRUE then - patch_init = nil - tome_dofile_anywhere(dir, "patch.lua", TRUE) - unset_safe_globals() - if patch_init == nil then - set_safe_globals() - quit("Patch in "..file.." did not include a patch_init() function") - else - set_safe_globals() - - -- create the dofile function - patch_dofile[scansubdir_result[i + 1]] = function(f) - tome_dofile_anywhere(%dir, f, TRUE) - end - - local name, version = patch_init() - if name == nil or version == nil then - quit("Patch in "..file.." did not return valid name or version.\nIt must return name, version") - end - patch_version(name, version) - end - end - end - end -end -load_patches() - -------------------------------------------------------------- -------------------------------------------------------------- -------------------------------------------------------------- diff --git a/lib/core/util.lua b/lib/core/util.lua index 2d437d61..185c0982 100644 --- a/lib/core/util.lua +++ b/lib/core/util.lua @@ -20,32 +20,6 @@ end set_safe_globals() --- Patch modules -__patch_modules = {} - -function patch_version(name, version) - assert(not __patch_modules[name], "Patch " .. name .. " already loaded!!!") - __patch_modules[name] = version -end - -function patchs_list() - local k, e, first - first = FALSE - for k, e in __patch_modules do - if first == FALSE then print_hook("\n\n [Patch modules]\n") first = TRUE end - print_hook("\n "..k.." version "..e) - end - if first == TRUE then print_hook("\n") end -end - -function patchs_display() - local k, e - for k, e in __patch_modules do - msg_print("Patch: "..k.." version "..e) - end -end - - -- Better hook interface __hooks_list_callback = {} __hooks_list_callback_max = 0 diff --git a/lib/mods/theme/core/init.lua b/lib/mods/theme/core/init.lua index 230a07a7..74486ba2 100644 --- a/lib/mods/theme/core/init.lua +++ b/lib/mods/theme/core/init.lua @@ -16,43 +16,6 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "objects.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") --- The dofile functions for each patch -patch_dofile = {} - --- Now load patches -function load_patches() - scansubdir(ANGBAND_DIR_PATCH) - for i = 0, scansubdir_max - 1 do - if (scansubdir_result[i + 1] ~= ".") and (scansubdir_result[i + 1] ~= "..") then - local dir = path_build(ANGBAND_DIR_PATCH, scansubdir_result[i + 1]) - local file = path_build(dir, "patch.lua") - if file_exist(file) == TRUE then - patch_init = nil - tome_dofile_anywhere(dir, "patch.lua", TRUE) - unset_safe_globals() - if patch_init == nil then - set_safe_globals() - quit("Patch in "..file.." did not include a patch_init() function") - else - set_safe_globals() - - -- create the dofile function - patch_dofile[scansubdir_result[i + 1]] = function(f) - tome_dofile_anywhere(%dir, f, TRUE) - end - - local name, version = patch_init() - if name == nil or version == nil then - quit("Patch in "..file.." did not return valid name or version.\nIt must return name, version") - end - patch_version(name, version) - end - end - end - end -end -load_patches() - -------------------------------------------------------------- -------------------------------------------------------------- -------------------------------------------------------------- diff --git a/lib/mods/theme/core/util.lua b/lib/mods/theme/core/util.lua index 2d437d61..185c0982 100644 --- a/lib/mods/theme/core/util.lua +++ b/lib/mods/theme/core/util.lua @@ -20,32 +20,6 @@ end set_safe_globals() --- Patch modules -__patch_modules = {} - -function patch_version(name, version) - assert(not __patch_modules[name], "Patch " .. name .. " already loaded!!!") - __patch_modules[name] = version -end - -function patchs_list() - local k, e, first - first = FALSE - for k, e in __patch_modules do - if first == FALSE then print_hook("\n\n [Patch modules]\n") first = TRUE end - print_hook("\n "..k.." version "..e) - end - if first == TRUE then print_hook("\n") end -end - -function patchs_display() - local k, e - for k, e in __patch_modules do - msg_print("Patch: "..k.." version "..e) - end -end - - -- Better hook interface __hooks_list_callback = {} __hooks_list_callback_max = 0 diff --git a/src/cmd4.c b/src/cmd4.c index fd57a9b5..0c1d28a7 100644 --- a/src/cmd4.c +++ b/src/cmd4.c @@ -2810,7 +2810,6 @@ void do_cmd_version(void) get_version_string(), modules[game_module_idx].meta.author.name, modules[game_module_idx].meta.author.email); - call_lua("patchs_display", "()", ""); } diff --git a/src/files.c b/src/files.c index f860e809..10617f74 100644 --- a/src/files.c +++ b/src/files.c @@ -2618,7 +2618,6 @@ errr file_character(cptr name, bool_ full) /* List the patches */ hook_file = fff; - exec_lua("patchs_list()"); fprintf(fff, "\n\n [Miscellaneous information]\n"); if (joke_monsters) -- cgit v1.2.3 From f9df262f44fe8b971813d9f136d8a6c6f44a0251 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 11 Jun 2012 20:26:42 +0200 Subject: Lua: Remove dead load/save code --- lib/core/init.lua | 11 -------- lib/core/load.lua | 37 -------------------------- lib/core/load2.lua | 56 -------------------------------------- lib/mods/theme/core/init.lua | 11 -------- lib/mods/theme/core/load.lua | 37 -------------------------- lib/mods/theme/core/load2.lua | 56 -------------------------------------- src/externs.h | 3 --- src/loadsave.c | 62 ------------------------------------------- src/util.pkg | 21 --------------- 9 files changed, 294 deletions(-) delete mode 100644 lib/core/load.lua delete mode 100644 lib/core/load2.lua delete mode 100644 lib/mods/theme/core/load.lua delete mode 100644 lib/mods/theme/core/load2.lua diff --git a/lib/core/init.lua b/lib/core/init.lua index 74486ba2..be3d40a3 100644 --- a/lib/core/init.lua +++ b/lib/core/init.lua @@ -3,9 +3,6 @@ -- Load the system functions -- --- Name of globals to save -tome_dofile_anywhere(ANGBAND_DIR_CORE, "load.lua") - -- Very thin xml parser(49 lines ;) tome_dofile_anywhere(ANGBAND_DIR_CORE, "xml.lua") @@ -15,11 +12,3 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "player.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "objects.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") - --------------------------------------------------------------- --------------------------------------------------------------- --------------------------------------------------------------- --- --- Do not thouch after this line --- -tome_dofile_anywhere(ANGBAND_DIR_CORE, "load2.lua") diff --git a/lib/core/load.lua b/lib/core/load.lua deleted file mode 100644 index 9522ec91..00000000 --- a/lib/core/load.lua +++ /dev/null @@ -1,37 +0,0 @@ --- Savefile stuff --- Do not meddle in the affairs of savefiles for they are subtle and quick to be become incompatible - -__loadsave_name = {} -__loadsave_max = 0 -__loadsave_tmp = 0 - -function add_loadsave(name, default) - assert(name, "No variable name to save") - assert(default, "No default value") - - -- if it is a table we must create many entries - if type(default) == "table" then - for k, e in default do - add_loadsave(name.."."..k, e) - end - else - __loadsave_name[__loadsave_max] = { name = name, default = default } - __loadsave_max = __loadsave_max + 1 - end -end - --- Example of how to save a table --- NOTE: { 1, 2, 3 } will NOT work, the key MUST be a string ---[[ -add_loadsave("t", -{ - foo = 7, - tab = { - a = 1, - b = 2, - tab = { - a=1, b=2, c=3, - }, - }, -}) -]] diff --git a/lib/core/load2.lua b/lib/core/load2.lua deleted file mode 100644 index 7e151d91..00000000 --- a/lib/core/load2.lua +++ /dev/null @@ -1,56 +0,0 @@ --- Savefile helpers - --- function called when a key in the variable part ofthe savefile is read --- if the key matches what we need, we use it, otehrwise just ignore it -function __savefile_load(key, val) - local index, elem - - for index, elem in __loadsave_name do - if (key == elem.name) then - dostring(elem.name.." = "..val) - end - end -end - --- called when the game is saved, can only save numbers --- assosiate a key with them to allow the loading code to recognize them -function __savefile_save() - local index, elem - for index, elem in __loadsave_name do - dostring("__loadsave_tmp = "..elem.name) - save_number_key(elem.name, __loadsave_tmp); - end -end - -register_savefile(__loadsave_max) -add_hook_script(HOOK_LOAD_GAME, "__savefile_load", "__hook_load") -add_hook_script(HOOK_SAVE_GAME, "__savefile_save", "__hook_save") - --- Parse a flattened(i.e: foo.bar.zog) table path and recrate tables -function reconstruct_table(name) - for i = 1, strlen(name) - 1 do - if strsub(name, i, i) == "." then - local tbl = strsub(name, 1, i - 1) - - if dostring("return "..tbl) == nil then - dostring(tbl.."={}") - end - end - end -end - --- Automagically set unkown variables, otherwise the savefile code --- might get VERY upset -do - local k, e - -- We need to be able to check for unknown globals - unset_safe_globals() - for k, e in __loadsave_name do - reconstruct_table(e.name) - if dostring("return "..(e.name)) == nil then - dostring((e.name).." = "..(e.default)) - end - end - -- Now taht we did, we set it back, for it is usefull ;) - set_safe_globals() -end diff --git a/lib/mods/theme/core/init.lua b/lib/mods/theme/core/init.lua index 74486ba2..be3d40a3 100644 --- a/lib/mods/theme/core/init.lua +++ b/lib/mods/theme/core/init.lua @@ -3,9 +3,6 @@ -- Load the system functions -- --- Name of globals to save -tome_dofile_anywhere(ANGBAND_DIR_CORE, "load.lua") - -- Very thin xml parser(49 lines ;) tome_dofile_anywhere(ANGBAND_DIR_CORE, "xml.lua") @@ -15,11 +12,3 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "player.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "objects.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") - --------------------------------------------------------------- --------------------------------------------------------------- --------------------------------------------------------------- --- --- Do not thouch after this line --- -tome_dofile_anywhere(ANGBAND_DIR_CORE, "load2.lua") diff --git a/lib/mods/theme/core/load.lua b/lib/mods/theme/core/load.lua deleted file mode 100644 index 9522ec91..00000000 --- a/lib/mods/theme/core/load.lua +++ /dev/null @@ -1,37 +0,0 @@ --- Savefile stuff --- Do not meddle in the affairs of savefiles for they are subtle and quick to be become incompatible - -__loadsave_name = {} -__loadsave_max = 0 -__loadsave_tmp = 0 - -function add_loadsave(name, default) - assert(name, "No variable name to save") - assert(default, "No default value") - - -- if it is a table we must create many entries - if type(default) == "table" then - for k, e in default do - add_loadsave(name.."."..k, e) - end - else - __loadsave_name[__loadsave_max] = { name = name, default = default } - __loadsave_max = __loadsave_max + 1 - end -end - --- Example of how to save a table --- NOTE: { 1, 2, 3 } will NOT work, the key MUST be a string ---[[ -add_loadsave("t", -{ - foo = 7, - tab = { - a = 1, - b = 2, - tab = { - a=1, b=2, c=3, - }, - }, -}) -]] diff --git a/lib/mods/theme/core/load2.lua b/lib/mods/theme/core/load2.lua deleted file mode 100644 index 7e151d91..00000000 --- a/lib/mods/theme/core/load2.lua +++ /dev/null @@ -1,56 +0,0 @@ --- Savefile helpers - --- function called when a key in the variable part ofthe savefile is read --- if the key matches what we need, we use it, otehrwise just ignore it -function __savefile_load(key, val) - local index, elem - - for index, elem in __loadsave_name do - if (key == elem.name) then - dostring(elem.name.." = "..val) - end - end -end - --- called when the game is saved, can only save numbers --- assosiate a key with them to allow the loading code to recognize them -function __savefile_save() - local index, elem - for index, elem in __loadsave_name do - dostring("__loadsave_tmp = "..elem.name) - save_number_key(elem.name, __loadsave_tmp); - end -end - -register_savefile(__loadsave_max) -add_hook_script(HOOK_LOAD_GAME, "__savefile_load", "__hook_load") -add_hook_script(HOOK_SAVE_GAME, "__savefile_save", "__hook_save") - --- Parse a flattened(i.e: foo.bar.zog) table path and recrate tables -function reconstruct_table(name) - for i = 1, strlen(name) - 1 do - if strsub(name, i, i) == "." then - local tbl = strsub(name, 1, i - 1) - - if dostring("return "..tbl) == nil then - dostring(tbl.."={}") - end - end - end -end - --- Automagically set unkown variables, otherwise the savefile code --- might get VERY upset -do - local k, e - -- We need to be able to check for unknown globals - unset_safe_globals() - for k, e in __loadsave_name do - reconstruct_table(e.name) - if dostring("return "..(e.name)) == nil then - dostring((e.name).." = "..(e.default)) - end - end - -- Now taht we did, we set it back, for it is usefull ;) - set_safe_globals() -end diff --git a/src/externs.h b/src/externs.h index dc449cb1..2c996223 100644 --- a/src/externs.h +++ b/src/externs.h @@ -994,7 +994,6 @@ extern u32b fake_text_size; extern bool_ gen_joke_monsters(void *data, void *in, void *out); /* loadsave.c */ -extern void register_savefile(int num); extern bool_ file_exist(char *buf); extern s16b rd_variable(void); extern void wr_variable(s16b *var); @@ -1004,8 +1003,6 @@ extern void save_dungeon(void); extern bool_ save_player(void); extern bool_ load_player(void); extern errr rd_savefile_new(void); -extern void load_number_key(char *key, u32b *val); -extern void save_number_key(char *key, u32b val); /* melee1.c */ /* melee2.c */ diff --git a/src/loadsave.c b/src/loadsave.c index 65d72d9c..dcdcaae9 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -2954,31 +2954,6 @@ static bool_ do_savefile_aux(int flag) C_FREE(reals, max_towns, bool_); - if (flag == LS_SAVE) tmp32u = extra_savefile_parts; - do_u32b(&tmp32u, flag); - if (flag == LS_SAVE) - { - /* Save the stuff */ - process_hooks(HOOK_SAVE_GAME, "()"); - } - - if (flag == LS_LOAD) - { - u32b len = tmp32u; - - while (len) - { - char key_buf[100]; - - /* Load a key */ - load_number_key(key_buf, &tmp32u); - - /* Process it -- the hooks can use it or ignore it */ - process_hooks(HOOK_LOAD_GAME, "(s,l)", key_buf, tmp32u); - len--; - } - } - /* I'm not dead yet... */ if (!death) { @@ -3294,40 +3269,3 @@ static void my_sentinel(char *place, u16b value, int flag) note(format("Impossible has occurred")); /* Programmer error */ exit(0); } - -/********** Variable savefile stuff **************/ - -/* - * Add num slots to the savefile - */ -void register_savefile(int num) -{ - extra_savefile_parts += (num > 0) ? num : 0; -} - -void save_number_key(char *key, u32b val) -{ - byte len = strlen(key); - - do_byte(&len, LS_SAVE); - while (*key) - { - do_byte((byte*)key, LS_SAVE); - key++; - } - do_u32b(&val, LS_SAVE); -} - -void load_number_key(char *key, u32b *val) -{ - byte len, i = 0; - - do_byte(&len, LS_LOAD); - while (i < len) - { - do_byte((byte*)&key[i], LS_LOAD); - i++; - } - key[i] = '\0'; - do_u32b(val, LS_LOAD); -} diff --git a/src/util.pkg b/src/util.pkg index 33f60a59..1412e66b 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -1369,27 +1369,6 @@ extern cptr string_exec_lua(char *file); */ extern void lua_print_hook@print_hook(cptr str); -/* Savefile stuff */ -/** @fn register_savefile(int num) - * @brief Add "num" slots to the savefile.\n - * @param num Number \n the number of slots to add. - * @brief Slots - * @note (see file loadsave.c) - */ -extern void register_savefile(int num); - -/** @fn save_number_key(char *key, s32b val) - * @brief Save a key-value combination in the save file.\n - * @param *key String \n the key to save. - * @brief Key - * @param val Number \n the value of the key. - * @brief Value - * @note - * The length of the key is stored first, then the key, then the value. - * @note (see file loadsave.c) - */ -extern void save_number_key(char *key, s32b val); - /* Tables */ /** @var adj_mag_study[100] -- cgit v1.2.3 From c6323f4a7db11a34ef0767c629364ca5474b55f1 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 11 Jun 2012 20:28:52 +0200 Subject: Lua: Remove dead 'dungeon.lua' --- lib/core/dungeon.lua | 9 --------- lib/core/init.lua | 1 - lib/mods/theme/core/dungeon.lua | 9 --------- lib/mods/theme/core/init.lua | 1 - 4 files changed, 20 deletions(-) delete mode 100644 lib/core/dungeon.lua delete mode 100644 lib/mods/theme/core/dungeon.lua diff --git a/lib/core/dungeon.lua b/lib/core/dungeon.lua deleted file mode 100644 index 13030eac..00000000 --- a/lib/core/dungeon.lua +++ /dev/null @@ -1,9 +0,0 @@ --- Internal lua file in charge of dungeon stuff - -function dungeon(d_idx) - return d_info[1 + d_idx] -end - -function explode_dir(dir) - return ddy[dir + 1], ddx[dir + 1] -end diff --git a/lib/core/init.lua b/lib/core/init.lua index be3d40a3..4df54799 100644 --- a/lib/core/init.lua +++ b/lib/core/init.lua @@ -11,4 +11,3 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "util.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "player.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "objects.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") diff --git a/lib/mods/theme/core/dungeon.lua b/lib/mods/theme/core/dungeon.lua deleted file mode 100644 index 13030eac..00000000 --- a/lib/mods/theme/core/dungeon.lua +++ /dev/null @@ -1,9 +0,0 @@ --- Internal lua file in charge of dungeon stuff - -function dungeon(d_idx) - return d_info[1 + d_idx] -end - -function explode_dir(dir) - return ddy[dir + 1], ddx[dir + 1] -end diff --git a/lib/mods/theme/core/init.lua b/lib/mods/theme/core/init.lua index be3d40a3..4df54799 100644 --- a/lib/mods/theme/core/init.lua +++ b/lib/mods/theme/core/init.lua @@ -11,4 +11,3 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "util.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "player.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "objects.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "dungeon.lua") -- cgit v1.2.3 From abe6d2ebc42ba47c989e8065b14ead870d118dae Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 11 Jun 2012 20:30:25 +0200 Subject: Lua: Remove dead 'monsters.lua' --- lib/core/init.lua | 1 - lib/core/monsters.lua | 16 ---------------- lib/mods/theme/core/init.lua | 1 - lib/mods/theme/core/monsters.lua | 16 ---------------- 4 files changed, 34 deletions(-) delete mode 100644 lib/core/monsters.lua delete mode 100644 lib/mods/theme/core/monsters.lua diff --git a/lib/core/init.lua b/lib/core/init.lua index 4df54799..51dfc1d2 100644 --- a/lib/core/init.lua +++ b/lib/core/init.lua @@ -10,4 +10,3 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "xml.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "util.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "player.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "objects.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") diff --git a/lib/core/monsters.lua b/lib/core/monsters.lua deleted file mode 100644 index ca2851a0..00000000 --- a/lib/core/monsters.lua +++ /dev/null @@ -1,16 +0,0 @@ --- SYSTEM FILE --- --- Monster stuff, do not touch --- - -function summon_monster(y, x, lev, friend, typ) - if type(typ) == "number" then - if friend == TRUE then - return summon_specific_friendly(y, x, lev, typ, FALSE) - else - return summon_specific(y, x, lev, typ) - end - else - return summon_monster_aux(y, x, lev, friend, typ) - end -end diff --git a/lib/mods/theme/core/init.lua b/lib/mods/theme/core/init.lua index 4df54799..51dfc1d2 100644 --- a/lib/mods/theme/core/init.lua +++ b/lib/mods/theme/core/init.lua @@ -10,4 +10,3 @@ tome_dofile_anywhere(ANGBAND_DIR_CORE, "xml.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "util.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "player.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "objects.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "monsters.lua") diff --git a/lib/mods/theme/core/monsters.lua b/lib/mods/theme/core/monsters.lua deleted file mode 100644 index ca2851a0..00000000 --- a/lib/mods/theme/core/monsters.lua +++ /dev/null @@ -1,16 +0,0 @@ --- SYSTEM FILE --- --- Monster stuff, do not touch --- - -function summon_monster(y, x, lev, friend, typ) - if type(typ) == "number" then - if friend == TRUE then - return summon_specific_friendly(y, x, lev, typ, FALSE) - else - return summon_specific(y, x, lev, typ) - end - else - return summon_monster_aux(y, x, lev, friend, typ) - end -end -- cgit v1.2.3 From b9894d348db43cacb2807c325fb48d8d46e84985 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 11 Jun 2012 20:39:06 +0200 Subject: Lua: Remove dead object & summoning code --- lib/core/objects.lua | 37 ------------------------------ lib/mods/theme/core/objects.lua | 37 ------------------------------ src/defines.h | 1 - src/externs.h | 2 -- src/lua_bind.c | 51 ----------------------------------------- src/monster.pkg | 23 ------------------- src/monster2.c | 5 ---- src/object.pkg | 2 -- 8 files changed, 158 deletions(-) diff --git a/lib/core/objects.lua b/lib/core/objects.lua index 97320b82..fa77c57b 100644 --- a/lib/core/objects.lua +++ b/lib/core/objects.lua @@ -3,43 +3,6 @@ -- Lua object funtions -- -function create_object(tval, sval) - local obj = new_object() - object_prep(obj, lookup_kind(tval, sval)) - return (obj) -end - -function set_item_tester(tester) - if tolua.type(tester) == "number" then - lua_set_item_tester(tester, "") - end - if tolua.type(tester) == "string" then - lua_set_item_tester(0, tester) - end - if tolua.type(tester) == "function" then - __get_item_hook_default = tester - lua_set_item_tester(0, "__get_item_hook_default") - end -end - -function create_artifact(a_idx) - local obj - local tval, sval - - tval = a_info[a_idx + 1].tval - sval = a_info[a_idx + 1].sval - obj = create_object(tval, sval) - obj.name1 = a_idx - apply_magic(obj, -1, TRUE, TRUE, TRUE) - - return (obj) -end - function get_kind(obj) return k_info[obj.k_idx + 1] end - -function get_item(ask, deny, flags, mask) - set_item_tester(mask) - return get_item_aux(0, ask, deny, flags) -end diff --git a/lib/mods/theme/core/objects.lua b/lib/mods/theme/core/objects.lua index 97320b82..fa77c57b 100644 --- a/lib/mods/theme/core/objects.lua +++ b/lib/mods/theme/core/objects.lua @@ -3,43 +3,6 @@ -- Lua object funtions -- -function create_object(tval, sval) - local obj = new_object() - object_prep(obj, lookup_kind(tval, sval)) - return (obj) -end - -function set_item_tester(tester) - if tolua.type(tester) == "number" then - lua_set_item_tester(tester, "") - end - if tolua.type(tester) == "string" then - lua_set_item_tester(0, tester) - end - if tolua.type(tester) == "function" then - __get_item_hook_default = tester - lua_set_item_tester(0, "__get_item_hook_default") - end -end - -function create_artifact(a_idx) - local obj - local tval, sval - - tval = a_info[a_idx + 1].tval - sval = a_info[a_idx + 1].sval - obj = create_object(tval, sval) - obj.name1 = a_idx - apply_magic(obj, -1, TRUE, TRUE, TRUE) - - return (obj) -end - function get_kind(obj) return k_info[obj.k_idx + 1] end - -function get_item(ask, deny, flags, mask) - set_item_tester(mask) - return get_item_aux(0, ask, deny, flags) -end diff --git a/src/defines.h b/src/defines.h index 7e4321a1..6fa426c7 100644 --- a/src/defines.h +++ b/src/defines.h @@ -2582,7 +2582,6 @@ #define SUMMON_SHADOWS 55 #define SUMMON_GHOST 56 #define SUMMON_QUYLTHULG 57 -#define SUMMON_LUA 58 /* diff --git a/src/externs.h b/src/externs.h index 2c996223..d4d7d140 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2379,8 +2379,6 @@ extern char *lua_object_desc(object_type *o_ptr, int pref, int mode); extern s16b add_new_power(cptr name, cptr desc, cptr gain, cptr lose, byte level, byte cost, byte stat, byte diff); extern void find_position(int y, int x, int *yy, int *xx); -extern bool_ summon_lua_okay(int r_idx); -extern bool_ lua_summon_monster(int y, int x, int lev, bool_ ffriend, char *fct); extern s16b add_new_gods(char *name); extern int get_lua_int(cptr name); diff --git a/src/lua_bind.c b/src/lua_bind.c index ab1a19c8..4ae8ed80 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -82,33 +82,6 @@ void end_object(object_type *o_ptr) FREE(o_ptr, object_type); } -static char *lua_item_tester_fct; -static bool_ lua_item_tester(object_type* o_ptr) -{ - int oldtop = lua_gettop(L); - bool_ ret; - - lua_getglobal(L, lua_item_tester_fct); - tolua_pushusertype(L, o_ptr, tolua_tag(L, "object_type")); - lua_call(L, 1, 1); - ret = lua_tonumber(L, -1); - lua_settop(L, oldtop); - return (ret); -} - -void lua_set_item_tester(int tval, char *fct) -{ - if (tval) - { - item_tester_tval = tval; - } - else - { - lua_item_tester_fct = fct; - item_tester_hook = lua_item_tester; - } -} - char *lua_object_desc(object_type *o_ptr, int pref, int mode) { static char buf[150]; @@ -132,30 +105,6 @@ void find_position(int y, int x, int *yy, int *xx) while (!(in_bounds(*yy, *xx) && cave_floor_bold(*yy, *xx)) && --attempts); } -static char *summon_lua_okay_fct; -bool_ summon_lua_okay(int r_idx) -{ - int oldtop = lua_gettop(L); - bool_ ret; - - lua_getglobal(L, lua_item_tester_fct); - tolua_pushnumber(L, r_idx); - lua_call(L, 1, 1); - ret = lua_tonumber(L, -1); - lua_settop(L, oldtop); - return (ret); -} - -bool_ lua_summon_monster(int y, int x, int lev, bool_ friend_, char *fct) -{ - summon_lua_okay_fct = fct; - - if (!friend_) - return summon_specific(y, x, lev, SUMMON_LUA); - else - return summon_specific_friendly(y, x, lev, SUMMON_LUA, TRUE); -} - /* * Misc */ diff --git a/src/monster.pkg b/src/monster.pkg index a9efd089..bf0f4661 100644 --- a/src/monster.pkg +++ b/src/monster.pkg @@ -2062,25 +2062,6 @@ extern bool summon_specific(int y1, int x1, int lev, int type); */ extern bool summon_specific_friendly(int y1, int x1, int lev, int type, bool Group_ok); -/** @fn summon_monster_aux(int y, int x, int lev, bool friend, char *fct); - * @brief Place a monster near grid "y","x".\n - * @param y Number \n the y coordinate of the target grid - * @brief Y-coordinate - * @param x Number \n the x coordinate of the target grid - * @brief X-coordinate - * @param lev Number \n the monster level of the summoning monster - * @brief Summoner level - * @param friend Boolean \n TRUE if friendly monsters are to be summoned, - * otherwise FALSE - * @brief Friendly? - * @param *fct String \n the function which determines which type of monster - * will be summoned - * @brief Monster type function - * @return Boolean \n TRUE if a monster was summoned, otherwise FALSE. - * @note (see file w_mnster.c) - */ -extern bool lua_summon_monster @ summon_monster_aux(int y, int x, int lev, bool friend, char *fct); - /** @fn can_create_companion() * @brief Determine if a companion can be created. * @return Boolean \n TRUE if a companion can be created, otherwise FALSE. @@ -2300,10 +2281,6 @@ extern void monster_set_level(int m_idx, int level); */ #define SUMMON_QUYLTHULG 57 -/** @def SUMMON_LUA - * @note Summon monsters according to a Lua script. - */ -#define SUMMON_LUA 58 /** @} */ /** @fn do_control_reconnect() diff --git a/src/monster2.c b/src/monster2.c index cdef75d4..e9ae164e 100644 --- a/src/monster2.c +++ b/src/monster2.c @@ -3355,11 +3355,6 @@ bool_ summon_specific_okay(int r_idx) break; } - case SUMMON_LUA: - { - okay = summon_lua_okay(r_idx); - break; - } } /* Result */ diff --git a/src/object.pkg b/src/object.pkg index 4859e35b..05ea9c1a 100644 --- a/src/object.pkg +++ b/src/object.pkg @@ -1130,8 +1130,6 @@ extern s16b drop_near(object_type *o_ptr, int chance, int y, int x); extern object_type *get_object(int item); extern object_type *new_object(); extern void end_object(object_type *o_ptr); -extern bool get_item @ get_item_aux(int *cp, cptr pmt, cptr str, int mode); -extern void lua_set_item_tester(int tval, char *fct); extern void identify_pack_fully(void); extern s16b inven_carry(object_type *o_ptr, bool final); extern s32b calc_total_weight(void); -- cgit v1.2.3 From f71485a5448f1e978101f9033f34875a96c88880 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 11 Jun 2012 20:43:12 +0200 Subject: Lua: Move increase_mana() to C --- lib/core/player.lua | 15 --------------- lib/mods/theme/core/player.lua | 15 --------------- src/lua_bind.c | 14 +++++++++++--- 3 files changed, 11 insertions(+), 33 deletions(-) diff --git a/lib/core/player.lua b/lib/core/player.lua index f5c7c13b..65406de2 100644 --- a/lib/core/player.lua +++ b/lib/core/player.lua @@ -30,21 +30,6 @@ function player.inventory(i) return player.inventory_real[i + 1] end --- modify mana --- returns TRUE if there is a pb -function increase_mana(amt) - player.csp = player.csp + amt - player.redraw = bor(player.redraw, PR_MANA) - if (player.csp < 0) then - player.csp = 0 - return TRUE - end - if (player.csp > player.msp) then - player.csp = player.msp - end - return FALSE -end - -- Return the coordinates of the player whether in wild or not function player.get_wild_coord() diff --git a/lib/mods/theme/core/player.lua b/lib/mods/theme/core/player.lua index f5c7c13b..65406de2 100644 --- a/lib/mods/theme/core/player.lua +++ b/lib/mods/theme/core/player.lua @@ -30,21 +30,6 @@ function player.inventory(i) return player.inventory_real[i + 1] end --- modify mana --- returns TRUE if there is a pb -function increase_mana(amt) - player.csp = player.csp + amt - player.redraw = bor(player.redraw, PR_MANA) - if (player.csp < 0) then - player.csp = 0 - return TRUE - end - if (player.csp > player.msp) then - player.csp = player.msp - end - return FALSE -end - -- Return the coordinates of the player whether in wild or not function player.get_wild_coord() diff --git a/src/lua_bind.c b/src/lua_bind.c index 4ae8ed80..0f41f9dc 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -483,9 +483,17 @@ int get_lua_list_size(cptr list_var) void increase_mana(int delta) { - char buf[256]; - sprintf(buf, "increase_mana(%d)", delta); - exec_lua(buf); + p_ptr->csp += delta; + p_ptr->redraw |= PR_MANA; + + if (p_ptr->csp < 0) + { + p_ptr->csp = 0; + } + if (p_ptr->csp > p_ptr->msp) + { + p_ptr->csp = p_ptr->msp; + } } timer_type *TIMER_AGGRAVATE_EVIL = 0; -- cgit v1.2.3 From 4dfd1e9255f421093ecf444fff7c76a9434d8fe1 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 11 Jun 2012 20:44:03 +0200 Subject: Lua: Remove dead code from 'player.lua' --- lib/core/player.lua | 31 ------------------------------- lib/mods/theme/core/player.lua | 31 ------------------------------- 2 files changed, 62 deletions(-) diff --git a/lib/core/player.lua b/lib/core/player.lua index 65406de2..deec2e21 100644 --- a/lib/core/player.lua +++ b/lib/core/player.lua @@ -10,38 +10,7 @@ function skill(i) return s_info[i + 1] end --- Sart a lasting spell -function player.start_lasting_spell(spl) - player.music_extra = -spl -end - --- stat mods -function player.modify_stat(stat, inc) - player.stat_add[1 + stat] = player.stat_add[1 + stat] + inc -end - --- powers mods -function player.add_power(pow) - player.powers[1 + pow] = TRUE -end - -- easier inventory access function player.inventory(i) return player.inventory_real[i + 1] end - - --- Return the coordinates of the player whether in wild or not -function player.get_wild_coord() - if player.wild_mode == TRUE then - return player.py, player.px - else - return player.wilderness_y, player.wilderness_x - end -end - - --- Subraces -function subrace(racem) - return race_mod_info[racem + 1] -end diff --git a/lib/mods/theme/core/player.lua b/lib/mods/theme/core/player.lua index 65406de2..deec2e21 100644 --- a/lib/mods/theme/core/player.lua +++ b/lib/mods/theme/core/player.lua @@ -10,38 +10,7 @@ function skill(i) return s_info[i + 1] end --- Sart a lasting spell -function player.start_lasting_spell(spl) - player.music_extra = -spl -end - --- stat mods -function player.modify_stat(stat, inc) - player.stat_add[1 + stat] = player.stat_add[1 + stat] + inc -end - --- powers mods -function player.add_power(pow) - player.powers[1 + pow] = TRUE -end - -- easier inventory access function player.inventory(i) return player.inventory_real[i + 1] end - - --- Return the coordinates of the player whether in wild or not -function player.get_wild_coord() - if player.wild_mode == TRUE then - return player.py, player.px - else - return player.wilderness_y, player.wilderness_x - end -end - - --- Subraces -function subrace(racem) - return race_mod_info[racem + 1] -end -- cgit v1.2.3 From 243116ee1e4a8414f759837412b3087ac3f8321b Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 11 Jun 2012 20:51:36 +0200 Subject: Lua: Remove dead code from 'util.lua' --- lib/core/util.lua | 57 -------------------------------- lib/mods/theme/core/util.lua | 57 -------------------------------- src/externs.h | 1 - src/lua_bind.c | 31 ------------------ src/util.pkg | 78 -------------------------------------------- 5 files changed, 224 deletions(-) diff --git a/lib/core/util.lua b/lib/core/util.lua index 185c0982..c3387401 100644 --- a/lib/core/util.lua +++ b/lib/core/util.lua @@ -20,21 +20,6 @@ end set_safe_globals() --- Better hook interface -__hooks_list_callback = {} -__hooks_list_callback_max = 0 - -function add_hooks(h_table, name_prefix) - local k, e - - if not name_prefix then name_prefix = "" end - for k, e in h_table do - add_hook_script(k, "__"..name_prefix.."__hooks_list_callback"..__hooks_list_callback_max, "__"..name_prefix.."__hooks_list_callback"..__hooks_list_callback_max) - setglobal("__"..name_prefix.."__hooks_list_callback"..__hooks_list_callback_max, e) - __hooks_list_callback_max = __hooks_list_callback_max + 1 - end -end - -- Wrapper for the real msg_print and cmsg_print -- it understands if we want color or not function msg_print(c, m) @@ -46,49 +31,7 @@ function msg_print(c, m) end --- displays a scrolling list -function display_list(y, x, h, w, title, list, begin, sel, sel_color) - local l = create_list(getn(list)) - - for i = 1, getn(list) do - add_to_list(l, i - 1, list[i]) - end - - %display_list(y, x, h, w, title, l, getn(list), begin - 1, sel - 1, sel_color) - - delete_list(l, getn(list)) -end - --- Easier access to special gene stuff -function set_monster_generation(monster, state) - if type(monster) == "string" then - m_allow_special[test_monster_name(monster) + 1] = state - else - m_allow_special[monster + 1] = state - end -end -function set_object_generation(obj, state) - if type(obj) == "string" then - m_allow_special[test_item_name(obj) + 1] = state - else - m_allow_special[obj + 1] = state - end -end -function set_artifact_generation(obj, state) - m_allow_special[obj + 1] = state -end - -- Strings -function strcap(str) - if strlen(str) > 1 then - return strupper(strsub(str, 1, 1))..strsub(str, 2) - elseif strlen(str) == 1 then - return strupper(str) - else - return str - end -end - function msg_format(...) msg_print(call(format, arg)) end diff --git a/lib/mods/theme/core/util.lua b/lib/mods/theme/core/util.lua index 185c0982..c3387401 100644 --- a/lib/mods/theme/core/util.lua +++ b/lib/mods/theme/core/util.lua @@ -20,21 +20,6 @@ end set_safe_globals() --- Better hook interface -__hooks_list_callback = {} -__hooks_list_callback_max = 0 - -function add_hooks(h_table, name_prefix) - local k, e - - if not name_prefix then name_prefix = "" end - for k, e in h_table do - add_hook_script(k, "__"..name_prefix.."__hooks_list_callback"..__hooks_list_callback_max, "__"..name_prefix.."__hooks_list_callback"..__hooks_list_callback_max) - setglobal("__"..name_prefix.."__hooks_list_callback"..__hooks_list_callback_max, e) - __hooks_list_callback_max = __hooks_list_callback_max + 1 - end -end - -- Wrapper for the real msg_print and cmsg_print -- it understands if we want color or not function msg_print(c, m) @@ -46,49 +31,7 @@ function msg_print(c, m) end --- displays a scrolling list -function display_list(y, x, h, w, title, list, begin, sel, sel_color) - local l = create_list(getn(list)) - - for i = 1, getn(list) do - add_to_list(l, i - 1, list[i]) - end - - %display_list(y, x, h, w, title, l, getn(list), begin - 1, sel - 1, sel_color) - - delete_list(l, getn(list)) -end - --- Easier access to special gene stuff -function set_monster_generation(monster, state) - if type(monster) == "string" then - m_allow_special[test_monster_name(monster) + 1] = state - else - m_allow_special[monster + 1] = state - end -end -function set_object_generation(obj, state) - if type(obj) == "string" then - m_allow_special[test_item_name(obj) + 1] = state - else - m_allow_special[obj + 1] = state - end -end -function set_artifact_generation(obj, state) - m_allow_special[obj + 1] = state -end - -- Strings -function strcap(str) - if strlen(str) > 1 then - return strupper(strsub(str, 1, 1))..strsub(str, 2) - elseif strlen(str) == 1 then - return strupper(str) - else - return str - end -end - function msg_format(...) msg_print(call(format, arg)) end diff --git a/src/externs.h b/src/externs.h index d4d7d140..46a4cf2b 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2417,7 +2417,6 @@ extern char lua_msg_box(cptr title); extern list_type *lua_create_list(int size); extern void lua_delete_list(list_type *, int size); extern void lua_add_to_list(list_type *, int idx, cptr str); -extern void lua_display_list(int y, int x, int h, int w, cptr title, list_type *list, int max, int begin, int sel, byte sel_color); extern void increase_mana(int delta); diff --git a/src/lua_bind.c b/src/lua_bind.c index 0f41f9dc..5a3806d8 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -434,37 +434,6 @@ char lua_msg_box(cptr title) return msg_box(title, hgt / 2, wid / 2); } -list_type *lua_create_list(int size) -{ - list_type *l; - cptr *list; - - MAKE(l, list_type); - C_MAKE(list, size, cptr); - l->list = list; - return l; -} - -void lua_delete_list(list_type *l, int size) -{ - int i; - - for (i = 0; i < size; i++) - string_free(l->list[i]); - C_FREE(l->list, size, cptr); - FREE(l, list_type); -} - -void lua_add_to_list(list_type *l, int idx, cptr str) -{ - l->list[idx] = string_make(str); -} - -void lua_display_list(int y, int x, int h, int w, cptr title, list_type* list, int max, int begin, int sel, byte sel_color) -{ - display_list(y, x, h, w, title, list->list, max, begin, sel, sel_color); -} - int get_lua_int(cptr name) diff --git a/src/util.pkg b/src/util.pkg index 1412e66b..196aabda 100644 --- a/src/util.pkg +++ b/src/util.pkg @@ -2229,84 +2229,6 @@ extern cptr game_module; */ extern int get_keymap_dir(char ch); -/* - * Lists - */ -/** @struct list_type - */ -struct list_type -{ -}; - -/** @fn create_list(int size); - * @dgonly - * @brief Create an empty list big enough to store "size" strings.\n - * @param size Number \n the number of strings the list will hold. - * @brief List size - * @return list_type \n The empty list. - * @note (see file lua_bind.c) - */ -extern list_type *lua_create_list@create_list(int size); - -/** @fn delete_list(list_type *, int size); - * @dgonly - * @brief Delete the list of strings.\n - * @param * list_type \n the list of strings. - * @brief List - * @param size Number \n the number of strings the list holds. - * @brief List size - * @note - * All the strings in the list are deleted first, then the list is deleted. - * @note (see file lua_bind.c) - */ -extern void lua_delete_list@delete_list(list_type *, int size); - -/** @fn add_to_list(list_type *, int idx, cptr str); - * @dgonly - * @brief Add string "str" to list in position "idx".\n - * @param * list_type \n the list of strings. - * @brief List - * @param idx Number \n the index of the list where the string will be added. - * @brief Index - * @param str String \n the string to be added. - * @brief String - * @note - * Too bad if there was something in that position already. - * You have been warned. - * @note (see file lua_bind.c) - */ -extern void lua_add_to_list@add_to_list(list_type *, int idx, cptr str); - -/** @fn display_list(int y, int x, int h, int w, cptr title, list_type *list, int max, int begin, int sel, byte sel_color); - * @dgonly - * @brief Display a scrollable boxed list with a selected item.\n - * @param y Number \n the y-coordinate of the top-left corner of the box. - * @brief Top-left y-coordinate - * @param x Number \n the x-coordinate of the top-left corner of the box. - * @brief Top-left x-coordinate - * @param h Number \n the height of the box. - * @brief Height - * @param w Number \n the width of the box. - * @brief Width - * @param title String \n the title for the list box. - * @brief Title - * @param *list list_type \n the list of strings to be displayed. - * @brief List - * @param max Number \n the maximum number of strings to display. - * @brief Maximum displayed strings - * @param begin Number \n the index of the first string to display. - * @brief Start index - * @param sel Number \n the index of the selected string. - * @brief Selected index - * @param sel_color Number \n the colour of the selected string. - * @brief Selected colour - * @note - * The title of the list is displayed in TERM_L_BLUE and the unselected strings - * are displayed in TERM_WHITE. - * @note (see file util.c) - */ -extern void lua_display_list@display_list(int y, int x, int h, int w, cptr title, list_type *list, int max, int begin, int sel, byte sel_color); - extern errr file_character(cptr name, bool full); extern void calc_bonuses(bool silent); -- cgit v1.2.3 From b2f264843721004eb67cbb890360d745b248bc1b Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 11 Jun 2012 21:08:54 +0200 Subject: Lua: Remove dead lua_spell_success() --- src/externs.h | 1 - src/lua_bind.c | 40 ---------------------------------------- src/spells.pkg | 21 --------------------- 3 files changed, 62 deletions(-) diff --git a/src/externs.h b/src/externs.h index 46a4cf2b..b041f960 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2369,7 +2369,6 @@ extern void init_hooks_module(); extern s16b can_spell_random(s16b spell_idx); extern magic_power *grab_magic_power(magic_power *m_ptr, int num); extern bool_ get_magic_power(int *sn, magic_power *powers, int max_powers, void (*power_info)(char *p, int power), int plev, int cast_stat); -extern bool_ lua_spell_success(magic_power *spell, int stat, char *oups_fct); extern object_type *new_object(void); extern void end_object(object_type *o_ptr); diff --git a/src/lua_bind.c b/src/lua_bind.c index 5a3806d8..adf0dd1e 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -27,46 +27,6 @@ magic_power *grab_magic_power(magic_power *m_ptr, int num) return (&m_ptr[num]); } -bool_ lua_spell_success(magic_power *spell, int stat, char *oups_fct) -{ - int chance; - int minfail = 0; - - /* Spell failure chance */ - chance = spell->fail; - - /* Reduce failure rate by "effective" level adjustment */ - chance -= 3 * (p_ptr->lev - spell->min_lev); - - /* Reduce failure rate by INT/WIS adjustment */ - chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[stat]] - 1); - - /* Not enough mana to cast */ - if (spell->mana_cost > p_ptr->csp) - { - chance += 5 * (spell->mana_cost - p_ptr->csp); - } - - /* Extract the minimum failure rate */ - minfail = adj_mag_fail[p_ptr->stat_ind[stat]]; - - /* Failure rate */ - chance = clamp_failure_chance(chance, minfail); - - /* Failed spell */ - if (rand_int(100) < chance) - { - if (flush_failure) flush(); - msg_format("You failed to concentrate hard enough!"); - sound(SOUND_FAIL); - - if (oups_fct != NULL) - exec_lua(format("%s(%d)", oups_fct, chance)); - return (FALSE); - } - return (TRUE); -} - /* * Create objects */ diff --git a/src/spells.pkg b/src/spells.pkg index 7385accc..26d7abab 100644 --- a/src/spells.pkg +++ b/src/spells.pkg @@ -2126,27 +2126,6 @@ struct magic_power */ extern magic_power *grab_magic_power @ get_magic_power(magic_power *m_ptr, int num); -/** @fn magic_power_sucess(magic_power *spell, int stat, char *oups_fct=NULL); - * @dgonly - * @brief Determine if using a magic power succeeds.\n - * @param *spell magic_power \n Spell is the magic power the player is using. - * @brief Power (spell) - * @param stat Number \n stat is the required casting statistic (INT or WIS). - * @brief Casting statistic - * @param *oups_fct String \n oups_fct is the message displayed when the power - * fails. - * @brief Fail message - * @return Boolean \n TRUE if spell succeeds, otherwise FALSE. - * @note - * The chance of using a power is adjusted for player magic skill, casting - * statistic, player mana points, and stunning. There is always at least a - * 5% chance the power works.\n\n - * Note: do not call this function.\n - * By order of DG. - * @note (see file lua_bind.c) - */ -extern bool lua_spell_success @ magic_power_sucess(magic_power *spell, int stat, char *oups_fct=NULL); - extern s16b can_spell_random(s16b spell_idx); /* Schools */ -- cgit v1.2.3 From a648471bf606dbe6bc5e3db16531a5624e552747 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 12 Jun 2012 05:07:59 +0200 Subject: Lua: Remove get_lua_int() --- src/externs.h | 1 - src/lua_bind.c | 7 ------- src/spells2.c | 3 +-- src/spells3.c | 31 +++++++++++++++++++++++++------ 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/externs.h b/src/externs.h index b041f960..1b8b0377 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2380,7 +2380,6 @@ extern s16b add_new_power(cptr name, cptr desc, cptr gain, cptr lose, byte le extern void find_position(int y, int x, int *yy, int *xx); extern s16b add_new_gods(char *name); -extern int get_lua_int(cptr name); extern int get_lua_list_size(cptr list_name); extern bool_ get_com_lua(cptr promtp, int *com); diff --git a/src/lua_bind.c b/src/lua_bind.c index adf0dd1e..f3c53b87 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -396,13 +396,6 @@ char lua_msg_box(cptr title) -int get_lua_int(cptr name) -{ - char buf[128]; - sprintf(buf, "return %s", name); - return exec_lua(buf); -} - int get_lua_list_size(cptr list_var) { char buf[128]; diff --git a/src/spells2.c b/src/spells2.c index 8df782a4..cdd3af66 100644 --- a/src/spells2.c +++ b/src/spells2.c @@ -8385,9 +8385,8 @@ void channel_the_elements(int y, int x, int level) case FEAT_SAND: { - int type, dur, FIERYAURA; + int type, dur; - FIERYAURA = get_lua_int("FIERYAURA"); type = (get_level(FIERYAURA, 50, 1) >= 8) ? SHIELD_GREAT_FIRE : SHIELD_FIRE; dur = randint(20) + level + get_skill(SKILL_AIR); diff --git a/src/spells3.c b/src/spells3.c index e6da0cf9..bb67ac61 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -1491,6 +1491,29 @@ static eff_type *geomancy_find_effect(eff_type effs[], int feat) return NULL; } +static u32b dir_to_eff_flags(int dir) +{ + assert(dir >= 1); + assert(dir <= 9); + + switch (dir) + { + case 1: return EFF_DIR1; + case 2: return EFF_DIR2; + case 3: return EFF_DIR3; + case 4: return EFF_DIR4; + case 5: return 0; + case 6: return EFF_DIR6; + case 7: return EFF_DIR7; + case 8: return EFF_DIR8; + case 9: return EFF_DIR9; + default: + assert(FALSE); + } + /* Default */ + return 0; +} + casting_result geomancy_elemental_wave(int item) { int dir = 0, y = 0, x = 0; @@ -1531,11 +1554,7 @@ casting_result geomancy_elemental_wave(int item) else { s16b typ = eff_ptr->low_effect; - char buf[16]; - s32b EFF_DIR; - - sprintf(buf, "EFF_DIR%d", dir); - EFF_DIR = get_lua_int(buf); + u32b dir_flag = dir_to_eff_flags(dir); if (get_level_s(ELEMENTAL_WAVE, 50) >= 20) { @@ -1549,7 +1568,7 @@ casting_result geomancy_elemental_wave(int item) eff_ptr->damage, 0, 6 + get_level_s(ELEMENTAL_WAVE, 20), - EFF_WAVE + EFF_LAST + EFF_DIR); + EFF_WAVE + EFF_LAST + dir_flag); return CAST_OBVIOUS; } -- cgit v1.2.3 From 5d09bdf66221f8bef38f2ab3dc4e8441a6bcf67f Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 12 Jun 2012 05:36:47 +0200 Subject: Lua: Remove get_lua_list_size() --- src/externs.h | 1 - src/lua_bind.c | 7 ------- 2 files changed, 8 deletions(-) diff --git a/src/externs.h b/src/externs.h index 1b8b0377..f2c38f08 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2380,7 +2380,6 @@ extern s16b add_new_power(cptr name, cptr desc, cptr gain, cptr lose, byte le extern void find_position(int y, int x, int *yy, int *xx); extern s16b add_new_gods(char *name); -extern int get_lua_list_size(cptr list_name); extern bool_ get_com_lua(cptr promtp, int *com); diff --git a/src/lua_bind.c b/src/lua_bind.c index f3c53b87..3d9038d1 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -396,13 +396,6 @@ char lua_msg_box(cptr title) -int get_lua_list_size(cptr list_var) -{ - char buf[128]; - sprintf(buf, "return getn(%s)", list_var); - return exec_lua(buf); -} - void increase_mana(int delta) { p_ptr->csp += delta; -- cgit v1.2.3 From 0d7dd4abbcdd427c05e4a6ba9031fa8735bda9d3 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 12 Jun 2012 05:37:24 +0200 Subject: Lua: Remove unused variable --- src/loadsave.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/loadsave.c b/src/loadsave.c index dcdcaae9..45f493a6 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -2539,7 +2539,6 @@ static bool_ do_savefile_aux(int flag) byte tmp8u; u16b tmp16u; - u32b tmp32u; bool_ *reals; u16b real_max = 0; -- cgit v1.2.3 From 66c6fdeaa54e9067b33cb8431f8181a1b928f19f Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 12 Jun 2012 05:45:24 +0200 Subject: Lua: Remove unused lua_State --- src/cmd5.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cmd5.c b/src/cmd5.c index e322186b..85f2b641 100644 --- a/src/cmd5.c +++ b/src/cmd5.c @@ -17,8 +17,6 @@ #include -extern lua_State *L; - /* Maximum number of tries for teleporting */ #define MAX_TRIES 300 -- cgit v1.2.3 From 6add91e17080e06cae938a31c53c94e59c7f0bfb Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 19 Jun 2012 18:32:22 +0200 Subject: Lua: Move automatizer to C --- CMakeLists.txt | 13 + README.txt | 13 + lib/core/auto.lua | 859 ---------- lib/core/init.lua | 3 - lib/core/xml.lua | 375 ----- lib/mods/theme/core/auto.lua | 859 ---------- lib/mods/theme/core/init.lua | 3 - lib/mods/theme/core/xml.lua | 375 ----- src/dungeon.c | 6 +- src/externs.h | 5 +- src/init2.c | 4 +- src/loadsave.c | 2 +- src/modules.c | 26 +- src/squeltch.c | 3550 ++++++++++++++++++++++++++++++++++++++---- 14 files changed, 3338 insertions(+), 2755 deletions(-) delete mode 100644 lib/core/auto.lua delete mode 100644 lib/core/xml.lua delete mode 100644 lib/mods/theme/core/auto.lua delete mode 100644 lib/mods/theme/core/xml.lua diff --git a/CMakeLists.txt b/CMakeLists.txt index 8714ca8a..da5486b2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,9 @@ CMAKE_MINIMUM_REQUIRED (VERSION 2.6) # We want a readable feature summary. INCLUDE(FeatureSummary) +# pkg-config support +INCLUDE(FindPkgConfig) + # Default flags. IF(CMAKE_COMPILER_IS_GNUCC) # Let's set sensible options. @@ -16,6 +19,16 @@ ENDIF() # Add definitions. ADD_DEFINITIONS(-DUSE_PRECISE_CMOVIE) +# +# JSON support +# +PKG_CHECK_MODULES(JANSSON REQUIRED jansson) +IF(JANSSON_FOUND) + ADD_DEFINITIONS(${JANSSON_CFLAGS}) + INCLUDE_DIRECTORIES(${JANSSON_INCLUDE_DIRS}) + SET(LIBS ${LIBS} ${JANSSON_LIBRARIES}) +ENDIF() + # # X11 support (OPTIONAL) # diff --git a/README.txt b/README.txt index b422701e..a4d243ef 100644 --- a/README.txt +++ b/README.txt @@ -4,6 +4,15 @@ Using the CMake build system There are basically two options for how to run ToME once built. +Prerequisites +============= + +You will need to have the following libraries installed +on your system somewhere where CMake can find them: + + - jansson + See http://www.digip.org/jansson/ + Option #1 : Run ToME from the build directory ============================================= @@ -46,6 +55,10 @@ probably missing the build-essential +package. You'll also need to install the + + libjansson-dev + package. Each frontend requires the additional packages listed below: diff --git a/lib/core/auto.lua b/lib/core/auto.lua deleted file mode 100644 index b758db52..00000000 --- a/lib/core/auto.lua +++ /dev/null @@ -1,859 +0,0 @@ --- This file is the core of the Automatizer --- Please do not touch unless you know what you are doing - -__rules = {} -__rules_max = 0 - -rule_aux = {} - --- Rule apply function, does .. nothing -function auto_nothing(obj, item) - return -end - -function auto_inscribe(obj, item, note) - if obj.note ~= 0 then return end - msg_print("") - obj.note = quark_add(note) - return TRUE -end - --- Rule apply function, pickup object -function auto_pickup(obj, item) - if item >= 0 then return end - if inven_carry_okay(obj) == FALSE then return end - msg_print("") - object_pickup(-item) - return TRUE -end - --- Rule apply function, destroy item -function auto_destroy(obj, item) - -- be carefull to what we can destroy - -- Unaware things won't be destroyed. - if is_aware(obj) == FALSE then return end - - -- Inscribed things won't be destroyed! - if obj.note ~= 0 then return end - - -- Keep Artifacts -- they cannot be destroyed anyway - if is_artifact(obj) == TRUE then return end - - -- Cannot destroy CURSE_NO_DROP objects - local f1, f2, f3, f4, f5, esp = object_flags(obj); - if band(f4, TR4_CURSE_NO_DROP) ~= 0 and band(obj.ident, IDENT_CURSED) then return end - - msg_print("") - - -- Eliminate the item (from the pack) - if item >= 0 then - inven_item_increase(item, -obj.number) - inven_item_describe(item) - inven_item_optimize(item) - -- Eliminate the item (from the floor) - else - floor_item_increase(0 - item, -obj.number) - floor_item_describe(0 - item) - floor_item_optimize(0 - item) - end - return TRUE -end - --- Report the status of an object -function object_status(obj) - local sense = - { - [SENSE_CURSED] = "bad", - [SENSE_WORTHLESS] = "very bad", - [SENSE_AVERAGE] = "average", - [SENSE_GOOD_LIGHT] = "good", - [SENSE_GOOD_HEAVY] = "good", - [SENSE_EXCELLENT] = "very good", - [SENSE_SPECIAL] = "special", - [SENSE_TERRIBLE] = "terrible", - } - - if is_known(obj) == FALSE then - if sense[obj.sense] then - return sense[obj.sense] - else - return "" - end - else -if nil then -- test - local osense = -1 - local type = select_sense(obj, TRUE, TRUE) - if type == 1 then - osense = value_check_aux1(obj) - elseif type == 2 then - osense = value_check_aux1_magic(obj) - end -print("type : "..type) - if sense[osense] then - print("sense: "..sense[osense]) - return sense[osense] - else - print("sense: ") - return "" - end - -else -- the real one - - local slot = wield_slot_ideal(obj, TRUE) - - -- Arts items - if is_artifact(obj) == TRUE then - if band(obj.ident, IDENT_CURSED) == 0 then return "special" - else return "terrible" end - -- Ego items - elseif (obj.name2 > 0 or obj.name2b > 0) then - if band(obj.ident, IDENT_CURSED) == 0 then return "very good" - else return "very bad" end - -- weapon - elseif (slot == INVEN_WIELD) or (slot == INVEN_BOW) or (slot == INVEN_AMMO) or (slot == INVEN_TOOL) then - if obj.to_h + obj.to_d < 0 then - return "bad" - elseif obj.to_h + obj.to_d > 0 then - return "good" - else - return "average" - end - -- armor - elseif (slot >= INVEN_BODY) and (slot <= INVEN_FEET) then - if obj.to_a < 0 then - return "bad" - elseif obj.to_a > 0 then - return "good" - else - return "average" - end - -- ring - elseif slot == INVEN_RING then - if (obj.to_d + obj.to_h < 0) or (obj.to_a < 0) or (obj.pval < 0) then - return "bad" - else - return "average" - end - -- amulet - elseif slot == INVEN_NECK then - if (obj.pval < 0) then - return "bad" - else - return "average" - end - -- chests - elseif obj.tval == TV_CHEST then - if obj.pval == 0 then - return "empty" - elseif obj.pval < 0 then - return "disarmed" - else - return "average" - end - else - return "average" - end -end - end -end - --- Recursive function to generate a rule function tree -function gen_rule_fct(r) - -- It is a test rule (or, and, ...) - if r.label == "and" or r.label == "or" then - local i - local fct_tbl = {} - for i = 1, getn(r) do - if r[i].label ~= "comment" then - tinsert(fct_tbl, gen_rule_fct(r[i])) - end - end - if r.label == "and" then - return function(object) - local fcts = %fct_tbl - local i - for i = 1, getn(fcts) do - if not fcts[i](object) then return end - end - return TRUE - end - elseif r.label == "or" then - return function(object) - local fcts = %fct_tbl - local i - for i = 1, getn(fcts) do - if fcts[i](object) then return TRUE end - end - end - end - -- It is a condition rule (name, type, level, ...) - else - if r.label == "not" then - local f - if not r[1] then - f = function (object) return TRUE end - else - f = gen_rule_fct(r[1]) - end - return function(object) return not %f(object) end - elseif r.label == "inventory" then - local f - if not r[1] then - f = function(object) return end - else - f = gen_rule_fct(r[1]) - end - return function(object) - local i = 0 - while i < INVEN_WIELD do - if %f(player.inventory(i)) then - return TRUE - end - i = i + 1 - end - end - elseif r.label == "equipment" then - local f - if not r[1] then - f = function(object) return end - else - f = gen_rule_fct(r[1]) - end - return function(object) - local i = INVEN_WIELD - while i < INVEN_TOTAL do - if %f(player.inventory(i)) then - return TRUE - end - i = i + 1 - end - end - elseif r.label == "name" then - return function(object) if strlower(object_desc(object, -1, 0)) == strlower(%r[1]) then return TRUE end end - elseif r.label == "contain" then - return function(object) if strfind(strlower(object_desc(object, -1, 0)), strlower(%r[1])) then return TRUE end end - elseif r.label == "symbol" then - return function(object) if strchar(get_kind(object).d_char) == %r[1] then return TRUE end end - elseif r.label == "inscribed" then - return function(object) if object.note ~= 0 and strfind(strlower(quark_str(object.note)), strlower(%r[1])) then return TRUE end end - elseif r.label == "discount" then - local d1 = r.args.min - local d2 = r.args.max - if tonumber(d1) == nil then d1 = getglobal(d1) else d1 = tonumber(d1) end - if tonumber(d2) == nil then d2 = getglobal(d2) else d2 = tonumber(d2) end - return function(object) if is_aware(object) == TRUE and object.discount >= %d1 and object.discount <= %d2 then return TRUE end end - elseif r.label == "tval" then - local tv = r[1] - if tonumber(tv) == nil then tv = getglobal(tv) else tv = tonumber(tv) end - return function(object) if object.tval == %tv then return TRUE end end - elseif r.label == "sval" then - assert(r.args.min and r.args.max, "sval rule lacks min or max") - local sv1 = r.args.min - local sv2 = r.args.max - if tonumber(sv1) == nil then sv1 = getglobal(sv1) else sv1 = tonumber(sv1) end - if tonumber(sv2) == nil then sv2 = getglobal(sv2) else sv2 = tonumber(sv2) end - return function(object) if is_aware(object) == TRUE and object.sval >= %sv1 and object.sval <= %sv2 then return TRUE end end - elseif r.label == "status" then - return function(object) if object_status(object) == strlower(%r[1]) then return TRUE end end - elseif r.label == "state" then - if r[1] == "identified" then - return function(object) if is_known(object) == TRUE then return TRUE end end - else - return function(object) if is_known(object) == FALSE then return TRUE end end - end - elseif r.label == "race" then - return function(object) if strlower(get_race_name()) == strlower(%r[1]) then return TRUE end end - elseif r.label == "subrace" then - return function(object) if strlower(get_subrace_name()) == strlower(%r[1]) then return TRUE end end - elseif r.label == "class" then - return function(object) if strlower(get_class_name()) == strlower(%r[1]) then return TRUE end end - elseif r.label == "level" then - assert(r.args.min and r.args.max, "level rule lacks min or max") - return function(object) if player.lev >= tonumber(%r.args.min) and player.lev <= tonumber(%r.args.max) then return TRUE end end - elseif r.label == "skill" then - assert(r.args.min and r.args.max, "skill rule lacks min or max") - local s = find_skill_i(r[1]) - assert(s ~= -1, "no skill "..r[1]) - return function(object) if get_skill(%s) >= tonumber(%r.args.min) and get_skill(%s) <= tonumber(%r.args.max) then return TRUE end end - elseif r.label == "ability" then - local s = find_ability(r[1]) - assert(s ~= -1, "no ability "..r[1]) - return function(object) if has_ability(%s) == TRUE then return TRUE end end - end - end -end - -function auto_inscribe_maker(inscription) - return function(...) - arg.n = arg.n + 1 - arg[getn(arg)] = %inscription - return call(auto_inscribe, arg) - end -end - --- Generate a rule from a table -function gen_full_rule(t) - -- only honor rules for this module - if not t.args.module then - t.args.module = "ToME" - end - - if not ((t.args.module == "all") or (t.args.module == game_module)) then - return function() end - end - - -- Check for which action to do - local apply_fct = auto_nothing - if t.args.type == "destroy" then apply_fct = auto_destroy - elseif t.args.type == "pickup" then apply_fct = auto_pickup - elseif t.args.type == "inscribe" then apply_fct = auto_inscribe_maker(t.args.inscription) - end - - -- create the function tree - local rf - if t[1] then - rf = gen_rule_fct(t[1]) - else - rf = function (object) end - end - - -- create the final function - return function(...) - local rf = %rf - if rf(arg[1]) then - if call(%apply_fct, arg) == TRUE then return TRUE end - end - end -end - --- Create a function that checks for the rules(passed in xml form) -function add_ruleset(s) - local tbl = xml:collect(s) - local i - - -- Add all rules - for i = 1, getn(tbl) do - local t = tbl[i] - - if t.label == "rule" then - -- Create the function tree - local fct = gen_full_rule(t) - - -- Create the test function - __rules[__rules_max] = - { - ["table"] = t, - ["fct"] = fct - } - __rules_max = __rules_max + 1 - end - end -end - --- Apply the current rules to an object --- call with at least (object, idx) -function apply_rules(...) - local i - for i = 0, __rules_max - 1 do - if call(__rules[i].fct, arg) then return TRUE end - end - return FALSE -end - --- Clear the current rules -function clean_ruleset() - __rules_max = 0 - __rules = {} -end - ------- helper fonctions for the GUI - -auto_aux = {} -auto_aux.stack = { n = 0 } -auto_aux.idx = 1 -auto_aux.rule = 1 -function auto_aux:go_right() - if auto_aux.rule[1] and type(auto_aux.rule[1]) == "table" then - tinsert(auto_aux.stack, auto_aux.idx) - tinsert(auto_aux.stack, auto_aux.rule) - auto_aux.rule = auto_aux.rule[1] - auto_aux.idx = 1 - end -end - -function auto_aux:go_left(sel) - local n = getn(auto_aux.stack) - - if n > 0 then - auto_aux.idx = auto_aux.stack[n - 1] - auto_aux.rule = auto_aux.stack[n] - tremove(auto_aux.stack) - tremove(auto_aux.stack) - end -end - -function auto_aux:go_down() - if getn(auto_aux.stack) > 1 then - if auto_aux.stack[getn(auto_aux.stack)][auto_aux.idx + 1] then - auto_aux.idx = auto_aux.idx + 1 - auto_aux.rule = auto_aux.stack[getn(auto_aux.stack)][auto_aux.idx] - end - end -end - -function auto_aux:go_up() - if getn(auto_aux.stack) > 1 then - if auto_aux.stack[getn(auto_aux.stack)][auto_aux.idx - 1] then - auto_aux.idx = auto_aux.idx - 1 - auto_aux.rule = auto_aux.stack[getn(auto_aux.stack)][auto_aux.idx] - end - end -end - -function auto_aux:scroll_up() - xml.write_off_y = xml.write_off_y - 1 -end - -function auto_aux:scroll_down() - xml.write_off_y = xml.write_off_y + 1 -end - -function auto_aux:scroll_left() - xml.write_off_x = xml.write_off_x + 1 -end - -function auto_aux:scroll_right() - xml.write_off_x = xml.write_off_x - 1 -end - -function auto_aux:adjust_current(sel) - if __rules_max == 0 then return end - - xml.write_off_y = 0 - xml.write_off_x = 0 - auto_aux.idx = 1 - auto_aux.stack = { n = 0 } - auto_aux.rule = __rules[sel].table -end - -function auto_aux:move_up(sel) - if sel > 0 then - local u = __rules[sel - 1] - local d = __rules[sel] - __rules[sel - 1] = d - __rules[sel] = u - return sel - 1 - end - return sel -end - -function auto_aux:move_down(sel) - if sel < __rules_max - 1 then - local u = __rules[sel] - local d = __rules[sel + 1] - __rules[sel + 1] = u - __rules[sel] = d - return sel + 1 - end - return sel -end - -function auto_aux:new_rule(sel, nam, typ, arg) - local r - - - -- nam can also directly be the table itself - if type(nam) == "table" then - r = - { - ["table"] = nam, - ["fct"] = function (object) end - } - elseif typ == "inscribe" then - if arg == "" then - arg = input_box("Inscription?", 79) - end - r = - { - ["table"] = - { - label = "rule", - args = { name = nam, type = typ, inscription = arg, module = game_module }, - }, - ["fct"] = function (object) end - } - else - r = - { - ["table"] = - { - label = "rule", - args = { name = nam, type = typ, module = game_module }, - }, - ["fct"] = function (object) end - } - end - tinsert(__rules, sel, r) - __rules_max = __rules_max + 1 -end - -function auto_aux:rename_rule(sel, nam) - if sel >= 0 and sel < __rules_max then - __rules[sel].table.args.name = nam - end -end - -function auto_aux:save_ruleset() - xml.write = xml.write_file - - print_hook("clean_ruleset()\nadd_ruleset\n[[\n") - local i - for i = 0, __rules_max - 1 do - xml:print_xml(__rules[i].table, '') - end - print_hook("]]\n") - - xml.write = xml.write_screen -end - -function auto_aux:del_self(sel) - if auto_aux.rule.label == "rule" then - tremove(__rules, sel) - __rules_max = __rules_max - 1 - return sel - 1 - else - local idx = auto_aux.idx - auto_aux:go_left(sel) - tremove(auto_aux.rule, idx) - return sel - end -end - -auto_aux.types_desc = -{ - ["and"] = - { - "Check is true if all rules within it are true", - xml:collect([[.........]]), - function () - return xml:collect("") - end, - }, - ["or"] = - { - "Check is true if at least one rule within it is true", - xml:collect([[.........]]), - function () - return xml:collect("") - end, - }, - ["not"] = - { - "Invert the result of its child rule", - xml:collect([[...]]), - function () - return xml:collect("") - end, - }, - ["comment"] = - { - "Comments are meaningless", - xml:collect([[Comment explaining something]]), - function () - local n = input_box("Comment?", 79) - if n == "" then return end - return xml:collect(""..n.."") - end, - }, - ["name"] = - { - "Check is true if object name matches name", - xml:collect([[potion of healing]]), - function () - local n = input_box("Object name to match?", 79) - if n == "" then return end - return xml:collect(""..n.."") - end, - }, - ["contain"] = - { - "Check is true if object name contains word", - xml:collect([[healing]]), - function () - local n = input_box("Word to find in object name?", 79) - if n == "" then return end - return xml:collect(""..n.."") - end, - }, - ["inscribed"] = - { - "Check is true if object inscription contains word", - xml:collect([[=g]]), - function () - local n = input_box("Word to find in object inscription?", 79) - if n == "" then return end - return xml:collect(""..n.."") - end, - }, - ["discount"] = - { - "Check is true if object discount is between 2 values", - xml:collect([[]]), - function () - local s = "" - return xml:collect(s) - end, - }, - ["symbol"] = - { - "Check is true if object symbol is ok", - xml:collect([[!]]), - function () - local n = input_box("Symbol to match?", 1) - if n == "" then return end - return xml:collect(""..n.."") - end, - }, - ["status"] = - { - "Check is true if object status is ok", - xml:collect([[good]]), - function () - local n = msg_box("[t]errible, [v]ery bad, [b]ad, [a]verage, [G]ood, [V]ery good, [S]pecial?") - local t = - { - ["t"] = "terrible", - ["v"] = "very bad", - ["b"] = "bad", - ["a"] = "average", - ["G"] = "good", - ["V"] = "very good", - ["S"] = "special", - } - if not t[strchar(n)] then return end - return xml:collect(""..t[strchar(n)].."") - end, - }, - ["state"] = - { - "Check is true if object is identified/unidentified", - xml:collect([[identified]]), - function () - local n = msg_box("[i]dentified, [n]on identified?") - local t = - { - ["i"] = "identified", - ["n"] = "not identified", - } - if not t[strchar(n)] then return end - return xml:collect(""..t[strchar(n)].."") - end, - }, - ["tval"] = - { - "Check is true if object tval(from k_info.txt) is ok", - xml:collect([[55]]), - function () - local n = input_box("Tval to match?", 79) - if n == "" then return end - return xml:collect(""..n.."") - end, - }, - ["sval"] = - { - { - "Check is true if object sval(from k_info.txt) is between", - "2 values", - }, - xml:collect([[]]), - function () - local s = "" - return xml:collect(s) - end, - }, - ["race"] = - { - "Check is true if player race is ok", - xml:collect([[dunadan]]), - function () - local n = input_box("Player race to match?", 79) - if n == "" then return end - return xml:collect(""..n.."") - end, - }, - ["subrace"] = - { - "Check is true if player subrace is ok", - xml:collect([[vampire]]), - function () - local n = input_box("Player subrace to match?", 79) - if n == "" then return end - return xml:collect(""..n.."") - end, - }, - ["class"] = - { - "Check is true if player class is ok", - xml:collect([[sorceror]]), - function () - local n = input_box("Player class to match?", 79) - if n == "" then return end - return xml:collect(""..n.."") - end, - }, - ["level"] = - { - "Check is true if player level is between 2 values", - xml:collect([[]]), - function () - local s = "" - - return xml:collect(s) - end, - }, - ["skill"] = - { - "Check is true if player skill level is between 2 values", - xml:collect([[Divination]]), - function () - local s = "" - - n = input_box("Skill name?", 79) - if n == "" then return end - if find_skill_i(n) == -1 then return end - s = s..n.."" - - return xml:collect(s) - end, - }, - ["ability"] = - { - "Check is true if player has the ability", - xml:collect([[Ammo creation]]), - function() - local n = input_box("Ability name?", 79) - if n == "" then return end - if find_ability(n) == -1 then return end - return xml:collect(""..n.."") - end, - }, - ["inventory"] = - { - { - "Check is true if something in player's inventory matches", - "the contained rule", - }, - xml:collect([[...]]), - function () - return xml:collect("") - end, - }, - ["equipment"] = - { - { - "Check is true if something in player's equipment matches", - "the contained rule", - }, - xml:collect([[...]]), - function () - return xml:collect("") - end, - }, -} - -function auto_aux:display_desc(sel) - local d = auto_aux.types_desc[sel][1] - if type(d) == "string" then - c_prt(TERM_WHITE, d, 1, 17) - else - local k, e, i - i = 0 - for k, e in d do - c_prt(TERM_WHITE, e, 1 + i, 17) - i = i + 1 - end - end -end - -function auto_aux:add_child(sel) - -- and contain only one match - if (auto_aux.rule.label == "rule" or auto_aux.rule.label == "not") and auto_aux.rule[1] then return end - if (auto_aux.rule.label == "rule" or auto_aux.rule.label == "equipment") and auto_aux.rule[1] then return end - if (auto_aux.rule.label == "rule" or auto_aux.rule.label == "inventory") and auto_aux.rule[1] then return end - - -- Only and can contain - if auto_aux.rule.label ~= "rule" and auto_aux.rule.label ~= "and" and auto_aux.rule.label ~= "or" and auto_aux.rule.label ~= "not" and auto_aux.rule.label ~= "equipment" and auto_aux.rule.label ~= "inventory" then return end - - -- get it - local r = auto_aux.types_desc[sel][3]() - if not r then return end - - -- Ok add it - tinsert(auto_aux.rule, r[1]) -end - -function auto_aux.regen_ruleset() - local i - for i = 0, __rules_max - 1 do - __rules[i].fct = gen_full_rule(__rules[i].table) - end -end - - --- Easily add new rules -function easy_add_rule(typ, mode, do_status, obj) - local detect_rule - - if mode == "tval" then - detect_rule = ""..obj.tval.."" - elseif mode == "tsval" then - detect_rule = ""..obj.tval.."" - elseif mode == "name" then - detect_rule = ""..strlower(object_desc(obj, -1, 0)).."" - end - - if do_status == TRUE then - local status = object_status(obj) - if status and not (status == "") then - detect_rule = ""..detect_rule..""..status.."" - end - end - - local rule = ""..detect_rule.."" - auto_aux:new_rule(0, xml:collect(rule)[1], '') - auto_aux.regen_ruleset() - msg_print("Rule added. Please go to the Automatizer screen (press = then T)") - msg_print("to save the modified ruleset.") -end diff --git a/lib/core/init.lua b/lib/core/init.lua index 51dfc1d2..44ef9a7a 100644 --- a/lib/core/init.lua +++ b/lib/core/init.lua @@ -3,9 +3,6 @@ -- Load the system functions -- --- Very thin xml parser(49 lines ;) -tome_dofile_anywhere(ANGBAND_DIR_CORE, "xml.lua") - -- various vital helper code tome_dofile_anywhere(ANGBAND_DIR_CORE, "util.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "player.lua") diff --git a/lib/core/xml.lua b/lib/core/xml.lua deleted file mode 100644 index 14f0511f..00000000 --- a/lib/core/xml.lua +++ /dev/null @@ -1,375 +0,0 @@ --- The xml module -xml = {} - -function xml:parseargs (s) - local arg = {} - gsub(s, "(%w+)=([\"'])(.-)%2", function (w, _, a) - %arg[w] = a - end) - return arg -end - --- s is a xml stream, returns a table -function xml:collect (s) - local stack = {n=0} - local top = {n=0} - tinsert(stack, top) - local ni,c,label,args, empty - local i, j = 1, 1 - while 1 do - ni,j,c,label,args, empty = strfind(s, "<(%/?)(%w+)(.-)(%/?)>", j) - if not ni then break end - local text = strsub(s, i, ni-1) - if not strfind(text, "^%s*$") then - tinsert(top, text) - end - if empty == "/" then -- empty element tag - tinsert(top, {n=0, label=label, args=xml:parseargs(args), empty=1}) - elseif c == "" then -- start tag - top = {n=0, label=label, args=xml:parseargs(args)} - tinsert(stack, top) -- new level - else -- end tag - local toclose = tremove(stack) -- remove top - top = stack[stack.n] - if stack.n < 1 then - error("nothing to close with "..label) - end - if toclose.label ~= label then - error("trying to close "..toclose.label.." with "..label) - end - tinsert(top, toclose) - end - i = j+1 - end - local text = strsub(s, i) - if not strfind(text, "^%s*$") then - tinsert(stack[stack.n], text) - end - if stack.n > 1 then - error("unclosed "..stack[stack.n].label) - end - return stack[1] -end - --- Viewport coordinates -xml.write_out_y = 0 -xml.write_out_x = 0 -xml.write_out_h = 24 -xml.write_out_w = 80 - --- Offsets -xml.write_off_y = 0 -xml.write_off_x = 0 - --- Current position -xml.write_y = 0 -xml.write_x = 0 - -xml.write_screen = function(color, s) - local i - for i = 1, strlen(s) do - local c = strsub(s, i, i + 1) - if c ~= "\n" then - if xml.write_y - xml.write_off_y >= 0 and xml.write_y - xml.write_off_y < xml.write_out_h and xml.write_x - xml.write_off_x >= 0 and xml.write_x - xml.write_off_x < xml.write_out_w then - Term_putch(xml.write_x - xml.write_off_x + xml.write_out_x, xml.write_y - xml.write_off_y + xml.write_out_y, color, strbyte(c)) - end - xml.write_x = xml.write_x + 1 - else - xml.write_x = 0 - xml.write_y = xml.write_y + 1 - end - end -end - -xml.write_file = function (color, s) - print_hook(s) -end - -xml.write = xml.write_screen - -xml.rule2string = { - ['name'] = {"Its ", "name", " is"}, - ['contain'] = {"Its ", "name", " contains"}, - ['symbol'] = {"Its ", "symbol", " is"}, - ['inscribed'] = {"Its ", "inscription", " contains"}, - ['state'] = {"Its ", "state", " is"}, - ['status'] = {"Its ", "status", " is"}, - ['tval'] = {"Its ", "tval", " is"}, - ['race'] = {"Your ", "race", " is"}, - ['subrace'] = {"Your ", "subrace", " is"}, - ['class'] = {"Your ", "class", " is"}, - ['foo1'] = {"The result of ", "test 1 ", "is"}, - ['foo2'] = {"The result of ", "test 2 ", "is"}, - ['foo3'] = {"The result of ", "test 3 ", "is"}, -} - -xml.display_english = 1 -function xml:display_xml(t, tab) - if xml.display_english then - xml:english_xml(t, tab) - else - xml:print_xml(t, tab) - end -end - -function xml:english_xml(t, tab, not_flag) - local i, k, e - local pre, post, recurse - local children_not_flag - local nextlevel - local bcol, ecol = TERM_L_GREEN, TERM_GREEN - - if xml.write_active and t == auto_aux.rule then bcol, ecol = TERM_VIOLET, TERM_VIOLET end - - nextlevel = tab .. " " - - recurse = 1 - - if t.label == "rule" then - if t.args.type == "inscribe" then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "A rule named \"") - xml.write(TERM_WHITE, tostring(t.args.name)) - xml.write(ecol, "\" to ") - xml.write(bcol, "inscribe") - xml.write(ecol, " an item with \"") - xml.write(TERM_WHITE, t.args.inscription) - xml.write(ecol, "\" when") - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "A rule named \"") - xml.write(TERM_WHITE, tostring(t.args.name)) - xml.write(ecol, "\" to ") - xml.write(bcol, t.args.type) - xml.write(ecol, " when") - xml.write(TERM_WHITE, "\n") - end - elseif t.label == "and" then - if not_flag then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "At least one of the following is false:") - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "All of the following are true:") - xml.write(TERM_WHITE, "\n") - end - elseif t.label == "or" then - if not_flag then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "All of the following are false:") - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "At least one of the following are true:") - xml.write(TERM_WHITE, "\n") - end - elseif t.label == "not" then - if bcol == TERM_VIOLET or getn(t) == 0 then - xml.write(ecol, "(a negating rule)") - xml.write(TERM_WHITE, "\n") - else - nextlevel = tab - end - children_not_flag = not nil - elseif t.label == "inventory" then - if not_flag then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Nothing in your ") - xml.write(bcol, "inventory") - xml.write(ecol, " matches the following:") - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Something in your ") - xml.write(bcol, "inventory") - xml.write(ecol, " matches the following:") - xml.write(TERM_WHITE, "\n") - end - elseif t.label == "equipment" then - if not_flag then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Nothing in your ") - xml.write(bcol, "equipment") - xml.write(ecol, " matches the following:") - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Something in your ") - xml.write(bcol, "equipment") - xml.write(ecol, " matches the following:") - xml.write(TERM_WHITE, "\n") - end - elseif t.label == "comment" then - xml.write(TERM_WHITE, tab) - xml.write(TERM_WHITE, "(" .. t[1] .. ")") - xml.write(TERM_WHITE, "\n") - elseif t.label == "skill" then - local s = t[1] - if not_flag then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Your skill in ") - xml.write(bcol, s) - xml.write(ecol, " is not from ") - xml.write(TERM_WHITE, tostring(t.args.min)) - xml.write(ecol, " to ") - xml.write(TERM_WHITE, tostring(t.args.max)) - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Your skill in ") - xml.write(bcol, s) - xml.write(ecol, " is from ") - xml.write(TERM_WHITE, tostring(t.args.min)) - xml.write(ecol, " to ") - xml.write(TERM_WHITE, tostring(t.args.max)) - xml.write(TERM_WHITE, "\n") - end - elseif t.label == "ability" then - local s = t[1] - if not_flag then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "You do not have the ") - xml.write(bcol, s) - xml.write(ecol, " ability") - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "You have the ") - xml.write(bcol, s) - xml.write(ecol, " ability") - xml.write(TERM_WHITE, "\n") - end - elseif t.label == "level" then - if not_flag then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Your ") - xml.write(bcol, "level") - xml.write(ecol, " is not from ") - xml.write(TERM_WHITE, tostring(t.args.min)) - xml.write(ecol, " to ") - xml.write(TERM_WHITE, tostring(t.args.max)) - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Your ") - xml.write(bcol, "level") - xml.write(ecol, " is from ") - xml.write(TERM_WHITE, tostring(t.args.min)) - xml.write(ecol, " to ") - xml.write(TERM_WHITE, tostring(t.args.max)) - xml.write(TERM_WHITE, "\n") - end - elseif t.label == "sval" then - if not_flag then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Its ") - xml.write(bcol, "sval") - xml.write(ecol, " is not from ") - xml.write(TERM_WHITE, tostring(t.args.min)) - xml.write(ecol, " to ") - xml.write(TERM_WHITE, tostring(t.args.max)) - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Its ") - xml.write(bcol, "sval") - xml.write(ecol, " is from ") - xml.write(TERM_WHITE, tostring(t.args.min)) - xml.write(ecol, " to ") - xml.write(TERM_WHITE, tostring(t.args.max)) - xml.write(TERM_WHITE, "\n") - end - elseif t.label == "discount" then - if not_flag then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Its ") - xml.write(bcol, "discount") - xml.write(ecol, " is not from ") - xml.write(TERM_WHITE, tostring(t.args.min)) - xml.write(ecol, " to ") - xml.write(TERM_WHITE, tostring(t.args.max)) - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Its ") - xml.write(bcol, "discount") - xml.write(ecol, " is from ") - xml.write(TERM_WHITE, tostring(t.args.min)) - xml.write(ecol, " to ") - xml.write(TERM_WHITE, tostring(t.args.max)) - xml.write(TERM_WHITE, "\n") - end - else - if xml.rule2string[t.label] then - local rule = xml.rule2string[t.label] - a, b, c = rule[1], rule[2], rule[3] - if not_flag then c = c .. " not" end - xml.write(TERM_WHITE, tab) - xml.write(ecol, a) - xml.write(bcol, b) - xml.write(ecol, c) - xml.write(ecol, " \"") - xml.write(TERM_WHITE, t[1]) - xml.write(ecol, "\"") - xml.write(TERM_WHITE, "\n") - else - if not_flag then - xml.write(bcol, "Not:\n") - tab = tab .. " " - xml:print_xml(t, tab) - return - end - end - end - - for i = 1, getn(t) do - if type(t[i]) == "string" then - -- xml.write(TERM_WHITE, t[i].."\n") - else - xml:english_xml(t[i], nextlevel, children_not_flag) - end - end -end - -function xml:print_xml(t, tab) - local i, k, e - local inside = nil - local bcol, ecol = TERM_L_GREEN, TERM_GREEN - - if xml.write_active and t == auto_aux.rule then bcol, ecol = TERM_VIOLET, TERM_VIOLET end - - xml.write(bcol, tab.."<"..t.label) - for k, e in t.args do - xml.write(TERM_L_BLUE, " "..k) - xml.write(TERM_WHITE, "=\"") - xml.write(TERM_YELLOW, e) - xml.write(TERM_WHITE, "\"") - end - xml.write(bcol, ">") - - for i = 1, getn(t) do - if type(t[i]) == "string" then - xml.write(TERM_WHITE, t[i]) - else - if not inside then xml.write(TERM_WHITE, "\n") end - inside = not nil - xml:print_xml(t[i], tab.." ") - end - end - - if not inside then - xml.write(ecol, "\n") - else - xml.write(ecol, tab.."\n") - end -end - --- t is a table representing xml, outputs the xml code via xml.write() -function xml:output(t) - local i - for i = 1, getn(t) do - xml:print_xml(t[i], "") - end -end diff --git a/lib/mods/theme/core/auto.lua b/lib/mods/theme/core/auto.lua deleted file mode 100644 index b758db52..00000000 --- a/lib/mods/theme/core/auto.lua +++ /dev/null @@ -1,859 +0,0 @@ --- This file is the core of the Automatizer --- Please do not touch unless you know what you are doing - -__rules = {} -__rules_max = 0 - -rule_aux = {} - --- Rule apply function, does .. nothing -function auto_nothing(obj, item) - return -end - -function auto_inscribe(obj, item, note) - if obj.note ~= 0 then return end - msg_print("") - obj.note = quark_add(note) - return TRUE -end - --- Rule apply function, pickup object -function auto_pickup(obj, item) - if item >= 0 then return end - if inven_carry_okay(obj) == FALSE then return end - msg_print("") - object_pickup(-item) - return TRUE -end - --- Rule apply function, destroy item -function auto_destroy(obj, item) - -- be carefull to what we can destroy - -- Unaware things won't be destroyed. - if is_aware(obj) == FALSE then return end - - -- Inscribed things won't be destroyed! - if obj.note ~= 0 then return end - - -- Keep Artifacts -- they cannot be destroyed anyway - if is_artifact(obj) == TRUE then return end - - -- Cannot destroy CURSE_NO_DROP objects - local f1, f2, f3, f4, f5, esp = object_flags(obj); - if band(f4, TR4_CURSE_NO_DROP) ~= 0 and band(obj.ident, IDENT_CURSED) then return end - - msg_print("") - - -- Eliminate the item (from the pack) - if item >= 0 then - inven_item_increase(item, -obj.number) - inven_item_describe(item) - inven_item_optimize(item) - -- Eliminate the item (from the floor) - else - floor_item_increase(0 - item, -obj.number) - floor_item_describe(0 - item) - floor_item_optimize(0 - item) - end - return TRUE -end - --- Report the status of an object -function object_status(obj) - local sense = - { - [SENSE_CURSED] = "bad", - [SENSE_WORTHLESS] = "very bad", - [SENSE_AVERAGE] = "average", - [SENSE_GOOD_LIGHT] = "good", - [SENSE_GOOD_HEAVY] = "good", - [SENSE_EXCELLENT] = "very good", - [SENSE_SPECIAL] = "special", - [SENSE_TERRIBLE] = "terrible", - } - - if is_known(obj) == FALSE then - if sense[obj.sense] then - return sense[obj.sense] - else - return "" - end - else -if nil then -- test - local osense = -1 - local type = select_sense(obj, TRUE, TRUE) - if type == 1 then - osense = value_check_aux1(obj) - elseif type == 2 then - osense = value_check_aux1_magic(obj) - end -print("type : "..type) - if sense[osense] then - print("sense: "..sense[osense]) - return sense[osense] - else - print("sense: ") - return "" - end - -else -- the real one - - local slot = wield_slot_ideal(obj, TRUE) - - -- Arts items - if is_artifact(obj) == TRUE then - if band(obj.ident, IDENT_CURSED) == 0 then return "special" - else return "terrible" end - -- Ego items - elseif (obj.name2 > 0 or obj.name2b > 0) then - if band(obj.ident, IDENT_CURSED) == 0 then return "very good" - else return "very bad" end - -- weapon - elseif (slot == INVEN_WIELD) or (slot == INVEN_BOW) or (slot == INVEN_AMMO) or (slot == INVEN_TOOL) then - if obj.to_h + obj.to_d < 0 then - return "bad" - elseif obj.to_h + obj.to_d > 0 then - return "good" - else - return "average" - end - -- armor - elseif (slot >= INVEN_BODY) and (slot <= INVEN_FEET) then - if obj.to_a < 0 then - return "bad" - elseif obj.to_a > 0 then - return "good" - else - return "average" - end - -- ring - elseif slot == INVEN_RING then - if (obj.to_d + obj.to_h < 0) or (obj.to_a < 0) or (obj.pval < 0) then - return "bad" - else - return "average" - end - -- amulet - elseif slot == INVEN_NECK then - if (obj.pval < 0) then - return "bad" - else - return "average" - end - -- chests - elseif obj.tval == TV_CHEST then - if obj.pval == 0 then - return "empty" - elseif obj.pval < 0 then - return "disarmed" - else - return "average" - end - else - return "average" - end -end - end -end - --- Recursive function to generate a rule function tree -function gen_rule_fct(r) - -- It is a test rule (or, and, ...) - if r.label == "and" or r.label == "or" then - local i - local fct_tbl = {} - for i = 1, getn(r) do - if r[i].label ~= "comment" then - tinsert(fct_tbl, gen_rule_fct(r[i])) - end - end - if r.label == "and" then - return function(object) - local fcts = %fct_tbl - local i - for i = 1, getn(fcts) do - if not fcts[i](object) then return end - end - return TRUE - end - elseif r.label == "or" then - return function(object) - local fcts = %fct_tbl - local i - for i = 1, getn(fcts) do - if fcts[i](object) then return TRUE end - end - end - end - -- It is a condition rule (name, type, level, ...) - else - if r.label == "not" then - local f - if not r[1] then - f = function (object) return TRUE end - else - f = gen_rule_fct(r[1]) - end - return function(object) return not %f(object) end - elseif r.label == "inventory" then - local f - if not r[1] then - f = function(object) return end - else - f = gen_rule_fct(r[1]) - end - return function(object) - local i = 0 - while i < INVEN_WIELD do - if %f(player.inventory(i)) then - return TRUE - end - i = i + 1 - end - end - elseif r.label == "equipment" then - local f - if not r[1] then - f = function(object) return end - else - f = gen_rule_fct(r[1]) - end - return function(object) - local i = INVEN_WIELD - while i < INVEN_TOTAL do - if %f(player.inventory(i)) then - return TRUE - end - i = i + 1 - end - end - elseif r.label == "name" then - return function(object) if strlower(object_desc(object, -1, 0)) == strlower(%r[1]) then return TRUE end end - elseif r.label == "contain" then - return function(object) if strfind(strlower(object_desc(object, -1, 0)), strlower(%r[1])) then return TRUE end end - elseif r.label == "symbol" then - return function(object) if strchar(get_kind(object).d_char) == %r[1] then return TRUE end end - elseif r.label == "inscribed" then - return function(object) if object.note ~= 0 and strfind(strlower(quark_str(object.note)), strlower(%r[1])) then return TRUE end end - elseif r.label == "discount" then - local d1 = r.args.min - local d2 = r.args.max - if tonumber(d1) == nil then d1 = getglobal(d1) else d1 = tonumber(d1) end - if tonumber(d2) == nil then d2 = getglobal(d2) else d2 = tonumber(d2) end - return function(object) if is_aware(object) == TRUE and object.discount >= %d1 and object.discount <= %d2 then return TRUE end end - elseif r.label == "tval" then - local tv = r[1] - if tonumber(tv) == nil then tv = getglobal(tv) else tv = tonumber(tv) end - return function(object) if object.tval == %tv then return TRUE end end - elseif r.label == "sval" then - assert(r.args.min and r.args.max, "sval rule lacks min or max") - local sv1 = r.args.min - local sv2 = r.args.max - if tonumber(sv1) == nil then sv1 = getglobal(sv1) else sv1 = tonumber(sv1) end - if tonumber(sv2) == nil then sv2 = getglobal(sv2) else sv2 = tonumber(sv2) end - return function(object) if is_aware(object) == TRUE and object.sval >= %sv1 and object.sval <= %sv2 then return TRUE end end - elseif r.label == "status" then - return function(object) if object_status(object) == strlower(%r[1]) then return TRUE end end - elseif r.label == "state" then - if r[1] == "identified" then - return function(object) if is_known(object) == TRUE then return TRUE end end - else - return function(object) if is_known(object) == FALSE then return TRUE end end - end - elseif r.label == "race" then - return function(object) if strlower(get_race_name()) == strlower(%r[1]) then return TRUE end end - elseif r.label == "subrace" then - return function(object) if strlower(get_subrace_name()) == strlower(%r[1]) then return TRUE end end - elseif r.label == "class" then - return function(object) if strlower(get_class_name()) == strlower(%r[1]) then return TRUE end end - elseif r.label == "level" then - assert(r.args.min and r.args.max, "level rule lacks min or max") - return function(object) if player.lev >= tonumber(%r.args.min) and player.lev <= tonumber(%r.args.max) then return TRUE end end - elseif r.label == "skill" then - assert(r.args.min and r.args.max, "skill rule lacks min or max") - local s = find_skill_i(r[1]) - assert(s ~= -1, "no skill "..r[1]) - return function(object) if get_skill(%s) >= tonumber(%r.args.min) and get_skill(%s) <= tonumber(%r.args.max) then return TRUE end end - elseif r.label == "ability" then - local s = find_ability(r[1]) - assert(s ~= -1, "no ability "..r[1]) - return function(object) if has_ability(%s) == TRUE then return TRUE end end - end - end -end - -function auto_inscribe_maker(inscription) - return function(...) - arg.n = arg.n + 1 - arg[getn(arg)] = %inscription - return call(auto_inscribe, arg) - end -end - --- Generate a rule from a table -function gen_full_rule(t) - -- only honor rules for this module - if not t.args.module then - t.args.module = "ToME" - end - - if not ((t.args.module == "all") or (t.args.module == game_module)) then - return function() end - end - - -- Check for which action to do - local apply_fct = auto_nothing - if t.args.type == "destroy" then apply_fct = auto_destroy - elseif t.args.type == "pickup" then apply_fct = auto_pickup - elseif t.args.type == "inscribe" then apply_fct = auto_inscribe_maker(t.args.inscription) - end - - -- create the function tree - local rf - if t[1] then - rf = gen_rule_fct(t[1]) - else - rf = function (object) end - end - - -- create the final function - return function(...) - local rf = %rf - if rf(arg[1]) then - if call(%apply_fct, arg) == TRUE then return TRUE end - end - end -end - --- Create a function that checks for the rules(passed in xml form) -function add_ruleset(s) - local tbl = xml:collect(s) - local i - - -- Add all rules - for i = 1, getn(tbl) do - local t = tbl[i] - - if t.label == "rule" then - -- Create the function tree - local fct = gen_full_rule(t) - - -- Create the test function - __rules[__rules_max] = - { - ["table"] = t, - ["fct"] = fct - } - __rules_max = __rules_max + 1 - end - end -end - --- Apply the current rules to an object --- call with at least (object, idx) -function apply_rules(...) - local i - for i = 0, __rules_max - 1 do - if call(__rules[i].fct, arg) then return TRUE end - end - return FALSE -end - --- Clear the current rules -function clean_ruleset() - __rules_max = 0 - __rules = {} -end - ------- helper fonctions for the GUI - -auto_aux = {} -auto_aux.stack = { n = 0 } -auto_aux.idx = 1 -auto_aux.rule = 1 -function auto_aux:go_right() - if auto_aux.rule[1] and type(auto_aux.rule[1]) == "table" then - tinsert(auto_aux.stack, auto_aux.idx) - tinsert(auto_aux.stack, auto_aux.rule) - auto_aux.rule = auto_aux.rule[1] - auto_aux.idx = 1 - end -end - -function auto_aux:go_left(sel) - local n = getn(auto_aux.stack) - - if n > 0 then - auto_aux.idx = auto_aux.stack[n - 1] - auto_aux.rule = auto_aux.stack[n] - tremove(auto_aux.stack) - tremove(auto_aux.stack) - end -end - -function auto_aux:go_down() - if getn(auto_aux.stack) > 1 then - if auto_aux.stack[getn(auto_aux.stack)][auto_aux.idx + 1] then - auto_aux.idx = auto_aux.idx + 1 - auto_aux.rule = auto_aux.stack[getn(auto_aux.stack)][auto_aux.idx] - end - end -end - -function auto_aux:go_up() - if getn(auto_aux.stack) > 1 then - if auto_aux.stack[getn(auto_aux.stack)][auto_aux.idx - 1] then - auto_aux.idx = auto_aux.idx - 1 - auto_aux.rule = auto_aux.stack[getn(auto_aux.stack)][auto_aux.idx] - end - end -end - -function auto_aux:scroll_up() - xml.write_off_y = xml.write_off_y - 1 -end - -function auto_aux:scroll_down() - xml.write_off_y = xml.write_off_y + 1 -end - -function auto_aux:scroll_left() - xml.write_off_x = xml.write_off_x + 1 -end - -function auto_aux:scroll_right() - xml.write_off_x = xml.write_off_x - 1 -end - -function auto_aux:adjust_current(sel) - if __rules_max == 0 then return end - - xml.write_off_y = 0 - xml.write_off_x = 0 - auto_aux.idx = 1 - auto_aux.stack = { n = 0 } - auto_aux.rule = __rules[sel].table -end - -function auto_aux:move_up(sel) - if sel > 0 then - local u = __rules[sel - 1] - local d = __rules[sel] - __rules[sel - 1] = d - __rules[sel] = u - return sel - 1 - end - return sel -end - -function auto_aux:move_down(sel) - if sel < __rules_max - 1 then - local u = __rules[sel] - local d = __rules[sel + 1] - __rules[sel + 1] = u - __rules[sel] = d - return sel + 1 - end - return sel -end - -function auto_aux:new_rule(sel, nam, typ, arg) - local r - - - -- nam can also directly be the table itself - if type(nam) == "table" then - r = - { - ["table"] = nam, - ["fct"] = function (object) end - } - elseif typ == "inscribe" then - if arg == "" then - arg = input_box("Inscription?", 79) - end - r = - { - ["table"] = - { - label = "rule", - args = { name = nam, type = typ, inscription = arg, module = game_module }, - }, - ["fct"] = function (object) end - } - else - r = - { - ["table"] = - { - label = "rule", - args = { name = nam, type = typ, module = game_module }, - }, - ["fct"] = function (object) end - } - end - tinsert(__rules, sel, r) - __rules_max = __rules_max + 1 -end - -function auto_aux:rename_rule(sel, nam) - if sel >= 0 and sel < __rules_max then - __rules[sel].table.args.name = nam - end -end - -function auto_aux:save_ruleset() - xml.write = xml.write_file - - print_hook("clean_ruleset()\nadd_ruleset\n[[\n") - local i - for i = 0, __rules_max - 1 do - xml:print_xml(__rules[i].table, '') - end - print_hook("]]\n") - - xml.write = xml.write_screen -end - -function auto_aux:del_self(sel) - if auto_aux.rule.label == "rule" then - tremove(__rules, sel) - __rules_max = __rules_max - 1 - return sel - 1 - else - local idx = auto_aux.idx - auto_aux:go_left(sel) - tremove(auto_aux.rule, idx) - return sel - end -end - -auto_aux.types_desc = -{ - ["and"] = - { - "Check is true if all rules within it are true", - xml:collect([[.........]]), - function () - return xml:collect("") - end, - }, - ["or"] = - { - "Check is true if at least one rule within it is true", - xml:collect([[.........]]), - function () - return xml:collect("") - end, - }, - ["not"] = - { - "Invert the result of its child rule", - xml:collect([[...]]), - function () - return xml:collect("") - end, - }, - ["comment"] = - { - "Comments are meaningless", - xml:collect([[Comment explaining something]]), - function () - local n = input_box("Comment?", 79) - if n == "" then return end - return xml:collect(""..n.."") - end, - }, - ["name"] = - { - "Check is true if object name matches name", - xml:collect([[potion of healing]]), - function () - local n = input_box("Object name to match?", 79) - if n == "" then return end - return xml:collect(""..n.."") - end, - }, - ["contain"] = - { - "Check is true if object name contains word", - xml:collect([[healing]]), - function () - local n = input_box("Word to find in object name?", 79) - if n == "" then return end - return xml:collect(""..n.."") - end, - }, - ["inscribed"] = - { - "Check is true if object inscription contains word", - xml:collect([[=g]]), - function () - local n = input_box("Word to find in object inscription?", 79) - if n == "" then return end - return xml:collect(""..n.."") - end, - }, - ["discount"] = - { - "Check is true if object discount is between 2 values", - xml:collect([[]]), - function () - local s = "" - return xml:collect(s) - end, - }, - ["symbol"] = - { - "Check is true if object symbol is ok", - xml:collect([[!]]), - function () - local n = input_box("Symbol to match?", 1) - if n == "" then return end - return xml:collect(""..n.."") - end, - }, - ["status"] = - { - "Check is true if object status is ok", - xml:collect([[good]]), - function () - local n = msg_box("[t]errible, [v]ery bad, [b]ad, [a]verage, [G]ood, [V]ery good, [S]pecial?") - local t = - { - ["t"] = "terrible", - ["v"] = "very bad", - ["b"] = "bad", - ["a"] = "average", - ["G"] = "good", - ["V"] = "very good", - ["S"] = "special", - } - if not t[strchar(n)] then return end - return xml:collect(""..t[strchar(n)].."") - end, - }, - ["state"] = - { - "Check is true if object is identified/unidentified", - xml:collect([[identified]]), - function () - local n = msg_box("[i]dentified, [n]on identified?") - local t = - { - ["i"] = "identified", - ["n"] = "not identified", - } - if not t[strchar(n)] then return end - return xml:collect(""..t[strchar(n)].."") - end, - }, - ["tval"] = - { - "Check is true if object tval(from k_info.txt) is ok", - xml:collect([[55]]), - function () - local n = input_box("Tval to match?", 79) - if n == "" then return end - return xml:collect(""..n.."") - end, - }, - ["sval"] = - { - { - "Check is true if object sval(from k_info.txt) is between", - "2 values", - }, - xml:collect([[]]), - function () - local s = "" - return xml:collect(s) - end, - }, - ["race"] = - { - "Check is true if player race is ok", - xml:collect([[dunadan]]), - function () - local n = input_box("Player race to match?", 79) - if n == "" then return end - return xml:collect(""..n.."") - end, - }, - ["subrace"] = - { - "Check is true if player subrace is ok", - xml:collect([[vampire]]), - function () - local n = input_box("Player subrace to match?", 79) - if n == "" then return end - return xml:collect(""..n.."") - end, - }, - ["class"] = - { - "Check is true if player class is ok", - xml:collect([[sorceror]]), - function () - local n = input_box("Player class to match?", 79) - if n == "" then return end - return xml:collect(""..n.."") - end, - }, - ["level"] = - { - "Check is true if player level is between 2 values", - xml:collect([[]]), - function () - local s = "" - - return xml:collect(s) - end, - }, - ["skill"] = - { - "Check is true if player skill level is between 2 values", - xml:collect([[Divination]]), - function () - local s = "" - - n = input_box("Skill name?", 79) - if n == "" then return end - if find_skill_i(n) == -1 then return end - s = s..n.."" - - return xml:collect(s) - end, - }, - ["ability"] = - { - "Check is true if player has the ability", - xml:collect([[Ammo creation]]), - function() - local n = input_box("Ability name?", 79) - if n == "" then return end - if find_ability(n) == -1 then return end - return xml:collect(""..n.."") - end, - }, - ["inventory"] = - { - { - "Check is true if something in player's inventory matches", - "the contained rule", - }, - xml:collect([[...]]), - function () - return xml:collect("") - end, - }, - ["equipment"] = - { - { - "Check is true if something in player's equipment matches", - "the contained rule", - }, - xml:collect([[...]]), - function () - return xml:collect("") - end, - }, -} - -function auto_aux:display_desc(sel) - local d = auto_aux.types_desc[sel][1] - if type(d) == "string" then - c_prt(TERM_WHITE, d, 1, 17) - else - local k, e, i - i = 0 - for k, e in d do - c_prt(TERM_WHITE, e, 1 + i, 17) - i = i + 1 - end - end -end - -function auto_aux:add_child(sel) - -- and contain only one match - if (auto_aux.rule.label == "rule" or auto_aux.rule.label == "not") and auto_aux.rule[1] then return end - if (auto_aux.rule.label == "rule" or auto_aux.rule.label == "equipment") and auto_aux.rule[1] then return end - if (auto_aux.rule.label == "rule" or auto_aux.rule.label == "inventory") and auto_aux.rule[1] then return end - - -- Only and can contain - if auto_aux.rule.label ~= "rule" and auto_aux.rule.label ~= "and" and auto_aux.rule.label ~= "or" and auto_aux.rule.label ~= "not" and auto_aux.rule.label ~= "equipment" and auto_aux.rule.label ~= "inventory" then return end - - -- get it - local r = auto_aux.types_desc[sel][3]() - if not r then return end - - -- Ok add it - tinsert(auto_aux.rule, r[1]) -end - -function auto_aux.regen_ruleset() - local i - for i = 0, __rules_max - 1 do - __rules[i].fct = gen_full_rule(__rules[i].table) - end -end - - --- Easily add new rules -function easy_add_rule(typ, mode, do_status, obj) - local detect_rule - - if mode == "tval" then - detect_rule = ""..obj.tval.."" - elseif mode == "tsval" then - detect_rule = ""..obj.tval.."" - elseif mode == "name" then - detect_rule = ""..strlower(object_desc(obj, -1, 0)).."" - end - - if do_status == TRUE then - local status = object_status(obj) - if status and not (status == "") then - detect_rule = ""..detect_rule..""..status.."" - end - end - - local rule = ""..detect_rule.."" - auto_aux:new_rule(0, xml:collect(rule)[1], '') - auto_aux.regen_ruleset() - msg_print("Rule added. Please go to the Automatizer screen (press = then T)") - msg_print("to save the modified ruleset.") -end diff --git a/lib/mods/theme/core/init.lua b/lib/mods/theme/core/init.lua index 51dfc1d2..44ef9a7a 100644 --- a/lib/mods/theme/core/init.lua +++ b/lib/mods/theme/core/init.lua @@ -3,9 +3,6 @@ -- Load the system functions -- --- Very thin xml parser(49 lines ;) -tome_dofile_anywhere(ANGBAND_DIR_CORE, "xml.lua") - -- various vital helper code tome_dofile_anywhere(ANGBAND_DIR_CORE, "util.lua") tome_dofile_anywhere(ANGBAND_DIR_CORE, "player.lua") diff --git a/lib/mods/theme/core/xml.lua b/lib/mods/theme/core/xml.lua deleted file mode 100644 index 14f0511f..00000000 --- a/lib/mods/theme/core/xml.lua +++ /dev/null @@ -1,375 +0,0 @@ --- The xml module -xml = {} - -function xml:parseargs (s) - local arg = {} - gsub(s, "(%w+)=([\"'])(.-)%2", function (w, _, a) - %arg[w] = a - end) - return arg -end - --- s is a xml stream, returns a table -function xml:collect (s) - local stack = {n=0} - local top = {n=0} - tinsert(stack, top) - local ni,c,label,args, empty - local i, j = 1, 1 - while 1 do - ni,j,c,label,args, empty = strfind(s, "<(%/?)(%w+)(.-)(%/?)>", j) - if not ni then break end - local text = strsub(s, i, ni-1) - if not strfind(text, "^%s*$") then - tinsert(top, text) - end - if empty == "/" then -- empty element tag - tinsert(top, {n=0, label=label, args=xml:parseargs(args), empty=1}) - elseif c == "" then -- start tag - top = {n=0, label=label, args=xml:parseargs(args)} - tinsert(stack, top) -- new level - else -- end tag - local toclose = tremove(stack) -- remove top - top = stack[stack.n] - if stack.n < 1 then - error("nothing to close with "..label) - end - if toclose.label ~= label then - error("trying to close "..toclose.label.." with "..label) - end - tinsert(top, toclose) - end - i = j+1 - end - local text = strsub(s, i) - if not strfind(text, "^%s*$") then - tinsert(stack[stack.n], text) - end - if stack.n > 1 then - error("unclosed "..stack[stack.n].label) - end - return stack[1] -end - --- Viewport coordinates -xml.write_out_y = 0 -xml.write_out_x = 0 -xml.write_out_h = 24 -xml.write_out_w = 80 - --- Offsets -xml.write_off_y = 0 -xml.write_off_x = 0 - --- Current position -xml.write_y = 0 -xml.write_x = 0 - -xml.write_screen = function(color, s) - local i - for i = 1, strlen(s) do - local c = strsub(s, i, i + 1) - if c ~= "\n" then - if xml.write_y - xml.write_off_y >= 0 and xml.write_y - xml.write_off_y < xml.write_out_h and xml.write_x - xml.write_off_x >= 0 and xml.write_x - xml.write_off_x < xml.write_out_w then - Term_putch(xml.write_x - xml.write_off_x + xml.write_out_x, xml.write_y - xml.write_off_y + xml.write_out_y, color, strbyte(c)) - end - xml.write_x = xml.write_x + 1 - else - xml.write_x = 0 - xml.write_y = xml.write_y + 1 - end - end -end - -xml.write_file = function (color, s) - print_hook(s) -end - -xml.write = xml.write_screen - -xml.rule2string = { - ['name'] = {"Its ", "name", " is"}, - ['contain'] = {"Its ", "name", " contains"}, - ['symbol'] = {"Its ", "symbol", " is"}, - ['inscribed'] = {"Its ", "inscription", " contains"}, - ['state'] = {"Its ", "state", " is"}, - ['status'] = {"Its ", "status", " is"}, - ['tval'] = {"Its ", "tval", " is"}, - ['race'] = {"Your ", "race", " is"}, - ['subrace'] = {"Your ", "subrace", " is"}, - ['class'] = {"Your ", "class", " is"}, - ['foo1'] = {"The result of ", "test 1 ", "is"}, - ['foo2'] = {"The result of ", "test 2 ", "is"}, - ['foo3'] = {"The result of ", "test 3 ", "is"}, -} - -xml.display_english = 1 -function xml:display_xml(t, tab) - if xml.display_english then - xml:english_xml(t, tab) - else - xml:print_xml(t, tab) - end -end - -function xml:english_xml(t, tab, not_flag) - local i, k, e - local pre, post, recurse - local children_not_flag - local nextlevel - local bcol, ecol = TERM_L_GREEN, TERM_GREEN - - if xml.write_active and t == auto_aux.rule then bcol, ecol = TERM_VIOLET, TERM_VIOLET end - - nextlevel = tab .. " " - - recurse = 1 - - if t.label == "rule" then - if t.args.type == "inscribe" then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "A rule named \"") - xml.write(TERM_WHITE, tostring(t.args.name)) - xml.write(ecol, "\" to ") - xml.write(bcol, "inscribe") - xml.write(ecol, " an item with \"") - xml.write(TERM_WHITE, t.args.inscription) - xml.write(ecol, "\" when") - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "A rule named \"") - xml.write(TERM_WHITE, tostring(t.args.name)) - xml.write(ecol, "\" to ") - xml.write(bcol, t.args.type) - xml.write(ecol, " when") - xml.write(TERM_WHITE, "\n") - end - elseif t.label == "and" then - if not_flag then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "At least one of the following is false:") - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "All of the following are true:") - xml.write(TERM_WHITE, "\n") - end - elseif t.label == "or" then - if not_flag then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "All of the following are false:") - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "At least one of the following are true:") - xml.write(TERM_WHITE, "\n") - end - elseif t.label == "not" then - if bcol == TERM_VIOLET or getn(t) == 0 then - xml.write(ecol, "(a negating rule)") - xml.write(TERM_WHITE, "\n") - else - nextlevel = tab - end - children_not_flag = not nil - elseif t.label == "inventory" then - if not_flag then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Nothing in your ") - xml.write(bcol, "inventory") - xml.write(ecol, " matches the following:") - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Something in your ") - xml.write(bcol, "inventory") - xml.write(ecol, " matches the following:") - xml.write(TERM_WHITE, "\n") - end - elseif t.label == "equipment" then - if not_flag then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Nothing in your ") - xml.write(bcol, "equipment") - xml.write(ecol, " matches the following:") - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Something in your ") - xml.write(bcol, "equipment") - xml.write(ecol, " matches the following:") - xml.write(TERM_WHITE, "\n") - end - elseif t.label == "comment" then - xml.write(TERM_WHITE, tab) - xml.write(TERM_WHITE, "(" .. t[1] .. ")") - xml.write(TERM_WHITE, "\n") - elseif t.label == "skill" then - local s = t[1] - if not_flag then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Your skill in ") - xml.write(bcol, s) - xml.write(ecol, " is not from ") - xml.write(TERM_WHITE, tostring(t.args.min)) - xml.write(ecol, " to ") - xml.write(TERM_WHITE, tostring(t.args.max)) - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Your skill in ") - xml.write(bcol, s) - xml.write(ecol, " is from ") - xml.write(TERM_WHITE, tostring(t.args.min)) - xml.write(ecol, " to ") - xml.write(TERM_WHITE, tostring(t.args.max)) - xml.write(TERM_WHITE, "\n") - end - elseif t.label == "ability" then - local s = t[1] - if not_flag then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "You do not have the ") - xml.write(bcol, s) - xml.write(ecol, " ability") - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "You have the ") - xml.write(bcol, s) - xml.write(ecol, " ability") - xml.write(TERM_WHITE, "\n") - end - elseif t.label == "level" then - if not_flag then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Your ") - xml.write(bcol, "level") - xml.write(ecol, " is not from ") - xml.write(TERM_WHITE, tostring(t.args.min)) - xml.write(ecol, " to ") - xml.write(TERM_WHITE, tostring(t.args.max)) - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Your ") - xml.write(bcol, "level") - xml.write(ecol, " is from ") - xml.write(TERM_WHITE, tostring(t.args.min)) - xml.write(ecol, " to ") - xml.write(TERM_WHITE, tostring(t.args.max)) - xml.write(TERM_WHITE, "\n") - end - elseif t.label == "sval" then - if not_flag then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Its ") - xml.write(bcol, "sval") - xml.write(ecol, " is not from ") - xml.write(TERM_WHITE, tostring(t.args.min)) - xml.write(ecol, " to ") - xml.write(TERM_WHITE, tostring(t.args.max)) - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Its ") - xml.write(bcol, "sval") - xml.write(ecol, " is from ") - xml.write(TERM_WHITE, tostring(t.args.min)) - xml.write(ecol, " to ") - xml.write(TERM_WHITE, tostring(t.args.max)) - xml.write(TERM_WHITE, "\n") - end - elseif t.label == "discount" then - if not_flag then - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Its ") - xml.write(bcol, "discount") - xml.write(ecol, " is not from ") - xml.write(TERM_WHITE, tostring(t.args.min)) - xml.write(ecol, " to ") - xml.write(TERM_WHITE, tostring(t.args.max)) - xml.write(TERM_WHITE, "\n") - else - xml.write(TERM_WHITE, tab) - xml.write(ecol, "Its ") - xml.write(bcol, "discount") - xml.write(ecol, " is from ") - xml.write(TERM_WHITE, tostring(t.args.min)) - xml.write(ecol, " to ") - xml.write(TERM_WHITE, tostring(t.args.max)) - xml.write(TERM_WHITE, "\n") - end - else - if xml.rule2string[t.label] then - local rule = xml.rule2string[t.label] - a, b, c = rule[1], rule[2], rule[3] - if not_flag then c = c .. " not" end - xml.write(TERM_WHITE, tab) - xml.write(ecol, a) - xml.write(bcol, b) - xml.write(ecol, c) - xml.write(ecol, " \"") - xml.write(TERM_WHITE, t[1]) - xml.write(ecol, "\"") - xml.write(TERM_WHITE, "\n") - else - if not_flag then - xml.write(bcol, "Not:\n") - tab = tab .. " " - xml:print_xml(t, tab) - return - end - end - end - - for i = 1, getn(t) do - if type(t[i]) == "string" then - -- xml.write(TERM_WHITE, t[i].."\n") - else - xml:english_xml(t[i], nextlevel, children_not_flag) - end - end -end - -function xml:print_xml(t, tab) - local i, k, e - local inside = nil - local bcol, ecol = TERM_L_GREEN, TERM_GREEN - - if xml.write_active and t == auto_aux.rule then bcol, ecol = TERM_VIOLET, TERM_VIOLET end - - xml.write(bcol, tab.."<"..t.label) - for k, e in t.args do - xml.write(TERM_L_BLUE, " "..k) - xml.write(TERM_WHITE, "=\"") - xml.write(TERM_YELLOW, e) - xml.write(TERM_WHITE, "\"") - end - xml.write(bcol, ">") - - for i = 1, getn(t) do - if type(t[i]) == "string" then - xml.write(TERM_WHITE, t[i]) - else - if not inside then xml.write(TERM_WHITE, "\n") end - inside = not nil - xml:print_xml(t[i], tab.." ") - end - end - - if not inside then - xml.write(ecol, "\n") - else - xml.write(ecol, tab.."\n") - end -end - --- t is a table representing xml, outputs the xml code via xml.write() -function xml:output(t) - local i - for i = 1, getn(t) do - xml:print_xml(t[i], "") - end -end diff --git a/src/dungeon.c b/src/dungeon.c index af46976d..ce259344 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -5420,7 +5420,11 @@ static void load_all_pref_files(void) process_pref_file(buf); /* Process player specific automatizer sets */ - tome_dofile_anywhere(ANGBAND_DIR_USER, format("%s.atm", player_name), FALSE); + /* TODO: Disabled temporarily because it causes duplicate + * rules on save and subsequent game load. */ + /* sprintf(buf2, "%s.atm", player_name); */ + /* path_build(buf, sizeof(buf), ANGBAND_DIR_USER, buf2); */ + /* automatizer_init(buf); */ } /* diff --git a/src/externs.h b/src/externs.h index f2c38f08..71d7b393 100644 --- a/src/externs.h +++ b/src/externs.h @@ -994,7 +994,7 @@ extern u32b fake_text_size; extern bool_ gen_joke_monsters(void *data, void *in, void *out); /* loadsave.c */ -extern bool_ file_exist(char *buf); +extern bool_ file_exist(cptr buf); extern s16b rd_variable(void); extern void wr_variable(s16b *var); extern void wr_scripts(void); @@ -2275,7 +2275,7 @@ extern void squeltch_grid(void); extern void do_cmd_automatizer(void); extern void automatizer_add_rule(object_type *o_ptr, bool_ destroy); extern bool_ automatizer_create; - +extern void automatizer_init(cptr file_name); /* @@ -2363,6 +2363,7 @@ extern bool_ module_savefile_loadable(cptr savefile_mod); extern void tome_intro(); extern void theme_intro(); extern void init_hooks_module(); +extern int find_module(cptr name); /* lua_bind.c */ diff --git a/src/init2.c b/src/init2.c index 0ce8c1a0..2f897d9b 100644 --- a/src/init2.c +++ b/src/init2.c @@ -2779,8 +2779,8 @@ void init_angband(void) process_pref_file(buf); /* Initialise the automatizer */ - tome_dofile_anywhere(ANGBAND_DIR_CORE, "auto.lua", TRUE); - tome_dofile_anywhere(ANGBAND_DIR_USER, "automat.atm", FALSE); + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "automat.atm"); + automatizer_init(buf); /* Done */ note("[Initialisation complete]"); diff --git a/src/loadsave.c b/src/loadsave.c index 45f493a6..08cb53b3 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -854,7 +854,7 @@ bool_ save_player(void) return (result); } -bool_ file_exist(char *buf) +bool_ file_exist(cptr buf) { int fd; bool_ result; diff --git a/src/modules.c b/src/modules.c index c4bea6eb..9376cc3d 100644 --- a/src/modules.c +++ b/src/modules.c @@ -181,6 +181,22 @@ bool_ module_savefile_loadable(cptr savefile_mod) /* Did the player force a module on command line */ cptr force_module = NULL; +/* Find module index by name. Returns -1 if matching module not found */ +int find_module(cptr name) +{ + int i = 0; + + for (i=0; i -extern lua_State *L; +#define RULES_MAX 4096 +#define STACK_MAX 1024 + +typedef enum { BAD, VERY_BAD, AVERAGE, + GOOD, VERY_GOOD, SPECIAL, + TERRIBLE, NONE, CHEST_EMPTY, + CHEST_DISARMED } status_type; + +struct status_map_type { + status_type status; + cptr status_s; +}; + +status_type object_status(object_type *o_ptr) +{ + if (!object_known_p(o_ptr)) + { + switch (o_ptr->sense) + { + case SENSE_CURSED: return BAD; + case SENSE_WORTHLESS: return VERY_BAD; + case SENSE_AVERAGE: return AVERAGE; + case SENSE_GOOD_LIGHT: return GOOD; + case SENSE_GOOD_HEAVY: return GOOD; + case SENSE_EXCELLENT: return VERY_GOOD; + case SENSE_SPECIAL: return SPECIAL; + case SENSE_TERRIBLE: return TERRIBLE; + default: return NONE; + } + } + else + { + s16b slot = wield_slot_ideal(o_ptr, TRUE); + + if (artifact_p(o_ptr)) + { + if (!(o_ptr->ident & IDENT_CURSED)) + { + return SPECIAL; + } + else + { + return TERRIBLE; + } + } + else if ((o_ptr->name2 > 0) || + (o_ptr->name2b > 0)) + { + if (!(o_ptr->ident & IDENT_CURSED)) + { + return VERY_GOOD; + } + else + { + return VERY_BAD; + } + } + else if ((slot == INVEN_WIELD) || + (slot == INVEN_BOW) || + (slot == INVEN_AMMO) || + (slot == INVEN_TOOL)) + { + if (o_ptr->to_h + o_ptr->to_d < 0) + { + return BAD; + } + else if (o_ptr->to_h + o_ptr->to_d > 0) + { + return GOOD; + } + else + { + return AVERAGE; + } + } + else if ((slot >= INVEN_BODY) && + (slot <= INVEN_FEET)) + { + if (o_ptr->to_a < 0) + { + return BAD; + } + else if (o_ptr->to_a > 0) + { + return GOOD; + } + else + { + return AVERAGE; + } + } + else if (slot == INVEN_RING) + { + if ((o_ptr->to_d + o_ptr->to_h < 0) || + (o_ptr->to_a < 0) || + (o_ptr->pval < 0)) + { + return BAD; + } + else + { + return AVERAGE; + } + } + else if (slot == INVEN_NECK) + { + if (o_ptr->pval < 0) + { + return BAD; + } + else + { + return AVERAGE; + } + } + else if (o_ptr->tval == TV_CHEST) + { + if (o_ptr->pval == 0) + { + return CHEST_EMPTY; + } + else if (o_ptr->pval < 0) + { + return CHEST_DISARMED; + } + else + { + return AVERAGE; + } + } + else + { + return AVERAGE; + } + } +} + +#define STATUS_MAP_SIZE 10 +struct status_map_type status_map[STATUS_MAP_SIZE] = { + { BAD, "bad" }, + { VERY_BAD, "very bad" }, + { AVERAGE, "average" }, + { GOOD, "good" }, + { VERY_GOOD, "very good" }, + { SPECIAL, "special" }, + { TERRIBLE, "terrible" }, + { NONE, "none" }, + { CHEST_EMPTY, "(empty chest)" }, + { CHEST_DISARMED, "(disarmed chest)" }, +}; + +static cptr status_to_string(status_type status) +{ + int i; + + for (i = 0; i < STATUS_MAP_SIZE; i++) + { + if (status_map[i].status == status) + { + return status_map[i].status_s; + } + } + + assert(FALSE); + return NULL; +} + +static bool_ status_from_string(cptr s, status_type *status) +{ + int i; + + for (i = 0; i < STATUS_MAP_SIZE; i++) + { + if (streq(status_map[i].status_s, s)) + { + *status = status_map[i].status; + return TRUE; + } + } + + return FALSE; +} + +/* Type of automatizer actions */ +typedef enum { AUTO_DESTROY, + AUTO_PICKUP, + AUTO_INSCRIBE } action_type; + +/* Convert action to/from string */ +struct action_map_type { + action_type action; + cptr action_s; +}; + +#define ACTION_MAP_SIZE 3 +struct action_map_type action_map[ACTION_MAP_SIZE] = { + { AUTO_DESTROY, "destroy" }, + { AUTO_PICKUP, "pickup" }, + { AUTO_INSCRIBE, "inscribe" } +}; + +static cptr action_to_string(action_type action) +{ + int i = 0; + + for (i = 0; i < ACTION_MAP_SIZE; i++) + { + if (action == action_map[i].action) + { + return action_map[i].action_s; + } + } + + assert(FALSE); + return NULL; +} + +static bool_ action_from_string(cptr s, action_type *action) +{ + int i = 0; + + for (i = 0; i < ACTION_MAP_SIZE; i++) + { + if (streq(action_map[i].action_s, s)) + { + *action = action_map[i].action; + return TRUE; + } + } + + return FALSE; +} + +/* Identification state */ +typedef enum { IDENTIFIED, NOT_IDENTIFIED } identification_state; + +#define S_IDENTIFIED "identified" +#define S_NOT_IDENTIFIED "not identified" + +cptr identification_state_to_string(identification_state i) +{ + switch (i) + { + case IDENTIFIED: return S_IDENTIFIED; + case NOT_IDENTIFIED: return S_NOT_IDENTIFIED; + } + + assert(FALSE); + return NULL; +} + +bool_ identification_state_from_string(cptr s, identification_state *state) +{ + if (streq(s, S_IDENTIFIED)) + { + *state = IDENTIFIED; + return TRUE; + } + else if (streq(s, S_NOT_IDENTIFIED)) + { + *state = NOT_IDENTIFIED; + return TRUE; + } + else + { + return FALSE; + } +} + +/* Match type */ +typedef enum { M_AND , M_OR , M_NOT , M_NAME , M_CONTAIN , + M_INSCRIBED, M_DISCOUNT, M_SYMBOL , M_STATE , M_STATUS , + M_TVAL , M_SVAL , M_RACE , M_SUBRACE , M_CLASS , + M_LEVEL , M_SKILL , M_ABILITY, M_INVENTORY, M_EQUIPMENT } + match_type; + +struct match_type_map { + match_type i; + cptr s; +}; + +#define MATCH_TYPE_MAP_SIZE 20 +struct match_type_map match_type_map[MATCH_TYPE_MAP_SIZE] = { + { M_AND, "and" }, + { M_OR, "or" }, + { M_NOT, "not" }, + { M_NAME, "name" }, + { M_CONTAIN, "contain" }, + { M_INSCRIBED, "inscribed" }, + { M_DISCOUNT, "discount" }, + { M_SYMBOL, "symbol" }, + { M_STATE, "state" }, + { M_STATUS, "status" }, + { M_TVAL, "tval" }, + { M_SVAL, "sval" }, + { M_RACE, "race" }, + { M_SUBRACE, "subrace" }, + { M_CLASS, "class" }, + { M_LEVEL, "level" }, + { M_SKILL, "skill" }, + { M_ABILITY, "ability" }, + { M_INVENTORY, "inventory" }, + { M_EQUIPMENT, "equipment" }, +}; + +cptr match_type_to_string(match_type m) +{ + int i; + + for (i = 0; i < MATCH_TYPE_MAP_SIZE; i++) + { + if (match_type_map[i].i == m) + { + return match_type_map[i].s; + } + } + + assert(FALSE); + return NULL; +} + +bool_ match_type_from_string(cptr s, match_type *match) +{ + int i; + + for (i = 0; i < MATCH_TYPE_MAP_SIZE; i++) + { + if (streq(match_type_map[i].s, s)) + { + *match = match_type_map[i].i; + return TRUE; + } + } + + return FALSE; +} + +/* Forward declarations */ +typedef struct condition_type condition_type; +struct condition_type; + +/* List of conditions */ +typedef struct condition_list condition_list; +struct condition_list { + condition_type *condition; + condition_list *next; +}; + +int compare_condition_list(condition_list *a, condition_list *b) +{ + assert(FALSE); +} + +SGLIB_DEFINE_LIST_PROTOTYPES(condition_list, compare_condition_list, next); +SGLIB_DEFINE_LIST_FUNCTIONS(condition_list, compare_condition_list, next); + +/* Condition instance */ +struct condition_type +{ + /* What do we want to match? */ + match_type match; + /* Sub-conditions for logical connectives; if applicable */ + struct { + condition_list *c; + } conditions; + /* Sub-condition for cases where there is only a single subcondition */ + condition_type *subcondition; + /* Tval to match if applicable. */ + byte tval; + /* Sval range if applicable. */ + struct { + byte min; + byte max; + } sval_range; + /* Discount range. */ + struct { + int min; + int max; + } discount; + /* Level range */ + struct { + int min; + int max; + } level_range; + /* Skill range */ + struct { + s16b min; + s16b max; + s16b skill_idx; + } skill_range; + /* Identification state to match if applicable */ + identification_state identification_state; + /* Status to match if applicable */ + status_type status; + /* Name to match */ + char *name; + /* Symbol to match if applicable */ + char symbol; + /* Inscription to find */ + char *inscription; + /* Subrace to match if applicable */ + char *subrace; + /* Race to match if applicable */ + char *race; + /* Class to match if applicable */ + char *klass; + /* Ability to match if applicable */ + s16b ability; + /* Comment */ + char *comment; +}; + +static condition_type *condition_new(match_type match) +{ + condition_type *cp = malloc(sizeof(condition_type)); + memset(cp, 0, sizeof(condition_type)); + cp->match = match; + return cp; +} + +static condition_type *condition_new_tval(byte tval) +{ + condition_type *cp = condition_new(M_TVAL); + cp->tval = tval; + return cp; +} + +static condition_type *condition_new_sval(byte min, byte max) +{ + condition_type *cp = condition_new(M_SVAL); + cp->sval_range.min = min; + cp->sval_range.max = max; + return cp; +} + +static condition_type *condition_new_and() +{ + condition_type *cp = condition_new(M_AND); + return cp; +} + +static condition_type *condition_new_or() +{ + condition_type *cp = condition_new(M_OR); + return cp; +} + +static condition_type *condition_new_not() +{ + condition_type *cp = condition_new(M_NOT); + return cp; +} + +static condition_type *condition_new_name(cptr name) +{ + condition_type *cp = condition_new(M_NAME); + cp->name = strdup(name); + return cp; +} + +static condition_type *condition_new_contain(cptr name) +{ + condition_type *cp = condition_new(M_CONTAIN); + cp->name = strdup(name); + return cp; +} + +static condition_type *condition_new_inscribed(cptr name) +{ + condition_type *cp = condition_new(M_INSCRIBED); + cp->inscription = strdup(name); + return cp; +} + +static condition_type *condition_new_status(status_type status) +{ + condition_type *cp = condition_new(M_STATUS); + cp->status = status; + return cp; +} + +static condition_type *condition_new_state(identification_state state) +{ + condition_type *cp = condition_new(M_STATE); + cp->identification_state = state; + return cp; +} + +static condition_type *condition_new_discount(int min, int max) +{ + condition_type *cp = condition_new(M_DISCOUNT); + cp->discount.min = min; + cp->discount.max = max; + return cp; +} + +static condition_type *condition_new_symbol(char c) +{ + condition_type *cp = condition_new(M_SYMBOL); + cp->symbol = c; + return cp; +} + +static condition_type *condition_new_race(cptr race) +{ + condition_type *cp = condition_new(M_RACE); + cp->race = strdup(race); + return cp; +} + +static condition_type *condition_new_subrace(cptr subrace) +{ + condition_type *cp = condition_new(M_SUBRACE); + cp->subrace = strdup(subrace); + return cp; +} + +static condition_type *condition_new_class(cptr klass) +{ + condition_type *cp = condition_new(M_CLASS); + cp->klass = strdup(klass); + return cp; +} + +static condition_type *condition_new_level(int min, int max) +{ + condition_type *cp = condition_new(M_LEVEL); + cp->level_range.min = min; + cp->level_range.max = max; + return cp; +} + +static condition_type *condition_new_skill(s16b min, s16b max, s16b skill_idx) +{ + condition_type *cp = condition_new(M_SKILL); + cp->skill_range.min = min; + cp->skill_range.max = max; + cp->skill_range.skill_idx = skill_idx; + return cp; +} + +static condition_type *condition_new_ability(s16b ability_idx) +{ + condition_type *cp = condition_new(M_ABILITY); + cp->ability = ability_idx; + return cp; +} + +static condition_type *condition_new_inventory() +{ + condition_type *cp = condition_new(M_INVENTORY); + return cp; +} + +static condition_type *condition_new_equipment() +{ + condition_type *cp = condition_new(M_EQUIPMENT); + return cp; +} + +static void condition_and_add(condition_type *and_c, condition_type *c) +{ + assert(and_c != NULL); + assert(c != NULL); + assert((and_c->match == M_AND) || (and_c->match == M_OR)); + + condition_list *cl = malloc(sizeof(condition_list)); + cl->condition = c; + cl->next = NULL; + + sglib_condition_list_add(&and_c->conditions.c, cl); +} + +static void condition_or_add(condition_type *or_c, condition_type *c) +{ + condition_and_add(or_c, c); +} + +static void condition_destroy(condition_type **cp) +{ + condition_type *c = NULL; + assert(cp != NULL); + assert(*cp != NULL); + + c = *cp; + + /* Free sub-conditions if any */ + { + condition_list *current = NULL; + condition_list *next = NULL; + + for (current = c->conditions.c; + current != NULL; + current = next) + { + condition_destroy(¤t->condition); + next = current->next; + free(current); + } + } + + /* Free sub-condition if any */ + if (c->subcondition) + { + condition_destroy(&c->subcondition); + } + + /* Free name if any */ + if (c->name) + { + free(c->name); + c->name = NULL; + } + + /* Free inscription if any */ + if (c->inscription) + { + free(c->inscription); + c->inscription = NULL; + } + + /* Free subrace if any */ + if (c->subrace) + { + free(c->subrace); + c->subrace = NULL; + } + + /* Free race if any */ + if (c->race) + { + free(c->race); + c->race = NULL; + } + + /* Free class if any */ + if (c->klass) + { + free(c->klass); + c->klass = NULL; + } + + /* Free comment if any */ + if (c->comment) + { + free(c->comment); + c->comment = NULL; + } + + /* Free the condition itself */ + free(*cp); + *cp = NULL; +} + +static bool_ condition_eval(condition_type *c, object_type *o_ptr) +{ + bool_ is_and = (c->match == M_AND); + bool_ is_or = (c->match == M_OR); + + switch (c->match) + { + case M_AND: + case M_OR: + { + struct sglib_condition_list_iterator it; + struct condition_list *child = NULL; + + for (child = sglib_condition_list_it_init(&it, c->conditions.c); + child != NULL; + child = sglib_condition_list_it_next(&it)) + { + if (is_and && (!condition_eval(child->condition, o_ptr))) + { + return FALSE; + } + + if (is_or && condition_eval(child->condition, o_ptr)) + { + return TRUE; + } + } + + if (is_and) + { + return TRUE; + } + else + { + return FALSE; + } + } + + case M_NOT: + { + if (c->subcondition == NULL) + { + return TRUE; + } + + return !condition_eval(c->subcondition, o_ptr); + } + + case M_INVENTORY: + { + int i; + + if (c->subcondition == NULL) + { + return FALSE; + } + + for (i = 0; i < INVEN_WIELD; i++) + { + if (condition_eval(c->subcondition, &p_ptr->inventory[i])) + { + return TRUE; + } + } + + return FALSE; + } + + case M_EQUIPMENT: + { + int i; + + if (c->subcondition == NULL) + { + return FALSE; + } + + for (i = INVEN_WIELD; i < INVEN_TOTAL; i++) + { + if (condition_eval(c->subcondition, &p_ptr->inventory[i])) + { + return TRUE; + } + } + + return FALSE; + } + + case M_NAME: + { + char buf1[128]; + char buf2[128]; + + object_desc(buf1, o_ptr, -1, 0); + strlower(buf1); + + sprintf(buf2, "%s", c->name); + strlower(buf2); + + return streq(buf1, buf2); + } + + case M_CONTAIN: + { + char buf1[128]; + char buf2[128]; + + object_desc(buf1, o_ptr, -1, 0); + strlower(buf1); + + sprintf(buf2, "%s", c->name); + strlower(buf2); + + return (strstr(buf1, buf2) != NULL); + } + + case M_SYMBOL: + { + object_kind *k_ptr = &k_info[o_ptr->k_idx]; + + return k_ptr->d_char == c->symbol; + } + + case M_INSCRIBED: + { + char buf1[128]; + char buf2[128]; + + if (o_ptr->note == 0) + { + return FALSE; + } + + sprintf(buf1, "%s", quark_str(o_ptr->note)); + strlower(buf1); + + sprintf(buf2, "%s", c->inscription); + strlower(buf2); + + return (strstr(buf1, buf2) != NULL); + } + + case M_DISCOUNT: + { + return (object_aware_p(o_ptr) && + (o_ptr->discount >= c->discount.min) && + (o_ptr->discount <= c->discount.max)); + } + + case M_TVAL: + { + return (o_ptr->tval == c->tval); + } + + case M_SVAL: + { + return (object_aware_p(o_ptr) && + (o_ptr->sval >= c->sval_range.min) && + (o_ptr->sval <= c->sval_range.max)); + } + + case M_STATUS: + { + return c->status == object_status(o_ptr); + } + + case M_STATE: + { + switch (c->identification_state) + { + case IDENTIFIED: + return object_known_p(o_ptr); + case NOT_IDENTIFIED: + return !object_known_p(o_ptr); + default: + assert(FALSE); + } + } + + case M_RACE: + { + char buf1[128]; + char buf2[128]; + + sprintf(buf1, "%s", rp_ptr->title + rp_name); + strlower(buf1); + + sprintf(buf2, "%s", c->race); + strlower(buf2); + + return streq(buf1, buf2); + } + + case M_SUBRACE: + { + char buf1[128]; + char buf2[128]; + + sprintf(buf1, "%s", rmp_ptr->title + rmp_name); + strlower(buf1); + + sprintf(buf2, "%s", c->subrace); + strlower(buf2); + + return streq(buf1, buf2); + } + + case M_CLASS: + { + char buf1[128]; + char buf2[128]; + + sprintf(buf1, "%s", spp_ptr->title + c_name); + strlower(buf1); + + sprintf(buf2, "%s", c->race); + strlower(buf2); + + return streq(buf1, buf2); + } + + case M_LEVEL: + { + return ((p_ptr->lev >= c->level_range.min) && + (p_ptr->lev <= c->level_range.max)); + } + + case M_SKILL: + { + s16b sk = get_skill(c->skill_range.skill_idx); + return ((sk >= c->skill_range.min) && + (sk <= c->skill_range.max)); + } + + case M_ABILITY: + { + return has_ability(c->ability); + } + + } + + /* Don't match by default */ + return FALSE; +} + +static json_t *condition_to_json(condition_type *c) +{ + json_t *json = NULL; + + if (c == NULL) + { + return json_null(); + } + + json = json_object(); + json_object_set_new(json, "type", + json_string(match_type_to_string(c->match))); + + switch (c->match) + { + case M_AND: + case M_OR: + { + struct sglib_condition_list_iterator it; + struct condition_list *child = NULL; + + json_t *conditions_json = json_array(); + + for (child = sglib_condition_list_it_init(&it, c->conditions.c); + child != NULL; + child = sglib_condition_list_it_next(&it)) + { + json_array_append_new(conditions_json, + condition_to_json(child->condition)); + } + + json_object_set_new(json, "conditions", conditions_json); + break; + } + + case M_NOT: + case M_INVENTORY: + case M_EQUIPMENT: + { + json_object_set_new(json, "condition", + condition_to_json(c->subcondition)); + break; + } + + case M_NAME: + { + json_object_set_new(json, "name", + json_string(c->name)); + break; + } + + case M_CONTAIN: + { + json_object_set_new(json, "contain", + json_string(c->name)); + break; + } + + case M_SYMBOL: + { + json_object_set_new(json, "symbol", + json_string(format("%c", c->symbol))); + break; + } + + case M_INSCRIBED: + { + json_object_set_new(json, "inscription", + json_string(c->inscription)); + break; + } + + case M_DISCOUNT: + { + json_object_set_new(json, "min", + json_integer(c->discount.min)); + json_object_set_new(json, "max", + json_integer(c->discount.max)); + break; + } + + case M_TVAL: + { + json_object_set_new(json, "tval", + json_integer(c->tval)); + break; + } + + case M_SVAL: + { + json_object_set_new(json, "min", + json_integer(c->sval_range.min)); + json_object_set_new(json, "max", + json_integer(c->sval_range.max)); + break; + } + + case M_STATUS: + { + json_object_set_new(json, "status", + json_string(status_to_string(c->status))); + break; + } + + case M_STATE: + { + json_object_set_new(json, "state", + json_string(identification_state_to_string(c->identification_state))); + break; + } + + case M_RACE: + { + json_object_set_new(json, "race", + json_string(c->race)); + break; + } + + case M_SUBRACE: + { + json_object_set_new(json, "subrace", + json_string(c->subrace)); + break; + } + + case M_CLASS: + { + json_object_set_new(json, "class", + json_string(c->klass)); + break; + } + + case M_LEVEL: + { + json_object_set_new(json, "min", + json_integer(c->level_range.min)); + json_object_set_new(json, "max", + json_integer(c->level_range.max)); + break; + } + + case M_SKILL: + { + json_object_set_new(json, "name", + json_string(s_info[c->skill_range.skill_idx].name + s_name)); + json_object_set_new(json, "min", + json_integer(c->skill_range.min)); + json_object_set_new(json, "max", + json_integer(c->skill_range.max)); + break; + } + + case M_ABILITY: + { + json_object_set_new(json, "ability", + json_string(ab_info[c->ability].name + ab_name)); + break; + } + + } + + return json; +} /* - * The functions here use direct lua stack manipulation for calls instead of - * exec_lua(format()) because string manipulations are too slow for such - * functions + * Cursor to maintain position in condition tree */ +static condition_type *cursor_stack[STACK_MAX]; +static int cursor_count = 0; + +static void cursor_push(condition_type *condition) +{ + assert(cursor_count < STACK_MAX); + + cursor_stack[cursor_count] = condition; + cursor_count++; +} + +static condition_type *cursor_pop() +{ + condition_type *c = NULL; + + assert(cursor_count > 0); + + c = cursor_stack[cursor_count-1]; + cursor_stack[cursor_count] = NULL; + cursor_count--; + return c; +} + +static condition_type *cursor_top() +{ + assert(cursor_count > 0); + + return cursor_stack[cursor_count - 1]; +} + +static void cursor_clear() +{ + while (cursor_count > 0) + { + cursor_pop(); + } +} + +/* Rule */ +typedef struct arule_type arule_type; +struct arule_type { + /* Rule name */ + char *name; + /* Which action do we take? */ + action_type action; /* Which action to take */ + /* Which module does this rule apply to? */ + int module_idx; + /* Inscription to use for inscription rules. */ + char *inscription; + /* Condition. */ + condition_type *condition; /* Condition for rule match */ +}; + +/* Initialize a rule */ +static arule_type *rule_new(cptr name, action_type action, int module_idx, condition_type *condition, cptr inscription) +{ + arule_type *rp = malloc(sizeof(arule_type)); + rp->name = strdup(name); + rp->action = action; + rp->module_idx = module_idx; + rp->condition = condition; + rp->inscription = (inscription == NULL) ? NULL : strdup(inscription); + return rp; +} + +static void rule_set_name(arule_type *rule, cptr new_name) +{ + if (rule->name) + { + free(rule->name); + } + + rule->name = strdup(new_name); +} + +static void rule_destroy(arule_type **rp) +{ + if ((*rp)->name) + { + free((*rp)->name); + } + + if ((*rp)->inscription) + { + free((*rp)->inscription); + } + + if ((*rp)->condition) + { + condition_destroy(&(*rp)->condition); + } + + free(*rp); + *rp = NULL; +} + +/* Current list of rules. */ +static arule_type *rules[RULES_MAX]; +static int rules_count = 0; /* Number of rules currently in list */ + +static int rules_append(arule_type *rule) +{ + assert(rules_count < RULES_MAX); + + rules[rules_count] = rule; + rules_count++; + return rules_count-1; +} + +static void rules_remove(arule_type *rule) +{ + int i, j; + + for (i = 0; i < rules_count; i++) + { + if (rules[i] == rule) + { + /* Free the rule */ + rule_destroy(&rule); + /* Move rest of rest "up" */ + for (j = i+1; j < rules_count; j++) + { + rules[j-1] = rules[j]; + } + /* We're done */ + rules_count--; + return; + } + } +} + +static void rules_swap(int i, int j) +{ + arule_type *tmp_rptr = NULL; + + assert(i >= 0); + assert(i < rules_count); + + assert(j >= 0); + assert(j < rules_count); + + tmp_rptr = rules[i]; + rules[i] = rules[j]; + rules[j] = tmp_rptr; +} + +static bool_* automatizer_auto_destroy(object_type *o_ptr, int item_idx) +{ + static bool_ TRUE_VAL = TRUE; + + /* Must be identified */ + if (object_aware_p(o_ptr) == FALSE) + { + return NULL; + } + + /* Inscribed things won't be destroyed! */ + if (o_ptr->note) + { + return NULL; + } + + /* Ignore artifacts; cannot be destroyed anyway. */ + if (artifact_p(o_ptr)) + { + return NULL; + } + + /* Cannot destroy CURSE_NO_DROP objects. */ + { + u32b f1, f2, f3, f4, f5, esp; + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + if ((f4 & TR4_CURSE_NO_DROP) != 0) + { + return NULL; + } + } + + /* Destroy! */ + msg_print(""); + + inc_stack_size(item_idx, -o_ptr->number); + return &TRUE_VAL; +} + +static bool_* automatizer_auto_pickup(object_type *o_ptr, int item_idx) +{ + static bool_ TRUE_VAL = TRUE; + + if (item_idx >= 0) + { + return NULL; + } + + if (!inven_carry_okay(o_ptr)) + { + return NULL; + } + + msg_print(""); + + object_pickup(-item_idx); + return &TRUE_VAL; +} + +/* Apply rules */ +static bool_ apply_rule(arule_type *rule, object_type *o_ptr, int item_idx) +{ + /* Check module */ + if (rule->module_idx == game_module_idx) + { + return FALSE; + } + + /* Check condition */ + assert (rule->condition != NULL); + if (condition_eval(rule->condition, o_ptr)) + { + switch (rule->action) + { + + case AUTO_DESTROY: + { + automatizer_auto_destroy(o_ptr, item_idx); + break; + } + + case AUTO_PICKUP: + { + automatizer_auto_pickup(o_ptr, item_idx); + break; + } + + case AUTO_INSCRIBE: + { + /* Already inscribed? */ + if (o_ptr->note != 0) + { + return FALSE; + } + + /* Inscribe */ + msg_format("", rule->inscription); + o_ptr->note = quark_add(rule->inscription); + break; + } + + } + + return TRUE; + } + + return FALSE; +} + +static bool_ apply_rules(object_type *o_ptr, int item_idx) +{ + int i; + + for (i = 0; i < rules_count; i++) + { + if (apply_rule(rules[i], o_ptr, item_idx)) + { + return TRUE; + } + } + + /* Don't keep trying */ + return FALSE; +} + +static json_t *rule_to_json(arule_type *rule) +{ + json_t *rule_json = json_object(); + + json_object_set_new(rule_json, + "name", + json_string(rule->name)); + json_object_set_new(rule_json, + "action", + json_string(action_to_string(rule->action))); + json_object_set_new(rule_json, + "module", + json_string(modules[rule->module_idx].meta.name)); + + if (rule->inscription) + { + json_object_set_new(rule_json, + "inscription", + json_string(rule->inscription)); + } + + json_object_set_new(rule_json, + "condition", + condition_to_json(rule->condition)); + + return rule_json; +} + +static json_t *rules_to_json() +{ + int i; + json_t *rules_json = json_array(); + + for (i = 0; i < rules_count; i++) + { + json_array_append_new(rules_json, rule_to_json(rules[i])); + } + + return rules_json; +} + +/* Check the floor for "crap" */ +void squeltch_grid(void) +{ + s16b this_o_idx, next_o_idx = 0; + + if (!automatizer_enabled) return; + + /* Scan the pile of objects */ + for (this_o_idx = cave[p_ptr->py][p_ptr->px].o_idx; this_o_idx; this_o_idx = next_o_idx) + { + /* Acquire object */ + object_type * o_ptr = &o_list[this_o_idx]; + + /* We've now seen one of these */ + if (!k_info[o_ptr->k_idx].flavor) + { + object_aware(o_ptr); + } + + /* Acquire next object */ + next_o_idx = o_ptr->next_o_idx; + + /* Apply rules */ + apply_rules(o_ptr, -this_o_idx); + } +} + + +/* Check the inventory for "crap" */ +void squeltch_inventory(void) +{ + int i; + int num_iter = 0; + bool_ found = TRUE; + + if (!automatizer_enabled) return; + + while (found && num_iter ++ < 100) + { + /* Sometimes an index in the inventory is skipped */ + found = FALSE; + + for (i = 0; i < INVEN_PACK; i++) + { + object_type *o_ptr = &p_ptr->inventory[i]; + + if (apply_rules(o_ptr, i)) + { + found = TRUE; + break; + } + } + } + if (num_iter >= 100) + { + cmsg_format(TERM_VIOLET, "'apply_rules' ran too often."); + } +} + +/********************** The interface **********************/ +static void get_rule_names(cptr *list) +{ + int i; + + for (i = 0; i < rules_count; i++) + { + list[i] = rules[i]->name; + } +} + +typedef struct condition_metadata condition_metadata; +struct condition_metadata { + match_type match; + cptr description[3]; + condition_type *(*create_condition)(); +}; + +#define TYPES_LIST_SIZE 21 + +static condition_type *create_condition_name() +{ + cptr s = lua_input_box("Object name to match?", 79); + if (strlen(s) == 0) + { + return NULL; + } + + return condition_new_name(s); +} + +static condition_type *create_condition_contain() +{ + cptr s = lua_input_box("Word to find in object name?", 79); + if (strlen(s) == 0) + { + return NULL; + } + + return condition_new_contain(s); +} + +static condition_type *create_condition_inscribed() +{ + cptr s = lua_input_box("Word to find in object inscription?", 79); + if (strlen(s) == 0) + { + return NULL; + } + + return condition_new_inscribed(s); +} + +static condition_type *create_condition_discount() +{ + int min, max; + + { + cptr s = lua_input_box("Min discount?", 79); + if (sscanf(s, "%d", &min) < 1) + { + return NULL; + } + } + + { + cptr s = lua_input_box("Max discount?", 79); + if (sscanf(s, "%d", &max) < 1) + { + return NULL; + } + } + + return condition_new_discount(min, max); +} + +static condition_type *create_condition_symbol() +{ + char c; + cptr s = lua_input_box("Symbol to match?", 1); + if (sscanf(s, "%c", &c) < 1) + { + return NULL; + } + + return condition_new_symbol(c); +} + +static condition_type *create_condition_status() +{ + status_type status; + char c; + + c = lua_msg_box("[t]errible, [v]ery bad, [b]ad, " + "[a]verage, [G]ood, [V]ery good, [S]pecial?"); + + switch (c) + { + case 't': status = TERRIBLE; break; + case 'v': status = VERY_BAD; break; + case 'b': status = BAD; break; + case 'a': status = AVERAGE; break; + case 'G': status = GOOD; break; + case 'V': status = VERY_GOOD; break; + case 'S': status = SPECIAL; break; + default: return NULL; + } + + return condition_new_status(status); +} + +static condition_type *create_condition_state() +{ + identification_state s; + char c; + + c = lua_msg_box("[i]dentified, [n]on identified?"); + + switch (c) + { + case 'i': s = IDENTIFIED; break; + case 'n': s = NOT_IDENTIFIED; break; + default: return NULL; + } + + return condition_new_state(s); +} + +static condition_type *create_condition_tval() +{ + int tval; + cptr s = lua_input_box("Tval to match?", 79); + if (sscanf(s, "%d", &tval) < 1) + { + return NULL; + } + + return condition_new_tval(tval); +} + +static condition_type *create_condition_sval() +{ + int sval_min, sval_max; + + { + cptr s = lua_input_box("Min sval?", 79); + if (sscanf(s, "%d", &sval_min) < 1) + { + return NULL; + } + } + + { + cptr s = lua_input_box("Max sval?", 79); + if (sscanf(s, "%d", &sval_max) < 1) + { + return NULL; + } + } + + return condition_new_sval(sval_min, sval_max); +} + +static condition_type *create_condition_race() +{ + cptr s = lua_input_box("Player race to match?", 79); + if (strlen(s) == 0) + { + return NULL; + } + + return condition_new_race(s); +} + +static condition_type *create_condition_subrace() +{ + cptr s = lua_input_box("Player subrace to match?", 79); + if (strlen(s) == 0) + { + return NULL; + } + + return condition_new_subrace(s); +} + +static condition_type *create_condition_class() +{ + cptr s = lua_input_box("Player class to match?", 79); + if (strlen(s) == 0) + { + return NULL; + } + + return condition_new_class(s); +} + +static condition_type *create_condition_level() +{ + int min, max; + + { + cptr s = lua_input_box("Min player level?", 79); + if (sscanf(s, "%d", &min) < 1) + { + return NULL; + } + } + + { + cptr s = lua_input_box("Max player level?", 79); + if (sscanf(s, "%d", &max) < 1) + { + return NULL; + } + } + + return condition_new_level(min, max); +} + +static condition_type *create_condition_skill() +{ + int min, max; + s16b skill_idx; + + { + cptr s = lua_input_box("Min skill level?", 79); + if (sscanf(s, "%d", &min) < 1) + { + return NULL; + } + } + + { + cptr s = lua_input_box("Max skill level?", 79); + if (sscanf(s, "%d", &max) < 1) + { + return NULL; + } + } + + { + cptr s = lua_input_box("Skill name?", 79); + if (strlen(s) == 0) + { + return NULL; + } + + skill_idx = find_skill_i(s); + if (skill_idx < 0) + { + return NULL; + } + } + + return condition_new_skill(min, max, skill_idx); +} + +static condition_type *create_condition_ability() +{ + s16b ai; + cptr s = lua_input_box("Ability name?", 79); + if (strlen(s) == 0) + { + return NULL; + } + + ai = find_ability(s); + if (ai < 0) + { + return NULL; + } + + return condition_new_ability(ai); +} + +static condition_metadata types_list[TYPES_LIST_SIZE] = +{ + { M_AND, + { "Check is true if all rules within it are true", + NULL }, + condition_new_and, + }, + { M_OR, + { "Check is true if at least one rule within it is true", + NULL }, + condition_new_or, + }, + { M_NOT, + { "Invert the result of its child rule", + NULL }, + condition_new_not, + }, + { M_NAME, + { "Check is true if object name matches name", + NULL }, + create_condition_name, + }, + { M_CONTAIN, + { "Check is true if object name contains word", + NULL }, + create_condition_contain, + }, + { M_INSCRIBED, + { "Check is true if object inscription contains word", + NULL }, + create_condition_inscribed, + }, + { M_DISCOUNT, + { "Check is true if object discount is between two values", + NULL }, + create_condition_discount, + }, + { M_SYMBOL, + { "Check is true if object symbol is ok", + NULL }, + create_condition_symbol, + }, + { M_STATE, + { "Check is true if object is identified/unidentified", + NULL }, + create_condition_state, + }, + { M_STATUS, + { "Check is true if object status is ok", + NULL }, + create_condition_status, + }, + { M_TVAL, + { "Check is true if object tval(from k_info.txt) is ok", + NULL }, + create_condition_tval, + }, + { M_SVAL, + { "Check is true if object sval(from k_info.txt) is between", + "two values", + NULL }, + create_condition_sval, + }, + { M_RACE, + { "Check is true if player race is ok", + NULL }, + create_condition_race, + }, + { M_SUBRACE, + { "Check is true if player subrace is ok", + NULL }, + create_condition_subrace, + }, + { M_CLASS, + { "Check is true if player class is ok", + NULL }, + create_condition_class, + }, + { M_LEVEL, + { "Check is true if player level is between 2 values", + NULL }, + create_condition_level, + }, + { M_SKILL, + { "Check is true if player skill level is between 2 values", + NULL }, + create_condition_skill, + }, + { M_ABILITY, + { "Check is true if player has the ability", + NULL }, + create_condition_ability, + }, + { M_INVENTORY, + { "Check is true if something in player's inventory matches", + "the contained rule", + NULL }, + condition_new_inventory, + }, + { M_EQUIPMENT, + { "Check is true if something in player's equipment matches", + "the contained rule", + NULL }, + condition_new_equipment, + }, +}; + +static void display_desc(condition_metadata *condition_metadata) +{ + int i; + + assert(condition_metadata != NULL); + + for (i = 0; condition_metadata->description[i] != NULL; i++) + { + c_prt(TERM_WHITE, condition_metadata->description[i], i + 1, 17); + } +} + +/* Create a new rule */ +static condition_metadata *automatizer_select_condition_type() +{ + int wid, hgt, max = TYPES_LIST_SIZE, begin = 0, sel = 0, i; + char c; + cptr types_names[TYPES_LIST_SIZE]; + + /* Create list of names for display */ + for (i = 0; i < TYPES_LIST_SIZE; i++) + { + types_names[i] = match_type_to_string(types_list[i].match); + } + + while (1) + { + Term_clear(); + Term_get_size(&wid, &hgt); + + display_list(0, 0, hgt - 1, 15, "Rule types", types_names, max, begin, sel, TERM_L_GREEN); + + display_desc(&types_list[sel]); + + c = inkey(); + + if (c == ESCAPE) break; + else if (c == '8') + { + sel--; + if (sel < 0) + { + sel = max - 1; + begin = max - hgt; + if (begin < 0) begin = 0; + } + if (sel < begin) begin = sel; + } + else if (c == '2') + { + sel++; + if (sel >= max) + { + sel = 0; + begin = 0; + } + if (sel >= begin + hgt - 1) begin++; + } + else if (c == '\r') + { + return &types_list[sel]; + } + } + return NULL; +} + +static void adjust_begin(int *begin, int *sel, int max, int hgt) +{ + if (*sel < 0) + { + *sel = max - 1; + *begin = *sel - hgt + 3; + if (*begin < 0) *begin = 0; + } + if (*sel < *begin) *begin = *sel; + + if (*sel >= max) + { + *sel = 0; + *begin = 0; + } + if (*sel >= *begin + hgt - 2) (*begin)++; +} + +static int create_new_rule() +{ + action_type action; + char name[20] = { '\0' }; + char *inscription = NULL; + int wid = 0, hgt = 0; + char typ; + arule_type *rule = NULL; + + Term_get_size(&wid, &hgt); + + sprintf(name, "%s", "No name"); + if (!input_box("Name?", hgt / 2, wid / 2, name, sizeof(name)+1)) + { + return -1; + } + + typ = lua_msg_box("[D]estroy, [P]ickup, [I]nscribe?"); + + switch (typ) + { + case 'd': + case 'D': + action = AUTO_DESTROY; + break; + + case 'p': + case 'P': + action = AUTO_PICKUP; + break; + + case 'i': + case 'I': + { + char *i = NULL; + + action = AUTO_INSCRIBE; + + i = lua_input_box("Inscription?", 79); + if ((i == NULL) || (strlen(i) == 0)) + { + return -1; + } + + inscription = i; + + break; + } + + default: + return -1; + } + + /* Make rule */ + rule = rule_new(name, action, game_module_idx, NULL, inscription); + + /* Append to list of rules */ + return rules_append(rule); +} + +static void add_child(condition_type *current) +{ + condition_metadata *metadata = NULL; + + switch (current->match) + { + case M_NOT: + case M_EQUIPMENT: + case M_INVENTORY: + { + if (current->subcondition != NULL) + { + return; + } + + metadata = automatizer_select_condition_type(); + if (metadata == NULL) + { + return; + } + + current->subcondition = metadata->create_condition(); + break; + } + + case M_AND: + metadata = automatizer_select_condition_type(); + if (metadata == NULL) + { + return; + } + condition_and_add(current, metadata->create_condition()); + break; + + case M_OR: + metadata = automatizer_select_condition_type(); + if (metadata == NULL) + { + return; + } + condition_or_add(current, metadata->create_condition()); + break; + + default: + /* No other types of conditions have children */ + break; + } +} + +static int tree_indent = 0; +static int tree_write_out_y = 0; +static int tree_write_out_x = 0; +static int tree_write_out_h = 0; +static int tree_write_out_w = 0; +static int tree_write_y = 0; +static int tree_write_x = 0; +static int tree_write_off_x = 0; +static int tree_write_off_y = 0; + +static void tree_write(byte color, cptr line) +{ + cptr p = line; + + for (p = line; *p != '\0'; p++) + { + char c = *p; + int x = tree_write_x - tree_write_off_x + 3*tree_indent; + int y = tree_write_y - tree_write_off_y; + + if (c != '\n') + { + if ((y >= 0) && + (y < tree_write_out_h) && + (x >= 0) && + (x < tree_write_out_w)) + { + Term_putch(x + tree_write_out_x, + y + tree_write_out_y, + color, + c); + } + + tree_write_x += 1; + } + else + { + tree_write_x = 0; + tree_write_y += 1; + } + } +} + +static void display_condition(condition_type *condition) +{ + byte bcol = TERM_L_GREEN; + byte ecol = TERM_GREEN; + int i; + + assert(condition != NULL); + + /* If this condition is present in the cursor stack, + then we use the "active" colors. */ + for (i = 0; i < cursor_count; i++) + { + if (cursor_stack[i] == condition) + { + bcol = TERM_VIOLET; + ecol = TERM_VIOLET; + break; + } + } + + tree_indent++; + + switch (condition->match) + { + case M_INVENTORY: + case M_EQUIPMENT: + { + cptr where_s = (condition->match == M_INVENTORY) + ? "inventory" + : "equipment"; + + tree_write(ecol, "Something in your "); + tree_write(bcol, where_s); + tree_write(ecol, " matches the following:"); + tree_write(TERM_WHITE, "\n"); + break; + } + + case M_SKILL: + { + cptr skill_name = + s_info[condition->skill_range.skill_idx].name + s_name; + + tree_write(ecol, "Your skill in "); + tree_write(bcol, skill_name); + tree_write(ecol, " is from "); + tree_write(TERM_WHITE, format("%d", (int) condition->skill_range.min)); + tree_write(ecol, " to "); + tree_write(TERM_WHITE, format("%d", (int) condition->skill_range.max)); + tree_write(TERM_WHITE, "\n"); + break; + } + + case M_ABILITY: + { + cptr ability_name = + ab_info[condition->ability].name + ab_name; + + tree_write(ecol, "You have the "); + tree_write(bcol, ability_name); + tree_write(ecol, " ability"); + tree_write(TERM_WHITE, "\n"); + break; + } + + case M_LEVEL: + { + tree_write(ecol, "Your "); + tree_write(bcol, "level"); + tree_write(ecol, " is from "); + + tree_write(TERM_WHITE, format("%d", condition->level_range.min)); + tree_write(ecol, " to "); + tree_write(TERM_WHITE, format("%d", condition->level_range.max)); + tree_write(TERM_WHITE, "\n"); + break; + } + + case M_SVAL: + { + tree_write(ecol, "Its "); + tree_write(bcol, "sval"); + tree_write(ecol, " is from "); + tree_write(TERM_WHITE, format("%d", condition->sval_range.min)); + tree_write(ecol, " to "); + tree_write(TERM_WHITE, format("%d", condition->sval_range.max)); + tree_write(TERM_WHITE, "\n"); + break; + } + + case M_DISCOUNT: + { + tree_write(ecol, "Its "); + tree_write(bcol, "discount"); + tree_write(ecol, " is from "); + tree_write(TERM_WHITE, format("%d", condition->discount.min)); + tree_write(ecol, " to "); + tree_write(TERM_WHITE, format("%d", condition->discount.max)); + tree_write(TERM_WHITE, "\n"); + break; + } + + case M_AND: + { + struct sglib_condition_list_iterator it; + struct condition_list *child = NULL; + + tree_write(ecol, "All of the following are true:"); + tree_write(TERM_WHITE, "\n"); + + for (child = sglib_condition_list_it_init(&it, condition->conditions.c); + child != NULL; + child = sglib_condition_list_it_next(&it)) + { + display_condition(child->condition); + } + + break; + } + + case M_OR: + { + struct sglib_condition_list_iterator it; + struct condition_list *child = NULL; + + tree_write(ecol, "At least one of the following are true:"); + tree_write(TERM_WHITE, "\n"); + + for (child = sglib_condition_list_it_init(&it, condition->conditions.c); + child != NULL; + child = sglib_condition_list_it_next(&it)) + { + display_condition(child->condition); + } + + break; + } -/* Check the floor for "crap" */ -void squeltch_grid(void) -{ - int oldtop; - s16b this_o_idx, next_o_idx = 0; + case M_NOT: + { + tree_write(ecol, "Negate the following:"); + tree_write(TERM_WHITE, "\n"); + display_condition(condition->subcondition); + break; + } - if (!automatizer_enabled) return; + case M_NAME: + { + tree_write(ecol, "Its "); + tree_write(bcol, "name"); + tree_write(ecol, " is \""); + tree_write(TERM_WHITE, condition->name); + tree_write(ecol, "\""); + tree_write(TERM_WHITE, "\n"); + break; + } - oldtop = lua_gettop(L); + case M_CONTAIN: + { + tree_write(ecol, "Its "); + tree_write(bcol, "name"); + tree_write(ecol, " contains \""); + tree_write(TERM_WHITE, condition->name); + tree_write(ecol, "\""); + tree_write(TERM_WHITE, "\n"); + break; + } - /* Scan the pile of objects */ - for (this_o_idx = cave[p_ptr->py][p_ptr->px].o_idx; this_o_idx; this_o_idx = next_o_idx) + case M_INSCRIBED: { - /* Acquire object */ - object_type * o_ptr = &o_list[this_o_idx]; + tree_write(ecol, "It is "); + tree_write(bcol, "inscribed"); + tree_write(ecol, " with "); + tree_write(ecol, "\""); + tree_write(TERM_WHITE, condition->inscription); + tree_write(ecol, "\""); + tree_write(TERM_WHITE, "\n"); + break; + } - /* We've now seen one of these */ - if (!k_info[o_ptr->k_idx].flavor) - { - object_aware(o_ptr); - } + case M_SYMBOL: + { + tree_write(ecol, "Its "); + tree_write(bcol, "symbol"); + tree_write(ecol, " is "); + tree_write(ecol, "\""); + tree_write(TERM_WHITE, format("%c", condition->symbol)); + tree_write(ecol, "\""); + tree_write(TERM_WHITE, "\n"); + break; + } - /* Acquire next object */ - next_o_idx = o_ptr->next_o_idx; + case M_STATE: + { + tree_write(ecol, "Its "); + tree_write(bcol, "state"); + tree_write(ecol, " is "); + tree_write(ecol, "\""); + tree_write(TERM_WHITE, identification_state_to_string(condition->identification_state)); + tree_write(ecol, "\""); + tree_write(TERM_WHITE, "\n"); + break; + } + + case M_STATUS: + { + tree_write(ecol, "Its "); + tree_write(bcol, "status"); + tree_write(ecol, " is "); + tree_write(ecol, "\""); + tree_write(TERM_WHITE, status_to_string(condition->status)); + tree_write(ecol, "\""); + tree_write(TERM_WHITE, "\n"); + break; + } + + case M_TVAL: + { + tree_write(ecol, "Its "); + tree_write(bcol, "tval"); + tree_write(ecol, " is "); + tree_write(ecol, "\""); + tree_write(TERM_WHITE, format("%d", condition->tval)); + tree_write(ecol, "\""); + tree_write(TERM_WHITE, "\n"); + break; + } - /* Push the function */ - lua_settop(L, oldtop); - lua_getglobal(L, "apply_rules"); + case M_RACE: + { + tree_write(ecol, "Player "); + tree_write(bcol, "race"); + tree_write(ecol, " is "); + tree_write(ecol, "\""); + tree_write(TERM_WHITE, condition->race); + tree_write(ecol, "\""); + tree_write(TERM_WHITE, "\n"); + break; + } - /* Push the args */ - tolua_pushusertype(L, o_ptr, tolua_tag(L, "object_type")); - tolua_pushnumber(L, -this_o_idx); + case M_SUBRACE: + { + tree_write(ecol, "Player "); + tree_write(bcol, "subrace"); + tree_write(ecol, " is "); + tree_write(ecol, "\""); + tree_write(TERM_WHITE, condition->subrace); + tree_write(ecol, "\""); + tree_write(TERM_WHITE, "\n"); + break; + } + + case M_CLASS: + { + tree_write(ecol, "Player "); + tree_write(bcol, "class"); + tree_write(ecol, " is "); + tree_write(ecol, "\""); + tree_write(TERM_WHITE, condition->klass); + tree_write(ecol, "\""); + tree_write(TERM_WHITE, "\n"); + break; + } - /* Call the function */ - if (lua_call(L, 2, 0)) - { - cmsg_format(TERM_VIOLET, "ERROR in lua_call while calling 'apply_rules'."); - lua_settop(L, oldtop); - return; - } } - lua_settop(L, oldtop); + + tree_indent--; } +static void display_rule(arule_type *rule) +{ + cptr action_s; + int hgt, wid; -/* Check the inventory for "crap" */ -void squeltch_inventory(void) + action_s = action_to_string(rule->action); + + Term_get_size(&wid, &hgt); + + tree_write_out_y = 1; + tree_write_out_x = 16; + tree_write_out_h = hgt - 4 - 1; + tree_write_out_w = wid - 1 - 15 - 1; + tree_write_y = 0; + tree_write_x = 0; + + switch (rule->action) + { + case AUTO_DESTROY: + case AUTO_PICKUP: + { + tree_write(TERM_GREEN, "A rule named \""); + tree_write(TERM_WHITE, rule->name); + tree_write(TERM_GREEN, "\" to "); + tree_write(TERM_L_GREEN, action_s); + tree_write(TERM_GREEN, " when"); + tree_write(TERM_WHITE, "\n"); + break; + } + + case AUTO_INSCRIBE: + { + tree_write(TERM_GREEN, "A rule named \""); + tree_write(TERM_WHITE, rule->name); + tree_write(TERM_GREEN, "\" to "); + tree_write(TERM_L_GREEN, "inscribe"); + tree_write(TERM_GREEN, " an item with \""); + tree_write(TERM_WHITE, rule->inscription); + tree_write(TERM_GREEN, "\" when"); + tree_write(TERM_WHITE, "\n"); + break; + } + + } + + /* Write out the condition */ + if (rule->condition != NULL) + { + display_condition(rule->condition); + } +} + +static void adjust_current(int sel) { - int oldtop; - int i; - int num_iter = 0; - bool_ found = TRUE; + if (rules_count == 0) + { + cursor_clear(); + return; + } - if (!automatizer_enabled) return; + tree_write_off_y = 0; + tree_write_off_x = 0; - oldtop = lua_gettop(L); - while (found && num_iter ++ < 100) + /* Put the top-level condition into cursor */ + cursor_clear(); + if (rules[sel]->condition != NULL) { - /* Sometimes an index in the inventory is skipped */ - found = FALSE; + cursor_push(rules[sel]->condition); + } +} - for (i = 0; i < INVEN_PACK; i++) - { - object_type *o_ptr = &p_ptr->inventory[i]; +static void tree_scroll_up() +{ + tree_write_off_y = tree_write_off_y - 1; +} - /* Push the function */ - lua_settop(L, oldtop); - lua_getglobal(L, "apply_rules"); +static void tree_scroll_down() +{ + tree_write_off_y = tree_write_off_y + 1; +} - /* Push the args */ - tolua_pushusertype(L, o_ptr, tolua_tag(L, "object_type")); - tolua_pushnumber(L, i); +static void tree_scroll_left() +{ + tree_write_off_x = tree_write_off_x + 1; +} - /* Call the function */ - if (lua_call(L, 2, 1)) - { - cmsg_format(TERM_VIOLET, "ERROR in lua_call while calling 'apply_rules'."); - lua_settop(L, oldtop); - return; - } +static void tree_scroll_right() +{ + tree_write_off_x = tree_write_off_x - 1; +} - /* Did it return TRUE */ - if (tolua_getnumber(L, -(lua_gettop(L) - oldtop), 0)) - { - found = TRUE; - break; - } +static void automatizer_save_rules() +{ + char name[30] = { '\0' }; + char buf[1025]; + char ch; + int hgt, wid; + + Term_get_size(&wid, &hgt); + + sprintf(name, "automat.atm"); + if (!input_box("Save name?", hgt / 2, wid / 2, name, sizeof(name)+1)) + { + return; + } + + /* Build the filename */ + path_build(buf, 1024, ANGBAND_DIR_USER, name); + + /* File type is "TEXT" */ + FILE_TYPE(FILE_TYPE_TEXT); + + if (file_exist(buf)) + { + c_put_str(TERM_WHITE, "File exists, continue?[y/n]", + hgt / 2, + wid / 2 - 14); + ch = inkey(); + if ((ch != 'Y') && (ch != 'y')) + { + return; } } - if (num_iter >= 100) + + /* Write to file */ { - cmsg_format(TERM_VIOLET, "'apply_rules' ran too often."); + json_t *rules_json = rules_to_json(); + int status = json_dump_file(rules_json, buf, JSON_INDENT(2) | JSON_SORT_KEYS); + if (status == 0) + { + c_put_str(TERM_WHITE, "Saved rules in file ", + hgt / 2, + wid / 2 - 14); + } + else + { + c_put_str(TERM_WHITE, "Saving rules failed! ", + hgt / 2, + wid / 2 - 14); + } + + /* Deallocate JSON */ + json_decref(rules_json); + + /* Wait for keypress */ + inkey(); } - lua_settop(L, oldtop); } -/********************** The interface **********************/ -static cptr *get_rule_list(int *max) +static void rename_rule(arule_type *rule) { - cptr *list; - int i; + char name[16]; + int wid, hgt; - *max = exec_lua("return __rules_max"); - C_MAKE(list, *max, cptr); - - for (i = 0; i < *max; i++) - { - list[i] = string_exec_lua(format("return __rules[%d].table.args.name", i)); - } - - return list; -} - -static cptr types_list[] = -{ - "and", - "or", - "not", - "name", - "contain", - "inscribed", - "discount", - "symbol", - "state", - "status", - "tval", - "sval", - "race", - "subrace", - "class", - "level", - "skill", - "ability", - "inventory", - "equipment", - "comment", - NULL, -}; + assert(rule != NULL); -/* Create a new rule */ -static int automatizer_new_rule() + Term_get_size(&wid, &hgt); + + sprintf(name, "%s", rule->name); + if (input_box("New name?", hgt / 2, wid / 2, name, sizeof(name)-1)) + { + rule_set_name(rule, name); + } +} + +static void add_new_condition(arule_type *current_rule) { - int wid, hgt, max, begin = 0, sel = 0; - char c; + /* Top-level condition? */ + if (current_rule->condition == NULL) + { + condition_metadata *metadata = NULL; - /* Get the number of types */ - max = 0; - while (types_list[max] != NULL) - max++; + /* Sanity check for navigation stack */ + assert(cursor_count == 0); - while (1) + /* Select type of clause */ + metadata = automatizer_select_condition_type(); + if (metadata == NULL) + { + return; + } + + /* Create the condition directly; we can + always add a top-level condition so there's + no need for the sanity checking in + add_child(). */ + current_rule->condition = metadata->create_condition(); + if (current_rule->condition != NULL) + { + cursor_push(current_rule->condition); + } + } + else { - Term_clear(); - Term_get_size(&wid, &hgt); + condition_type *current_condition = cursor_top(); + add_child(current_condition); + } +} + +static void tree_go_right() +{ + condition_type *top = cursor_top(); + + /* Can only go right if the currently selected condition + has children. */ + switch (top->match) + { + case M_AND: + case M_OR: + { + /* Pick first child */ + struct sglib_condition_list_iterator it; + condition_list *i = sglib_condition_list_it_init(&it, top->conditions.c); + /* Move right if possible */ + if (i != NULL) + { + cursor_push(i->condition); + } + break; + } - display_list(0, 0, hgt - 1, 15, "Rule types", types_list, max, begin, sel, TERM_L_GREEN); + case M_NOT: + case M_INVENTORY: + case M_EQUIPMENT: + { + if (top->subcondition != NULL) + { + cursor_push(top->subcondition); + } + break; + } - exec_lua(format("auto_aux:display_desc('%s')", types_list[sel])); - c_prt(TERM_YELLOW, "Example:", 5, 17); - exec_lua(format("xml.write_out_y = 6; xml.write_out_x = 16; xml.write_out_h = %d; xml.write_out_w = %d; xml.write_y = 0; xml.write_x = 0; xml:display_xml(auto_aux.types_desc['%s'][2][1], '')", hgt - 3 - 5, wid - 1 - 15 - 1, types_list[sel])); + default: + /* Not possible to move */ + break; + } +} - c = inkey(); +static void tree_go_left() +{ + if (cursor_count > 1) + { + cursor_pop(); + } +} - if (c == ESCAPE) break; - else if (c == '8') +static void tree_go_up() +{ + if (cursor_count > 1) + { + condition_type *prev_top = cursor_pop(); + condition_type *top = cursor_top(); + + switch (top->match) { - sel--; - if (sel < 0) + case M_AND: + case M_OR: + { + struct sglib_condition_list_iterator it; + condition_list *child = NULL; + condition_list *prev_child = NULL; + + /* We have a list of children */ + for (child = sglib_condition_list_it_init(&it, top->conditions.c); + child != NULL; + child = sglib_condition_list_it_next(&it)) { - sel = max - 1; - begin = max - hgt; - if (begin < 0) begin = 0; + if (child->condition == prev_top) + { + /* Do we have a previous child? */ + if (prev_child == NULL) + { + /* No predecessor; don't move */ + cursor_push(prev_top); + break; + } + else + { + cursor_push(prev_child->condition); + break; /* Done */ + } + } + /* Keep track of previous child */ + prev_child = child; } - if (sel < begin) begin = sel; + + break; } - else if (c == '2') + + default: { - sel++; - if (sel >= max) + /* No other match types have children; restore + original top. */ + cursor_push(prev_top); + break; + } + + } + } +} + +static void tree_go_down() +{ + if (cursor_count > 1) + { + condition_type *prev_top = cursor_pop(); + condition_type *top = cursor_top(); + + switch (top->match) + { + case M_AND: + case M_OR: + { + struct sglib_condition_list_iterator it; + condition_list *child = NULL; + + /* We have a list of children */ + for (child = sglib_condition_list_it_init(&it, top->conditions.c); + child != NULL; + child = sglib_condition_list_it_next(&it)) { - sel = 0; - begin = 0; + if (child->condition == prev_top) + { + /* Move to next child (if any) */ + child = sglib_condition_list_it_next(&it); + if (child == NULL) + { + /* No successor; don't move */ + cursor_push(prev_top); + break; + } + else + { + cursor_push(child->condition); + break; /* Done */ + } + } } - if (sel >= begin + hgt - 1) begin++; + + break; } - else if (c == '\r') + + default: { - return sel; + /* No other match types have multiple children; restore + original top. */ + cursor_push(prev_top); + break; + } + } } - return -1; } -static void adjust_begin(int *begin, int *sel, int max, int hgt) +static int automatizer_del_self(int sel) { - if (*sel < 0) + /* If the cursor is at the top level then + we want to delete the rule itself */ + if (cursor_count < 1) { - *sel = max - 1; - *begin = *sel - hgt + 3; - if (*begin < 0) *begin = 0; + rules_remove(rules[sel]); + return sel - 1; /* Move selection up */ } - if (*sel < *begin) *begin = *sel; - - if (*sel >= max) + else if (cursor_count == 1) { - *sel = 0; - *begin = 0; + cursor_pop(); + condition_destroy(&rules[sel]->condition); + return sel; + } + else + { + condition_type *prev_top = cursor_pop(); + condition_type *top = cursor_top(); + + /* Jump up a level; this is a simple way to ensure a + valid cursor. We could be a little cleverer here by + trying to move inside the current level, but it's a + little complicated. */ + tree_go_left(); + + /* Now we can remove the condition from its parent */ + switch (top->match) + { + + case M_AND: + case M_OR: + { + struct sglib_condition_list_iterator it; + condition_list *item = NULL; + + /* We have a list of children */ + for (item = sglib_condition_list_it_init(&it, top->conditions.c); + item != NULL; + item = sglib_condition_list_it_next(&it)) + { + if (item->condition == prev_top) + { + /* Found */ + break; + } + } + + /* Must have found item; otherwise internal structure + is damaged. */ + assert (item != NULL); + sglib_condition_list_delete(&top->conditions.c, item); + + /* Destroy the condition */ + condition_destroy(&prev_top); + break; + } + + case M_NOT: + case M_EQUIPMENT: + case M_INVENTORY: + { + assert(top->subcondition != NULL); + condition_destroy(&top->subcondition); + break; + } + + default: + /* If we get here, something's wrong with the + navigation structures. */ + assert(FALSE); + break; + } + + /* Keep selection */ + return sel; } - if (*sel >= *begin + hgt - 2) (*begin)++; } #define ACTIVE_LIST 0 @@ -239,12 +2779,12 @@ void do_cmd_automatizer() { int wid = 0, hgt = 0; char c; - cptr *list = NULL; int max, begin = 0, sel = 0; int active = ACTIVE_LIST; cptr keys; cptr keys2; cptr keys3; + cptr rule_names[RULES_MAX]; Term_get_size(&wid, &hgt); @@ -260,37 +2800,38 @@ void do_cmd_automatizer() screen_save(); - exec_lua(format("auto_aux:adjust_current(%d)", sel)); + adjust_current(sel); while (1) { Term_clear(); Term_get_size(&wid, &hgt); - list = get_rule_list(&max); - display_list(0, 0, hgt - 1, 15, "Rules", list, max, begin, sel, (active == ACTIVE_LIST) ? TERM_L_GREEN : TERM_GREEN); - C_FREE(list, max, cptr); + max = rules_count; + get_rule_names(rule_names); + display_list(0, 0, hgt - 1, 15, "Rules", rule_names, max, begin, sel, (active == ACTIVE_LIST) ? TERM_L_GREEN : TERM_GREEN); draw_box(0, 15, hgt - 4, wid - 1 - 15); if (active == ACTIVE_RULE) { keys = "#Bup#W/#Bdown#W/#Bleft#W/#Bright#W to navitage rule, #B9#W/#B3#W/#B7#W/#B1#W to scroll"; keys2 = "#Btab#W for switch, #Ba#Wdd clause, #Bd#Welete clause/rule"; - keys3 = "#Bx#W to toggle english/xml, #G?#W for Automatizer help"; - exec_lua("xml.write_active = not nil"); + keys3 = "#G?#W for Automatizer help"; } else { keys = "#Bup#W/#Bdown#W to scroll, #Btab#W to switch to the rule window"; keys2 = "#Bu#W/#Bd#W to move rules, #Bn#Wew rule, #Br#Wename rule, #Bs#Wave rules"; keys3 = "#Rk#W to #rdisable#W the automatizer, #G?#W for Automatizer help"; - exec_lua("xml.write_active = nil"); } display_message(17, hgt - 3, strlen(keys), TERM_WHITE, keys); display_message(17, hgt - 2, strlen(keys2), TERM_WHITE, keys2); display_message(17, hgt - 1, strlen(keys3), TERM_WHITE, keys3); - if (max) exec_lua(format("xml.write_out_y = 1; xml.write_out_x = 16; xml.write_out_h = %d; xml.write_out_w = %d; xml.write_y = 0; xml.write_x = 0; xml:display_xml(__rules[%d].table, '')", hgt - 4 - 1, wid - 1 - 15 - 1, sel)); + if (max) + { + display_rule(rules[sel]); + } c = inkey(); @@ -308,105 +2849,58 @@ void do_cmd_automatizer() if (!max) continue; sel--; adjust_begin(&begin, &sel, max, hgt); - exec_lua(format("auto_aux:adjust_current(%d)", sel)); + adjust_current(sel); } else if (c == '2') { if (!max) continue; sel++; adjust_begin(&begin, &sel, max, hgt); - exec_lua(format("auto_aux:adjust_current(%d)", sel)); + adjust_current(sel); } else if (c == 'u') { - if (!max) continue; - sel = exec_lua(format("return auto_aux:move_up(%d)", sel)); - adjust_begin(&begin, &sel, max, hgt); - exec_lua(format("auto_aux:adjust_current(%d)", sel)); + if (sel > 0) + { + rules_swap(sel-1, sel); + sel -= 1; + + adjust_begin(&begin, &sel, max, hgt); + adjust_current(sel); + } } else if (c == 'd') { if (!max) continue; - sel = exec_lua(format("return auto_aux:move_down(%d)", sel)); - adjust_begin(&begin, &sel, max, hgt); - exec_lua(format("auto_aux:adjust_current(%d)", sel)); + + if (sel < rules_count - 1) + { + rules_swap(sel, sel+1); + sel += 1; + + adjust_begin(&begin, &sel, max, hgt); + adjust_current(sel); + } } else if (c == 'n') { - char name[20] = { '\0' }; - char typ; - - sprintf(name, "No name"); - if (input_box("Name?", hgt / 2, wid / 2, name, sizeof(name)+1)) + int i = create_new_rule(); + if (i >= 0) { - cptr styp = "nothing"; - typ = msg_box("[D]estroy, [P]ickup, [I]nscribe, [N]othing rule?", hgt / 2, wid / 2); - if ((typ == 'd') || (typ == 'D')) styp = "destroy"; - else if ((typ == 'p') || (typ == 'P')) styp = "pickup"; - else if ((typ == 'i') || (typ == 'I')) styp = "inscribe"; - exec_lua(format("auto_aux:new_rule(%d, '%s', '%s', ''); auto_aux:adjust_current(%d)", sel, name, styp, sel)); + sel = i; + adjust_current(sel); active = ACTIVE_RULE; } } else if (c == 's') { - char name[30] = { '\0' }; - - sprintf(name, "automat.atm"); - if (input_box("Save name?", hgt / 2, wid / 2, name, sizeof(name)+1)) - { - char buf[1025]; - char ch; - - /* Build the filename */ - path_build(buf, 1024, ANGBAND_DIR_USER, name); - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - if (file_exist(buf)) - { - c_put_str(TERM_WHITE, "File exists, continue?[y/n]", hgt / 2, wid / 2 - 14); - ch = inkey(); - if ((ch != 'Y') && (ch != 'y')) - continue; - } - - /* Open the non-existing file */ - hook_file = my_fopen(buf, "w"); - - /* Invalid file */ - if (!hook_file) - { - /* Message */ - c_put_str(TERM_WHITE, "Saving rules failed! ", hgt / 2, wid / 2 - 14); - (void) inkey(); - - /* Error */ - continue; - } - - - - exec_lua("auto_aux:save_ruleset()"); - my_fclose(hook_file); - /* Overwrite query message */ - c_put_str(TERM_WHITE, "Saved rules in file ", hgt / 2, wid / 2 - 14); - (void) inkey(); - } + automatizer_save_rules(); } else if (c == 'r') { - char name[20]; - if (!max) continue; - sprintf(name, "%s", string_exec_lua(format("return __rules[%d].table.args.name", sel))); - if (input_box("New name?", hgt / 2, wid / 2, name, 15)) - { - exec_lua(format("auto_aux:rename_rule(%d, '%s')", sel, name)); - } - + rename_rule(rules[sel]); continue; } else if (c == 'k') @@ -419,10 +2913,6 @@ void do_cmd_automatizer() if (!max) continue; active = ACTIVE_RULE; } - else if (c == 'x') - { - exec_lua("xml.display_english = not xml.display_english"); - } } else if (active == ACTIVE_RULE) { @@ -434,41 +2924,39 @@ void do_cmd_automatizer() } else if (c == '8') { - exec_lua("auto_aux:go_up()"); + tree_go_up(); } else if (c == '2') { - exec_lua("auto_aux:go_down()"); + tree_go_down(); } else if (c == '6') { - exec_lua("auto_aux:go_right()"); + tree_go_right(); } else if (c == '4') { - exec_lua(format("auto_aux:go_left(%d)", sel)); + tree_go_left(); } else if (c == '9') { - exec_lua("auto_aux:scroll_up()"); + tree_scroll_up(); } else if (c == '3') { - exec_lua("auto_aux:scroll_down()"); + tree_scroll_down(); } else if (c == '7') { - exec_lua("auto_aux:scroll_left()"); + tree_scroll_left(); } else if (c == '1') { - exec_lua("auto_aux:scroll_right()"); + tree_scroll_right(); } else if (c == 'a') { - int s = automatizer_new_rule(); - if (s == -1) continue; - exec_lua(format("auto_aux:add_child('%s')", types_list[s])); + add_new_condition(rules[sel]); } else if (c == 'd') { @@ -476,12 +2964,12 @@ void do_cmd_automatizer() { int new_sel; - new_sel = exec_lua(format("return auto_aux:del_self(%d)", sel)); + new_sel = automatizer_del_self(sel); if ((sel != new_sel) && (new_sel >= 0)) { sel = new_sel; adjust_begin(&begin, &sel, max, hgt); - exec_lua(format("auto_aux:adjust_current(%d)", sel)); + adjust_current(sel); } else if (new_sel == -1) { @@ -493,30 +2981,84 @@ void do_cmd_automatizer() { active = ACTIVE_LIST; } - else if (c == 'x') - { - exec_lua("xml.display_english = not xml.display_english"); - } } } - /* Recalculate the rules */ - exec_lua("auto_aux.regen_ruleset()"); - screen_load(); } +static void easy_add_rule(action_type action, cptr mode, bool_ do_status, object_type *o_ptr) +{ + condition_type *condition = NULL; + + if (streq(mode, "tval")) + { + condition = condition_new_tval(o_ptr->tval); + } + else if (streq(mode, "tsval")) + { + condition_type *sval_condition = + condition_new_sval(o_ptr->sval, o_ptr->sval); + condition_type *tval_condition = + condition_new_tval(o_ptr->tval); + + condition = condition_new_and(); + condition_and_add(condition, tval_condition); + condition_and_add(condition, sval_condition); + } + else if (streq(mode, "name")) + { + char buf[128]; + object_desc(buf, o_ptr, -1, 0); + strlower(buf); + + condition = condition_new_name(buf); + } + + /* Use object status? */ + if (do_status == TRUE) + { + status_type status = object_status(o_ptr); + condition_type *status_condition = + condition_new_status(status); + condition_type *and_condition = + condition_new_and(); + + condition_and_add(and_condition, condition); + condition_and_add(and_condition, status_condition); + /* Replace condition */ + condition = and_condition; + } + + /* Build rule */ + { + static arule_type *rule = NULL; + /* Make rule */ + rule = rule_new(action_to_string(action), + action, + game_module_idx, + condition, + NULL); + + /* Append to list of rules */ + rules_append(rule); + } + + msg_print("Rule added. Please go to the Automatizer screen (press = then T)"); + msg_print("to save the modified ruleset."); +} + /* Add a new rule in an easy way */ bool_ automatizer_create = FALSE; void automatizer_add_rule(object_type *o_ptr, bool_ destroy) { char ch; bool_ do_status = FALSE; - cptr type = "destroy"; + action_type action = AUTO_DESTROY; if (!destroy) { - type = "pickup"; + action = AUTO_PICKUP; } while (TRUE) @@ -534,20 +3076,496 @@ void automatizer_add_rule(object_type *o_ptr, bool_ destroy) if (ch == 'T' || ch == 't') { - call_lua("easy_add_rule", "(s,s,d,O)", "", type, "tsval", do_status, o_ptr); + easy_add_rule(action, "tsval", do_status, o_ptr); break; } if (ch == 'F' || ch == 'f') { - call_lua("easy_add_rule", "(s,s,d,O)", "", type, "tval", do_status, o_ptr); + easy_add_rule(action, "tval", do_status, o_ptr); break; } if (ch == 'N' || ch == 'n') { - call_lua("easy_add_rule", "(s,s,d,O)", "", type, "name", do_status, o_ptr); + easy_add_rule(action, "name", do_status, o_ptr); break; } } } + +static condition_type *parse_condition(json_t *condition_json) +{ + cptr type_s = NULL; + match_type match; + + if ((condition_json == NULL) || json_is_null(condition_json)) + { + return NULL; + } + + if (json_unpack(condition_json, + "{s:s}", + "type", &type_s) < 0) + { + msg_print("Missing/invalid 'type' in condition"); + return NULL; + } + + if (!match_type_from_string(type_s, &match)) + { + msg_format("Invalid 'type' in condition: %s", type_s); + return NULL; + } + + switch (match) + { + case M_AND: + case M_OR: + { + json_t *conditions_j = json_object_get(condition_json, + "conditions"); + + if ((conditions_j == NULL) || + (json_is_null(conditions_j))) + { + return NULL; + } + else if (json_is_array(conditions_j)) + { + int i; + json_t *subcondition_j = NULL; + condition_type *condition = condition_new(match); + condition_type *subcondition = NULL; + + for (i = 0; i < json_array_size(conditions_j); i++) + { + subcondition_j = + json_array_get(conditions_j, i); + subcondition = + parse_condition(subcondition_j); + + if (subcondition != NULL) + { + condition_and_add(condition, subcondition); + } + } + + return condition; + } + else + { + msg_print("'conditions' property has invalid type"); + return NULL; + } + + break; + } + + case M_NOT: + case M_INVENTORY: + case M_EQUIPMENT: + { + json_t *condition_j = json_object_get(condition_json, + "condition"); + + if ((condition_j == NULL) || + (json_is_null(condition_j))) + { + return NULL; + } + else if (json_is_object(condition_j)) + { + condition_type *condition = + condition_new(match); + condition->subcondition = + parse_condition(condition_j); + return condition; + } + else + { + msg_print("Invlalid 'condition' property"); + return NULL; + } + } + + case M_NAME: + { + cptr s = NULL; + if (json_unpack(condition_json, + "{s:s}", + "name", &s) < 0) + { + msg_print("Missing/invalid 'name' property"); + return NULL; + } + + return condition_new_name(s); + } + + case M_CONTAIN: + { + cptr s = NULL; + if (json_unpack(condition_json, + "{s:s}", + "contain", &s) < 0) + { + msg_print("Missing/invalid 'contain' property"); + return NULL; + } + + return condition_new_contain(s); + } + + case M_SYMBOL: + { + cptr s = NULL; + int sl; + if (json_unpack(condition_json, "{s:s}", "symbol", &s) < 0) + { + msg_print("Missing/invalid 'symbol' property"); + return NULL; + } + + sl = strlen(s); + if (sl == 0) + { + msg_print("Invalid 'symbol' property: Too short"); + return NULL; + } + if (sl > 1) + { + msg_print("Invalid 'symbol' property: Too long"); + return NULL; + } + + return condition_new_symbol(s[0]); + } + + case M_INSCRIBED: + { + cptr s = NULL; + if (json_unpack(condition_json, "{s:s}", "inscription", &s) < 0) + { + msg_print("Missing/invalid 'inscription' property"); + return NULL; + } + + return condition_new_inscribed(s); + } + + case M_DISCOUNT: + { + int min, max; + + if (json_unpack(condition_json, "{s:i,s:i}", + "min", &min, + "max", &max) < 0) + { + msg_print("Missing/invalid 'min'/'max' properties"); + return NULL; + } + + return condition_new_discount(min, max); + } + + case M_TVAL: + { + int tval; + + if (json_unpack(condition_json, "{s:i}", "tval", &tval) < 0) + { + msg_print("Missing/invalid 'tval' property"); + return NULL; + } + + return condition_new_tval(tval); + } + + case M_SVAL: + { + int min, max; + + if (json_unpack(condition_json, "{s:i,s:i}", + "min", &min, + "max", &max) < 0) + { + msg_print("Missing/invalid 'min'/'max' properties"); + return NULL; + } + + return condition_new_sval(min, max); + } + + case M_STATUS: + { + cptr s; + status_type status; + + if (json_unpack(condition_json, "{s:s}", "status", &s) < 0) + { + msg_print("Missing/invalid 'status' property"); + return NULL; + } + + if (!status_from_string(s, &status)) + { + msg_format("Invalid 'status' property: %s", s); + return NULL; + } + + return condition_new_status(status); + } + + case M_STATE: + { + cptr s; + identification_state state; + + if (json_unpack(condition_json, "{s:s}", "state", &s) < 0) + { + msg_print("Missing/invalid 'state' property"); + return NULL; + } + + if (!identification_state_from_string(s, &state)) + { + msg_format("Invalid 'state' property: %s", s); + return NULL; + } + + return condition_new_state(state); + } + + case M_RACE: + { + cptr s; + + if (json_unpack(condition_json, "{s:s}", "race", &s) < 0) + { + msg_print("Missing/invalid 'race' property"); + return NULL; + } + + return condition_new_race(s); + } + + case M_SUBRACE: + { + cptr s; + + if (json_unpack(condition_json, "{s:s}", "subrace", &s) < 0) + { + msg_print("Missing/invalid 'subrace' property"); + return NULL; + } + + return condition_new_subrace(s); + } + + case M_CLASS: + { + cptr s; + + if (json_unpack(condition_json, "{s:s}", "class", &s) < 0) + { + msg_print("Missing/invalid 'class' property"); + return NULL; + } + + return condition_new_class(s); + } + + case M_LEVEL: + { + int min, max; + + if (json_unpack(condition_json, "{s:i,s:i}", + "min", &min, + "max", &max) < 0) + { + msg_print("Missing/invalid 'min'/'max' properties"); + return NULL; + } + + return condition_new_level(min, max); + } + + case M_SKILL: + { + cptr s; + s16b si; + int min, max; + + if (json_unpack(condition_json, "{s:i,s:i,s:s}", + "min", &min, + "max", &max, + "name", &s) < 0) + { + msg_print("Missing/invalid 'min'/'max'/'name' properties"); + return NULL; + } + + si = find_skill_i(s); + if (si < 0) + { + msg_print("Invalid 'name' property"); + return NULL; + } + + return condition_new_skill(min, max, si); + } + + case M_ABILITY: + { + cptr a; + s16b ai; + + if (json_unpack(condition_json, "{s:s}", + "ability", &a) < 0) + { + msg_print("Missing/invalid 'ability' property"); + return NULL; + } + + ai = find_ability(a); + if (ai < 0) + { + msg_print("Invalid 'ability' property"); + return NULL; + } + + return condition_new_ability(ai); + } + + } + + /* Could not parse */ + return NULL; +} + +static void parse_rule(json_t *rule_json) +{ + char *rule_name_s = NULL; + char *rule_action_s = NULL; + char *rule_module_s = NULL; + json_t *rule_inscription_j = NULL; + arule_type *rule = NULL; + action_type action; + int module_idx; + + if (!json_is_object(rule_json)) + { + msg_print("Rule is not an object"); + return; + } + + /* Retrieve the attributes */ + if (json_unpack(rule_json, + "{s:s,s:s,s:s}", + "name", &rule_name_s, + "action", &rule_action_s, + "module", &rule_module_s) < 0) + { + msg_print("Rule missing required field(s)"); + return; + } + + /* Get the optional inscription */ + rule_inscription_j = json_object_get(rule_json, "inscription"); + + /* Convert attributes */ + if (!action_from_string((cptr) rule_action_s, &action)) + { + msg_format("Invalid rule action '%s'", rule_action_s); + return; + } + + module_idx = find_module((cptr) rule_module_s); + if (module_idx < 0) + { + msg_format("Skipping rule for unrecognized module '%s'", + (cptr) rule_module_s); + return; + } + + /* Sanity check: Inscription */ + if (action == AUTO_INSCRIBE) + { + if (rule_inscription_j == NULL) + { + msg_print("Inscription rule missing 'inscription' attribute"); + return; + } + if (!json_is_string(rule_inscription_j)) + { + msg_print("Inscription rule 'inscription' attribute wrong type"); + return; + } + } + + /* Create rule */ + rule = rule_new(rule_name_s, + action, + module_idx, + NULL, + json_string_value(rule_inscription_j)); + rules_append(rule); + + /* Parse the conditions */ + rule->condition = parse_condition(json_object_get(rule_json, "condition")); +} + +static void parse_rules(json_t *rules) +{ + int i; + + if (!json_is_array(rules)) + { + msg_format("Error 'rules' is not an array"); + return; + } + + for (i = 0; i < json_array_size(rules); i++) + { + json_t *rule = json_array_get(rules, i); + parse_rule(rule); + } +} + +/** + * Initialize the automatizer. This function may be called multiple + * times with different file names -- it should NOT clear any + * automatizer state (including loaded rules). + */ +void automatizer_init(cptr file_path) +{ + json_t *rules_json = NULL; + json_error_t error; + + /* Does the file exist? */ + if (!file_exist(file_path)) + { + /* No big deal, we'll just skip */ + goto out; + } + + /* Parse file */ + rules_json = json_load_file(file_path, 0, &error); + if (rules_json == NULL) + { + msg_format("Error parsing automatizer rules from '%s'.", file_path); + msg_format("Line %d, Column %d", error.line, error.column); + msg_print(NULL); + goto out; + } + + /* Go through all the found rules */ + parse_rules(rules_json); + +out: + if (rules_json == NULL) + { + json_decref(rules_json); + } +} -- cgit v1.2.3 From 2a2fcac0fdb76ce7481ab4ab17e6f64f3ca7bc1d Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 19 Jun 2012 18:32:22 +0200 Subject: Lua: Eliminate use of exec_lua() in files.c --- lib/help/def.aux | 3 --- lib/mods/theme/help/def.aux | 3 --- src/files.c | 14 +++----------- 3 files changed, 3 insertions(+), 17 deletions(-) delete mode 100644 lib/help/def.aux delete mode 100644 lib/mods/theme/help/def.aux diff --git a/lib/help/def.aux b/lib/help/def.aux deleted file mode 100644 index 983e9683..00000000 --- a/lib/help/def.aux +++ /dev/null @@ -1,3 +0,0 @@ -file_ext="html" -link_prefix="" -link_suffix="" diff --git a/lib/mods/theme/help/def.aux b/lib/mods/theme/help/def.aux deleted file mode 100644 index 983e9683..00000000 --- a/lib/mods/theme/help/def.aux +++ /dev/null @@ -1,3 +0,0 @@ -file_ext="html" -link_prefix="" -link_suffix="" diff --git a/src/files.c b/src/files.c index 10617f74..ee3bc86c 100644 --- a/src/files.c +++ b/src/files.c @@ -3523,9 +3523,9 @@ bool_ txt_to_html(cptr head, cptr foot, cptr base, cptr ext, bool_ force, bool_ /* Char array type of hyperlink info */ hyperlink_type *h_ptr; - cptr file_ext; - cptr link_prefix; - cptr link_suffix; + cptr file_ext = "html"; + cptr link_prefix = ""; + cptr link_suffix = ""; /* Pointer to general buffer in the above */ char *buf; @@ -3542,14 +3542,6 @@ bool_ txt_to_html(cptr head, cptr foot, cptr base, cptr ext, bool_ force, bool_ h_ptr->link_x[i] = -1; } - /* Parse it(yeah lua is neat :) */ - tome_dofile_anywhere(ANGBAND_DIR_HELP, "def.aux", TRUE); - - /* Ok now get the parameters */ - file_ext = string_exec_lua("return file_ext"); - link_prefix = string_exec_lua("return link_prefix"); - link_suffix = string_exec_lua("return link_suffix"); - sprintf(buf_name, "%s.%s", base, file_ext); if ((!force) && file_exist(buf_name)) return FALSE; -- cgit v1.2.3 From 64e064330c5c595d0b8553028e0c5ca95c5e5392 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 19 Jun 2012 18:32:22 +0200 Subject: Lua: Remove Lua --- lib/CMakeLists.txt | 1 - lib/core/gen_idx.lua | 261 --- lib/core/init.lua | 9 - lib/core/objects.lua | 8 - lib/core/player.lua | 16 - lib/core/util.lua | 37 - lib/mods/theme/core/gen_idx.lua | 261 --- lib/mods/theme/core/init.lua | 9 - lib/mods/theme/core/objects.lua | 8 - lib/mods/theme/core/player.lua | 16 - lib/mods/theme/core/util.lua | 37 - src/CMakeLists.txt | 26 +- src/cmd5.c | 2 - src/defines.h | 1 - src/dungeon.c | 4 - src/dungeon.pkg | 1607 ------------------ src/externs.h | 8 - src/init2.c | 3 +- src/lauxlib.h | 100 -- src/lua/.gitignore | 2 - src/lua/CMakeLists.txt | 11 - src/lua/array.lua | 203 --- src/lua/basic.lua | 190 --- src/lua/class.lua | 85 - src/lua/clean.lua | 74 - src/lua/code.lua | 73 - src/lua/container.lua | 311 ---- src/lua/declaration.lua | 399 ----- src/lua/define.lua | 72 - src/lua/doit.lua | 73 - src/lua/enumerate.lua | 93 -- src/lua/feature.lua | 72 - src/lua/function.lua | 317 ---- src/lua/lapi.c | 499 ------ src/lua/lapi.h | 17 - src/lua/lauxlib.c | 216 --- src/lua/lauxlib.h | 100 -- src/lua/lbaselib.c | 651 -------- src/lua/lcode.c | 701 -------- src/lua/lcode.h | 70 - src/lua/ldblib.c | 188 --- src/lua/ldebug.c | 466 ------ src/lua/ldebug.h | 21 - src/lua/ldo.c | 385 ----- src/lua/ldo.h | 33 - src/lua/lfunc.c | 109 -- src/lua/lfunc.h | 24 - src/lua/lgc.c | 353 ---- src/lua/lgc.h | 18 - src/lua/liolib.c | 710 -------- src/lua/llex.c | 411 ----- src/lua/llex.h | 72 - src/lua/llimits.h | 204 --- src/lua/lmem.c | 150 -- src/lua/lmem.h | 42 - src/lua/lobject.c | 125 -- src/lua/lobject.h | 204 --- src/lua/lopcodes.h | 168 -- src/lua/lparser.c | 1129 ------------- src/lua/lparser.h | 60 - src/lua/lstate.c | 121 -- src/lua/lstate.h | 77 - src/lua/lstring.c | 155 -- src/lua/lstring.h | 37 - src/lua/lstrlib.c | 621 ------- src/lua/ltable.c | 303 ---- src/lua/ltable.h | 34 - src/lua/ltests.c | 543 ------ src/lua/ltm.c | 163 -- src/lua/ltm.h | 59 - src/lua/lua.h | 248 --- src/lua/lua2c.lua | 29 - src/lua/luadebug.h | 46 - src/lua/lualib.h | 34 - src/lua/lundump.c | 244 --- src/lua/lundump.h | 35 - src/lua/lvm.c | 710 -------- src/lua/lvm.h | 32 - src/lua/lzio.c | 84 - src/lua/lzio.h | 53 - src/lua/module.lua | 69 - src/lua/operator.lua | 111 -- src/lua/package.lua | 222 --- src/lua/print.h | 55 - src/lua/tolua.c | 149 -- src/lua/tolua.h | 127 -- src/lua/tolua_bd.c | 214 --- src/lua/tolua_eh.c | 66 - src/lua/tolua_eh.h | 24 - src/lua/tolua_gp.c | 197 --- src/lua/tolua_lb.c | 160 -- src/lua/tolua_rg.c | 243 --- src/lua/tolua_rg.h | 22 - src/lua/tolua_tm.c | 585 ------- src/lua/tolua_tm.h | 32 - src/lua/tolua_tt.c | 316 ---- src/lua/tolua_tt.h | 31 - src/lua/tolualua.c | 2975 --------------------------------- src/lua/tolualua.h | 2713 ------------------------------ src/lua/tolualua.pkg | 21 - src/lua/typedef.lua | 59 - src/lua/variable.lua | 192 --- src/lua/verbatim.lua | 77 - src/lua_bind.c | 4 - src/main.c | 3 +- src/modules.c | 3 - src/monster.pkg | 2301 -------------------------- src/object.pkg | 1161 ------------- src/player.pkg | 3446 --------------------------------------- src/player_c.pkg | 1060 ------------ src/plots.c | 110 -- src/q_fireprof.c | 2 +- src/script.c | 496 ------ src/spells.pkg | 2258 ------------------------- src/squeltch.c | 2 - src/util.pkg | 2251 ------------------------- src/wizard2.c | 46 - src/z_pack.pkg | 398 ----- 118 files changed, 5 insertions(+), 37339 deletions(-) delete mode 100644 lib/core/gen_idx.lua delete mode 100644 lib/core/init.lua delete mode 100644 lib/core/objects.lua delete mode 100644 lib/core/player.lua delete mode 100644 lib/core/util.lua delete mode 100644 lib/mods/theme/core/gen_idx.lua delete mode 100644 lib/mods/theme/core/init.lua delete mode 100644 lib/mods/theme/core/objects.lua delete mode 100644 lib/mods/theme/core/player.lua delete mode 100644 lib/mods/theme/core/util.lua delete mode 100644 src/dungeon.pkg delete mode 100644 src/lauxlib.h delete mode 100644 src/lua/.gitignore delete mode 100644 src/lua/CMakeLists.txt delete mode 100644 src/lua/array.lua delete mode 100644 src/lua/basic.lua delete mode 100644 src/lua/class.lua delete mode 100644 src/lua/clean.lua delete mode 100644 src/lua/code.lua delete mode 100644 src/lua/container.lua delete mode 100644 src/lua/declaration.lua delete mode 100644 src/lua/define.lua delete mode 100644 src/lua/doit.lua delete mode 100644 src/lua/enumerate.lua delete mode 100644 src/lua/feature.lua delete mode 100644 src/lua/function.lua delete mode 100644 src/lua/lapi.c delete mode 100644 src/lua/lapi.h delete mode 100644 src/lua/lauxlib.c delete mode 100644 src/lua/lauxlib.h delete mode 100644 src/lua/lbaselib.c delete mode 100644 src/lua/lcode.c delete mode 100644 src/lua/lcode.h delete mode 100644 src/lua/ldblib.c delete mode 100644 src/lua/ldebug.c delete mode 100644 src/lua/ldebug.h delete mode 100644 src/lua/ldo.c delete mode 100644 src/lua/ldo.h delete mode 100644 src/lua/lfunc.c delete mode 100644 src/lua/lfunc.h delete mode 100644 src/lua/lgc.c delete mode 100644 src/lua/lgc.h delete mode 100644 src/lua/liolib.c delete mode 100644 src/lua/llex.c delete mode 100644 src/lua/llex.h delete mode 100644 src/lua/llimits.h delete mode 100644 src/lua/lmem.c delete mode 100644 src/lua/lmem.h delete mode 100644 src/lua/lobject.c delete mode 100644 src/lua/lobject.h delete mode 100644 src/lua/lopcodes.h delete mode 100644 src/lua/lparser.c delete mode 100644 src/lua/lparser.h delete mode 100644 src/lua/lstate.c delete mode 100644 src/lua/lstate.h delete mode 100644 src/lua/lstring.c delete mode 100644 src/lua/lstring.h delete mode 100644 src/lua/lstrlib.c delete mode 100644 src/lua/ltable.c delete mode 100644 src/lua/ltable.h delete mode 100644 src/lua/ltests.c delete mode 100644 src/lua/ltm.c delete mode 100644 src/lua/ltm.h delete mode 100644 src/lua/lua.h delete mode 100644 src/lua/lua2c.lua delete mode 100644 src/lua/luadebug.h delete mode 100644 src/lua/lualib.h delete mode 100644 src/lua/lundump.c delete mode 100644 src/lua/lundump.h delete mode 100644 src/lua/lvm.c delete mode 100644 src/lua/lvm.h delete mode 100644 src/lua/lzio.c delete mode 100644 src/lua/lzio.h delete mode 100644 src/lua/module.lua delete mode 100644 src/lua/operator.lua delete mode 100644 src/lua/package.lua delete mode 100644 src/lua/print.h delete mode 100644 src/lua/tolua.c delete mode 100644 src/lua/tolua.h delete mode 100644 src/lua/tolua_bd.c delete mode 100644 src/lua/tolua_eh.c delete mode 100644 src/lua/tolua_eh.h delete mode 100644 src/lua/tolua_gp.c delete mode 100644 src/lua/tolua_lb.c delete mode 100644 src/lua/tolua_rg.c delete mode 100644 src/lua/tolua_rg.h delete mode 100644 src/lua/tolua_tm.c delete mode 100644 src/lua/tolua_tm.h delete mode 100644 src/lua/tolua_tt.c delete mode 100644 src/lua/tolua_tt.h delete mode 100644 src/lua/tolualua.c delete mode 100644 src/lua/tolualua.h delete mode 100644 src/lua/tolualua.pkg delete mode 100644 src/lua/typedef.lua delete mode 100644 src/lua/variable.lua delete mode 100644 src/lua/verbatim.lua delete mode 100644 src/monster.pkg delete mode 100644 src/object.pkg delete mode 100644 src/player.pkg delete mode 100644 src/player_c.pkg delete mode 100644 src/spells.pkg delete mode 100644 src/util.pkg delete mode 100644 src/z_pack.pkg diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 245d98f8..f6e7748c 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -5,7 +5,6 @@ INSTALL(FILES INSTALL(DIRECTORY apex cmov - core data dngn edit diff --git a/lib/core/gen_idx.lua b/lib/core/gen_idx.lua deleted file mode 100644 index 5f3af435..00000000 --- a/lib/core/gen_idx.lua +++ /dev/null @@ -1,261 +0,0 @@ --- Place here the list of files to parse -files = -{ - "birth.txt", - "experien.hlp", - "gods.txt", - "explore.hlp", - "newbie.hlp", - "advanced.hlp", - "help.hlp", - "general.txt", - "whattome.txt", - "dungeon.txt", - "spoiler.hlp", - "g_melkor.txt", - "skills.txt", - "c_bard.txt", - "c_druid.txt", - "c_lorema.txt", - "c_mage.txt", - "c_mimic.txt", - "c_mindcr.txt", - "c_monk.txt", - "c_palad.txt", - "c_posses.txt", - "c_pr_drk.txt", - "c_pr_eru.txt", - "c_pr_man.txt", - "c_symbia.txt", - "c_alchem.txt", - "c_archer.txt", - "c_assass.txt", - "c_axemas.txt", - "c_demono.txt", - "c_geoman.txt", - "c_hafted.txt", - "c_necro.txt", - "c_polear.txt", - "c_ranger.txt", - "c_rogue.txt", - "c_runecr.txt", - "c_sorcer.txt", - "c_swordm.txt", - "c_thaum.txt", - "c_unbel.txt", - "c_warper.txt", - "c_warrio.txt", - "m_meta.txt", - "rm_skel.txt", - "rm_zomb.txt", - "luckspoi.txt", - "m_air.txt", - "dunspoil.txt", - "g_eru.txt", - "g_manwe.txt", - "g_tulkas.txt", - "m_divin.txt", - "m_mimic.txt", - "m_water.txt", - "magic.txt", - "r_drkelf.txt", - "r_dwarf.txt", - "r_elf.txt", - "r_hielf.txt", - "r_hobbit.txt", - "r_pettyd.txt", - "r_wodelf.txt", - "rm_spec.txt", - "tome_faq.txt", - "ability.txt", - "automat.txt", - "c_summon.txt", - "command.txt", - "corspoil.txt", - "debug.txt", - "m_music.txt", - "rm_barb.txt", - "macrofaq.txt", - "m_necrom.txt", - "m_mindcr.txt", - "m_symbio.txt", - "m_thaum.txt", - "magic.hlp", - "m_convey.txt", - "m_fire.txt", - "m_mana.txt", - "m_mind.txt", - "m_nature.txt", - "m_tempo.txt", - "m_udun.txt", - "m_geoman.txt", - "essences.txt", - "r_ent.txt", - "g_yavann.txt", - "defines.txt", - "rm_vamp.txt", - "inscrip.txt", - "m_earth.txt", - "option.txt", - "attack.txt", - "version.txt", - "m_demono.txt", - "r_beorn.txt", - "r_deathm.txt", - "r_rohank.txt", - "r_hafogr.txt", - "r_human.txt", - "r_kobold.txt", - "r_maia.txt", - "r_orc.txt", - "r_thlord.txt", - "r_troll.txt", - "r_yeek.txt", - "rm_class.txt", - "rm_herm.txt", - "rm_lsoul.txt", - "wishing.txt", - "c_priest.txt", - "fatespoi.txt", - "gambling.txt", - "r_dunad.txt", - "r_gnome.txt", - "r_hafelf.txt", - "c_merch.txt", - "spoil_faq.txt", -} - -out_file = "index.txt" - -index = {} - -function parse_file(file) - local fff = openfile(path_build(ANGBAND_DIR_HELP, file), "r") - local line - - line = read(fff, "*l") - while line do - local i, j, anchor, name, subname = strfind(line, "~~~~~(%d+)|([%d%a -]+)|([%d%a -]+)") - if not i then - i, j, anchor, name = strfind(line, "~~~~~(%d+)|([%d%a -]+)") - - subname = nil - end - - if i then - if not index[name] then - index[name] = {} - end - if subname then - tinsert(index[name], { __name__ = subname, __file__ = file, __anchor__ = anchor}) - else - tinsert(index[name], { __name__ = "__primary__", __file__ = file, __anchor__ = anchor}) - end - end - - line = read(fff, "*l") - end - - closefile(fff) -end - -function sort_fct(a, b) - local i, len - - a = a.__name__ - b = b.__name__ - - if strlen(a) > strlen(b) then len = strlen(b) else len = strlen(a) end - - for i = 1, len do - local ac = strbyte(a, i) - local bc = strbyte(b, i) - - if ac < bc then - return not nil - elseif ac > bc then - return nil - end - end - if strlen(a) > strlen(b) then return nil else return not nil end -end - -function generate_index() - local k, e, index_list - for _, e in files do - parse_file(e) - end - - index_list = {} - for k, e in index do - -- Ok either my sort function or lua sort function sucks ass .. - sort(e, sort_fct) - sort(e, sort_fct) - sort(e, sort_fct) - sort(e, sort_fct) - sort(e, sort_fct) - tinsert(index_list, {__name__= k, __table__ = e}) - end - - -- Ok either my sort function or lua sort function sucks ass .. - sort(index_list, sort_fct) - sort(index_list, sort_fct) - sort(index_list, sort_fct) - sort(index_list, sort_fct) - sort(index_list, sort_fct) - index = index_list -end - -function out_link(fff, space, name, file, anchor) - write(fff, space.."*****"..file.."*"..anchor.."["..name.."]\n") -end - -function print_index() - local i, j, c, new_c - local fff = openfile(path_build(ANGBAND_DIR_HELP, out_file), "w") - - write(fff, -[[|||||oy -#####R /----------------------------------------\ -#####R < Help Index > -#####R \----------------------------------------/ - -This is the index of everything in the T.o.M.E. documentation. - -#####BHit a letter key to jump to the entries for that letter. - -Some entries in the index link to the same place as other entries. This is -intentional, so that the information you want is easy to find. - -Don't forget you can browse the help from the *****help.hlp*02[Main menu]. - -#####sSpotted a problem with the help files, or some content thats missing? -#####sContact fearoffours@t-o-m-e.net . - -]]) - - c = ' ' - for i = 1, getn(index) do - new_c = strbyte(index[i].__name__, 1) - if c ~= new_c then - c = new_c - write(fff, "~~~~~"..c.."\n") - write(fff, "*****/"..strchar(c)..out_file.."*"..c.."["..strchar(c).."]\n") - end - for j = 1, getn(index[i].__table__) do - if index[i].__table__[j].__name__ == "__primary__" then - out_link(fff, " ", index[i].__name__, index[i].__table__[j].__file__, index[i].__table__[j].__anchor__) - end - end - for j = 1, getn(index[i].__table__) do - if index[i].__table__[j].__name__ ~= "__primary__" then - out_link(fff, " ", index[i].__table__[j].__name__, index[i].__table__[j].__file__, index[i].__table__[j].__anchor__) - end - end - end - closefile(fff) -end - -generate_index() - -print_index() diff --git a/lib/core/init.lua b/lib/core/init.lua deleted file mode 100644 index 44ef9a7a..00000000 --- a/lib/core/init.lua +++ /dev/null @@ -1,9 +0,0 @@ --- --- This file is loaded at the initialisation of ToME --- Load the system functions --- - --- various vital helper code -tome_dofile_anywhere(ANGBAND_DIR_CORE, "util.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "player.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "objects.lua") diff --git a/lib/core/objects.lua b/lib/core/objects.lua deleted file mode 100644 index fa77c57b..00000000 --- a/lib/core/objects.lua +++ /dev/null @@ -1,8 +0,0 @@ --- SYSTEM FILE --- --- Lua object funtions --- - -function get_kind(obj) - return k_info[obj.k_idx + 1] -end diff --git a/lib/core/player.lua b/lib/core/player.lua deleted file mode 100644 index deec2e21..00000000 --- a/lib/core/player.lua +++ /dev/null @@ -1,16 +0,0 @@ --- SYSTEM FILE --- --- Lua player funtions --- - --------- skill stuff --------- - --- Easy skill access -function skill(i) - return s_info[i + 1] -end - --- easier inventory access -function player.inventory(i) - return player.inventory_real[i + 1] -end diff --git a/lib/core/util.lua b/lib/core/util.lua deleted file mode 100644 index c3387401..00000000 --- a/lib/core/util.lua +++ /dev/null @@ -1,37 +0,0 @@ --- various stuff to make scripters life easier - --- Beware of the scary undefined globals -function safe_getglobal(x) - local v = rawget(globals(), x) - - if v then - return v - else - error("undefined global variable '"..x.."'") - end -end - -function set_safe_globals() - settagmethod(tag(nil), "getglobal", safe_getglobal) -end -function unset_safe_globals() - settagmethod(tag(nil), "getglobal", nil) -end - -set_safe_globals() - --- Wrapper for the real msg_print and cmsg_print --- it understands if we want color or not -function msg_print(c, m) - if type(c) == "number" then - cmsg_print(c, m) - else - call(%msg_print, { c }) - end -end - - --- Strings -function msg_format(...) - msg_print(call(format, arg)) -end diff --git a/lib/mods/theme/core/gen_idx.lua b/lib/mods/theme/core/gen_idx.lua deleted file mode 100644 index 5f3af435..00000000 --- a/lib/mods/theme/core/gen_idx.lua +++ /dev/null @@ -1,261 +0,0 @@ --- Place here the list of files to parse -files = -{ - "birth.txt", - "experien.hlp", - "gods.txt", - "explore.hlp", - "newbie.hlp", - "advanced.hlp", - "help.hlp", - "general.txt", - "whattome.txt", - "dungeon.txt", - "spoiler.hlp", - "g_melkor.txt", - "skills.txt", - "c_bard.txt", - "c_druid.txt", - "c_lorema.txt", - "c_mage.txt", - "c_mimic.txt", - "c_mindcr.txt", - "c_monk.txt", - "c_palad.txt", - "c_posses.txt", - "c_pr_drk.txt", - "c_pr_eru.txt", - "c_pr_man.txt", - "c_symbia.txt", - "c_alchem.txt", - "c_archer.txt", - "c_assass.txt", - "c_axemas.txt", - "c_demono.txt", - "c_geoman.txt", - "c_hafted.txt", - "c_necro.txt", - "c_polear.txt", - "c_ranger.txt", - "c_rogue.txt", - "c_runecr.txt", - "c_sorcer.txt", - "c_swordm.txt", - "c_thaum.txt", - "c_unbel.txt", - "c_warper.txt", - "c_warrio.txt", - "m_meta.txt", - "rm_skel.txt", - "rm_zomb.txt", - "luckspoi.txt", - "m_air.txt", - "dunspoil.txt", - "g_eru.txt", - "g_manwe.txt", - "g_tulkas.txt", - "m_divin.txt", - "m_mimic.txt", - "m_water.txt", - "magic.txt", - "r_drkelf.txt", - "r_dwarf.txt", - "r_elf.txt", - "r_hielf.txt", - "r_hobbit.txt", - "r_pettyd.txt", - "r_wodelf.txt", - "rm_spec.txt", - "tome_faq.txt", - "ability.txt", - "automat.txt", - "c_summon.txt", - "command.txt", - "corspoil.txt", - "debug.txt", - "m_music.txt", - "rm_barb.txt", - "macrofaq.txt", - "m_necrom.txt", - "m_mindcr.txt", - "m_symbio.txt", - "m_thaum.txt", - "magic.hlp", - "m_convey.txt", - "m_fire.txt", - "m_mana.txt", - "m_mind.txt", - "m_nature.txt", - "m_tempo.txt", - "m_udun.txt", - "m_geoman.txt", - "essences.txt", - "r_ent.txt", - "g_yavann.txt", - "defines.txt", - "rm_vamp.txt", - "inscrip.txt", - "m_earth.txt", - "option.txt", - "attack.txt", - "version.txt", - "m_demono.txt", - "r_beorn.txt", - "r_deathm.txt", - "r_rohank.txt", - "r_hafogr.txt", - "r_human.txt", - "r_kobold.txt", - "r_maia.txt", - "r_orc.txt", - "r_thlord.txt", - "r_troll.txt", - "r_yeek.txt", - "rm_class.txt", - "rm_herm.txt", - "rm_lsoul.txt", - "wishing.txt", - "c_priest.txt", - "fatespoi.txt", - "gambling.txt", - "r_dunad.txt", - "r_gnome.txt", - "r_hafelf.txt", - "c_merch.txt", - "spoil_faq.txt", -} - -out_file = "index.txt" - -index = {} - -function parse_file(file) - local fff = openfile(path_build(ANGBAND_DIR_HELP, file), "r") - local line - - line = read(fff, "*l") - while line do - local i, j, anchor, name, subname = strfind(line, "~~~~~(%d+)|([%d%a -]+)|([%d%a -]+)") - if not i then - i, j, anchor, name = strfind(line, "~~~~~(%d+)|([%d%a -]+)") - - subname = nil - end - - if i then - if not index[name] then - index[name] = {} - end - if subname then - tinsert(index[name], { __name__ = subname, __file__ = file, __anchor__ = anchor}) - else - tinsert(index[name], { __name__ = "__primary__", __file__ = file, __anchor__ = anchor}) - end - end - - line = read(fff, "*l") - end - - closefile(fff) -end - -function sort_fct(a, b) - local i, len - - a = a.__name__ - b = b.__name__ - - if strlen(a) > strlen(b) then len = strlen(b) else len = strlen(a) end - - for i = 1, len do - local ac = strbyte(a, i) - local bc = strbyte(b, i) - - if ac < bc then - return not nil - elseif ac > bc then - return nil - end - end - if strlen(a) > strlen(b) then return nil else return not nil end -end - -function generate_index() - local k, e, index_list - for _, e in files do - parse_file(e) - end - - index_list = {} - for k, e in index do - -- Ok either my sort function or lua sort function sucks ass .. - sort(e, sort_fct) - sort(e, sort_fct) - sort(e, sort_fct) - sort(e, sort_fct) - sort(e, sort_fct) - tinsert(index_list, {__name__= k, __table__ = e}) - end - - -- Ok either my sort function or lua sort function sucks ass .. - sort(index_list, sort_fct) - sort(index_list, sort_fct) - sort(index_list, sort_fct) - sort(index_list, sort_fct) - sort(index_list, sort_fct) - index = index_list -end - -function out_link(fff, space, name, file, anchor) - write(fff, space.."*****"..file.."*"..anchor.."["..name.."]\n") -end - -function print_index() - local i, j, c, new_c - local fff = openfile(path_build(ANGBAND_DIR_HELP, out_file), "w") - - write(fff, -[[|||||oy -#####R /----------------------------------------\ -#####R < Help Index > -#####R \----------------------------------------/ - -This is the index of everything in the T.o.M.E. documentation. - -#####BHit a letter key to jump to the entries for that letter. - -Some entries in the index link to the same place as other entries. This is -intentional, so that the information you want is easy to find. - -Don't forget you can browse the help from the *****help.hlp*02[Main menu]. - -#####sSpotted a problem with the help files, or some content thats missing? -#####sContact fearoffours@t-o-m-e.net . - -]]) - - c = ' ' - for i = 1, getn(index) do - new_c = strbyte(index[i].__name__, 1) - if c ~= new_c then - c = new_c - write(fff, "~~~~~"..c.."\n") - write(fff, "*****/"..strchar(c)..out_file.."*"..c.."["..strchar(c).."]\n") - end - for j = 1, getn(index[i].__table__) do - if index[i].__table__[j].__name__ == "__primary__" then - out_link(fff, " ", index[i].__name__, index[i].__table__[j].__file__, index[i].__table__[j].__anchor__) - end - end - for j = 1, getn(index[i].__table__) do - if index[i].__table__[j].__name__ ~= "__primary__" then - out_link(fff, " ", index[i].__table__[j].__name__, index[i].__table__[j].__file__, index[i].__table__[j].__anchor__) - end - end - end - closefile(fff) -end - -generate_index() - -print_index() diff --git a/lib/mods/theme/core/init.lua b/lib/mods/theme/core/init.lua deleted file mode 100644 index 44ef9a7a..00000000 --- a/lib/mods/theme/core/init.lua +++ /dev/null @@ -1,9 +0,0 @@ --- --- This file is loaded at the initialisation of ToME --- Load the system functions --- - --- various vital helper code -tome_dofile_anywhere(ANGBAND_DIR_CORE, "util.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "player.lua") -tome_dofile_anywhere(ANGBAND_DIR_CORE, "objects.lua") diff --git a/lib/mods/theme/core/objects.lua b/lib/mods/theme/core/objects.lua deleted file mode 100644 index fa77c57b..00000000 --- a/lib/mods/theme/core/objects.lua +++ /dev/null @@ -1,8 +0,0 @@ --- SYSTEM FILE --- --- Lua object funtions --- - -function get_kind(obj) - return k_info[obj.k_idx + 1] -end diff --git a/lib/mods/theme/core/player.lua b/lib/mods/theme/core/player.lua deleted file mode 100644 index deec2e21..00000000 --- a/lib/mods/theme/core/player.lua +++ /dev/null @@ -1,16 +0,0 @@ --- SYSTEM FILE --- --- Lua player funtions --- - --------- skill stuff --------- - --- Easy skill access -function skill(i) - return s_info[i + 1] -end - --- easier inventory access -function player.inventory(i) - return player.inventory_real[i + 1] -end diff --git a/lib/mods/theme/core/util.lua b/lib/mods/theme/core/util.lua deleted file mode 100644 index c3387401..00000000 --- a/lib/mods/theme/core/util.lua +++ /dev/null @@ -1,37 +0,0 @@ --- various stuff to make scripters life easier - --- Beware of the scary undefined globals -function safe_getglobal(x) - local v = rawget(globals(), x) - - if v then - return v - else - error("undefined global variable '"..x.."'") - end -end - -function set_safe_globals() - settagmethod(tag(nil), "getglobal", safe_getglobal) -end -function unset_safe_globals() - settagmethod(tag(nil), "getglobal", nil) -end - -set_safe_globals() - --- Wrapper for the real msg_print and cmsg_print --- it understands if we want color or not -function msg_print(c, m) - if type(c) == "number" then - cmsg_print(c, m) - else - call(%msg_print, { c }) - end -end - - --- Strings -function msg_format(...) - msg_print(call(format, arg)) -end diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0e1b21da..452ca3e2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,3 @@ -# Lua support code. -ADD_SUBDIRECTORY(lua) - SET(SRCS main-gcu.c main-x11.c main-xaw.c main-sdl.c main-gtk2.c z-rand.c z-util.c z-form.c z-virt.c z-term.c @@ -19,8 +16,7 @@ SET(SRCS cmovie.c wizard2.c init2.c birth.c wizard1.c init1.c main.c # Lua bits: - lua_bind.c script.c w_mnster.c w_player.c w_play_c.c w_z_pack.c - w_obj.c w_util.c w_spells.c w_dun.c + lua_bind.c script.c ) # Need a few additional source files for Windows. @@ -41,26 +37,6 @@ if(WIN32) endif(WIN32) -# Macro for defining tolua targets. -MACRO(TOLUA_FILE MODULE_NAME OUTPUT_FILE_NAME) - ADD_CUSTOM_COMMAND( - OUTPUT ${OUTPUT_FILE_NAME} - COMMAND tolua -n ${MODULE_NAME} -o ${CMAKE_CURRENT_BINARY_DIR}/${OUTPUT_FILE_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/${MODULE_NAME}.pkg - DEPENDS tolua ${CMAKE_CURRENT_SOURCE_DIR}/${MODULE_NAME}.pkg - ) - SET_SOURCE_FILES_PROPERTIES("${OUTPUT_FILE_NAME}" PROPERTIES GENERATED TRUE) -ENDMACRO(TOLUA_FILE) - -# Process all the needed modules. -TOLUA_FILE(monster w_mnster.c) -TOLUA_FILE(player w_player.c) -TOLUA_FILE(player_c w_play_c.c) -TOLUA_FILE(z_pack w_z_pack.c) -TOLUA_FILE(object w_obj.c) -TOLUA_FILE(util w_util.c) -TOLUA_FILE(spells w_spells.c) -TOLUA_FILE(dungeon w_dun.c) - # tome executable INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) diff --git a/src/cmd5.c b/src/cmd5.c index 85f2b641..7a69f396 100644 --- a/src/cmd5.c +++ b/src/cmd5.c @@ -12,8 +12,6 @@ #include "angband.h" -#include "lua/lua.h" -#include "tolua.h" #include diff --git a/src/defines.h b/src/defines.h index 6fa426c7..0b6c4c26 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4558,7 +4558,6 @@ #define MAX_HOOKS 77 #define HOOK_TYPE_C 0 -#define HOOK_TYPE_LUA 1 #define HOOK_TYPE_NEW 2 /* diff --git a/src/dungeon.c b/src/dungeon.c index ce259344..d13da812 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -11,12 +11,8 @@ */ #include "angband.h" -#include "lua/lua.h" -#include "tolua.h" #include -extern lua_State* L; - #define TY_CURSE_CHANCE 100 #define DG_CURSE_CHANCE 50 #define AUTO_CURSE_CHANCE 15 diff --git a/src/dungeon.pkg b/src/dungeon.pkg deleted file mode 100644 index f5e4045f..00000000 --- a/src/dungeon.pkg +++ /dev/null @@ -1,1607 +0,0 @@ -/* File: dungeon.pkg */ - -/* - * Purpose: Lua interface defitions for dungeon routines. - * To be processed by tolua to generate C source code. - */ - -$#include "angband.h" - -/** @typedef cptr - * @note String - */ -typedef char* cptr; - -/** @typedef errr - * @note Number - */ -typedef int errr; - -/** @typedef bool - * @note Boolean - */ -typedef unsigned char bool; - -/** @typedef byte - * @note Number - */ -typedef unsigned char byte; - -/** @typedef s16b - * @note Number - */ -typedef signed short s16b; - -/** @typedef u16b - * @note Number - */ -typedef unsigned short u16b; - -/** @typedef s32b - * @note Number - */ -typedef signed int s32b; - -/** @typedef u32b - * @note Number - */ -typedef unsigned int u32b; - -/** @name Cave Grid - * @note Special cave grid flags - * @{ - */ - -/** @def CAVE_MARK - * @note memorized feature - */ -#define CAVE_MARK 0x0001 - -/** @def CAVE_GLOW - * @note self-illuminating - */ -#define CAVE_GLOW 0x0002 - -/** @def CAVE_ICKY - * @note part of a vault - */ -#define CAVE_ICKY 0x0004 - -/** @def CAVE_ROOM - * @note part of a room - */ -#define CAVE_ROOM 0x0008 - -/** @def CAVE_SEEN - * @note seen flag - */ -#define CAVE_SEEN 0x0010 - -/** @def CAVE_VIEW - * @note view flag - */ -#define CAVE_VIEW 0x0020 - -/** @def CAVE_TEMP - * @note temp flag - */ -#define CAVE_TEMP 0x0040 - -/** @def CAVE_WALL - * @note wall flag - */ -#define CAVE_WALL 0x0080 - -/** @def CAVE_TRDT - * @note trap detected - */ -#define CAVE_TRDT 0x0100 - -/** @def CAVE_IDNT - * @note grid identified (fountains) - */ -#define CAVE_IDNT 0x0200 - -/** @def CAVE_SPEC - * @note special mark(quests) - */ -#define CAVE_SPEC 0x0400 - -/** @def CAVE_FREE - * @note no random generation on it - */ -#define CAVE_FREE 0x0800 - -/** @def CAVE_DETECT - * @note Traps detected here - */ -#define CAVE_DETECT 0x1000 - -/** @def CAVE_PLIT - * @note Player lit grid - */ -#define CAVE_PLIT 0x2000 - -/** @def CAVE_MLIT - * @note Monster lit grid - */ -#define CAVE_MLIT 0x4000 -/** @} */ - -/** @name Terrain Feature Indexes - * @note (see "lib/edit/f_info.txt") - * @{ - */ - -/* Nothing */ -/** @def FEAT_NONE */ -#define FEAT_NONE 0x00 - - -/* Basic features */ -/** @def FEAT_FLOOR */ -#define FEAT_FLOOR 0x01 - -/** @def FEAT_FOUNTAIN */ -#define FEAT_FOUNTAIN 0x02 - -/** @def FEAT_GLYPH */ -#define FEAT_GLYPH 0x03 - -/** @def FEAT_OPEN */ -#define FEAT_OPEN 0x04 - -/** @def FEAT_BROKEN */ -#define FEAT_BROKEN 0x05 - -/** @def FEAT_LESS */ -#define FEAT_LESS 0x06 - -/** @def FEAT_MORE */ -#define FEAT_MORE 0x07 - - -/* Quest features -KMW- */ -/** @def FEAT_QUEST_ENTER */ -#define FEAT_QUEST_ENTER 0x08 - -/** @def FEAT_QUEST_EXIT */ -#define FEAT_QUEST_EXIT 0x09 - -/** @def FEAT_QUEST_DOWN */ -#define FEAT_QUEST_DOWN 0x0A - -/** @def FEAT_QUEST_UP */ -#define FEAT_QUEST_UP 0x0B - - -/* Shafts -GSN- */ -/** @def FEAT_SHAFT_DOWN */ -#define FEAT_SHAFT_DOWN 0x0D - -/** @def FEAT_SHAFT_UP */ -#define FEAT_SHAFT_UP 0x0E - - -/* Basic feature */ -/** @def FEAT_EMPTY_FOUNTAIN */ -#define FEAT_EMPTY_FOUNTAIN 0x0F - - -/* Feature 0x10 -- web */ - -/* Traps */ -/** @def FEAT_TRAP */ -#define FEAT_TRAP 0x11 - - -/* Features 0x12 - 0x1F -- unused */ - -/* Doors */ -/** @def FEAT_DOOR_HEAD */ -#define FEAT_DOOR_HEAD 0x20 - -/** @def FEAT_DOOR_TAIL */ -#define FEAT_DOOR_TAIL 0x2F - - -/* Extra */ -/** @def FEAT_SECRET */ -#define FEAT_SECRET 0x30 - -/** @def FEAT_RUBBLE */ -#define FEAT_RUBBLE 0x31 - - -/* Seams */ -/** @def FEAT_MAGMA */ -#define FEAT_MAGMA 0x32 - -/** @def FEAT_QUARTZ */ -#define FEAT_QUARTZ 0x33 - -/** @def FEAT_MAGMA_H */ -#define FEAT_MAGMA_H 0x34 - -/** @def FEAT_QUARTZ_H */ -#define FEAT_QUARTZ_H 0x35 - -/** @def FEAT_MAGMA_K */ -#define FEAT_MAGMA_K 0x36 - -/** @def FEAT_QUARTZ_K */ -#define FEAT_QUARTZ_K 0x37 - - -/* Walls */ -/** @def FEAT_WALL_EXTRA */ -#define FEAT_WALL_EXTRA 0x38 - -/** @def FEAT_WALL_INNER */ -#define FEAT_WALL_INNER 0x39 - -/** @def FEAT_WALL_OUTER */ -#define FEAT_WALL_OUTER 0x3A - -/** @def FEAT_WALL_SOLID */ -#define FEAT_WALL_SOLID 0x3B - -/** @def FEAT_PERM_EXTRA */ -#define FEAT_PERM_EXTRA 0x3C - -/** @def FEAT_PERM_INNER */ -#define FEAT_PERM_INNER 0x3D - -/** @def FEAT_PERM_OUTER */ -#define FEAT_PERM_OUTER 0x3E - -/** @def FEAT_PERM_SOLID */ -#define FEAT_PERM_SOLID 0x3F - - -/* Explosive rune */ -/** @def FEAT_MINOR_GLYPH */ -#define FEAT_MINOR_GLYPH 0x40 - - -/* Pattern */ -/** @def FEAT_PATTERN_START */ -#define FEAT_PATTERN_START 0x41 - -/** @def FEAT_PATTERN_1 */ -#define FEAT_PATTERN_1 0x42 - -/** @def FEAT_PATTERN_2 */ -#define FEAT_PATTERN_2 0x43 - -/** @def FEAT_PATTERN_3 */ -#define FEAT_PATTERN_3 0x44 - -/** @def FEAT_PATTERN_4 */ -#define FEAT_PATTERN_4 0x45 - -/** @def FEAT_PATTERN_END */ -#define FEAT_PATTERN_END 0x46 - -/** @def FEAT_PATTERN_OLD */ -#define FEAT_PATTERN_OLD 0x47 - -/** @def FEAT_PATTERN_XTRA1 */ -#define FEAT_PATTERN_XTRA1 0x48 - -/** @def FEAT_PATTERN_XTRA2 */ -#define FEAT_PATTERN_XTRA2 0x49 - - -/* Shops */ -/** @def FEAT_SHOP */ -#define FEAT_SHOP 0x4A - - -/* Permanent walls for quests */ -/** @def FEAT_QUEST1 */ -#define FEAT_QUEST1 0x4B - -/** @def FEAT_QUEST2 */ -#define FEAT_QUEST2 0x4C - -/** @def FEAT_QUEST3 */ -#define FEAT_QUEST3 0x4D - -/** @def FEAT_QUEST4 */ -#define FEAT_QUEST4 0x4E - - -/* Features 0x4F - 0x53 -- unused */ - -/* Additional terrains */ -/** @def FEAT_SHAL_WATER */ -#define FEAT_SHAL_WATER 0x54 - -/** @def FEAT_DEEP_LAVA */ -#define FEAT_DEEP_LAVA 0x55 - -/** @def FEAT_SHAL_LAVA */ -#define FEAT_SHAL_LAVA 0x56 - -/** @def FEAT_DARK_PIT */ -#define FEAT_DARK_PIT 0x57 - -/** @def FEAT_DIRT */ -#define FEAT_DIRT 0x58 - -/** @def FEAT_GRASS */ -#define FEAT_GRASS 0x59 - -/** @def FEAT_ICE */ -#define FEAT_ICE 0x5A - -/** @def FEAT_SAND */ -#define FEAT_SAND 0x5B - -/** @def FEAT_DEAD_TREE */ -#define FEAT_DEAD_TREE 0x5C - -/** @def FEAT_ASH */ -#define FEAT_ASH 0x5D - -/** @def FEAT_MUD */ -#define FEAT_MUD 0x5E - -/** @def FEAT_ICE_WALL */ -#define FEAT_ICE_WALL 0x5F - -/** @def FEAT_TREES */ -#define FEAT_TREES 0x60 - -/** @def FEAT_MOUNTAIN */ -#define FEAT_MOUNTAIN 0x61 - -/** @def FEAT_SANDWALL */ -#define FEAT_SANDWALL 0x62 - -/** @def FEAT_SANDWALL_H */ -#define FEAT_SANDWALL_H 0x63 - -/** @def FEAT_SANDWALL_K */ -#define FEAT_SANDWALL_K 0x64 - -/* Feature 0x65 -- high mountain chain */ -/* Feature 0x66 -- nether mist */ - -/* Features 0x67 - 0x9F -- unused */ - -/** @def FEAT_BETWEEN - * @note 160 - */ -#define FEAT_BETWEEN 0xA0 - -/* Altars */ -/** @def FEAT_ALTAR_HEAD - * @note 161 - */ -#define FEAT_ALTAR_HEAD 0xA1 - -/** @def FEAT_ALTAR_TAIL - * @note 171 - */ -#define FEAT_ALTAR_TAIL 0xAB - -/** @def FEAT_MARKER - * @note 172 - */ -#define FEAT_MARKER 0xAC - -/* Feature 0xAD -- Underground Tunnel */ -/** @def FEAT_TAINTED_WATER - * @note 174 - */ -#define FEAT_TAINTED_WATER 0xAE - -/** @def FEAT_MON_TRAP - * @note 175 - */ -#define FEAT_MON_TRAP 0xAF - -/** @def FEAT_BETWEEN2 - * @note 176 - */ -#define FEAT_BETWEEN2 0xB0 - -/** @def FEAT_LAVA_WALL - * @note 177 - */ -#define FEAT_LAVA_WALL 0xB1 - -/** @def FEAT_GREAT_FIRE - * @note 178 - */ -#define FEAT_GREAT_FIRE 0xB2 - -/** @def FEAT_WAY_MORE - * @note 179 - */ -#define FEAT_WAY_MORE 0xB3 - -/** @def FEAT_WAY_LESS - * @note 180 - */ -#define FEAT_WAY_LESS 0xB4 - -/* Feature 0xB5 -- field */ - -/** @def FEAT_EKKAIA - * @note 182 - */ -#define FEAT_EKKAIA 0xB6 - -/* Features 0xB7 - 0xBA -- unused */ - -/** @def FEAT_DEEP_WATER - * @note 187 - */ -#define FEAT_DEEP_WATER 0xBB - -/** @def FEAT_GLASS_WALL - * @note 188 - */ -#define FEAT_GLASS_WALL 0xBC - -/** @def FEAT_ILLUS_WALL - * @note 189 - */ -#define FEAT_ILLUS_WALL 0xBD - -/* Feature 0xBE -- grass roof */ -/* Feature 0xBF -- grass roof top */ -/* Feature 0xC0 -- grass roof chimney */ -/* Feature 0xC1 -- brick roof */ -/* Feature 0xC2 -- brick roof top */ -/* Feature 0xC3 -- brick roof chimney */ -/* Feature 0xC4 -- window */ -/* Feature 0xC5 -- small window */ -/* Feature 0xC6 -- rain barrel */ - -/** @def FEAT_FLOWER - * @note 199 - */ -#define FEAT_FLOWER 0xC7 - -/* Feature 0xC8 -- cobblestone road */ -/* Feature 0xC9 -- cobblestone with outlet */ - -/** @def FEAT_SMALL_TREES - * @note 202 - */ -#define FEAT_SMALL_TREES 0xCA - -/** @def FEAT_TOWN - * @note 203 - */ -#define FEAT_TOWN 0xCB - -/* Feature 0xCC -- Underground Tunnel */ - -/** @def FEAT_FIRE - * @note 205 - */ -#define FEAT_FIRE 0xCD - -/* Feature 0xCE -- pile of rubble (permanent) */ -/* Features 0xCF - 0xFF -- unused */ -/** @} */ - -/** @name Dungeon Type Flags (part 1) - * @{ */ - -/** @def DF1_PRINCIPAL - * @note Is a principal dungeon - */ -#define DF1_PRINCIPAL 0x00000001L -/** @def DF1_MAZE - * @note Is a maze-type dungeon - */ -#define DF1_MAZE 0x00000002L -/** @def DF1_SMALLEST - * @note Creates VERY small levels like The Maze - */ -#define DF1_SMALLEST 0x00000004L -/** @def DF1_SMALL - * @note Creates small levels like Dol Goldor - */ -#define DF1_SMALL 0x00000008L -/** @def DF1_BIG - * @note Creates big levels like Moria, and Angband dungeons - */ -#define DF1_BIG 0x00000010L -/** @def DF1_NO_DOORS - * @note No doors on rooms, like Barrowdowns, Old Forest etc) - */ -#define DF1_NO_DOORS 0x00000020L -/** @def DF1_WATER_RIVER - * @note Allow a single water streamer on a level - */ -#define DF1_WATER_RIVER 0x00000040L -/** @def DF1_LAVA_RIVER - * @note Allow a single lava streamer on a level - */ -#define DF1_LAVA_RIVER 0x00000080L -/** @def DF1_WATER_RIVERS - * @note Allow multiple water streamers on a level - */ -#define DF1_WATER_RIVERS 0x00000100L -/** @def DF1_LAVA_RIVERS - * @note Allow multiple lava streamers on a level - */ -#define DF1_LAVA_RIVERS 0x00000200L -/** @def DF1_CAVE - * @note Allow orc-cave like 'fractal' rooms - */ -#define DF1_CAVE 0x00000400L -/** @def DF1_CAVERN - * @note Allow cavern rooms - */ -#define DF1_CAVERN 0x00000800L -/** @def DF1_NO_UP - * @note Disallow up stairs - */ -#define DF1_NO_UP 0x00001000L -/** @def DF1_HOT - * @note Corpses on ground and in pack decay quicker through heat - */ -#define DF1_HOT 0x00002000L -/** @def DF1_COLD - * @note Corpses on ground and in pack decay quicker through cold - */ -#define DF1_COLD 0x00004000L -/** @def DF1_FORCE_DOWN - * @note No up stairs generated - */ -#define DF1_FORCE_DOWN 0x00008000L -/** @def DF1_FORGET - * @note Features are forgotten, like the Maze and Illusory Castle - */ -#define DF1_FORGET 0x00010000L -/** @def DF1_NO_DESTROY - * @note No destroyed levels in dungeon - */ -#define DF1_NO_DESTROY 0x00020000L -/** @def DF1_SAND_VEIN - * @note Like in the sandworm lair - */ -#define DF1_SAND_VEIN 0x00040000L -/** @def DF1_CIRCULAR_ROOMS - * @note Allow circular rooms - */ -#define DF1_CIRCULAR_ROOMS 0x00080000L -/** @def DF1_EMPTY - * @note Allow arena levels - */ -#define DF1_EMPTY 0x00100000L -/** @def DF1_DAMAGE_FEAT - * @note Effect specified in will affect all grids incl. terrain and monsters - */ -#define DF1_DAMAGE_FEAT 0x00200000L -/** @def DF1_FLAT - * @note Creates paths to next areas at edge of level, like Barrowdowns - */ -#define DF1_FLAT 0x00400000L -/** @def DF1_TOWER - * @note You start at bottom and go up rather than the reverse - */ -#define DF1_TOWER 0x00800000L -/** @def DF1_RANDOM_TOWNS - * @note Allow random towns - */ -#define DF1_RANDOM_TOWNS 0x01000000L -/** @def DF1_DOUBLE - * @note Generates everything at double size like Helcaraxe and Erebor - */ -#define DF1_DOUBLE 0x02000000L -/** @def DF1_LIFE_LEVEL - * @note Creates dungeon level on modified 'game of life' algorithm - */ -#define DF1_LIFE_LEVEL 0x04000000L -/** @def DF1_EVOLVE - * @note Evolving, pulsing levels like Heart of the Earth - */ -#define DF1_EVOLVE 0x08000000L -/** @def DF1_ADJUST_LEVEL_1 - * @note Minimum monster level will be equal to dungeon level - */ -#define DF1_ADJUST_LEVEL_1 0x10000000L -/** @def DF1_ADJUST_LEVEL_2 - * @note Minimum monster level will be double the dungeon level - */ -#define DF1_ADJUST_LEVEL_2 0x20000000L -/** @def DF1_NO_RECALL - * @note No recall allowed - */ -#define DF1_NO_RECALL 0x40000000L -/** @def DF1_NO_STREAMERS - * @note No streamers - */ -#define DF1_NO_STREAMERS 0x80000000L -/** @} */ - -/** @name Dungeon Type Flags (part 2) - * @{ */ - -/** @def DF2_ADJUST_LEVEL_1_2 - * @note Minimum monster level will be half the dungeon level - */ -#define DF2_ADJUST_LEVEL_1_2 0x00000001L - -/** @def DF2_NO_SHAFT - * @note No shafts - */ -#define DF2_NO_SHAFT 0x00000002L - -/** @def DF2_ADJUST_LEVEL_PLAYER - * @note Uses player level*2 instead of dungeon level for other ADJUST_LEVEL flags - */ -#define DF2_ADJUST_LEVEL_PLAYER 0x00000004L - -/** @def DF2_NO_TELEPORT */ -#define DF2_NO_TELEPORT 0x00000008L - -/** @def DF2_ASK_LEAVE */ -#define DF2_ASK_LEAVE 0x00000010L - -/** @def DF2_NO_STAIR */ -#define DF2_NO_STAIR 0x00000020L - -/** @def DF2_SPECIAL */ -#define DF2_SPECIAL 0x00000040L - -/** @def DF2_NO_NEW_MONSTER */ -#define DF2_NO_NEW_MONSTER 0x00000080L - -/** @def DF2_DESC */ -#define DF2_DESC 0x00000100L - -/** @def DF2_NO_GENO */ -#define DF2_NO_GENO 0x00000200L - -/** @def DF2_NO_BREATH - * @note Oups, cannot breath here - */ -#define DF2_NO_BREATH 0x00000400L - -/** @def DF2_WATER_BREATH - * @note Oups, cannot breath here, need water breathing - */ -#define DF2_WATER_BREATH 0x00000800L - -/** @def DF2_ELVEN - * @note Try to create elven monster ego - */ -#define DF2_ELVEN 0x00001000L - -/** @def DF2_DWARVEN - * @note Try to create dwarven monster ego - */ -#define DF2_DWARVEN 0x00002000L - -/** @def DF2_NO_EASY_MOVE - * @note Forbid stuff like teleport level, probability travel, ... - */ -#define DF2_NO_EASY_MOVE 0x00004000L - -/** @def DF2_NO_RECALL_OUT - * @note Cannot recall out of the place - */ -#define DF2_NO_RECALL_OUT 0x00008000L - -/** @def DF2_DESC_ALWAYS - * @note Always shows the desc - */ -#define DF2_DESC_ALWAYS 0x00010000L -/** @} */ - -/** @var level_flags1; - * @brief Number - */ -extern u32b dungeon_flags1@level_flags1; - -/** @var level_flags2; - * @brief Number - */ -extern u32b dungeon_flags2@level_flags2; - -/** @def MAX_HGT - * @note Maximum dungeon height in grids, must be a multiple of SCREEN_HGT, - * probably hard-coded to SCREEN_HGT * 3. - */ -#define MAX_HGT 66 - - -/** @def MAX_WID - * @note Maximum dungeon width in grids, must be a multiple of SCREEN_WID, - * probably hard-coded to SCREEN_WID * 3. - */ -#define MAX_WID 198 - - -/** @name Town Defines - * @{ */ - -/** @def TOWN_RANDOM - * @note First random town - */ -#define TOWN_RANDOM 20 - -/** @def TOWN_DUNGEON - * @note Maximun number of towns per dungeon - */ -#define TOWN_DUNGEON 4 - -/** @def TOWN_CHANCE - * @note Chance of 1 town - */ -#define TOWN_CHANCE 50 - -/** @} */ - -/** @name Wilderness Terrains - * @{ - */ - -/** @def TERRAIN_EDGE - * @note Edge of the World - */ -#define TERRAIN_EDGE 0 - -/** @def TERRAIN_TOWN - * @note Town - */ -#define TERRAIN_TOWN 1 - -/** @def TERRAIN_DEEP_WATER - * @note Deep water - */ -#define TERRAIN_DEEP_WATER 2 - -/** @def TERRAIN_SHALLOW_WATER - * @note Shallow water - */ -#define TERRAIN_SHALLOW_WATER 3 - -/** @def TERRAIN_SWAMP - * @note Swamp - */ -#define TERRAIN_SWAMP 4 - -/** @def TERRAIN_DIRT - * @note Dirt - */ -#define TERRAIN_DIRT 5 - -/** @def TERRAIN_GRASS - * @note Grass - */ -#define TERRAIN_GRASS 6 - -/** @def TERRAIN_TREES - * @note Trees - */ -#define TERRAIN_TREES 7 - -/** @def TERRAIN_DESERT - * @note Desert - */ -#define TERRAIN_DESERT 8 - -/** @def TERRAIN_SHALLOW_LAVA - * @note Shallow lava - */ -#define TERRAIN_SHALLOW_LAVA 9 - -/** @def TERRAIN_DEEP_LAVA - * @note Deep lava - */ -#define TERRAIN_DEEP_LAVA 10 - -/** @def TERRAIN_MOUNTAIN - * @note Mountain - */ -#define TERRAIN_MOUNTAIN 11 - -/** @def MAX_WILD_TERRAIN */ -#define MAX_WILD_TERRAIN 18 -/** @} */ - -/** @struct border_type - * @note Border - */ -struct border_type -{ - /** @structvar north[MAX_WID] - * @brief Number - */ - byte north[MAX_WID]; - - /** @structvar south[MAX_WID] - * @brief Number - */ - byte south[MAX_WID]; - - /** @structvar east[MAX_HGT] - * @brief Number - */ - byte east[MAX_HGT]; - - /** @structvar west[MAX_HGT] - * @brief Number - */ - byte west[MAX_HGT]; - - /** @structvar north_west - * @brief Number - */ - byte north_west; - - /** @structvar north_east - * @brief Number - */ - byte north_east; - - /** @structvar south_west - * @brief Number - */ - byte south_west; - - /** @structvar south_east - * @brief Number - */ - byte south_east; -}; - - -/** @struct wilderness_type_info - * @note A structure describing a wilderness area - * with a terrain, a town or a dungeon entrance - */ -struct wilderness_type_info -{ - /** @structvar name - * @brief Number - * @note Name (offset) - */ - u32b name; - - /** @structvar text - * @brief Number - * @note Text (offset) - */ - u32b text; - - /** @structvar entrance - * @brief Number - * @note Which town is there(<1000 i's a town, >=1000 it a dungeon) - */ - u16b entrance; - - /** @structvar road - * @brief Number - * @note Flags of road - */ - byte road; - - /** @structvar level - * @brief Number - * @note Difficulty level - */ - int level; - - /** @structvar flags1 - * @brief Number - * @note Some flags - */ - u32b flags1; - - /** @structvar feat - * @brief Number - * @note The feature of f_info.txt that is used to allow passing, ... and to get a char/color/graph - */ - byte feat; - - /** @structvar terrain_idx - * @brief Number - * @note Terrain index(defined in defines.h) - */ - byte terrain_idx; - - /** @structvar terrain[MAX_WILD_TERRAIN] - * @brief Number - * @note Feature types for the plasma generator - */ - byte terrain[MAX_WILD_TERRAIN]; -}; - -/** @struct wilderness_map - * @note A structure describing a wilderness map - */ -struct wilderness_map -{ - /** @structvar feat - * @brief Number - * @note Wilderness feature - */ - int feat; - - /** @structvar seed - * @brief Number - * @note Seed for the RNG - */ - u32b seed; - - /** @structvar entrance - * @brief Number - * @note Entrance for dungeons - */ - u16b entrance; - - /** @structvar known - * @brief Boolean - * @note Is it seen by the player ? - */ - bool known; -}; - - -/** @struct town_type - * @note A structure describing a town with - * stores and buildings - */ -struct town_type -{ - /** @structvar name - * @brief String - */ - cptr name; - - /** @structvar seed - * @brief Number - * @note Seed for RNG - */ - u32b seed; - - /** @structvar *store - * @brief store_type - * @note The stores [max_st_idx] - */ - store_type store[max_st_idx]; - - /** @structvar numstores - * @brief Number - */ - byte numstores; - - /** @structvar flags - * @brief Number - * @note Town flags - */ - byte flags; - - /** @structvar stocked - * @brief Boolean - * @note Is the town actually stocked ? - * Left this for the sake of compatibility - */ - bool stocked; - - /** @structvar destroyed - * @brief Boolean - * @note Is the town destroyed? - */ - bool destroyed; -}; - -/** @var max_towns - * @brief Number - */ -extern u16b max_towns; - -/** @var town_info[max_towns] - * @brief town_type - */ -extern town_type town_info[max_towns]; - -/** @struct rule_type - * Define monster generation rules - */ -struct rule_type -{ - /** @structvar mode - * @brief Number - * @note Mode of combination of the monster flags - */ - byte mode; - - /** @structvar percent - * @brief Number - * @note Percent of monsters affected by the rule - */ - byte percent; - - /** @structvar mflags1 - * @brief Number - * @note The monster flags that are allowed - */ - u32b mflags1; - - /** @structvar mflags2 - * @brief Number - */ - u32b mflags2; - - /** @structvar mflags3 - * @brief Number - */ - u32b mflags3; - - /** @structvar mflags4 - * @brief Number - */ - u32b mflags4; - - /** @structvar mflags5 - * @brief Number - */ - u32b mflags5; - - /** @structvar mflags6 - * @brief Number - */ - u32b mflags6; - - /** @structvar mflags7 - * @brief Number - */ - u32b mflags7; - - /** @structvar mflags8 - * @brief Number - */ - u32b mflags8; - - /** @structvar mflags9 - * @brief Number - */ - u32b mflags9; - - /** @structvar r_char[5] - * @brief String - * @note Monster race allowed - */ - char r_char[5]; -}; - -/** @struct obj_theme - * @brief "Themed" objects. - * @note Probability in percent for each class of objects to be dropped. - * This could perhaps be an array - but that wouldn't be as clear. - */ -struct obj_theme -{ - /** @structvar treasure - * @brief Number - */ - byte treasure; - - /** @structvar combat - * @brief Number - */ - byte combat; - - /** @structvar magic - * @brief Number - */ - byte magic; - - /** @structvar tools - * @brief Number - */ - byte tools; -}; - -/** @struct dungeon_info_type - * A structure for the != dungeon types - */ -struct dungeon_info_type -{ - /** @structvar name - * @brief Number - * @note Name - */ - u32b name; - - /** @structvar text - * @brief Number - * @note Description - */ - u32b text; - - /** @structvar short_name[3] - * @brief String - * @note Short name - */ - char short_name[3]; - - /** @structvar floor1 - * @brief Number - * @note Floor tile 1 - */ - s16b floor1; - - /** @structvar floor_percent1[2] - * @brief Number - * @note Chance of type 1 - */ - byte floor_percent1[2]; - - /** @structvar floor2 - * @brief Number - * @note Floor tile 2 - */ - s16b floor2; - - /** @structvar floor_percent2[2] - * @brief Number - * @note Chance of type 2 - */ - byte floor_percent2[2]; - - /** @structvar floor3 - * @brief Number - * @note Floor tile 3 - */ - s16b floor3; - - /** @structvar floor_percent3[2] - * @brief Number - * @note Chance of type 3 - */ - byte floor_percent3[2]; - - /** @structvar outer_wall - * @brief Number - * @note Outer wall tile - */ - s16b outer_wall; - - /** @structvar inner_wall - * @brief Number - * @note Inner wall tile - */ - s16b inner_wall; - - /** @structvar fill_type1 - * @brief Number - * @note Cave tile 1 - */ - s16b fill_type1; - - /** @structvar fill_percent1[2] - * @brief Number - * @note Chance of type 1 - */ - byte fill_percent1[2]; - - /** @structvar fill_type2 - * @brief Number - * @note Cave tile 2 - */ - s16b fill_type2; - - /** @structvar fill_percent2[2] - * @brief Number - * @note Chance of type 2 - */ - byte fill_percent2[2]; - - /** @structvar fill_type3 - * @brief Number - * @note Cave tile 3 - */ - s16b fill_type3; - - /** @structvar fill_percent3[2] - * @brief Number - * @note Chance of type 3 - */ - byte fill_percent3[2]; - - /** @structvar fill_method - * @brief Number - * @note Smoothing parameter for the above - */ - byte fill_method; - - /** @structvar mindepth - * @brief Number - * @note Minimal depth - */ - s16b mindepth; - - /** @structvar maxdepth - * @brief Number - * @note Maximal depth - */ - s16b maxdepth; - - /** @structvar principal - * @brief Boolean - * @note If it's a part of the main dungeon - */ - bool principal; - - /** @structvar next - * @brief Number - * @note The next part of the main dungeon - */ - byte next; - - /** @structvar min_plev - * @brief Number - * @note Minimal plev needed to enter -- it's an anti-cheating mesure - */ - byte min_plev; - - /** @structvar min_m_alloc_level - * @brief Number - * @note Minimal number of monsters per level - */ - int min_m_alloc_level; - - /** @structvar max_m_alloc_chance - * @brief Number - * @note There is a 1/max_m_alloc_chance chance per round of creating a new monster - */ - int max_m_alloc_chance; - - /** @structvar flags1 - * @brief Number - * @note Flags 1 - */ - u32b flags1; - - /** @structvar flags2 - * @brief Number - * @note Flags 1 - */ - u32b flags2; - - /** @structvar size_x - * @brief Number - */ - int size_x; - - /** @structvar size_y - * @brief Number - * @note Desired numers of panels - */ - int size_y; - - /** @structvar rule_percents[100] - * @brief Number - * @note Flat rule percents - */ - byte rule_percents[100]; - - /** @structvar rules[5] - * @brief rule_type - * @note Monster generation rules - */ - rule_type rules[5]; - - /** @structvar final_object - * @brief Number - * @note The object you'll find at the bottom - */ - int final_object; - - /** @structvar final_artifact - * @brief Number - * @note The artifact you'll find at the bottom - */ - int final_artifact; - - /** @structvar final_guardian - * @brief Number - * @note The artifact's guardian. If an artifact is specified, then it's NEEDED - */ - int final_guardian; - - /** @structvar ix - * @brief Number - */ - int ix; - - /** @structvar iy - * @brief Number - */ - int iy; - - /** @structvar ox - * @brief Number - */ - int ox; - - /** @structvar oy - * @brief Number - * @note Wilderness coordinates of the entrance/output of the dungeon - */ - int oy; - - /** @structvar objs - * @brief obj_theme - * @note The drops type - */ - obj_theme objs; - - /** @structvar d_dice[4] - * @brief Number - * @note Number of dices - */ - int d_dice[4]; - - /** @structvar d_side[4] - * @brief Number - * @note Number of sides - */ - int d_side[4]; - - /** @structvar d_frequency[4] - * @brief Number - * @note Frequency of damage (1 is the minimum) - */ - int d_frequency[4]; - - /** @structvar d_type[4] - * @brief Number - * @note Type of damage - */ - int d_type[4]; - - /** @structvar t_idx[TOWN_DUNGEON] - * @brief Number - * @note The towns - */ - s16b t_idx[TOWN_DUNGEON]; - - /** @structvar t_level[TOWN_DUNGEON] - * @brief Number - * @note The towns levels - */ - s16b t_level[TOWN_DUNGEON]; - - /** @structvar t_num - * @brief Number - * @note Number of towns - */ - s16b t_num; -}; - -/** @var max_d_idx - * @brief Number - */ -extern u16b max_d_idx; - -/** @var d_info[max_d_idx] - * @brief dungeon_info_type - */ -extern dungeon_info_type d_info[max_d_idx]; - -/** @var *d_name - * @brief String - */ -extern char *d_name; - -/** @var *d_text - * @brief String - */ -extern char *d_text; - -/** @var max_wild_x - * @brief Number - */ -extern u16b max_wild_x; - -/** @var max_wild_y - * @brief Number - */ -extern u16b max_wild_y; - -/** @var max_wf_idx - * @brief Number - */ -extern u16b max_wf_idx; - -/** @var wf_info[max_wf_idx] - * @brief wilderness_type_info - */ -extern wilderness_type_info wf_info[max_wf_idx]; - -/** @var *wf_name - * @brief String - */ -extern char *wf_name; - -/** @var *wf_text - * @brief String - */ -extern char *wf_text; - -/** @var DUNGEON_DEATH - * @brief Number - */ -extern s32b DUNGEON_DEATH; - -/** @var current_dungeon_idx; - * @brief Number - */ -extern byte dungeon_type@current_dungeon_idx; - -/* - * tolua doesnt like wierd arraysn, I'll use accessing functions - * extern wilderness_map wild_map[max_wild_y][max_wild_x]; - */ -$static wilderness_map* lua_get_wild_map(int y, int x) { return &wild_map[y][x]; } - -/** @fn wild_map(int y, int x); - * @brief Return a map of the wilderness at coordinate (y,x).\n - * @param y Number \n y coordinate of wilderness map - * @brief Y-coordinate - * @param x Number \n x coordinate of wilderness map - * @brief X-coordinate - * @return wilderness_map \n map of wilderness at coordinate (y,x) - * @note (see file w_dun.c) - */ -wilderness_map* lua_get_wild_map@wild_map(int y, int x); - -/** @fn place_trap(int y, int x) - * @brief Place a random trap at the given location.\n - * @param y Number \n y coordinate of dungeon - * @brief Y-coordinate - * @param x Number \n x coordinate of dungeon - * @brief X-coordinate - * @note - * Places a random trap at the given location.\n - * The location must be a valid, empty, clean, floor grid. - * @note (see file traps.c) - */ -extern void place_trap(int y, int x); - -/** @fn place_floor(int y, int x) - * @brief Place floor terrain at (y, x).\n - * @param y Number \n y coordinate of dungeon - * @brief Y-coordinate - * @param x Number \n x coordinate of dungeon - * @brief X-coordinate - * @note - * Place floor terrain at (y, x) according to dungeon info. - * @note (see file cave.c) - */ -extern void place_floor(int y, int x); - -/** @fn place_filler(int y, int x) - * @brief Place a cave filler at (y, x).\n - * @param y Number \n y coordinate of dungeon - * @brief Y-coordinate - * @param x Number \n x coordinate of dungeon - * @brief X-coordinate - * @note (see file generate.c) - */ -extern void place_filler(int y, int x); - -/** @fn new_player_spot(int branch) - * @brief Places player in a new location.\n - * @param branch Number \n branch is the dungeon branch (if any). - * @brief Dungeon branch - * @return Boolean \n TRUE if player was placed successfully, otherwise FALSE. - * The global values py and px are updated. - * @note - * Up to 5000 attempts are made to place the player in the dungeon. The grid - * must be a naked floor and not an anti-teleport grid. In some circumstances - * stairs or ways in/out may be created under the player. - * @note (see file generate.c) - */ -extern bool new_player_spot(int branch); - -/** @fn get_level_desc(char *buf) - * @brief Return the special level desc.\n - * @param *buf String - * @brief Description - * @return *buf String \n The level description - * @return Boolean \n TRUE if a level description was returned, otherwise FALSE - * @note - * This is the 'D' line in the dngn files. - * @note (see file levels.c) - */ -extern bool get_level_desc(char *buf); - -/** @fn get_level_flags() - * These are the 'F' lines in the dngn files. - * @note (see file levels.c) - */ -extern void get_level_flags(); - -/** @fn get_dungeon_name(char *buf) - * @brief Return the special level name.\n - * @param *buf String - * @brief Name - * @return *buf String \n The level name - * @return Boolean \n TRUE if a level name was returned, otherwise FALSE - * @note - * This is the 'N' line in the dngn files. - * @note (see file levels.c) - */ -extern bool get_dungeon_name(char *buf); - -/** @fn get_dungeon_special(char *buf) - * @brief Return the map filename.\n - * @param *buf String - * @brief Map filename - * @return *buf String \n The map filename - * @return Boolean \n TRUE if a map filename was returned, otherwise FALSE - * @note - * This is the 'S' line in the dngn files. - * @note (see file levels.c) - */ -extern bool get_dungeon_special(char *buf); - -/** @fn get_command(const char *file, char comm, char *param) - * @brief Return the parameter of command "comm" in file "*file".\n - * @param *file String \n name of the dungeon file. - * @brief Dungeon file - * @param comm String \n The command \n - * 'A' = father branch, 'B' = branch, 'D' = desccription, 'L' = father level, - * 'N' = name, 'S' = savefile extension, 'U' = map filename - * @brief Command - * @param *param String - * @brief Parameter - * @return *param String \n The result of the command - * @return Boolean \n TRUE if a result is returned, otherwise FALSE - * @note (see file levels.c) - */ -extern bool get_command(const char *file, char comm, char *param); - -/** @fn get_branch() - * @brief return the dungeon branch starting form the current dungeon/level. - * @return Number \n The branch - * @note - * This is the 'B' line in the dngn files. - * @note (see file levels.c) - */ -extern int get_branch(); - -/** @fn get_fbranch() - * @brief Return the father dungeon branch. - * @return Number \n The father branch - * @note - * This is the 'A' line in the dngn files. - * @note (see file levels.c) - */ -extern int get_fbranch(); - -/** @fn get_flevel() - * @brief Return the father dungeon level. - * @return Number \n The father level - * @note - * This is the 'L' line in the dngn files. - * @note (see file levels.c) - */ -extern int get_flevel(); - -/** @fn get_dungeon_save(char *buf) - * @brief Return the extension of the savefile for the level.\n - * @param *buf String - * @brief Savefile extension - * @return *buf String \n The savefile extension - * @return Boolean \n TRUE if a savefile extension was returned, otherwise FALSE - * This is the 'S' line in the dngn files. - * @note (see file levels.c) - */ -extern bool get_dungeon_save(char *buf); diff --git a/src/externs.h b/src/externs.h index 71d7b393..f86014dd 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2345,15 +2345,7 @@ extern bool_ easy_floor; /* script.c */ -extern void init_lua(void); extern void init_lua_init(void); -extern int exec_lua(char *file); -extern cptr string_exec_lua(char *file); -extern bool_ tome_dofile(char *file); -extern bool_ tome_dofile_anywhere(cptr dir, char *file, bool_ test_exist); -extern void dump_lua_stack(int min, int max); -extern bool_ call_lua(cptr function, cptr args, cptr ret, ...); -extern bool_ get_lua_var(cptr name, char type, void *arg); /* modules.c */ extern void module_reset_dir(cptr dir, cptr new_path); diff --git a/src/init2.c b/src/init2.c index 2f897d9b..8f20ecfc 100644 --- a/src/init2.c +++ b/src/init2.c @@ -2652,8 +2652,7 @@ void init_angband(void) wipe_hooks(); /* Initialise some other arrays */ - note("[Initialising lua scripting... (lua)]"); - init_lua(); + note("[Initialising scripting... (script)]"); init_lua_init(); /* Initialise skills info */ diff --git a/src/lauxlib.h b/src/lauxlib.h deleted file mode 100644 index 8b6db343..00000000 --- a/src/lauxlib.h +++ /dev/null @@ -1,100 +0,0 @@ -/* -** $Id: lauxlib.h,v 1.4 2002/01/04 03:31:23 pelpel Exp $ -** Auxiliary functions for building Lua libraries -** See Copyright Notice in lua.h -*/ - - -#ifndef lauxlib_h -#define lauxlib_h - - -#include -#include - -#include "lua.h" - - -#ifndef LUALIB_API -#define LUALIB_API extern -#endif - - -struct luaL_reg { - const char *name; - lua_CFunction func; -}; - - -LUALIB_API void luaL_openlib (lua_State *L, const struct luaL_reg *l, int n); -LUALIB_API void luaL_argerror (lua_State *L, int numarg, const char *extramsg); -LUALIB_API const char *luaL_check_lstr (lua_State *L, int numArg, size_t *len); -LUALIB_API const char *luaL_opt_lstr (lua_State *L, int numArg, const char *def, size_t *len); -LUALIB_API long luaL_check_number (lua_State *L, int numArg); -LUALIB_API long luaL_opt_number (lua_State *L, int numArg, long def); - -LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg); -LUALIB_API void luaL_checktype (lua_State *L, int narg, int t); -LUALIB_API void luaL_checkany (lua_State *L, int narg); - -LUALIB_API void luaL_verror (lua_State *L, const char *fmt, ...); -LUALIB_API int luaL_findstring (const char *name, const char *const list[]); - - - -/* -** =============================================================== -** some useful macros -** =============================================================== -*/ - -#define luaL_arg_check(L, cond,numarg,extramsg) if (!(cond)) \ - luaL_argerror(L, numarg,extramsg) -#define luaL_check_string(L,n) (luaL_check_lstr(L, (n), NULL)) -#define luaL_opt_string(L,n,d) (luaL_opt_lstr(L, (n), (d), NULL)) -#define luaL_check_int(L,n) ((int)luaL_check_number(L, n)) -#define luaL_check_long(L,n) ((long)luaL_check_number(L, n)) -#define luaL_opt_int(L,n,d) ((int)luaL_opt_number(L, n,d)) -#define luaL_opt_long(L,n,d) ((long)luaL_opt_number(L, n,d)) -#define luaL_openl(L,a) luaL_openlib(L, a, (sizeof(a)/sizeof(a[0]))) - - -/* -** {====================================================== -** Generic Buffer manipulation -** ======================================================= -*/ - - -#ifndef LUAL_BUFFERSIZE -#define LUAL_BUFFERSIZE BUFSIZ -#endif - - -typedef struct luaL_Buffer { - char *p; /* current position in buffer */ - int level; - lua_State *L; - char buffer[LUAL_BUFFERSIZE]; -} luaL_Buffer; - -#define luaL_putchar(B,c) \ - ((void)((B)->p < &(B)->buffer[LUAL_BUFFERSIZE] || luaL_prepbuffer(B)), \ - (*(B)->p++ = (char)(c))) - -#define luaL_addsize(B,n) ((B)->p += (n)) - -LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B); -LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B); -LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l); -LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s); -LUALIB_API void luaL_addvalue (luaL_Buffer *B); -LUALIB_API void luaL_pushresult (luaL_Buffer *B); - - -/* }====================================================== */ - - -#endif - - diff --git a/src/lua/.gitignore b/src/lua/.gitignore deleted file mode 100644 index 26548e17..00000000 --- a/src/lua/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/liblua.a -/tolua diff --git a/src/lua/CMakeLists.txt b/src/lua/CMakeLists.txt deleted file mode 100644 index df2b30e7..00000000 --- a/src/lua/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -ADD_LIBRARY (lua STATIC - lapi.c lcode.c ldebug.c ldo.c lfunc.c lgc.c - llex.c lmem.c lobject.c lparser.c lstate.c lstring.c - ltable.c ltests.c ltm.c lundump.c lvm.c lzio.c - lauxlib.c lbaselib.c ldblib.c liolib.c lstrlib.c - tolua_lb.c tolua_rg.c tolua_tt.c tolua_tm.c tolua_gp.c - tolua_eh.c tolua_bd.c) - -ADD_EXECUTABLE(tolua tolua.c tolualua.c lua) - -TARGET_LINK_LIBRARIES(tolua lua) diff --git a/src/lua/array.lua b/src/lua/array.lua deleted file mode 100644 index 7929f8cd..00000000 --- a/src/lua/array.lua +++ /dev/null @@ -1,203 +0,0 @@ --- tolua: array class --- Written by Waldemar Celes --- TeCGraf/PUC-Rio --- Jul 1999 --- $Id: array.lua,v 1.2 2001/11/26 23:00:23 darkgod Exp $ - --- This code is free software; you can redistribute it and/or modify it. --- The software provided hereunder is on an "as is" basis, and --- the author has no obligation to provide maintenance, support, updates, --- enhancements, or modifications. - - --- Array class --- Represents a extern array variable or a public member of a class. --- Stores all fields present in a declaration. -classArray = { - _base = classDeclaration, -} - -settag(classArray,tolua_tag) - --- Print method -function classArray:print (ident,close) - print(ident.."Array{") - print(ident.." mod = '"..self.mod.."',") - print(ident.." type = '"..self.type.."',") - print(ident.." ptr = '"..self.ptr.."',") - print(ident.." name = '"..self.name.."',") - print(ident.." def = '"..self.def.."',") - print(ident.." dim = '"..self.dim.."',") - print(ident.." ret = '"..self.ret.."',") - print(ident.."}"..close) -end - --- get variable value -function classArray:getvalue (class,static) - if class and static then - return class..'::'..self.name..'[toluaI_index]' - elseif class then - return 'self->'..self.name..'[toluaI_index]' - else - return self.name..'[toluaI_index]' - end -end - --- Write binding functions -function classArray:supcode () - local class = self:inclass() - - -- get function ------------------------------------------------ - if class then - output("/* get function:",self.name," of class ",class," */") - else - output("/* get function:",self.name," */") - end - self.cgetname = self:cfuncname("toluaI_get") - output("static int",self.cgetname,"(lua_State* tolua_S)") - output("{") - - -- declare index - output(' int toluaI_index;') - - -- declare self, if the case - local _,_,static = strfind(self.mod,'^%s*(static)') - if class and static==nil then - output(' ',class,'*','self;') - output(' lua_pushstring(tolua_S,".self");') - output(' lua_rawget(tolua_S,1);') - output(' self = ') - output('(',class,'*) ') - output('lua_touserdata(tolua_S,-1);') - elseif static then - _,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)') - end - - -- check index - output(' if (!tolua_istype(tolua_S,2,LUA_TNUMBER,0))') - output(' tolua_error(tolua_S,"invalid type in array indexing.");') - output(' toluaI_index = (int)tolua_getnumber(tolua_S,2,0)-1;') - output(' if (toluaI_index<0 || toluaI_index>='..self.dim..')') - output(' tolua_error(tolua_S,"array indexing out of range.");') - - -- return value - local t,ct = isbasic(self.type) - if t then - output(' tolua_push'..t..'(tolua_S,(',ct,')'..self:getvalue(class,static)..');') - else - if self.ptr == '&' or self.ptr == '' then - output(' tolua_pushusertype(tolua_S,(void*)&'..self:getvalue(class,static)..',',self.tag,');') - else - output(' tolua_pushusertype(tolua_S,(void*)'..self:getvalue(class,static)..',',self.tag,');') - end - end - output(' return 1;') - output('}') - output('\n') - - -- set function ------------------------------------------------ - if not strfind(self.mod,'const') then - if class then - output("/* set function:",self.name," of class ",class," */") - else - output("/* set function:",self.name," */") - end - self.csetname = self:cfuncname("toluaI_set") - output("static int",self.csetname,"(lua_State* tolua_S)") - output("{") - - -- declare index - output(' int toluaI_index;') - - -- declare self, if the case - local _,_,static = strfind(self.mod,'^%s*(static)') - if class and static==nil then - output(' ',class,'*','self;') - output(' lua_pushstring(tolua_S,".self");') - output(' lua_rawget(tolua_S,1);') - output(' self = ') - output('(',class,'*) ') - output('lua_touserdata(tolua_S,-1);') - elseif static then - _,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)') - end - - -- check index - output(' if (!tolua_istype(tolua_S,2,LUA_TNUMBER,0))') - output(' tolua_error(tolua_S,"invalid type in array indexing.");') - output(' toluaI_index = (int)tolua_getnumber(tolua_S,2,0)-1;') - output(' if (toluaI_index<0 || toluaI_index>='..self.dim..')') - output(' tolua_error(tolua_S,"array indexing out of range.");') - - -- assign value - local ptr = '' - if self.ptr~='' then ptr = '*' end - output(' ') - if class and static then - output(class..'::'..self.name..'[toluaI_index]') - elseif class then - output('self->'..self.name..'[toluaI_index]') - else - output(self.name..'[toluaI_index]') - end - local t = isbasic(self.type) - output(' = ') - if not t and ptr=='' then output('*') end - output('((',self.mod,self.type) - if not t then - output('*') - end - output(') ') - local def = 0 - if self.def ~= '' then def = self.def end - if t then - output('tolua_get'..t,'(tolua_S,3,',def,'));') - else - output('tolua_getusertype(tolua_S,3,',def,'));') - end - output(' return 0;') - output('}') - output('\n') - end - -end - -function classArray:register () - local parent = self:inclass() or self:inmodule() - if parent then - if self.csetname then - output(' tolua_tablearray(tolua_S,"'..parent..'","'..self.lname..'",'..self.cgetname..','..self.csetname..');') - else - output(' tolua_tablearray(tolua_S,"'..parent..'","'..self.lname..'",'..self.cgetname..',NULL);') - end - else - if self.csetname then - output(' tolua_globalarray(tolua_S,"'..self.lname..'",'..self.cgetname..','..self.csetname..');') - else - output(' tolua_globalarray(tolua_S,"'..self.lname..'",'..self.cgetname..',NULL);') - end - end -end - -function classArray:unregister () - if self:inclass()==nil and self:inmodule()==nil then - output(' lua_pushnil(tolua_S); lua_setglobal(tolua_S,"'..self.lname..'");') - end -end - - --- Internal constructor -function _Array (t) - t._base = classArray - settag(t,tolua_tag) - append(t) - return t -end - --- Constructor --- Expects a string representing the variable declaration. -function Array (s) - return _Array (Declaration(s,'var')) -end - - diff --git a/src/lua/basic.lua b/src/lua/basic.lua deleted file mode 100644 index 2bac463f..00000000 --- a/src/lua/basic.lua +++ /dev/null @@ -1,190 +0,0 @@ --- tolua: basic utility functions --- Written by Waldemar Celes --- TeCGraf/PUC-Rio --- Jul 1998 --- $Id: basic.lua,v 1.2 2001/11/26 23:00:23 darkgod Exp $ - --- This code is free software; you can redistribute it and/or modify it. --- The software provided hereunder is on an "as is" basis, and --- the author has no obligation to provide maintenance, support, updates, --- enhancements, or modifications. - - --- Basic C types and their corresponding Lua types --- All occurrences of "char*" will be replaced by "_cstring", --- and all occurrences of "void*" will be replaced by "_userdata" -_basic = { - ['void'] = '', - ['char'] = 'number', - ['int'] = 'number', - ['short'] = 'number', - ['long'] = 'number', - ['_cstring'] = 'string', - ['_userdata'] = 'userdata', - ['char*'] = 'string', - ['void*'] = 'userdata', - ['bool'] = 'bool', - ['LUA_VALUE'] = 'value', - ['byte'] = 'number', - ['s16b'] = 'number', - ['u16b'] = 'number', - ['s32b'] = 'number', - ['u32b'] = 'number', -} - -_basic_tag = { - ['void'] = '', - ['char'] = 'LUA_TNUMBER', - ['int'] = 'LUA_TNUMBER', - ['short'] = 'LUA_TNUMBER', - ['long'] = 'LUA_TNUMBER', - ['_cstring'] = 'LUA_TSTRING', - ['_userdata'] = 'LUA_TUSERDATA', - ['char*'] = 'LUA_TSTRING', - ['void*'] = 'LUA_TUSERDATA', - ['bool'] = 'tolua_tag(tolua_S,"bool")', - ['byte'] = 'LUA_TNUMBER', - ['s16b'] = 'LUA_TNUMBER', - ['u16b'] = 'LUA_TNUMBER', - ['s32b'] = 'LUA_TNUMBER', - ['u32b'] = 'LUA_TNUMBER', -} - -_basic_ctype = { - number = "long", - string = "const char*", - userdata = "void*", - bool = "int", -} - --- List of user defined types --- Each type corresponds to a variable name that stores its tag value. -_usertype = {} - --- Tag method to provide inheritance -function tolua_index (t,f) - if f == '_base' then -- to avoid loop - return tolua_old_index(t,f) - else - return t._base[f] - end -end - -tolua_tag = newtag() -tolua_old_index = settagmethod(tolua_tag,"index",tolua_index) - --- Error handler -function tolua_error (s) - local out = _OUTPUT - _OUTPUT = _STDERR - if strsub(s,1,1) == '#' then - write("\n** tolua: "..strsub(s,2)..".\n\n") - else - write("\n** tolua internal error: "..s..".\n\n") - return - end - - if _curr_code then - local _,_,s = strfind(_curr_code,"^%s*(.-\n)") -- extract first line - if s==nil then s = _curr_code end - s = gsub(s,"_userdata","void*") -- return with 'void*' - s = gsub(s,"_cstring","char*") -- return with 'char*' - write("Code being processed:\n"..s.."\n") - end - _OUTPUT = out -end - - -_ERRORMESSAGE = tolua_error - --- register an user defined type -function regtype (t) - if not istype(t) then - _usertype[t] = t - end - return t -end - --- return tag name -function tagvar(type,const) - if type == '' or type == 'void' then - return type,0 - else - local m,t = findtypedef(type) - if isbasic(t) then - return t, _basic_tag[t] - end - if strfind(m,'const') then const = 'const' end - regtype(t) - if const and const ~= '' then - t = 'const '..t - end - return t,'tolua_tag(tolua_S,"'..t..'")' - end -end - --- check if basic type -function isbasic (type) - local m,t = findtypedef(type) - local b = _basic[t] - if b then - return b,_basic_ctype[b] - end - return nil -end - --- check if type -function istype (t) - return _basic[t] or _usertype[t] or istypedef(t) -end - - --- split string using a token -function split (s,t) - local l = {n=0} - local f = function (s) - %l.n = %l.n + 1 - %l[%l.n] = s - end - local p = "%s*(.-)%s*"..t.."%s*" - s = gsub(s,"^%s+","") - s = gsub(s,"%s+$","") - s = gsub(s,p,f) - l.n = l.n + 1 - l[l.n] = gsub(s,"(%s%s*)$","") - return l -end - - --- concatenate strings of a table -function concat (t,f,l) - local s = '' - local i=f - while i<=l do - s = s..t[i] - i = i+1 - if i <= l then s = s..' ' end - end - return s -end - --- output line -function output (...) - local i=1 - while i<=arg.n do - if _cont and not strfind(_cont,'[%(,"]') and - strfind(arg[i],"^[%a_~]") then - write(' ') - end - write(arg[i]) - if arg[i] ~= '' then - _cont = strsub(arg[i],-1,-1) - end - i = i+1 - end - if strfind(arg[arg.n],"[%/%)%;%{%}]$") then - _cont=nil write('\n') - end -end - - diff --git a/src/lua/class.lua b/src/lua/class.lua deleted file mode 100644 index 01385178..00000000 --- a/src/lua/class.lua +++ /dev/null @@ -1,85 +0,0 @@ --- tolua: class class --- Written by Waldemar Celes --- TeCGraf/PUC-Rio --- Jul 1998 --- $Id: class.lua,v 1.2 2001/11/26 23:00:23 darkgod Exp $ - --- This code is free software; you can redistribute it and/or modify it. --- The software provided hereunder is on an "as is" basis, and --- the author has no obligation to provide maintenance, support, updates, --- enhancements, or modifications. - - --- Class class --- Represents a class definition. --- Stores the following fields: --- name = class name --- base = class base, if any (only single inheritance is supported) --- {i} = list of members -classClass = { - _base = classContainer, - type = 'class', - name = '', - base = '', -} -settag(classClass,tolua_tag) - - --- register class -function classClass:register () - output(' tolua_cclass(tolua_S,"'..self.name..'","'..self.base..'");') - local i=1 - while self[i] do - self[i]:register() - i = i+1 - end -end - --- unregister class -function classClass:unregister () - output(' lua_pushnil(tolua_S); lua_setglobal(tolua_S,"'..self.name..'");') -end - --- output tags -function classClass:decltag () - self.itype,self.tag = tagvar(self.name); - self.citype,self.ctag = tagvar(self.name,'const'); - local i=1 - while self[i] do - self[i]:decltag() - i = i+1 - end -end - - --- Print method -function classClass:print (ident,close) - print(ident.."Class{") - print(ident.." name = '"..self.name.."',") - print(ident.." base = '"..self.base.."';") - local i=1 - while self[i] do - self[i]:print(ident.." ",",") - i = i+1 - end - print(ident.."}"..close) -end - --- Internal constructor -function _Class (t) - t._base = classClass - settag(t,tolua_tag) - append(t) - return t -end - --- Constructor --- Expects the name, the base and the body of the class. -function Class (n,p,b) - local c = _Class(_Container{name=n, base=p}) - push(c) - c:parse(strsub(b,2,strlen(b)-1)) -- eliminate braces - pop() -end - - diff --git a/src/lua/clean.lua b/src/lua/clean.lua deleted file mode 100644 index ba08d534..00000000 --- a/src/lua/clean.lua +++ /dev/null @@ -1,74 +0,0 @@ --- mark up comments and strings -STR1 = "\001" -STR2 = "\002" -STR3 = "\003" -STR4 = "\004" -REM = "\005" -ANY = "([\001-\005])" -ESC1 = "\006" -ESC2 = "\007" - -MASK = { -- the substitution order is important - {ESC1, "\\'"}, - {ESC2, '\\"'}, - {STR1, "'"}, - {STR2, '"'}, - {STR3, "%[%["}, - {STR4, "%]%]"}, - {REM , "%-%-"}, -} - -function mask (s) - for i = 1,getn(MASK) do - s = gsub(s,MASK[i][2],MASK[i][1]) - end - return s -end - -function unmask (s) - for i = 1,getn(MASK) do - s = gsub(s,MASK[i][1],MASK[i][2]) - end - return s -end - -function clean (s) - -- check for compilation error - local code = "return function () " .. s .. " end" - if not dostring(code) then - return nil - end - - local S = "" -- saved string - - s = mask(s) - - -- remove blanks and comments - while 1 do - local b,e,d = strfind(s,ANY) - if b then - S = S..strsub(s,1,b-1) - s = strsub(s,b+1) - if d==STR1 or d==STR2 then - e = strfind(s,d) - S = S ..d..strsub(s,1,e) - s = strsub(s,e+1) - elseif d==STR3 then - e = strfind(s,STR4) - S = S..d..strsub(s,1,e) - s = strsub(s,e+1) - elseif d==REM then - s = gsub(s,"[^\n]*(\n?)","%1",1) - end - else - S = S..s - break - end - end - -- eliminate unecessary spaces - S = gsub(S,"[ \t]+"," ") - S = gsub(S,"[ \t]*\n[ \t]*","\n") - S = unmask(S) - return S -end - diff --git a/src/lua/code.lua b/src/lua/code.lua deleted file mode 100644 index 08f38ad2..00000000 --- a/src/lua/code.lua +++ /dev/null @@ -1,73 +0,0 @@ --- tolua: code class --- Written by Waldemar Celes --- TeCGraf/PUC-Rio --- Jul 1999 --- $Id: code.lua,v 1.2 2001/11/26 23:00:23 darkgod Exp $ - --- This code is free software; you can redistribute it and/or modify it. --- The software provided hereunder is on an "as is" basis, and --- the author has no obligation to provide maintenance, support, updates, --- enhancements, or modifications. - - --- Code class --- Represents Lua code to be compiled and included --- in the initialization function. --- The following fields are stored: --- text = text code -classCode = { - text = '', - _base = classFeature, -} -settag(classCode,tolua_tag) - --- register code -function classCode:register () - -- clean Lua code - local s = clean(self.text) - if not s then - error("parser error in embedded code") - end - - -- convert to C - output('\n { /* begin embedded lua code */\n') - output(' static unsigned char B[] = {\n ') - local t={n=0} - local b = gsub(s,'(.)',function (c) - local e = '' - %t.n=%t.n+1 if %t.n==15 then %t.n=0 e='\n ' end - return format('%3u,%s',strbyte(c),e) - end - ) - output(b..strbyte(" ")) - output('\n };\n') - output(' lua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua: embedded Lua code");') - output(' } /* end of embedded lua code */\n\n') -end - - --- Print method -function classCode:print (ident,close) - print(ident.."Code{") - print(ident.." text = [["..self.text.."]],") - print(ident.."}"..close) -end - - --- Internal constructor -function _Code (t) - t._base = classCode - settag(t,tolua_tag) - append(t) - return t -end - --- Constructor --- Expects a string representing the code text -function Code (l) - return _Code { - text = l - } -end - - diff --git a/src/lua/container.lua b/src/lua/container.lua deleted file mode 100644 index cbbf11c1..00000000 --- a/src/lua/container.lua +++ /dev/null @@ -1,311 +0,0 @@ --- tolua: container abstract class --- Written by Waldemar Celes --- TeCGraf/PUC-Rio --- Jul 1998 --- $Id: container.lua,v 1.2 2001/11/26 23:00:23 darkgod Exp $ - --- This code is free software; you can redistribute it and/or modify it. --- The software provided hereunder is on an "as is" basis, and --- the author has no obligation to provide maintenance, support, updates, --- enhancements, or modifications. - - --- Container class --- Represents a container of features to be bound --- to lua. -classContainer = -{ - curr = nil, - _base = classFeature, -} -settag(classContainer,tolua_tag) - --- output tags -function classContainer:decltag () - push(self) - local i=1 - while self[i] do - self[i]:decltag() - i = i+1 - end - pop() -end - - --- write support code -function classContainer:supcode () - push(self) - local i=1 - while self[i] do - self[i]:supcode() - i = i+1 - end - pop() -end - - --- Internal container constructor -function _Container (self) - self._base = classContainer - settag(self,tolua_tag) - self.n = 0 - self.typedefs = {n=0} - self.lnames = {} - return self -end - --- push container -function push (t) - classContainer.curr = t -end - --- pop container -function pop () - classContainer.curr = classContainer.curr.parent -end - --- append to current container -function append (t) - return classContainer.curr:append(t) -end - --- append typedef to current container -function appendtypedef (t) - return classContainer.curr:appendtypedef(t) -end - --- substitute typedef -function findtypedef (type) - return classContainer.curr:findtypedef(type) -end - --- check if is typedef -function istypedef (type) - return classContainer.curr:istypedef(type) -end - --- append feature to container -function classContainer:append (t) - self.n = self.n + 1 - self[self.n] = t - t.parent = self -end - --- append typedef -function classContainer:appendtypedef (t) - self.typedefs.n = self.typedefs.n + 1 - self.typedefs[self.typedefs.n] = t -end - --- determine lua function name overload -function classContainer:overload (lname) - if not self.lnames[lname] then - self.lnames[lname] = 0 - else - self.lnames[lname] = self.lnames[lname] + 1 - end - return format("%02d",self.lnames[lname]) -end - -function classContainer:findtypedef (type) - local env = self - while env do - if env.typedefs then - local i=1 - while env.typedefs[i] do - if env.typedefs[i].utype == type then - local mod1,type1 = env.typedefs[i].mod,env.typedefs[i].type - local mod2,type2 = findtypedef(type1) - return mod2..' '..mod1,type2 - end - i = i+1 - end - end - env = env.parent - end - return '',type -end - -function classContainer:istypedef (type) - local env = self - while env do - if env.typedefs then - local i=1 - while env.typedefs[i] do - if env.typedefs[i].utype == type then - return 1 - end - i = i+1 - end - end - env = env.parent - end - return nil -end - --- parse chunk -function classContainer:doparse (s) - - -- try module - do - local b,e,name,body = strfind(s,"^%s*module%s%s*([_%w][_%w]*)%s*(%b{})%s*") - if b then - _curr_code = strsub(s,b,e) - Module(name,body) - return strsub(s,e+1) - end - end - - -- try define - do - local b,e,name = strfind(s,"^%s*#define%s%s*([^%s]*)[^\n]*\n%s*") - if b then - _curr_code = strsub(s,b,e) - Define(name) - return strsub(s,e+1) - end - end - - -- try enumerates - do - local b,e,body = strfind(s,"^%s*enum[^{]*(%b{})%s*;?%s*") - if b then - _curr_code = strsub(s,b,e) - Enumerate(body) - return strsub(s,e+1) - end - end - - do - local b,e,body,name = strfind(s,"^%s*typedef%s%s*enum[^{]*(%b{})%s*([%w_][^%s]*)%s*;%s*") - if b then - _curr_code = strsub(s,b,e) - Enumerate(body) - Typedef("int "..name) - return strsub(s,e+1) - end - end - - -- try operator - do - local b,e,decl,kind,arg,const = strfind(s,"^%s*([_%w][_%w%s%*&]*operator)%s*([^%s][^%s]*)%s*(%b())%s*(c?o?n?s?t?)%s*;%s*") - if b then - _curr_code = strsub(s,b,e) - Operator(decl,kind,arg,const) - return strsub(s,e+1) - end - end - - -- try function - do - local b,e,decl,arg,const = strfind(s,"^%s*([~_%w][_@%w%s%*&]*[_%w])%s*(%b())%s*(c?o?n?s?t?)%s*=?%s*0?%s*;%s*") - if not b then - -- try a single letter function name - b,e,decl,arg,const = strfind(s,"^%s*([_%w])%s*(%b())%s*(c?o?n?s?t?)%s*;%s*") - end - if b then - _curr_code = strsub(s,b,e) - Function(decl,arg,const) - return strsub(s,e+1) - end - end - - -- try inline function - do - local b,e,decl,arg,const = strfind(s,"^%s*([~_%w][_@%w%s%*&]*[_%w])%s*(%b())%s*(c?o?n?s?t?)%s*%b{}%s*") - if not b then - -- try a single letter function name - b,e,decl,arg,const = strfind(s,"^%s*([_%w])%s*(%b())%s*(c?o?n?s?t?)%s*%b{}%s*") - end - if b then - _curr_code = strsub(s,b,e) - Function(decl,arg,const) - return strsub(s,e+1) - end - end - - -- try class - do - local b,e,name,base,body = strfind(s,"^%s*class%s*([_%w][_%w]*)%s*(.-)%s*(%b{})%s*;%s*") - if not b then - b,e,name,base,body = strfind(s,"^%s*struct%s*([_%w][_%w]*)%s*(.-)%s*(%b{})%s*;%s*") - if not b then - base = '' - b,e,body,name = strfind(s,"^%s*typedef%s%s*struct%s%s*[_%w]*%s*(%b{})%s*([_%w][_%w]*)%s*;%s*") - end - end - if b then - if base ~= '' then - local b,e - b,e,base = strfind(base,".-([_%w][_%w]*)$") - end - _curr_code = strsub(s,b,e) - Class(name,base,body) - return strsub(s,e+1) - end - end - - -- try typedef - do - local b,e,types = strfind(s,"^%s*typedef%s%s*(.-)%s*;%s*") - if b then - _curr_code = strsub(s,b,e) - Typedef(types) - return strsub(s,e+1) - end - end - - -- try variable - do - local b,e,decl = strfind(s,"^%s*([_%w][_@%s%w%d%*&]*[_%w%d])%s*;%s*") - if b then - _curr_code = strsub(s,b,e) - Variable(decl) - return strsub(s,e+1) - end - end - - -- try array - do - local b,e,decl = strfind(s,"^%s*([_%w][][_@%s%w%d%*&%-%>]*[]_%w%d])%s*;%s*") - if b then - _curr_code = strsub(s,b,e) - Array(decl) - return strsub(s,e+1) - end - end - - -- try code - do - local b,e,code = strfind(s,"^%s*(%b\1\2)") - if b then - Code(strsub(code,2,-2)) - return strsub(s,e+1) - end - end - - -- try verbatim - do - local b,e,line = strfind(s,"^%s*%$(.-\n)") - if b then - Verbatim(line) - return strsub(s,e+1) - end - end - - -- no matching - if gsub(s,"%s%s*","") ~= "" then - _curr_code = s - error("#parse error") - else - return "" - end -end - -function classContainer:parse (s) - while s ~= '' do - s = self:doparse(s) - end -end - - diff --git a/src/lua/declaration.lua b/src/lua/declaration.lua deleted file mode 100644 index e4d5c688..00000000 --- a/src/lua/declaration.lua +++ /dev/null @@ -1,399 +0,0 @@ --- tolua: declaration class --- Written by Waldemar Celes --- TeCGraf/PUC-Rio --- Jul 1998 --- $Id: declaration.lua,v 1.2 2001/11/26 23:00:23 darkgod Exp $ - --- This code is free software; you can redistribute it and/or modify it. --- The software provided hereunder is on an "as is" basis, and --- the author has no obligation to provide maintenance, support, updates, --- enhancements, or modifications. - - --- Declaration class --- Represents variable, function, or argument declaration. --- Stores the following fields: --- mod = type modifiers --- type = type --- ptr = "*" or "&", if representing a pointer or a reference --- name = name --- dim = dimension, if a vector --- def = default value, if any (only for arguments) --- ret = "*" or "&", if value is to be returned (only for arguments) -classDeclaration = { - _base = classFeature, - mod = '', - type = '', - ptr = '', - name = '', - dim = '', - ret = '', - def = '' -} -settag(classDeclaration,tolua_tag) - --- Create an unique variable name -function create_varname () - if not _varnumber then _varnumber = 0 end - _varnumber = _varnumber + 1 - return "tolua_var_".._varnumber -end - --- Check declaration name --- It also identifies default values -function classDeclaration:checkname () - - if strsub(self.name,1,1) == '[' and not istype(self.type) then - self.name = self.type..self.name - local m = split(self.mod,'%s%s*') - self.type = m[m.n] - self.mod = concat(m,1,m.n-1) - end - - local t = split(self.name,'=') - if t.n==2 then - self.name = t[1] - self.def = t[t.n] - end - - local b,e,d = strfind(self.name,"%[(.-)%]") - if b then - self.name = strsub(self.name,1,b-1) - self.dim = d - end - - - if self.type ~= '' and self.type ~= 'void' and self.name == '' then - self.name = create_varname() - elseif self.kind=='var' then - if self.type=='' and self.name~='' then - self.type = self.type..self.name - self.name = create_varname() - elseif istype(self.name) then - if self.type=='' then self.type = self.name - else self.type = self.type..' '..self.name end - self.name = create_varname() - end - end - -end - --- Check declaration type --- Substitutes typedef's. -function classDeclaration:checktype () - - -- check if there is a pointer to basic type - if isbasic(self.type) and self.ptr~='' then - self.ret = self.ptr - self.ptr = nil - end - - -- check if there is array to be returned - if self.dim~='' and self.ret~='' then - error('#invalid parameter: cannot return an array of values') - end - - -- register type - if self.type~='' then - regtype(self.type) - end - - -- restore 'void*' and 'string*' - if self.type == '_userdata' then self.type = 'void*' - elseif self.type == '_cstring' then self.type = 'char*' - end - --- --- -- if returning value, automatically set default value --- if self.ret ~= '' and self.def == '' then --- self.def = '0' --- end --- - -end - --- Print method -function classDeclaration:print (ident,close) - print(ident.."Declaration{") - print(ident.." mod = '"..self.mod.."',") - print(ident.." type = '"..self.type.."',") - print(ident.." ptr = '"..self.ptr.."',") - print(ident.." name = '"..self.name.."',") - print(ident.." dim = '"..self.dim.."',") - print(ident.." def = '"..self.def.."',") - print(ident.." ret = '"..self.ret.."',") - print(ident.."}"..close) -end - --- declare tag -function classDeclaration:decltag () - self.itype, self.tag = tagvar(self.type,strfind(self.mod,'const')) -end - - --- output type checking -function classDeclaration:outchecktype (narg) - local tag, def - if self.dim ~= '' then - tag = 'LUA_TTABLE' - def = 0 - else - tag = self.tag - def = self.def~='' or 0 - end - return 'tolua_istype(tolua_S,'..narg..','..tag..','..def..')' -end - --- Declare variable -function classDeclaration:declare (narg) - local ptr = '' - if self.ptr~='' then ptr = '*' end - output(" ",self.mod,self.type,ptr) - if self.dim ~= '' and tonumber(self.dim)==nil then - output('*') - end - output(self.name) - if self.dim ~= '' then - if tonumber(self.dim)~=nil then - output('[',self.dim,'];') - else - output(' = (',self.mod,self.type,ptr,'*)', - 'malloc(',self.dim,'*sizeof(',self.type,ptr,'));') - end - else - local t = isbasic(self.type) - output(' = ') - if not t and ptr=='' then output('*') end - output('((',self.mod,self.type) - if not t then - output('*') - end - output(') ') - local def = 0 - if self.def ~= '' then def = self.def end - if t then - output('tolua_get'..t,'(tolua_S,',narg,',',def,'));') - else - output('tolua_getusertype(tolua_S,',narg,',',def,'));') - end - end -end - --- Get parameter value -function classDeclaration:getarray (narg) - if self.dim ~= '' then - output(' {') - local def = self.def~='' or 0 - output(' if (!tolua_arrayistype(tolua_S,',narg,',',self.tag,',',self.dim,',',def,'))') - output(' goto tolua_lerror;') - output(' else\n') - output(' {') - output(' int i;') - output(' for(i=0; i<'..self.dim..';i++)') - local t = isbasic(self.type) - local ptr = '' - if self.ptr~='' then ptr = '*' end - output(' ',self.name..'[i] = ') - if not t and ptr=='' then output('*') end - output('((',self.mod,self.type) - if not t then - output('*') - end - output(') ') - local def = 0 - if self.def ~= '' then def = self.def end - if t then - output('tolua_getfield'..t..'(tolua_S,',narg,',i+1,',def,'));') - else - output('tolua_getfieldusertype(tolua_S,',narg,',i+1,',def,'));') - end - output(' }') - output(' }') - end -end - --- Get parameter value -function classDeclaration:setarray (narg) - if self.dim ~= '' then - output(' {') - output(' int i;') - output(' for(i=0; i<'..self.dim..';i++)') - local t,ct = isbasic(self.type) - if t then - output(' tolua_pushfield'..t..'(tolua_S,',narg,',i+1,(',ct,')',self.name,'[i]);') - else - if self.ptr == '' then - output(' {') - output('#ifdef __cplusplus\n') - output(' void* toluaI_clone = new',self.type,'(',self.name,'[i]);') - output('#else\n') - output(' void* toluaI_clone = tolua_copy(tolua_S,(void*)&',self.name,'[i],sizeof(',self.type,'));') - output('#endif\n') - output(' tolua_pushfieldusertype(tolua_S,',narg,',i+1,tolua_doclone(tolua_S,toluaI_clone,',self.tag,'),',self.tag,');') - output(' }') - - --output(' tolua_pushfieldclone(tolua_S,',narg,',i+1,(void*)&',self.name,'[i],sizeof(',self.type,'),',self.tag,');') - else - output(' tolua_pushfieldusertype(tolua_S,',narg,',i+1,(void*)',self.name,'[i],',self.tag,');') - end - end - output(' }') - end -end - --- Free dynamically allocated array -function classDeclaration:freearray () - if self.dim ~= '' and tonumber(self.dim)==nil then - output(' free(',self.name,');') - end -end - --- Pass parameter -function classDeclaration:passpar () - if self.ptr=='&' then - output('*'..self.name) - elseif self.ret=='*' then - output('&'..self.name) - else - output(self.name) - end -end - --- Return parameter value -function classDeclaration:retvalue () - if self.ret ~= '' then - local t,ct = isbasic(self.type) - if t then - output(' tolua_push'..t..'(tolua_S,(',ct,')'..self.name..');') - else - output(' tolua_pushusertype(tolua_S,(void*)'..self.name..',',self.tag,');') - end - return 1 - end - return 0 -end - --- Internal constructor -function _Declaration (t) - if t.name and t.name~='' then - local n = split(t.name,'@') - t.name = n[1] - t.lname = gsub(n[2] or n[1],"%[.-%]","") - end - t._base = classDeclaration - settag(t,tolua_tag) - t:checkname() - t:checktype() - return t -end - --- Constructor --- Expects the string declaration. --- The kind of declaration can be "var" or "func". -function Declaration (s,kind) - -- eliminate spaces if default value is provided - s = gsub(s,"%s*=%s*","=") - - if kind == "var" then - -- check the form: void - if s == '' or s == 'void' then - return _Declaration{type = 'void', kind = kind} - end - end - - -- check the form: mod type*& name - local t = split(s,'%*%s*&') - if t.n == 2 then - if kind == 'func' then - error("#invalid function return type: "..s) - end - local m = split(t[1],'%s%s*') - return _Declaration{ - name = t[2], - ptr = '*', - ret = '&', - type = m[m.n], - mod = concat(m,1,m.n-1), - kind = kind - } - end - - -- check the form: mod type** name - t = split(s,'%*%s*%*') - if t.n == 2 then - if kind == 'func' then - error("#invalid function return type: "..s) - end - local m = split(t[1],'%s%s*') - return _Declaration{ - name = t[2], - ptr = '*', - ret = '*', - type = m[m.n], - mod = concat(m,1,m.n-1), - kind = kind - } - end - - -- check the form: mod type& name - t = split(s,'&') - if t.n == 2 then - local m = split(t[1],'%s%s*') - return _Declaration{ - name = t[2], - ptr = '&', - type = m[m.n], - mod = concat(m,1,m.n-1) , - kind = kind - } - end - - -- check the form: mod type* name - local s1 = gsub(s,"(%b\[\])",function (n) return gsub(n,'%*','\1') end) - t = split(s1,'%*') - if t.n == 2 then - t[2] = gsub(t[2],'\1','%*') -- restore * in dimension expression - local m = split(t[1],'%s%s*') - return _Declaration{ - name = t[2], - ptr = '*', - type = m[m.n], - mod = concat(m,1,m.n-1) , - kind = kind - } - end - - if kind == 'var' then - -- check the form: mod type name - t = split(s,'%s%s*') - local v - if istype(t[t.n]) then v = '' else v = t[t.n]; t.n = t.n-1 end - return _Declaration{ - name = v, - type = t[t.n], - mod = concat(t,1,t.n-1), - kind = kind - } - - else -- kind == "func" - - -- check the form: mod type name - t = split(s,'%s%s*') - local v = t[t.n] -- last word is the function name - local tp,md - if t.n>1 then - tp = t[t.n-1] - md = concat(t,1,t.n-2) - end - return _Declaration{ - name = v, - type = tp, - mod = md, - kind = kind - } - end - -end - - - diff --git a/src/lua/define.lua b/src/lua/define.lua deleted file mode 100644 index db64db50..00000000 --- a/src/lua/define.lua +++ /dev/null @@ -1,72 +0,0 @@ --- tolua: define class --- Written by Waldemar Celes --- TeCGraf/PUC-Rio --- Jul 1998 --- $Id: define.lua,v 1.2 2001/11/26 23:00:23 darkgod Exp $ - --- This code is free software; you can redistribute it and/or modify it. --- The software provided hereunder is on an "as is" basis, and --- the author has no obligation to provide maintenance, support, updates, --- enhancements, or modifications. - - --- Define class --- Represents a numeric const definition --- The following filds are stored: --- name = constant name -classDefine = { - name = '', - _base = classFeature, -} -settag(classDefine,tolua_tag) - --- register define -function classDefine:register () - local p = self:inmodule() - if p then - output(' tolua_constant(tolua_S,"'..p..'","'..self.lname..'",'..self.name..');') - else - output(' tolua_constant(tolua_S,NULL,"'..self.lname..'",'..self.name..');') - end -end - --- unregister define -function classDefine:unregister () - if not self:inmodule() then - output(' lua_pushnil(tolua_S); lua_setglobal(tolua_S,"'..self.lname..'");') - end -end - --- Print method -function classDefine:print (ident,close) - print(ident.."Define{") - print(ident.." name = '"..self.name.."',") - print(ident.." lname = '"..self.lname.."',") - print(ident.."}"..close) -end - - --- Internal constructor -function _Define (t) - t._base = classDefine - settag(t,tolua_tag) - - if t.name == '' then - error("#invalid define") - end - - append(t) - return t -end - --- Constructor --- Expects a string representing the constant name -function Define (n) - local t = split(n,'@') - return _Define { - name = t[1], - lname = t[2] or t[1] - } -end - - diff --git a/src/lua/doit.lua b/src/lua/doit.lua deleted file mode 100644 index aa184d62..00000000 --- a/src/lua/doit.lua +++ /dev/null @@ -1,73 +0,0 @@ --- Generate binding code --- Written by Waldemar Celes --- TeCGraf/PUC-Rio --- Jul 1998 --- $Id: doit.lua,v 1.2 2001/11/26 23:00:23 darkgod Exp $ - - --- This code is free software; you can redistribute it and/or modify it. --- The software provided hereunder is on an "as is" basis, and --- the author has no obligation to provide maintenance, support, updates, --- enhancements, or modifications. - - --- open input file, if any -if flags.f then - local st, msg = readfrom(flags.f) - if not st then - error('#'..msg) - end -end - --- define package name, if not provided -if not flags.n then - if flags.f then - flags.n = gsub(flags.f,"%..*","") - else - error("#no package name nor input file provided") - end -end - -local p = Package(flags.n) - -if flags.f then - readfrom() -end - -if flags.p then - return -- only parse -end - -if flags.o then - local st,msg = writeto(flags.o) - if not st then - error('#'..msg) - end -end - -if flags.P then - p:print() -else - p:decltag() - p:preamble() - p:supcode() - p:register() - p:unregister() -end - -if flags.o then - writeto() -end - --- write header file -if not flags.P then - if flags.H then - local st,msg = writeto(flags.H) - if not st then - error('#'..msg) - end - p:header() - writeto() - end -end - diff --git a/src/lua/enumerate.lua b/src/lua/enumerate.lua deleted file mode 100644 index 6b2b7466..00000000 --- a/src/lua/enumerate.lua +++ /dev/null @@ -1,93 +0,0 @@ --- tolua: enumerate class --- Written by Waldemar Celes --- TeCGraf/PUC-Rio --- Jul 1998 --- $Id: enumerate.lua,v 1.2 2001/11/26 23:00:23 darkgod Exp $ - --- This code is free software; you can redistribute it and/or modify it. --- The software provided hereunder is on an "as is" basis, and --- the author has no obligation to provide maintenance, support, updates, --- enhancements, or modifications. - - --- Enumerate class --- Represents enumeration --- The following fields are stored: --- {i} = list of constant names -classEnumerate = { - _base = classFeature, -} -settag(classEnumerate,tolua_tag) - --- register enumeration -function classEnumerate:register () - local p = self:inclass() or self:inmodule() - local i=1 - while self[i] do - if p then - if self:inclass() then - output(' tolua_constant(tolua_S,"'..p..'","'..self.lnames[i]..'",'..p..'::'..self[i]..');') - else - output(' tolua_constant(tolua_S,"'..p..'","'..self.lnames[i]..'",'..self[i]..');') - end - else - output(' tolua_constant(tolua_S,NULL,"'..self.lnames[i]..'",'..self[i]..');') - end - i = i+1 - end -end --- register enumeration -function classEnumerate:unregister () - if self:inclass()==nil and self:inmodule()==nil then - local i=1 - while self[i] do - output(' lua_pushnil(tolua_S); lua_setglobal(tolua_S,"'..self.lnames[i]..'");') - i = i+1 - end - end -end - --- Print method -function classEnumerate:print (ident,close) - print(ident.."Enumerate{") - local i=1 - while self[i] do - print(ident.." '"..self[i].."'("..self.lnames[i].."),") - i = i+1 - end - print(ident.."}"..close) -end - --- Internal constructor -function _Enumerate (t) - t._base = classEnumerate - settag(t,tolua_tag) - append(t) - return t -end - --- Constructor --- Expects a string representing the enumerate body -function Enumerate (b) - local t = split(strsub(b,2,-2),',') -- eliminate braces - local i = 1 - local e = {n=0} - while t[i] do - local tt = split(t[i],'=') -- discard initial value - e.n = e.n + 1 - e[e.n] = tt[1] - i = i+1 - end - -- set lua names - i = 1 - e.lnames = {} - while e[i] do - local t = split(e[i],'@') - e[i] = t[1] - e.lnames[i] = t[2] or t[1] - i = i+1 - end - return _Enumerate(e) -end - - diff --git a/src/lua/feature.lua b/src/lua/feature.lua deleted file mode 100644 index 4a4379e1..00000000 --- a/src/lua/feature.lua +++ /dev/null @@ -1,72 +0,0 @@ --- tolua: abstract feature class --- Written by Waldemar Celes --- TeCGraf/PUC-Rio --- Jul 1998 --- $Id: feature.lua,v 1.2 2001/11/26 23:00:23 darkgod Exp $ - --- This code is free software; you can redistribute it and/or modify it. --- The software provided hereunder is on an "as is" basis, and --- the author has no obligation to provide maintenance, support, updates, --- enhancements, or modifications. - - --- Feature class --- Represents the base class of all mapped feature. -classFeature = { -} - --- write support code -function classFeature:supcode () -end - --- output tag -function classFeature:decltag () -end - --- register feature -function classFeature:register () -end - --- unregister feature -function classFeature:unregister () -end - --- translate verbatim -function classFeature:preamble () -end - --- check if feature is inside a class definition --- it returns the feature class name or nil. -function classFeature:inclass () - if self.parent and self.parent.type == 'class' then - return self.parent.name - else - return nil - end -end - --- check if feature is inside a module --- it returns the feature module name or nil. -function classFeature:inmodule () - if self.parent and self.parent.type == 'module' then - return self.parent.name - else - return nil - end -end - --- return C binding function name based on name --- the client specifies a prefix --- return C binding function name --- the client specifies a prefix -function classFeature:cfuncname (n) - if self.parent then - n = self.parent:cfuncname(n) - end - if self.lname then - return n..'_'..self.lname - else - return n..'_'..self.name - end -end - diff --git a/src/lua/function.lua b/src/lua/function.lua deleted file mode 100644 index b87e3488..00000000 --- a/src/lua/function.lua +++ /dev/null @@ -1,317 +0,0 @@ --- tolua: function class --- Written by Waldemar Celes --- TeCGraf/PUC-Rio --- Jul 1998 --- $Id: function.lua,v 1.2 2001/11/26 23:00:23 darkgod Exp $ - --- This code is free software; you can redistribute it and/or modify it. --- The software provided hereunder is on an "as is" basis, and --- the author has no obligation to provide maintenance, support, updates, --- enhancements, or modifications. - - - --- Function class --- Represents a function or a class method. --- The following fields are stored: --- mod = type modifiers --- type = type --- ptr = "*" or "&", if representing a pointer or a reference --- name = name --- args = list of argument declarations --- const = if it is a method receiving a const "this". -classFunction = { - mod = '', - type = '', - ptr = '', - name = '', - args = {n=0}, - const = '', - _base = classFeature, -} -settag(classFunction,tolua_tag) - --- declare tags -function classFunction:decltag () - self.itype,self.tag = tagvar(self.type,strfind(self.mod,'const')) - local i=1 - while self.args[i] do - self.args[i]:decltag() - i = i+1 - end -end - - --- Write binding function --- Outputs C/C++ binding function. -function classFunction:supcode () - local nret = 0 -- number of returned values - local class = self:inclass() - local _,_,static = strfind(self.mod,'^%s*(static)') - - if class then - output("/* method:",self.name," of class ",class," */") - else - output("/* function:",self.name," */") - end - output("static int",self.cname,"(lua_State* tolua_S)") - output("{") - - -- check types - output(' if (\n') - -- check self - local narg - if class then narg=2 else narg=1 end - if class and self.name~='new' and static==nil then - if self.const == 'const' then - output(' !tolua_istype(tolua_S,1,',self.parent.ctag,',0) ||\n') - else - output(' !tolua_istype(tolua_S,1,',self.parent.tag,',0) ||\n') - end - end - -- check args - if self.args[1].type ~= 'void' then - local i=1 - while self.args[i] do - if isbasic(self.args[i].type) ~= 'value' then - output(' !'..self.args[i]:outchecktype(narg)..' ||\n') - end - narg = narg+1 - i = i+1 - end - end - -- check end of list - output(' !tolua_isnoobj(tolua_S,'..narg..')\n )\n goto tolua_lerror;') - - output(' else\n {') - - -- declare self, if the case - local narg - if class then narg=2 else narg=1 end - if class and self.name~='new' and static==nil then - output(' ',self.const,class,'*','self = ') - output('(',self.const,class,'*) ') - output('tolua_getusertype(tolua_S,1,0);') - elseif static then - _,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)') - end - -- declare parameters - if self.args[1].type ~= 'void' then - local i=1 - while self.args[i] do - self.args[i]:declare(narg) - narg = narg+1 - i = i+1 - end - end - - -- check self - if class and self.name~='new' and static==nil then - output(' if (!self) tolua_error(tolua_S,"invalid \'self\' in function \''..self.name..'\'");'); - end - - -- get array element values - if class then narg=2 else narg=1 end - if self.args[1].type ~= 'void' then - local i=1 - while self.args[i] do - self.args[i]:getarray(narg) - narg = narg+1 - i = i+1 - end - end - - -- call function - if class and self.name=='delete' then - output(' delete self;') - elseif class and self.name == 'operator&[]' then - output(' self->operator[](',self.args[1].name,') = ',self.args[2].name,';') - else - output(' {') - if self.type ~= '' and self.type ~= 'void' then - output(' ',self.mod,self.type,self.ptr,'toluaI_ret = ') - output('(',self.mod,self.type,self.ptr,') ') - else - output(' ') - end - if class and self.name=='new' then - output('new',class,'(') - elseif class and static then - output(class..'::'..self.name,'(') - elseif class then - output('self->'..self.name,'(') - else - output(self.name,'(') - end - - -- write parameters - local i=1 - while self.args[i] do - self.args[i]:passpar() - i = i+1 - if self.args[i] then - output(',') - end - end - - output(');') - - -- return values - if self.type ~= '' and self.type ~= 'void' then - nret = nret + 1 - local t,ct = isbasic(self.type) - if t then - output(' tolua_push'..t..'(tolua_S,(',ct,')toluaI_ret);') - else - if self.ptr == '' then - output(' {') - output('#ifdef __cplusplus\n') - output(' void* toluaI_clone = new',self.type,'(toluaI_ret);') - output('#else\n') - output(' void* toluaI_clone = tolua_copy(tolua_S,(void*)&toluaI_ret,sizeof(',self.type,'));') - output('#endif\n') - output(' tolua_pushusertype(tolua_S,tolua_doclone(tolua_S,toluaI_clone,',self.tag,'),',self.tag,');') - output(' }') - --output(' tolua_pushclone((void*)&toluaI_ret,sizeof(',self.type,'),',self.tag,');') - elseif self.ptr == '&' then - output(' tolua_pushusertype(tolua_S,(void*)&toluaI_ret,',self.tag,');') - else - output(' tolua_pushusertype(tolua_S,(void*)toluaI_ret,',self.tag,');') - end - end - end - local i=1 - while self.args[i] do - nret = nret + self.args[i]:retvalue() - i = i+1 - end - output(' }') - - -- set array element values - if class then narg=2 else narg=1 end - if self.args[1].type ~= 'void' then - local i=1 - while self.args[i] do - self.args[i]:setarray(narg) - narg = narg+1 - i = i+1 - end - end - - -- free dynamically allocated array - if self.args[1].type ~= 'void' then - local i=1 - while self.args[i] do - self.args[i]:freearray() - i = i+1 - end - end - end - - output(' }') - output(' return '..nret..';') - - -- call overloaded function or generate error - output('tolua_lerror:\n') - local overload = strsub(self.cname,-2,-1) - 1 - if overload >= 0 then - output(' return '..strsub(self.cname,1,-3)..format("%02d",overload)..'(tolua_S);') - else - output(' tolua_error(tolua_S,"#ferror in function \''..self.lname..'\'.");') - output(' return 0;') - end - - output('}') - output('\n') -end - --- register function -function classFunction:register () - local parent = self:inclass() or self:inmodule() - if parent then - output(' tolua_function(tolua_S,"'..parent..'","'..self.lname..'",'..self.cname..');') - else - output(' tolua_function(tolua_S,NULL,"'..self.lname..'",'..self.cname..');') - end -end - --- unregister function -function classFunction:unregister () - if self:inclass()==nil and self:inmodule()==nil then - output(' lua_pushnil(tolua_S); lua_setglobal(tolua_S,"'..self.lname..'");') - end -end - - --- Print method -function classFunction:print (ident,close) - print(ident.."Function{") - print(ident.." mod = '"..self.mod.."',") - print(ident.." type = '"..self.type.."',") - print(ident.." ptr = '"..self.ptr.."',") - print(ident.." name = '"..self.name.."',") - print(ident.." const = '"..self.const.."',") - print(ident.." cname = '"..self.cname.."',") - print(ident.." lname = '"..self.lname.."',") - print(ident.." args = {") - local i=1 - while self.args[i] do - self.args[i]:print(ident.." ",",") - i = i+1 - end - print(ident.." }") - print(ident.."}"..close) -end - --- determine lua function name overload -function classFunction:overload () - return self.parent:overload(self.lname) -end - - - --- Internal constructor -function _Function (t) - t._base = classFunction - settag(t,tolua_tag) - - if t.const ~= 'const' and t.const ~= '' then - error("#invalid 'const' specification") - end - - append(t) - if t:inclass() then - if t.name == t.parent.name then - t.name = 'new' - t.lname = 'new' - t.type = t.parent.name - t.ptr = '*' - elseif t.name == '~'..t.parent.name then - t.name = 'delete' - t.lname = 'delete' - end - end - t.cname = t:cfuncname("toluaI")..t:overload(t) - return t -end - --- Constructor --- Expects three strings: one representing the function declaration, --- another representing the argument list, and the third representing --- the "const" or empty string. -function Function (d,a,c) - local t = split(strsub(a,2,-2),',') -- eliminate braces - local i=1 - local l = {n=0} - while t[i] do - l.n = l.n+1 - l[l.n] = Declaration(t[i],'var') - i = i+1 - end - local f = Declaration(d,'func') - f.args = l - f.const = c - return _Function(f) -end - - diff --git a/src/lua/lapi.c b/src/lua/lapi.c deleted file mode 100644 index b597e00a..00000000 --- a/src/lua/lapi.c +++ /dev/null @@ -1,499 +0,0 @@ -/* -** $Id: lapi.c,v 1.3 2001/11/26 23:00:23 darkgod Exp $ -** Lua API -** See Copyright Notice in lua.h -*/ - - -#include - -#include "lua.h" - -#include "lapi.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lvm.h" - - -const char lua_ident[] = "$Lua: " LUA_VERSION " " LUA_COPYRIGHT " $\n" - "$Authors: " LUA_AUTHORS " $"; - - - -#define Index(L,i) ((i) >= 0 ? (L->Cbase+((i)-1)) : (L->top+(i))) - -#define api_incr_top(L) incr_top - - - - -TObject *luaA_index (lua_State *L, int index) { - return Index(L, index); -} - - -static TObject *luaA_indexAcceptable (lua_State *L, int index) { - if (index == 0) { - return NULL; - } else if (index > 0) { - TObject *o = L->Cbase+(index-1); - if (o >= L->top) return NULL; - else return o; - } else { - TObject *o = L->top+index; - if(o < L->Cbase) return NULL; - else return o; - } -} - - -void luaA_pushobject (lua_State *L, const TObject *o) { - *L->top = *o; - incr_top; -} - -LUA_API int lua_stackspace (lua_State *L) { - return (L->stack_last - L->top); -} - - - -/* -** basic stack manipulation -*/ - - -LUA_API int lua_gettop (lua_State *L) { - return (L->top - L->Cbase); -} - - -LUA_API void lua_settop (lua_State *L, int index) { - if (index >= 0) - luaD_adjusttop(L, L->Cbase, index); - else - L->top = L->top+index+1; /* index is negative */ -} - - -LUA_API void lua_remove (lua_State *L, int index) { - StkId p = luaA_index(L, index); - while (++p < L->top) *(p-1) = *p; - L->top--; -} - - -LUA_API void lua_insert (lua_State *L, int index) { - StkId p = luaA_index(L, index); - StkId q; - for (q = L->top; q>p; q--) - *q = *(q-1); - *p = *L->top; -} - - -LUA_API void lua_pushvalue (lua_State *L, int index) { - *L->top = *luaA_index(L, index); - api_incr_top(L); -} - - - -/* -** access functions (stack -> C) -*/ - - -LUA_API int lua_type (lua_State *L, int index) { - StkId o = luaA_indexAcceptable(L, index); - return (o == NULL) ? LUA_TNONE : ttype(o); -} - -LUA_API const char *lua_typename (lua_State *L, int t) { - UNUSED(L); - return (t == LUA_TNONE) ? "no value" : luaO_typenames[t]; -} - - -LUA_API int lua_iscfunction (lua_State *L, int index) { - StkId o = luaA_indexAcceptable(L, index); - return (o == NULL) ? 0 : iscfunction(o); -} - -LUA_API int lua_isnumber (lua_State *L, int index) { - TObject *o = luaA_indexAcceptable(L, index); - return (o == NULL) ? 0 : (tonumber(o) == 0); -} - -LUA_API int lua_isstring (lua_State *L, int index) { - int t = lua_type(L, index); - return (t == LUA_TSTRING || t == LUA_TNUMBER); -} - - -LUA_API int lua_tag (lua_State *L, int index) { - StkId o = luaA_indexAcceptable(L, index); - return (o == NULL) ? LUA_NOTAG : luaT_tag(o); -} - -LUA_API int lua_equal (lua_State *L, int index1, int index2) { - StkId o1 = luaA_indexAcceptable(L, index1); - StkId o2 = luaA_indexAcceptable(L, index2); - if (o1 == NULL || o2 == NULL) return 0; /* index out-of-range */ - else return luaO_equalObj(o1, o2); -} - -LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { - StkId o1 = luaA_indexAcceptable(L, index1); - StkId o2 = luaA_indexAcceptable(L, index2); - if (o1 == NULL || o2 == NULL) return 0; /* index out-of-range */ - else return luaV_lessthan(L, o1, o2, L->top); -} - - - -LUA_API long lua_tonumber (lua_State *L, int index) { - StkId o = luaA_indexAcceptable(L, index); - return (o == NULL || tonumber(o)) ? 0 : nvalue(o); -} - -LUA_API const char *lua_tostring (lua_State *L, int index) { - StkId o = luaA_indexAcceptable(L, index); - return (o == NULL || tostring(L, o)) ? NULL : svalue(o); -} - -LUA_API size_t lua_strlen (lua_State *L, int index) { - StkId o = luaA_indexAcceptable(L, index); - return (o == NULL || tostring(L, o)) ? 0 : tsvalue(o)->len; -} - -LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index) { - StkId o = luaA_indexAcceptable(L, index); - return (o == NULL || !iscfunction(o)) ? NULL : clvalue(o)->f.c; -} - -LUA_API void *lua_touserdata (lua_State *L, int index) { - StkId o = luaA_indexAcceptable(L, index); - return (o == NULL || ttype(o) != LUA_TUSERDATA) ? NULL : - tsvalue(o)->u.d.value; -} - -LUA_API const void *lua_topointer (lua_State *L, int index) { - StkId o = luaA_indexAcceptable(L, index); - if (o == NULL) return NULL; - switch (ttype(o)) { - case LUA_TTABLE: - return hvalue(o); - case LUA_TFUNCTION: - return clvalue(o); - default: return NULL; - } -} - - - -/* -** push functions (C -> stack) -*/ - - -LUA_API void lua_pushnil (lua_State *L) { - ttype(L->top) = LUA_TNIL; - api_incr_top(L); -} - - -LUA_API void lua_pushnumber (lua_State *L, long n) { - nvalue(L->top) = n; - ttype(L->top) = LUA_TNUMBER; - api_incr_top(L); -} - - -LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { - tsvalue(L->top) = luaS_newlstr(L, s, len); - ttype(L->top) = LUA_TSTRING; - api_incr_top(L); -} - - -LUA_API void lua_pushstring (lua_State *L, const char *s) { - if (s == NULL) - lua_pushnil(L); - else - lua_pushlstring(L, s, strlen(s)); -} - - -LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { - luaV_Cclosure(L, fn, n); -} - - -LUA_API void lua_pushusertag (lua_State *L, void *u, int tag) { - /* ORDER LUA_T */ - if (!(tag == LUA_ANYTAG || tag == LUA_TUSERDATA || validtag(tag))) - luaO_verror(L, "invalid tag for a userdata (%d)", tag); - tsvalue(L->top) = luaS_createudata(L, u, tag); - ttype(L->top) = LUA_TUSERDATA; - api_incr_top(L); -} - - - -/* -** get functions (Lua -> stack) -*/ - - -LUA_API void lua_getglobal (lua_State *L, const char *name) { - StkId top = L->top; - *top = *luaV_getglobal(L, luaS_new(L, name)); - L->top = top; - api_incr_top(L); -} - - -LUA_API void lua_gettable (lua_State *L, int index) { - StkId t = Index(L, index); - StkId top = L->top; - *(top-1) = *luaV_gettable(L, t); - L->top = top; /* tag method may change top */ -} - - -LUA_API void lua_rawget (lua_State *L, int index) { - StkId t = Index(L, index); - LUA_ASSERT(ttype(t) == LUA_TTABLE, "table expected"); - *(L->top - 1) = *luaH_get(L, hvalue(t), L->top - 1); -} - - -LUA_API void lua_rawgeti (lua_State *L, int index, int n) { - StkId o = Index(L, index); - LUA_ASSERT(ttype(o) == LUA_TTABLE, "table expected"); - *L->top = *luaH_getnum(hvalue(o), n); - api_incr_top(L); -} - - -LUA_API void lua_getglobals (lua_State *L) { - hvalue(L->top) = L->gt; - ttype(L->top) = LUA_TTABLE; - api_incr_top(L); -} - - -LUA_API int lua_getref (lua_State *L, int ref) { - if (ref == LUA_REFNIL) - ttype(L->top) = LUA_TNIL; - else if (0 <= ref && ref < L->refSize && - (L->refArray[ref].st == LOCK || L->refArray[ref].st == HOLD)) - *L->top = L->refArray[ref].o; - else - return 0; - api_incr_top(L); - return 1; -} - - -LUA_API void lua_newtable (lua_State *L) { - hvalue(L->top) = luaH_new(L, 0); - ttype(L->top) = LUA_TTABLE; - api_incr_top(L); -} - - - -/* -** set functions (stack -> Lua) -*/ - - -LUA_API void lua_setglobal (lua_State *L, const char *name) { - StkId top = L->top; - luaV_setglobal(L, luaS_new(L, name)); - L->top = top-1; /* remove element from the top */ -} - - -LUA_API void lua_settable (lua_State *L, int index) { - StkId t = Index(L, index); - StkId top = L->top; - luaV_settable(L, t, top-2); - L->top = top-2; /* pop index and value */ -} - - -LUA_API void lua_rawset (lua_State *L, int index) { - StkId t = Index(L, index); - LUA_ASSERT(ttype(t) == LUA_TTABLE, "table expected"); - *luaH_set(L, hvalue(t), L->top-2) = *(L->top-1); - L->top -= 2; -} - - -LUA_API void lua_rawseti (lua_State *L, int index, int n) { - StkId o = Index(L, index); - LUA_ASSERT(ttype(o) == LUA_TTABLE, "table expected"); - *luaH_setint(L, hvalue(o), n) = *(L->top-1); - L->top--; -} - - -LUA_API void lua_setglobals (lua_State *L) { - StkId newtable = --L->top; - LUA_ASSERT(ttype(newtable) == LUA_TTABLE, "table expected"); - L->gt = hvalue(newtable); -} - - -LUA_API int lua_ref (lua_State *L, int lock) { - int ref; - if (ttype(L->top-1) == LUA_TNIL) - ref = LUA_REFNIL; - else { - if (L->refFree != NONEXT) { /* is there a free place? */ - ref = L->refFree; - L->refFree = L->refArray[ref].st; - } - else { /* no more free places */ - luaM_growvector(L, L->refArray, L->refSize, 1, struct Ref, - "reference table overflow", MAX_INT); - L->nblocks += sizeof(struct Ref); - ref = L->refSize++; - } - L->refArray[ref].o = *(L->top-1); - L->refArray[ref].st = lock ? LOCK : HOLD; - } - L->top--; - return ref; -} - - -/* -** "do" functions (run Lua code) -** (most of them are in ldo.c) -*/ - -LUA_API void lua_rawcall (lua_State *L, int nargs, int nresults) { - luaD_call(L, L->top-(nargs+1), nresults); -} - - -/* -** Garbage-collection functions -*/ - -/* GC values are expressed in Kbytes: #bytes/2^10 */ -#define GCscale(x) ((int)((x)>>10)) -#define GCunscale(x) ((unsigned long)(x)<<10) - -LUA_API int lua_getgcthreshold (lua_State *L) { - return GCscale(L->GCthreshold); -} - -LUA_API int lua_getgccount (lua_State *L) { - return GCscale(L->nblocks); -} - -LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold) { - if (newthreshold > GCscale(ULONG_MAX)) - L->GCthreshold = ULONG_MAX; - else - L->GCthreshold = GCunscale(newthreshold); - luaC_checkGC(L); -} - - -/* -** miscellaneous functions -*/ - -LUA_API void lua_settag (lua_State *L, int tag) { - luaT_realtag(L, tag); - switch (ttype(L->top-1)) { - case LUA_TTABLE: - hvalue(L->top-1)->htag = tag; - break; - case LUA_TUSERDATA: - tsvalue(L->top-1)->u.d.tag = tag; - break; - default: - luaO_verror(L, "cannot change the tag of a %.20s", - luaO_typename(L->top-1)); - } -} - - -LUA_API void lua_unref (lua_State *L, int ref) { - if (ref >= 0) { - LUA_ASSERT(ref < L->refSize && L->refArray[ref].st < 0, "invalid ref"); - L->refArray[ref].st = L->refFree; - L->refFree = ref; - } -} - - -LUA_API int lua_next (lua_State *L, int index) { - StkId t = luaA_index(L, index); - Node *n; - LUA_ASSERT(ttype(t) == LUA_TTABLE, "table expected"); - n = luaH_next(L, hvalue(t), luaA_index(L, -1)); - if (n) { - *(L->top-1) = *key(n); - *L->top = *val(n); - api_incr_top(L); - return 1; - } - else { /* no more elements */ - L->top -= 1; /* remove key */ - return 0; - } -} - - -LUA_API int lua_getn (lua_State *L, int index) { - Hash *h = hvalue(luaA_index(L, index)); - const TObject *value = luaH_getstr(h, luaS_new(L, "n")); /* value = h.n */ - if (ttype(value) == LUA_TNUMBER) - return (int)nvalue(value); - else { - Number max = 0; - int i = h->size; - Node *n = h->node; - while (i--) { - if (ttype(key(n)) == LUA_TNUMBER && - ttype(val(n)) != LUA_TNIL && - nvalue(key(n)) > max) - max = nvalue(key(n)); - n++; - } - return (int)max; - } -} - - -LUA_API void lua_concat (lua_State *L, int n) { - StkId top = L->top; - luaV_strconc(L, n, top); - L->top = top-(n-1); - luaC_checkGC(L); -} - - -LUA_API void *lua_newuserdata (lua_State *L, size_t size) { - TString *ts = luaS_newudata(L, size, NULL); - tsvalue(L->top) = ts; - ttype(L->top) = LUA_TUSERDATA; - api_incr_top(L); - return ts->u.d.value; -} - diff --git a/src/lua/lapi.h b/src/lua/lapi.h deleted file mode 100644 index d6e1c44f..00000000 --- a/src/lua/lapi.h +++ /dev/null @@ -1,17 +0,0 @@ -/* -** $Id: lapi.h,v 1.3 2001/11/26 23:00:23 darkgod Exp $ -** Auxiliary functions from Lua API -** See Copyright Notice in lua.h -*/ - -#ifndef lapi_h -#define lapi_h - - -#include "lobject.h" - - -TObject *luaA_index (lua_State *L, int index); -void luaA_pushobject (lua_State *L, const TObject *o); - -#endif diff --git a/src/lua/lauxlib.c b/src/lua/lauxlib.c deleted file mode 100644 index 810bca20..00000000 --- a/src/lua/lauxlib.c +++ /dev/null @@ -1,216 +0,0 @@ -/* -** $Id: lauxlib.c,v 1.3 2001/11/26 23:00:23 darkgod Exp $ -** Auxiliary functions for building Lua libraries -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include - -/* This file uses only the official API of Lua. -** Any function declared here could be written as an application function. -** With care, these functions can be used by other libraries. -*/ - -#include "lua.h" - -#include "lauxlib.h" -#include "luadebug.h" - - - -LUALIB_API int luaL_findstring (const char *name, const char *const list[]) { - int i; - for (i=0; list[i]; i++) - if (strcmp(list[i], name) == 0) - return i; - return -1; /* name not found */ -} - -LUALIB_API void luaL_argerror (lua_State *L, int narg, const char *extramsg) { - lua_Debug ar; - lua_getstack(L, 0, &ar); - lua_getinfo(L, "n", &ar); - if (ar.name == NULL) - ar.name = "?"; - luaL_verror(L, "bad argument #%d to `%.50s' (%.100s)", - narg, ar.name, extramsg); -} - - -static void type_error (lua_State *L, int narg, int t) { - char buff[50]; - sprintf(buff, "%.8s expected, got %.8s", lua_typename(L, t), - lua_typename(L, lua_type(L, narg))); - luaL_argerror(L, narg, buff); -} - - -LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { - if (space > lua_stackspace(L)) - luaL_verror(L, "stack overflow (%.30s)", mes); -} - - -LUALIB_API void luaL_checktype(lua_State *L, int narg, int t) { - if (lua_type(L, narg) != t) - type_error(L, narg, t); -} - - -LUALIB_API void luaL_checkany (lua_State *L, int narg) { - if (lua_type(L, narg) == LUA_TNONE) - luaL_argerror(L, narg, "value expected"); -} - - -LUALIB_API const char *luaL_check_lstr (lua_State *L, int narg, size_t *len) { - const char *s = lua_tostring(L, narg); - if (!s) type_error(L, narg, LUA_TSTRING); - if (len) *len = lua_strlen(L, narg); - return s; -} - - -LUALIB_API const char *luaL_opt_lstr (lua_State *L, int narg, const char *def, size_t *len) { - if (lua_isnull(L, narg)) { - if (len) - *len = (def ? strlen(def) : 0); - return def; - } - else return luaL_check_lstr(L, narg, len); -} - - -LUALIB_API long luaL_check_number (lua_State *L, int narg) { - long d = lua_tonumber(L, narg); - if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ - type_error(L, narg, LUA_TNUMBER); - return d; -} - - -LUALIB_API long luaL_opt_number (lua_State *L, int narg, long def) { - if (lua_isnull(L, narg)) return def; - else return luaL_check_number(L, narg); -} - - -LUALIB_API void luaL_openlib (lua_State *L, const struct luaL_reg *l, int n) { - int i; - for (i=0; ip == (B)->buffer) -#define bufflen(B) ((B)->p - (B)->buffer) -#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) - -#define LIMIT (LUA_MINSTACK/2) - - -static int emptybuffer (luaL_Buffer *B) { - size_t l = bufflen(B); - if (l == 0) return 0; /* put nothing on stack */ - else { - lua_pushlstring(B->L, B->buffer, l); - B->p = B->buffer; - B->level++; - return 1; - } -} - - -static void adjuststack (luaL_Buffer *B) { - if (B->level > 1) { - lua_State *L = B->L; - int toget = 1; /* number of levels to concat */ - size_t toplen = lua_strlen(L, -1); - do { - size_t l = lua_strlen(L, -(toget+1)); - if (B->level - toget + 1 >= LIMIT || toplen > l) { - toplen += l; - toget++; - } - else break; - } while (toget < B->level); - if (toget >= 2) { - lua_concat(L, toget); - B->level = B->level - toget + 1; - } - } -} - - -LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { - if (emptybuffer(B)) - adjuststack(B); - return B->buffer; -} - - -LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { - while (l--) - luaL_putchar(B, *s++); -} - - -LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { - luaL_addlstring(B, s, strlen(s)); -} - - -LUALIB_API void luaL_pushresult (luaL_Buffer *B) { - emptybuffer(B); - if (B->level == 0) - lua_pushlstring(B->L, NULL, 0); - else if (B->level > 1) - lua_concat(B->L, B->level); - B->level = 1; -} - - -LUALIB_API void luaL_addvalue (luaL_Buffer *B) { - lua_State *L = B->L; - size_t vl = lua_strlen(L, -1); - if (vl <= bufffree(B)) { /* fit into buffer? */ - memcpy(B->p, lua_tostring(L, -1), vl); /* put it there */ - B->p += vl; - lua_pop(L, 1); /* remove from stack */ - } - else { - if (emptybuffer(B)) - lua_insert(L, -2); /* put buffer before new value */ - B->level++; /* add new value into B stack */ - adjuststack(B); - } -} - - -LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { - B->L = L; - B->p = B->buffer; - B->level = 0; -} - -/* }====================================================== */ diff --git a/src/lua/lauxlib.h b/src/lua/lauxlib.h deleted file mode 100644 index a8d35aff..00000000 --- a/src/lua/lauxlib.h +++ /dev/null @@ -1,100 +0,0 @@ -/* -** $Id: lauxlib.h,v 1.2 2001/11/26 23:00:23 darkgod Exp $ -** Auxiliary functions for building Lua libraries -** See Copyright Notice in lua.h -*/ - - -#ifndef lauxlib_h -#define lauxlib_h - - -#include -#include - -#include "lua.h" - - -#ifndef LUALIB_API -#define LUALIB_API extern -#endif - - -struct luaL_reg { - const char *name; - lua_CFunction func; -}; - - -LUALIB_API void luaL_openlib (lua_State *L, const struct luaL_reg *l, int n); -LUALIB_API void luaL_argerror (lua_State *L, int numarg, const char *extramsg); -LUALIB_API const char *luaL_check_lstr (lua_State *L, int numArg, size_t *len); -LUALIB_API const char *luaL_opt_lstr (lua_State *L, int numArg, const char *def, size_t *len); -LUALIB_API long luaL_check_number (lua_State *L, int numArg); -LUALIB_API long luaL_opt_number (lua_State *L, int numArg, long def); - -LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg); -LUALIB_API void luaL_checktype (lua_State *L, int narg, int t); -LUALIB_API void luaL_checkany (lua_State *L, int narg); - -LUALIB_API void luaL_verror (lua_State *L, const char *fmt, ...); -LUALIB_API int luaL_findstring (const char *name, const char *const list[]); - - - -/* -** =============================================================== -** some useful macros -** =============================================================== -*/ - -#define luaL_arg_check(L, cond,numarg,extramsg) if (!(cond)) \ - luaL_argerror(L, numarg,extramsg) -#define luaL_check_string(L,n) (luaL_check_lstr(L, (n), NULL)) -#define luaL_opt_string(L,n,d) (luaL_opt_lstr(L, (n), (d), NULL)) -#define luaL_check_int(L,n) ((int)luaL_check_number(L, n)) -#define luaL_check_long(L,n) ((long)luaL_check_number(L, n)) -#define luaL_opt_int(L,n,d) ((int)luaL_opt_number(L, n,d)) -#define luaL_opt_long(L,n,d) ((long)luaL_opt_number(L, n,d)) -#define luaL_openl(L,a) luaL_openlib(L, a, (sizeof(a)/sizeof(a[0]))) - - -/* -** {====================================================== -** Generic Buffer manipulation -** ======================================================= -*/ - - -#ifndef LUAL_BUFFERSIZE -#define LUAL_BUFFERSIZE BUFSIZ -#endif - - -typedef struct luaL_Buffer { - char *p; /* current position in buffer */ - int level; - lua_State *L; - char buffer[LUAL_BUFFERSIZE]; -} luaL_Buffer; - -#define luaL_putchar(B,c) \ - ((void)((B)->p < &(B)->buffer[LUAL_BUFFERSIZE] || luaL_prepbuffer(B)), \ - (*(B)->p++ = (char)(c))) - -#define luaL_addsize(B,n) ((B)->p += (n)) - -LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B); -LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B); -LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l); -LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s); -LUALIB_API void luaL_addvalue (luaL_Buffer *B); -LUALIB_API void luaL_pushresult (luaL_Buffer *B); - - -/* }====================================================== */ - - -#endif - - diff --git a/src/lua/lbaselib.c b/src/lua/lbaselib.c deleted file mode 100644 index 71c643aa..00000000 --- a/src/lua/lbaselib.c +++ /dev/null @@ -1,651 +0,0 @@ -/* -** $Id: lbaselib.c,v 1.2 2001/11/26 23:00:23 darkgod Exp $ -** Basic library -** See Copyright Notice in lua.h -*/ - - - -#include -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "luadebug.h" -#include "lualib.h" - - - -/* -** If your system does not support `stderr', redefine this function, or -** redefine _ERRORMESSAGE so that it won't need _ALERT. -*/ -static int luaB__ALERT (lua_State *L) { - fputs(luaL_check_string(L, 1), stderr); - return 0; -} - - -/* -** Basic implementation of _ERRORMESSAGE. -** The library `liolib' redefines _ERRORMESSAGE for better error information. -*/ -static int luaB__ERRORMESSAGE (lua_State *L) { - luaL_checktype(L, 1, LUA_TSTRING); - lua_getglobal(L, LUA_ALERT); - if (lua_isfunction(L, -1)) { /* avoid error loop if _ALERT is not defined */ - lua_Debug ar; - lua_pushstring(L, "error: "); - lua_pushvalue(L, 1); - if (lua_getstack(L, 1, &ar)) { - lua_getinfo(L, "Sl", &ar); - if (ar.source && ar.currentline > 0) { - char buff[100]; - sprintf(buff, "\n <%.70s: line %d>", ar.short_src, ar.currentline); - lua_pushstring(L, buff); - lua_concat(L, 2); - } - } - lua_pushstring(L, "\n"); - lua_concat(L, 3); - lua_rawcall(L, 1, 0); - } - return 0; -} - - -/* -** If your system does not support `stdout', you can just remove this function. -** If you need, you can define your own `print' function, following this -** model but changing `fputs' to put the strings at a proper place -** (a console window or a log file, for instance). -*/ -static int luaB_print (lua_State *L) { - int n = lua_gettop(L); /* number of arguments */ - int i; - lua_getglobal(L, "tostring"); - for (i=1; i<=n; i++) { - const char *s; - lua_pushvalue(L, -1); /* function to be called */ - lua_pushvalue(L, i); /* value to print */ - lua_rawcall(L, 1, 1); - s = lua_tostring(L, -1); /* get result */ - if (s == NULL) - lua_error(L, "`tostring' must return a string to `print'"); - if (i>1) fputs("\t", stdout); - fputs(s, stdout); - lua_pop(L, 1); /* pop result */ - } - fputs("\n", stdout); - return 0; -} - - -static int luaB_tonumber (lua_State *L) { - int base = luaL_opt_int(L, 2, 10); - if (base == 10) { /* standard conversion */ - luaL_checkany(L, 1); - if (lua_isnumber(L, 1)) { - lua_pushnumber(L, lua_tonumber(L, 1)); - return 1; - } - } - else { - const char *s1 = luaL_check_string(L, 1); - char *s2; - unsigned long n; - luaL_arg_check(L, 2 <= base && base <= 36, 2, "base out of range"); - n = strtoul(s1, &s2, base); - if (s1 != s2) { /* at least one valid digit? */ - while (isspace((unsigned char)*s2)) s2++; /* skip trailing spaces */ - if (*s2 == '\0') { /* no invalid trailing characters? */ - lua_pushnumber(L, n); - return 1; - } - } - } - lua_pushnil(L); /* else not a number */ - return 1; -} - - -static int luaB_error (lua_State *L) { - lua_error(L, luaL_opt_string(L, 1, NULL)); - return 0; /* to avoid warnings */ -} - -static int luaB_setglobal (lua_State *L) { - luaL_checkany(L, 2); - lua_setglobal(L, luaL_check_string(L, 1)); - return 0; -} - -static int luaB_getglobal (lua_State *L) { - lua_getglobal(L, luaL_check_string(L, 1)); - return 1; -} - -static int luaB_tag (lua_State *L) { - luaL_checkany(L, 1); - lua_pushnumber(L, lua_tag(L, 1)); - return 1; -} - -static int luaB_settag (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushvalue(L, 1); /* push table */ - lua_settag(L, luaL_check_int(L, 2)); - return 1; /* return table */ -} - -static int luaB_newtag (lua_State *L) { - lua_pushnumber(L, lua_newtag(L)); - return 1; -} - -static int luaB_copytagmethods (lua_State *L) { - lua_pushnumber(L, lua_copytagmethods(L, luaL_check_int(L, 1), - luaL_check_int(L, 2))); - return 1; -} - -static int luaB_globals (lua_State *L) { - lua_getglobals(L); /* value to be returned */ - if (!lua_isnull(L, 1)) { - luaL_checktype(L, 1, LUA_TTABLE); - lua_pushvalue(L, 1); /* new table of globals */ - lua_setglobals(L); - } - return 1; -} - -static int luaB_rawget (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - lua_rawget(L, -2); - return 1; -} - -static int luaB_rawset (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - luaL_checkany(L, 2); - luaL_checkany(L, 3); - lua_rawset(L, -3); - return 1; -} - -static int luaB_settagmethod (lua_State *L) { - int tag = luaL_check_int(L, 1); - const char *event = luaL_check_string(L, 2); - luaL_arg_check(L, lua_isfunction(L, 3) || lua_isnil(L, 3), 3, - "function or nil expected"); - if (strcmp(event, "gc") == 0) - lua_error(L, "deprecated use: cannot set the `gc' tag method from Lua"); - lua_gettagmethod(L, tag, event); - lua_pushvalue(L, 3); - lua_settagmethod(L, tag, event); - return 1; -} - - -static int luaB_gettagmethod (lua_State *L) { - int tag = luaL_check_int(L, 1); - const char *event = luaL_check_string(L, 2); - if (strcmp(event, "gc") == 0) - lua_error(L, "deprecated use: cannot get the `gc' tag method from Lua"); - lua_gettagmethod(L, tag, event); - return 1; -} - - -static int luaB_gcinfo (lua_State *L) { - lua_pushnumber(L, lua_getgccount(L)); - lua_pushnumber(L, lua_getgcthreshold(L)); - return 2; -} - - -static int luaB_collectgarbage (lua_State *L) { - lua_setgcthreshold(L, luaL_opt_int(L, 1, 0)); - return 0; -} - - -static int luaB_type (lua_State *L) { - luaL_checkany(L, 1); - lua_pushstring(L, lua_typename(L, lua_type(L, 1))); - return 1; -} - - -static int luaB_next (lua_State *L) { - luaL_checktype(L, 1, LUA_TTABLE); - lua_settop(L, 2); /* create a 2nd argument if there isn't one */ - if (lua_next(L, 1)) - return 2; - else { - lua_pushnil(L); - return 1; - } -} - - -static int passresults (lua_State *L, int status, int oldtop) { - static const char *const errornames[] = - {"ok", "run-time error", "file error", "syntax error", - "memory error", "error in error handling"}; - if (status == 0) { - int nresults = lua_gettop(L) - oldtop; - if (nresults > 0) - return nresults; /* results are already on the stack */ - else { - lua_pushuserdata(L, NULL); /* at least one result to signal no errors */ - return 1; - } - } - else { /* error */ - lua_pushnil(L); - lua_pushstring(L, errornames[status]); /* error code */ - return 2; - } -} - -static int luaB_dostring (lua_State *L) { - int oldtop = lua_gettop(L); - size_t l; - const char *s = luaL_check_lstr(L, 1, &l); - if (*s == '\27') /* binary files start with ESC... */ - lua_error(L, "`dostring' cannot run pre-compiled code"); - return passresults(L, lua_dobuffer(L, s, l, luaL_opt_string(L, 2, s)), oldtop); -} - - -static int luaB_dofile (lua_State *L) { - int oldtop = lua_gettop(L); - const char *fname = luaL_opt_string(L, 1, NULL); - return passresults(L, lua_dofile(L, fname), oldtop); -} - - -static int luaB_call (lua_State *L) { - int oldtop; - const char *options = luaL_opt_string(L, 3, ""); - int err = 0; /* index of old error method */ - int i, status; - int n; - luaL_checktype(L, 2, LUA_TTABLE); - n = lua_getn(L, 2); - if (!lua_isnull(L, 4)) { /* set new error method */ - lua_getglobal(L, LUA_ERRORMESSAGE); - err = lua_gettop(L); /* get index */ - lua_pushvalue(L, 4); - lua_setglobal(L, LUA_ERRORMESSAGE); - } - oldtop = lua_gettop(L); /* top before function-call preparation */ - /* push function */ - lua_pushvalue(L, 1); - luaL_checkstack(L, n, "too many arguments"); - for (i=0; i=pos; n--) { - lua_rawgeti(L, 1, n); - lua_rawseti(L, 1, n+1); /* t[n+1] = t[n] */ - } - lua_pushvalue(L, v); - lua_rawseti(L, 1, pos); /* t[pos] = v */ - return 0; -} - - -static int luaB_tremove (lua_State *L) { - int pos, n; - luaL_checktype(L, 1, LUA_TTABLE); - n = lua_getn(L, 1); - pos = luaL_opt_int(L, 2, n); - if (n <= 0) return 0; /* table is "empty" */ - lua_rawgeti(L, 1, pos); /* result = t[pos] */ - for ( ;pos= P */ - while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { - if (i>u) lua_error(L, "invalid order function for sorting"); - lua_pop(L, 1); /* remove a[i] */ - } - /* repeat --j until a[j] <= P */ - while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { - if (jt.token); -} - - -/* -** Returns the the previous instruction, for optimizations. -** If there is a jump target between this and the current instruction, -** returns a dummy instruction to avoid wrong optimizations. -*/ -static Instruction previous_instruction (FuncState *fs) { - if (fs->pc > fs->lasttarget) /* no jumps to current position? */ - return fs->f->code[fs->pc-1]; /* returns previous instruction */ - else - return CREATE_0(OP_END); /* no optimizations after an `END' */ -} - - -int luaK_jump (FuncState *fs) { - int j = luaK_code1(fs, OP_JMP, NO_JUMP); - if (j == fs->lasttarget) { /* possible jumps to this jump? */ - luaK_concat(fs, &j, fs->jlt); /* keep them on hold */ - fs->jlt = NO_JUMP; - } - return j; -} - - -static void luaK_fixjump (FuncState *fs, int pc, int dest) { - Instruction *jmp = &fs->f->code[pc]; - if (dest == NO_JUMP) - SETARG_S(*jmp, NO_JUMP); /* point to itself to represent end of list */ - else { /* jump is relative to position following jump instruction */ - int offset = dest-(pc+1); - if (abs(offset) > MAXARG_S) - luaK_error(fs->ls, "control structure too long"); - SETARG_S(*jmp, offset); - } -} - - -static int luaK_getjump (FuncState *fs, int pc) { - int offset = GETARG_S(fs->f->code[pc]); - if (offset == NO_JUMP) /* point to itself represents end of list */ - return NO_JUMP; /* end of list */ - else - return (pc+1)+offset; /* turn offset into absolute position */ -} - - -/* -** returns current `pc' and marks it as a jump target (to avoid wrong -** optimizations with consecutive instructions not in the same basic block). -** discharge list of jumps to last target. -*/ -int luaK_getlabel (FuncState *fs) { - if (fs->pc != fs->lasttarget) { - int lasttarget = fs->lasttarget; - fs->lasttarget = fs->pc; - luaK_patchlist(fs, fs->jlt, lasttarget); /* discharge old list `jlt' */ - fs->jlt = NO_JUMP; /* nobody jumps to this new label (yet) */ - } - return fs->pc; -} - - -void luaK_deltastack (FuncState *fs, int delta) { - fs->stacklevel += delta; - if (fs->stacklevel > fs->f->maxstacksize) { - if (fs->stacklevel > MAXSTACK) - luaK_error(fs->ls, "function or expression too complex"); - fs->f->maxstacksize = fs->stacklevel; - } -} - - -void luaK_kstr (LexState *ls, int c) { - luaK_code1(ls->fs, OP_PUSHSTRING, c); -} - - -static int number_constant (FuncState *fs, Number r) { - /* check whether `r' has appeared within the last LOOKBACKNUMS entries */ - Proto *f = fs->f; - int c = f->nknum; - int lim = c < LOOKBACKNUMS ? 0 : c-LOOKBACKNUMS; - while (--c >= lim) - if (f->knum[c] == r) return c; - /* not found; create a new entry */ - luaM_growvector(fs->L, f->knum, f->nknum, 1, Number, - "constant table overflow", MAXARG_U); - c = f->nknum++; - f->knum[c] = r; - return c; -} - - -void luaK_number (FuncState *fs, Number f) { - if (f <= (Number)MAXARG_S && (Number)(int)f == f) - luaK_code1(fs, OP_PUSHINT, (int)f); /* f has a short integer value */ - else - luaK_code1(fs, OP_PUSHNUM, number_constant(fs, f)); -} - - -void luaK_adjuststack (FuncState *fs, int n) { - if (n > 0) - luaK_code1(fs, OP_POP, n); - else - luaK_code1(fs, OP_PUSHNIL, -n); -} - - -int luaK_lastisopen (FuncState *fs) { - /* check whether last instruction is an open function call */ - Instruction i = previous_instruction(fs); - if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET) - return 1; - else return 0; -} - - -void luaK_setcallreturns (FuncState *fs, int nresults) { - if (luaK_lastisopen(fs)) { /* expression is an open function call? */ - SETARG_B(fs->f->code[fs->pc-1], nresults); /* set number of results */ - luaK_deltastack(fs, nresults); /* push results */ - } -} - - -static int discharge (FuncState *fs, expdesc *var) { - switch (var->k) { - case VLOCAL: - luaK_code1(fs, OP_GETLOCAL, var->u.index); - break; - case VGLOBAL: - luaK_code1(fs, OP_GETGLOBAL, var->u.index); - break; - case VINDEXED: - luaK_code0(fs, OP_GETTABLE); - break; - case VEXP: - return 0; /* nothing to do */ - } - var->k = VEXP; - var->u.l.t = var->u.l.f = NO_JUMP; - return 1; -} - - -static void discharge1 (FuncState *fs, expdesc *var) { - discharge(fs, var); - /* if it has jumps then it is already discharged */ - if (var->u.l.t == NO_JUMP && var->u.l.f == NO_JUMP) - luaK_setcallreturns(fs, 1); /* call must return 1 value */ -} - - -void luaK_storevar (LexState *ls, const expdesc *var) { - FuncState *fs = ls->fs; - switch (var->k) { - case VLOCAL: - luaK_code1(fs, OP_SETLOCAL, var->u.index); - break; - case VGLOBAL: - luaK_code1(fs, OP_SETGLOBAL, var->u.index); - break; - case VINDEXED: /* table is at top-3; pop 3 elements after operation */ - luaK_code2(fs, OP_SETTABLE, 3, 3); - break; - default: - LUA_INTERNALERROR("invalid var kind to store"); - } -} - - -static OpCode invertjump (OpCode op) { - switch (op) { - case OP_JMPNE: return OP_JMPEQ; - case OP_JMPEQ: return OP_JMPNE; - case OP_JMPLT: return OP_JMPGE; - case OP_JMPLE: return OP_JMPGT; - case OP_JMPGT: return OP_JMPLE; - case OP_JMPGE: return OP_JMPLT; - case OP_JMPT: case OP_JMPONT: return OP_JMPF; - case OP_JMPF: case OP_JMPONF: return OP_JMPT; - default: - LUA_INTERNALERROR("invalid jump instruction"); - return OP_END; /* to avoid warnings */ - } -} - - -static void luaK_patchlistaux (FuncState *fs, int list, int target, - OpCode special, int special_target) { - Instruction *code = fs->f->code; - while (list != NO_JUMP) { - int next = luaK_getjump(fs, list); - Instruction *i = &code[list]; - OpCode op = GET_OPCODE(*i); - if (op == special) /* this `op' already has a value */ - luaK_fixjump(fs, list, special_target); - else { - luaK_fixjump(fs, list, target); /* do the patch */ - if (op == OP_JMPONT) /* remove eventual values */ - SET_OPCODE(*i, OP_JMPT); - else if (op == OP_JMPONF) - SET_OPCODE(*i, OP_JMPF); - } - list = next; - } -} - - -void luaK_patchlist (FuncState *fs, int list, int target) { - if (target == fs->lasttarget) /* same target that list `jlt'? */ - luaK_concat(fs, &fs->jlt, list); /* delay fixing */ - else - luaK_patchlistaux(fs, list, target, OP_END, 0); -} - - -static int need_value (FuncState *fs, int list, OpCode hasvalue) { - /* check whether list has a jump without a value */ - for (; list != NO_JUMP; list = luaK_getjump(fs, list)) - if (GET_OPCODE(fs->f->code[list]) != hasvalue) return 1; - return 0; /* not found */ -} - - -void luaK_concat (FuncState *fs, int *l1, int l2) { - if (*l1 == NO_JUMP) - *l1 = l2; - else { - int list = *l1; - for (;;) { /* traverse `l1' */ - int next = luaK_getjump(fs, list); - if (next == NO_JUMP) { /* end of list? */ - luaK_fixjump(fs, list, l2); - return; - } - list = next; - } - } -} - - -static void luaK_testgo (FuncState *fs, expdesc *v, int invert, OpCode jump) { - int prevpos; /* position of last instruction */ - Instruction *previous; - int *golist, *exitlist; - if (!invert) { - golist = &v->u.l.f; /* go if false */ - exitlist = &v->u.l.t; /* exit if true */ - } - else { - golist = &v->u.l.t; /* go if true */ - exitlist = &v->u.l.f; /* exit if false */ - } - discharge1(fs, v); - prevpos = fs->pc-1; - previous = &fs->f->code[prevpos]; - LUA_ASSERT(*previous==previous_instruction(fs), "no jump allowed here"); - if (!ISJUMP(GET_OPCODE(*previous))) - prevpos = luaK_code1(fs, jump, NO_JUMP); - else { /* last instruction is already a jump */ - if (invert) - SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); - } - luaK_concat(fs, exitlist, prevpos); /* insert last jump in `exitlist' */ - luaK_patchlist(fs, *golist, luaK_getlabel(fs)); - *golist = NO_JUMP; -} - - -void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue) { - luaK_testgo(fs, v, 1, keepvalue ? OP_JMPONF : OP_JMPF); -} - - -static void luaK_goiffalse (FuncState *fs, expdesc *v, int keepvalue) { - luaK_testgo(fs, v, 0, keepvalue ? OP_JMPONT : OP_JMPT); -} - - -static int code_label (FuncState *fs, OpCode op, int arg) { - luaK_getlabel(fs); /* those instructions may be jump targets */ - return luaK_code1(fs, op, arg); -} - - -void luaK_tostack (LexState *ls, expdesc *v, int onlyone) { - FuncState *fs = ls->fs; - if (!discharge(fs, v)) { /* `v' is an expression? */ - OpCode previous = GET_OPCODE(fs->f->code[fs->pc-1]); - if (!ISJUMP(previous) && v->u.l.f == NO_JUMP && v->u.l.t == NO_JUMP) { - /* expression has no jumps */ - if (onlyone) - luaK_setcallreturns(fs, 1); /* call must return 1 value */ - } - else { /* expression has jumps */ - int final; /* position after whole expression */ - int j = NO_JUMP; /* eventual jump over values */ - int p_nil = NO_JUMP; /* position of an eventual PUSHNIL */ - int p_1 = NO_JUMP; /* position of an eventual PUSHINT */ - if (ISJUMP(previous) || need_value(fs, v->u.l.f, OP_JMPONF) - || need_value(fs, v->u.l.t, OP_JMPONT)) { - /* expression needs values */ - if (ISJUMP(previous)) - luaK_concat(fs, &v->u.l.t, fs->pc-1); /* put `previous' in t. list */ - else { - j = code_label(fs, OP_JMP, NO_JUMP); /* to jump over both pushes */ - /* correct stack for compiler and symbolic execution */ - luaK_adjuststack(fs, 1); - } - p_nil = code_label(fs, OP_PUSHNILJMP, 0); - p_1 = code_label(fs, OP_PUSHINT, 1); - luaK_patchlist(fs, j, luaK_getlabel(fs)); - } - final = luaK_getlabel(fs); - luaK_patchlistaux(fs, v->u.l.f, p_nil, OP_JMPONF, final); - luaK_patchlistaux(fs, v->u.l.t, p_1, OP_JMPONT, final); - v->u.l.f = v->u.l.t = NO_JUMP; - } - } -} - - -void luaK_prefix (LexState *ls, UnOpr op, expdesc *v) { - FuncState *fs = ls->fs; - if (op == OPR_MINUS) { - luaK_tostack(ls, v, 1); - luaK_code0(fs, OP_MINUS); - } - else { /* op == NOT */ - Instruction *previous; - discharge1(fs, v); - previous = &fs->f->code[fs->pc-1]; - if (ISJUMP(GET_OPCODE(*previous))) - SET_OPCODE(*previous, invertjump(GET_OPCODE(*previous))); - else - luaK_code0(fs, OP_NOT); - /* interchange true and false lists */ - { int temp = v->u.l.f; v->u.l.f = v->u.l.t; v->u.l.t = temp; } - } -} - - -void luaK_infix (LexState *ls, BinOpr op, expdesc *v) { - FuncState *fs = ls->fs; - switch (op) { - case OPR_AND: - luaK_goiftrue(fs, v, 1); - break; - case OPR_OR: - luaK_goiffalse(fs, v, 1); - break; - default: - luaK_tostack(ls, v, 1); /* all other binary operators need a value */ - } -} - - - -static const struct { - OpCode opcode; /* opcode for each binary operator */ - int arg; /* default argument for the opcode */ -} codes[] = { /* ORDER OPR */ - {OP_ADD, 0}, {OP_SUB, 0}, {OP_MULT, 0}, {OP_DIV, 0}, - {OP_POW, 0}, {OP_CONCAT, 2}, - {OP_JMPNE, NO_JUMP}, {OP_JMPEQ, NO_JUMP}, - {OP_JMPLT, NO_JUMP}, {OP_JMPLE, NO_JUMP}, - {OP_JMPGT, NO_JUMP}, {OP_JMPGE, NO_JUMP} -}; - - -void luaK_posfix (LexState *ls, BinOpr op, expdesc *v1, expdesc *v2) { - FuncState *fs = ls->fs; - switch (op) { - case OPR_AND: { - LUA_ASSERT(v1->u.l.t == NO_JUMP, "list must be closed"); - discharge1(fs, v2); - v1->u.l.t = v2->u.l.t; - luaK_concat(fs, &v1->u.l.f, v2->u.l.f); - break; - } - case OPR_OR: { - LUA_ASSERT(v1->u.l.f == NO_JUMP, "list must be closed"); - discharge1(fs, v2); - v1->u.l.f = v2->u.l.f; - luaK_concat(fs, &v1->u.l.t, v2->u.l.t); - break; - } - default: { - luaK_tostack(ls, v2, 1); /* `v2' must be a value */ - luaK_code1(fs, codes[op].opcode, codes[op].arg); - } - } -} - - -static void codelineinfo (FuncState *fs) { - Proto *f = fs->f; - LexState *ls = fs->ls; - if (ls->lastline > fs->lastline) { - luaM_growvector(fs->L, f->lineinfo, f->nlineinfo, 2, int, - "line info overflow", MAX_INT); - if (ls->lastline > fs->lastline+1) - f->lineinfo[f->nlineinfo++] = -(ls->lastline - (fs->lastline+1)); - f->lineinfo[f->nlineinfo++] = fs->pc; - fs->lastline = ls->lastline; - } -} - - -int luaK_code0 (FuncState *fs, OpCode o) { - return luaK_code2(fs, o, 0, 0); -} - - -int luaK_code1 (FuncState *fs, OpCode o, int arg1) { - return luaK_code2(fs, o, arg1, 0); -} - - -int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2) { - Instruction i = previous_instruction(fs); - int delta = luaK_opproperties[o].push - luaK_opproperties[o].pop; - int optm = 0; /* 1 when there is an optimization */ - switch (o) { - case OP_CLOSURE: { - delta = -arg2+1; - break; - } - case OP_SETTABLE: { - delta = -arg2; - break; - } - case OP_SETLIST: { - if (arg2 == 0) return NO_JUMP; /* nothing to do */ - delta = -arg2; - break; - } - case OP_SETMAP: { - if (arg1 == 0) return NO_JUMP; /* nothing to do */ - delta = -2*arg1; - break; - } - case OP_RETURN: { - if (GET_OPCODE(i) == OP_CALL && GETARG_B(i) == MULT_RET) { - SET_OPCODE(i, OP_TAILCALL); - SETARG_B(i, arg1); - optm = 1; - } - break; - } - case OP_PUSHNIL: { - if (arg1 == 0) return NO_JUMP; /* nothing to do */ - delta = arg1; - switch(GET_OPCODE(i)) { - case OP_PUSHNIL: SETARG_U(i, GETARG_U(i)+arg1); optm = 1; break; - default: break; - } - break; - } - case OP_POP: { - if (arg1 == 0) return NO_JUMP; /* nothing to do */ - delta = -arg1; - switch(GET_OPCODE(i)) { - case OP_SETTABLE: SETARG_B(i, GETARG_B(i)+arg1); optm = 1; break; - default: break; - } - break; - } - case OP_GETTABLE: { - switch(GET_OPCODE(i)) { - case OP_PUSHSTRING: /* `t.x' */ - SET_OPCODE(i, OP_GETDOTTED); - optm = 1; - break; - case OP_GETLOCAL: /* `t[i]' */ - SET_OPCODE(i, OP_GETINDEXED); - optm = 1; - break; - default: break; - } - break; - } - case OP_ADD: { - switch(GET_OPCODE(i)) { - case OP_PUSHINT: SET_OPCODE(i, OP_ADDI); optm = 1; break; /* `a+k' */ - default: break; - } - break; - } - case OP_SUB: { - switch(GET_OPCODE(i)) { - case OP_PUSHINT: /* `a-k' */ - i = CREATE_S(OP_ADDI, -GETARG_S(i)); - optm = 1; - break; - default: break; - } - break; - } - case OP_CONCAT: { - delta = -arg1+1; - switch(GET_OPCODE(i)) { - case OP_CONCAT: /* `a..b..c' */ - SETARG_U(i, GETARG_U(i)+1); - optm = 1; - break; - default: break; - } - break; - } - case OP_MINUS: { - switch(GET_OPCODE(i)) { - case OP_PUSHINT: /* `-k' */ - SETARG_S(i, -GETARG_S(i)); - optm = 1; - break; - case OP_PUSHNUM: /* `-k' */ - SET_OPCODE(i, OP_PUSHNEGNUM); - optm = 1; - break; - default: break; - } - break; - } - case OP_JMPNE: { - if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a~=nil' */ - i = CREATE_S(OP_JMPT, NO_JUMP); - optm = 1; - } - break; - } - case OP_JMPEQ: { - if (i == CREATE_U(OP_PUSHNIL, 1)) { /* `a==nil' */ - i = CREATE_0(OP_NOT); - delta = -1; /* just undo effect of previous PUSHNIL */ - optm = 1; - } - break; - } - case OP_JMPT: - case OP_JMPONT: { - switch (GET_OPCODE(i)) { - case OP_NOT: { - i = CREATE_S(OP_JMPF, NO_JUMP); - optm = 1; - break; - } - case OP_PUSHINT: { - if (o == OP_JMPT) { /* JMPONT must keep original integer value */ - i = CREATE_S(OP_JMP, NO_JUMP); - optm = 1; - } - break; - } - case OP_PUSHNIL: { - if (GETARG_U(i) == 1) { - fs->pc--; /* erase previous instruction */ - luaK_deltastack(fs, -1); /* correct stack */ - return NO_JUMP; - } - break; - } - default: break; - } - break; - } - case OP_JMPF: - case OP_JMPONF: { - switch (GET_OPCODE(i)) { - case OP_NOT: { - i = CREATE_S(OP_JMPT, NO_JUMP); - optm = 1; - break; - } - case OP_PUSHINT: { /* `while 1 do ...' */ - fs->pc--; /* erase previous instruction */ - luaK_deltastack(fs, -1); /* correct stack */ - return NO_JUMP; - } - case OP_PUSHNIL: { /* `repeat ... until nil' */ - if (GETARG_U(i) == 1) { - i = CREATE_S(OP_JMP, NO_JUMP); - optm = 1; - } - break; - } - default: break; - } - break; - } - case OP_GETDOTTED: - case OP_GETINDEXED: - case OP_TAILCALL: - case OP_ADDI: { - LUA_INTERNALERROR("instruction used only for optimizations"); - break; - } - default: { - LUA_ASSERT(delta != VD, "invalid delta"); - break; - } - } - luaK_deltastack(fs, delta); - if (optm) { /* optimize: put instruction in place of last one */ - fs->f->code[fs->pc-1] = i; /* change previous instruction */ - return fs->pc-1; /* do not generate new instruction */ - } - /* else build new instruction */ - switch ((enum Mode)luaK_opproperties[o].mode) { - case iO: i = CREATE_0(o); break; - case iU: i = CREATE_U(o, arg1); break; - case iS: i = CREATE_S(o, arg1); break; - case iAB: i = CREATE_AB(o, arg1, arg2); break; - } - codelineinfo(fs); - /* put new instruction in code array */ - luaM_growvector(fs->L, fs->f->code, fs->pc, 1, Instruction, - "code size overflow", MAX_INT); - fs->f->code[fs->pc] = i; - return fs->pc++; -} - - -const struct OpProperties luaK_opproperties[NUM_OPCODES] = { - {iO, 0, 0}, /* OP_END */ - {iU, 0, 0}, /* OP_RETURN */ - {iAB, 0, 0}, /* OP_CALL */ - {iAB, 0, 0}, /* OP_TAILCALL */ - {iU, VD, 0}, /* OP_PUSHNIL */ - {iU, VD, 0}, /* OP_POP */ - {iS, 1, 0}, /* OP_PUSHINT */ - {iU, 1, 0}, /* OP_PUSHSTRING */ - {iU, 1, 0}, /* OP_PUSHNUM */ - {iU, 1, 0}, /* OP_PUSHNEGNUM */ - {iU, 1, 0}, /* OP_PUSHUPVALUE */ - {iU, 1, 0}, /* OP_GETLOCAL */ - {iU, 1, 0}, /* OP_GETGLOBAL */ - {iO, 1, 2}, /* OP_GETTABLE */ - {iU, 1, 1}, /* OP_GETDOTTED */ - {iU, 1, 1}, /* OP_GETINDEXED */ - {iU, 2, 1}, /* OP_PUSHSELF */ - {iU, 1, 0}, /* OP_CREATETABLE */ - {iU, 0, 1}, /* OP_SETLOCAL */ - {iU, 0, 1}, /* OP_SETGLOBAL */ - {iAB, VD, 0}, /* OP_SETTABLE */ - {iAB, VD, 0}, /* OP_SETLIST */ - {iU, VD, 0}, /* OP_SETMAP */ - {iO, 1, 2}, /* OP_ADD */ - {iS, 1, 1}, /* OP_ADDI */ - {iO, 1, 2}, /* OP_SUB */ - {iO, 1, 2}, /* OP_MULT */ - {iO, 1, 2}, /* OP_DIV */ - {iO, 1, 2}, /* OP_POW */ - {iU, VD, 0}, /* OP_CONCAT */ - {iO, 1, 1}, /* OP_MINUS */ - {iO, 1, 1}, /* OP_NOT */ - {iS, 0, 2}, /* OP_JMPNE */ - {iS, 0, 2}, /* OP_JMPEQ */ - {iS, 0, 2}, /* OP_JMPLT */ - {iS, 0, 2}, /* OP_JMPLE */ - {iS, 0, 2}, /* OP_JMPGT */ - {iS, 0, 2}, /* OP_JMPGE */ - {iS, 0, 1}, /* OP_JMPT */ - {iS, 0, 1}, /* OP_JMPF */ - {iS, 0, 1}, /* OP_JMPONT */ - {iS, 0, 1}, /* OP_JMPONF */ - {iS, 0, 0}, /* OP_JMP */ - {iO, 0, 0}, /* OP_PUSHNILJMP */ - {iS, 0, 0}, /* OP_FORPREP */ - {iS, 0, 3}, /* OP_FORLOOP */ - {iS, 2, 0}, /* OP_LFORPREP */ - {iS, 0, 3}, /* OP_LFORLOOP */ - {iAB, VD, 0} /* OP_CLOSURE */ -}; - diff --git a/src/lua/lcode.h b/src/lua/lcode.h deleted file mode 100644 index c413c897..00000000 --- a/src/lua/lcode.h +++ /dev/null @@ -1,70 +0,0 @@ -/* -** $Id: lcode.h,v 1.2 2001/11/26 23:00:23 darkgod Exp $ -** Code generator for Lua -** See Copyright Notice in lua.h -*/ - -#ifndef lcode_h -#define lcode_h - -#include "llex.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" - - -/* -** Marks the end of a patch list. It is an invalid value both as an absolute -** address, and as a list link (would link an element to itself). -*/ -#define NO_JUMP (-1) - - -/* -** grep "ORDER OPR" if you change these enums -*/ -typedef enum BinOpr { - OPR_ADD, OPR_SUB, OPR_MULT, OPR_DIV, OPR_POW, - OPR_CONCAT, - OPR_NE, OPR_EQ, OPR_LT, OPR_LE, OPR_GT, OPR_GE, - OPR_AND, OPR_OR, - OPR_NOBINOPR -} BinOpr; - -typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_NOUNOPR } UnOpr; - - -enum Mode {iO, iU, iS, iAB}; /* instruction format */ - -#define VD 100 /* flag for variable delta */ - -extern const struct OpProperties { - char mode; - unsigned char push; - unsigned char pop; -} luaK_opproperties[NUM_OPCODES]; - - -void luaK_error (LexState *ls, const char *msg); -int luaK_code0 (FuncState *fs, OpCode o); -int luaK_code1 (FuncState *fs, OpCode o, int arg1); -int luaK_code2 (FuncState *fs, OpCode o, int arg1, int arg2); -int luaK_jump (FuncState *fs); -void luaK_patchlist (FuncState *fs, int list, int target); -void luaK_concat (FuncState *fs, int *l1, int l2); -void luaK_goiftrue (FuncState *fs, expdesc *v, int keepvalue); -int luaK_getlabel (FuncState *fs); -void luaK_deltastack (FuncState *fs, int delta); -void luaK_kstr (LexState *ls, int c); -void luaK_number (FuncState *fs, Number f); -void luaK_adjuststack (FuncState *fs, int n); -int luaK_lastisopen (FuncState *fs); -void luaK_setcallreturns (FuncState *fs, int nresults); -void luaK_tostack (LexState *ls, expdesc *v, int onlyone); -void luaK_storevar (LexState *ls, const expdesc *var); -void luaK_prefix (LexState *ls, UnOpr op, expdesc *v); -void luaK_infix (LexState *ls, BinOpr op, expdesc *v); -void luaK_posfix (LexState *ls, BinOpr op, expdesc *v1, expdesc *v2); - - -#endif diff --git a/src/lua/ldblib.c b/src/lua/ldblib.c deleted file mode 100644 index 481f1d6f..00000000 --- a/src/lua/ldblib.c +++ /dev/null @@ -1,188 +0,0 @@ -/* -** $Id: ldblib.c,v 1.2 2001/11/26 23:00:23 darkgod Exp $ -** Interface from Lua to its debug API -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "luadebug.h" -#include "lualib.h" - - - -static void settabss (lua_State *L, const char *i, const char *v) { - lua_pushstring(L, i); - lua_pushstring(L, v); - lua_settable(L, -3); -} - - -static void settabsi (lua_State *L, const char *i, int v) { - lua_pushstring(L, i); - lua_pushnumber(L, v); - lua_settable(L, -3); -} - - -static int getinfo (lua_State *L) { - lua_Debug ar; - const char *options = luaL_opt_string(L, 2, "flnSu"); - char buff[20]; - if (lua_isnumber(L, 1)) { - if (!lua_getstack(L, (int)lua_tonumber(L, 1), &ar)) { - lua_pushnil(L); /* level out of range */ - return 1; - } - } - else if (lua_isfunction(L, 1)) { - lua_pushvalue(L, 1); - sprintf(buff, ">%.10s", options); - options = buff; - } - else - luaL_argerror(L, 1, "function or level expected"); - if (!lua_getinfo(L, options, &ar)) - luaL_argerror(L, 2, "invalid option"); - lua_newtable(L); - for (; *options; options++) { - switch (*options) { - case 'S': - settabss(L, "source", ar.source); - if (ar.source) - settabss(L, "short_src", ar.short_src); - settabsi(L, "linedefined", ar.linedefined); - settabss(L, "what", ar.what); - break; - case 'l': - settabsi(L, "currentline", ar.currentline); - break; - case 'u': - settabsi(L, "nups", ar.nups); - break; - case 'n': - settabss(L, "name", ar.name); - settabss(L, "namewhat", ar.namewhat); - break; - case 'f': - lua_pushstring(L, "func"); - lua_pushvalue(L, -3); - lua_settable(L, -3); - break; - } - } - return 1; /* return table */ -} - - -static int getlocal (lua_State *L) { - lua_Debug ar; - const char *name; - if (!lua_getstack(L, luaL_check_int(L, 1), &ar)) /* level out of range? */ - luaL_argerror(L, 1, "level out of range"); - name = lua_getlocal(L, &ar, luaL_check_int(L, 2)); - if (name) { - lua_pushstring(L, name); - lua_pushvalue(L, -2); - return 2; - } - else { - lua_pushnil(L); - return 1; - } -} - - -static int setlocal (lua_State *L) { - lua_Debug ar; - if (!lua_getstack(L, luaL_check_int(L, 1), &ar)) /* level out of range? */ - luaL_argerror(L, 1, "level out of range"); - luaL_checkany(L, 3); - lua_pushstring(L, lua_setlocal(L, &ar, luaL_check_int(L, 2))); - return 1; -} - - - -/* dummy variables (to define unique addresses) */ -static char key1, key2; -#define KEY_CALLHOOK (&key1) -#define KEY_LINEHOOK (&key2) - - -static void hookf (lua_State *L, void *key) { - lua_getregistry(L); - lua_pushuserdata(L, key); - lua_gettable(L, -2); - if (lua_isfunction(L, -1)) { - lua_pushvalue(L, 1); - lua_rawcall(L, 1, 0); - } - else - lua_pop(L, 1); /* pop result from gettable */ - lua_pop(L, 1); /* pop table */ -} - - -static void callf (lua_State *L, lua_Debug *ar) { - lua_pushstring(L, ar->event); - hookf(L, KEY_CALLHOOK); -} - - -static void linef (lua_State *L, lua_Debug *ar) { - lua_pushnumber(L, ar->currentline); - hookf(L, KEY_LINEHOOK); -} - - -static void sethook (lua_State *L, void *key, lua_Hook hook, - lua_Hook (*sethookf)(lua_State * L, lua_Hook h)) { - lua_settop(L, 1); - if (lua_isnil(L, 1)) - (*sethookf)(L, NULL); - else if (lua_isfunction(L, 1)) - (*sethookf)(L, hook); - else - luaL_argerror(L, 1, "function expected"); - lua_getregistry(L); - lua_pushuserdata(L, key); - lua_pushvalue(L, -1); /* dup key */ - lua_gettable(L, -3); /* get old value */ - lua_pushvalue(L, -2); /* key (again) */ - lua_pushvalue(L, 1); - lua_settable(L, -5); /* set new value */ -} - - -static int setcallhook (lua_State *L) { - sethook(L, KEY_CALLHOOK, callf, lua_setcallhook); - return 1; -} - - -static int setlinehook (lua_State *L) { - sethook(L, KEY_LINEHOOK, linef, lua_setlinehook); - return 1; -} - - -static const struct luaL_reg dblib[] = { - {"getlocal", getlocal}, - {"getinfo", getinfo}, - {"setcallhook", setcallhook}, - {"setlinehook", setlinehook}, - {"setlocal", setlocal} -}; - - -LUALIB_API void lua_dblibopen (lua_State *L) { - luaL_openl(L, dblib); -} - diff --git a/src/lua/ldebug.c b/src/lua/ldebug.c deleted file mode 100644 index 02481b4c..00000000 --- a/src/lua/ldebug.c +++ /dev/null @@ -1,466 +0,0 @@ -/* -** $Id: ldebug.c,v 1.2 2001/11/26 23:00:23 darkgod Exp $ -** Debug Interface -** See Copyright Notice in lua.h -*/ - - -#include - -#include "lua.h" - -#include "lapi.h" -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "luadebug.h" - - - -static const char *getfuncname (lua_State *L, StkId f, const char **name); - - -static void setnormalized (TObject *d, const TObject *s) { - if (ttype(s) == LUA_TMARK) { - clvalue(d) = infovalue(s)->func; - ttype(d) = LUA_TFUNCTION; - } - else *d = *s; -} - - -static int isLmark (StkId o) { - return (o && ttype(o) == LUA_TMARK && !infovalue(o)->func->isC); -} - - -LUA_API lua_Hook lua_setcallhook (lua_State *L, lua_Hook func) { - lua_Hook oldhook = L->callhook; - L->callhook = func; - return oldhook; -} - - -LUA_API lua_Hook lua_setlinehook (lua_State *L, lua_Hook func) { - lua_Hook oldhook = L->linehook; - L->linehook = func; - return oldhook; -} - - -static StkId aux_stackedfunction (lua_State *L, int level, StkId top) { - int i; - for (i = (top-1) - L->stack; i>=0; i--) { - if (is_T_MARK(L->stack[i].ttype)) { - if (level == 0) - return L->stack+i; - level--; - } - } - return NULL; -} - - -LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { - StkId f = aux_stackedfunction(L, level, L->top); - if (f == NULL) return 0; /* there is no such level */ - else { - ar->_func = f; - return 1; - } -} - - -static int nups (StkId f) { - switch (ttype(f)) { - case LUA_TFUNCTION: - return clvalue(f)->nupvalues; - case LUA_TMARK: - return infovalue(f)->func->nupvalues; - default: - return 0; - } -} - - -int luaG_getline (int *lineinfo, int pc, int refline, int *prefi) { - int refi; - if (lineinfo == NULL || pc == -1) - return -1; /* no line info or function is not active */ - refi = prefi ? *prefi : 0; - if (lineinfo[refi] < 0) - refline += -lineinfo[refi++]; - LUA_ASSERT(lineinfo[refi] >= 0, "invalid line info"); - while (lineinfo[refi] > pc) { - refline--; - refi--; - if (lineinfo[refi] < 0) - refline -= -lineinfo[refi--]; - LUA_ASSERT(lineinfo[refi] >= 0, "invalid line info"); - } - for (;;) { - int nextline = refline + 1; - int nextref = refi + 1; - if (lineinfo[nextref] < 0) - nextline += -lineinfo[nextref++]; - LUA_ASSERT(lineinfo[nextref] >= 0, "invalid line info"); - if (lineinfo[nextref] > pc) - break; - refline = nextline; - refi = nextref; - } - if (prefi) *prefi = refi; - return refline; -} - - -static int currentpc (StkId f) { - CallInfo *ci = infovalue(f); - LUA_ASSERT(isLmark(f), "function has no pc"); - if (ci->pc) - return (*ci->pc - ci->func->f.l->code) - 1; - else - return -1; /* function is not active */ -} - - -static int currentline (StkId f) { - if (!isLmark(f)) - return -1; /* only active lua functions have current-line information */ - else { - CallInfo *ci = infovalue(f); - int *lineinfo = ci->func->f.l->lineinfo; - return luaG_getline(lineinfo, currentpc(f), 1, NULL); - } -} - - - -static Proto *getluaproto (StkId f) { - return (isLmark(f) ? infovalue(f)->func->f.l : NULL); -} - - -LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { - const char *name; - StkId f = ar->_func; - Proto *fp = getluaproto(f); - if (!fp) return NULL; /* `f' is not a Lua function? */ - name = luaF_getlocalname(fp, n, currentpc(f)); - if (!name) return NULL; - luaA_pushobject(L, (f+1)+(n-1)); /* push value */ - return name; -} - - -LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { - const char *name; - StkId f = ar->_func; - Proto *fp = getluaproto(f); - L->top--; /* pop new value */ - if (!fp) return NULL; /* `f' is not a Lua function? */ - name = luaF_getlocalname(fp, n, currentpc(f)); - if (!name || name[0] == '(') return NULL; /* `(' starts private locals */ - *((f+1)+(n-1)) = *L->top; - return name; -} - - -static void infoLproto (lua_Debug *ar, Proto *f) { - ar->source = f->source->str; - ar->linedefined = f->lineDefined; - ar->what = "Lua"; -} - - -static void funcinfo (lua_State *L, lua_Debug *ar, StkId func) { - Closure *cl = NULL; - switch (ttype(func)) { - case LUA_TFUNCTION: - cl = clvalue(func); - break; - case LUA_TMARK: - cl = infovalue(func)->func; - break; - default: - lua_error(L, "value for `lua_getinfo' is not a function"); - } - if (cl->isC) { - ar->source = "=C"; - ar->linedefined = -1; - ar->what = "C"; - } - else - infoLproto(ar, cl->f.l); - luaO_chunkid(ar->short_src, ar->source, sizeof(ar->short_src)); - if (ar->linedefined == 0) - ar->what = "main"; -} - - -static const char *travtagmethods (lua_State *L, const TObject *o) { - if (ttype(o) == LUA_TFUNCTION) { - int e; - for (e=0; elast_tag; t++) - if (clvalue(o) == luaT_gettm(L, t, e)) - return luaT_eventname[e]; - } - } - return NULL; -} - - -static const char *travglobals (lua_State *L, const TObject *o) { - Hash *g = L->gt; - int i; - for (i=0; isize; i++) { - if (luaO_equalObj(o, val(node(g, i))) && - ttype(key(node(g, i))) == LUA_TSTRING) - return tsvalue(key(node(g, i)))->str; - } - return NULL; -} - - -static void getname (lua_State *L, StkId f, lua_Debug *ar) { - TObject o; - setnormalized(&o, f); - /* try to find a name for given function */ - if ((ar->name = travglobals(L, &o)) != NULL) - ar->namewhat = "global"; - /* not found: try tag methods */ - else if ((ar->name = travtagmethods(L, &o)) != NULL) - ar->namewhat = "tag-method"; - else ar->namewhat = ""; /* not found at all */ -} - - -LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { - StkId func; - int isactive = (*what != '>'); - if (isactive) - func = ar->_func; - else { - what++; /* skip the '>' */ - func = L->top - 1; - } - for (; *what; what++) { - switch (*what) { - case 'S': { - funcinfo(L, ar, func); - break; - } - case 'l': { - ar->currentline = currentline(func); - break; - } - case 'u': { - ar->nups = nups(func); - break; - } - case 'n': { - ar->namewhat = (isactive) ? getfuncname(L, func, &ar->name) : NULL; - if (ar->namewhat == NULL) - getname(L, func, ar); - break; - } - case 'f': { - setnormalized(L->top, func); - incr_top; /* push function */ - break; - } - default: return 0; /* invalid option */ - } - } - if (!isactive) L->top--; /* pop function */ - return 1; -} - - -/* -** {====================================================== -** Symbolic Execution -** ======================================================= -*/ - - -static int pushpc (int *stack, int pc, int top, int n) { - while (n--) - stack[top++] = pc-1; - return top; -} - - -static Instruction luaG_symbexec (const Proto *pt, int lastpc, int stackpos) { - int stack[MAXSTACK]; /* stores last instruction that changed a stack entry */ - const Instruction *code = pt->code; - int top = pt->numparams; - int pc = 0; - if (pt->is_vararg) /* varargs? */ - top++; /* `arg' */ - while (pc < lastpc) { - const Instruction i = code[pc++]; - LUA_ASSERT(0 <= top && top <= pt->maxstacksize, "wrong stack"); - switch (GET_OPCODE(i)) { - case OP_RETURN: { - LUA_ASSERT(top >= GETARG_U(i), "wrong stack"); - top = GETARG_U(i); - break; - } - case OP_TAILCALL: { - LUA_ASSERT(top >= GETARG_A(i), "wrong stack"); - top = GETARG_B(i); - break; - } - case OP_CALL: { - int nresults = GETARG_B(i); - if (nresults == MULT_RET) nresults = 1; - LUA_ASSERT(top >= GETARG_A(i), "wrong stack"); - top = pushpc(stack, pc, GETARG_A(i), nresults); - break; - } - case OP_PUSHNIL: { - top = pushpc(stack, pc, top, GETARG_U(i)); - break; - } - case OP_POP: { - top -= GETARG_U(i); - break; - } - case OP_SETTABLE: - case OP_SETLIST: { - top -= GETARG_B(i); - break; - } - case OP_SETMAP: { - top -= 2*GETARG_U(i); - break; - } - case OP_CONCAT: { - top -= GETARG_U(i); - stack[top++] = pc-1; - break; - } - case OP_CLOSURE: { - top -= GETARG_B(i); - stack[top++] = pc-1; - break; - } - case OP_JMPONT: - case OP_JMPONF: { - int newpc = pc + GETARG_S(i); - /* jump is forward and do not skip `lastpc'? */ - if (pc < newpc && newpc <= lastpc) { - stack[top-1] = pc-1; /* value comes from `and'/`or' */ - pc = newpc; /* do the jump */ - } - else - top--; /* do not jump; pop value */ - break; - } - default: { - OpCode op = GET_OPCODE(i); - LUA_ASSERT(luaK_opproperties[op].push != VD, - "invalid opcode for default"); - top -= luaK_opproperties[op].pop; - LUA_ASSERT(top >= 0, "wrong stack"); - top = pushpc(stack, pc, top, luaK_opproperties[op].push); - } - } - } - return code[stack[stackpos]]; -} - - -static const char *getobjname (lua_State *L, StkId obj, const char **name) { - StkId func = aux_stackedfunction(L, 0, obj); - if (!isLmark(func)) - return NULL; /* not an active Lua function */ - else { - Proto *p = infovalue(func)->func->f.l; - int pc = currentpc(func); - int stackpos = obj - (func+1); /* func+1 == function base */ - Instruction i = luaG_symbexec(p, pc, stackpos); - LUA_ASSERT(pc != -1, "function must be active"); - switch (GET_OPCODE(i)) { - case OP_GETGLOBAL: { - *name = p->kstr[GETARG_U(i)]->str; - return "global"; - } - case OP_GETLOCAL: { - *name = luaF_getlocalname(p, GETARG_U(i)+1, pc); - LUA_ASSERT(*name, "local must exist"); - return "local"; - } - case OP_PUSHSELF: - case OP_GETDOTTED: { - *name = p->kstr[GETARG_U(i)]->str; - return "field"; - } - default: - return NULL; /* no useful name found */ - } - } -} - - -static const char *getfuncname (lua_State *L, StkId f, const char **name) { - StkId func = aux_stackedfunction(L, 0, f); /* calling function */ - if (!isLmark(func)) - return NULL; /* not an active Lua function */ - else { - Proto *p = infovalue(func)->func->f.l; - int pc = currentpc(func); - Instruction i; - if (pc == -1) return NULL; /* function is not activated */ - i = p->code[pc]; - switch (GET_OPCODE(i)) { - case OP_CALL: case OP_TAILCALL: - return getobjname(L, (func+1)+GETARG_A(i), name); - default: - return NULL; /* no useful name found */ - } - } -} - - -/* }====================================================== */ - - -void luaG_typeerror (lua_State *L, StkId o, const char *op) { - const char *name; - const char *kind = getobjname(L, o, &name); - const char *t = luaO_typename(o); - if (kind) - luaO_verror(L, "attempt to %.30s %.20s `%.40s' (a %.10s value)", - op, kind, name, t); - else - luaO_verror(L, "attempt to %.30s a %.10s value", op, t); -} - - -void luaG_binerror (lua_State *L, StkId p1, int t, const char *op) { - if (ttype(p1) == t) p1++; - LUA_ASSERT(ttype(p1) != t, "must be an error"); - luaG_typeerror(L, p1, op); -} - - -void luaG_ordererror (lua_State *L, StkId top) { - const char *t1 = luaO_typename(top-2); - const char *t2 = luaO_typename(top-1); - if (t1[2] == t2[2]) - luaO_verror(L, "attempt to compare two %.10s values", t1); - else - luaO_verror(L, "attempt to compare %.10s with %.10s", t1, t2); -} - diff --git a/src/lua/ldebug.h b/src/lua/ldebug.h deleted file mode 100644 index 76865616..00000000 --- a/src/lua/ldebug.h +++ /dev/null @@ -1,21 +0,0 @@ -/* -** $Id: ldebug.h,v 1.2 2001/11/26 23:00:23 darkgod Exp $ -** Auxiliary functions from Debug Interface module -** See Copyright Notice in lua.h -*/ - -#ifndef ldebug_h -#define ldebug_h - - -#include "lstate.h" -#include "luadebug.h" - - -void luaG_typeerror (lua_State *L, StkId o, const char *op); -void luaG_binerror (lua_State *L, StkId p1, int t, const char *op); -int luaG_getline (int *lineinfo, int pc, int refline, int *refi); -void luaG_ordererror (lua_State *L, StkId top); - - -#endif diff --git a/src/lua/ldo.c b/src/lua/ldo.c deleted file mode 100644 index 5f23bfd9..00000000 --- a/src/lua/ldo.c +++ /dev/null @@ -1,385 +0,0 @@ -/* -** $Id: ldo.c,v 1.7 2004/06/04 13:42:10 neil Exp $ -** Stack and Call structure of Lua -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include - -#include "lua.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lundump.h" -#include "lvm.h" -#include "lzio.h" - - -/* space to handle stack overflow errors */ -#define EXTRA_STACK (2*LUA_MINSTACK) - - -void luaD_init (lua_State *L, int stacksize) { - L->stack = luaM_newvector(L, stacksize+EXTRA_STACK, TObject); - L->nblocks += stacksize*sizeof(TObject); - L->stack_last = L->stack+(stacksize-1); - L->stacksize = stacksize; - L->Cbase = L->top = L->stack; -} - - -void luaD_checkstack (lua_State *L, int n) { - if (L->stack_last - L->top <= n) { /* stack overflow? */ - if (L->stack_last-L->stack > (L->stacksize-1)) { - /* overflow while handling overflow */ - luaD_breakrun(L, LUA_ERRERR); /* break run without error message */ - } - else { - L->stack_last += EXTRA_STACK; /* to be used by error message */ - lua_error(L, "stack overflow"); - } - } -} - - -static void restore_stack_limit (lua_State *L) { - if (L->top - L->stack < L->stacksize - 1) - L->stack_last = L->stack + (L->stacksize-1); -} - - -/* -** Adjust stack. Set top to base+extra, pushing NILs if needed. -** (we cannot add base+extra unless we are sure it fits in the stack; -** otherwise the result of such operation on pointers is undefined) -*/ -void luaD_adjusttop (lua_State *L, StkId base, int extra) { - int diff = extra-(L->top-base); - if (diff <= 0) - L->top = base+extra; - else { - luaD_checkstack(L, diff); - while (diff--) - ttype(L->top++) = LUA_TNIL; - } -} - - -/* -** Open a hole inside the stack at `pos' -*/ -static void luaD_openstack (lua_State *L, StkId pos) { - int i = L->top-pos; - while (i--) pos[i+1] = pos[i]; - incr_top; -} - - -static void dohook (lua_State *L, lua_Debug *ar, lua_Hook hook) { - StkId old_Cbase = L->Cbase; - StkId old_top = L->Cbase = L->top; - luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - L->allowhooks = 0; /* cannot call hooks inside a hook */ - (*hook)(L, ar); - LUA_ASSERT(L->allowhooks == 0, "invalid allow"); - L->allowhooks = 1; - L->top = old_top; - L->Cbase = old_Cbase; -} - - -void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook) { - if (L->allowhooks) { - lua_Debug ar; - ar._func = func; - ar.event = "line"; - ar.currentline = line; - dohook(L, &ar, linehook); - } -} - - -static void luaD_callHook (lua_State *L, StkId func, lua_Hook callhook, - const char *event) { - if (L->allowhooks) { - lua_Debug ar; - ar._func = func; - ar.event = event; - infovalue(func)->pc = NULL; /* function is not active */ - dohook(L, &ar, callhook); - } -} - - -static StkId callCclosure (lua_State *L, const struct Closure *cl, StkId base) { - int nup = cl->nupvalues; /* number of upvalues */ - StkId old_Cbase = L->Cbase; - int n; - L->Cbase = base; /* new base for C function */ - luaD_checkstack(L, nup+LUA_MINSTACK); /* ensure minimum stack size */ - for (n=0; ntop++) = cl->upvalue[n]; - n = (*cl->f.c)(L); /* do the actual call */ - L->Cbase = old_Cbase; /* restore old C base */ - return L->top - n; /* return index of first result */ -} - - -void luaD_callTM (lua_State *L, Closure *f, int nParams, int nResults) { - StkId base = L->top - nParams; - luaD_openstack(L, base); - clvalue(base) = f; - ttype(base) = LUA_TFUNCTION; - luaD_call(L, base, nResults); -} - - -/* -** Call a function (C or Lua). The function to be called is at *func. -** The arguments are on the stack, right after the function. -** When returns, the results are on the stack, starting at the original -** function position. -** The number of results is nResults, unless nResults=LUA_MULTRET. -*/ -void luaD_call (lua_State *L, StkId func, int nResults) { - lua_Hook callhook; - StkId firstResult; - CallInfo ci; - Closure *cl; - if (ttype(func) != LUA_TFUNCTION) { - /* `func' is not a function; check the `function' tag method */ - Closure *tm = luaT_gettmbyObj(L, func, TM_FUNCTION); - if (tm == NULL) - luaG_typeerror(L, func, "call"); - luaD_openstack(L, func); - clvalue(func) = tm; /* tag method is the new function to be called */ - ttype(func) = LUA_TFUNCTION; - } - cl = clvalue(func); - ci.func = cl; - infovalue(func) = &ci; - ttype(func) = LUA_TMARK; - callhook = L->callhook; - if (callhook) - luaD_callHook(L, func, callhook, "call"); - firstResult = (cl->isC ? callCclosure(L, cl, func+1) : - luaV_execute(L, cl, func+1)); - if (callhook) /* same hook that was active at entry */ - luaD_callHook(L, func, callhook, "return"); - LUA_ASSERT(ttype(func) == LUA_TMARK, "invalid tag"); - /* move results to `func' (to erase parameters and function) */ - if (nResults == LUA_MULTRET) { - while (firstResult < L->top) /* copy all results */ - *func++ = *firstResult++; - L->top = func; - } - else { /* copy at most `nResults' */ - for (; nResults > 0 && firstResult < L->top; nResults--) - *func++ = *firstResult++; - L->top = func; - for (; nResults > 0; nResults--) { /* if there are not enough results */ - ttype(L->top) = LUA_TNIL; /* adjust the stack */ - incr_top; /* must check stack space */ - } - } - luaC_checkGC(L); -} - - -/* -** Execute a protected call. -*/ -struct CallS { /* data to `f_call' */ - StkId func; - int nresults; -}; - -static void f_call (lua_State *L, void *ud) { - struct CallS *c = (struct CallS *)ud; - luaD_call(L, c->func, c->nresults); -} - - -LUA_API int lua_call (lua_State *L, int nargs, int nresults) { - StkId func = L->top - (nargs+1); /* function to be called */ - struct CallS c; - int status; - c.func = func; c.nresults = nresults; - status = luaD_runprotected(L, f_call, &c); - if (status != 0) /* an error occurred? */ - L->top = func; /* remove parameters from the stack */ - return status; -} - - -/* -** Execute a protected parser. -*/ -struct ParserS { /* data to `f_parser' */ - ZIO *z; - int bin; -}; - -static void f_parser (lua_State *L, void *ud) { - struct ParserS *p = (struct ParserS *)ud; - Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z); - luaV_Lclosure(L, tf, 0); -} - - -static int protectedparser (lua_State *L, ZIO *z, int bin) { - struct ParserS p; - unsigned long old_blocks; - int status; - p.z = z; p.bin = bin; - luaC_checkGC(L); - old_blocks = L->nblocks; - status = luaD_runprotected(L, f_parser, &p); - if (status == 0) { - /* add new memory to threshold (as it probably will stay) */ - L->GCthreshold += (L->nblocks - old_blocks); - } - else if (status == LUA_ERRRUN) /* an error occurred: correct error code */ - status = LUA_ERRSYNTAX; - return status; -} - - -static int parse_file (lua_State *L, const char *filename) { - ZIO z; - int status; - int bin; /* flag for file mode */ - int c; /* look ahead char */ - FILE *f = (filename == NULL) ? stdin : fopen(filename, "r"); - if (f == NULL) return LUA_ERRFILE; /* unable to open file */ - c = fgetc(f); - ungetc(c, f); - bin = (c == ID_CHUNK); - if (bin && f != stdin) { - f = freopen(filename, "rb", f); /* set binary mode */ - if (f == NULL) return LUA_ERRFILE; /* unable to reopen file */ - } - lua_pushstring(L, "@"); - lua_pushstring(L, (filename == NULL) ? "(stdin)" : filename); - lua_concat(L, 2); - filename = lua_tostring(L, -1); /* filename = '@'..filename */ - lua_pop(L, 1); /* OK: there is no GC during parser */ - luaZ_Fopen(&z, f, filename); - status = protectedparser(L, &z, bin); - if (f != stdin) - fclose(f); - return status; -} - - -LUA_API int lua_dofile (lua_State *L, const char *filename) { - int status = parse_file(L, filename); - if (status == 0) /* parse OK? */ - status = lua_call(L, 0, LUA_MULTRET); /* call main */ - return status; -} - - -static int parse_buffer (lua_State *L, const char *buff, size_t size, - const char *name) { - ZIO z; - if (!name) name = "?"; - luaZ_mopen(&z, buff, size, name); - return protectedparser(L, &z, buff[0]==ID_CHUNK); -} - - -LUA_API int lua_dobuffer (lua_State *L, const char *buff, size_t size, const char *name) { - int status = parse_buffer(L, buff, size, name); - if (status == 0) /* parse OK? */ - status = lua_call(L, 0, LUA_MULTRET); /* call main */ - return status; -} - - -LUA_API int lua_dostring (lua_State *L, const char *str) { - return lua_dobuffer(L, str, strlen(str), str); -} - - -/* -** {====================================================== -** Error-recover functions (based on long jumps) -** ======================================================= -*/ - -/* chain list of long jump buffers */ -struct lua_longjmp { - jmp_buf b; - struct lua_longjmp *previous; - volatile int status; /* error code */ -}; - - -static void message (lua_State *L, const char *s) { - const TObject *em = luaH_getglobal(L, LUA_ERRORMESSAGE); - if (ttype(em) == LUA_TFUNCTION) { - *L->top = *em; - incr_top; - lua_pushstring(L, s); - luaD_call(L, L->top-2, 0); - } -} - - -/* -** Reports an error, and jumps up to the available recovery label -*/ -LUA_API void lua_error (lua_State *L, const char *s) { - if (s) message(L, s); - luaD_breakrun(L, LUA_ERRRUN); -} - - -void luaD_breakrun (lua_State *L, int errcode) { - if (L->errorJmp) { - L->errorJmp->status = errcode; - longjmp(L->errorJmp->b, 1); - } - else { - if (errcode != LUA_ERRMEM) - message(L, "unable to recover; exiting\n"); - exit(EXIT_FAILURE); - } -} - - -int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud) { - StkId oldCbase = L->Cbase; - StkId oldtop = L->top; - struct lua_longjmp lj; - int allowhooks = L->allowhooks; - lj.status = 0; - lj.previous = L->errorJmp; /* chain new error handler */ - L->errorJmp = &lj; - if (setjmp(lj.b) == 0) - (*f)(L, ud); - else { /* an error occurred: restore the state */ - L->allowhooks = allowhooks; - L->Cbase = oldCbase; - L->top = oldtop; - restore_stack_limit(L); - } - L->errorJmp = lj.previous; /* restore old error handler */ - return lj.status; -} - -/* }====================================================== */ - diff --git a/src/lua/ldo.h b/src/lua/ldo.h deleted file mode 100644 index d948ad35..00000000 --- a/src/lua/ldo.h +++ /dev/null @@ -1,33 +0,0 @@ -/* -** $Id: ldo.h,v 1.3 2001/11/26 23:00:23 darkgod Exp $ -** Stack and Call structure of Lua -** See Copyright Notice in lua.h -*/ - -#ifndef ldo_h -#define ldo_h - - -#include "lobject.h" -#include "lstate.h" - - -/* -** macro to increment stack top. -** There must be always an empty slot at the L->stack.top -*/ -#define incr_top {if (L->top == L->stack_last) luaD_checkstack(L, 1); L->top++;} - - -void luaD_init (lua_State *L, int stacksize); -void luaD_adjusttop (lua_State *L, StkId base, int extra); -void luaD_lineHook (lua_State *L, StkId func, int line, lua_Hook linehook); -void luaD_call (lua_State *L, StkId func, int nResults); -void luaD_callTM (lua_State *L, Closure *f, int nParams, int nResults); -void luaD_checkstack (lua_State *L, int n); - -void luaD_breakrun (lua_State *L, int errcode); -int luaD_runprotected (lua_State *L, void (*f)(lua_State *, void *), void *ud); - - -#endif diff --git a/src/lua/lfunc.c b/src/lua/lfunc.c deleted file mode 100644 index d3427653..00000000 --- a/src/lua/lfunc.c +++ /dev/null @@ -1,109 +0,0 @@ -/* -** $Id: lfunc.c,v 1.3 2001/11/26 23:00:23 darkgod Exp $ -** Auxiliary functions to manipulate prototypes and closures -** See Copyright Notice in lua.h -*/ - - -#include - -#include "lua.h" - -#include "lfunc.h" -#include "lmem.h" -#include "lstate.h" - - -#define sizeclosure(n) ((int)sizeof(Closure) + (int)sizeof(TObject)*((n)-1)) - - -Closure *luaF_newclosure (lua_State *L, int nelems) { - int size = sizeclosure(nelems); - Closure *c = (Closure *)luaM_malloc(L, size); - c->next = L->rootcl; - L->rootcl = c; - c->mark = c; - c->nupvalues = nelems; - L->nblocks += size; - return c; -} - - -Proto *luaF_newproto (lua_State *L) { - Proto *f = luaM_new(L, Proto); - f->knum = NULL; - f->nknum = 0; - f->kstr = NULL; - f->nkstr = 0; - f->kproto = NULL; - f->nkproto = 0; - f->code = NULL; - f->ncode = 0; - f->numparams = 0; - f->is_vararg = 0; - f->maxstacksize = 0; - f->marked = 0; - f->lineinfo = NULL; - f->nlineinfo = 0; - f->nlocvars = 0; - f->locvars = NULL; - f->lineDefined = 0; - f->source = NULL; - f->next = L->rootproto; /* chain in list of protos */ - L->rootproto = f; - return f; -} - - -static size_t protosize (Proto *f) { - return sizeof(Proto) - + f->nknum*sizeof(Number) - + f->nkstr*sizeof(TString *) - + f->nkproto*sizeof(Proto *) - + f->ncode*sizeof(Instruction) - + f->nlocvars*sizeof(struct LocVar) - + f->nlineinfo*sizeof(int); -} - - -void luaF_protook (lua_State *L, Proto *f, int pc) { - f->ncode = pc; /* signal that proto was properly created */ - L->nblocks += protosize(f); -} - - -void luaF_freeproto (lua_State *L, Proto *f) { - if (f->ncode > 0) /* function was properly created? */ - L->nblocks -= protosize(f); - luaM_free(L, f->code); - luaM_free(L, f->locvars); - luaM_free(L, f->kstr); - luaM_free(L, f->knum); - luaM_free(L, f->kproto); - luaM_free(L, f->lineinfo); - luaM_free(L, f); -} - - -void luaF_freeclosure (lua_State *L, Closure *c) { - L->nblocks -= sizeclosure(c->nupvalues); - luaM_free(L, c); -} - - -/* -** Look for n-th local variable at line `line' in function `func'. -** Returns NULL if not found. -*/ -const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { - int i; - for (i = 0; inlocvars && f->locvars[i].startpc <= pc; i++) { - if (pc < f->locvars[i].endpc) { /* is variable active? */ - local_number--; - if (local_number == 0) - return f->locvars[i].varname->str; - } - } - return NULL; /* not found */ -} - diff --git a/src/lua/lfunc.h b/src/lua/lfunc.h deleted file mode 100644 index 1bd9722d..00000000 --- a/src/lua/lfunc.h +++ /dev/null @@ -1,24 +0,0 @@ -/* -** $Id: lfunc.h,v 1.3 2001/11/26 23:00:23 darkgod Exp $ -** Auxiliary functions to manipulate prototypes and closures -** See Copyright Notice in lua.h -*/ - -#ifndef lfunc_h -#define lfunc_h - - -#include "lobject.h" - - - -Proto *luaF_newproto (lua_State *L); -void luaF_protook (lua_State *L, Proto *f, int pc); -Closure *luaF_newclosure (lua_State *L, int nelems); -void luaF_freeproto (lua_State *L, Proto *f); -void luaF_freeclosure (lua_State *L, Closure *c); - -const char *luaF_getlocalname (const Proto *func, int local_number, int pc); - - -#endif diff --git a/src/lua/lgc.c b/src/lua/lgc.c deleted file mode 100644 index 4e8b234d..00000000 --- a/src/lua/lgc.c +++ /dev/null @@ -1,353 +0,0 @@ -/* -** $Id: lgc.c,v 1.3 2001/11/26 23:00:24 darkgod Exp $ -** Garbage Collector -** See Copyright Notice in lua.h -*/ - -#include "lua.h" - -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" - - -typedef struct GCState { - Hash *tmark; /* list of marked tables to be visited */ - Closure *cmark; /* list of marked closures to be visited */ -} GCState; - - - -static void markobject (GCState *st, TObject *o); - - -/* mark a string; marks larger than 1 cannot be changed */ -#define strmark(s) {if ((s)->marked == 0) (s)->marked = 1;} - - - -static void protomark (Proto *f) { - if (!f->marked) { - int i; - f->marked = 1; - strmark(f->source); - for (i=0; inkstr; i++) - strmark(f->kstr[i]); - for (i=0; inkproto; i++) - protomark(f->kproto[i]); - for (i=0; inlocvars; i++) /* mark local-variable names */ - strmark(f->locvars[i].varname); - } -} - - -static void markstack (lua_State *L, GCState *st) { - StkId o; - for (o=L->stack; otop; o++) - markobject(st, o); -} - - -static void marklock (lua_State *L, GCState *st) { - int i; - for (i=0; irefSize; i++) { - if (L->refArray[i].st == LOCK) - markobject(st, &L->refArray[i].o); - } -} - - -static void markclosure (GCState *st, Closure *cl) { - if (!ismarked(cl)) { - if (!cl->isC) - protomark(cl->f.l); - cl->mark = st->cmark; /* chain it for later traversal */ - st->cmark = cl; - } -} - - -static void marktagmethods (lua_State *L, GCState *st) { - int e; - for (e=0; elast_tag; t++) { - Closure *cl = luaT_gettm(L, t, e); - if (cl) markclosure(st, cl); - } - } -} - - -static void markobject (GCState *st, TObject *o) { - switch (ttype(o)) { - case LUA_TUSERDATA: case LUA_TSTRING: - strmark(tsvalue(o)); - break; - case LUA_TMARK: - markclosure(st, infovalue(o)->func); - break; - case LUA_TFUNCTION: - markclosure(st, clvalue(o)); - break; - case LUA_TTABLE: { - if (!ismarked(hvalue(o))) { - hvalue(o)->mark = st->tmark; /* chain it in list of marked */ - st->tmark = hvalue(o); - } - break; - } - default: break; /* numbers, etc */ - } -} - - -static void markall (lua_State *L) { - GCState st; - st.cmark = NULL; - st.tmark = L->gt; /* put table of globals in mark list */ - L->gt->mark = NULL; - marktagmethods(L, &st); /* mark tag methods */ - markstack(L, &st); /* mark stack objects */ - marklock(L, &st); /* mark locked objects */ - for (;;) { /* mark tables and closures */ - if (st.cmark) { - int i; - Closure *f = st.cmark; /* get first closure from list */ - st.cmark = f->mark; /* remove it from list */ - for (i=0; inupvalues; i++) /* mark its upvalues */ - markobject(&st, &f->upvalue[i]); - } - else if (st.tmark) { - int i; - Hash *h = st.tmark; /* get first table from list */ - st.tmark = h->mark; /* remove it from list */ - for (i=0; isize; i++) { - Node *n = node(h, i); - if (ttype(key(n)) != LUA_TNIL) { - if (ttype(val(n)) == LUA_TNIL) - luaH_remove(h, key(n)); /* dead element; try to remove it */ - markobject(&st, &n->key); - markobject(&st, &n->val); - } - } - } - else break; /* nothing else to mark */ - } -} - - -static int hasmark (const TObject *o) { - /* valid only for locked objects */ - switch (o->ttype) { - case LUA_TSTRING: case LUA_TUSERDATA: - return tsvalue(o)->marked; - case LUA_TTABLE: - return ismarked(hvalue(o)); - case LUA_TFUNCTION: - return ismarked(clvalue(o)); - default: /* number */ - return 1; - } -} - - -/* macro for internal debugging; check if a link of free refs is valid */ -#define VALIDLINK(L, st,n) (NONEXT <= (st) && (st) < (n)) - -static void invalidaterefs (lua_State *L) { - int n = L->refSize; - int i; - for (i=0; irefArray[i]; - if (r->st == HOLD && !hasmark(&r->o)) - r->st = COLLECTED; - LUA_ASSERT((r->st == LOCK && hasmark(&r->o)) || - (r->st == HOLD && hasmark(&r->o)) || - r->st == COLLECTED || - r->st == NONEXT || - (r->st < n && VALIDLINK(L, L->refArray[r->st].st, n)), - "inconsistent ref table"); - } - LUA_ASSERT(VALIDLINK(L, L->refFree, n), "inconsistent ref table"); -} - - - -static void collectproto (lua_State *L) { - Proto **p = &L->rootproto; - Proto *next; - while ((next = *p) != NULL) { - if (next->marked) { - next->marked = 0; - p = &next->next; - } - else { - *p = next->next; - luaF_freeproto(L, next); - } - } -} - - -static void collectclosure (lua_State *L) { - Closure **p = &L->rootcl; - Closure *next; - while ((next = *p) != NULL) { - if (ismarked(next)) { - next->mark = next; /* unmark */ - p = &next->next; - } - else { - *p = next->next; - luaF_freeclosure(L, next); - } - } -} - - -static void collecttable (lua_State *L) { - Hash **p = &L->roottable; - Hash *next; - while ((next = *p) != NULL) { - if (ismarked(next)) { - next->mark = next; /* unmark */ - p = &next->next; - } - else { - *p = next->next; - luaH_free(L, next); - } - } -} - - -static void checktab (lua_State *L, stringtable *tb) { - if (tb->nuse < (lint32)(tb->size/4) && tb->size > 10) - luaS_resize(L, tb, tb->size/2); /* table is too big */ -} - - -static void collectstrings (lua_State *L, int all) { - int i; - for (i=0; istrt.size; i++) { /* for each list */ - TString **p = &L->strt.hash[i]; - TString *next; - while ((next = *p) != NULL) { - if (next->marked && !all) { /* preserve? */ - if (next->marked < FIXMARK) /* does not change FIXMARKs */ - next->marked = 0; - p = &next->nexthash; - } - else { /* collect */ - *p = next->nexthash; - L->strt.nuse--; - L->nblocks -= sizestring(next->len); - luaM_free(L, next); - } - } - } - checktab(L, &L->strt); -} - - -static void collectudata (lua_State *L, int all) { - int i; - for (i=0; iudt.size; i++) { /* for each list */ - TString **p = &L->udt.hash[i]; - TString *next; - while ((next = *p) != NULL) { - LUA_ASSERT(next->marked <= 1, "udata cannot be fixed"); - if (next->marked && !all) { /* preserve? */ - next->marked = 0; - p = &next->nexthash; - } - else { /* collect */ - int tag = next->u.d.tag; - *p = next->nexthash; - next->nexthash = L->TMtable[tag].collected; /* chain udata */ - L->TMtable[tag].collected = next; - L->nblocks -= sizestring(next->len); - L->udt.nuse--; - } - } - } - checktab(L, &L->udt); -} - - -#define MINBUFFER 256 -static void checkMbuffer (lua_State *L) { - if (L->Mbuffsize > MINBUFFER*2) { /* is buffer too big? */ - size_t newsize = L->Mbuffsize/2; /* still larger than MINBUFFER */ - L->nblocks += (newsize - L->Mbuffsize)*sizeof(char); - L->Mbuffsize = newsize; - luaM_reallocvector(L, L->Mbuffer, newsize, char); - } -} - - -static void callgcTM (lua_State *L, const TObject *o) { - Closure *tm = luaT_gettmbyObj(L, o, TM_GC); - if (tm != NULL) { - int oldah = L->allowhooks; - L->allowhooks = 0; /* stop debug hooks during GC tag methods */ - luaD_checkstack(L, 2); - clvalue(L->top) = tm; - ttype(L->top) = LUA_TFUNCTION; - *(L->top+1) = *o; - L->top += 2; - luaD_call(L, L->top-2, 0); - L->allowhooks = oldah; /* restore hooks */ - } -} - - -static void callgcTMudata (lua_State *L) { - int tag; - TObject o; - ttype(&o) = LUA_TUSERDATA; - L->GCthreshold = 2*L->nblocks; /* avoid GC during tag methods */ - for (tag=L->last_tag; tag>=0; tag--) { /* for each tag (in reverse order) */ - TString *udata; - while ((udata = L->TMtable[tag].collected) != NULL) { - L->TMtable[tag].collected = udata->nexthash; /* remove it from list */ - tsvalue(&o) = udata; - callgcTM(L, &o); - luaM_free(L, udata); - } - } -} - - -void luaC_collect (lua_State *L, int all) { - collectudata(L, all); - callgcTMudata(L); - collectstrings(L, all); - collecttable(L); - collectproto(L); - collectclosure(L); -} - - -static void luaC_collectgarbage (lua_State *L) { - markall(L); - invalidaterefs(L); /* check unlocked references */ - luaC_collect(L, 0); - checkMbuffer(L); - L->GCthreshold = 2*L->nblocks; /* set new threshold */ - callgcTM(L, &luaO_nilobject); -} - - -void luaC_checkGC (lua_State *L) { - if (L->nblocks >= L->GCthreshold) - luaC_collectgarbage(L); -} - diff --git a/src/lua/lgc.h b/src/lua/lgc.h deleted file mode 100644 index 2dea9e4d..00000000 --- a/src/lua/lgc.h +++ /dev/null @@ -1,18 +0,0 @@ -/* -** $Id: lgc.h,v 1.3 2001/11/26 23:00:24 darkgod Exp $ -** Garbage Collector -** See Copyright Notice in lua.h -*/ - -#ifndef lgc_h -#define lgc_h - - -#include "lobject.h" - - -void luaC_collect (lua_State *L, int all); -void luaC_checkGC (lua_State *L); - - -#endif diff --git a/src/lua/liolib.c b/src/lua/liolib.c deleted file mode 100644 index 4fb385f4..00000000 --- a/src/lua/liolib.c +++ /dev/null @@ -1,710 +0,0 @@ -/* -** $Id: liolib.c,v 1.5 2004/06/04 13:42:10 neil Exp $ -** Standard I/O (and system) library -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "luadebug.h" -#include "lualib.h" - - -#ifndef OLD_ANSI -#include -#include -#define realloc(b,s) ((b) == NULL ? malloc(s) : (realloc)(b, s)) -#define free(b) if (b) (free)(b) -#else -/* no support for locale and for strerror: fake them */ -#define setlocale(a,b) ((void)a, strcmp((b),"C")==0?"C":NULL) -#define LC_ALL 0 -#define LC_COLLATE 0 -#define LC_CTYPE 0 -#define LC_MONETARY 0 -#define LC_NUMERIC 0 -#define LC_TIME 0 -#define strerror(e) "generic I/O error" -#define errno (-1) -#endif - - - -#ifdef POPEN -/* FILE *popen(); -int pclose(); */ -#define CLOSEFILE(L, f) ((pclose(f) == -1) ? fclose(f) : 0) -#else -/* no support for popen */ -#define popen(x,y) NULL /* that is, popen always fails */ -#define CLOSEFILE(L, f) (fclose(f)) -#endif - - -#define INFILE 0 -#define OUTFILE 1 - -typedef struct IOCtrl { - int ref[2]; /* ref for strings _INPUT/_OUTPUT */ - int iotag; /* tag for file handles */ - int closedtag; /* tag for closed handles */ -} IOCtrl; - - - -static const char *const filenames[] = {"_INPUT", "_OUTPUT"}; - - -static int pushresult (lua_State *L, int i) { - if (i) { - lua_pushuserdata(L, NULL); - return 1; - } - else { - lua_pushnil(L); - lua_pushstring(L, strerror(errno)); - lua_pushnumber(L, errno); - return 3;; - } -} - - -/* -** {====================================================== -** FILE Operations -** ======================================================= -*/ - - -static FILE *gethandle (lua_State *L, IOCtrl *ctrl, int f) { - void *p = lua_touserdata(L, f); - if (p != NULL) { /* is `f' a userdata ? */ - int ftag = lua_tag(L, f); - if (ftag == ctrl->iotag) /* does it have the correct tag? */ - return (FILE *)p; - else if (ftag == ctrl->closedtag) - lua_error(L, "cannot access a closed file"); - /* else go through */ - } - return NULL; -} - - -static FILE *getnonullfile (lua_State *L, IOCtrl *ctrl, int arg) { - FILE *f = gethandle(L, ctrl, arg); - luaL_arg_check(L, f, arg, "invalid file handle"); - return f; -} - - -static FILE *getfilebyref (lua_State *L, IOCtrl *ctrl, int inout) { - FILE *f; - lua_getglobals(L); - lua_getref(L, ctrl->ref[inout]); - lua_rawget(L, -2); - f = gethandle(L, ctrl, -1); - if (f == NULL) - luaL_verror(L, "global variable `%.10s' is not a file handle", - filenames[inout]); - return f; -} - - -static void setfilebyname (lua_State *L, IOCtrl *ctrl, FILE *f, - const char *name) { - lua_pushusertag(L, f, ctrl->iotag); - lua_setglobal(L, name); -} - - -#define setfile(L,ctrl,f,inout) (setfilebyname(L,ctrl,f,filenames[inout])) - - -static int setreturn (lua_State *L, IOCtrl *ctrl, FILE *f, int inout) { - if (f == NULL) - return pushresult(L, 0); - else { - setfile(L, ctrl, f, inout); - lua_pushusertag(L, f, ctrl->iotag); - return 1; - } -} - - -static int closefile (lua_State *L, IOCtrl *ctrl, FILE *f) { - if (f == stdin || f == stdout || f == stderr) - return 1; - else { - lua_pushusertag(L, f, ctrl->iotag); - lua_settag(L, ctrl->closedtag); - return (CLOSEFILE(L, f) == 0); - } -} - - -static int io_close (lua_State *L) { - IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); - lua_pop(L, 1); /* remove upvalue */ - return pushresult(L, closefile(L, ctrl, getnonullfile(L, ctrl, 1))); -} - - -static int file_collect (lua_State *L) { - IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); - FILE *f = getnonullfile(L, ctrl, 1); - if (f != stdin && f != stdout && f != stderr) - CLOSEFILE(L, f); - return 0; -} - - -static int io_open (lua_State *L) { - IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); - FILE *f; - lua_pop(L, 1); /* remove upvalue */ - f = fopen(luaL_check_string(L, 1), luaL_check_string(L, 2)); - if (f) { - lua_pushusertag(L, f, ctrl->iotag); - return 1; - } - else - return pushresult(L, 0); -} - - - -static int io_fromto (lua_State *L, int inout, const char *mode) { - IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); - FILE *current; - lua_pop(L, 1); /* remove upvalue */ - if (lua_isnull(L, 1)) { - closefile(L, ctrl, getfilebyref(L, ctrl, inout)); - current = (inout == 0) ? stdin : stdout; - } - else if (lua_tag(L, 1) == ctrl->iotag) /* deprecated option */ - current = (FILE *)lua_touserdata(L, 1); - else { - const char *s = luaL_check_string(L, 1); - current = (*s == '|') ? popen(s+1, mode) : fopen(s, mode); - } - return setreturn(L, ctrl, current, inout); -} - - -static int io_readfrom (lua_State *L) { - return io_fromto(L, INFILE, "r"); -} - - -static int io_writeto (lua_State *L) { - return io_fromto(L, OUTFILE, "w"); -} - - -static int io_appendto (lua_State *L) { - IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); - FILE *current; - lua_pop(L, 1); /* remove upvalue */ - current = fopen(luaL_check_string(L, 1), "a"); - return setreturn(L, ctrl, current, OUTFILE); -} - - - -/* -** {====================================================== -** READ -** ======================================================= -*/ - - - -#ifdef LUA_COMPAT_READPATTERN - -/* -** We cannot lookahead without need, because this can lock stdin. -** This flag signals when we need to read a next char. -*/ -#define NEED_OTHER (EOF-1) /* just some flag different from EOF */ - - -static int read_pattern (lua_State *L, FILE *f, const char *p) { - int inskip = 0; /* {skip} level */ - int c = NEED_OTHER; - luaL_Buffer b; - luaL_buffinit(L, &b); - while (*p != '\0') { - switch (*p) { - case '{': - inskip++; - p++; - continue; - case '}': - if (!inskip) lua_error(L, "unbalanced braces in read pattern"); - inskip--; - p++; - continue; - default: { - const char *ep = luaI_classend(L, p); /* get what is next */ - int m; /* match result */ - if (c == NEED_OTHER) c = getc(f); - m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep); - if (m) { - if (!inskip) luaL_putchar(&b, c); - c = NEED_OTHER; - } - switch (*ep) { - case '+': /* repetition (1 or more) */ - if (!m) goto break_while; /* pattern fails? */ - /* else go through */ - case '*': /* repetition (0 or more) */ - while (m) { /* reads the same item until it fails */ - c = getc(f); - m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep); - if (m && !inskip) luaL_putchar(&b, c); - } - /* go through to continue reading the pattern */ - case '?': /* optional */ - p = ep+1; /* continues reading the pattern */ - continue; - default: - if (!m) goto break_while; /* pattern fails? */ - p = ep; /* else continues reading the pattern */ - } - } - } - } break_while: - if (c != NEED_OTHER) ungetc(c, f); - luaL_pushresult(&b); /* close buffer */ - return (*p == '\0'); -} - -#else - -#define read_pattern(L, f, p) (lua_error(L, "read patterns are deprecated"), 0) - -#endif - - -static int read_number (lua_State *L, FILE *f) { - long d; - if (fscanf(f, "%ld", &d) == 1) { - lua_pushnumber(L, d); - return 1; - } - else return 0; /* read fails */ -} - - -static int read_word (lua_State *L, FILE *f) { - int c; - luaL_Buffer b; - luaL_buffinit(L, &b); - do { c = fgetc(f); } while (isspace(c)); /* skip spaces */ - while (c != EOF && !isspace(c)) { - luaL_putchar(&b, c); - c = fgetc(f); - } - ungetc(c, f); - luaL_pushresult(&b); /* close buffer */ - return (lua_strlen(L, -1) > 0); -} - - -static int read_line (lua_State *L, FILE *f) { - int n = 0; - luaL_Buffer b; - luaL_buffinit(L, &b); - for (;;) { - char *p = luaL_prepbuffer(&b); - if (!fgets(p, LUAL_BUFFERSIZE, f)) /* read fails? */ - break; - n = strlen(p); - if (p[n-1] != '\n') - luaL_addsize(&b, n); - else { - luaL_addsize(&b, n-1); /* do not add the `\n' */ - break; - } - } - luaL_pushresult(&b); /* close buffer */ - return (n > 0); /* read something? */ -} - - -static void read_file (lua_State *L, FILE *f) { - size_t len = 0; - size_t size = BUFSIZ; - char *buffer = NULL; - for (;;) { - char *newbuffer = (char *)realloc(buffer, size); - if (newbuffer == NULL) { - free(buffer); - lua_error(L, "not enough memory to read a file"); - } - buffer = newbuffer; - len += fread(buffer+len, sizeof(char), size-len, f); - if (len < size) break; /* did not read all it could */ - size *= 2; - } - lua_pushlstring(L, buffer, len); - free(buffer); -} - - -static int read_chars (lua_State *L, FILE *f, size_t n) { - char *buffer; - size_t n1; - char statbuff[BUFSIZ]; - if (n <= BUFSIZ) - buffer = statbuff; - else { - buffer = (char *)malloc(n); - if (buffer == NULL) - lua_error(L, "not enough memory to read a file"); - } - n1 = fread(buffer, sizeof(char), n, f); - lua_pushlstring(L, buffer, n1); - if (buffer != statbuff) free(buffer); - return (n1 > 0 || n == 0); -} - - -static int io_read (lua_State *L) { - IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); - int lastarg = lua_gettop(L) - 1; - int firstarg = 1; - FILE *f = gethandle(L, ctrl, firstarg); - int n; - if (f) firstarg++; - else f = getfilebyref(L, ctrl, INFILE); /* get _INPUT */ - lua_pop(L, 1); - if (firstarg > lastarg) { /* no arguments? */ - lua_settop(L, 0); /* erase upvalue and other eventual garbage */ - firstarg = lastarg = 1; /* correct indices */ - lua_pushstring(L, "*l"); /* push default argument */ - } - else /* ensure stack space for all results and for auxlib's buffer */ - luaL_checkstack(L, lastarg-firstarg+1+LUA_MINSTACK, "too many arguments"); - for (n = firstarg; n<=lastarg; n++) { - int success; - if (lua_isnumber(L, n)) - success = read_chars(L, f, (size_t)lua_tonumber(L, n)); - else { - const char *p = luaL_check_string(L, n); - if (p[0] != '*') - success = read_pattern(L, f, p); /* deprecated! */ - else { - switch (p[1]) { - case 'n': /* number */ - if (!read_number(L, f)) goto endloop; /* read fails */ - continue; /* number is already pushed; avoid the "pushstring" */ - case 'l': /* line */ - success = read_line(L, f); - break; - case 'a': /* file */ - read_file(L, f); - success = 1; /* always success */ - break; - case 'w': /* word */ - success = read_word(L, f); - break; - default: - luaL_argerror(L, n, "invalid format"); - success = 0; /* to avoid warnings */ - } - } - } - if (!success) { - lua_pop(L, 1); /* remove last result */ - break; /* read fails */ - } - } endloop: - return n - firstarg; -} - -/* }====================================================== */ - - -static int io_write (lua_State *L) { - int lastarg = lua_gettop(L) - 1; - IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); - int arg = 1; - int status = 1; - FILE *f = gethandle(L, ctrl, arg); - if (f) arg++; - else f = getfilebyref(L, ctrl, OUTFILE); /* get _OUTPUT */ - for (; arg <= lastarg; arg++) { - if (lua_type(L, arg) == LUA_TNUMBER) { /* LUA_NUMBER */ - /* optimization: could be done exactly as for strings */ - status = status && fprintf(f, "%ld", lua_tonumber(L, arg)) > 0; - } - else { - size_t l; - const char *s = luaL_check_lstr(L, arg, &l); - status = status && (fwrite(s, sizeof(char), l, f) == l); - } - } - pushresult(L, status); - return 1; -} - - -static int io_seek (lua_State *L) { - static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; - static const char *const modenames[] = {"set", "cur", "end", NULL}; - IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); - FILE *f; - int op; - long offset; - lua_pop(L, 1); /* remove upvalue */ - f = getnonullfile(L, ctrl, 1); - op = luaL_findstring(luaL_opt_string(L, 2, "cur"), modenames); - offset = luaL_opt_long(L, 3, 0); - luaL_arg_check(L, op != -1, 2, "invalid mode"); - op = fseek(f, offset, mode[op]); - if (op) - return pushresult(L, 0); /* error */ - else { - lua_pushnumber(L, ftell(f)); - return 1; - } -} - - -static int io_flush (lua_State *L) { - IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1); - FILE *f; - lua_pop(L, 1); /* remove upvalue */ - f = gethandle(L, ctrl, 1); - luaL_arg_check(L, f || lua_isnull(L, 1), 1, "invalid file handle"); - return pushresult(L, fflush(f) == 0); -} - -/* }====================================================== */ - - -/* -** {====================================================== -** Other O.S. Operations -** ======================================================= -*/ - -static int io_execute (lua_State *L) { - lua_pushnumber(L, system(luaL_check_string(L, 1))); - return 1; -} - - -static int io_remove (lua_State *L) { - return pushresult(L, remove(luaL_check_string(L, 1)) == 0); -} - - -static int io_rename (lua_State *L) { - return pushresult(L, rename(luaL_check_string(L, 1), - luaL_check_string(L, 2)) == 0); -} - - -static int io_getenv (lua_State *L) { - lua_pushstring(L, getenv(luaL_check_string(L, 1))); /* if NULL push nil */ - return 1; -} - - -static int io_clock (lua_State *L) { - lua_pushnumber(L, ((long)clock())/CLOCKS_PER_SEC); - return 1; -} - - -static int io_date (lua_State *L) { - char b[256]; - const char *s = luaL_opt_string(L, 1, "%c"); - struct tm *stm; - time_t t; - time(&t); stm = localtime(&t); - if (strftime(b, sizeof(b), s, stm)) - lua_pushstring(L, b); - else - lua_error(L, "invalid `date' format"); - return 1; -} - - -static int setloc (lua_State *L) { - static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, - LC_NUMERIC, LC_TIME}; - static const char *const catnames[] = {"all", "collate", "ctype", "monetary", - "numeric", "time", NULL}; - int op = luaL_findstring(luaL_opt_string(L, 2, "all"), catnames); - luaL_arg_check(L, op != -1, 2, "invalid option"); - lua_pushstring(L, setlocale(cat[op], luaL_check_string(L, 1))); - return 1; -} - - -static int io_exit (lua_State *L) { - exit(luaL_opt_int(L, 1, EXIT_SUCCESS)); - return 0; /* to avoid warnings */ -} - -/* }====================================================== */ - - - -static int io_debug (lua_State *L) { - for (;;) { - char buffer[250]; - fprintf(stderr, "lua_debug> "); - if (fgets(buffer, sizeof(buffer), stdin) == 0 || - strcmp(buffer, "cont\n") == 0) - return 0; - lua_dostring(L, buffer); - lua_settop(L, 0); /* remove eventual returns */ - } -} - - -#define LEVELS1 12 /* size of the first part of the stack */ -#define LEVELS2 10 /* size of the second part of the stack */ - -static int errorfb (lua_State *L) { - int level = 1; /* skip level 0 (it's this function) */ - int firstpart = 1; /* still before eventual `...' */ - lua_Debug ar; - luaL_Buffer b; - luaL_buffinit(L, &b); - luaL_addstring(&b, "error: "); - luaL_addstring(&b, luaL_check_string(L, 1)); - luaL_addstring(&b, "\n"); - while (lua_getstack(L, level++, &ar)) { - char buff[120]; /* enough to fit following `sprintf's */ - if (level == 2) - luaL_addstring(&b, "stack traceback:\n"); - else if (level > LEVELS1 && firstpart) { - /* no more than `LEVELS2' more levels? */ - if (!lua_getstack(L, level+LEVELS2, &ar)) - level--; /* keep going */ - else { - luaL_addstring(&b, " ...\n"); /* too many levels */ - while (lua_getstack(L, level+LEVELS2, &ar)) /* find last levels */ - level++; - } - firstpart = 0; - continue; - } - sprintf(buff, "%4d: ", level-1); - luaL_addstring(&b, buff); - lua_getinfo(L, "Snl", &ar); - switch (*ar.namewhat) { - case 'g': case 'l': /* global, local */ - sprintf(buff, "function `%.50s'", ar.name); - break; - case 'f': /* field */ - sprintf(buff, "method `%.50s'", ar.name); - break; - case 't': /* tag method */ - sprintf(buff, "`%.50s' tag method", ar.name); - break; - default: { - if (*ar.what == 'm') /* main? */ - sprintf(buff, "main of %.70s", ar.short_src); - else if (*ar.what == 'C') /* C function? */ - sprintf(buff, "%.70s", ar.short_src); - else - sprintf(buff, "function <%d:%.70s>", ar.linedefined, ar.short_src); - ar.source = NULL; /* do not print source again */ - } - } - luaL_addstring(&b, buff); - if (ar.currentline > 0) { - sprintf(buff, " at line %d", ar.currentline); - luaL_addstring(&b, buff); - } - if (ar.source) { - sprintf(buff, " [%.70s]", ar.short_src); - luaL_addstring(&b, buff); - } - luaL_addstring(&b, "\n"); - } - luaL_pushresult(&b); - lua_getglobal(L, LUA_ALERT); - if (lua_isfunction(L, -1)) { /* avoid loop if _ALERT is not defined */ - lua_pushvalue(L, -2); /* error message */ - lua_rawcall(L, 1, 0); - } - return 0; -} - - - -static const struct luaL_reg iolib[] = { - {LUA_ERRORMESSAGE, errorfb}, - {"clock", io_clock}, - {"date", io_date}, - {"debug", io_debug}, - {"execute", io_execute}, - {"exit", io_exit}, - {"getenv", io_getenv}, - {"remove", io_remove}, - {"rename", io_rename}, - {"setlocale", setloc}, -}; - - -static const struct luaL_reg iolibtag[] = { - {"appendto", io_appendto}, - {"closefile", io_close}, - {"flush", io_flush}, - {"openfile", io_open}, - {"read", io_read}, - {"readfrom", io_readfrom}, - {"seek", io_seek}, - {"write", io_write}, - {"writeto", io_writeto} -}; - - -static void openwithcontrol (lua_State *L) { - IOCtrl *ctrl = (IOCtrl *)lua_newuserdata(L, sizeof(IOCtrl)); - unsigned int i; - ctrl->iotag = lua_newtag(L); - ctrl->closedtag = lua_newtag(L); - for (i=0; iref[INFILE] = lua_ref(L, 1); - lua_pushstring(L, filenames[OUTFILE]); - ctrl->ref[OUTFILE] = lua_ref(L, 1); - /* predefined file handles */ - setfile(L, ctrl, stdin, INFILE); - setfile(L, ctrl, stdout, OUTFILE); - setfilebyname(L, ctrl, stdin, "_STDIN"); - setfilebyname(L, ctrl, stdout, "_STDOUT"); - setfilebyname(L, ctrl, stderr, "_STDERR"); - /* close files when collected */ - lua_pushcclosure(L, file_collect, 1); /* pops `ctrl' from stack */ - lua_settagmethod(L, ctrl->iotag, "gc"); -} - - -LUALIB_API void lua_iolibopen (lua_State *L) { - luaL_openl(L, iolib); - openwithcontrol(L); -} - diff --git a/src/lua/llex.c b/src/lua/llex.c deleted file mode 100644 index 86fb69ab..00000000 --- a/src/lua/llex.c +++ /dev/null @@ -1,411 +0,0 @@ -/* -** $Id: llex.c,v 1.6 2004/06/04 13:42:10 neil Exp $ -** Lexical Analyzer -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include - -#include "lua.h" - -#include "llex.h" -#include "lmem.h" -#include "lobject.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "luadebug.h" -#include "lzio.h" - - - -#define next(LS) (LS->current = zgetc(LS->z)) - - - -/* ORDER RESERVED */ -static const char *const token2string [] = { - "and", "break", "do", "else", "elseif", "end", "for", - "function", "if", "local", "nil", "not", "or", "repeat", "return", "then", - "until", "while", "", "..", "...", "==", ">=", "<=", "~=", "", "", ""}; - - -void luaX_init (lua_State *L) { - int i; - for (i=0; imarked = (unsigned char)(RESERVEDMARK+i); /* reserved word */ - } -} - - -#define MAXSRC 80 - - -void luaX_checklimit (LexState *ls, int val, int limit, const char *msg) { - if (val > limit) { - char buff[100]; - sprintf(buff, "too many %.50s (limit=%d)", msg, limit); - luaX_error(ls, buff, ls->t.token); - } -} - - -void luaX_syntaxerror (LexState *ls, const char *s, const char *token) { - char buff[MAXSRC]; - luaO_chunkid(buff, ls->source->str, sizeof(buff)); - luaO_verror(ls->L, "%.99s;\n last token read: `%.30s' at line %d in %.80s", - s, token, ls->linenumber, buff); -} - - -void luaX_error (LexState *ls, const char *s, int token) { - char buff[TOKEN_LEN]; - luaX_token2str(token, buff); - if (buff[0] == '\0') - luaX_syntaxerror(ls, s, ls->L->Mbuffer); - else - luaX_syntaxerror(ls, s, buff); -} - - -void luaX_token2str (int token, char *s) { - if (token < 256) { - s[0] = (char)token; - s[1] = '\0'; - } - else - strcpy(s, token2string[token-FIRST_RESERVED]); -} - - -static void luaX_invalidchar (LexState *ls, int c) { - char buff[8]; - sprintf(buff, "0x%02X", c); - luaX_syntaxerror(ls, "invalid control char", buff); -} - - -static void inclinenumber (LexState *LS) { - next(LS); /* skip '\n' */ - ++LS->linenumber; - luaX_checklimit(LS, LS->linenumber, MAX_INT, "lines in a chunk"); -} - - -void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source) { - LS->L = L; - LS->lookahead.token = TK_EOS; /* no look-ahead token */ - LS->z = z; - LS->fs = NULL; - LS->linenumber = 1; - LS->lastline = 1; - LS->source = source; - next(LS); /* read first char */ - if (LS->current == '#') { - do { /* skip first line */ - next(LS); - } while (LS->current != '\n' && LS->current != '\r' && LS->current != EOZ); - } -} - - - -/* -** ======================================================= -** LEXICAL ANALYZER -** ======================================================= -*/ - - -/* use Mbuffer to store names, literal strings and numbers */ - -#define EXTRABUFF 128 -#define checkbuffer(L, n, len) if ((len)+(n) > L->Mbuffsize) \ - luaO_openspace(L, (len)+(n)+EXTRABUFF) - -#define save(L, c, l) (L->Mbuffer[l++] = (char)c) -#define save_and_next(L, LS, l) (save(L, LS->current, l), next(LS)) - - -static const char *readname (LexState *LS) { - lua_State *L = LS->L; - size_t l = 0; - checkbuffer(L, 10, l); - do { - checkbuffer(L, 10, l); - save_and_next(L, LS, l); - } while (isalnum(LS->current) || LS->current == '_'); - save(L, '\0', l); - return L->Mbuffer; -} - - -/* LUA_NUMBER */ -static void read_number (LexState *LS, int comma, SemInfo *seminfo) { - lua_State *L = LS->L; - size_t l = 0; - checkbuffer(L, 10, l); - if (comma) save(L, '.', l); - while (isdigit(LS->current)) { - checkbuffer(L, 10, l); - save_and_next(L, LS, l); - } - if (LS->current == '.') { - save_and_next(L, LS, l); - if (LS->current == '.') { - save_and_next(L, LS, l); - save(L, '\0', l); - luaX_error(LS, "ambiguous syntax" - " (decimal point x string concatenation)", TK_NUMBER); - } - } - while (isdigit(LS->current)) { - checkbuffer(L, 10, l); - save_and_next(L, LS, l); - } - if (LS->current == 'e' || LS->current == 'E') { - save_and_next(L, LS, l); /* read 'E' */ - if (LS->current == '+' || LS->current == '-') - save_and_next(L, LS, l); /* optional exponent sign */ - while (isdigit(LS->current)) { - checkbuffer(L, 10, l); - save_and_next(L, LS, l); - } - } - save(L, '\0', l); - if (!luaO_str2d(L->Mbuffer, &seminfo->r)) - luaX_error(LS, "malformed number", TK_NUMBER); -} - - -static void read_long_string (LexState *LS, SemInfo *seminfo) { - lua_State *L = LS->L; - int cont = 0; - size_t l = 0; - checkbuffer(L, 10, l); - save(L, '[', l); /* save first '[' */ - save_and_next(L, LS, l); /* pass the second '[' */ - for (;;) { - checkbuffer(L, 10, l); - switch (LS->current) { - case EOZ: - save(L, '\0', l); - if (seminfo) - luaX_error(LS, "unfinished long string", TK_STRING); - else - luaX_error(LS, "unfinished comment", TK_EOS); - break; /* to avoid warnings */ - case '[': - save_and_next(L, LS, l); - if (LS->current == '[') { - cont++; - save_and_next(L, LS, l); - } - continue; - case ']': - save_and_next(L, LS, l); - if (LS->current == ']') { - if (cont == 0) goto endloop; - cont--; - save_and_next(L, LS, l); - } - continue; - case '\n': - save(L, '\n', l); - inclinenumber(LS); - if (LS->current == '\r') next(LS); - continue; - case '\r': - save(L, '\n', l); - inclinenumber(LS); - if (LS->current == '\n') next(LS); - continue; - default: - if (seminfo) /* no need to save complete comment */ - save(L, LS->current, l); - next(LS); - } - } endloop: - save_and_next(L, LS, l); /* skip the second ']' */ - save(L, '\0', l); - if (seminfo) - seminfo->ts = luaS_newlstr(L, L->Mbuffer+2, l-5); -} - - -static void read_string (LexState *LS, int del, SemInfo *seminfo) { - lua_State *L = LS->L; - size_t l = 0; - checkbuffer(L, 10, l); - save_and_next(L, LS, l); - while (LS->current != del) { - checkbuffer(L, 10, l); - switch (LS->current) { - case EOZ: case '\n': case '\r': - save(L, '\0', l); - luaX_error(LS, "unfinished string", TK_STRING); - break; /* to avoid warnings */ - case '\\': - next(LS); /* do not save the '\' */ - switch (LS->current) { - case 'a': save(L, '\a', l); next(LS); break; - case 'b': save(L, '\b', l); next(LS); break; - case 'f': save(L, '\f', l); next(LS); break; - case 'n': save(L, '\n', l); next(LS); break; - case 'r': save(L, '\r', l); next(LS); break; - case 't': save(L, '\t', l); next(LS); break; - case 'v': save(L, '\v', l); next(LS); break; - case '\n': - save(L, '\n', l); - inclinenumber(LS); - if (LS->current == '\r') next(LS); - break; - case '\r': - save(L, '\n', l); - inclinenumber(LS); - if (LS->current == '\n') next(LS); - break; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': { - int c = 0; - int i = 0; - do { - c = 10*c + (LS->current-'0'); - next(LS); - } while (++i<3 && isdigit(LS->current)); - if (c != (unsigned char)c) { - save(L, '\0', l); - luaX_error(LS, "escape sequence too large", TK_STRING); - } - save(L, c, l); - break; - } - default: /* handles \\, \", \', and \? */ - save_and_next(L, LS, l); - } - break; - default: - save_and_next(L, LS, l); - } - } - save_and_next(L, LS, l); /* skip delimiter */ - save(L, '\0', l); - seminfo->ts = luaS_newlstr(L, L->Mbuffer+1, l-3); -} - - -int luaX_lex (LexState *LS, SemInfo *seminfo) { - for (;;) { - switch (LS->current) { - - case ' ': case '\t': - next(LS); - continue; - - case '\n': - inclinenumber(LS); - if (LS->current == '\r') next(LS); - continue; - - case '\r': - inclinenumber(LS); - if (LS->current == '\n') next(LS); - continue; - - case '$': - luaX_error(LS, "unexpected `$' (pragmas are no longer supported)", '$'); - break; - - case '-': - next(LS); - if (LS->current != '-') return '-'; - if (next(LS) == '[' && next(LS) == '[') - read_long_string(LS, NULL); - else - while (LS->current != '\n' && LS->current != '\r' && LS->current != EOZ) - next(LS); - continue; - - case '[': - next(LS); - if (LS->current != '[') return '['; - else { - read_long_string(LS, seminfo); - return TK_STRING; - } - - case '=': - next(LS); - if (LS->current != '=') return '='; - else { next(LS); return TK_EQ; } - - case '<': - next(LS); - if (LS->current != '=') return '<'; - else { next(LS); return TK_LE; } - - case '>': - next(LS); - if (LS->current != '=') return '>'; - else { next(LS); return TK_GE; } - - case '~': - next(LS); - if (LS->current != '=') return '~'; - else { next(LS); return TK_NE; } - - case '"': - case '\'': - read_string(LS, LS->current, seminfo); - return TK_STRING; - - case '.': - next(LS); - if (LS->current == '.') { - next(LS); - if (LS->current == '.') { - next(LS); - return TK_DOTS; /* ... */ - } - else return TK_CONCAT; /* .. */ - } - else if (!isdigit(LS->current)) return '.'; - else { - read_number(LS, 1, seminfo); - return TK_NUMBER; - } - - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - read_number(LS, 0, seminfo); - return TK_NUMBER; - - case EOZ: - return TK_EOS; - - case '_': goto tname; - - default: - if (!isalpha(LS->current)) { - int c = LS->current; - if (iscntrl(c)) - luaX_invalidchar(LS, c); - next(LS); - return c; - } - tname: { /* identifier or reserved word */ - TString *ts = luaS_new(LS->L, readname(LS)); - if (ts->marked >= RESERVEDMARK) /* reserved word? */ - return ts->marked-RESERVEDMARK+FIRST_RESERVED; - seminfo->ts = ts; - return TK_NAME; - } - } - } -} - diff --git a/src/lua/llex.h b/src/lua/llex.h deleted file mode 100644 index 5fb13c88..00000000 --- a/src/lua/llex.h +++ /dev/null @@ -1,72 +0,0 @@ -/* -** $Id: llex.h,v 1.3 2001/11/26 23:00:24 darkgod Exp $ -** Lexical Analyzer -** See Copyright Notice in lua.h -*/ - -#ifndef llex_h -#define llex_h - -#include "lobject.h" -#include "lzio.h" - - -#define FIRST_RESERVED 257 - -/* maximum length of a reserved word (+1 for final 0) */ -#define TOKEN_LEN 15 - - -/* -* WARNING: if you change the order of this enumeration, -* grep "ORDER RESERVED" -*/ -enum RESERVED { - /* terminal symbols denoted by reserved words */ - TK_AND = FIRST_RESERVED, TK_BREAK, - TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FOR, TK_FUNCTION, TK_IF, TK_LOCAL, - TK_NIL, TK_NOT, TK_OR, TK_REPEAT, TK_RETURN, TK_THEN, TK_UNTIL, TK_WHILE, - /* other terminal symbols */ - TK_NAME, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, - TK_STRING, TK_EOS -}; - -/* number of reserved words */ -#define NUM_RESERVED ((int)(TK_WHILE-FIRST_RESERVED+1)) - - -typedef union { - Number r; - TString *ts; -} SemInfo; /* semantics information */ - - -typedef struct Token { - int token; - SemInfo seminfo; -} Token; - - -typedef struct LexState { - int current; /* current character */ - Token t; /* current token */ - Token lookahead; /* look ahead token */ - struct FuncState *fs; /* `FuncState' is private to the parser */ - struct lua_State *L; - struct zio *z; /* input stream */ - int linenumber; /* input line counter */ - int lastline; /* line of last token `consumed' */ - TString *source; /* current source name */ -} LexState; - - -void luaX_init (lua_State *L); -void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source); -int luaX_lex (LexState *LS, SemInfo *seminfo); -void luaX_checklimit (LexState *ls, int val, int limit, const char *msg); -void luaX_syntaxerror (LexState *ls, const char *s, const char *token); -void luaX_error (LexState *ls, const char *s, int token); -void luaX_token2str (int token, char *s); - - -#endif diff --git a/src/lua/llimits.h b/src/lua/llimits.h deleted file mode 100644 index 4b124503..00000000 --- a/src/lua/llimits.h +++ /dev/null @@ -1,204 +0,0 @@ -/* -** $Id: llimits.h,v 1.2 2001/11/26 23:00:24 darkgod Exp $ -** Limits, basic types, and some other "installation-dependent" definitions -** See Copyright Notice in lua.h -*/ - -#ifndef llimits_h -#define llimits_h - - -#include -#include - - - -/* -** try to find number of bits in an integer -*/ -#ifndef BITS_INT -/* avoid overflows in comparison */ -#if INT_MAX-20 < 32760 -#define BITS_INT 16 -#else -#if INT_MAX > 2147483640L -/* machine has at least 32 bits */ -#define BITS_INT 32 -#else -#error "you must define BITS_INT with number of bits in an integer" -#endif -#endif -#endif - - -/* -** Define the type `number' of Lua -** GREP LUA_NUMBER to change that -*/ -#ifndef LUA_NUM_TYPE -#define LUA_NUM_TYPE long -#endif - -typedef LUA_NUM_TYPE Number; - -/* function to convert a Number to a string */ -#define NUMBER_FMT "%ld" /* LUA_NUMBER */ -#define lua_number2str(s,n) sprintf((s), NUMBER_FMT, (n)) - -/* function to convert a string to a Number */ -#define lua_str2number(s,p) strtol((s), (p), 10) - - - -typedef unsigned long lint32; /* unsigned int with at least 32 bits */ - - -#define MAX_SIZET ((size_t)(~(size_t)0)-2) - - -#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ - -/* -** conversion of pointer to int (for hashing only) -** (the shift removes bits that are usually 0 because of alignment) -*/ -#define IntPoint(p) (((unsigned long)(p)) >> 3) - - - -#define MINPOWER2 4 /* minimum size for "growing" vectors */ - - - -#ifndef DEFAULT_STACK_SIZE -#define DEFAULT_STACK_SIZE 1024 -#endif - - - -/* type to ensure maximum alignment */ -union L_Umaxalign { long d; char *s; long l; }; - - - -/* -** type for virtual-machine instructions -** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) -** For a very small machine, you may change that to 2 bytes (and adjust -** the following limits accordingly) -*/ -typedef unsigned long Instruction; - - -/* -** size and position of opcode arguments. -** For an instruction with 2 bytes, size is 16, and size_b can be 5 -** (accordingly, size_u will be 10, and size_a will be 5) -*/ -#define SIZE_INSTRUCTION 32 -#define SIZE_B 9 - -#define SIZE_OP 6 -#define SIZE_U (SIZE_INSTRUCTION-SIZE_OP) -#define POS_U SIZE_OP -#define POS_B SIZE_OP -#define SIZE_A (SIZE_INSTRUCTION-(SIZE_OP+SIZE_B)) -#define POS_A (SIZE_OP+SIZE_B) - - -/* -** limits for opcode arguments. -** we use (signed) int to manipulate most arguments, -** so they must fit in BITS_INT-1 bits (-1 for sign) -*/ -#if SIZE_U < BITS_INT-1 -#define MAXARG_U ((1<>1) /* `S' is signed */ -#else -#define MAXARG_U MAX_INT -#define MAXARG_S MAX_INT -#endif - -#if SIZE_A < BITS_INT-1 -#define MAXARG_A ((1< MAXARG_B -#undef MAXSTACK -#define MAXSTACK MAXARG_B -#endif - - -/* maximum number of local variables */ -#ifndef MAXLOCALS -#define MAXLOCALS 200 /* arbitrary limit (=MAXSTACK -#undef MAXLOCALS -#define MAXLOCALS (MAXSTACK-1) -#endif - - -/* maximum number of upvalues */ -#ifndef MAXUPVALUES -#define MAXUPVALUES 32 /* arbitrary limit (<=MAXARG_B) */ -#endif -#if MAXUPVALUES>MAXARG_B -#undef MAXUPVALUES -#define MAXUPVALUES MAXARG_B -#endif - - -/* maximum number of variables in the left side of an assignment */ -#ifndef MAXVARSLH -#define MAXVARSLH 100 /* arbitrary limit (=MULT_RET -#undef MAXVARSLH -#define MAXVARSLH (MULT_RET-1) -#endif - - -/* maximum number of parameters in a function */ -#ifndef MAXPARAMS -#define MAXPARAMS 100 /* arbitrary limit (=MAXLOCALS -#undef MAXPARAMS -#define MAXPARAMS (MAXLOCALS-1) -#endif - - -/* number of list items to accumulate before a SETLIST instruction */ -#define LFIELDS_PER_FLUSH 64 -#if LFIELDS_PER_FLUSH>(MAXSTACK/4) -#undef LFIELDS_PER_FLUSH -#define LFIELDS_PER_FLUSH (MAXSTACK/4) -#endif - -/* number of record items to accumulate before a SETMAP instruction */ -/* (each item counts 2 elements on the stack: an index and a value) */ -#define RFIELDS_PER_FLUSH (LFIELDS_PER_FLUSH/2) - - -/* maximum lookback to find a real constant (for code generation) */ -#ifndef LOOKBACKNUMS -#define LOOKBACKNUMS 20 /* arbitrary constant */ -#endif - - -#endif diff --git a/src/lua/lmem.c b/src/lua/lmem.c deleted file mode 100644 index 8fdecef3..00000000 --- a/src/lua/lmem.c +++ /dev/null @@ -1,150 +0,0 @@ -/* -** $Id: lmem.c,v 1.3 2001/11/26 23:00:24 darkgod Exp $ -** Interface to Memory Manager -** See Copyright Notice in lua.h -*/ - - -#include - -#include "lua.h" - -#include "ldo.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" - - - - -#ifdef LUA_DEBUG -/* -** {====================================================================== -** Controlled version for realloc. -** ======================================================================= -*/ - - -#include -#include -#include - -#define realloc(b, s) debug_realloc(b, s) -#define malloc(b) debug_realloc(NULL, b) -#define free(b) debug_realloc(b, 0) - - -/* ensures maximum alignment for HEADER */ -#define HEADER (sizeof(union L_Umaxalign)) - -#define MARKSIZE 16 -#define MARK 0x55 /* 01010101 (a nice pattern) */ - - -#define blocksize(b) ((unsigned long *)((char *)(b) - HEADER)) - -unsigned long memdebug_numblocks = 0; -unsigned long memdebug_total = 0; -unsigned long memdebug_maxmem = 0; -unsigned long memdebug_memlimit = LONG_MAX; - - -static void *checkblock (void *block) { - unsigned long *b = blocksize(block); - unsigned long size = *b; - int i; - for (i=0;i memdebug_memlimit) - return NULL; /* to test memory allocation errors */ - else { - size_t realsize = HEADER+size+MARKSIZE; - char *newblock = (char *)(malloc)(realsize); /* alloc a new block */ - int i; - if (realsize < size) return NULL; /* overflow! */ - if (newblock == NULL) return NULL; - if (block) { - size_t oldsize = *blocksize(block); - if (oldsize > size) oldsize = size; - memcpy(newblock+HEADER, block, oldsize); - freeblock(block); /* erase (and check) old copy */ - } - memdebug_total += size; - if (memdebug_total > memdebug_maxmem) memdebug_maxmem = memdebug_total; - memdebug_numblocks++; - *(unsigned long *)newblock = size; - for (i=0;i= limit-inc) lua_error(L, errormsg); - if ((newn ^ nelems) <= nelems || /* still the same power-of-2 limit? */ - (nelems > 0 && newn < MINPOWER2)) /* or block already is MINPOWER2? */ - return block; /* do not need to reallocate */ - else /* it crossed a power-of-2 boundary; grow to next power */ - return luaM_realloc(L, block, luaO_power2(newn)*size); -} - - -/* -** generic allocation routine. -*/ -void *luaM_realloc (lua_State *L, void *block, lint32 size) { - if (size == 0) { - free(block); /* block may be NULL; that is OK for free */ - return NULL; - } - else if (size >= MAX_SIZET) - lua_error(L, "memory allocation error: block too big"); - block = realloc(block, size); - if (block == NULL) { - if (L) - luaD_breakrun(L, LUA_ERRMEM); /* break run without error message */ - else return NULL; /* error before creating state! */ - } - return block; -} - - diff --git a/src/lua/lmem.h b/src/lua/lmem.h deleted file mode 100644 index 0d27c336..00000000 --- a/src/lua/lmem.h +++ /dev/null @@ -1,42 +0,0 @@ -/* -** $Id: lmem.h,v 1.3 2001/11/26 23:00:24 darkgod Exp $ -** Interface to Memory Manager -** See Copyright Notice in lua.h -*/ - -#ifndef lmem_h -#define lmem_h - - -#include - -#include "llimits.h" -#include "lua.h" - -void *luaM_realloc (lua_State *L, void *oldblock, lint32 size); -void *luaM_growaux (lua_State *L, void *block, size_t nelems, - int inc, size_t size, const char *errormsg, - size_t limit); - -#define luaM_free(L, b) luaM_realloc(L, (b), 0) -#define luaM_malloc(L, t) luaM_realloc(L, NULL, (t)) -#define luaM_new(L, t) ((t *)luaM_malloc(L, sizeof(t))) -#define luaM_newvector(L, n,t) ((t *)luaM_malloc(L, (n)*(lint32)sizeof(t))) - -#define luaM_growvector(L, v,nelems,inc,t,e,l) \ - ((v)=(t *)luaM_growaux(L, v,nelems,inc,sizeof(t),e,l)) - -#define luaM_reallocvector(L, v,n,t) \ - ((v)=(t *)luaM_realloc(L, v,(n)*(lint32)sizeof(t))) - - -#ifdef LUA_DEBUG -extern unsigned long memdebug_numblocks; -extern unsigned long memdebug_total; -extern unsigned long memdebug_maxmem; -extern unsigned long memdebug_memlimit; -#endif - - -#endif - diff --git a/src/lua/lobject.c b/src/lua/lobject.c deleted file mode 100644 index cd9d1f0b..00000000 --- a/src/lua/lobject.c +++ /dev/null @@ -1,125 +0,0 @@ -/* -** $Id: lobject.c,v 1.3 2001/11/26 23:00:24 darkgod Exp $ -** Some generic functions over Lua objects -** See Copyright Notice in lua.h -*/ - -#include -#include -#include -#include -#include - -#include "lua.h" - -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" - - - -const TObject luaO_nilobject = {LUA_TNIL, {NULL}}; - - -const char *const luaO_typenames[] = { - "userdata", "nil", "number", "string", "table", "function" -}; - - - -/* -** returns smaller power of 2 larger than `n' (minimum is MINPOWER2) -*/ -lint32 luaO_power2 (lint32 n) { - lint32 p = MINPOWER2; - while (p<=n) p<<=1; - return p; -} - - -int luaO_equalObj (const TObject *t1, const TObject *t2) { - if (ttype(t1) != ttype(t2)) return 0; - switch (ttype(t1)) { - case LUA_TNUMBER: - return nvalue(t1) == nvalue(t2); - case LUA_TSTRING: case LUA_TUSERDATA: - return tsvalue(t1) == tsvalue(t2); - case LUA_TTABLE: - return hvalue(t1) == hvalue(t2); - case LUA_TFUNCTION: - return clvalue(t1) == clvalue(t2); - default: - LUA_ASSERT(ttype(t1) == LUA_TNIL, "invalid type"); - return 1; /* LUA_TNIL */ - } -} - - -char *luaO_openspace (lua_State *L, size_t n) { - if (n > L->Mbuffsize) { - luaM_reallocvector(L, L->Mbuffer, n, char); - L->nblocks += (n - L->Mbuffsize)*sizeof(char); - L->Mbuffsize = n; - } - return L->Mbuffer; -} - - -int luaO_str2d (const char *s, Number *result) { /* LUA_NUMBER */ - char *endptr; - Number res = lua_str2number(s, &endptr); - if (endptr == s) return 0; /* no conversion */ - while (isspace((unsigned char)*endptr)) endptr++; - if (*endptr != '\0') return 0; /* invalid trailing characters? */ - *result = res; - return 1; -} - - -/* maximum length of a string format for `luaO_verror' */ -#define MAX_VERROR 280 - -/* this function needs to handle only '%d' and '%.XXs' formats */ -void luaO_verror (lua_State *L, const char *fmt, ...) { - va_list argp; - char buff[MAX_VERROR]; /* to hold formatted message */ - va_start(argp, fmt); - vsprintf(buff, fmt, argp); - va_end(argp); - lua_error(L, buff); -} - - -void luaO_chunkid (char *out, const char *source, int bufflen) { - if (*source == '=') { - strncpy(out, source+1, bufflen); /* remove first char */ - out[bufflen-1] = '\0'; /* ensures null termination */ - } - else { - if (*source == '@') { - int l; - source++; /* skip the `@' */ - bufflen -= sizeof("file `...%s'"); - l = strlen(source); - if (l>bufflen) { - source += (l-bufflen); /* get last part of file name */ - sprintf(out, "file `...%.99s'", source); - } - else - sprintf(out, "file `%.99s'", source); - } - else { - int len = strcspn(source, "\n"); /* stop at first newline */ - bufflen -= sizeof("string \"%.*s...\""); - if (len > bufflen) len = bufflen; - if (source[len] != '\0') { /* must truncate? */ - strcpy(out, "string \""); - out += strlen(out); - strncpy(out, source, len); - strcpy(out+len, "...\""); - } - else - sprintf(out, "string \"%.99s\"", source); - } - } -} diff --git a/src/lua/lobject.h b/src/lua/lobject.h deleted file mode 100644 index ce978205..00000000 --- a/src/lua/lobject.h +++ /dev/null @@ -1,204 +0,0 @@ -/* -** $Id: lobject.h,v 1.3 2001/11/26 23:00:24 darkgod Exp $ -** Type definitions for Lua objects -** See Copyright Notice in lua.h -*/ - -#ifndef lobject_h -#define lobject_h - - -#include "llimits.h" -#include "lua.h" - - -#ifdef LUA_DEBUG -#undef NDEBUG -#include -#define LUA_INTERNALERROR(s) assert(((void)s,0)) -#define LUA_ASSERT(c,s) assert(((void)s,(c))) -#else -#define LUA_INTERNALERROR(s) /* empty */ -#define LUA_ASSERT(c,s) /* empty */ -#endif - - -#ifdef LUA_DEBUG -/* to avoid warnings, and make sure value is really unused */ -#define UNUSED(x) (x=0, (void)(x)) -#else -#define UNUSED(x) ((void)(x)) /* to avoid warnings */ -#endif - - -/* mark for closures active in the stack */ -#define LUA_TMARK 6 - - -/* tags for values visible from Lua == first user-created tag */ -#define NUM_TAGS 6 - - -/* check whether `t' is a mark */ -#define is_T_MARK(t) ((t) == LUA_TMARK) - - -typedef union { - struct TString *ts; /* LUA_TSTRING, LUA_TUSERDATA */ - struct Closure *cl; /* LUA_TFUNCTION */ - struct Hash *a; /* LUA_TTABLE */ - struct CallInfo *i; /* LUA_TLMARK */ - Number n; /* LUA_TNUMBER */ -} Value; - - -/* Macros to access values */ -#define ttype(o) ((o)->ttype) -#define nvalue(o) ((o)->value.n) -#define tsvalue(o) ((o)->value.ts) -#define clvalue(o) ((o)->value.cl) -#define hvalue(o) ((o)->value.a) -#define infovalue(o) ((o)->value.i) -#define svalue(o) (tsvalue(o)->str) - - -typedef struct lua_TObject { - int ttype; - Value value; -} TObject; - - -/* -** String headers for string table -*/ - -/* -** most `malloc' libraries allocate memory in blocks of 8 bytes. TSPACK -** tries to make sizeof(TString) a multiple of this granularity, to reduce -** waste of space. -*/ -#define TSPACK ((int)sizeof(int)) - -typedef struct TString { - union { - struct { /* for strings */ - unsigned long hash; - int constindex; /* hint to reuse constants */ - } s; - struct { /* for userdata */ - int tag; - void *value; - } d; - } u; - size_t len; - struct TString *nexthash; /* chain for hash table */ - int marked; - char str[TSPACK]; /* variable length string!! must be the last field! */ -} TString; - - -/* -** Function Prototypes -*/ -typedef struct Proto { - Number *knum; /* Number numbers used by the function */ - int nknum; /* size of `knum' */ - struct TString **kstr; /* strings used by the function */ - int nkstr; /* size of `kstr' */ - struct Proto **kproto; /* functions defined inside the function */ - int nkproto; /* size of `kproto' */ - Instruction *code; - int ncode; /* size of `code'; when 0 means an incomplete `Proto' */ - short numparams; - short is_vararg; - short maxstacksize; - short marked; - struct Proto *next; - /* debug information */ - int *lineinfo; /* map from opcodes to source lines */ - int nlineinfo; /* size of `lineinfo' */ - int nlocvars; - struct LocVar *locvars; /* information about local variables */ - int lineDefined; - TString *source; -} Proto; - - -typedef struct LocVar { - TString *varname; - int startpc; /* first point where variable is active */ - int endpc; /* first point where variable is dead */ -} LocVar; - - -/* -** Closures -*/ -typedef struct Closure { - union { - lua_CFunction c; /* C functions */ - struct Proto *l; /* Lua functions */ - } f; - struct Closure *next; - struct Closure *mark; /* marked closures (point to itself when not marked) */ - short isC; /* 0 for Lua functions, 1 for C functions */ - short nupvalues; - TObject upvalue[1]; -} Closure; - - -#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->isC) - - -typedef struct Node { - TObject key; - TObject val; - struct Node *next; /* for chaining */ -} Node; - -typedef struct Hash { - Node *node; - int htag; - int size; - Node *firstfree; /* this position is free; all positions after it are full */ - struct Hash *next; - struct Hash *mark; /* marked tables (point to itself when not marked) */ -} Hash; - - -/* unmarked tables and closures are represented by pointing `mark' to -** themselves -*/ -#define ismarked(x) ((x)->mark != (x)) - - -/* -** informations about a call (for debugging) -*/ -typedef struct CallInfo { - struct Closure *func; /* function being called */ - const Instruction **pc; /* current pc of called function */ - int lastpc; /* last pc traced */ - int line; /* current line */ - int refi; /* current index in `lineinfo' */ -} CallInfo; - - -extern const TObject luaO_nilobject; -extern const char *const luaO_typenames[]; - - -#define luaO_typename(o) (luaO_typenames[ttype(o)]) - - -lint32 luaO_power2 (lint32 n); -char *luaO_openspace (lua_State *L, size_t n); - -int luaO_equalObj (const TObject *t1, const TObject *t2); -int luaO_str2d (const char *s, Number *result); - -void luaO_verror (lua_State *L, const char *fmt, ...); -void luaO_chunkid (char *out, const char *source, int len); - - -#endif diff --git a/src/lua/lopcodes.h b/src/lua/lopcodes.h deleted file mode 100644 index 59740896..00000000 --- a/src/lua/lopcodes.h +++ /dev/null @@ -1,168 +0,0 @@ -/* -** $Id: lopcodes.h,v 1.5 2004/06/04 13:42:10 neil Exp $ -** Opcodes for Lua virtual machine -** See Copyright Notice in lua.h -*/ - -#ifndef lopcodes_h -#define lopcodes_h - -#include "llimits.h" - - -/*=========================================================================== - We assume that instructions are unsigned numbers. - All instructions have an opcode in the first 6 bits. Moreover, - an instruction can have 0, 1, or 2 arguments. Instructions can - have the following types: - type 0: no arguments - type 1: 1 unsigned argument in the higher bits (called `U') - type 2: 1 signed argument in the higher bits (`S') - type 3: 1st unsigned argument in the higher bits (`A') - 2nd unsigned argument in the middle bits (`B') - - A signed argument is represented in excess K; that is, the number - value is the unsigned value minus K. K is exactly the maximum value - for that argument (so that -max is represented by 0, and +max is - represented by 2*max), which is half the maximum for the corresponding - unsigned argument. - - The size of each argument is defined in `llimits.h'. The usual is an - instruction with 32 bits, U arguments with 26 bits (32-6), B arguments - with 9 bits, and A arguments with 17 bits (32-6-9). For small - installations, the instruction size can be 16, so U has 10 bits, - and A and B have 5 bits each. -===========================================================================*/ - - - - -/* creates a mask with `n' 1 bits at position `p' */ -#define MASK1(n,p) ((~((~(Instruction)0)<>POS_U)) -#define SETARG_U(i,u) ((i) = (((i)&MASK0(SIZE_U,POS_U)) | \ - ((Instruction)(u)<>POS_A)) -#define SETARG_A(i,a) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ - ((Instruction)(a)<>POS_B) & MASK1(SIZE_B,0))) -#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ - ((Instruction)(b)<y)? PC+=s */ -OP_JMPGE,/* J y x - (x>=y)? PC+=s */ - -OP_JMPT,/* J x - (x~=nil)? PC+=s */ -OP_JMPF,/* J x - (x==nil)? PC+=s */ -OP_JMPONT,/* J x (x~=nil)? x : - (x~=nil)? PC+=s */ -OP_JMPONF,/* J x (x==nil)? x : - (x==nil)? PC+=s */ -OP_JMP,/* J - - PC+=s */ - -OP_PUSHNILJMP,/* - - nil PC++; */ - -OP_FORPREP,/* J */ -OP_FORLOOP,/* J */ - -OP_LFORPREP,/* J */ -OP_LFORLOOP,/* J */ - -OP_CLOSURE/* A B v_b-v_1 closure(KPROTO[a], v_1-v_b) */ - -} OpCode; - -#define NUM_OPCODES ((int)OP_CLOSURE+1) - - -#define ISJUMP(o) (OP_JMPNE <= (o) && (o) <= OP_JMP) - - - -/* special code to fit a LUA_MULTRET inside an argB */ -#define MULT_RET 255 /* (<=MAXARG_B) */ -#if MULT_RET>MAXARG_B -#undef MULT_RET -#define MULT_RET MAXARG_B -#endif - - -#endif diff --git a/src/lua/lparser.c b/src/lua/lparser.c deleted file mode 100644 index 1ac1f37b..00000000 --- a/src/lua/lparser.c +++ /dev/null @@ -1,1129 +0,0 @@ -/* -** $Id: lparser.c,v 1.8 2004/06/04 13:42:10 neil Exp $ -** LL(1) Parser and code generator for Lua -** See Copyright Notice in lua.h -*/ - - -#include -#include - -#include "lua.h" - -#include "lcode.h" -#include "lfunc.h" -#include "llex.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" - -#ifdef __MWERKS__ -/* To avoid name conflict resulting from the use of prefix header */ -#define stat lua_hack_stat -#endif /* __MWERKS__ */ - - -/* -** Constructors descriptor: -** `n' indicates number of elements, and `k' signals whether -** it is a list constructor (k = 0) or a record constructor (k = 1) -** or empty (k = ';' or '}') -*/ -typedef struct Constdesc { - int n; - int k; -} Constdesc; - - -typedef struct Breaklabel { - struct Breaklabel *previous; /* chain */ - int breaklist; - int stacklevel; -} Breaklabel; - - - - -/* -** prototypes for recursive non-terminal functions -*/ -static void body (LexState *ls, int needself, int line); -static void chunk (LexState *ls); -static void constructor (LexState *ls); -static void expr (LexState *ls, expdesc *v); -static void exp1 (LexState *ls); - - - -static void next (LexState *ls) { - ls->lastline = ls->linenumber; - if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ - ls->t = ls->lookahead; /* use this one */ - ls->lookahead.token = TK_EOS; /* and discharge it */ - } - else - ls->t.token = luaX_lex(ls, &ls->t.seminfo); /* read next token */ -} - - -static void lookahead (LexState *ls) { - LUA_ASSERT(ls->lookahead.token == TK_EOS, "two look-aheads"); - ls->lookahead.token = luaX_lex(ls, &ls->lookahead.seminfo); -} - - -static void error_expected (LexState *ls, int token) { - char buff[100], t[TOKEN_LEN]; - luaX_token2str(token, t); - sprintf(buff, "`%.20s' expected", t); - luaK_error(ls, buff); -} - - -static void check (LexState *ls, int c) { - if (ls->t.token != c) - error_expected(ls, c); - next(ls); -} - - -static void check_condition (LexState *ls, int c, const char *msg) { - if (!c) luaK_error(ls, msg); -} - - -static int optional (LexState *ls, int c) { - if (ls->t.token == c) { - next(ls); - return 1; - } - else return 0; -} - - -static void check_match (LexState *ls, int what, int who, int where) { - if (ls->t.token != what) { - if (where == ls->linenumber) - error_expected(ls, what); - else { - char buff[100]; - char t_what[TOKEN_LEN], t_who[TOKEN_LEN]; - luaX_token2str(what, t_what); - luaX_token2str(who, t_who); - sprintf(buff, "`%.20s' expected (to close `%.20s' at line %d)", - t_what, t_who, where); - luaK_error(ls, buff); - } - } - next(ls); -} - - -static int string_constant (FuncState *fs, TString *s) { - Proto *f = fs->f; - int c = s->u.s.constindex; - if (c >= f->nkstr || f->kstr[c] != s) { - luaM_growvector(fs->L, f->kstr, f->nkstr, 1, TString *, - "constant table overflow", MAXARG_U); - c = f->nkstr++; - f->kstr[c] = s; - s->u.s.constindex = c; /* hint for next time */ - } - return c; -} - - -static void code_string (LexState *ls, TString *s) { - luaK_kstr(ls, string_constant(ls->fs, s)); -} - - -static TString *str_checkname (LexState *ls) { - TString *ts; - check_condition(ls, (ls->t.token == TK_NAME), " expected"); - ts = ls->t.seminfo.ts; - next(ls); - return ts; -} - - -static int checkname (LexState *ls) { - return string_constant(ls->fs, str_checkname(ls)); -} - - -static int luaI_registerlocalvar (LexState *ls, TString *varname) { - Proto *f = ls->fs->f; - luaM_growvector(ls->L, f->locvars, f->nlocvars, 1, LocVar, "", MAX_INT); - f->locvars[f->nlocvars].varname = varname; - return f->nlocvars++; -} - - -static void new_localvar (LexState *ls, TString *name, int n) { - FuncState *fs = ls->fs; - luaX_checklimit(ls, fs->nactloc+n+1, MAXLOCALS, "local variables"); - fs->actloc[fs->nactloc+n] = luaI_registerlocalvar(ls, name); -} - - -static void adjustlocalvars (LexState *ls, int nvars) { - FuncState *fs = ls->fs; - while (nvars--) - fs->f->locvars[fs->actloc[fs->nactloc++]].startpc = fs->pc; -} - - -static void removelocalvars (LexState *ls, int nvars) { - FuncState *fs = ls->fs; - while (nvars--) - fs->f->locvars[fs->actloc[--fs->nactloc]].endpc = fs->pc; -} - - -static void new_localvarstr (LexState *ls, const char *name, int n) { - new_localvar(ls, luaS_newfixed(ls->L, name), n); -} - - -static int search_local (LexState *ls, TString *n, expdesc *var) { - FuncState *fs; - int level = 0; - for (fs=ls->fs; fs; fs=fs->prev) { - int i; - for (i=fs->nactloc-1; i >= 0; i--) { - if (n == fs->f->locvars[fs->actloc[i]].varname) { - var->k = VLOCAL; - var->u.index = i; - return level; - } - } - level++; /* `var' not found; check outer level */ - } - var->k = VGLOBAL; /* not found in any level; must be global */ - return -1; -} - - -static void singlevar (LexState *ls, TString *n, expdesc *var) { - int level = search_local(ls, n, var); - if (level >= 1) /* neither local (0) nor global (-1)? */ - luaX_syntaxerror(ls, "cannot access a variable in outer scope", n->str); - else if (level == -1) /* global? */ - var->u.index = string_constant(ls->fs, n); -} - - -static int indexupvalue (LexState *ls, expdesc *v) { - FuncState *fs = ls->fs; - int i; - for (i=0; inupvalues; i++) { - if (fs->upvalues[i].k == v->k && fs->upvalues[i].u.index == v->u.index) - return i; - } - /* new one */ - luaX_checklimit(ls, fs->nupvalues+1, MAXUPVALUES, "upvalues"); - fs->upvalues[fs->nupvalues] = *v; - return fs->nupvalues++; -} - - -static void pushupvalue (LexState *ls, TString *n) { - FuncState *fs = ls->fs; - expdesc v; - int level = search_local(ls, n, &v); - if (level == -1) { /* global? */ - if (fs->prev == NULL) - luaX_syntaxerror(ls, "cannot access upvalue in main", n->str); - v.u.index = string_constant(fs->prev, n); - } - else if (level != 1) - luaX_syntaxerror(ls, - "upvalue must be global or local to immediately outer scope", n->str); - luaK_code1(fs, OP_PUSHUPVALUE, indexupvalue(ls, &v)); -} - - -static void adjust_mult_assign (LexState *ls, int nvars, int nexps) { - FuncState *fs = ls->fs; - int diff = nexps - nvars; - if (nexps > 0 && luaK_lastisopen(fs)) { /* list ends in a function call */ - diff--; /* do not count function call itself */ - if (diff <= 0) { /* more variables than values? */ - luaK_setcallreturns(fs, -diff); /* function call provide extra values */ - diff = 0; /* no more difference */ - } - else /* more values than variables */ - luaK_setcallreturns(fs, 0); /* call should provide no value */ - } - /* push or pop eventual difference between list lengths */ - luaK_adjuststack(fs, diff); -} - - -static void code_params (LexState *ls, int nparams, int dots) { - FuncState *fs = ls->fs; - adjustlocalvars(ls, nparams); - luaX_checklimit(ls, fs->nactloc, MAXPARAMS, "parameters"); - fs->f->numparams = fs->nactloc; /* `self' could be there already */ - fs->f->is_vararg = dots; - if (dots) { - new_localvarstr(ls, "arg", 0); - adjustlocalvars(ls, 1); - } - luaK_deltastack(fs, fs->nactloc); /* count parameters in the stack */ -} - - -static void enterbreak (FuncState *fs, Breaklabel *bl) { - bl->stacklevel = fs->stacklevel; - bl->breaklist = NO_JUMP; - bl->previous = fs->bl; - fs->bl = bl; -} - - -static void leavebreak (FuncState *fs, Breaklabel *bl) { - fs->bl = bl->previous; - LUA_ASSERT(bl->stacklevel == fs->stacklevel, "wrong levels"); - luaK_patchlist(fs, bl->breaklist, luaK_getlabel(fs)); -} - - -static void pushclosure (LexState *ls, FuncState *func) { - FuncState *fs = ls->fs; - Proto *f = fs->f; - int i; - for (i=0; inupvalues; i++) - luaK_tostack(ls, &func->upvalues[i], 1); - luaM_growvector(ls->L, f->kproto, f->nkproto, 1, Proto *, - "constant table overflow", MAXARG_A); - f->kproto[f->nkproto++] = func->f; - luaK_code2(fs, OP_CLOSURE, f->nkproto-1, func->nupvalues); -} - - -static void open_func (LexState *ls, FuncState *fs) { - Proto *f = luaF_newproto(ls->L); - fs->prev = ls->fs; /* linked list of funcstates */ - fs->ls = ls; - fs->L = ls->L; - ls->fs = fs; - fs->stacklevel = 0; - fs->nactloc = 0; - fs->nupvalues = 0; - fs->bl = NULL; - fs->f = f; - f->source = ls->source; - fs->pc = 0; - fs->lasttarget = 0; - fs->lastline = 0; - fs->jlt = NO_JUMP; - f->code = NULL; - f->maxstacksize = 0; - f->numparams = 0; /* default for main chunk */ - f->is_vararg = 0; /* default for main chunk */ -} - - -static void close_func (LexState *ls) { - lua_State *L = ls->L; - FuncState *fs = ls->fs; - Proto *f = fs->f; - luaK_code0(fs, OP_END); - luaK_getlabel(fs); /* close eventual list of pending jumps */ - luaM_reallocvector(L, f->code, fs->pc, Instruction); - luaM_reallocvector(L, f->kstr, f->nkstr, TString *); - luaM_reallocvector(L, f->knum, f->nknum, Number); - luaM_reallocvector(L, f->kproto, f->nkproto, Proto *); - removelocalvars(ls, fs->nactloc); - luaM_reallocvector(L, f->locvars, f->nlocvars, LocVar); - luaM_reallocvector(L, f->lineinfo, f->nlineinfo+1, int); - f->lineinfo[f->nlineinfo++] = MAX_INT; /* end flag */ - luaF_protook(L, f, fs->pc); /* proto is ok now */ - ls->fs = fs->prev; - LUA_ASSERT(fs->bl == NULL, "wrong list end"); -} - - -Proto *luaY_parser (lua_State *L, ZIO *z) { - struct LexState lexstate; - struct FuncState funcstate; - luaX_setinput(L, &lexstate, z, luaS_new(L, zname(z))); - open_func(&lexstate, &funcstate); - next(&lexstate); /* read first token */ - chunk(&lexstate); - check_condition(&lexstate, (lexstate.t.token == TK_EOS), " expected"); - close_func(&lexstate); - LUA_ASSERT(funcstate.prev == NULL, "wrong list end"); - LUA_ASSERT(funcstate.nupvalues == 0, "no upvalues in main"); - return funcstate.f; -} - - - -/*============================================================*/ -/* GRAMMAR RULES */ -/*============================================================*/ - - -static int explist1 (LexState *ls) { - /* explist1 -> expr { ',' expr } */ - int n = 1; /* at least one expression */ - expdesc v; - expr(ls, &v); - while (ls->t.token == ',') { - luaK_tostack(ls, &v, 1); /* gets only 1 value from previous expression */ - next(ls); /* skip comma */ - expr(ls, &v); - n++; - } - luaK_tostack(ls, &v, 0); /* keep open number of values of last expression */ - return n; -} - - -static void funcargs (LexState *ls, int slf) { - FuncState *fs = ls->fs; - int slevel = fs->stacklevel - slf - 1; /* where is func in the stack */ - switch (ls->t.token) { - case '(': { /* funcargs -> '(' [ explist1 ] ')' */ - int line = ls->linenumber; - int nargs = 0; - next(ls); - if (ls->t.token != ')') /* arg list not empty? */ - nargs = explist1(ls); - check_match(ls, ')', '(', line); -#ifdef LUA_COMPAT_ARGRET - if (nargs > 0) /* arg list is not empty? */ - luaK_setcallreturns(fs, 1); /* last call returns only 1 value */ -#else - UNUSED(nargs); /* to avoid warnings */ -#endif - break; - } - case '{': { /* funcargs -> constructor */ - constructor(ls); - break; - } - case TK_STRING: { /* funcargs -> STRING */ - code_string(ls, ls->t.seminfo.ts); /* must use `seminfo' before `next' */ - next(ls); - break; - } - default: { - luaK_error(ls, "function arguments expected"); - break; - } - } - fs->stacklevel = slevel; /* call will remove function and arguments */ - luaK_code2(fs, OP_CALL, slevel, MULT_RET); -} - - -static void var_or_func_tail (LexState *ls, expdesc *v) { - for (;;) { - switch (ls->t.token) { - case '.': { /* var_or_func_tail -> '.' NAME */ - next(ls); - luaK_tostack(ls, v, 1); /* `v' must be on stack */ - luaK_kstr(ls, checkname(ls)); - v->k = VINDEXED; - break; - } - case '[': { /* var_or_func_tail -> '[' exp1 ']' */ - next(ls); - luaK_tostack(ls, v, 1); /* `v' must be on stack */ - v->k = VINDEXED; - exp1(ls); - check(ls, ']'); - break; - } - case ':': { /* var_or_func_tail -> ':' NAME funcargs */ - int name; - next(ls); - name = checkname(ls); - luaK_tostack(ls, v, 1); /* `v' must be on stack */ - luaK_code1(ls->fs, OP_PUSHSELF, name); - funcargs(ls, 1); - v->k = VEXP; - v->u.l.t = v->u.l.f = NO_JUMP; - break; - } - case '(': case TK_STRING: case '{': { /* var_or_func_tail -> funcargs */ - luaK_tostack(ls, v, 1); /* `v' must be on stack */ - funcargs(ls, 0); - v->k = VEXP; - v->u.l.t = v->u.l.f = NO_JUMP; - break; - } - default: return; /* should be follow... */ - } - } -} - - -static void var_or_func (LexState *ls, expdesc *v) { - /* var_or_func -> ['%'] NAME var_or_func_tail */ - if (optional(ls, '%')) { /* upvalue? */ - pushupvalue(ls, str_checkname(ls)); - v->k = VEXP; - v->u.l.t = v->u.l.f = NO_JUMP; - } - else /* variable name */ - singlevar(ls, str_checkname(ls), v); - var_or_func_tail(ls, v); -} - - - -/* -** {====================================================================== -** Rules for Constructors -** ======================================================================= -*/ - - -static void recfield (LexState *ls) { - /* recfield -> (NAME | '['exp1']') = exp1 */ - switch (ls->t.token) { - case TK_NAME: { - luaK_kstr(ls, checkname(ls)); - break; - } - case '[': { - next(ls); - exp1(ls); - check(ls, ']'); - break; - } - default: luaK_error(ls, " or `[' expected"); - } - check(ls, '='); - exp1(ls); -} - - -static int recfields (LexState *ls) { - /* recfields -> recfield { ',' recfield } [','] */ - FuncState *fs = ls->fs; - int n = 1; /* at least one element */ - recfield(ls); - while (ls->t.token == ',') { - next(ls); - if (ls->t.token == ';' || ls->t.token == '}') - break; - recfield(ls); - n++; - if (n%RFIELDS_PER_FLUSH == 0) - luaK_code1(fs, OP_SETMAP, RFIELDS_PER_FLUSH); - } - luaK_code1(fs, OP_SETMAP, n%RFIELDS_PER_FLUSH); - return n; -} - - -static int listfields (LexState *ls) { - /* listfields -> exp1 { ',' exp1 } [','] */ - FuncState *fs = ls->fs; - int n = 1; /* at least one element */ - exp1(ls); - while (ls->t.token == ',') { - next(ls); - if (ls->t.token == ';' || ls->t.token == '}') - break; - exp1(ls); - n++; - luaX_checklimit(ls, n/LFIELDS_PER_FLUSH, MAXARG_A, - "`item groups' in a list initializer"); - if (n%LFIELDS_PER_FLUSH == 0) - luaK_code2(fs, OP_SETLIST, n/LFIELDS_PER_FLUSH - 1, LFIELDS_PER_FLUSH); - } - luaK_code2(fs, OP_SETLIST, n/LFIELDS_PER_FLUSH, n%LFIELDS_PER_FLUSH); - return n; -} - - - -static void constructor_part (LexState *ls, Constdesc *cd) { - switch (ls->t.token) { - case ';': case '}': { /* constructor_part -> empty */ - cd->n = 0; - cd->k = ls->t.token; - break; - } - case TK_NAME: { /* may be listfields or recfields */ - lookahead(ls); - if (ls->lookahead.token != '=') /* expression? */ - goto case_default; - /* else go through to recfields */ - } - case '[': { /* constructor_part -> recfields */ - cd->n = recfields(ls); - cd->k = 1; /* record */ - break; - } - default: { /* constructor_part -> listfields */ - case_default: - cd->n = listfields(ls); - cd->k = 0; /* list */ - break; - } - } -} - - -static void constructor (LexState *ls) { - /* constructor -> '{' constructor_part [';' constructor_part] '}' */ - FuncState *fs = ls->fs; - int line = ls->linenumber; - int pc = luaK_code1(fs, OP_CREATETABLE, 0); - int nelems; - Constdesc cd; - check(ls, '{'); - constructor_part(ls, &cd); - nelems = cd.n; - if (optional(ls, ';')) { - Constdesc other_cd; - constructor_part(ls, &other_cd); - check_condition(ls, (cd.k != other_cd.k), "invalid constructor syntax"); - nelems += other_cd.n; - } - check_match(ls, '}', '{', line); - luaX_checklimit(ls, nelems, MAXARG_U, "elements in a table constructor"); - SETARG_U(fs->f->code[pc], nelems); /* set initial table size */ -} - -/* }====================================================================== */ - - - - -/* -** {====================================================================== -** Expression parsing -** ======================================================================= -*/ - - -static void simpleexp (LexState *ls, expdesc *v) { - FuncState *fs = ls->fs; - switch (ls->t.token) { - case TK_NUMBER: { /* simpleexp -> NUMBER */ - Number r = ls->t.seminfo.r; - next(ls); - luaK_number(fs, r); - break; - } - case TK_STRING: { /* simpleexp -> STRING */ - code_string(ls, ls->t.seminfo.ts); /* must use `seminfo' before `next' */ - next(ls); - break; - } - case TK_NIL: { /* simpleexp -> NIL */ - luaK_adjuststack(fs, -1); - next(ls); - break; - } - case '{': { /* simpleexp -> constructor */ - constructor(ls); - break; - } - case TK_FUNCTION: { /* simpleexp -> FUNCTION body */ - next(ls); - body(ls, 0, ls->linenumber); - break; - } - case '(': { /* simpleexp -> '(' expr ')' */ - next(ls); - expr(ls, v); - check(ls, ')'); - return; - } - case TK_NAME: case '%': { - var_or_func(ls, v); - return; - } - default: { - luaK_error(ls, " expected"); - return; - } - } - v->k = VEXP; - v->u.l.t = v->u.l.f = NO_JUMP; -} - - -static void exp1 (LexState *ls) { - expdesc v; - expr(ls, &v); - luaK_tostack(ls, &v, 1); -} - - -static UnOpr getunopr (int op) { - switch (op) { - case TK_NOT: return OPR_NOT; - case '-': return OPR_MINUS; - default: return OPR_NOUNOPR; - } -} - - -static BinOpr getbinopr (int op) { - switch (op) { - case '+': return OPR_ADD; - case '-': return OPR_SUB; - case '*': return OPR_MULT; - case '/': return OPR_DIV; - case '^': return OPR_POW; - case TK_CONCAT: return OPR_CONCAT; - case TK_NE: return OPR_NE; - case TK_EQ: return OPR_EQ; - case '<': return OPR_LT; - case TK_LE: return OPR_LE; - case '>': return OPR_GT; - case TK_GE: return OPR_GE; - case TK_AND: return OPR_AND; - case TK_OR: return OPR_OR; - default: return OPR_NOBINOPR; - } -} - - -static const struct { - char left; /* left priority for each binary operator */ - char right; /* right priority */ -} priority[] = { /* ORDER OPR */ - {5, 5}, {5, 5}, {6, 6}, {6, 6}, /* arithmetic */ - {9, 8}, {4, 3}, /* power and concat (right associative) */ - {2, 2}, {2, 2}, /* equality */ - {2, 2}, {2, 2}, {2, 2}, {2, 2}, /* order */ - {1, 1}, {1, 1} /* logical */ -}; - -#define UNARY_PRIORITY 7 /* priority for unary operators */ - - -/* -** subexpr -> (simplexep | unop subexpr) { binop subexpr } -** where `binop' is any binary operator with a priority higher than `limit' -*/ -static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { - BinOpr op; - UnOpr uop = getunopr(ls->t.token); - if (uop != OPR_NOUNOPR) { - next(ls); - subexpr(ls, v, UNARY_PRIORITY); - luaK_prefix(ls, uop, v); - } - else simpleexp(ls, v); - /* expand while operators have priorities higher than `limit' */ - op = getbinopr(ls->t.token); - while (op != OPR_NOBINOPR && priority[op].left > limit) { - expdesc v2; - BinOpr nextop; - next(ls); - luaK_infix(ls, op, v); - /* read sub-expression with higher priority */ - nextop = subexpr(ls, &v2, priority[op].right); - luaK_posfix(ls, op, v, &v2); - op = nextop; - } - return op; /* return first untreated operator */ -} - - -static void expr (LexState *ls, expdesc *v) { - subexpr(ls, v, -1); -} - -/* }==================================================================== */ - - -/* -** {====================================================================== -** Rules for Statements -** ======================================================================= -*/ - - -static int block_follow (int token) { - switch (token) { - case TK_ELSE: case TK_ELSEIF: case TK_END: - case TK_UNTIL: case TK_EOS: - return 1; - default: return 0; - } -} - - -static void block (LexState *ls) { - /* block -> chunk */ - FuncState *fs = ls->fs; - int nactloc = fs->nactloc; - chunk(ls); - luaK_adjuststack(fs, fs->nactloc - nactloc); /* remove local variables */ - removelocalvars(ls, fs->nactloc - nactloc); -} - - -static int assignment (LexState *ls, expdesc *v, int nvars) { - int left = 0; /* number of values left in the stack after assignment */ - luaX_checklimit(ls, nvars, MAXVARSLH, "variables in a multiple assignment"); - if (ls->t.token == ',') { /* assignment -> ',' NAME assignment */ - expdesc nv; - next(ls); - var_or_func(ls, &nv); - check_condition(ls, (nv.k != VEXP), "syntax error"); - left = assignment(ls, &nv, nvars+1); - } - else { /* assignment -> '=' explist1 */ - int nexps; - check(ls, '='); - nexps = explist1(ls); - adjust_mult_assign(ls, nvars, nexps); - } - if (v->k != VINDEXED) - luaK_storevar(ls, v); - else { /* there may be garbage between table-index and value */ - luaK_code2(ls->fs, OP_SETTABLE, left+nvars+2, 1); - left += 2; - } - return left; -} - - -static void cond (LexState *ls, expdesc *v) { - /* cond -> exp */ - expr(ls, v); /* read condition */ - luaK_goiftrue(ls->fs, v, 0); -} - - -static void whilestat (LexState *ls, int line) { - /* whilestat -> WHILE cond DO block END */ - FuncState *fs = ls->fs; - int while_init = luaK_getlabel(fs); - expdesc v; - Breaklabel bl; - enterbreak(fs, &bl); - next(ls); - cond(ls, &v); - check(ls, TK_DO); - block(ls); - luaK_patchlist(fs, luaK_jump(fs), while_init); - luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); - check_match(ls, TK_END, TK_WHILE, line); - leavebreak(fs, &bl); -} - - -static void repeatstat (LexState *ls, int line) { - /* repeatstat -> REPEAT block UNTIL cond */ - FuncState *fs = ls->fs; - int repeat_init = luaK_getlabel(fs); - expdesc v; - Breaklabel bl; - enterbreak(fs, &bl); - next(ls); - block(ls); - check_match(ls, TK_UNTIL, TK_REPEAT, line); - cond(ls, &v); - luaK_patchlist(fs, v.u.l.f, repeat_init); - leavebreak(fs, &bl); -} - - -static void forbody (LexState *ls, int nvar, OpCode prepfor, OpCode loopfor) { - /* forbody -> DO block END */ - FuncState *fs = ls->fs; - int prep = luaK_code1(fs, prepfor, NO_JUMP); - int blockinit = luaK_getlabel(fs); - check(ls, TK_DO); - adjustlocalvars(ls, nvar); /* scope for control variables */ - block(ls); - luaK_patchlist(fs, luaK_code1(fs, loopfor, NO_JUMP), blockinit); - luaK_patchlist(fs, prep, luaK_getlabel(fs)); - removelocalvars(ls, nvar); -} - - -static void fornum (LexState *ls, TString *varname) { - /* fornum -> NAME = exp1,exp1[,exp1] forbody */ - FuncState *fs = ls->fs; - check(ls, '='); - exp1(ls); /* initial value */ - check(ls, ','); - exp1(ls); /* limit */ - if (optional(ls, ',')) - exp1(ls); /* optional step */ - else - luaK_code1(fs, OP_PUSHINT, 1); /* default step */ - new_localvar(ls, varname, 0); - new_localvarstr(ls, "(limit)", 1); - new_localvarstr(ls, "(step)", 2); - forbody(ls, 3, OP_FORPREP, OP_FORLOOP); -} - - -static void forlist (LexState *ls, TString *indexname) { - /* forlist -> NAME,NAME IN exp1 forbody */ - TString *valname; - check(ls, ','); - valname = str_checkname(ls); - /* next test is dirty, but avoids `in' being a reserved word */ - check_condition(ls, - (ls->t.token == TK_NAME && ls->t.seminfo.ts == luaS_new(ls->L, "in")), - "`in' expected"); - next(ls); /* skip `in' */ - exp1(ls); /* table */ - new_localvarstr(ls, "(table)", 0); - new_localvar(ls, indexname, 1); - new_localvar(ls, valname, 2); - forbody(ls, 3, OP_LFORPREP, OP_LFORLOOP); -} - - -static void forstat (LexState *ls, int line) { - /* forstat -> fornum | forlist */ - FuncState *fs = ls->fs; - TString *varname; - Breaklabel bl; - enterbreak(fs, &bl); - next(ls); /* skip `for' */ - varname = str_checkname(ls); /* first variable name */ - switch (ls->t.token) { - case '=': fornum(ls, varname); break; - case ',': forlist(ls, varname); break; - default: luaK_error(ls, "`=' or `,' expected"); - } - check_match(ls, TK_END, TK_FOR, line); - leavebreak(fs, &bl); -} - - -static void test_then_block (LexState *ls, expdesc *v) { - /* test_then_block -> [IF | ELSEIF] cond THEN block */ - next(ls); /* skip IF or ELSEIF */ - cond(ls, v); - check(ls, TK_THEN); - block(ls); /* `then' part */ -} - - -static void ifstat (LexState *ls, int line) { - /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ - FuncState *fs = ls->fs; - expdesc v; - int escapelist = NO_JUMP; - test_then_block(ls, &v); /* IF cond THEN block */ - while (ls->t.token == TK_ELSEIF) { - luaK_concat(fs, &escapelist, luaK_jump(fs)); - luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); - test_then_block(ls, &v); /* ELSEIF cond THEN block */ - } - if (ls->t.token == TK_ELSE) { - luaK_concat(fs, &escapelist, luaK_jump(fs)); - luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); - next(ls); /* skip ELSE */ - block(ls); /* `else' part */ - } - else - luaK_concat(fs, &escapelist, v.u.l.f); - luaK_patchlist(fs, escapelist, luaK_getlabel(fs)); - check_match(ls, TK_END, TK_IF, line); -} - - -static void localstat (LexState *ls) { - /* stat -> LOCAL NAME {',' NAME} ['=' explist1] */ - int nvars = 0; - int nexps; - do { - next(ls); /* skip LOCAL or ',' */ - new_localvar(ls, str_checkname(ls), nvars++); - } while (ls->t.token == ','); - if (optional(ls, '=')) - nexps = explist1(ls); - else - nexps = 0; - adjust_mult_assign(ls, nvars, nexps); - adjustlocalvars(ls, nvars); -} - - -static int funcname (LexState *ls, expdesc *v) { - /* funcname -> NAME [':' NAME | '.' NAME] */ - int needself = 0; - singlevar(ls, str_checkname(ls), v); - if (ls->t.token == ':' || ls->t.token == '.') { - needself = (ls->t.token == ':'); - next(ls); - luaK_tostack(ls, v, 1); - luaK_kstr(ls, checkname(ls)); - v->k = VINDEXED; - } - return needself; -} - - -static void funcstat (LexState *ls, int line) { - /* funcstat -> FUNCTION funcname body */ - int needself; - expdesc v; - next(ls); /* skip FUNCTION */ - needself = funcname(ls, &v); - body(ls, needself, line); - luaK_storevar(ls, &v); -} - - -static void namestat (LexState *ls) { - /* stat -> func | ['%'] NAME assignment */ - FuncState *fs = ls->fs; - expdesc v; - var_or_func(ls, &v); - if (v.k == VEXP) { /* stat -> func */ - check_condition(ls, luaK_lastisopen(fs), "syntax error"); /* an upvalue? */ - luaK_setcallreturns(fs, 0); /* call statement uses no results */ - } - else { /* stat -> ['%'] NAME assignment */ - int left = assignment(ls, &v, 1); - luaK_adjuststack(fs, left); /* remove eventual garbage left on stack */ - } -} - - -static void retstat (LexState *ls) { - /* stat -> RETURN explist */ - FuncState *fs = ls->fs; - next(ls); /* skip RETURN */ - if (!block_follow(ls->t.token)) - explist1(ls); /* optional return values */ - luaK_code1(fs, OP_RETURN, ls->fs->nactloc); - fs->stacklevel = fs->nactloc; /* removes all temp values */ -} - - -static void breakstat (LexState *ls) { - /* stat -> BREAK [NAME] */ - FuncState *fs = ls->fs; - int currentlevel = fs->stacklevel; - Breaklabel *bl = fs->bl; - if (!bl) - luaK_error(ls, "no loop to break"); - next(ls); /* skip BREAK */ - luaK_adjuststack(fs, currentlevel - bl->stacklevel); - luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); - /* correct stack for compiler and symbolic execution */ - luaK_adjuststack(fs, bl->stacklevel - currentlevel); -} - - -static int stat (LexState *ls) { - int line = ls->linenumber; /* may be needed for error messages */ - switch (ls->t.token) { - case TK_IF: { /* stat -> ifstat */ - ifstat(ls, line); - return 0; - } - case TK_WHILE: { /* stat -> whilestat */ - whilestat(ls, line); - return 0; - } - case TK_DO: { /* stat -> DO block END */ - next(ls); /* skip DO */ - block(ls); - check_match(ls, TK_END, TK_DO, line); - return 0; - } - case TK_FOR: { /* stat -> forstat */ - forstat(ls, line); - return 0; - } - case TK_REPEAT: { /* stat -> repeatstat */ - repeatstat(ls, line); - return 0; - } - case TK_FUNCTION: { /* stat -> funcstat */ - funcstat(ls, line); - return 0; - } - case TK_LOCAL: { /* stat -> localstat */ - localstat(ls); - return 0; - } - case TK_NAME: case '%': { /* stat -> namestat */ - namestat(ls); - return 0; - } - case TK_RETURN: { /* stat -> retstat */ - retstat(ls); - return 1; /* must be last statement */ - } - case TK_BREAK: { /* stat -> breakstat */ - breakstat(ls); - return 1; /* must be last statement */ - } - default: { - luaK_error(ls, " expected"); - return 0; /* to avoid warnings */ - } - } -} - - -static void parlist (LexState *ls) { - /* parlist -> [ param { ',' param } ] */ - int nparams = 0; - int dots = 0; - if (ls->t.token != ')') { /* is `parlist' not empty? */ - do { - switch (ls->t.token) { - case TK_DOTS: next(ls); dots = 1; break; - case TK_NAME: new_localvar(ls, str_checkname(ls), nparams++); break; - default: luaK_error(ls, " or `...' expected"); - } - } while (!dots && optional(ls, ',')); - } - code_params(ls, nparams, dots); -} - - -static void body (LexState *ls, int needself, int line) { - /* body -> '(' parlist ')' chunk END */ - FuncState new_fs; - open_func(ls, &new_fs); - new_fs.f->lineDefined = line; - check(ls, '('); - if (needself) { - new_localvarstr(ls, "self", 0); - adjustlocalvars(ls, 1); - } - parlist(ls); - check(ls, ')'); - chunk(ls); - check_match(ls, TK_END, TK_FUNCTION, line); - close_func(ls); - pushclosure(ls, &new_fs); -} - - -/* }====================================================================== */ - - -static void chunk (LexState *ls) { - /* chunk -> { stat [';'] } */ - int islast = 0; - while (!islast && !block_follow(ls->t.token)) { - islast = stat(ls); - optional(ls, ';'); - LUA_ASSERT(ls->fs->stacklevel == ls->fs->nactloc, - "stack size != # local vars"); - } -} - diff --git a/src/lua/lparser.h b/src/lua/lparser.h deleted file mode 100644 index d83fb5f1..00000000 --- a/src/lua/lparser.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -** $Id: lparser.h,v 1.3 2001/11/26 23:00:26 darkgod Exp $ -** LL(1) Parser and code generator for Lua -** See Copyright Notice in lua.h -*/ - -#ifndef lparser_h -#define lparser_h - -#include "lobject.h" -#include "lzio.h" - - -/* -** Expression descriptor -*/ - -typedef enum { - VGLOBAL, - VLOCAL, - VINDEXED, - VEXP -} expkind; - -typedef struct expdesc { - expkind k; - union { - int index; /* VGLOBAL: `kstr' index of global name; VLOCAL: stack index */ - struct { - int t; /* patch list of `exit when true' */ - int f; /* patch list of `exit when false' */ - } l; - } u; -} expdesc; - - - -/* state needed to generate code for a given function */ -typedef struct FuncState { - Proto *f; /* current function header */ - struct FuncState *prev; /* enclosing function */ - struct LexState *ls; /* lexical state */ - struct lua_State *L; /* copy of the Lua state */ - int pc; /* next position to code */ - int lasttarget; /* `pc' of last `jump target' */ - int jlt; /* list of jumps to `lasttarget' */ - short stacklevel; /* number of values on activation register */ - short nactloc; /* number of active local variables */ - short nupvalues; /* number of upvalues */ - int lastline; /* line where last `lineinfo' was generated */ - struct Breaklabel *bl; /* chain of breakable blocks */ - expdesc upvalues[MAXUPVALUES]; /* upvalues */ - int actloc[MAXLOCALS]; /* local-variable stack (indices to locvars) */ -} FuncState; - - -Proto *luaY_parser (lua_State *L, ZIO *z); - - -#endif diff --git a/src/lua/lstate.c b/src/lua/lstate.c deleted file mode 100644 index 6310cb7e..00000000 --- a/src/lua/lstate.c +++ /dev/null @@ -1,121 +0,0 @@ -/* -** $Id: lstate.c,v 1.3 2001/11/26 23:00:26 darkgod Exp $ -** Global State -** See Copyright Notice in lua.h -*/ - - -#include - -#include "lua.h" - -#include "ldo.h" -#include "lgc.h" -#include "llex.h" -#include "lmem.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" - - -#ifdef LUA_DEBUG -static lua_State *lua_state = NULL; -void luaB_opentests (lua_State *L); -#endif - - -/* -** built-in implementation for ERRORMESSAGE. In a "correct" environment -** ERRORMESSAGE should have an external definition, and so this function -** would not be used. -*/ -static int errormessage (lua_State *L) { - const char *s = lua_tostring(L, 1); - if (s == NULL) s = "(no message)"; - fprintf(stderr, "error: %s\n", s); - return 0; -} - - -/* -** open parts that may cause memory-allocation errors -*/ -static void f_luaopen (lua_State *L, void *ud) { - int stacksize = *(int *)ud; - if (stacksize == 0) - stacksize = DEFAULT_STACK_SIZE; - else - stacksize += LUA_MINSTACK; - L->gt = luaH_new(L, 10); /* table of globals */ - luaD_init(L, stacksize); - luaS_init(L); - luaX_init(L); - luaT_init(L); - lua_newtable(L); - lua_ref(L, 1); /* create registry */ - lua_register(L, LUA_ERRORMESSAGE, errormessage); -#ifdef LUA_DEBUG - luaB_opentests(L); - if (lua_state == NULL) lua_state = L; /* keep first state to be opened */ -#endif - LUA_ASSERT(lua_gettop(L) == 0, "wrong API stack"); -} - - -LUA_API lua_State *lua_open (int stacksize) { - lua_State *L = luaM_new(NULL, lua_State); - if (L == NULL) return NULL; /* memory allocation error */ - L->stack = NULL; - L->strt.size = L->udt.size = 0; - L->strt.nuse = L->udt.nuse = 0; - L->strt.hash = NULL; - L->udt.hash = NULL; - L->Mbuffer = NULL; - L->Mbuffsize = 0; - L->rootproto = NULL; - L->rootcl = NULL; - L->roottable = NULL; - L->TMtable = NULL; - L->last_tag = -1; - L->refArray = NULL; - L->refSize = 0; - L->refFree = NONEXT; - L->nblocks = sizeof(lua_State); - L->GCthreshold = MAX_INT; /* to avoid GC during pre-definitions */ - L->callhook = NULL; - L->linehook = NULL; - L->allowhooks = 1; - L->errorJmp = NULL; - if (luaD_runprotected(L, f_luaopen, &stacksize) != 0) { - /* memory allocation error: free partial state */ - lua_close(L); - return NULL; - } - L->GCthreshold = 2*L->nblocks; - return L; -} - - -LUA_API void lua_close (lua_State *L) { - LUA_ASSERT(L != lua_state || lua_gettop(L) == 0, "garbage in C stack"); - luaC_collect(L, 1); /* collect all elements */ - LUA_ASSERT(L->rootproto == NULL, "list should be empty"); - LUA_ASSERT(L->rootcl == NULL, "list should be empty"); - LUA_ASSERT(L->roottable == NULL, "list should be empty"); - luaS_freeall(L); - if (L->stack) - L->nblocks -= (L->stack_last - L->stack + 1)*sizeof(TObject); - luaM_free(L, L->stack); - L->nblocks -= (L->last_tag+1)*sizeof(struct TM); - luaM_free(L, L->TMtable); - L->nblocks -= (L->refSize)*sizeof(struct Ref); - luaM_free(L, L->refArray); - L->nblocks -= (L->Mbuffsize)*sizeof(char); - luaM_free(L, L->Mbuffer); - LUA_ASSERT(L->nblocks == sizeof(lua_State), "wrong count for nblocks"); - luaM_free(L, L); - LUA_ASSERT(L != lua_state || memdebug_numblocks == 0, "memory leak!"); - LUA_ASSERT(L != lua_state || memdebug_total == 0,"memory leak!"); -} - diff --git a/src/lua/lstate.h b/src/lua/lstate.h deleted file mode 100644 index ee02db01..00000000 --- a/src/lua/lstate.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -** $Id: lstate.h,v 1.3 2001/11/26 23:00:26 darkgod Exp $ -** Global State -** See Copyright Notice in lua.h -*/ - -#ifndef lstate_h -#define lstate_h - -#include "lobject.h" -#include "lua.h" -#include "luadebug.h" - - - -typedef TObject *StkId; /* index to stack elements */ - - -/* -** marks for Reference array -*/ -#define NONEXT -1 /* to end the free list */ -#define HOLD -2 -#define COLLECTED -3 -#define LOCK -4 - - -struct Ref { - TObject o; - int st; /* can be LOCK, HOLD, COLLECTED, or next (for free list) */ -}; - - -struct lua_longjmp; /* defined in ldo.c */ -struct TM; /* defined in ltm.h */ - - -typedef struct stringtable { - int size; - lint32 nuse; /* number of elements */ - TString **hash; -} stringtable; - - - -struct lua_State { - /* thread-specific state */ - StkId top; /* first free slot in the stack */ - StkId stack; /* stack base */ - StkId stack_last; /* last free slot in the stack */ - int stacksize; - StkId Cbase; /* base for current C function */ - struct lua_longjmp *errorJmp; /* current error recover point */ - char *Mbuffer; /* global buffer */ - size_t Mbuffsize; /* size of Mbuffer */ - /* global state */ - Proto *rootproto; /* list of all prototypes */ - Closure *rootcl; /* list of all closures */ - Hash *roottable; /* list of all tables */ - stringtable strt; /* hash table for strings */ - stringtable udt; /* hash table for udata */ - Hash *gt; /* table for globals */ - struct TM *TMtable; /* table for tag methods */ - int last_tag; /* last used tag in TMtable */ - struct Ref *refArray; /* locked objects */ - int refSize; /* size of refArray */ - int refFree; /* list of free positions in refArray */ - unsigned long GCthreshold; - unsigned long nblocks; /* number of `bytes' currently allocated */ - lua_Hook callhook; - lua_Hook linehook; - int allowhooks; -}; - - -#endif - diff --git a/src/lua/lstring.c b/src/lua/lstring.c deleted file mode 100644 index 7293e195..00000000 --- a/src/lua/lstring.c +++ /dev/null @@ -1,155 +0,0 @@ -/* -** $Id: lstring.c,v 1.3 2001/11/26 23:00:26 darkgod Exp $ -** String table (keeps all strings handled by Lua) -** See Copyright Notice in lua.h -*/ - - -#include - -#include "lua.h" - -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" - - -/* -** type equivalent to TString, but with maximum alignment requirements -*/ -union L_UTString { - TString ts; - union L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ -}; - - - -void luaS_init (lua_State *L) { - L->strt.hash = luaM_newvector(L, 1, TString *); - L->udt.hash = luaM_newvector(L, 1, TString *); - L->nblocks += 2*sizeof(TString *); - L->strt.size = L->udt.size = 1; - L->strt.nuse = L->udt.nuse = 0; - L->strt.hash[0] = L->udt.hash[0] = NULL; -} - - -void luaS_freeall (lua_State *L) { - LUA_ASSERT(L->strt.nuse==0, "non-empty string table"); - L->nblocks -= (L->strt.size + L->udt.size)*sizeof(TString *); - luaM_free(L, L->strt.hash); - LUA_ASSERT(L->udt.nuse==0, "non-empty udata table"); - luaM_free(L, L->udt.hash); -} - - -static unsigned long hash_s (const char *s, size_t l) { - unsigned long h = l; /* seed */ - size_t step = (l>>5)|1; /* if string is too long, don't hash all its chars */ - for (; l>=step; l-=step) - h = h ^ ((h<<5)+(h>>2)+(unsigned char)*(s++)); - return h; -} - - -void luaS_resize (lua_State *L, stringtable *tb, int newsize) { - TString **newhash = luaM_newvector(L, newsize, TString *); - int i; - for (i=0; isize; i++) { - TString *p = tb->hash[i]; - while (p) { /* for each node in the list */ - TString *next = p->nexthash; /* save next */ - unsigned long h = (tb == &L->strt) ? p->u.s.hash : IntPoint(p->u.d.value); - int h1 = h&(newsize-1); /* new position */ - LUA_ASSERT(h%newsize == (h&(newsize-1)), - "a&(x-1) == a%x, for x power of 2"); - p->nexthash = newhash[h1]; /* chain it in new position */ - newhash[h1] = p; - p = next; - } - } - luaM_free(L, tb->hash); - L->nblocks += (newsize - tb->size)*sizeof(TString *); - tb->size = newsize; - tb->hash = newhash; -} - - -static void newentry (lua_State *L, stringtable *tb, TString *ts, int h) { - ts->nexthash = tb->hash[h]; /* chain new entry */ - tb->hash[h] = ts; - tb->nuse++; - if (tb->nuse > (lint32)tb->size && tb->size < MAX_INT/2) /* too crowded? */ - luaS_resize(L, tb, tb->size*2); -} - - - -TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { - unsigned long h = hash_s(str, l); - int h1 = h & (L->strt.size-1); - TString *ts; - for (ts = L->strt.hash[h1]; ts; ts = ts->nexthash) { - if (ts->len == l && (memcmp(str, ts->str, l) == 0)) - return ts; - } - /* not found */ - ts = (TString *)luaM_malloc(L, sizestring(l)); - ts->marked = 0; - ts->nexthash = NULL; - ts->len = l; - ts->u.s.hash = h; - ts->u.s.constindex = 0; - memcpy(ts->str, str, l); - ts->str[l] = 0; /* ending 0 */ - L->nblocks += sizestring(l); - newentry(L, &L->strt, ts, h1); /* insert it on table */ - return ts; -} - - -TString *luaS_newudata (lua_State *L, size_t s, void *udata) { - union L_UTString *uts = (union L_UTString *)luaM_malloc(L, - (lint32)sizeof(union L_UTString)+s); - TString *ts = &uts->ts; - ts->marked = 0; - ts->nexthash = NULL; - ts->len = s; - ts->u.d.tag = 0; - ts->u.d.value = (udata == NULL) ? uts+1 : udata; - L->nblocks += sizestring(s); - /* insert it on table */ - newentry(L, &L->udt, ts, IntPoint(ts->u.d.value) & (L->udt.size-1)); - return ts; -} - - -TString *luaS_createudata (lua_State *L, void *udata, int tag) { - int h1 = IntPoint(udata) & (L->udt.size-1); - TString *ts; - for (ts = L->udt.hash[h1]; ts; ts = ts->nexthash) { - if (udata == ts->u.d.value && (tag == ts->u.d.tag || tag == LUA_ANYTAG)) - return ts; - } - /* not found */ - ts = luaS_newudata(L, 0, udata); - if (tag != LUA_ANYTAG) - ts->u.d.tag = tag; - return ts; -} - - -TString *luaS_new (lua_State *L, const char *str) { - return luaS_newlstr(L, str, strlen(str)); -} - - -TString *luaS_newfixed (lua_State *L, const char *str) { - TString *ts = luaS_new(L, str); - if (ts->marked == 0) ts->marked = FIXMARK; /* avoid GC */ - return ts; -} - diff --git a/src/lua/lstring.h b/src/lua/lstring.h deleted file mode 100644 index f23159ec..00000000 --- a/src/lua/lstring.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -** $Id: lstring.h,v 1.3 2001/11/26 23:00:26 darkgod Exp $ -** String table (keep all strings handled by Lua) -** See Copyright Notice in lua.h -*/ - -#ifndef lstring_h -#define lstring_h - - -#include "lobject.h" -#include "lstate.h" - - -/* -** any TString with mark>=FIXMARK is never collected. -** Marks>=RESERVEDMARK are used to identify reserved words. -*/ -#define FIXMARK 2 -#define RESERVEDMARK 3 - - -#define sizestring(l) ((long)sizeof(TString) + \ - ((long)(l+1)-TSPACK)*(long)sizeof(char)) - - -void luaS_init (lua_State *L); -void luaS_resize (lua_State *L, stringtable *tb, int newsize); -TString *luaS_newudata (lua_State *L, size_t s, void *udata); -TString *luaS_createudata (lua_State *L, void *udata, int tag); -void luaS_freeall (lua_State *L); -TString *luaS_newlstr (lua_State *L, const char *str, size_t l); -TString *luaS_new (lua_State *L, const char *str); -TString *luaS_newfixed (lua_State *L, const char *str); - - -#endif diff --git a/src/lua/lstrlib.c b/src/lua/lstrlib.c deleted file mode 100644 index 051eccf7..00000000 --- a/src/lua/lstrlib.c +++ /dev/null @@ -1,621 +0,0 @@ -/* -** $Id: lstrlib.c,v 1.3 2001/11/26 23:00:26 darkgod Exp $ -** Standard library for string operations and pattern-matching -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include -#include - -#include "lua.h" - -#include "lauxlib.h" -#include "lualib.h" - - - -static int str_len (lua_State *L) { - size_t l; - luaL_check_lstr(L, 1, &l); - lua_pushnumber(L, l); - return 1; -} - - -static long posrelat (long pos, size_t len) { - /* relative string position: negative means back from end */ - return (pos>=0) ? pos : (long)len+pos+1; -} - - -static int str_sub (lua_State *L) { - size_t l; - const char *s = luaL_check_lstr(L, 1, &l); - long start = posrelat(luaL_check_long(L, 2), l); - long end = posrelat(luaL_opt_long(L, 3, -1), l); - if (start < 1) start = 1; - if (end > (long)l) end = l; - if (start <= end) - lua_pushlstring(L, s+start-1, end-start+1); - else lua_pushstring(L, ""); - return 1; -} - - -static int str_lower (lua_State *L) { - size_t l; - size_t i; - luaL_Buffer b; - const char *s = luaL_check_lstr(L, 1, &l); - luaL_buffinit(L, &b); - for (i=0; i 0) - luaL_addlstring(&b, s, l); - luaL_pushresult(&b); - return 1; -} - - -static int str_byte (lua_State *L) { - size_t l; - const char *s = luaL_check_lstr(L, 1, &l); - long pos = posrelat(luaL_opt_long(L, 2, 1), l); - luaL_arg_check(L, 0level && cap->capture[l].len != -1)) - lua_error(L, "invalid capture index"); - return l; -} - - -static int capture_to_close (lua_State *L, struct Capture *cap) { - int level = cap->level; - for (level--; level>=0; level--) - if (cap->capture[level].len == -1) return level; - lua_error(L, "invalid pattern capture"); - return 0; /* to avoid warnings */ -} - - -const char *luaI_classend (lua_State *L, const char *p) { - switch (*p++) { - case ESC: - if (*p == '\0') lua_error(L, "malformed pattern (ends with `%')"); - return p+1; - case '[': - if (*p == '^') p++; - do { /* look for a ']' */ - if (*p == '\0') lua_error(L, "malformed pattern (missing `]')"); - if (*(p++) == ESC && *p != '\0') p++; /* skip escapes (e.g. '%]') */ - } while (*p != ']'); - return p+1; - default: - return p; - } -} - - -static int match_class (int c, int cl) { - int res; - switch (tolower(cl)) { - case 'a' : res = isalpha(c); break; - case 'c' : res = iscntrl(c); break; - case 'd' : res = isdigit(c); break; - case 'l' : res = islower(c); break; - case 'p' : res = ispunct(c); break; - case 's' : res = isspace(c); break; - case 'u' : res = isupper(c); break; - case 'w' : res = isalnum(c); break; - case 'x' : res = isxdigit(c); break; - case 'z' : res = (c == '\0'); break; - default: return (cl == c); - } - return (islower(cl) ? res : !res); -} - - - -static int matchbracketclass (int c, const char *p, const char *endclass) { - int sig = 1; - if (*(p+1) == '^') { - sig = 0; - p++; /* skip the '^' */ - } - while (++p < endclass) { - if (*p == ESC) { - p++; - if (match_class(c, (unsigned char)*p)) - return sig; - } - else if ((*(p+1) == '-') && (p+2 < endclass)) { - p+=2; - if ((int)(unsigned char)*(p-2) <= c && c <= (int)(unsigned char)*p) - return sig; - } - else if ((int)(unsigned char)*p == c) return sig; - } - return !sig; -} - - - -int luaI_singlematch (int c, const char *p, const char *ep) { - switch (*p) { - case '.': /* matches any char */ - return 1; - case ESC: - return match_class(c, (unsigned char)*(p+1)); - case '[': - return matchbracketclass(c, p, ep-1); - default: - return ((unsigned char)*p == c); - } -} - - -static const char *match (lua_State *L, const char *s, const char *p, - struct Capture *cap); - - -static const char *matchbalance (lua_State *L, const char *s, const char *p, - struct Capture *cap) { - if (*p == 0 || *(p+1) == 0) - lua_error(L, "unbalanced pattern"); - if (*s != *p) return NULL; - else { - int b = *p; - int e = *(p+1); - int cont = 1; - while (++s < cap->src_end) { - if (*s == e) { - if (--cont == 0) return s+1; - } - else if (*s == b) cont++; - } - } - return NULL; /* string ends out of balance */ -} - - -static const char *max_expand (lua_State *L, const char *s, const char *p, - const char *ep, struct Capture *cap) { - long i = 0; /* counts maximum expand for item */ - while ((s+i)src_end && luaI_singlematch((unsigned char)*(s+i), p, ep)) - i++; - /* keeps trying to match with the maximum repetitions */ - while (i>=0) { - const char *res = match(L, (s+i), ep+1, cap); - if (res) return res; - i--; /* else didn't match; reduce 1 repetition to try again */ - } - return NULL; -} - - -static const char *min_expand (lua_State *L, const char *s, const char *p, - const char *ep, struct Capture *cap) { - for (;;) { - const char *res = match(L, s, ep+1, cap); - if (res != NULL) - return res; - else if (ssrc_end && luaI_singlematch((unsigned char)*s, p, ep)) - s++; /* try with one more repetition */ - else return NULL; - } -} - - -static const char *start_capture (lua_State *L, const char *s, const char *p, - struct Capture *cap) { - const char *res; - int level = cap->level; - if (level >= MAX_CAPTURES) lua_error(L, "too many captures"); - cap->capture[level].init = s; - cap->capture[level].len = -1; - cap->level = level+1; - if ((res=match(L, s, p+1, cap)) == NULL) /* match failed? */ - cap->level--; /* undo capture */ - return res; -} - - -static const char *end_capture (lua_State *L, const char *s, const char *p, - struct Capture *cap) { - int l = capture_to_close(L, cap); - const char *res; - cap->capture[l].len = s - cap->capture[l].init; /* close capture */ - if ((res = match(L, s, p+1, cap)) == NULL) /* match failed? */ - cap->capture[l].len = -1; /* undo capture */ - return res; -} - - -static const char *match_capture (lua_State *L, const char *s, int level, - struct Capture *cap) { - int l = check_capture(L, level, cap); - size_t len = cap->capture[l].len; - if ((size_t)(cap->src_end-s) >= len && - memcmp(cap->capture[l].init, s, len) == 0) - return s+len; - else return NULL; -} - - -static const char *match (lua_State *L, const char *s, const char *p, - struct Capture *cap) { - init: /* using goto's to optimize tail recursion */ - switch (*p) { - case '(': /* start capture */ - return start_capture(L, s, p, cap); - case ')': /* end capture */ - return end_capture(L, s, p, cap); - case ESC: /* may be %[0-9] or %b */ - if (isdigit((unsigned char)(*(p+1)))) { /* capture? */ - s = match_capture(L, s, *(p+1), cap); - if (s == NULL) return NULL; - p+=2; goto init; /* else return match(L, s, p+2, cap) */ - } - else if (*(p+1) == 'b') { /* balanced string? */ - s = matchbalance(L, s, p+2, cap); - if (s == NULL) return NULL; - p+=4; goto init; /* else return match(L, s, p+4, cap); */ - } - else goto dflt; /* case default */ - case '\0': /* end of pattern */ - return s; /* match succeeded */ - case '$': - if (*(p+1) == '\0') /* is the '$' the last char in pattern? */ - return (s == cap->src_end) ? s : NULL; /* check end of string */ - else goto dflt; - default: dflt: { /* it is a pattern item */ - const char *ep = luaI_classend(L, p); /* points to what is next */ - int m = ssrc_end && luaI_singlematch((unsigned char)*s, p, ep); - switch (*ep) { - case '?': { /* optional */ - const char *res; - if (m && ((res=match(L, s+1, ep+1, cap)) != NULL)) - return res; - p=ep+1; goto init; /* else return match(L, s, ep+1, cap); */ - } - case '*': /* 0 or more repetitions */ - return max_expand(L, s, p, ep, cap); - case '+': /* 1 or more repetitions */ - return (m ? max_expand(L, s+1, p, ep, cap) : NULL); - case '-': /* 0 or more repetitions (minimum) */ - return min_expand(L, s, p, ep, cap); - default: - if (!m) return NULL; - s++; p=ep; goto init; /* else return match(L, s+1, ep, cap); */ - } - } - } -} - - - -static const char *lmemfind (const char *s1, size_t l1, - const char *s2, size_t l2) { - if (l2 == 0) return s1; /* empty strings are everywhere */ - else if (l2 > l1) return NULL; /* avoids a negative `l1' */ - else { - const char *init; /* to search for a `*s2' inside `s1' */ - l2--; /* 1st char will be checked by `memchr' */ - l1 = l1-l2; /* `s2' cannot be found after that */ - while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { - init++; /* 1st char is already checked */ - if (memcmp(init, s2+1, l2) == 0) - return init-1; - else { /* correct `l1' and `s1' to try again */ - l1 -= init-s1; - s1 = init; - } - } - return NULL; /* not found */ - } -} - - -static int push_captures (lua_State *L, struct Capture *cap) { - int i; - luaL_checkstack(L, cap->level, "too many captures"); - for (i=0; ilevel; i++) { - int l = cap->capture[i].len; - if (l == -1) lua_error(L, "unfinished capture"); - lua_pushlstring(L, cap->capture[i].init, l); - } - return cap->level; /* number of strings pushed */ -} - - -static int str_find (lua_State *L) { - size_t l1, l2; - const char *s = luaL_check_lstr(L, 1, &l1); - const char *p = luaL_check_lstr(L, 2, &l2); - long init = posrelat(luaL_opt_long(L, 3, 1), l1) - 1; - struct Capture cap; - luaL_arg_check(L, 0 <= init && (size_t)init <= l1, 3, "out of range"); - if (lua_gettop(L) > 3 || /* extra argument? */ - strpbrk(p, SPECIALS) == NULL) { /* or no special characters? */ - const char *s2 = lmemfind(s+init, l1-init, p, l2); - if (s2) { - lua_pushnumber(L, s2-s+1); - lua_pushnumber(L, s2-s+l2); - return 2; - } - } - else { - int anchor = (*p == '^') ? (p++, 1) : 0; - const char *s1=s+init; - cap.src_end = s+l1; - do { - const char *res; - cap.level = 0; - if ((res=match(L, s1, p, &cap)) != NULL) { - lua_pushnumber(L, s1-s+1); /* start */ - lua_pushnumber(L, res-s); /* end */ - return push_captures(L, &cap) + 2; - } - } while (s1++capture[level].init, cap->capture[level].len); - } - } - } - } - else { /* is a function */ - int n; - lua_pushvalue(L, 3); - n = push_captures(L, cap); - lua_rawcall(L, n, 1); - if (lua_isstring(L, -1)) - luaL_addvalue(b); /* add return to accumulated result */ - else - lua_pop(L, 1); /* function result is not a string: pop it */ - } -} - - -static int str_gsub (lua_State *L) { - size_t srcl; - const char *src = luaL_check_lstr(L, 1, &srcl); - const char *p = luaL_check_string(L, 2); - int max_s = luaL_opt_int(L, 4, srcl+1); - int anchor = (*p == '^') ? (p++, 1) : 0; - int n = 0; - struct Capture cap; - luaL_Buffer b; - luaL_arg_check(L, - lua_gettop(L) >= 3 && (lua_isstring(L, 3) || lua_isfunction(L, 3)), - 3, "string or function expected"); - luaL_buffinit(L, &b); - cap.src_end = src+srcl; - while (n < max_s) { - const char *e; - cap.level = 0; - e = match(L, src, p, &cap); - if (e) { - n++; - add_s(L, &b, &cap); - } - if (e && e>src) /* non empty match? */ - src = e; /* skip it */ - else if (src < cap.src_end) - luaL_putchar(&b, *src++); - else break; - if (anchor) break; - } - luaL_addlstring(&b, src, cap.src_end-src); - luaL_pushresult(&b); - lua_pushnumber(L, n); /* number of substitutions */ - return 2; -} - -/* }====================================================== */ - - -static void luaI_addquoted (lua_State *L, luaL_Buffer *b, int arg) { - size_t l; - const char *s = luaL_check_lstr(L, arg, &l); - luaL_putchar(b, '"'); - while (l--) { - switch (*s) { - case '"': case '\\': case '\n': - luaL_putchar(b, '\\'); - luaL_putchar(b, *s); - break; - case '\0': luaL_addlstring(b, "\\000", 4); break; - default: luaL_putchar(b, *s); - } - s++; - } - luaL_putchar(b, '"'); -} - -/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ -#define MAX_ITEM 512 -/* maximum size of each format specification (such as '%-099.99d') */ -#define MAX_FORMAT 20 - -static int str_format (lua_State *L) { - int arg = 1; - const char *strfrmt = luaL_check_string(L, arg); - luaL_Buffer b; - luaL_buffinit(L, &b); - while (*strfrmt) { - if (*strfrmt != '%') - luaL_putchar(&b, *strfrmt++); - else if (*++strfrmt == '%') - luaL_putchar(&b, *strfrmt++); /* %% */ - else { /* format item */ - struct Capture cap; - char form[MAX_FORMAT]; /* to store the format ('%...') */ - char buff[MAX_ITEM]; /* to store the formatted item */ - const char *initf = strfrmt; - form[0] = '%'; - if (isdigit((unsigned char)*initf) && *(initf+1) == '$') { - arg = *initf - '0'; - initf += 2; /* skip the 'n$' */ - } - arg++; - cap.src_end = strfrmt+strlen(strfrmt)+1; - cap.level = 0; - strfrmt = match(L, initf, "[-+ #0]*(%d*)%.?(%d*)", &cap); - if (cap.capture[0].len > 2 || cap.capture[1].len > 2 || /* < 100? */ - strfrmt-initf > MAX_FORMAT-2) - lua_error(L, "invalid format (width or precision too long)"); - strncpy(form+1, initf, strfrmt-initf+1); /* +1 to include conversion */ - form[strfrmt-initf+2] = 0; - switch (*strfrmt++) { - case 'c': case 'd': case 'i': - sprintf(buff, form, luaL_check_int(L, arg)); - break; - case 'o': case 'u': case 'x': case 'X': - sprintf(buff, form, (unsigned int)luaL_check_number(L, arg)); - break; - case 'e': case 'E': case 'f': case 'g': case 'G': - sprintf(buff, form, luaL_check_number(L, arg)); - break; - case 'q': - luaI_addquoted(L, &b, arg); - continue; /* skip the "addsize" at the end */ - case 's': { - size_t l; - const char *s = luaL_check_lstr(L, arg, &l); - if (cap.capture[1].len == 0 && l >= 100) { - /* no precision and string is too long to be formatted; - keep original string */ - lua_pushvalue(L, arg); - luaL_addvalue(&b); - continue; /* skip the "addsize" at the end */ - } - else { - sprintf(buff, form, s); - break; - } - } - default: /* also treat cases 'pnLlh' */ - lua_error(L, "invalid option in `format'"); - } - luaL_addlstring(&b, buff, strlen(buff)); - } - } - luaL_pushresult(&b); - return 1; -} - - -static const struct luaL_reg strlib[] = { -{"strlen", str_len}, -{"strsub", str_sub}, -{"strlower", str_lower}, -{"strupper", str_upper}, -{"strchar", str_char}, -{"strrep", str_rep}, -{"ascii", str_byte}, /* for compatibility with 3.0 and earlier */ -{"strbyte", str_byte}, -{"format", str_format}, -{"strfind", str_find}, -{"gsub", str_gsub} -}; - - -/* -** Open string library -*/ -LUALIB_API void lua_strlibopen (lua_State *L) { - luaL_openl(L, strlib); -} diff --git a/src/lua/ltable.c b/src/lua/ltable.c deleted file mode 100644 index 1e3eb4f5..00000000 --- a/src/lua/ltable.c +++ /dev/null @@ -1,303 +0,0 @@ -/* -** $Id: ltable.c,v 1.3 2001/11/26 23:00:26 darkgod Exp $ -** Lua tables (hash) -** See Copyright Notice in lua.h -*/ - - -/* -** Implementation of tables (aka arrays, objects, or hash tables); -** uses a mix of chained scatter table with Brent's variation. -** A main invariant of these tables is that, if an element is not -** in its main position (i.e. the `original' position that its hash gives -** to it), then the colliding element is in its own main position. -** In other words, there are collisions only when two elements have the -** same main position (i.e. the same hash values for that table size). -** Because of that, the load factor of these tables can be 100% without -** performance penalties. -*/ - - -#include "lua.h" - -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" - - -#define gcsize(L, n) (sizeof(Hash)+(n)*sizeof(Node)) - - - -#define TagDefault LUA_TTABLE - - - -/* -** returns the `main' position of an element in a table (that is, the index -** of its hash value) -*/ -Node *luaH_mainposition (const Hash *t, const TObject *key) { - unsigned long h; - switch (ttype(key)) { - case LUA_TNUMBER: - h = (unsigned long)(long)nvalue(key); - break; - case LUA_TSTRING: - h = tsvalue(key)->u.s.hash; - break; - case LUA_TUSERDATA: - h = IntPoint(tsvalue(key)); - break; - case LUA_TTABLE: - h = IntPoint(hvalue(key)); - break; - case LUA_TFUNCTION: - h = IntPoint(clvalue(key)); - break; - default: - return NULL; /* invalid key */ - } - LUA_ASSERT(h%(unsigned int)t->size == (h&((unsigned int)t->size-1)), - "a&(x-1) == a%x, for x power of 2"); - return &t->node[h&(t->size-1)]; -} - - -static const TObject *luaH_getany (lua_State *L, const Hash *t, - const TObject *key) { - Node *n = luaH_mainposition(t, key); - if (!n) - lua_error(L, "table index is nil"); - else do { - if (luaO_equalObj(key, &n->key)) - return &n->val; - n = n->next; - } while (n); - return &luaO_nilobject; /* key not found */ -} - - -/* specialized version for numbers */ -const TObject *luaH_getnum (const Hash *t, Number key) { - Node *n = &t->node[(unsigned long)(long)key&(t->size-1)]; - do { - if (ttype(&n->key) == LUA_TNUMBER && nvalue(&n->key) == key) - return &n->val; - n = n->next; - } while (n); - return &luaO_nilobject; /* key not found */ -} - - -/* specialized version for strings */ -const TObject *luaH_getstr (const Hash *t, TString *key) { - Node *n = &t->node[key->u.s.hash&(t->size-1)]; - do { - if (ttype(&n->key) == LUA_TSTRING && tsvalue(&n->key) == key) - return &n->val; - n = n->next; - } while (n); - return &luaO_nilobject; /* key not found */ -} - - -const TObject *luaH_get (lua_State *L, const Hash *t, const TObject *key) { - switch (ttype(key)) { - case LUA_TNUMBER: return luaH_getnum(t, nvalue(key)); - case LUA_TSTRING: return luaH_getstr(t, tsvalue(key)); - default: return luaH_getany(L, t, key); - } -} - - -Node *luaH_next (lua_State *L, const Hash *t, const TObject *key) { - int i; - if (ttype(key) == LUA_TNIL) - i = 0; /* first iteration */ - else { - const TObject *v = luaH_get(L, t, key); - if (v == &luaO_nilobject) - lua_error(L, "invalid key for `next'"); - i = (int)(((const char *)v - - (const char *)(&t->node[0].val)) / sizeof(Node)) + 1; - } - for (; isize; i++) { - Node *n = node(t, i); - if (ttype(val(n)) != LUA_TNIL) - return n; - } - return NULL; /* no more elements */ -} - - -/* -** try to remove a key without value from a table. To avoid problems with -** hash, change `key' for a number with the same hash. -*/ -void luaH_remove (Hash *t, TObject *key) { - if (ttype(key) == LUA_TNUMBER || - (ttype(key) == LUA_TSTRING && tsvalue(key)->len <= 30)) - return; /* do not remove numbers nor small strings */ - else { - /* try to find a number `n' with the same hash as `key' */ - Node *mp = luaH_mainposition(t, key); - int n = mp - &t->node[0]; - /* make sure `n' is not in `t' */ - while (luaH_getnum(t, n) != &luaO_nilobject) { - if (n >= MAX_INT - t->size) - return; /* give up; (to avoid overflow) */ - n += t->size; - } - ttype(key) = LUA_TNUMBER; - nvalue(key) = n; - LUA_ASSERT(luaH_mainposition(t, key) == mp, "cannot change hash"); - } -} - - -static void setnodevector (lua_State *L, Hash *t, lint32 size) { - int i; - if (size > MAX_INT) - lua_error(L, "table overflow"); - t->node = luaM_newvector(L, size, Node); - for (i=0; i<(int)size; i++) { - ttype(&t->node[i].key) = ttype(&t->node[i].val) = LUA_TNIL; - t->node[i].next = NULL; - } - L->nblocks += gcsize(L, size) - gcsize(L, t->size); - t->size = size; - t->firstfree = &t->node[size-1]; /* first free position to be used */ -} - - -Hash *luaH_new (lua_State *L, int size) { - Hash *t = luaM_new(L, Hash); - t->htag = TagDefault; - t->next = L->roottable; - L->roottable = t; - t->mark = t; - t->size = 0; - L->nblocks += gcsize(L, 0); - t->node = NULL; - setnodevector(L, t, luaO_power2(size)); - return t; -} - - -void luaH_free (lua_State *L, Hash *t) { - L->nblocks -= gcsize(L, t->size); - luaM_free(L, t->node); - luaM_free(L, t); -} - - -static int numuse (const Hash *t) { - Node *v = t->node; - int size = t->size; - int realuse = 0; - int i; - for (i=0; isize; - Node *nold = t->node; - int nelems = numuse(t); - int i; - LUA_ASSERT(nelems<=oldsize, "wrong count"); - if (nelems >= oldsize-oldsize/4) /* using more than 3/4? */ - setnodevector(L, t, (lint32)oldsize*2); - else if (nelems <= oldsize/4 && /* less than 1/4? */ - oldsize > MINPOWER2) - setnodevector(L, t, oldsize/2); - else - setnodevector(L, t, oldsize); - for (i=0; ival) != LUA_TNIL) - *luaH_set(L, t, &old->key) = old->val; - } - luaM_free(L, nold); /* free old array */ -} - - -/* -** inserts a key into a hash table; first, check whether key is -** already present; if not, check whether key's main position is free; -** if not, check whether colliding node is in its main position or not; -** if it is not, move colliding node to an empty place and put new key -** in its main position; otherwise (colliding node is in its main position), -** new key goes to an empty position. -*/ -TObject *luaH_set (lua_State *L, Hash *t, const TObject *key) { - Node *mp = luaH_mainposition(t, key); - Node *n = mp; - if (!mp) - lua_error(L, "table index is nil"); - do { /* check whether `key' is somewhere in the chain */ - if (luaO_equalObj(key, &n->key)) - return &n->val; /* that's all */ - else n = n->next; - } while (n); - /* `key' not found; must insert it */ - if (ttype(&mp->key) != LUA_TNIL) { /* main position is not free? */ - Node *othern; /* main position of colliding node */ - n = t->firstfree; /* get a free place */ - /* is colliding node out of its main position? (can only happens if - its position is after "firstfree") */ - if (mp > n && (othern=luaH_mainposition(t, &mp->key)) != mp) { - /* yes; move colliding node into free position */ - while (othern->next != mp) othern = othern->next; /* find previous */ - othern->next = n; /* redo the chain with `n' in place of `mp' */ - *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ - mp->next = NULL; /* now `mp' is free */ - } - else { /* colliding node is in its own main position */ - /* new node will go into free position */ - n->next = mp->next; /* chain new position */ - mp->next = n; - mp = n; - } - } - mp->key = *key; - for (;;) { /* correct `firstfree' */ - if (ttype(&t->firstfree->key) == LUA_TNIL) - return &mp->val; /* OK; table still has a free place */ - else if (t->firstfree == t->node) break; /* cannot decrement from here */ - else (t->firstfree)--; - } - rehash(L, t); /* no more free places */ - return luaH_set(L, t, key); /* `rehash' invalidates this insertion */ -} - - -TObject *luaH_setint (lua_State *L, Hash *t, int key) { - TObject index; - ttype(&index) = LUA_TNUMBER; - nvalue(&index) = key; - return luaH_set(L, t, &index); -} - - -void luaH_setstrnum (lua_State *L, Hash *t, TString *key, Number val) { - TObject *value, index; - ttype(&index) = LUA_TSTRING; - tsvalue(&index) = key; - value = luaH_set(L, t, &index); - ttype(value) = LUA_TNUMBER; - nvalue(value) = val; -} - - -const TObject *luaH_getglobal (lua_State *L, const char *name) { - return luaH_getstr(L->gt, luaS_new(L, name)); -} - diff --git a/src/lua/ltable.h b/src/lua/ltable.h deleted file mode 100644 index 3bc2a5df..00000000 --- a/src/lua/ltable.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -** $Id: ltable.h,v 1.3 2001/11/26 23:00:26 darkgod Exp $ -** Lua tables (hash) -** See Copyright Notice in lua.h -*/ - -#ifndef ltable_h -#define ltable_h - -#include "lobject.h" - - -#define node(t,i) (&(t)->node[i]) -#define key(n) (&(n)->key) -#define val(n) (&(n)->val) - -Hash *luaH_new (lua_State *L, int nhash); -void luaH_free (lua_State *L, Hash *t); -const TObject *luaH_get (lua_State *L, const Hash *t, const TObject *key); -const TObject *luaH_getnum (const Hash *t, Number key); -const TObject *luaH_getstr (const Hash *t, TString *key); -void luaH_remove (Hash *t, TObject *key); -TObject *luaH_set (lua_State *L, Hash *t, const TObject *key); -Node * luaH_next (lua_State *L, const Hash *t, const TObject *r); -TObject *luaH_setint (lua_State *L, Hash *t, int key); -void luaH_setstrnum (lua_State *L, Hash *t, TString *key, Number val); -unsigned long luaH_hash (lua_State *L, const TObject *key); -const TObject *luaH_getglobal (lua_State *L, const char *name); - -/* exported only for debugging */ -Node *luaH_mainposition (const Hash *t, const TObject *key); - - -#endif diff --git a/src/lua/ltests.c b/src/lua/ltests.c deleted file mode 100644 index 06e08f5a..00000000 --- a/src/lua/ltests.c +++ /dev/null @@ -1,543 +0,0 @@ -/* -** $Id: ltests.c,v 1.2 2001/11/26 23:00:26 darkgod Exp $ -** Internal Module for Debugging of the Lua Implementation -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include -#include - - -#include "lua.h" - -#include "lapi.h" -#include "lauxlib.h" -#include "lcode.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lmem.h" -#include "lopcodes.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "luadebug.h" -#include "lualib.h" - - -void luaB_opentests (lua_State *L); - - -/* -** The whole module only makes sense with LUA_DEBUG on -*/ -#ifdef LUA_DEBUG - - - -static void setnameval (lua_State *L, const char *name, int val) { - lua_pushstring(L, name); - lua_pushnumber(L, val); - lua_settable(L, -3); -} - - -/* -** {====================================================== -** Disassembler -** ======================================================= -*/ - - -static const char *const instrname[NUM_OPCODES] = { - "END", "RETURN", "CALL", "TAILCALL", "PUSHNIL", "POP", "PUSHINT", - "PUSHSTRING", "PUSHNUM", "PUSHNEGNUM", "PUSHUPVALUE", "GETLOCAL", - "GETGLOBAL", "GETTABLE", "GETDOTTED", "GETINDEXED", "PUSHSELF", - "CREATETABLE", "SETLOCAL", "SETGLOBAL", "SETTABLE", "SETLIST", "SETMAP", - "ADD", "ADDI", "SUB", "MULT", "DIV", "POW", "CONCAT", "MINUS", "NOT", - "JMPNE", "JMPEQ", "JMPLT", "JMPLE", "JMPGT", "JMPGE", "JMPT", "JMPF", - "JMPONT", "JMPONF", "JMP", "PUSHNILJMP", "FORPREP", "FORLOOP", "LFORPREP", - "LFORLOOP", "CLOSURE" -}; - - -static int pushop (lua_State *L, Proto *p, int pc) { - char buff[100]; - Instruction i = p->code[pc]; - OpCode o = GET_OPCODE(i); - const char *name = instrname[o]; - sprintf(buff, "%5d - ", luaG_getline(p->lineinfo, pc, 1, NULL)); - switch ((enum Mode)luaK_opproperties[o].mode) { - case iO: - sprintf(buff+8, "%-12s", name); - break; - case iU: - sprintf(buff+8, "%-12s%4u", name, GETARG_U(i)); - break; - case iS: - sprintf(buff+8, "%-12s%4d", name, GETARG_S(i)); - break; - case iAB: - sprintf(buff+8, "%-12s%4d %4d", name, GETARG_A(i), GETARG_B(i)); - break; - } - lua_pushstring(L, buff); - return (o != OP_END); -} - - -static int listcode (lua_State *L) { - int pc; - Proto *p; - int res; - luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), - 1, "Lua function expected"); - p = clvalue(luaA_index(L, 1))->f.l; - lua_newtable(L); - setnameval(L, "maxstack", p->maxstacksize); - setnameval(L, "numparams", p->numparams); - pc = 0; - do { - lua_pushnumber(L, pc+1); - res = pushop(L, p, pc++); - lua_settable(L, -3); - } while (res); - return 1; -} - - -static int liststrings (lua_State *L) { - Proto *p; - int i; - luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), - 1, "Lua function expected"); - p = clvalue(luaA_index(L, 1))->f.l; - lua_newtable(L); - for (i=0; inkstr; i++) { - lua_pushnumber(L, i+1); - lua_pushstring(L, p->kstr[i]->str); - lua_settable(L, -3); - } - return 1; -} - - -static int listlocals (lua_State *L) { - Proto *p; - int pc = luaL_check_int(L, 2) - 1; - int i = 0; - const char *name; - luaL_arg_check(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), - 1, "Lua function expected"); - p = clvalue(luaA_index(L, 1))->f.l; - while ((name = luaF_getlocalname(p, ++i, pc)) != NULL) - lua_pushstring(L, name); - return i-1; -} - -/* }====================================================== */ - - - -static int get_limits (lua_State *L) { - lua_newtable(L); - setnameval(L, "BITS_INT", BITS_INT); - setnameval(L, "LFPF", LFIELDS_PER_FLUSH); - setnameval(L, "MAXARG_A", MAXARG_A); - setnameval(L, "MAXARG_B", MAXARG_B); - setnameval(L, "MAXARG_S", MAXARG_S); - setnameval(L, "MAXARG_U", MAXARG_U); - setnameval(L, "MAXLOCALS", MAXLOCALS); - setnameval(L, "MAXPARAMS", MAXPARAMS); - setnameval(L, "MAXSTACK", MAXSTACK); - setnameval(L, "MAXUPVALUES", MAXUPVALUES); - setnameval(L, "MAXVARSLH", MAXVARSLH); - setnameval(L, "RFPF", RFIELDS_PER_FLUSH); - setnameval(L, "SIZE_A", SIZE_A); - setnameval(L, "SIZE_B", SIZE_B); - setnameval(L, "SIZE_OP", SIZE_OP); - setnameval(L, "SIZE_U", SIZE_U); - return 1; -} - - -static int mem_query (lua_State *L) { - if (lua_isnull(L, 1)) { - lua_pushnumber(L, memdebug_total); - lua_pushnumber(L, memdebug_numblocks); - lua_pushnumber(L, memdebug_maxmem); - return 3; - } - else { - memdebug_memlimit = luaL_check_int(L, 1); - return 0; - } -} - - -static int hash_query (lua_State *L) { - if (lua_isnull(L, 2)) { - luaL_arg_check(L, lua_tag(L, 1) == LUA_TSTRING, 1, "string expected"); - lua_pushnumber(L, tsvalue(luaA_index(L, 1))->u.s.hash); - } - else { - Hash *t; - luaL_checktype(L, 2, LUA_TTABLE); - t = hvalue(luaA_index(L, 2)); - lua_pushnumber(L, luaH_mainposition(t, luaA_index(L, 1)) - t->node); - } - return 1; -} - - -static int table_query (lua_State *L) { - const Hash *t; - int i = luaL_opt_int(L, 2, -1); - luaL_checktype(L, 1, LUA_TTABLE); - t = hvalue(luaA_index(L, 1)); - if (i == -1) { - lua_pushnumber(L, t->size); - lua_pushnumber(L, t->firstfree - t->node); - return 2; - } - else if (i < t->size) { - luaA_pushobject(L, &t->node[i].key); - luaA_pushobject(L, &t->node[i].val); - if (t->node[i].next) { - lua_pushnumber(L, t->node[i].next - t->node); - return 3; - } - else - return 2; - } - return 0; -} - - -static int string_query (lua_State *L) { - stringtable *tb = (*luaL_check_string(L, 1) == 's') ? &L->strt : &L->udt; - int s = luaL_opt_int(L, 2, 0) - 1; - if (s==-1) { - lua_pushnumber(L ,tb->nuse); - lua_pushnumber(L ,tb->size); - return 2; - } - else if (s < tb->size) { - TString *ts; - int n = 0; - for (ts = tb->hash[s]; ts; ts = ts->nexthash) { - ttype(L->top) = LUA_TSTRING; - tsvalue(L->top) = ts; - incr_top; - n++; - } - return n; - } - return 0; -} - - -static int tref (lua_State *L) { - luaL_checkany(L, 1); - lua_pushvalue(L, 1); - lua_pushnumber(L, lua_ref(L, luaL_opt_int(L, 2, 1))); - return 1; -} - -static int getref (lua_State *L) { - if (lua_getref(L, luaL_check_int(L, 1))) - return 1; - else - return 0; -} - -static int unref (lua_State *L) { - lua_unref(L, luaL_check_int(L, 1)); - return 0; -} - -static int newuserdata (lua_State *L) { - if (lua_isnumber(L, 2)) - lua_pushusertag(L, (void *)luaL_check_int(L, 1), luaL_check_int(L, 2)); - else - lua_newuserdata(L, luaL_check_int(L, 1)); - return 1; -} - -static int udataval (lua_State *L) { - luaL_checktype(L, 1, LUA_TUSERDATA); - lua_pushnumber(L, (int)lua_touserdata(L, 1)); - return 1; -} - -static int newstate (lua_State *L) { - lua_State *L1 = lua_open(luaL_check_int(L, 1)); - if (L1) - lua_pushuserdata(L, L1); - else - lua_pushnil(L); - return 1; -} - -static int loadlib (lua_State *L) { - lua_State *L1 = (lua_State *)lua_touserdata(L, 1); - switch (*luaL_check_string(L, 2)) { - case 'm': lua_mathlibopen(L1); break; - case 's': lua_strlibopen(L1); break; - case 'i': lua_iolibopen(L1); break; - case 'd': lua_dblibopen(L1); break; - case 'b': lua_baselibopen(L1); break; - default: luaL_argerror(L, 2, "invalid option"); - } - return 0; -} - -static int closestate (lua_State *L) { - luaL_checktype(L, 1, LUA_TUSERDATA); - lua_close((lua_State *)lua_touserdata(L, 1)); - return 0; -} - -static int doremote (lua_State *L) { - lua_State *L1; - const char *code = luaL_check_string(L, 2); - int status; - luaL_checktype(L, 1, LUA_TUSERDATA); - L1 = (lua_State *)lua_touserdata(L, 1); - status = lua_dostring(L1, code); - if (status != 0) { - lua_pushnil(L); - lua_pushnumber(L, status); - return 2; - } - else { - int i = 0; - while (!lua_isnull(L1, ++i)) - lua_pushstring(L, lua_tostring(L1, i)); - return i-1; - } -} - -static int settagmethod (lua_State *L) { - int tag = luaL_check_int(L, 1); - const char *event = luaL_check_string(L, 2); - luaL_checkany(L, 3); - lua_gettagmethod(L, tag, event); - lua_pushvalue(L, 3); - lua_settagmethod(L, tag, event); - return 1; -} - -static int pushbool (lua_State *L, int b) { - if (b) lua_pushnumber(L, 1); - else lua_pushnil(L); - return 1; -} - -static int equal (lua_State *L) { - return pushbool(L, lua_equal(L, 1, 2)); -} - - - -/* -** {====================================================== -** function to test the API with C. It interprets a kind of "assembler" -** language with calls to the API, so the test can be driven by Lua code -** ======================================================= -*/ - -static const char *const delimits = " \t\n,;"; - -static void skip (const char **pc) { - while (**pc != '\0' && strchr(delimits, **pc)) (*pc)++; -} - -static int getnum (lua_State *L, const char **pc) { - int res = 0; - int sig = 1; - skip(pc); - if (**pc == '.') { - res = (int)lua_tonumber(L, -1); - lua_pop(L, 1); - (*pc)++; - return res; - } - else if (**pc == '-') { - sig = -1; - (*pc)++; - } - while (isdigit(**pc)) res = res*10 + (*(*pc)++) - '0'; - return sig*res; -} - -static const char *getname (char *buff, const char **pc) { - int i = 0; - skip(pc); - while (**pc != '\0' && !strchr(delimits, **pc)) - buff[i++] = *(*pc)++; - buff[i] = '\0'; - return buff; -} - - -#define EQ(s1) (strcmp(s1, inst) == 0) - -#define getnum ((getnum)(L, &pc)) -#define getname ((getname)(buff, &pc)) - - -static int testC (lua_State *L) { - char buff[30]; - const char *pc = luaL_check_string(L, 1); - for (;;) { - const char *inst = getname; - if EQ("") return 0; - else if EQ("isnumber") { - lua_pushnumber(L, lua_isnumber(L, getnum)); - } - else if EQ("isstring") { - lua_pushnumber(L, lua_isstring(L, getnum)); - } - else if EQ("istable") { - lua_pushnumber(L, lua_istable(L, getnum)); - } - else if EQ("iscfunction") { - lua_pushnumber(L, lua_iscfunction(L, getnum)); - } - else if EQ("isfunction") { - lua_pushnumber(L, lua_isfunction(L, getnum)); - } - else if EQ("isuserdata") { - lua_pushnumber(L, lua_isuserdata(L, getnum)); - } - else if EQ("isnil") { - lua_pushnumber(L, lua_isnil(L, getnum)); - } - else if EQ("isnull") { - lua_pushnumber(L, lua_isnull(L, getnum)); - } - else if EQ("tonumber") { - lua_pushnumber(L, lua_tonumber(L, getnum)); - } - else if EQ("tostring") { - lua_pushstring(L, lua_tostring(L, getnum)); - } - else if EQ("tonumber") { - lua_pushnumber(L, lua_tonumber(L, getnum)); - } - else if EQ("strlen") { - lua_pushnumber(L, lua_strlen(L, getnum)); - } - else if EQ("tocfunction") { - lua_pushcfunction(L, lua_tocfunction(L, getnum)); - } - else if EQ("return") { - return getnum; - } - else if EQ("gettop") { - lua_pushnumber(L, lua_gettop(L)); - } - else if EQ("settop") { - lua_settop(L, getnum); - } - else if EQ("pop") { - lua_pop(L, getnum); - } - else if EQ("pushnum") { - lua_pushnumber(L, getnum); - } - else if EQ("pushvalue") { - lua_pushvalue(L, getnum); - } - else if EQ("remove") { - lua_remove(L, getnum); - } - else if EQ("insert") { - lua_insert(L, getnum); - } - else if EQ("gettable") { - lua_gettable(L, getnum); - } - else if EQ("settable") { - lua_settable(L, getnum); - } - else if EQ("next") { - lua_next(L, -2); - } - else if EQ("concat") { - lua_concat(L, getnum); - } - else if EQ("rawcall") { - int narg = getnum; - int nres = getnum; - lua_rawcall(L, narg, nres); - } - else if EQ("call") { - int narg = getnum; - int nres = getnum; - lua_call(L, narg, nres); - } - else if EQ("dostring") { - lua_dostring(L, luaL_check_string(L, getnum)); - } - else if EQ("settagmethod") { - int tag = getnum; - const char *event = getname; - lua_settagmethod(L, tag, event); - } - else if EQ("gettagmethod") { - int tag = getnum; - const char *event = getname; - lua_gettagmethod(L, tag, event); - } - else if EQ("type") { - lua_pushstring(L, lua_typename(L, lua_type(L, getnum))); - } - else luaL_verror(L, "unknown instruction %.30s", buff); - } - return 0; -} - -/* }====================================================== */ - - - -static const struct luaL_reg tests_funcs[] = { - {"hash", hash_query}, - {"limits", get_limits}, - {"listcode", listcode}, - {"liststrings", liststrings}, - {"listlocals", listlocals}, - {"loadlib", loadlib}, - {"querystr", string_query}, - {"querytab", table_query}, - {"testC", testC}, - {"ref", tref}, - {"getref", getref}, - {"unref", unref}, - {"newuserdata", newuserdata}, - {"udataval", udataval}, - {"newstate", newstate}, - {"closestate", closestate}, - {"doremote", doremote}, - {"settagmethod", settagmethod}, - {"equal", equal}, - {"totalmem", mem_query} -}; - - -void luaB_opentests (lua_State *L) { - lua_newtable(L); - lua_getglobals(L); - lua_pushvalue(L, -2); - lua_setglobals(L); - luaL_openl(L, tests_funcs); /* open functions inside new table */ - lua_setglobals(L); /* restore old table of globals */ - lua_setglobal(L, "T"); /* set new table as global T */ -} - -#endif diff --git a/src/lua/ltm.c b/src/lua/ltm.c deleted file mode 100644 index 3f69a6ca..00000000 --- a/src/lua/ltm.c +++ /dev/null @@ -1,163 +0,0 @@ -/* -** $Id: ltm.c,v 1.3 2001/11/26 23:00:26 darkgod Exp $ -** Tag methods -** See Copyright Notice in lua.h -*/ - - -#include -#include - -#include "lua.h" - -#include "ldo.h" -#include "lmem.h" -#include "lobject.h" -#include "lstate.h" -#include "ltm.h" - - -const char *const luaT_eventname[] = { /* ORDER TM */ - "gettable", "settable", "index", "getglobal", "setglobal", "add", "sub", - "mul", "div", "pow", "unm", "lt", "concat", "gc", "function", - "le", "gt", "ge", /* deprecated options!! */ - NULL -}; - - -static int findevent (const char *name) { - int i; - for (i=0; luaT_eventname[i]; i++) - if (strcmp(luaT_eventname[i], name) == 0) - return i; - return -1; /* name not found */ -} - - -static int luaI_checkevent (lua_State *L, const char *name, int t) { - int e = findevent(name); - if (e >= TM_N) - luaO_verror(L, "event `%.50s' is deprecated", name); - if (e == TM_GC && t == LUA_TTABLE) - luaO_verror(L, "event `gc' for tables is deprecated"); - if (e < 0) - luaO_verror(L, "`%.50s' is not a valid event name", name); - return e; -} - - - -/* events in LUA_TNIL are all allowed, since this is used as a -* 'placeholder' for "default" fallbacks -*/ -/* ORDER LUA_T, ORDER TM */ -static const char luaT_validevents[NUM_TAGS][TM_N] = { - {1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_TUSERDATA */ - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, /* LUA_TNIL */ - {1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}, /* LUA_TNUMBER */ - {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, /* LUA_TSTRING */ - {0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1}, /* LUA_TTABLE */ - {1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0} /* LUA_TFUNCTION */ -}; - -int luaT_validevent (int t, int e) { /* ORDER LUA_T */ - return (t >= NUM_TAGS) ? 1 : luaT_validevents[t][e]; -} - - -static void init_entry (lua_State *L, int tag) { - int i; - for (i=0; iTMtable[tag].collected = NULL; -} - - -void luaT_init (lua_State *L) { - int t; - luaM_growvector(L, L->TMtable, 0, NUM_TAGS, struct TM, "", MAX_INT); - L->nblocks += NUM_TAGS*sizeof(struct TM); - L->last_tag = NUM_TAGS-1; - for (t=0; t<=L->last_tag; t++) - init_entry(L, t); -} - - -LUA_API int lua_newtag (lua_State *L) { - luaM_growvector(L, L->TMtable, L->last_tag, 1, struct TM, - "tag table overflow", MAX_INT); - L->nblocks += sizeof(struct TM); - L->last_tag++; - init_entry(L, L->last_tag); - return L->last_tag; -} - - -static void checktag (lua_State *L, int tag) { - if (!(0 <= tag && tag <= L->last_tag)) - luaO_verror(L, "%d is not a valid tag", tag); -} - -void luaT_realtag (lua_State *L, int tag) { - if (!validtag(tag)) - luaO_verror(L, "tag %d was not created by `newtag'", tag); -} - - -LUA_API int lua_copytagmethods (lua_State *L, int tagto, int tagfrom) { - int e; - checktag(L, tagto); - checktag(L, tagfrom); - for (e=0; eu.d.tag; - case LUA_TTABLE: return hvalue(o)->htag; - default: return t; - } -} - - -LUA_API void lua_gettagmethod (lua_State *L, int t, const char *event) { - int e; - e = luaI_checkevent(L, event, t); - checktag(L, t); - if (luaT_validevent(t, e) && luaT_gettm(L, t, e)) { - clvalue(L->top) = luaT_gettm(L, t, e); - ttype(L->top) = LUA_TFUNCTION; - } - else - ttype(L->top) = LUA_TNIL; - incr_top; -} - - -LUA_API void lua_settagmethod (lua_State *L, int t, const char *event) { - int e = luaI_checkevent(L, event, t); - checktag(L, t); - if (!luaT_validevent(t, e)) - luaO_verror(L, "cannot change `%.20s' tag method for type `%.20s'%.20s", - luaT_eventname[e], luaO_typenames[t], - (t == LUA_TTABLE || t == LUA_TUSERDATA) ? - " with default tag" : ""); - switch (ttype(L->top - 1)) { - case LUA_TNIL: - luaT_gettm(L, t, e) = NULL; - break; - case LUA_TFUNCTION: - luaT_gettm(L, t, e) = clvalue(L->top - 1); - break; - default: - lua_error(L, "tag method must be a function (or nil)"); - } - L->top--; -} - diff --git a/src/lua/ltm.h b/src/lua/ltm.h deleted file mode 100644 index f6be13ed..00000000 --- a/src/lua/ltm.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -** $Id: ltm.h,v 1.3 2001/11/26 23:00:26 darkgod Exp $ -** Tag methods -** See Copyright Notice in lua.h -*/ - -#ifndef ltm_h -#define ltm_h - - -#include "lobject.h" -#include "lstate.h" - -/* -* WARNING: if you change the order of this enumeration, -* grep "ORDER TM" -*/ -typedef enum { - TM_GETTABLE = 0, - TM_SETTABLE, - TM_INDEX, - TM_GETGLOBAL, - TM_SETGLOBAL, - TM_ADD, - TM_SUB, - TM_MUL, - TM_DIV, - TM_POW, - TM_UNM, - TM_LT, - TM_CONCAT, - TM_GC, - TM_FUNCTION, - TM_N /* number of elements in the enum */ -} TMS; - - -struct TM { - Closure *method[TM_N]; - TString *collected; /* list of garbage-collected udata with this tag */ -}; - - -#define luaT_gettm(L,tag,event) (L->TMtable[tag].method[event]) -#define luaT_gettmbyObj(L,o,e) (luaT_gettm((L),luaT_tag(o),(e))) - - -#define validtag(t) (NUM_TAGS <= (t) && (t) <= L->last_tag) - -extern const char *const luaT_eventname[]; - - -void luaT_init (lua_State *L); -void luaT_realtag (lua_State *L, int tag); -int luaT_tag (const TObject *o); -int luaT_validevent (int t, int e); /* used by compatibility module */ - - -#endif diff --git a/src/lua/lua.h b/src/lua/lua.h deleted file mode 100644 index 87d64e71..00000000 --- a/src/lua/lua.h +++ /dev/null @@ -1,248 +0,0 @@ -/* -** $Id: lua.h,v 1.2 2001/11/26 23:00:26 darkgod Exp $ -** Lua - An Extensible Extension Language -** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil -** e-mail: lua@tecgraf.puc-rio.br -** www: http://www.tecgraf.puc-rio.br/lua/ -** See Copyright Notice at the end of this file -*/ - - -#ifndef lua_h -#define lua_h - - -/* definition of `size_t' */ -#include - - -/* mark for all API functions */ -#ifndef LUA_API -#define LUA_API extern -#endif - - -#define LUA_VERSION "Lua 4.0" -#define LUA_COPYRIGHT "Copyright (C) 1994-2000 TeCGraf, PUC-Rio" -#define LUA_AUTHORS "W. Celes, R. Ierusalimschy & L. H. de Figueiredo" - - -/* name of global variable with error handler */ -#define LUA_ERRORMESSAGE "_ERRORMESSAGE" - - -/* pre-defined references */ -#define LUA_NOREF (-2) -#define LUA_REFNIL (-1) -#define LUA_REFREGISTRY 0 - -/* pre-defined tags */ -#define LUA_ANYTAG (-1) -#define LUA_NOTAG (-2) - - -/* option for multiple returns in lua_call */ -#define LUA_MULTRET (-1) - - -/* minimum stack available for a C function */ -#define LUA_MINSTACK 20 - - -/* error codes for lua_do* */ -#define LUA_ERRRUN 1 -#define LUA_ERRFILE 2 -#define LUA_ERRSYNTAX 3 -#define LUA_ERRMEM 4 -#define LUA_ERRERR 5 - - -typedef struct lua_State lua_State; - -typedef int (*lua_CFunction) (lua_State *L); - -/* -** types returned by `lua_type' -*/ -#define LUA_TNONE (-1) - -#define LUA_TUSERDATA 0 -#define LUA_TNIL 1 -#define LUA_TNUMBER 2 -#define LUA_TSTRING 3 -#define LUA_TTABLE 4 -#define LUA_TFUNCTION 5 - - - -/* -** state manipulation -*/ -LUA_API lua_State *lua_open (int stacksize); -LUA_API void lua_close (lua_State *L); - - -/* -** basic stack manipulation -*/ -LUA_API int lua_gettop (lua_State *L); -LUA_API void lua_settop (lua_State *L, int index); -LUA_API void lua_pushvalue (lua_State *L, int index); -LUA_API void lua_remove (lua_State *L, int index); -LUA_API void lua_insert (lua_State *L, int index); -LUA_API int lua_stackspace (lua_State *L); - - -/* -** access functions (stack -> C) -*/ - -LUA_API int lua_type (lua_State *L, int index); -LUA_API const char *lua_typename (lua_State *L, int t); -LUA_API int lua_isnumber (lua_State *L, int index); -LUA_API int lua_isstring (lua_State *L, int index); -LUA_API int lua_iscfunction (lua_State *L, int index); -LUA_API int lua_tag (lua_State *L, int index); - -LUA_API int lua_equal (lua_State *L, int index1, int index2); -LUA_API int lua_lessthan (lua_State *L, int index1, int index2); - -LUA_API long lua_tonumber (lua_State *L, int index); -LUA_API const char *lua_tostring (lua_State *L, int index); -LUA_API size_t lua_strlen (lua_State *L, int index); -LUA_API lua_CFunction lua_tocfunction (lua_State *L, int index); -LUA_API void *lua_touserdata (lua_State *L, int index); -LUA_API const void *lua_topointer (lua_State *L, int index); - - -/* -** push functions (C -> stack) -*/ -LUA_API void lua_pushnil (lua_State *L); -LUA_API void lua_pushnumber (lua_State *L, long n); -LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len); -LUA_API void lua_pushstring (lua_State *L, const char *s); -LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n); -LUA_API void lua_pushusertag (lua_State *L, void *u, int tag); - - -/* -** get functions (Lua -> stack) -*/ -LUA_API void lua_getglobal (lua_State *L, const char *name); -LUA_API void lua_gettable (lua_State *L, int index); -LUA_API void lua_rawget (lua_State *L, int index); -LUA_API void lua_rawgeti (lua_State *L, int index, int n); -LUA_API void lua_getglobals (lua_State *L); -LUA_API void lua_gettagmethod (lua_State *L, int tag, const char *event); -LUA_API int lua_getref (lua_State *L, int ref); -LUA_API void lua_newtable (lua_State *L); - - -/* -** set functions (stack -> Lua) -*/ -LUA_API void lua_setglobal (lua_State *L, const char *name); -LUA_API void lua_settable (lua_State *L, int index); -LUA_API void lua_rawset (lua_State *L, int index); -LUA_API void lua_rawseti (lua_State *L, int index, int n); -LUA_API void lua_setglobals (lua_State *L); -LUA_API void lua_settagmethod (lua_State *L, int tag, const char *event); -LUA_API int lua_ref (lua_State *L, int lock); - - -/* -** "do" functions (run Lua code) -*/ -LUA_API int lua_call (lua_State *L, int nargs, int nresults); -LUA_API void lua_rawcall (lua_State *L, int nargs, int nresults); -LUA_API int lua_dofile (lua_State *L, const char *filename); -LUA_API int lua_dostring (lua_State *L, const char *str); -LUA_API int lua_dobuffer (lua_State *L, const char *buff, size_t size, const char *name); - -/* -** Garbage-collection functions -*/ -LUA_API int lua_getgcthreshold (lua_State *L); -LUA_API int lua_getgccount (lua_State *L); -LUA_API void lua_setgcthreshold (lua_State *L, int newthreshold); - -/* -** miscellaneous functions -*/ -LUA_API int lua_newtag (lua_State *L); -LUA_API int lua_copytagmethods (lua_State *L, int tagto, int tagfrom); -LUA_API void lua_settag (lua_State *L, int tag); - -LUA_API void lua_error (lua_State *L, const char *s); - -LUA_API void lua_unref (lua_State *L, int ref); - -LUA_API int lua_next (lua_State *L, int index); -LUA_API int lua_getn (lua_State *L, int index); - -LUA_API void lua_concat (lua_State *L, int n); - -LUA_API void *lua_newuserdata (lua_State *L, size_t size); - - -/* -** =============================================================== -** some useful macros -** =============================================================== -*/ - -#define lua_pop(L,n) lua_settop(L, -(n)-1) - -#define lua_register(L,n,f) (lua_pushcfunction(L, f), lua_setglobal(L, n)) -#define lua_pushuserdata(L,u) lua_pushusertag(L, u, 0) -#define lua_pushcfunction(L,f) lua_pushcclosure(L, f, 0) -#define lua_clonetag(L,t) lua_copytagmethods(L, lua_newtag(L), (t)) - -#define lua_isfunction(L,n) (lua_type(L,n) == LUA_TFUNCTION) -#define lua_istable(L,n) (lua_type(L,n) == LUA_TTABLE) -#define lua_isuserdata(L,n) (lua_type(L,n) == LUA_TUSERDATA) -#define lua_isnil(L,n) (lua_type(L,n) == LUA_TNIL) -#define lua_isnull(L,n) (lua_type(L,n) == LUA_TNONE) - -#define lua_getregistry(L) lua_getref(L, LUA_REFREGISTRY) - -#endif - - - -/****************************************************************************** -* Copyright (C) 1994-2000 TeCGraf, PUC-Rio. All rights reserved. -* -* Permission is hereby granted, without written agreement and without license -* or royalty fees, to use, copy, modify, and distribute this software and its -* documentation for any purpose, including commercial applications, subject to -* the following conditions: -* -* - The above copyright notice and this permission notice shall appear in all -* copies or substantial portions of this software. -* -* - The origin of this software must not be misrepresented; you must not -* claim that you wrote the original software. If you use this software in a -* product, an acknowledgment in the product documentation would be greatly -* appreciated (but it is not required). -* -* - Altered source versions must be plainly marked as such, and must not be -* misrepresented as being the original software. -* -* The authors specifically disclaim any warranties, including, but not limited -* to, the implied warranties of merchantability and fitness for a particular -* purpose. The software provided hereunder is on an "as is" basis, and the -* authors have no obligation to provide maintenance, support, updates, -* enhancements, or modifications. In no event shall TeCGraf, PUC-Rio, or the -* authors be held liable to any party for direct, indirect, special, -* incidental, or consequential damages arising out of the use of this software -* and its documentation. -* -* The Lua language and this implementation have been entirely designed and -* written by Waldemar Celes Filho, Roberto Ierusalimschy and -* Luiz Henrique de Figueiredo at TeCGraf, PUC-Rio. -* -* This implementation contains no third-party code. -******************************************************************************/ - diff --git a/src/lua/lua2c.lua b/src/lua/lua2c.lua deleted file mode 100644 index 3f8d1716..00000000 --- a/src/lua/lua2c.lua +++ /dev/null @@ -1,29 +0,0 @@ --- lua2c.lua --- embed lua code into C source --- celetecgraf.puc-rio.br --- dez 2000 - -function embed (code) - - -- clean Lua code - local s = clean(code) - if not s then - error("parser error in embedded code") - end - - -- convert to C - output('\n { /* begin embedded lua code */\n') - output(' static unsigned char B[] = {\n ') - local t={n=0} - local b = gsub(s,'(.)',function (c) - local e = '' - %t.n=%t.n+1 if %t.n==15 then %t.n=0 e='\n ' end - return format('%3u,%s',strbyte(c),e) - end - ) - output(b..strbyte(" ")) - output('\n };\n') - output(' lua_dobuffer(tolua_S,(char*)B,sizeof(B),"'..fn..': embedded Lua code");') - output(' } /* end of embedded lua code */\n\n') -end - diff --git a/src/lua/luadebug.h b/src/lua/luadebug.h deleted file mode 100644 index 21522445..00000000 --- a/src/lua/luadebug.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -** $Id: luadebug.h,v 1.2 2001/11/26 23:00:26 darkgod Exp $ -** Debugging API -** See Copyright Notice in lua.h -*/ - - -#ifndef luadebug_h -#define luadebug_h - - -#include "lua.h" - -typedef struct lua_Debug lua_Debug; /* activation record */ -typedef struct lua_Localvar lua_Localvar; - -typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); - - -LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); -LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); -LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); -LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); - -LUA_API lua_Hook lua_setcallhook (lua_State *L, lua_Hook func); -LUA_API lua_Hook lua_setlinehook (lua_State *L, lua_Hook func); - - -#define LUA_IDSIZE 60 - -struct lua_Debug { - const char *event; /* `call', `return' */ - int currentline; /* (l) */ - const char *name; /* (n) */ - const char *namewhat; /* (n) `global', `tag method', `local', `field' */ - int nups; /* (u) number of upvalues */ - int linedefined; /* (S) */ - const char *what; /* (S) `Lua' function, `C' function, Lua `main' */ - const char *source; /* (S) */ - char short_src[LUA_IDSIZE]; /* (S) */ - /* private part */ - struct lua_TObject *_func; /* active function */ -}; - - -#endif diff --git a/src/lua/lualib.h b/src/lua/lualib.h deleted file mode 100644 index 89f5519f..00000000 --- a/src/lua/lualib.h +++ /dev/null @@ -1,34 +0,0 @@ -/* -** $Id: lualib.h,v 1.2 2001/11/26 23:00:26 darkgod Exp $ -** Lua standard libraries -** See Copyright Notice in lua.h -*/ - - -#ifndef lualib_h -#define lualib_h - -#include "lua.h" - - -#ifndef LUALIB_API -#define LUALIB_API extern -#endif - - -#define LUA_ALERT "_ALERT" - -LUALIB_API void lua_baselibopen (lua_State *L); -LUALIB_API void lua_iolibopen (lua_State *L); -LUALIB_API void lua_strlibopen (lua_State *L); -LUALIB_API void lua_mathlibopen (lua_State *L); -LUALIB_API void lua_dblibopen (lua_State *L); - - - -/* Auxiliary functions (private) */ - -const char *luaI_classend (lua_State *L, const char *p); -int luaI_singlematch (int c, const char *p, const char *ep); - -#endif diff --git a/src/lua/lundump.c b/src/lua/lundump.c deleted file mode 100644 index 7f69573e..00000000 --- a/src/lua/lundump.c +++ /dev/null @@ -1,244 +0,0 @@ -/* -** $Id: lundump.c,v 1.3 2001/11/26 23:00:26 darkgod Exp $ -** load bytecodes from files -** See Copyright Notice in lua.h -*/ - -#include -#include - -#include "lfunc.h" -#include "lmem.h" -#include "lopcodes.h" -#include "lstring.h" -#include "lundump.h" - -#define LoadByte ezgetc - -static const char* ZNAME (ZIO* Z) -{ - const char* s=zname(Z); - return (*s=='@') ? s+1 : s; -} - -static void unexpectedEOZ (lua_State* L, ZIO* Z) -{ - luaO_verror(L,"unexpected end of file in `%.99s'",ZNAME(Z)); -} - -static int ezgetc (lua_State* L, ZIO* Z) -{ - int c=zgetc(Z); - if (c==EOZ) unexpectedEOZ(L,Z); - return c; -} - -static void ezread (lua_State* L, ZIO* Z, void* b, int n) -{ - int r=zread(Z,b,n); - if (r!=0) unexpectedEOZ(L,Z); -} - -static void LoadBlock (lua_State* L, void* b, size_t size, ZIO* Z, int swap) -{ - if (swap) - { - char *p=(char *) b+size-1; - int n=size; - while (n--) *p--=(char)ezgetc(L,Z); - } - else - ezread(L,Z,b,size); -} - -static void LoadVector (lua_State* L, void* b, int m, size_t size, ZIO* Z, int swap) -{ - if (swap) - { - char *q=(char *) b; - while (m--) - { - char *p=q+size-1; - int n=size; - while (n--) *p--=(char)ezgetc(L,Z); - q+=size; - } - } - else - ezread(L,Z,b,m*size); -} - -static int LoadInt (lua_State* L, ZIO* Z, int swap) -{ - int x; - LoadBlock(L,&x,sizeof(x),Z,swap); - return x; -} - -static size_t LoadSize (lua_State* L, ZIO* Z, int swap) -{ - size_t x; - LoadBlock(L,&x,sizeof(x),Z,swap); - return x; -} - -static Number LoadNumber (lua_State* L, ZIO* Z, int swap) -{ - Number x; - LoadBlock(L,&x,sizeof(x),Z,swap); - return x; -} - -static TString* LoadString (lua_State* L, ZIO* Z, int swap) -{ - size_t size=LoadSize(L,Z,swap); - if (size==0) - return NULL; - else - { - char* s=luaO_openspace(L,size); - LoadBlock(L,s,size,Z,0); - return luaS_newlstr(L,s,size-1); /* remove trailing '\0' */ - } -} - -static void LoadCode (lua_State* L, Proto* tf, ZIO* Z, int swap) -{ - int size=LoadInt(L,Z,swap); - tf->code=luaM_newvector(L,size,Instruction); - LoadVector(L,tf->code,size,sizeof(*tf->code),Z,swap); - if (tf->code[size-1]!=OP_END) luaO_verror(L,"bad code in `%.99s'",ZNAME(Z)); - luaF_protook(L,tf,size); -} - -static void LoadLocals (lua_State* L, Proto* tf, ZIO* Z, int swap) -{ - int i,n; - tf->nlocvars=n=LoadInt(L,Z,swap); - tf->locvars=luaM_newvector(L,n,LocVar); - for (i=0; ilocvars[i].varname=LoadString(L,Z,swap); - tf->locvars[i].startpc=LoadInt(L,Z,swap); - tf->locvars[i].endpc=LoadInt(L,Z,swap); - } -} - -static void LoadLines (lua_State* L, Proto* tf, ZIO* Z, int swap) -{ - int n; - tf->nlineinfo=n=LoadInt(L,Z,swap); - tf->lineinfo=luaM_newvector(L,n,int); - LoadVector(L,tf->lineinfo,n,sizeof(*tf->lineinfo),Z,swap); -} - -static Proto* LoadFunction (lua_State* L, ZIO* Z, int swap); - -static void LoadConstants (lua_State* L, Proto* tf, ZIO* Z, int swap) -{ - int i,n; - tf->nkstr=n=LoadInt(L,Z,swap); - tf->kstr=luaM_newvector(L,n,TString*); - for (i=0; ikstr[i]=LoadString(L,Z,swap); - tf->nknum=n=LoadInt(L,Z,swap); - tf->knum=luaM_newvector(L,n,Number); - LoadVector(L,tf->knum,n,sizeof(*tf->knum),Z,swap); - tf->nkproto=n=LoadInt(L,Z,swap); - tf->kproto=luaM_newvector(L,n,Proto*); - for (i=0; ikproto[i]=LoadFunction(L,Z,swap); -} - -static Proto* LoadFunction (lua_State* L, ZIO* Z, int swap) -{ - Proto* tf=luaF_newproto(L); - tf->source=LoadString(L,Z,swap); - tf->lineDefined=LoadInt(L,Z,swap); - tf->numparams=LoadInt(L,Z,swap); - tf->is_vararg=LoadByte(L,Z); - tf->maxstacksize=LoadInt(L,Z,swap); - LoadLocals(L,tf,Z,swap); - LoadLines(L,tf,Z,swap); - LoadConstants(L,tf,Z,swap); - LoadCode(L,tf,Z,swap); - return tf; -} - -static void LoadSignature (lua_State* L, ZIO* Z) -{ - const char* s=SIGNATURE; - while (*s!=0 && ezgetc(L,Z)==*s) - ++s; - if (*s!=0) luaO_verror(L,"bad signature in `%.99s'",ZNAME(Z)); -} - -static void TestSize (lua_State* L, int s, const char* what, ZIO* Z) -{ - int r=ezgetc(L,Z); - if (r!=s) - luaO_verror(L,"virtual machine mismatch in `%.99s':\n" - " %.20s is %d but read %d",ZNAME(Z),what,s,r); -} - -#define TESTSIZE(s) TestSize(L,s,#s,Z) -#define V(v) v/16,v%16 - -static int LoadHeader (lua_State* L, ZIO* Z) -{ - int version,swap; - Number f=0,tf=TEST_NUMBER; - LoadSignature(L,Z); - version=ezgetc(L,Z); - if (version>VERSION) - luaO_verror(L,"`%.99s' too new:\n" - " read version %d.%d; expected at most %d.%d", - ZNAME(Z),V(version),V(VERSION)); - if (version" -#define SOURCE tf->lineDefined,tf->source->str -#define IN_FMT " in %p " SOURCE_FMT -#define IN tf,SOURCE - -/* a multiple of PI for testing native format */ -/* multiplying by 1E8 gives non-trivial integer values */ -#define TEST_NUMBER 3 - -#endif diff --git a/src/lua/lvm.c b/src/lua/lvm.c deleted file mode 100644 index e304e11e..00000000 --- a/src/lua/lvm.c +++ /dev/null @@ -1,710 +0,0 @@ -/* -** $Id: lvm.c,v 1.5 2004/06/04 13:42:10 neil Exp $ -** Lua virtual machine -** See Copyright Notice in lua.h -*/ - - -#include -#include -#include - -#include "lua.h" - -#include "lapi.h" -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lgc.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lstate.h" -#include "lstring.h" -#include "ltable.h" -#include "ltm.h" -#include "lvm.h" - - -#ifdef OLD_ANSI -#define strcoll(a,b) strcmp(a,b) -#endif - - - -/* -** Extra stack size to run a function: -** TAG_LINE(1), NAME(1), TM calls(3) (plus some extra...) -*/ -#define EXTRA_STACK 8 - - - -int luaV_tonumber (TObject *obj) { - if (ttype(obj) != LUA_TSTRING) - return 1; - else { - if (!luaO_str2d(svalue(obj), &nvalue(obj))) - return 2; - ttype(obj) = LUA_TNUMBER; - return 0; - } -} - - -int luaV_tostring (lua_State *L, TObject *obj) { /* LUA_NUMBER */ - if (ttype(obj) != LUA_TNUMBER) - return 1; - else { - char s[32]; /* 16 digits, sign, point and \0 (+ some extra...) */ - lua_number2str(s, nvalue(obj)); /* convert `s' to number */ - tsvalue(obj) = luaS_new(L, s); - ttype(obj) = LUA_TSTRING; - return 0; - } -} - - -static void traceexec (lua_State *L, StkId base, StkId top, lua_Hook linehook) { - CallInfo *ci = infovalue(base-1); - int *lineinfo = ci->func->f.l->lineinfo; - int pc = (*ci->pc - ci->func->f.l->code) - 1; - int newline; - if (pc == 0) { /* may be first time? */ - ci->line = 1; - ci->refi = 0; - ci->lastpc = pc+1; /* make sure it will call linehook */ - } - newline = luaG_getline(lineinfo, pc, ci->line, &ci->refi); - /* calls linehook when enters a new line or jumps back (loop) */ - if (newline != ci->line || pc <= ci->lastpc) { - ci->line = newline; - L->top = top; - luaD_lineHook(L, base-2, newline, linehook); - } - ci->lastpc = pc; -} - - -static Closure *luaV_closure (lua_State *L, int nelems) { - Closure *c = luaF_newclosure(L, nelems); - L->top -= nelems; - while (nelems--) - c->upvalue[nelems] = *(L->top+nelems); - clvalue(L->top) = c; - ttype(L->top) = LUA_TFUNCTION; - incr_top; - return c; -} - - -void luaV_Cclosure (lua_State *L, lua_CFunction c, int nelems) { - Closure *cl = luaV_closure(L, nelems); - cl->f.c = c; - cl->isC = 1; -} - - -void luaV_Lclosure (lua_State *L, Proto *l, int nelems) { - Closure *cl = luaV_closure(L, nelems); - cl->f.l = l; - cl->isC = 0; -} - - -/* -** Function to index a table. -** Receives the table at `t' and the key at top. -*/ -const TObject *luaV_gettable (lua_State *L, StkId t) { - Closure *tm; - int tg; - if (ttype(t) == LUA_TTABLE && /* `t' is a table? */ - ((tg = hvalue(t)->htag) == LUA_TTABLE || /* with default tag? */ - luaT_gettm(L, tg, TM_GETTABLE) == NULL)) { /* or no TM? */ - /* do a primitive get */ - const TObject *h = luaH_get(L, hvalue(t), L->top-1); - /* result is no nil or there is no `index' tag method? */ - if (ttype(h) != LUA_TNIL || ((tm=luaT_gettm(L, tg, TM_INDEX)) == NULL)) - return h; /* return result */ - /* else call `index' tag method */ - } - else { /* try a `gettable' tag method */ - tm = luaT_gettmbyObj(L, t, TM_GETTABLE); - } - if (tm != NULL) { /* is there a tag method? */ - luaD_checkstack(L, 2); - *(L->top+1) = *(L->top-1); /* key */ - *L->top = *t; /* table */ - clvalue(L->top-1) = tm; /* tag method */ - ttype(L->top-1) = LUA_TFUNCTION; - L->top += 2; - luaD_call(L, L->top - 3, 1); - return L->top - 1; /* call result */ - } - else { /* no tag method */ - luaG_typeerror(L, t, "index"); - return NULL; /* to avoid warnings */ - } -} - - -/* -** Receives table at `t', key at `key' and value at top. -*/ -void luaV_settable (lua_State *L, StkId t, StkId key) { - int tg; - if (ttype(t) == LUA_TTABLE && /* `t' is a table? */ - ((tg = hvalue(t)->htag) == LUA_TTABLE || /* with default tag? */ - luaT_gettm(L, tg, TM_SETTABLE) == NULL)) /* or no TM? */ - *luaH_set(L, hvalue(t), key) = *(L->top-1); /* do a primitive set */ - else { /* try a `settable' tag method */ - Closure *tm = luaT_gettmbyObj(L, t, TM_SETTABLE); - if (tm != NULL) { - luaD_checkstack(L, 3); - *(L->top+2) = *(L->top-1); - *(L->top+1) = *key; - *(L->top) = *t; - clvalue(L->top-1) = tm; - ttype(L->top-1) = LUA_TFUNCTION; - L->top += 3; - luaD_call(L, L->top - 4, 0); /* call `settable' tag method */ - } - else /* no tag method... */ - luaG_typeerror(L, t, "index"); - } -} - - -const TObject *luaV_getglobal (lua_State *L, TString *s) { - const TObject *value = luaH_getstr(L->gt, s); - Closure *tm = luaT_gettmbyObj(L, value, TM_GETGLOBAL); - if (tm == NULL) /* is there a tag method? */ - return value; /* default behavior */ - else { /* tag method */ - luaD_checkstack(L, 3); - clvalue(L->top) = tm; - ttype(L->top) = LUA_TFUNCTION; - tsvalue(L->top+1) = s; /* global name */ - ttype(L->top+1) = LUA_TSTRING; - *(L->top+2) = *value; - L->top += 3; - luaD_call(L, L->top - 3, 1); - return L->top - 1; - } -} - - -void luaV_setglobal (lua_State *L, TString *s) { - const TObject *oldvalue = luaH_getstr(L->gt, s); - Closure *tm = luaT_gettmbyObj(L, oldvalue, TM_SETGLOBAL); - if (tm == NULL) { /* is there a tag method? */ - if (oldvalue != &luaO_nilobject) { - /* cast to remove `const' is OK, because `oldvalue' != luaO_nilobject */ - *(TObject *)oldvalue = *(L->top - 1); - } - else { - TObject key; - ttype(&key) = LUA_TSTRING; - tsvalue(&key) = s; - *luaH_set(L, L->gt, &key) = *(L->top - 1); - } - } - else { - luaD_checkstack(L, 3); - *(L->top+2) = *(L->top-1); /* new value */ - *(L->top+1) = *oldvalue; - ttype(L->top) = LUA_TSTRING; - tsvalue(L->top) = s; - clvalue(L->top-1) = tm; - ttype(L->top-1) = LUA_TFUNCTION; - L->top += 3; - luaD_call(L, L->top - 4, 0); - } -} - - -static int call_binTM (lua_State *L, StkId top, TMS event) { - /* try first operand */ - Closure *tm = luaT_gettmbyObj(L, top-2, event); - L->top = top; - if (tm == NULL) { - tm = luaT_gettmbyObj(L, top-1, event); /* try second operand */ - if (tm == NULL) { - tm = luaT_gettm(L, 0, event); /* try a `global' method */ - if (tm == NULL) - return 0; /* error */ - } - } - lua_pushstring(L, luaT_eventname[event]); - luaD_callTM(L, tm, 3, 1); - return 1; -} - - -static void call_arith (lua_State *L, StkId top, TMS event) { - if (!call_binTM(L, top, event)) - luaG_binerror(L, top-2, LUA_TNUMBER, "perform arithmetic on"); -} - - -static int luaV_strcomp (const TString *ls, const TString *rs) { - const char *l = ls->str; - size_t ll = ls->len; - const char *r = rs->str; - size_t lr = rs->len; - for (;;) { - int temp = strcoll(l, r); - if (temp != 0) return temp; - else { /* strings are equal up to a '\0' */ - size_t len = strlen(l); /* index of first '\0' in both strings */ - if (len == ll) /* l is finished? */ - return (len == lr) ? 0 : -1; /* l is equal or smaller than r */ - else if (len == lr) /* r is finished? */ - return 1; /* l is greater than r (because l is not finished) */ - /* both strings longer than `len'; go on comparing (after the '\0') */ - len++; - l += len; ll -= len; r += len; lr -= len; - } - } -} - - -int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r, StkId top) { - if (ttype(l) == LUA_TNUMBER && ttype(r) == LUA_TNUMBER) - return (nvalue(l) < nvalue(r)); - else if (ttype(l) == LUA_TSTRING && ttype(r) == LUA_TSTRING) - return (luaV_strcomp(tsvalue(l), tsvalue(r)) < 0); - else { /* call TM */ - luaD_checkstack(L, 2); - *top++ = *l; - *top++ = *r; - if (!call_binTM(L, top, TM_LT)) - luaG_ordererror(L, top-2); - L->top--; - return (ttype(L->top) != LUA_TNIL); - } -} - - -void luaV_strconc (lua_State *L, int total, StkId top) { - do { - int n = 2; /* number of elements handled in this pass (at least 2) */ - if (tostring(L, top-2) || tostring(L, top-1)) { - if (!call_binTM(L, top, TM_CONCAT)) - luaG_binerror(L, top-2, LUA_TSTRING, "concat"); - } - else if (tsvalue(top-1)->len > 0) { /* if len=0, do nothing */ - /* at least two string values; get as many as possible */ - lint32 tl = (lint32)tsvalue(top-1)->len + - (lint32)tsvalue(top-2)->len; - char *buffer; - int i; - while (n < total && !tostring(L, top-n-1)) { /* collect total length */ - tl += tsvalue(top-n-1)->len; - n++; - } - if (tl > MAX_SIZET) lua_error(L, "string size overflow"); - buffer = luaO_openspace(L, tl); - tl = 0; - for (i=n; i>0; i--) { /* concat all strings */ - size_t l = tsvalue(top-i)->len; - memcpy(buffer+tl, tsvalue(top-i)->str, l); - tl += l; - } - tsvalue(top-n) = luaS_newlstr(L, buffer, tl); - } - total -= n-1; /* got `n' strings to create 1 new */ - top -= n-1; - } while (total > 1); /* repeat until only 1 result left */ -} - - -static void luaV_pack (lua_State *L, StkId firstelem) { - int i; - Hash *htab = luaH_new(L, 0); - for (i=0; firstelem+itop; i++) - *luaH_setint(L, htab, i+1) = *(firstelem+i); - /* store counter in field `n' */ - luaH_setstrnum(L, htab, luaS_new(L, "n"), i); - L->top = firstelem; /* remove elements from the stack */ - ttype(L->top) = LUA_TTABLE; - hvalue(L->top) = htab; - incr_top; -} - - -static void adjust_varargs (lua_State *L, StkId base, int nfixargs) { - int nvararg = (L->top-base) - nfixargs; - if (nvararg < 0) - luaD_adjusttop(L, base, nfixargs); - luaV_pack(L, base+nfixargs); -} - - - -#define dojump(pc, i) { int d = GETARG_S(i); pc += d; } - -/* -** Executes the given Lua function. Parameters are between [base,top). -** Returns n such that the the results are between [n,top). -*/ -StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) { - const Proto *const tf = cl->f.l; - StkId top; /* keep top local, for performance */ - const Instruction *pc = tf->code; - TString **const kstr = tf->kstr; - const lua_Hook linehook = L->linehook; - infovalue(base-1)->pc = &pc; - luaD_checkstack(L, tf->maxstacksize+EXTRA_STACK); - if (tf->is_vararg) /* varargs? */ - adjust_varargs(L, base, tf->numparams); - else - luaD_adjusttop(L, base, tf->numparams); - top = L->top; - /* main loop of interpreter */ - for (;;) { - const Instruction i = *pc++; - if (linehook) - traceexec(L, base, top, linehook); - switch (GET_OPCODE(i)) { - case OP_END: { - L->top = top; - return top; - } - case OP_RETURN: { - L->top = top; - return base+GETARG_U(i); - } - case OP_CALL: { - int nres = GETARG_B(i); - if (nres == MULT_RET) nres = LUA_MULTRET; - L->top = top; - luaD_call(L, base+GETARG_A(i), nres); - top = L->top; - break; - } - case OP_TAILCALL: { - L->top = top; - luaD_call(L, base+GETARG_A(i), LUA_MULTRET); - return base+GETARG_B(i); - } - case OP_PUSHNIL: { - int n = GETARG_U(i); - LUA_ASSERT(n>0, "invalid argument"); - do { - ttype(top++) = LUA_TNIL; - } while (--n > 0); - break; - } - case OP_POP: { - top -= GETARG_U(i); - break; - } - case OP_PUSHINT: { - ttype(top) = LUA_TNUMBER; - nvalue(top) = (Number)GETARG_S(i); - top++; - break; - } - case OP_PUSHSTRING: { - ttype(top) = LUA_TSTRING; - tsvalue(top) = kstr[GETARG_U(i)]; - top++; - break; - } - case OP_PUSHNUM: { - ttype(top) = LUA_TNUMBER; - nvalue(top) = tf->knum[GETARG_U(i)]; - top++; - break; - } - case OP_PUSHNEGNUM: { - ttype(top) = LUA_TNUMBER; - nvalue(top) = -tf->knum[GETARG_U(i)]; - top++; - break; - } - case OP_PUSHUPVALUE: { - *top++ = cl->upvalue[GETARG_U(i)]; - break; - } - case OP_GETLOCAL: { - *top++ = *(base+GETARG_U(i)); - break; - } - case OP_GETGLOBAL: { - L->top = top; - *top = *luaV_getglobal(L, kstr[GETARG_U(i)]); - top++; - break; - } - case OP_GETTABLE: { - L->top = top; - top--; - *(top-1) = *luaV_gettable(L, top-1); - break; - } - case OP_GETDOTTED: { - ttype(top) = LUA_TSTRING; - tsvalue(top) = kstr[GETARG_U(i)]; - L->top = top+1; - *(top-1) = *luaV_gettable(L, top-1); - break; - } - case OP_GETINDEXED: { - *top = *(base+GETARG_U(i)); - L->top = top+1; - *(top-1) = *luaV_gettable(L, top-1); - break; - } - case OP_PUSHSELF: { - TObject receiver; - receiver = *(top-1); - ttype(top) = LUA_TSTRING; - tsvalue(top++) = kstr[GETARG_U(i)]; - L->top = top; - *(top-2) = *luaV_gettable(L, top-2); - *(top-1) = receiver; - break; - } - case OP_CREATETABLE: { - L->top = top; - luaC_checkGC(L); - hvalue(top) = luaH_new(L, GETARG_U(i)); - ttype(top) = LUA_TTABLE; - top++; - break; - } - case OP_SETLOCAL: { - *(base+GETARG_U(i)) = *(--top); - break; - } - case OP_SETGLOBAL: { - L->top = top; - luaV_setglobal(L, kstr[GETARG_U(i)]); - top--; - break; - } - case OP_SETTABLE: { - StkId t = top-GETARG_A(i); - L->top = top; - luaV_settable(L, t, t+1); - top -= GETARG_B(i); /* pop values */ - break; - } - case OP_SETLIST: { - int aux = GETARG_A(i) * LFIELDS_PER_FLUSH; - int n = GETARG_B(i); - Hash *arr = hvalue(top-n-1); - L->top = top-n; /* final value of `top' (in case of errors) */ - for (; n; n--) - *luaH_setint(L, arr, n+aux) = *(--top); - break; - } - case OP_SETMAP: { - int n = GETARG_U(i); - StkId finaltop = top-2*n; - Hash *arr = hvalue(finaltop-1); - L->top = finaltop; /* final value of `top' (in case of errors) */ - for (; n; n--) { - top-=2; - *luaH_set(L, arr, top) = *(top+1); - } - break; - } - case OP_ADD: { - if (tonumber(top-2) || tonumber(top-1)) - call_arith(L, top, TM_ADD); - else - nvalue(top-2) += nvalue(top-1); - top--; - break; - } - case OP_ADDI: { - if (tonumber(top-1)) { - ttype(top) = LUA_TNUMBER; - nvalue(top) = (Number)GETARG_S(i); - call_arith(L, top+1, TM_ADD); - } - else - nvalue(top-1) += (Number)GETARG_S(i); - break; - } - case OP_SUB: { - if (tonumber(top-2) || tonumber(top-1)) - call_arith(L, top, TM_SUB); - else - nvalue(top-2) -= nvalue(top-1); - top--; - break; - } - case OP_MULT: { - if (tonumber(top-2) || tonumber(top-1)) - call_arith(L, top, TM_MUL); - else - nvalue(top-2) *= nvalue(top-1); - top--; - break; - } - case OP_DIV: { - if (tonumber(top-2) || tonumber(top-1)) - call_arith(L, top, TM_DIV); - else - nvalue(top-2) /= nvalue(top-1); - top--; - break; - } - case OP_POW: { - if (!call_binTM(L, top, TM_POW)) - lua_error(L, "undefined operation"); - top--; - break; - } - case OP_CONCAT: { - int n = GETARG_U(i); - luaV_strconc(L, n, top); - top -= n-1; - L->top = top; - luaC_checkGC(L); - break; - } - case OP_MINUS: { - if (tonumber(top-1)) { - ttype(top) = LUA_TNIL; - call_arith(L, top+1, TM_UNM); - } - else - nvalue(top-1) = -nvalue(top-1); - break; - } - case OP_NOT: { - ttype(top-1) = - (ttype(top-1) == LUA_TNIL) ? LUA_TNUMBER : LUA_TNIL; - nvalue(top-1) = 1; - break; - } - case OP_JMPNE: { - top -= 2; - if (!luaO_equalObj(top, top+1)) dojump(pc, i); - break; - } - case OP_JMPEQ: { - top -= 2; - if (luaO_equalObj(top, top+1)) dojump(pc, i); - break; - } - case OP_JMPLT: { - top -= 2; - if (luaV_lessthan(L, top, top+1, top+2)) dojump(pc, i); - break; - } - case OP_JMPLE: { /* a <= b === !(b b === (b= b === !(a 0 ? - nvalue(top-3) > nvalue(top-2) : - nvalue(top-3) < nvalue(top-2)) { /* `empty' loop? */ - top -= 3; /* remove control variables */ - dojump(pc, i); /* jump to loop end */ - } - break; - } - case OP_FORLOOP: { - LUA_ASSERT(ttype(top-1) == LUA_TNUMBER, "invalid step"); - LUA_ASSERT(ttype(top-2) == LUA_TNUMBER, "invalid limit"); - if (ttype(top-3) != LUA_TNUMBER) - lua_error(L, "`for' index must be a number"); - nvalue(top-3) += nvalue(top-1); /* increment index */ - if (nvalue(top-1) > 0 ? - nvalue(top-3) > nvalue(top-2) : - nvalue(top-3) < nvalue(top-2)) - top -= 3; /* end loop: remove control variables */ - else - dojump(pc, i); /* repeat loop */ - break; - } - case OP_LFORPREP: { - Node *node; - if (ttype(top-1) != LUA_TTABLE) - lua_error(L, "`for' table must be a table"); - node = luaH_next(L, hvalue(top-1), &luaO_nilobject); - if (node == NULL) { /* `empty' loop? */ - top--; /* remove table */ - dojump(pc, i); /* jump to loop end */ - } - else { - top += 2; /* index,value */ - *(top-2) = *key(node); - *(top-1) = *val(node); - } - break; - } - case OP_LFORLOOP: { - Node *node; - LUA_ASSERT(ttype(top-3) == LUA_TTABLE, "invalid table"); - node = luaH_next(L, hvalue(top-3), top-2); - if (node == NULL) /* end loop? */ - top -= 3; /* remove table, key, and value */ - else { - *(top-2) = *key(node); - *(top-1) = *val(node); - dojump(pc, i); /* repeat loop */ - } - break; - } - case OP_CLOSURE: { - L->top = top; - luaV_Lclosure(L, tf->kproto[GETARG_A(i)], GETARG_B(i)); - top = L->top; - luaC_checkGC(L); - break; - } - } - } -} diff --git a/src/lua/lvm.h b/src/lua/lvm.h deleted file mode 100644 index ac95ae41..00000000 --- a/src/lua/lvm.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -** $Id: lvm.h,v 1.3 2001/11/26 23:00:26 darkgod Exp $ -** Lua virtual machine -** See Copyright Notice in lua.h -*/ - -#ifndef lvm_h -#define lvm_h - - -#include "ldo.h" -#include "lobject.h" -#include "ltm.h" - - -#define tonumber(o) ((ttype(o) != LUA_TNUMBER) && (luaV_tonumber(o) != 0)) -#define tostring(L,o) ((ttype(o) != LUA_TSTRING) && (luaV_tostring(L, o) != 0)) - - -int luaV_tonumber (TObject *obj); -int luaV_tostring (lua_State *L, TObject *obj); -const TObject *luaV_gettable (lua_State *L, StkId t); -void luaV_settable (lua_State *L, StkId t, StkId key); -const TObject *luaV_getglobal (lua_State *L, TString *s); -void luaV_setglobal (lua_State *L, TString *s); -StkId luaV_execute (lua_State *L, const Closure *cl, StkId base); -void luaV_Cclosure (lua_State *L, lua_CFunction c, int nelems); -void luaV_Lclosure (lua_State *L, Proto *l, int nelems); -int luaV_lessthan (lua_State *L, const TObject *l, const TObject *r, StkId top); -void luaV_strconc (lua_State *L, int total, StkId top); - -#endif diff --git a/src/lua/lzio.c b/src/lua/lzio.c deleted file mode 100644 index 84d4a35c..00000000 --- a/src/lua/lzio.c +++ /dev/null @@ -1,84 +0,0 @@ -/* -** $Id: lzio.c,v 1.5 2004/06/04 13:42:10 neil Exp $ -** a generic input stream interface -** See Copyright Notice in lua.h -*/ - - - -#include -#include - -#include "lua.h" - -#include "lzio.h" - - - -/* ----------------------------------------------------- memory buffers --- */ - -static int zmfilbuf (ZIO* z) { - (void)z; /* to avoid warnings */ - return EOZ; -} - - -ZIO* zmopen (ZIO* z, const char* b, size_t size, const char *name) { - if (b==NULL) return NULL; - z->n = size; - z->p = (const unsigned char *)b; - z->filbuf = zmfilbuf; - z->u = NULL; - z->name = name; - return z; -} - -/* ------------------------------------------------------------ strings --- */ - -ZIO* zsopen (ZIO* z, const char* s, const char *name) { - if (s==NULL) return NULL; - return zmopen(z, s, strlen(s), name); -} - -/* -------------------------------------------------------------- FILEs --- */ - -static int zffilbuf (ZIO* z) { - size_t n; - if (feof((FILE *)z->u)) return EOZ; - n = fread(z->buffer, 1, ZBSIZE, (FILE *)z->u); - if (n==0) return EOZ; - z->n = n-1; - z->p = z->buffer; - return *(z->p++); -} - - -ZIO* zFopen (ZIO* z, FILE* f, const char *name) { - if (f==NULL) return NULL; - z->n = 0; - z->p = z->buffer; - z->filbuf = zffilbuf; - z->u = f; - z->name = name; - return z; -} - - -/* --------------------------------------------------------------- read --- */ -size_t zread (ZIO *z, void *b, size_t n) { - while (n) { - size_t m; - if (z->n == 0) { - if (z->filbuf(z) == EOZ) - return n; /* return number of missing bytes */ - zungetc(z); /* put result from `filbuf' in the buffer */ - } - m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ - memcpy(b, z->p, m); - z->n -= m; - z->p += m; - b = (char *)b + m; - n -= m; - } - return 0; -} diff --git a/src/lua/lzio.h b/src/lua/lzio.h deleted file mode 100644 index 45feeee3..00000000 --- a/src/lua/lzio.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -** $Id: lzio.h,v 1.5 2004/06/04 13:42:10 neil Exp $ -** Buffered streams -** See Copyright Notice in lua.h -*/ - - -#ifndef lzio_h -#define lzio_h - -#include - - - -/* For Lua only */ -#define zFopen luaZ_Fopen -#define zsopen luaZ_sopen -#define zmopen luaZ_mopen -#define zread luaZ_read - -#define EOZ (-1) /* end of stream */ - -typedef struct zio ZIO; - -ZIO* zFopen (ZIO* z, FILE* f, const char *name); /* open FILEs */ -ZIO* zsopen (ZIO* z, const char* s, const char *name); /* string */ -ZIO* zmopen (ZIO* z, const char* b, size_t size, const char *name); /* memory */ - -size_t zread (ZIO* z, void* b, size_t n); /* read next n bytes */ - -#define zgetc(z) (((z)->n--)>0 ? ((int)*(z)->p++): (z)->filbuf(z)) -#define zungetc(z) (++(z)->n,--(z)->p) -#define zname(z) ((z)->name) - - - -/* --------- Private Part ------------------ */ - -#ifndef ZBSIZE -#define ZBSIZE 256 /* buffer size */ -#endif - -struct zio { - size_t n; /* bytes still unread */ - const unsigned char* p; /* current position in buffer */ - int (*filbuf)(ZIO* z); - void* u; /* additional data */ - const char *name; - unsigned char buffer[ZBSIZE]; /* buffer */ -}; - - -#endif diff --git a/src/lua/module.lua b/src/lua/module.lua deleted file mode 100644 index 98dffe6e..00000000 --- a/src/lua/module.lua +++ /dev/null @@ -1,69 +0,0 @@ --- tolua: module class --- Written by Waldemar Celes --- TeCGraf/PUC-Rio --- Jul 1998 --- $Id: module.lua,v 1.2 2001/11/26 23:00:26 darkgod Exp $ - --- This code is free software; you can redistribute it and/or modify it. --- The software provided hereunder is on an "as is" basis, and --- the author has no obligation to provide maintenance, support, updates, --- enhancements, or modifications. - - - --- Module class --- Represents module. --- The following fields are stored: --- {i} = list of objects in the module. -classModule = { - _base = classContainer, - type = 'module' -} -settag(classModule,tolua_tag) - --- register module -function classModule:register () - output(' tolua_module(tolua_S,"'..self.name..'");') - local i=1 - while self[i] do - self[i]:register() - i = i+1 - end -end - --- unregister module -function classModule:unregister () - output(' lua_pushnil(tolua_S); lua_setglobal(tolua_S,"'..self.name..'");') -end - --- Print method -function classModule:print (ident,close) - print(ident.."Module{") - print(ident.." name = '"..self.name.."';") - local i=1 - while self[i] do - self[i]:print(ident.." ",",") - i = i+1 - end - print(ident.."}"..close) -end - --- Internal constructor -function _Module (t) - t._base = classModule - settag(t,tolua_tag) - append(t) - return t -end - --- Constructor --- Expects two string representing the module name and body. -function Module (n,b) - local t = _Module(_Container{name=n}) - push(t) - t:parse(strsub(b,2,strlen(b)-1)) -- eliminate braces - pop() - return t -end - - diff --git a/src/lua/operator.lua b/src/lua/operator.lua deleted file mode 100644 index 7a42cf1b..00000000 --- a/src/lua/operator.lua +++ /dev/null @@ -1,111 +0,0 @@ --- tolua: operator class --- Written by Waldemar Celes --- TeCGraf/PUC-Rio --- Jul 1998 --- $Id: operator.lua,v 1.2 2001/11/26 23:00:27 darkgod Exp $ - --- This code is free software; you can redistribute it and/or modify it. --- The software provided hereunder is on an "as is" basis, and --- the author has no obligation to provide maintenance, support, updates, --- enhancements, or modifications. - - --- Operator class --- Represents an operator function or a class operator method. --- It stores the same fields as functions do plus: --- kind = set of character representing the operator (as it appers in C++ code) -classOperator = { - kind = '', - _base = classFunction, -} -settag(classOperator,tolua_tag) - --- table to transform operator kind into the appropriate tag method name -_TM = {['+'] = 'operator_add', - ['-'] = 'operator_sub', - ['*'] = 'operator_mul', - ['/'] = 'operator_div', - ['<'] = 'operator_lt', - ['[]'] = 'operator_get', - ['&[]'] = 'operator_set', - } - - --- Print method -function classOperator:print (ident,close) - print(ident.."Operator{") - print(ident.." kind = '"..self.kind.."',") - print(ident.." mod = '"..self.mod.."',") - print(ident.." type = '"..self.type.."',") - print(ident.." ptr = '"..self.ptr.."',") - print(ident.." name = '"..self.name.."',") - print(ident.." const = '"..self.const.."',") - print(ident.." cname = '"..self.cname.."',") - print(ident.." lname = '"..self.lname.."',") - print(ident.." args = {") - local i=1 - while self.args[i] do - self.args[i]:print(ident.." ",",") - i = i+1 - end - print(ident.." }") - print(ident.."}"..close) -end - --- Internal constructor -function _Operator (t) - t._base = classOperator - settag(t,tolua_tag) - - if t.const ~= 'const' and t.const ~= '' then - error("#invalid 'const' specification") - end - - append(t) - if not t:inclass() then - error("#operator can only be defined as class member") - end - - t.cname = t:cfuncname("toluaI")..t:overload(t) - t.name = t.name..t.kind - return t -end - --- Constructor --- Expects three strings: one representing the function declaration, --- another representing the argument list, and the third representing --- the "const" or empty string. -function Operator (d,k,a,c) - local t = split(strsub(a,2,strlen(a)-1),',') -- eliminate braces - local i=1 - local l = {n=0} - while t[i] do - l.n = l.n+1 - l[l.n] = Declaration(t[i],'var') - i = i+1 - end - if k == '[]' then - d = gsub(d,'&','') - elseif k=='&[]' then - l.n = l.n+1 - l[l.n] = Declaration(d,'var') - l[l.n].name = 'toluaI_value' - end - local f = Declaration(d,'func') - if k == '[]' and (l[1]==nil or isbasic(l[1].type)~='number') then - error('operator[] can only be defined for numeric index.') - end - f.args = l - f.const = c - f.kind = gsub(k,"%s","") - f.lname = _TM[f.kind] - if not f.lname then - error("tolua: no support for operator" .. f.kind) - end - if f.kind == '[]' and not strfind(f.mod,'const') then - Operator(d,'&'..k,a,c) -- create correspoding set operator - end - return _Operator(f) -end - - diff --git a/src/lua/package.lua b/src/lua/package.lua deleted file mode 100644 index 42dbfaac..00000000 --- a/src/lua/package.lua +++ /dev/null @@ -1,222 +0,0 @@ --- tolua: package class --- Written by Waldemar Celes --- TeCGraf/PUC-Rio --- Jul 1998 --- $Id: package.lua,v 1.4 2002/01/03 13:45:08 takkaria Exp $ - --- This code is free software; you can redistribute it and/or modify it. --- The software provided hereunder is on an "as is" basis, and --- the author has no obligation to provide maintenance, support, updates, --- enhancements, or modifications. - - - --- Package class --- Represents the whole package being bound. --- The following fields are stored: --- {i} = list of objects in the package. -classPackage = { - _base = classContainer, - type = 'package' -} -settag(classPackage,tolua_tag) - --- Print method -function classPackage:print () - print("Package: "..self.name) - local i=1 - while self[i] do - self[i]:print("","") - i = i+1 - end -end - -function classPackage:preprocess () - self.code = "\n"..self.code -- add a blank sentinel line - -- avoid preprocessing verbatim lines - local V = {} - self.code = gsub(self.code,"\n(%s*%$[^%[%]][^\n]*)",function (v) - tinsert(%V,v) - return "\n$"..getn(%V).."$" - end) - -- avoid preprocessing embedded lua code - local C = {} - self.code = gsub(self.code,"\n%s*%$%[","\1") -- deal with embedded Lua code - self.code = gsub(self.code,"\n%s*%$%]","\2") - self.code = gsub(self.code,"(%b\1\2)", function (c) - tinsert(%C,c) - return "\n$["..getn(%C).."]$" - end) - -- perform global substitution - - self.code = gsub(self.code,"(//[^\n]*)","") -- eliminate C++ comments - self.code = gsub(self.code,"/%*","\1") - self.code = gsub(self.code,"%*/","\2") - self.code = gsub(self.code,"%b\1\2","") - self.code = gsub(self.code,"\1","/%*") - self.code = gsub(self.code,"\2","%*/") - self.code = gsub(self.code,"%s*@%s*","@") -- eliminate spaces beside @ - self.code = gsub(self.code,"%s?inline(%s)","%1") -- eliminate 'inline' keyword - self.code = gsub(self.code,"%s?extern(%s)","%1") -- eliminate 'extern' keyword - self.code = gsub(self.code,"%s?virtual(%s)","%1") -- eliminate 'virtual' keyword - self.code = gsub(self.code,"public:","") -- eliminate 'public:' keyword - self.code = gsub(self.code,"([^%w_])void%s*%*","%1_userdata ") -- substitute 'void*' - self.code = gsub(self.code,"([^%w_])void%s*%*","%1_userdata ") -- substitute 'void*' - self.code = gsub(self.code,"([^%w_])char%s*%*","%1_cstring ") -- substitute 'char*' - - -- restore embedded code - self.code = gsub(self.code,"%$%[(%d+)%]%$",function (n) - return %C[tonumber(n)] - end) - -- restore verbatim lines - self.code = gsub(self.code,"%$(%d+)%$",function (n) - return %V[tonumber(n)] - end) -end - --- translate verbatim -function classPackage:preamble () - output('/*\n') - output('** Lua binding: '..self.name..'\n') - output('** Generated automatically by '..TOLUA_VERSION..'\n') - output('*/\n\n') - - output('#include "lua/tolua.h"\n\n') - - if not flags.h then - output('/* Exported function */') - output('int tolua_'..self.name..'_open (lua_State* tolua_S);') - output('void tolua_'..self.name..'_close (lua_State* tolua_S);') - output('\n') - end - - local i=1 - while self[i] do - self[i]:preamble() - i = i+1 - end - output('\n') - output('/* function to register type */') - output('static void toluaI_reg_types (lua_State* tolua_S)') - output('{') - foreach(_usertype,function(n,v) output(' tolua_usertype(tolua_S,"',v,'");') end) - output('}') - output('\n') - - output('/* error messages */') - output('#define TOLUA_ERR_SELF tolua_error(tolua_S,\"invalid \'self\'\")') - output('#define TOLUA_ERR_ASSIGN tolua_error(tolua_S,\"#vinvalid type in variable assignment.\")') - output('\n') -end - --- register package --- write package open function -function classPackage:register () - output("/* Open function */") - output("int tolua_"..self.name.."_open (lua_State* tolua_S)") - output("{") - output(" tolua_open(tolua_S);") - output(" toluaI_reg_types(tolua_S);") - local i=1 - while self[i] do - self[i]:register() - i = i+1 - end - output(" return 1;") - output("}") -end - --- unregister package --- write package close function -function classPackage:unregister () - output("/* Close function */") - output("void tolua_"..self.name.."_close (lua_State* tolua_S)") - output("{") - local i=1 - while self[i] do - self[i]:unregister() - i = i+1 - end - output("}") -end - --- write header file -function classPackage:header () - output('/*\n') output('** Lua binding: '..self.name..'\n') - output('** Generated automatically by '..TOLUA_VERSION..'.\n') - output('*/\n\n') - - if not flags.h then - output('/* Exported function */') - output('int tolua_'..self.name..'_open (lua_State* tolua_S);') - output('void tolua_'..self.name..'_close (lua_State* tolua_S);') - output('\n') - end -end - --- Internal constructor -function _Package (t) - t._base = classPackage - settag(t,tolua_tag) - return t -end - --- Constructor --- Expects the base file name. --- It assumes the file has extension ".pkg". -function Package (name) - -- read file - local code = read("*a") - code = "\n" .. code -- add sentinel - -- deal with include directive - local nsubst - repeat - code,nsubst = gsub(code,"\n%s*%$<(.-)>%s*\n",function (fn) - local fp,msg = openfile(fn,'r') - if not fp then - error('#'..msg..': '..fn) - end - local s = read(fp,'*a') - closefile(fp) - return "\n" .. s - end) - until nsubst==0 - - -- deal with include directive for C/C++ header files - local nsubst - repeat - code,nsubst = - gsub(code,"\n%s*%${(.-)}%s*\n", - function (fn) - local fp,msg = openfile(fn,'r') - if not fp then - error('#'..msg..': '..fn) - end - local s = read(fp,'*a') - closefile(fp) - -- extract marked code - local T = {code="\n"} - s= "\n" .. s .. "\n" -- add blank lines as sentinels - -- extract one-line statments - gsub(s,"\n(.-)[Tt][Oo][Ll][Uu][Aa]_[Ee][Xx][Pp][Oo][Rr][Tt][^\n]*\n", - function (c) %T.code = %T.code .. c .. "\n" end - ) - -- extract multiline statments - gsub(s,"\n[^\n]*[Tt][Oo][Ll][Uu][Aa]_[Bb][Ee][Gg][Ii][Nn][^\n]*".. - "(.-)" .. - "\n[^\n]*[Tt][Oo][Ll][Uu][Aa]_[Ee][Nn][Dd][^\n]*\n", - function (c) %T.code = %T.code .. c .. "\n" end - ) - return T.code - end) - until nsubst==0 - - local t = _Package(_Container{name=name, code=code}) - push(t) - t:preprocess() - t:parse(t.code) - pop() - return t -end - - diff --git a/src/lua/print.h b/src/lua/print.h deleted file mode 100644 index 49f4c4cb..00000000 --- a/src/lua/print.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -** $Id: print.h,v 1.2 2001/11/26 23:00:27 darkgod Exp $ -** extracted automatically from lopcodes.h by mkprint.lua -- DO NOT EDIT -** See Copyright Notice in lua.h -*/ - - case OP_END: P_OP("END"); P_NONE; break; - case OP_RETURN: P_OP("RETURN"); P_U; break; - case OP_CALL: P_OP("CALL"); P_AB; break; - case OP_TAILCALL: P_OP("TAILCALL"); P_AB; break; - case OP_PUSHNIL: P_OP("PUSHNIL"); P_U; break; - case OP_POP: P_OP("POP"); P_U; break; - case OP_PUSHINT: P_OP("PUSHINT"); P_S; break; - case OP_PUSHSTRING: P_OP("PUSHSTRING"); P_Q; break; - case OP_PUSHNUM: P_OP("PUSHNUM"); P_N; break; - case OP_PUSHNEGNUM: P_OP("PUSHNEGNUM"); P_N; break; - case OP_PUSHUPVALUE: P_OP("PUSHUPVALUE"); P_U; break; - case OP_GETLOCAL: P_OP("GETLOCAL"); P_L; break; - case OP_GETGLOBAL: P_OP("GETGLOBAL"); P_K; break; - case OP_GETTABLE: P_OP("GETTABLE"); P_NONE; break; - case OP_GETDOTTED: P_OP("GETDOTTED"); P_K; break; - case OP_GETINDEXED: P_OP("GETINDEXED"); P_L; break; - case OP_PUSHSELF: P_OP("PUSHSELF"); P_K; break; - case OP_CREATETABLE: P_OP("CREATETABLE"); P_U; break; - case OP_SETLOCAL: P_OP("SETLOCAL"); P_L; break; - case OP_SETGLOBAL: P_OP("SETGLOBAL"); P_K; break; - case OP_SETTABLE: P_OP("SETTABLE"); P_AB; break; - case OP_SETLIST: P_OP("SETLIST"); P_AB; break; - case OP_SETMAP: P_OP("SETMAP"); P_U; break; - case OP_ADD: P_OP("ADD"); P_NONE; break; - case OP_ADDI: P_OP("ADDI"); P_S; break; - case OP_SUB: P_OP("SUB"); P_NONE; break; - case OP_MULT: P_OP("MULT"); P_NONE; break; - case OP_DIV: P_OP("DIV"); P_NONE; break; - case OP_POW: P_OP("POW"); P_NONE; break; - case OP_CONCAT: P_OP("CONCAT"); P_U; break; - case OP_MINUS: P_OP("MINUS"); P_NONE; break; - case OP_NOT: P_OP("NOT"); P_NONE; break; - case OP_JMPNE: P_OP("JMPNE"); P_J; break; - case OP_JMPEQ: P_OP("JMPEQ"); P_J; break; - case OP_JMPLT: P_OP("JMPLT"); P_J; break; - case OP_JMPLE: P_OP("JMPLE"); P_J; break; - case OP_JMPGT: P_OP("JMPGT"); P_J; break; - case OP_JMPGE: P_OP("JMPGE"); P_J; break; - case OP_JMPT: P_OP("JMPT"); P_J; break; - case OP_JMPF: P_OP("JMPF"); P_J; break; - case OP_JMPONT: P_OP("JMPONT"); P_J; break; - case OP_JMPONF: P_OP("JMPONF"); P_J; break; - case OP_JMP: P_OP("JMP"); P_J; break; - case OP_PUSHNILJMP: P_OP("PUSHNILJMP"); P_NONE; break; - case OP_FORPREP: P_OP("FORPREP"); P_J; break; - case OP_FORLOOP: P_OP("FORLOOP"); P_J; break; - case OP_LFORPREP: P_OP("LFORPREP"); P_J; break; - case OP_LFORLOOP: P_OP("LFORLOOP"); P_J; break; - case OP_CLOSURE: P_OP("CLOSURE"); P_F; break; diff --git a/src/lua/tolua.c b/src/lua/tolua.c deleted file mode 100644 index 3cb09291..00000000 --- a/src/lua/tolua.c +++ /dev/null @@ -1,149 +0,0 @@ -/* tolua -** Support code for Lua bindings. -** Written by Waldemar Celes -** TeCGraf/PUC-Rio -** Jul 1998 -** $Id: tolua.c,v 1.4 2004/06/04 13:42:10 neil Exp $ -*/ - -/* This code is free software; you can redistribute it and/or modify it. -** The software provided hereunder is on an "as is" basis, and -** the author has no obligation to provide maintenance, support, updates, -** enhancements, or modifications. -*/ - -#include "tolua.h" -#include "lua.h" -#include "lualib.h" - -#include -#include -#include - - -static void help (void) -{ - fprintf(stderr,"\n" - "usage: tolua [options] input_file\n" - "\n" - "Command line options are:\n" - " -v : print version information.\n" - " -o file : set output file; default is stdout.\n" - " -H file : create include file.\n" - " -n name : set package name; default is input file root name.\n" - " -p : parse only.\n" - " -P : parse and print structure information (for debug).\n" - " -h : print this message.\n" - "Should the input file be omitted, stdin is assumed;\n" - "in that case, the package name must be explicitly set.\n\n" - ); -} - -static void version (void) -{ - fprintf(stderr, "%s (written by W. Celes)\n",TOLUA_VERSION); -} - -static void setfield (lua_State* L, int table, char* f, char* v) -{ - lua_pushstring(L,f); - lua_pushstring(L,v); - lua_settable(L,table); -} - -static void error (char* o) -{ - fprintf(stderr,"tolua: unknown option '%s'\n",o); - help(); - exit(1); -} - -int main (int argc, char* argv[]) -{ - lua_State* L = lua_open(0); - lua_baselibopen(L); - lua_iolibopen(L); - lua_strlibopen(L); - lua_pushstring(L,TOLUA_VERSION); lua_setglobal(L,"TOLUA_VERSION"); - - if (argc==1) - { - help(); - return 0; - } - else - { - int i, t; - lua_newtable(L); - lua_pushvalue(L,-1); - lua_setglobal(L,"flags"); - t = lua_gettop(L); - for (i=1; i /* NULL, malloc, free */ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "lua.h" - -/* Evil hack for C++ bool_ vs. C bool. */ -#ifndef __cplusplus -typedef unsigned char bool; -#endif - -/*************************************** Exported functions */ - -int tolua_open (lua_State* L); -void tolua_using (lua_State* L, int module); -void tolua_class (lua_State* L, int derived, int base); -void tolua_instance (lua_State* L, int instance, int classobj); -void tolua_foreach (lua_State* L, int lo, int f); -int tolua_tag (lua_State* L, char* type); -const char* tolua_type (lua_State* L, int lo); -int tolua_base (lua_State* L, int lo); -int tolua_cast (lua_State* L, int lo, char* type); -void tolua_takeownership (lua_State* L, int lo); - - - -/*************************************** Support functions for binding code */ - -#define LUA_VALUE int -#define LUA_NIL 0 /* TODO */ -/*#define TOLUA_NIL (lua_pushnil(),lua_pop())*/ - -/* Register functions */ -void tolua_globalvar (lua_State* L, char* name, lua_CFunction get, lua_CFunction set); -void tolua_globalarray (lua_State* L, char* name, lua_CFunction get, lua_CFunction set); -void tolua_module (lua_State* L, char* name); -void tolua_cclass (lua_State* L, char* name, char* base); -void tolua_function (lua_State* L, char* parent, char* name, lua_CFunction func); -void tolua_constant (lua_State* L, char* parent, char* name, long value); -void tolua_tablevar -(lua_State* L, char* table, char* name, lua_CFunction get, lua_CFunction set); -void tolua_tablearray -(lua_State* L, char* table, char* name, lua_CFunction get, lua_CFunction set); - - -/* Get and push functions */ -long tolua_getnumber (lua_State* L, int narg, long def); -const char* tolua_getstring (lua_State* L, int narg, const char* def); -void* tolua_getuserdata (lua_State* L, int narg, void* def); -void* tolua_getusertype (lua_State* L, int narg, void* def); -int tolua_getvalue (lua_State* L, int narg, int def); -int tolua_getbool (lua_State* L, int narg, int def); -long tolua_getfieldnumber (lua_State* L, int lo, int index, long def); -const char* tolua_getfieldstring (lua_State* L, int lo, int index, const char* def); -void* tolua_getfielduserdata (lua_State* L, int lo, int index, void* def); -void* tolua_getfieldusertype (lua_State* L, int lo, int index, void* def); -int tolua_getfieldvalue (lua_State* L, int lo, int index, int def); -int tolua_getfieldbool (lua_State* L, int lo, int index, int def); - -void tolua_pushnumber (lua_State* L, long value); -void tolua_pushstring (lua_State* L, const char* value); -void tolua_pushuserdata (lua_State* L, void* value); -void tolua_pushusertype (lua_State* L, void* value, int tag); -void tolua_pushvalue (lua_State* L, int lo); -void tolua_pushbool (lua_State* L, int value); -void tolua_pushfieldnumber (lua_State* L, int lo, int index, long v); -void tolua_pushfieldstring (lua_State* L, int lo, int index, char* v); -void tolua_pushfielduserdata (lua_State* L, int lo, int index, void* v); -void tolua_pushfieldusertype (lua_State* L, int lo, int index, void* v, int tag); -void tolua_pushfieldvalue (lua_State* L, int lo, int index, int v); -void tolua_pushfieldbool (lua_State* L, int lo, int index, int v); - - -/* Type & tag manipulation */ -void tolua_usertype (lua_State* L, char* type); -#if 0 -void tolua_settag (lua_State* L, char* type, int* tag); -#endif -int tolua_istype (lua_State* L, int narg, int tag, int dim); -int tolua_arrayistype (lua_State* L, int narg, int tag, int dim, int def); - -int tolua_isnoobj (lua_State* L, int narg); - -/* Tag method manipulation */ -void* tolua_doclone (lua_State* L, void* value, int tag); -void* tolua_copy (lua_State* L, void* value, unsigned int size); - -/* Error handling */ -void tolua_error (lua_State* L, char* msg); - -/* Exported variables */ -extern int tolua_tag_nil; -extern int tolua_tag_number; -extern int tolua_tag_string; -extern int tolua_tag_userdata; -extern int tolua_tag_table; -extern int tolua_tag_function; - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/src/lua/tolua_bd.c b/src/lua/tolua_bd.c deleted file mode 100644 index d36a5ce9..00000000 --- a/src/lua/tolua_bd.c +++ /dev/null @@ -1,214 +0,0 @@ -/* -** Lua binding: tolua -** Generated automatically by tolua 4.0b on Tue Nov 14 14:18:50 2000. -*/ - -#include "tolua.h" - -/* Exported function */ -int tolua_tolua_open (lua_State* tolua_S); -void tolua_tolua_close (lua_State* tolua_S); - -#define tolua_using(module) (tolua_using)(tolua_S,module) -#define tolua_type(lo) (tolua_type)(tolua_S,lo) -#define tolua_foreach(lo,f) (tolua_foreach)(tolua_S,lo,f) -#define tolua_class(derived,base) (tolua_class)(tolua_S,derived,base) -#define tolua_instance(inst,cobj) (tolua_instance)(tolua_S,inst,cobj) -#define tolua_base(lo) (tolua_base)(tolua_S,lo) -#define tolua_cast(lo,type) (tolua_cast)(tolua_S,lo,type) -#define tolua_takeownership(lo) (tolua_takeownership)(tolua_S,lo) - -/* function to register type */ -static void toluaI_reg_types (lua_State* tolua_S) -{ -} - -/* function: tolua_using */ -static int toluaI_tolua_tolua_using00(lua_State* tolua_S) -{ - if ( - !tolua_isnoobj(tolua_S,2) - ) - goto tolua_lerror; - else - { - LUA_VALUE module = ((LUA_VALUE) tolua_getvalue(tolua_S,1,0)); - { - tolua_using(module); - } - } - return 0; -tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'using'."); - return 0; -} - -/* function: tolua_type */ -static int toluaI_tolua_tolua_type00(lua_State* tolua_S) -{ - if ( - !tolua_isnoobj(tolua_S,2) - ) - goto tolua_lerror; - else - { - LUA_VALUE lo = ((LUA_VALUE) tolua_getvalue(tolua_S,1,0)); - { - char* toluaI_ret = (char*) tolua_type(lo); - tolua_pushstring(tolua_S,toluaI_ret); - } - } - return 1; -tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'type'."); - return 0; -} - -/* function: tolua_foreach */ -static int toluaI_tolua_tolua_foreach00(lua_State* tolua_S) -{ - if ( - !tolua_isnoobj(tolua_S,3) - ) - goto tolua_lerror; - else - { - LUA_VALUE lo = ((LUA_VALUE) tolua_getvalue(tolua_S,1,0)); - LUA_VALUE f = ((LUA_VALUE) tolua_getvalue(tolua_S,2,0)); - { - tolua_foreach(lo,f); - } - } - return 0; -tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'foreach'."); - return 0; -} - -/* function: tolua_class */ -static int toluaI_tolua_tolua_class00(lua_State* tolua_S) -{ - if ( - !tolua_isnoobj(tolua_S,3) - ) - goto tolua_lerror; - else - { - LUA_VALUE derived = ((LUA_VALUE) tolua_getvalue(tolua_S,1,0)); - LUA_VALUE base = ((LUA_VALUE) tolua_getvalue(tolua_S,2,0)); - { - tolua_class(derived,base); - } - } - return 0; -tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'class'."); - return 0; -} - -/* function: tolua_instance */ -static int toluaI_tolua_tolua_instance00(lua_State* tolua_S) -{ - if ( - !tolua_isnoobj(tolua_S,3) - ) - goto tolua_lerror; - else - { - LUA_VALUE instance = ((LUA_VALUE) tolua_getvalue(tolua_S,1,0)); - LUA_VALUE classobj = ((LUA_VALUE) tolua_getvalue(tolua_S,2,0)); - { - tolua_instance(instance,classobj); - } - } - return 0; -tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'instance'."); - return 0; -} - -/* function: tolua_base */ -static int toluaI_tolua_tolua_base00(lua_State* tolua_S) -{ - if ( - !tolua_isnoobj(tolua_S,2) - ) - goto tolua_lerror; - else - { - LUA_VALUE lo = ((LUA_VALUE) tolua_getvalue(tolua_S,1,0)); - { - LUA_VALUE toluaI_ret = (LUA_VALUE) tolua_base(lo); - tolua_pushvalue(tolua_S,toluaI_ret); - } - } - return 1; -tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'base'."); - return 0; -} - -/* function: tolua_cast */ -static int toluaI_tolua_tolua_cast00(lua_State* tolua_S) -{ - if ( - !tolua_istype(tolua_S,2,LUA_TSTRING,0) || - !tolua_isnoobj(tolua_S,3) - ) - goto tolua_lerror; - else - { - LUA_VALUE lo = ((LUA_VALUE) tolua_getvalue(tolua_S,1,0)); - char* type = ((char*) tolua_getstring(tolua_S,2,0)); - { - LUA_VALUE toluaI_ret = (LUA_VALUE) tolua_cast(lo,type); - tolua_pushvalue(tolua_S,toluaI_ret); - } - } - return 1; -tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'cast'."); - return 0; -} - -/* function: tolua_takeownership */ -static int toluaI_tolua_tolua_takeownership00(lua_State* tolua_S) -{ - if ( - !tolua_isnoobj(tolua_S,2) - ) - goto tolua_lerror; - else - { - LUA_VALUE lo = ((LUA_VALUE) tolua_getvalue(tolua_S,1,0)); - { - tolua_takeownership(lo); - } - } - return 0; -tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'takeownership'."); - return 0; -} - -/* Open function */ -int tolua_tolua_open (lua_State* tolua_S) -{ - tolua_open(tolua_S); - toluaI_reg_types(tolua_S); - tolua_module(tolua_S,"tolua"); - tolua_function(tolua_S,"tolua","using",toluaI_tolua_tolua_using00); - tolua_function(tolua_S,"tolua","type",toluaI_tolua_tolua_type00); - tolua_function(tolua_S,"tolua","foreach",toluaI_tolua_tolua_foreach00); - tolua_function(tolua_S,"tolua","class",toluaI_tolua_tolua_class00); - tolua_function(tolua_S,"tolua","instance",toluaI_tolua_tolua_instance00); - tolua_function(tolua_S,"tolua","base",toluaI_tolua_tolua_base00); - tolua_function(tolua_S,"tolua","cast",toluaI_tolua_tolua_cast00); - tolua_function(tolua_S,"tolua","takeownership",toluaI_tolua_tolua_takeownership00); - return 1; -} -/* Close function */ -void tolua_tolua_close (lua_State* tolua_S) -{ - lua_pushnil(tolua_S); lua_setglobal(tolua_S,"tolua"); -} diff --git a/src/lua/tolua_eh.c b/src/lua/tolua_eh.c deleted file mode 100644 index 0709cb4c..00000000 --- a/src/lua/tolua_eh.c +++ /dev/null @@ -1,66 +0,0 @@ -/* tolua: error handling -** Support code for Lua bindings. -** Written by Waldemar Celes -** TeCGraf/PUC-Rio -** Jul 1998 -** $Id: tolua_eh.c,v 1.2 2001/11/26 23:00:27 darkgod Exp $ -*/ - -/* This code is free software; you can redistribute it and/or modify it. -** The software provided hereunder is on an "as is" basis, and -** the author has no obligation to provide maintenance, support, updates, -** enhancements, or modifications. -*/ - -#include "tolua.h" -#include "tolua_eh.h" -#include "tolua_rg.h" - -#include - -/* registry fiels used to hold current error info - - tolua_err_narg: number of wrong argument - - tolua_err_provided: provided type - - tolua_err_expected: expected type -*/ - -void toluaI_eh_set -(lua_State* L, int narg, const char* provided, const char* expected) -{ - lua_pushnumber(L,narg); - toluaI_setregistry(L,"tolua_err_narg"); - lua_pushstring(L,provided); - toluaI_setregistry(L,"tolua_err_provided"); - lua_pushstring(L,expected); - toluaI_setregistry(L,"tolua_err_expected"); -} - -void tolua_error (lua_State* L, char* msg) -{ - if (msg[0]=='#') - { - static char buffer[BUFSIZ]; - const char* err_provided; - const char* err_expected; - toluaI_getregistry(L,"tolua_err_provided"); - err_provided = lua_tostring(L,-1); - toluaI_getregistry(L,"tolua_err_expected"); - err_expected = lua_tostring(L,-1); - lua_pop(L,2); - if (msg[1]=='f') - { - int err_narg; - toluaI_getregistry(L,"tolua_err_narg"); - err_narg = (int)lua_tonumber(L,-1); - lua_pop(L,1); - sprintf(buffer,"%s\n argument #%d is '%s'; '%s' expected.\n", - msg+2,err_narg,err_provided,err_expected); - } - else if (msg[1]=='v') - sprintf(buffer,"%s\n value is '%s'; '%s' expected.\n", - msg+2,err_provided,err_expected); - lua_error(L,buffer); - } - else - lua_error(L,msg); -} diff --git a/src/lua/tolua_eh.h b/src/lua/tolua_eh.h deleted file mode 100644 index 168ba122..00000000 --- a/src/lua/tolua_eh.h +++ /dev/null @@ -1,24 +0,0 @@ -/* tolua: error handling -** Support code for Lua bindings. -** Written by Waldemar Celes -** TeCGraf/PUC-Rio -** Jul 1998 -** $Id: tolua_eh.h,v 1.2 2001/11/26 23:00:27 darkgod Exp $ -*/ - -/* This code is free software; you can redistribute it and/or modify it. -** The software provided hereunder is on an "as is" basis, and -** the author has no obligation to provide maintenance, support, updates, -** enhancements, or modifications. -*/ - - - -#ifndef tolua_eh_h -#define tolua_eh_h - -void toluaI_eh_set -(lua_State* L, int narg, const char* provided, const char* expected); - - -#endif diff --git a/src/lua/tolua_gp.c b/src/lua/tolua_gp.c deleted file mode 100644 index 77ff0c26..00000000 --- a/src/lua/tolua_gp.c +++ /dev/null @@ -1,197 +0,0 @@ -/* tolua: get & push functions. -** Support code for Lua bindings. -** Written by Waldemar Celes -** TeCGraf/PUC-Rio -** Jul 1998 -** $Id: tolua_gp.c,v 1.2 2001/11/26 23:00:27 darkgod Exp $ -*/ - -/* This code is free software; you can redistribute it and/or modify it. -** The software provided hereunder is on an "as is" basis, and -** the author has no obligation to provide maintenance, support, updates, -** enhancements, or modifications. -*/ - -#include "tolua.h" -#include "tolua_tm.h" - -#include -#include - -long tolua_getnumber (lua_State* L, int narg, long def) -{ - return lua_gettop(L) - -#include "tolua.h" -#include "tolua_rg.h" -#include "tolua_tm.h" -#include "tolua_tt.h" - -void tolua_globalvar (lua_State* L, char* name, lua_CFunction get, lua_CFunction set) -{ - lua_newtable(L); - lua_pushstring(L,".get"); - lua_pushcfunction(L,get); - lua_settable(L,-3); - if (set) - { - lua_pushstring(L,".set"); - lua_pushcfunction(L,set); - lua_settable(L,-3); - } - lua_pushvalue(L,-1); /* duplicate top */ - lua_setglobal(L,name); - toluaI_tm_global(L,lua_gettop(L)); - lua_pop(L,1); -} - -static int toluaI_const_global_array (lua_State* L) -{ - lua_error(L,"value of const array cannot be changed"); - return 0; -} - - -void tolua_globalarray (lua_State* L,char* name, lua_CFunction get, lua_CFunction set) -{ - int tag = lua_newtag(L); - lua_newtable(L); - lua_settag(L,tag); - lua_setglobal(L,name); - - lua_pushcfunction(L,get); - lua_settagmethod(L,tag,"gettable"); - if (set) - lua_pushcfunction(L,set); - else - lua_pushcfunction(L,toluaI_const_global_array); - lua_settagmethod(L,tag,"settable"); -} - -void tolua_tablevar -(lua_State* L, char* table, char* name, lua_CFunction get, lua_CFunction set) -{ - lua_getglobal(L,table); - - lua_pushstring(L,".get"); - lua_gettable(L,-2); - lua_pushstring(L,name); - lua_pushcfunction(L,get); - lua_settable(L,-3); - lua_pop(L,1); - if (set) - { - lua_pushstring(L,".set"); - lua_gettable(L,-2); - lua_pushstring(L,name); - lua_pushcfunction(L,set); - lua_settable(L,-3); - lua_pop(L,1); - } - - lua_pop(L,1); -} - -static int toluaI_get_array (lua_State* L) -{ - void* self = tolua_getuserdata(L,1,0); - const char* field = tolua_getstring(L,2,0); - - if (!field) - tolua_error(L,"invalid 'field' in accessing array"); - if (!self) - { - static char msg[BUFSIZ]; - sprintf(msg,"invalid 'self' in accessing array '%s'",field); - tolua_error(L,msg); - } - toluaI_getregistry(L,"tolua_tbl_itype"); - lua_pushnumber(L,lua_tag(L,1)); - lua_gettable(L,-2); - lua_getglobal(L,lua_tostring(L,-1)); - lua_pushstring(L,".array"); - lua_gettable(L,-2); - lua_pushvalue(L,2); /* field */ - lua_gettable(L,-2); - lua_pushstring(L,".self"); - lua_pushvalue(L,1); /* self */ - lua_rawset(L,-3); - return 1; -} - -static int toluaI_const_array (lua_State* L) -{ - lua_error(L,"value of const field cannot be changed"); - return 0; -} - -void tolua_tablearray -(lua_State* L, char* table, char* name, lua_CFunction get, lua_CFunction set) -{ - int tag = lua_newtag(L); - lua_getglobal(L,table); - lua_pushstring(L,".array"); - lua_rawget(L,-2); - lua_pushstring(L,name); - lua_newtable(L); - lua_settag(L,tag); - lua_settable(L,-3); - lua_pop(L,2); - - lua_pushcfunction(L,get); - lua_settagmethod(L,tag,"gettable"); - if (set) - lua_pushcfunction(L,set); - else - lua_pushcfunction(L,toluaI_const_array); - lua_settagmethod(L,tag,"settable"); - - tolua_tablevar(L,table,name,toluaI_get_array,NULL); -} - -void tolua_module (lua_State* L, char* name) -{ - lua_getglobal(L,name); - if (!lua_istable(L,-1)) - { - lua_newtable(L); - lua_pushstring(L,".get"); - lua_newtable(L); - lua_settable(L,-3); - lua_pushstring(L,".set"); - lua_newtable(L); - lua_settable(L,-3); - lua_pushvalue(L,-1); /* duplicate top */ - lua_setglobal(L,name); - toluaI_tm_module(L,lua_gettop(L)); - lua_pop(L,1); - } - lua_pop(L,1); -} - -void tolua_cclass (lua_State* L, char* name, char* base) -{ - int t; - lua_newtable(L); - lua_pushstring(L,".get"); - lua_newtable(L); - lua_settable(L,-3); - lua_pushstring(L,".set"); - lua_newtable(L); - lua_settable(L,-3); - lua_pushstring(L,".array"); - lua_newtable(L); - lua_settable(L,-3); - if (*base != 0) - { - lua_pushstring(L,".base"); - lua_getglobal(L,base); - lua_rawset(L,-3); - } - lua_pushvalue(L,-1); /* duplicate top */ - lua_setglobal(L,name); - t = lua_gettop(L); - toluaI_tm_class(L,t,name); - toluaI_tt_class(L,t,name,base); - lua_pop(L,1); -} - - -void tolua_function (lua_State* L, char* parent, char* name, lua_CFunction func) -{ - if (parent==NULL) - { - lua_pushcfunction(L,func); - lua_setglobal(L,name); - } - else - { - lua_getglobal(L,parent); - lua_pushstring(L,name); - lua_pushcfunction(L,func); - lua_settable(L,-3); - lua_pop(L,1); - } -} - -void tolua_constant (lua_State* L, char* parent, char* name, long value) -{ - if (parent==NULL) - { - lua_pushnumber(L,value); - lua_setglobal(L,name); - } - else - { - lua_getglobal(L,parent); - lua_pushstring(L,name); - lua_pushnumber(L,value); - lua_settable(L,-3); - lua_pop(L,1); - } -} - -void toluaI_setregistry (lua_State* L, char* field) -{ - lua_getregistry(L); - lua_insert(L,-2); - lua_pushstring(L,field); - lua_insert(L,-2); - lua_settable(L,-3); - lua_pop(L,1); -} - -void toluaI_getregistry (lua_State* L, char* field) -{ - lua_getregistry(L); - lua_pushstring(L,field); - lua_gettable(L,-2); - lua_insert(L,-2); - lua_pop(L,1); -} diff --git a/src/lua/tolua_rg.h b/src/lua/tolua_rg.h deleted file mode 100644 index 0feb6078..00000000 --- a/src/lua/tolua_rg.h +++ /dev/null @@ -1,22 +0,0 @@ -/* tolua: register functions -** Support code for Lua bindings. -** Written by Waldemar Celes -** TeCGraf/PUC-Rio -** Nov 200 -** $Id: tolua_rg.h,v 1.2 2001/11/26 23:00:27 darkgod Exp $ -*/ - -/* This code is free software; you can redistribute it and/or modify it. -** The software provided hereunder is on an "as is" basis, and -** the author has no obligation to provide maintenance, support, updates, -** enhancements, or modifications. -*/ - - -#ifndef tolua_rg_h -#define tolua_rg_h - -void toluaI_setregistry (lua_State* L, char* field); -void toluaI_getregistry (lua_State* L, char* field); - -#endif diff --git a/src/lua/tolua_tm.c b/src/lua/tolua_tm.c deleted file mode 100644 index 8fd7b28d..00000000 --- a/src/lua/tolua_tm.c +++ /dev/null @@ -1,585 +0,0 @@ -/* tolua: tag methods -** Support code for Lua bindings. -** Written by Waldemar Celes -** TeCGraf/PUC-Rio -** Jul 1998 -** $Id: tolua_tm.c,v 1.2 2001/11/26 23:00:27 darkgod Exp $ -*/ - -/* This code is free software; you can redistribute it and/or modify it. -** The software provided hereunder is on an "as is" basis, and -** the author has no obligation to provide maintenance, support, updates, -** enhancements, or modifications. -*/ - -#include "tolua.h" -#include "tolua_tm.h" -#include "tolua_tt.h" -#include "tolua_rg.h" - -#include - - - -/* Global tables created in Lua registry: - tolua_tbl_class: indexed by instance tags, stores the class tables. - tolua_tbl_clone: indexed by memory address, stores the tag indicanting - it is a clone. - tolua_tbl_mate: indexed by memory address, stores the associate instance - table. - - General tags stored in Lua registry: - tolua_tag_global; - tolua_tag_module; - tolua_tag_class; - tolua_tag_instance; - tolua_tag_linstance; - tolua_tag_indirect; -*/ - -/* internal function prototype */ -static void setmethods (lua_State* L); - -static void settag (lua_State* L, int lo, char* tag_registry_field) -{ - toluaI_getregistry(L,tag_registry_field); - lua_pushvalue(L,lo); - lua_settag(L,(int)lua_tonumber(L,-2)); - lua_pop(L,2); -} - -void toluaI_tm_global (lua_State* L, int lo) -{ - settag(L,lo,"tolua_tag_global"); -} - -void toluaI_tm_module (lua_State* L, int lo) -{ - settag(L,lo,"tolua_tag_module"); -} - -void toluaI_tm_setclass (lua_State* L, int lo) -{ - settag(L,lo,"tolua_tag_class"); -} - -void toluaI_tm_class (lua_State* L, int lo, char* name) -{ - int tag_class; - int tag = lua_newtag(L); - char* type = toluaI_tt_concat("class ",name); - toluaI_getregistry(L,"tolua_tag_class"); - tag_class = (int)lua_tonumber(L,-1); - lua_copytagmethods(L,tag,tag_class); - toluaI_tt_register(L,tag,type); - toluaI_tt_sethierarchy(L,tag,tag_class); - lua_pushvalue(L,lo); - lua_settag(L,tag); - lua_pop(L,2); /* tag_class and lo */ -} - -void toluaI_tm_instance (lua_State* L, int tag, int lo) -{ - toluaI_getregistry(L,"tolua_tbl_class"); - lua_pushnumber(L,tag); - lua_pushvalue(L,lo); - lua_settable(L,-3); - toluaI_getregistry(L,"tolua_tag_instance"); - lua_copytagmethods(L,tag,(int)lua_tonumber(L,-1)); - lua_pop(L,2); /* tbl_class and tag_instance */ -} - -void toluaI_tm_linstance (lua_State* L, int tag, int lo) -{ - toluaI_getregistry(L,"tolua_tbl_class"); - lua_pushnumber(L,tag); - lua_pushvalue(L,lo); - lua_settable(L,-3); - toluaI_getregistry(L,"tolua_tag_linstance"); - lua_copytagmethods(L,tag,(int)lua_tonumber(L,-1)); - lua_pop(L,2); /* tbl_class and tag_linstance */ -} - -void* tolua_doclone (lua_State* L, void* value, int tag) -{ - toluaI_getregistry(L,"tolua_tbl_clone"); - lua_pushuserdata(L,value); - lua_pushnumber(L,tag); - lua_settable(L,-3); - lua_pop(L,1); - return value; -} - -void* tolua_copy (lua_State* L, void* value, unsigned int size) -{ - void* clone = (void*)malloc(size); - if (clone) - memcpy(clone,value,size); - else - tolua_error(L,"insuficient memory"); - return clone; -} - -static void toluaI_tm_undoclone (lua_State* L, int tag, void* clone) -{ - toluaI_getregistry(L,"tolua_tbl_clone"); - lua_pushuserdata(L,clone); - lua_gettable(L,-2); - if (lua_isnumber(L,-1) && lua_tonumber(L,-1)==tag) - { - lua_pushuserdata(L,clone); - lua_pushnil(L); - lua_settable(L,-4); - - /* get base class */ - toluaI_getregistry(L,"tolua_tbl_class"); - lua_pushnumber(L,tag); - lua_rawget(L,-2); - - /* look for destructor */ - lua_pushstring(L,"delete"); - lua_gettable(L,-2); - if (lua_iscfunction(L,-1)) - { - lua_pushusertag(L,clone,tag); - lua_call(L,1,0); - } - else - { - free(clone); /* no destructor: use raw free */ - lua_pop(L,1); /* the nil function value */ - } - lua_pop(L,2); /* tbl_class and class method table */ - } - lua_pop(L,2); /* table and value */ -} - -void toluaI_tm_pushmate (lua_State* L, int lo) -{ - toluaI_getregistry(L,"tolua_tbl_mate"); - lua_pushvalue(L,lo); - lua_rawget(L,-2); - lua_insert(L,-2); - lua_pop(L,1); -} - -void toluaI_tm_pushclass (lua_State* L, int lo) -{ - toluaI_getregistry(L,"tolua_tbl_class"); - lua_pushnumber(L,lua_tag(L,lo)); - lua_rawget(L,-2); - lua_insert(L,-2); - lua_pop(L,1); -} - -int toluaI_gettag (lua_State* L, char* tagname) -{ - int tag; - toluaI_getregistry(L,tagname); - tag = (int)lua_tonumber(L,-1); - lua_pop(L,1); - return tag; -} - -void toluaI_tm_init (lua_State* L) -{ - lua_newtable(L); toluaI_setregistry(L,"tolua_tbl_class"); - lua_newtable(L); toluaI_setregistry(L,"tolua_tbl_clone"); - lua_newtable(L); toluaI_setregistry(L,"tolua_tbl_mate"); - - lua_pushnumber(L,lua_newtag(L)); toluaI_setregistry(L,"tolua_tag_global"); - lua_pushnumber(L,lua_newtag(L)); toluaI_setregistry(L,"tolua_tag_module"); - lua_pushnumber(L,lua_newtag(L)); toluaI_setregistry(L,"tolua_tag_class"); - lua_pushnumber(L,lua_newtag(L)); toluaI_setregistry(L,"tolua_tag_instance"); - lua_pushnumber(L,lua_newtag(L)); toluaI_setregistry(L,"tolua_tag_linstance"); - lua_pushnumber(L,lua_newtag(L)); toluaI_setregistry(L,"tolua_tag_indirect"); - - toluaI_tt_register(L,toluaI_gettag(L,"tolua_tag_global"),"generic variable"); - toluaI_tt_register(L,toluaI_gettag(L,"tolua_tag_module"),"generic module"); - toluaI_tt_register(L,toluaI_gettag(L,"tolua_tag_class"),"generic class"); - toluaI_tt_register(L,toluaI_gettag(L,"tolua_tag_indirect"),"generic indirect"); - toluaI_tt_register(L,toluaI_gettag(L,"tolua_tag_instance"),"generic instance"); - toluaI_tt_register(L,toluaI_gettag(L,"tolua_tag_linstance"),"generic lua instance"); - - /* allows modules and classes to be used as ordinary tables */ - toluaI_tt_sethierarchy(L,toluaI_gettag(L,"tolua_tag_module"),tolua_tag_table); - toluaI_tt_sethierarchy(L,toluaI_gettag(L,"tolua_tag_class"),tolua_tag_table); - - setmethods(L); -} - -static int map (lua_State* L) -{ - int m = lua_gettop(L); - /* do not pass string fields starting with a dot */ - if (!lua_isstring(L,1) || *lua_tostring(L,1)!='.') - { - lua_getglobals(L); - lua_pushvalue(L,1); - lua_pushvalue(L,m); - lua_rawset(L,-3); - lua_pop(L,1); - } - return 0; -} - -void toluaI_tm_using (lua_State* L, int module) -{ - lua_newtable(L); - lua_settag(L,toluaI_gettag(L,"tolua_tag_indirect")); - lua_pushstring(L,".module"); - lua_pushvalue(L,module); - lua_settable(L,-3); - - lua_getglobal(L,"foreach"); - lua_pushvalue(L,module); - lua_pushvalue(L,-3); - lua_pushcclosure(L,map,1); - lua_call(L,2,0); - - lua_getglobal(L,"foreach"); - lua_pushvalue(L,module); - lua_pushstring(L,".get"); - lua_gettable(L,-2); - lua_insert(L,-2); - lua_pop(L,1); /* module table */ - lua_pushvalue(L,-3); - lua_pushcclosure(L,map,1); - lua_call(L,2,0); - lua_pop(L,1); /* indirect table */ -} - -/********************************************************** tag methods */ - -/* tag methods coded in C */ - -/* generic gettable */ -static void oo_gettable (lua_State* L, int table, int base, int index) -{ - while (lua_istable(L,base)) - { - lua_pushvalue(L,index); - lua_rawget(L,base); - if (!lua_isnil(L,-1)) - return; /* returned value already on the top */ - else if (lua_isnumber(L,index)) - { - lua_pushstring(L,"operator_get"); - lua_rawget(L,base); - if (!lua_isnil(L,-1)) - { - lua_pushvalue(L,table); - lua_pushvalue(L,index); - lua_call(L,2,1); - return; - } - } - else - { - lua_pushstring(L,".get"); - lua_rawget(L,base); - if (!lua_isnil(L,-1)) - { - lua_pushvalue(L,index); - lua_rawget(L,-2); - if (!lua_isnil(L,-1)) - { - lua_pushvalue(L,table); - lua_pushvalue(L,index); /* need to access array field (?) */ - lua_call(L,2,1); - return; - } - } - } - lua_pushstring(L,".base"); lua_rawget(L,base); - base = lua_gettop(L); - } - lua_pushnil(L); -} - -/* generic settable */ -static int oo_settable (lua_State* L, int table, int base, int index, int value) -{ - while (lua_istable(L,base)) - { - lua_pushstring(L,".set"); - lua_rawget(L,base); - if (!lua_isnil(L,-1)) - { - lua_pushvalue(L,index); - lua_rawget(L,-2); - if (!lua_isnil(L,-1)) - { - lua_pushvalue(L,table); - lua_pushvalue(L,value); - lua_call(L,2,0); - return 1; - } - } - lua_pushstring(L,".base"); lua_rawget(L,base); - base = lua_gettop(L); - } - return 0; -} - -/* class tag methods */ -static int class_index (lua_State* L) -{ - int table = 1; - int index = 2; - oo_gettable(L,table,table,index); - return 1; -} -static int class_settable (lua_State* L) -{ - int table = 1; - int index = 2; - int value = 3; - if (oo_settable(L,table,table,index,value) == 0) - { - lua_pushvalue(L,table); - lua_pushvalue(L,index); - lua_pushvalue(L,value); - lua_rawset(L,-3); - } - return 0; -} - -/* instance tags */ -static int instance_gettable (lua_State* L) -{ - int table = 1; - int index = 2; - toluaI_tm_pushmate(L,table); /* pushes mate */ - if (!lua_isnil(L,-1)) /* if there's a mate table */ - { - lua_pushvalue(L,index); - lua_rawget(L,-2); - if (!lua_isnil(L,-1)) /* if field in mate table exists */ - return 1; - } - toluaI_tm_pushclass(L,table); /* pushes base */ - oo_gettable(L,table,lua_gettop(L),index); - return 1; -} -static int instance_settable (lua_State* L) -{ - int table = 1; - int index = 2; - int value = 3; - toluaI_tm_pushclass(L,table); /* pushes base */ - if (lua_isnumber(L,index)) - { - lua_pushstring(L,"operator_set"); - lua_rawget(L,-2); - if (!lua_isnil(L,-1)) - {/* the stack here is: table,index,value,base,operator */ - /* call operator passing table, index, and value */ - lua_insert(L,1); - lua_pop(L,1); /* base */ - lua_call(L,3,0); - return 0; - } - } - if (oo_settable(L,table,4,index,value) == 0) - { - toluaI_tm_pushmate(L,table); /* pushes mate */ - if (lua_isnil(L,-1)) - { - /* creates mate table */ - lua_newtable(L); - toluaI_getregistry(L,"tolua_tbl_mate"); - lua_pushvalue(L,table); /* that is the userdata */ - lua_pushvalue(L,-3); - lua_rawset(L,-3); - lua_pop(L,1); /* tbl_mate */ - } - /* the mate table is on the top */ - lua_pushvalue(L,index); - lua_pushvalue(L,value); - lua_rawset(L,-3); - } - return 0; -} -static int instance_gc (lua_State* L) -{ - toluaI_tm_undoclone(L,lua_tag(L,1),lua_touserdata(L,1)); - return 0; -} -static int gen_operator (lua_State* L) -{ - int op1 = 1; - int op2 = 2; - int event = 3; - char* name = toluaI_tt_concat("operator_",lua_tostring(L,event)); - lua_pushstring(L,name); - lua_gettable(L,op1); - lua_pushvalue(L,op1); - lua_pushvalue(L,op2); - lua_call(L,2,1); - return 1; -} -static int instance_operator (lua_State* L) -{ - return gen_operator(L); -} -static int instance_relational (lua_State* L) -{ - gen_operator(L); - if ((int)lua_tonumber(L,-1)==0) lua_pushnil(L); - return 1; -} - -/* lua instance tags */ -static int linstance_index (lua_State* L) -{ - toluaI_tm_pushclass(L,1); - oo_gettable(L,1,3,2); /* table,base,index */ - return 1; -} - - -/* module tag methods */ -static int module_index (lua_State* L) -{ - int table = 1; - int index = 2; - lua_pushstring(L,".get"); - lua_rawget(L,table); - if (!lua_isnil(L,-1)) - { - lua_pushvalue(L,index); - lua_rawget(L,-2); - if (!lua_isnil(L,-1)) - { - lua_call(L,0,1); - return 1; - } - } - lua_pushnil(L); - return 1; -} -static int module_settable (lua_State* L) -{ - int table = 1; - int index = 2; - int value = 3; - lua_pushstring(L,".set"); - lua_rawget(L,table); - if (!lua_isnil(L,-1)) - { - lua_pushvalue(L,index); - lua_rawget(L,-2); - if (!lua_isnil(L,-1)) - { - lua_pushvalue(L,value); - lua_call(L,1,0); - return 0; - } - } - lua_pushvalue(L,index); - lua_pushvalue(L,value); - lua_rawset(L,table); - return 0; -} - -/* global variable tag methods */ -static int global_getglobal (lua_State* L) -{ - int value = 2; - lua_pushstring(L,".get"); - lua_rawget(L,value); - lua_call(L,0,1); - return 1; -} -static int global_setglobal (lua_State* L) -{ - int value = 2; - int newvalue = 3; - lua_pushstring(L,".set"); - lua_rawget(L,value); - if (lua_isnil(L,-1)) - lua_error(L,"value of const variable cannot be changed"); - else - { - lua_pushvalue(L,newvalue); - lua_call(L,1,0); - } - return 0; -} - -/* indirect tag methods */ -static int indirect_getglobal (lua_State* L) -{ - int varname = 1; - int value = 2; - lua_pushstring(L,".module"); - lua_gettable(L,value); - lua_pushvalue(L,varname); - lua_gettable(L,-2); - return 1; -} -static int indirect_setglobal (lua_State* L) -{ - int varname = 1; - int value = 2; - int newvalue = 3; - lua_pushstring(L,".module"); - lua_gettable(L,value); - lua_pushvalue(L,varname); - lua_pushvalue(L,newvalue); - lua_settable(L,-3); - return 0; -} - -static void setmethods (lua_State* L) -{ - /* global variable */ - lua_pushcfunction(L,global_getglobal); - lua_settagmethod(L,toluaI_gettag(L,"tolua_tag_global"),"getglobal"); - lua_pushcfunction(L,global_setglobal); - lua_settagmethod(L,toluaI_gettag(L,"tolua_tag_global"),"setglobal"); - - /* module */ - lua_pushcfunction(L,module_index); - lua_settagmethod(L,toluaI_gettag(L,"tolua_tag_module"),"index"); - lua_pushcfunction(L,module_settable); - lua_settagmethod(L,toluaI_gettag(L,"tolua_tag_module"),"settable"); - - /* class */ - lua_pushcfunction(L,class_index); - lua_settagmethod(L,toluaI_gettag(L,"tolua_tag_class"),"index"); - lua_pushcfunction(L,class_settable); - lua_settagmethod(L,toluaI_gettag(L,"tolua_tag_class"),"settable"); - - /* instance */ - lua_pushcfunction(L,instance_gettable); - lua_settagmethod(L,toluaI_gettag(L,"tolua_tag_instance"),"gettable"); - lua_pushcfunction(L,instance_settable); - lua_settagmethod(L,toluaI_gettag(L,"tolua_tag_instance"),"settable"); - lua_pushcfunction(L,instance_operator); - lua_settagmethod(L,toluaI_gettag(L,"tolua_tag_instance"),"add"); - lua_pushcfunction(L,instance_operator); - lua_settagmethod(L,toluaI_gettag(L,"tolua_tag_instance"),"sub"); - lua_pushcfunction(L,instance_operator); - lua_settagmethod(L,toluaI_gettag(L,"tolua_tag_instance"),"mul"); - lua_pushcfunction(L,instance_operator); - lua_settagmethod(L,toluaI_gettag(L,"tolua_tag_instance"),"div"); - lua_pushcfunction(L,instance_relational); - lua_settagmethod(L,toluaI_gettag(L,"tolua_tag_instance"),"lt"); - lua_pushcfunction(L,instance_gc); - lua_settagmethod(L,toluaI_gettag(L,"tolua_tag_instance"),"gc"); - - /* lua instance */ - lua_pushcfunction(L,linstance_index); - lua_settagmethod(L,toluaI_gettag(L,"tolua_tag_linstance"),"index"); - - /* indirect */ - lua_pushcfunction(L,indirect_getglobal); - lua_settagmethod(L,toluaI_gettag(L,"tolua_tag_indirect"),"getglobal"); - lua_pushcfunction(L,indirect_setglobal); - lua_settagmethod(L,toluaI_gettag(L,"tolua_tag_indirect"),"setglobal"); -} - - - diff --git a/src/lua/tolua_tm.h b/src/lua/tolua_tm.h deleted file mode 100644 index c1bf06dc..00000000 --- a/src/lua/tolua_tm.h +++ /dev/null @@ -1,32 +0,0 @@ -/* tolua: tag methods -** Support code for Lua bindings. -** Written by Waldemar Celes -** TeCGraf/PUC-Rio -** Jul 1998 -** $Id: tolua_tm.h,v 1.2 2001/11/26 23:00:27 darkgod Exp $ -*/ - -/* This code is free software; you can redistribute it and/or modify it. -** The software provided hereunder is on an "as is" basis, and -** the author has no obligation to provide maintenance, support, updates, -** enhancements, or modifications. -*/ - - - -#ifndef tolua_tm_h -#define tolua_tm_h - -void toluaI_tm_init (lua_State* L); -void toluaI_tm_global (lua_State* L, int lo); -void toluaI_tm_module (lua_State* L, int lo); -void toluaI_tm_class (lua_State* L, int lo, char* name); -void toluaI_tm_instance (lua_State* L, int tag, int lo); -void toluaI_tm_linstance (lua_State* L, int tag, int lo); -void toluaI_tm_using (lua_State* L, int module); -void toluaI_tm_setclass (lua_State* L, int lo); -void toluaI_tm_pushmate (lua_State* L, int lo); -void toluaI_tm_pushclass (lua_State* L, int lo); - - -#endif diff --git a/src/lua/tolua_tt.c b/src/lua/tolua_tt.c deleted file mode 100644 index 33c384c6..00000000 --- a/src/lua/tolua_tt.c +++ /dev/null @@ -1,316 +0,0 @@ -/* tolua: type & tag manipulation. -** Support code for Lua bindings. -** Written by Waldemar Celes -** TeCGraf/PUC-Rio -** Jul 1998 -** $Id: tolua_tt.c,v 1.2 2001/11/26 23:00:27 darkgod Exp $ -*/ - -/* This code is free software; you can redistribute it and/or modify it. -** The software provided hereunder is on an "as is" basis, and -** the author has no obligation to provide maintenance, support, updates, -** enhancements, or modifications. -*/ - -#include "tolua.h" -#include "tolua_tt.h" -#include "tolua_tm.h" -#include "tolua_eh.h" -#include "tolua_rg.h" - -#include -#include -#include - -/* Global tables created in Lua registry: - tolua_tbl_itype: indexed by instance tags, stores the instance types. - tolua_tbl_itag: indexed by instance types, stores the instance tags. - tolua_tbl_const: indexed by constant tags, stores the tags. - tolua_tbl_hierarchy: indexed by instance tags, stores the base tags. -*/ - -/* exported basic type tags */ -int tolua_tag_nil; -int tolua_tag_number; -int tolua_tag_string; -int tolua_tag_userdata; -int tolua_tag_table; -int tolua_tag_function; - - -static const char* gettype (lua_State* L, int tag) -{ - const char* type; - toluaI_getregistry(L,"tolua_tbl_itype"); - lua_pushnumber(L,tag); - lua_gettable(L,-2); - type = lua_tostring(L,-1); - if (type==NULL) type = "[undefined]"; - lua_pop(L,2); - return type; -} - -const char* toluaI_tt_getobjtype (lua_State* L, int lo) -{ - if (lua_gettop(L)=abs(narg)) - { - toluaI_eh_set(L,narg,toluaI_tt_getobjtype(L,narg), - toluaI_tt_getobjtype(L,lua_gettop(L)+1)); - return 0; - } - return 1; -} - - diff --git a/src/lua/tolua_tt.h b/src/lua/tolua_tt.h deleted file mode 100644 index 941a2b02..00000000 --- a/src/lua/tolua_tt.h +++ /dev/null @@ -1,31 +0,0 @@ -/* tolua: type & tag manipulation. -** Support code for Lua bindings. -** Written by Waldemar Celes -** TeCGraf/PUC-Rio -** Jul 1998 -** $Id: tolua_tt.h,v 1.2 2001/11/26 23:00:27 darkgod Exp $ -*/ - -/* This code is free software; you can redistribute it and/or modify it. -** The software provided hereunder is on an "as is" basis, and -** the author has no obligation to provide maintenance, support, updates, -** enhancements, or modifications. -*/ - - -#ifndef tolua_tt_h -#define tolua_tt_h - -void toluaI_tt_init (lua_State* L); -void toluaI_tt_register (lua_State* L, int tag, char* type); -void toluaI_tt_class (lua_State* L, int lo, char* derived, char* base); -void toluaI_tt_sethierarchy (lua_State* L, int tag, int btag); -int toluaI_tt_isusertype (lua_State* L, int lo); -int toluaI_tt_gettag (lua_State* L, char* type); -const char* toluaI_tt_getobjtype (lua_State* L, int lo); -char* toluaI_tt_concat (const char* s1, const char* s2); - - - - -#endif diff --git a/src/lua/tolualua.c b/src/lua/tolualua.c deleted file mode 100644 index adbb8635..00000000 --- a/src/lua/tolualua.c +++ /dev/null @@ -1,2975 +0,0 @@ -/* -** Lua binding: tolualua -** Generated automatically by tolua 4.0a - angband on Sun Nov 11 22:59:08 2001. -*/ - -#include "tolua.h" - -/* Exported function */ -int tolua_tolualua_open (lua_State* tolua_S); -void tolua_tolualua_close (lua_State* tolua_S); - - -/* function to register type */ -static void toluaI_reg_types (lua_State* tolua_S) -{ -} - -/* error messages */ -#define TOLUA_ERR_SELF tolua_error(tolua_S,"invalid 'self'") -#define TOLUA_ERR_ASSIGN tolua_error(tolua_S,"#vinvalid type in variable assignment.") - -/* Open function */ -int tolua_tolualua_open (lua_State* tolua_S) -{ - tolua_open(tolua_S); - toluaI_reg_types(tolua_S); - - { /* begin embedded lua code */ - static unsigned char B[] = { - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 95, 98, 97,115,105, 99, 32, 61, 32,123, 10, 91, 39,118, - 111,105,100, 39, 93, 32, 61, 32, 39, 39, 44, 10, 91, 39, 99, - 104, 97,114, 39, 93, 32, 61, 32, 39,110,117,109, 98,101,114, - 39, 44, 10, 91, 39,105,110,116, 39, 93, 32, 61, 32, 39,110, - 117,109, 98,101,114, 39, 44, 10, 91, 39,115,104,111,114,116, - 39, 93, 32, 61, 32, 39,110,117,109, 98,101,114, 39, 44, 10, - 91, 39,108,111,110,103, 39, 93, 32, 61, 32, 39,110,117,109, - 98,101,114, 39, 44, 10, 91, 39, 95, 99,115,116,114,105,110, - 103, 39, 93, 32, 61, 32, 39,115,116,114,105,110,103, 39, 44, - 10, 91, 39, 95,117,115,101,114,100, 97,116, 97, 39, 93, 32, - 61, 32, 39,117,115,101,114,100, 97,116, 97, 39, 44, 10, 91, - 39, 99,104, 97,114, 42, 39, 93, 32, 61, 32, 39,115,116,114, - 105,110,103, 39, 44, 10, 91, 39,118,111,105,100, 42, 39, 93, - 32, 61, 32, 39,117,115,101,114,100, 97,116, 97, 39, 44, 10, - 91, 39, 98,111,111,108, 39, 93, 32, 61, 32, 39, 98,111,111, - 108, 39, 44, 10, 91, 39, 76, 85, 65, 95, 86, 65, 76, 85, 69, - 39, 93, 32, 61, 32, 39,118, 97,108,117,101, 39, 44, 10, 91, - 39, 98,121,116,101, 39, 93, 32, 61, 32, 39,110,117,109, 98, - 101,114, 39, 44, 10, 91, 39,115, 49, 54, 98, 39, 93, 32, 61, - 32, 39,110,117,109, 98,101,114, 39, 44, 10, 91, 39,117, 49, - 54, 98, 39, 93, 32, 61, 32, 39,110,117,109, 98,101,114, 39, - 44, 10, 91, 39,115, 51, 50, 98, 39, 93, 32, 61, 32, 39,110, - 117,109, 98,101,114, 39, 44, 10, 91, 39,117, 51, 50, 98, 39, - 93, 32, 61, 32, 39,110,117,109, 98,101,114, 39, 44, 10,125, - 10, 10, 95, 98, 97,115,105, 99, 95,116, 97,103, 32, 61, 32, - 123, 10, 91, 39,118,111,105,100, 39, 93, 32, 61, 32, 39, 39, - 44, 10, 91, 39, 99,104, 97,114, 39, 93, 32, 61, 32, 39, 76, - 85, 65, 95, 84, 78, 85, 77, 66, 69, 82, 39, 44, 10, 91, 39, - 105,110,116, 39, 93, 32, 61, 32, 39, 76, 85, 65, 95, 84, 78, - 85, 77, 66, 69, 82, 39, 44, 10, 91, 39,115,104,111,114,116, - 39, 93, 32, 61, 32, 39, 76, 85, 65, 95, 84, 78, 85, 77, 66, - 69, 82, 39, 44, 10, 91, 39,108,111,110,103, 39, 93, 32, 61, - 32, 39, 76, 85, 65, 95, 84, 78, 85, 77, 66, 69, 82, 39, 44, - 10, 91, 39, 95, 99,115,116,114,105,110,103, 39, 93, 32, 61, - 32, 39, 76, 85, 65, 95, 84, 83, 84, 82, 73, 78, 71, 39, 44, - 10, 91, 39, 95,117,115,101,114,100, 97,116, 97, 39, 93, 32, - 61, 32, 39, 76, 85, 65, 95, 84, 85, 83, 69, 82, 68, 65, 84, - 65, 39, 44, 10, 91, 39, 99,104, 97,114, 42, 39, 93, 32, 61, - 32, 39, 76, 85, 65, 95, 84, 83, 84, 82, 73, 78, 71, 39, 44, - 10, 91, 39,118,111,105,100, 42, 39, 93, 32, 61, 32, 39, 76, - 85, 65, 95, 84, 85, 83, 69, 82, 68, 65, 84, 65, 39, 44, 10, - 91, 39, 98,111,111,108, 39, 93, 32, 61, 32, 39,116,111,108, - 117, 97, 95,116, 97,103, 40,116,111,108,117, 97, 95, 83, 44, - 34, 98,111,111,108, 34, 41, 39, 44, 10, 91, 39, 98,121,116, - 101, 39, 93, 32, 61, 32, 39, 76, 85, 65, 95, 84, 78, 85, 77, - 66, 69, 82, 39, 44, 10, 91, 39,115, 49, 54, 98, 39, 93, 32, - 61, 32, 39, 76, 85, 65, 95, 84, 78, 85, 77, 66, 69, 82, 39, - 44, 10, 91, 39,117, 49, 54, 98, 39, 93, 32, 61, 32, 39, 76, - 85, 65, 95, 84, 78, 85, 77, 66, 69, 82, 39, 44, 10, 91, 39, - 115, 51, 50, 98, 39, 93, 32, 61, 32, 39, 76, 85, 65, 95, 84, - 78, 85, 77, 66, 69, 82, 39, 44, 10, 91, 39,117, 51, 50, 98, - 39, 93, 32, 61, 32, 39, 76, 85, 65, 95, 84, 78, 85, 77, 66, - 69, 82, 39, 44, 10,125, 10, 10, 95, 98, 97,115,105, 99, 95, - 99,116,121,112,101, 32, 61, 32,123, 10,110,117,109, 98,101, - 114, 32, 61, 32, 34,108,111,110,103, 34, 44, 10,115,116,114, - 105,110,103, 32, 61, 32, 34, 99,111,110,115,116, 32, 99,104, - 97,114, 42, 34, 44, 10,117,115,101,114,100, 97,116, 97, 32, - 61, 32, 34,118,111,105,100, 42, 34, 44, 10, 98,111,111,108, - 32, 61, 32, 34,105,110,116, 34, 44, 10,125, 10, 10, 10, 10, - 95,117,115,101,114,116,121,112,101, 32, 61, 32,123,125, 10, - 10, 10,102,117,110, 99,116,105,111,110, 32,116,111,108,117, - 97, 95,105,110,100,101,120, 32, 40,116, 44,102, 41, 10,105, - 102, 32,102, 32, 61, 61, 32, 39, 95, 98, 97,115,101, 39, 32, - 116,104,101,110, 10,114,101,116,117,114,110, 32,116,111,108, - 117, 97, 95,111,108,100, 95,105,110,100,101,120, 40,116, 44, - 102, 41, 10,101,108,115,101, 10,114,101,116,117,114,110, 32, - 116, 46, 95, 98, 97,115,101, 91,102, 93, 10,101,110,100, 10, - 101,110,100, 10, 10,116,111,108,117, 97, 95,116, 97,103, 32, - 61, 32,110,101,119,116, 97,103, 40, 41, 10,116,111,108,117, - 97, 95,111,108,100, 95,105,110,100,101,120, 32, 61, 32,115, - 101,116,116, 97,103,109,101,116,104,111,100, 40,116,111,108, - 117, 97, 95,116, 97,103, 44, 34,105,110,100,101,120, 34, 44, - 116,111,108,117, 97, 95,105,110,100,101,120, 41, 10, 10, 10, - 102,117,110, 99,116,105,111,110, 32,116,111,108,117, 97, 95, - 101,114,114,111,114, 32, 40,115, 41, 10,108,111, 99, 97,108, - 32,111,117,116, 32, 61, 32, 95, 79, 85, 84, 80, 85, 84, 10, - 95, 79, 85, 84, 80, 85, 84, 32, 61, 32, 95, 83, 84, 68, 69, - 82, 82, 10,105,102, 32,115,116,114,115,117, 98, 40,115, 44, - 49, 44, 49, 41, 32, 61, 61, 32, 39, 35, 39, 32,116,104,101, - 110, 10,119,114,105,116,101, 40, 34, 92,110, 42, 42, 32,116, - 111,108,117, 97, 58, 32, 34, 46, 46,115,116,114,115,117, 98, - 40,115, 44, 50, 41, 46, 46, 34, 46, 92,110, 92,110, 34, 41, - 10,101,108,115,101, 10,119,114,105,116,101, 40, 34, 92,110, - 42, 42, 32,116,111,108,117, 97, 32,105,110,116,101,114,110, - 97,108, 32,101,114,114,111,114, 58, 32, 34, 46, 46,115, 46, - 46, 34, 46, 92,110, 92,110, 34, 41, 10,114,101,116,117,114, - 110, 10,101,110,100, 10, 10,105,102, 32, 95, 99,117,114,114, - 95, 99,111,100,101, 32,116,104,101,110, 10,108,111, 99, 97, - 108, 32, 95, 44, 95, 44,115, 32, 61, 32,115,116,114,102,105, - 110,100, 40, 95, 99,117,114,114, 95, 99,111,100,101, 44, 34, - 94, 37,115, 42, 40, 46, 45, 92,110, 41, 34, 41, 10,105,102, - 32,115, 61, 61,110,105,108, 32,116,104,101,110, 32,115, 32, - 61, 32, 95, 99,117,114,114, 95, 99,111,100,101, 32,101,110, - 100, 10,115, 32, 61, 32,103,115,117, 98, 40,115, 44, 34, 95, - 117,115,101,114,100, 97,116, 97, 34, 44, 34,118,111,105,100, - 42, 34, 41, 10,115, 32, 61, 32,103,115,117, 98, 40,115, 44, - 34, 95, 99,115,116,114,105,110,103, 34, 44, 34, 99,104, 97, - 114, 42, 34, 41, 10,119,114,105,116,101, 40, 34, 67,111,100, - 101, 32, 98,101,105,110,103, 32,112,114,111, 99,101,115,115, - 101,100, 58, 92,110, 34, 46, 46,115, 46, 46, 34, 92,110, 34, - 41, 10,101,110,100, 10, 95, 79, 85, 84, 80, 85, 84, 32, 61, - 32,111,117,116, 10,101,110,100, 10, 10, 10, 95, 69, 82, 82, - 79, 82, 77, 69, 83, 83, 65, 71, 69, 32, 61, 32,116,111,108, - 117, 97, 95,101,114,114,111,114, 10, 10, 10,102,117,110, 99, - 116,105,111,110, 32,114,101,103,116,121,112,101, 32, 40,116, - 41, 10,105,102, 32,110,111,116, 32,105,115,116,121,112,101, - 40,116, 41, 32,116,104,101,110, 10, 95,117,115,101,114,116, - 121,112,101, 91,116, 93, 32, 61, 32,116, 10,101,110,100, 10, - 114,101,116,117,114,110, 32,116, 10,101,110,100, 10, 10, 10, - 102,117,110, 99,116,105,111,110, 32,116, 97,103,118, 97,114, - 40,116,121,112,101, 44, 99,111,110,115,116, 41, 10,105,102, - 32,116,121,112,101, 32, 61, 61, 32, 39, 39, 32,111,114, 32, - 116,121,112,101, 32, 61, 61, 32, 39,118,111,105,100, 39, 32, - 116,104,101,110, 10,114,101,116,117,114,110, 32,116,121,112, - 101, 44, 48, 10,101,108,115,101, 10,108,111, 99, 97,108, 32, - 109, 44,116, 32, 61, 32,102,105,110,100,116,121,112,101,100, - 101,102, 40,116,121,112,101, 41, 10,105,102, 32,105,115, 98, - 97,115,105, 99, 40,116, 41, 32,116,104,101,110, 10,114,101, - 116,117,114,110, 32,116, 44, 32, 95, 98, 97,115,105, 99, 95, - 116, 97,103, 91,116, 93, 10,101,110,100, 10,105,102, 32,115, - 116,114,102,105,110,100, 40,109, 44, 39, 99,111,110,115,116, - 39, 41, 32,116,104,101,110, 32, 99,111,110,115,116, 32, 61, - 32, 39, 99,111,110,115,116, 39, 32,101,110,100, 10,114,101, - 103,116,121,112,101, 40,116, 41, 10,105,102, 32, 99,111,110, - 115,116, 32, 97,110,100, 32, 99,111,110,115,116, 32,126, 61, - 32, 39, 39, 32,116,104,101,110, 10,116, 32, 61, 32, 39, 99, - 111,110,115,116, 32, 39, 46, 46,116, 10,101,110,100, 10,114, - 101,116,117,114,110, 32,116, 44, 39,116,111,108,117, 97, 95, - 116, 97,103, 40,116,111,108,117, 97, 95, 83, 44, 34, 39, 46, - 46,116, 46, 46, 39, 34, 41, 39, 10,101,110,100, 10,101,110, - 100, 10, 10, 10,102,117,110, 99,116,105,111,110, 32,105,115, - 98, 97,115,105, 99, 32, 40,116,121,112,101, 41, 10,108,111, - 99, 97,108, 32,109, 44,116, 32, 61, 32,102,105,110,100,116, - 121,112,101,100,101,102, 40,116,121,112,101, 41, 10,108,111, - 99, 97,108, 32, 98, 32, 61, 32, 95, 98, 97,115,105, 99, 91, - 116, 93, 10,105,102, 32, 98, 32,116,104,101,110, 10,114,101, - 116,117,114,110, 32, 98, 44, 95, 98, 97,115,105, 99, 95, 99, - 116,121,112,101, 91, 98, 93, 10,101,110,100, 10,114,101,116, - 117,114,110, 32,110,105,108, 10,101,110,100, 10, 10, 10,102, - 117,110, 99,116,105,111,110, 32,105,115,116,121,112,101, 32, - 40,116, 41, 10,114,101,116,117,114,110, 32, 95, 98, 97,115, - 105, 99, 91,116, 93, 32,111,114, 32, 95,117,115,101,114,116, - 121,112,101, 91,116, 93, 32,111,114, 32,105,115,116,121,112, - 101,100,101,102, 40,116, 41, 10,101,110,100, 10, 10, 10, 10, - 102,117,110, 99,116,105,111,110, 32,115,112,108,105,116, 32, - 40,115, 44,116, 41, 10,108,111, 99, 97,108, 32,108, 32, 61, - 32,123,110, 61, 48,125, 10,108,111, 99, 97,108, 32,102, 32, - 61, 32,102,117,110, 99,116,105,111,110, 32, 40,115, 41, 10, - 37,108, 46,110, 32, 61, 32, 37,108, 46,110, 32, 43, 32, 49, - 10, 37,108, 91, 37,108, 46,110, 93, 32, 61, 32,115, 10,101, - 110,100, 10,108,111, 99, 97,108, 32,112, 32, 61, 32, 34, 37, - 115, 42, 40, 46, 45, 41, 37,115, 42, 34, 46, 46,116, 46, 46, - 34, 37,115, 42, 34, 10,115, 32, 61, 32,103,115,117, 98, 40, - 115, 44, 34, 94, 37,115, 43, 34, 44, 34, 34, 41, 10,115, 32, - 61, 32,103,115,117, 98, 40,115, 44, 34, 37,115, 43, 36, 34, - 44, 34, 34, 41, 10,115, 32, 61, 32,103,115,117, 98, 40,115, - 44,112, 44,102, 41, 10,108, 46,110, 32, 61, 32,108, 46,110, - 32, 43, 32, 49, 10,108, 91,108, 46,110, 93, 32, 61, 32,103, - 115,117, 98, 40,115, 44, 34, 40, 37,115, 37,115, 42, 41, 36, - 34, 44, 34, 34, 41, 10,114,101,116,117,114,110, 32,108, 10, - 101,110,100, 10, 10, 10, 10,102,117,110, 99,116,105,111,110, - 32, 99,111,110, 99, 97,116, 32, 40,116, 44,102, 44,108, 41, - 10,108,111, 99, 97,108, 32,115, 32, 61, 32, 39, 39, 10,108, - 111, 99, 97,108, 32,105, 61,102, 10,119,104,105,108,101, 32, - 105, 60, 61,108, 32,100,111, 10,115, 32, 61, 32,115, 46, 46, - 116, 91,105, 93, 10,105, 32, 61, 32,105, 43, 49, 10,105,102, - 32,105, 32, 60, 61, 32,108, 32,116,104,101,110, 32,115, 32, - 61, 32,115, 46, 46, 39, 32, 39, 32,101,110,100, 10,101,110, - 100, 10,114,101,116,117,114,110, 32,115, 10,101,110,100, 10, - 10, 10,102,117,110, 99,116,105,111,110, 32,111,117,116,112, - 117,116, 32, 40, 46, 46, 46, 41, 10,108,111, 99, 97,108, 32, - 105, 61, 49, 10,119,104,105,108,101, 32,105, 60, 61, 97,114, - 103, 46,110, 32,100,111, 10,105,102, 32, 95, 99,111,110,116, - 32, 97,110,100, 32,110,111,116, 32,115,116,114,102,105,110, - 100, 40, 95, 99,111,110,116, 44, 39, 91, 37, 40, 44, 34, 93, - 39, 41, 32, 97,110,100, 10,115,116,114,102,105,110,100, 40, - 97,114,103, 91,105, 93, 44, 34, 94, 91, 37, 97, 95,126, 93, - 34, 41, 32,116,104,101,110, 10,119,114,105,116,101, 40, 39, - 32, 39, 41, 10,101,110,100, 10,119,114,105,116,101, 40, 97, - 114,103, 91,105, 93, 41, 10,105,102, 32, 97,114,103, 91,105, - 93, 32,126, 61, 32, 39, 39, 32,116,104,101,110, 10, 95, 99, - 111,110,116, 32, 61, 32,115,116,114,115,117, 98, 40, 97,114, - 103, 91,105, 93, 44, 45, 49, 44, 45, 49, 41, 10,101,110,100, - 10,105, 32, 61, 32,105, 43, 49, 10,101,110,100, 10,105,102, - 32,115,116,114,102,105,110,100, 40, 97,114,103, 91, 97,114, - 103, 46,110, 93, 44, 34, 91, 37, 47, 37, 41, 37, 59, 37,123, - 37,125, 93, 36, 34, 41, 32,116,104,101,110, 10, 95, 99,111, - 110,116, 61,110,105,108, 32,119,114,105,116,101, 40, 39, 92, - 110, 39, 41, 10,101,110,100, 10,101,110,100, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 99,108, 97,115, - 115, 70,101, 97,116,117,114,101, 32, 61, 32,123, 10,125, 10, - 10, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115, - 115, 70,101, 97,116,117,114,101, 58,115,117,112, 99,111,100, - 101, 32, 40, 41, 10,101,110,100, 10, 10, 10,102,117,110, 99, - 116,105,111,110, 32, 99,108, 97,115,115, 70,101, 97,116,117, - 114,101, 58,100,101, 99,108,116, 97,103, 32, 40, 41, 10,101, - 110,100, 10, 10, 10,102,117,110, 99,116,105,111,110, 32, 99, - 108, 97,115,115, 70,101, 97,116,117,114,101, 58,114,101,103, - 105,115,116,101,114, 32, 40, 41, 10,101,110,100, 10, 10, 10, - 102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 70, - 101, 97,116,117,114,101, 58,117,110,114,101,103,105,115,116, - 101,114, 32, 40, 41, 10,101,110,100, 10, 10, 10,102,117,110, - 99,116,105,111,110, 32, 99,108, 97,115,115, 70,101, 97,116, - 117,114,101, 58,112,114,101, 97,109, 98,108,101, 32, 40, 41, - 10,101,110,100, 10, 10, 10, 10,102,117,110, 99,116,105,111, - 110, 32, 99,108, 97,115,115, 70,101, 97,116,117,114,101, 58, - 105,110, 99,108, 97,115,115, 32, 40, 41, 10,105,102, 32,115, - 101,108,102, 46,112, 97,114,101,110,116, 32, 97,110,100, 32, - 115,101,108,102, 46,112, 97,114,101,110,116, 46,116,121,112, - 101, 32, 61, 61, 32, 39, 99,108, 97,115,115, 39, 32,116,104, - 101,110, 10,114,101,116,117,114,110, 32,115,101,108,102, 46, - 112, 97,114,101,110,116, 46,110, 97,109,101, 10,101,108,115, - 101, 10,114,101,116,117,114,110, 32,110,105,108, 10,101,110, - 100, 10,101,110,100, 10, 10, 10, 10,102,117,110, 99,116,105, - 111,110, 32, 99,108, 97,115,115, 70,101, 97,116,117,114,101, - 58,105,110,109,111,100,117,108,101, 32, 40, 41, 10,105,102, - 32,115,101,108,102, 46,112, 97,114,101,110,116, 32, 97,110, - 100, 32,115,101,108,102, 46,112, 97,114,101,110,116, 46,116, - 121,112,101, 32, 61, 61, 32, 39,109,111,100,117,108,101, 39, - 32,116,104,101,110, 10,114,101,116,117,114,110, 32,115,101, - 108,102, 46,112, 97,114,101,110,116, 46,110, 97,109,101, 10, - 101,108,115,101, 10,114,101,116,117,114,110, 32,110,105,108, - 10,101,110,100, 10,101,110,100, 10, 10, 10, 10, 10, 10,102, - 117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 70,101, - 97,116,117,114,101, 58, 99,102,117,110, 99,110, 97,109,101, - 32, 40,110, 41, 10,105,102, 32,115,101,108,102, 46,112, 97, - 114,101,110,116, 32,116,104,101,110, 10,110, 32, 61, 32,115, - 101,108,102, 46,112, 97,114,101,110,116, 58, 99,102,117,110, - 99,110, 97,109,101, 40,110, 41, 10,101,110,100, 10,105,102, - 32,115,101,108,102, 46,108,110, 97,109,101, 32,116,104,101, - 110, 10,114,101,116,117,114,110, 32,110, 46, 46, 39, 95, 39, - 46, 46,115,101,108,102, 46,108,110, 97,109,101, 10,101,108, - 115,101, 10,114,101,116,117,114,110, 32,110, 46, 46, 39, 95, - 39, 46, 46,115,101,108,102, 46,110, 97,109,101, 10,101,110, - 100, 10,101,110,100, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 99,108, 97,115,115, 86, - 101,114, 98, 97,116,105,109, 32, 61, 32,123, 10,108,105,110, - 101, 32, 61, 32, 39, 39, 44, 10, 95, 98, 97,115,101, 32, 61, - 32, 99,108, 97,115,115, 70,101, 97,116,117,114,101, 44, 10, - 125, 10,115,101,116,116, 97,103, 40, 99,108, 97,115,115, 86, - 101,114, 98, 97,116,105,109, 44,116,111,108,117, 97, 95,116, - 97,103, 41, 10, 10, 10,102,117,110, 99,116,105,111,110, 32, - 99,108, 97,115,115, 86,101,114, 98, 97,116,105,109, 58,112, - 114,101, 97,109, 98,108,101, 32, 40, 41, 10,105,102, 32,110, - 111,116, 32,115,101,108,102, 46, 99,111,110,100, 32,116,104, - 101,110, 10,119,114,105,116,101, 40,115,101,108,102, 46,108, - 105,110,101, 41, 10,101,110,100, 10,101,110,100, 10, 10, 10, - 102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 86, - 101,114, 98, 97,116,105,109, 58,115,117,112, 99,111,100,101, - 32, 40, 41, 10,105,102, 32,115,101,108,102, 46, 99,111,110, - 100, 32,116,104,101,110, 10,119,114,105,116,101, 40,115,101, - 108,102, 46,108,105,110,101, 41, 10,119,114,105,116,101, 40, - 39, 92,110, 39, 41, 10,101,110,100, 10,101,110,100, 10, 10, - 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, - 86,101,114, 98, 97,116,105,109, 58,114,101,103,105,115,116, - 101,114, 32, 40, 41, 10,105,102, 32,115,101,108,102, 46, 99, - 111,110,100, 32,116,104,101,110, 10,119,114,105,116,101, 40, - 115,101,108,102, 46,108,105,110,101, 41, 10,101,110,100, 10, - 101,110,100, 10, 10, 10, 10,102,117,110, 99,116,105,111,110, - 32, 99,108, 97,115,115, 86,101,114, 98, 97,116,105,109, 58, - 112,114,105,110,116, 32, 40,105,100,101,110,116, 44, 99,108, - 111,115,101, 41, 10,112,114,105,110,116, 40,105,100,101,110, - 116, 46, 46, 34, 86,101,114, 98, 97,116,105,109,123, 34, 41, - 10,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, - 32,108,105,110,101, 32, 61, 32, 39, 34, 46, 46,115,101,108, - 102, 46,108,105,110,101, 46, 46, 34, 39, 44, 34, 41, 10,112, - 114,105,110,116, 40,105,100,101,110,116, 46, 46, 34,125, 34, - 46, 46, 99,108,111,115,101, 41, 10,101,110,100, 10, 10, 10, - 10,102,117,110, 99,116,105,111,110, 32, 95, 86,101,114, 98, - 97,116,105,109, 32, 40,116, 41, 10,116, 46, 95, 98, 97,115, - 101, 32, 61, 32, 99,108, 97,115,115, 86,101,114, 98, 97,116, - 105,109, 10,115,101,116,116, 97,103, 40,116, 44,116,111,108, - 117, 97, 95,116, 97,103, 41, 10, 97,112,112,101,110,100, 40, - 116, 41, 10,114,101,116,117,114,110, 32,116, 10,101,110,100, - 10, 10, 10, 10,102,117,110, 99,116,105,111,110, 32, 86,101, - 114, 98, 97,116,105,109, 32, 40,108, 41, 10,108,111, 99, 97, - 108, 32, 99, 10,105,102, 32,115,116,114,115,117, 98, 40,108, - 44, 49, 44, 49, 41, 32, 61, 61, 32, 39, 36, 39, 32,116,104, - 101,110, 10, 99, 32, 61, 32, 49, 10,108, 32, 61, 32,115,116, - 114,115,117, 98, 40,108, 44, 50, 41, 10,101,110,100, 10,114, - 101,116,117,114,110, 32, 95, 86,101,114, 98, 97,116,105,109, - 32,123, 10,108,105,110,101, 32, 61, 32,108, 44, 10, 99,111, - 110,100, 32, 61, 32, 99, 10,125, 10,101,110,100, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 99,108, 97,115,115, 67,111,100,101, 32, 61, 32,123, 10,116, - 101,120,116, 32, 61, 32, 39, 39, 44, 10, 95, 98, 97,115,101, - 32, 61, 32, 99,108, 97,115,115, 70,101, 97,116,117,114,101, - 44, 10,125, 10,115,101,116,116, 97,103, 40, 99,108, 97,115, - 115, 67,111,100,101, 44,116,111,108,117, 97, 95,116, 97,103, - 41, 10, 10, 10,102,117,110, 99,116,105,111,110, 32, 99,108, - 97,115,115, 67,111,100,101, 58,114,101,103,105,115,116,101, - 114, 32, 40, 41, 10, 10,108,111, 99, 97,108, 32,115, 32, 61, - 32, 99,108,101, 97,110, 40,115,101,108,102, 46,116,101,120, - 116, 41, 10,105,102, 32,110,111,116, 32,115, 32,116,104,101, - 110, 10,101,114,114,111,114, 40, 34,112, 97,114,115,101,114, - 32,101,114,114,111,114, 32,105,110, 32,101,109, 98,101,100, - 100,101,100, 32, 99,111,100,101, 34, 41, 10,101,110,100, 10, - 10, 10,111,117,116,112,117,116, 40, 39, 92,110, 32,123, 32, - 47, 42, 32, 98,101,103,105,110, 32,101,109, 98,101,100,100, - 101,100, 32,108,117, 97, 32, 99,111,100,101, 32, 42, 47, 92, - 110, 39, 41, 10,111,117,116,112,117,116, 40, 39, 32,115,116, - 97,116,105, 99, 32,117,110,115,105,103,110,101,100, 32, 99, - 104, 97,114, 32, 66, 91, 93, 32, 61, 32,123, 92,110, 32, 39, - 41, 10,108,111, 99, 97,108, 32,116, 61,123,110, 61, 48,125, - 10,108,111, 99, 97,108, 32, 98, 32, 61, 32,103,115,117, 98, - 40,115, 44, 39, 40, 46, 41, 39, 44,102,117,110, 99,116,105, - 111,110, 32, 40, 99, 41, 10,108,111, 99, 97,108, 32,101, 32, - 61, 32, 39, 39, 10, 37,116, 46,110, 61, 37,116, 46,110, 43, - 49, 32,105,102, 32, 37,116, 46,110, 61, 61, 49, 53, 32,116, - 104,101,110, 32, 37,116, 46,110, 61, 48, 32,101, 61, 39, 92, - 110, 32, 39, 32,101,110,100, 10,114,101,116,117,114,110, 32, - 102,111,114,109, 97,116, 40, 39, 37, 51,117, 44, 37,115, 39, - 44,115,116,114, 98,121,116,101, 40, 99, 41, 44,101, 41, 10, - 101,110,100, 10, 41, 10,111,117,116,112,117,116, 40, 98, 46, - 46,115,116,114, 98,121,116,101, 40, 34, 32, 34, 41, 41, 10, - 111,117,116,112,117,116, 40, 39, 92,110, 32,125, 59, 92,110, - 39, 41, 10,111,117,116,112,117,116, 40, 39, 32,108,117, 97, - 95,100,111, 98,117,102,102,101,114, 40,116,111,108,117, 97, - 95, 83, 44, 40, 99,104, 97,114, 42, 41, 66, 44,115,105,122, - 101,111,102, 40, 66, 41, 44, 34,116,111,108,117, 97, 58, 32, - 101,109, 98,101,100,100,101,100, 32, 76,117, 97, 32, 99,111, - 100,101, 34, 41, 59, 39, 41, 10,111,117,116,112,117,116, 40, - 39, 32,125, 32, 47, 42, 32,101,110,100, 32,111,102, 32,101, - 109, 98,101,100,100,101,100, 32,108,117, 97, 32, 99,111,100, - 101, 32, 42, 47, 92,110, 92,110, 39, 41, 10,101,110,100, 10, - 10, 10, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97, - 115,115, 67,111,100,101, 58,112,114,105,110,116, 32, 40,105, - 100,101,110,116, 44, 99,108,111,115,101, 41, 10,112,114,105, - 110,116, 40,105,100,101,110,116, 46, 46, 34, 67,111,100,101, - 123, 34, 41, 10,112,114,105,110,116, 40,105,100,101,110,116, - 46, 46, 34, 32,116,101,120,116, 32, 61, 32, 91, 91, 34, 46, - 46,115,101,108,102, 46,116,101,120,116, 46, 46, 34, 93, 93, - 44, 34, 41, 10,112,114,105,110,116, 40,105,100,101,110,116, - 46, 46, 34,125, 34, 46, 46, 99,108,111,115,101, 41, 10,101, - 110,100, 10, 10, 10, 10,102,117,110, 99,116,105,111,110, 32, - 95, 67,111,100,101, 32, 40,116, 41, 10,116, 46, 95, 98, 97, - 115,101, 32, 61, 32, 99,108, 97,115,115, 67,111,100,101, 10, - 115,101,116,116, 97,103, 40,116, 44,116,111,108,117, 97, 95, - 116, 97,103, 41, 10, 97,112,112,101,110,100, 40,116, 41, 10, - 114,101,116,117,114,110, 32,116, 10,101,110,100, 10, 10, 10, - 10,102,117,110, 99,116,105,111,110, 32, 67,111,100,101, 32, - 40,108, 41, 10,114,101,116,117,114,110, 32, 95, 67,111,100, - 101, 32,123, 10,116,101,120,116, 32, 61, 32,108, 10,125, 10, - 101,110,100, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 99,108, 97, - 115,115, 84,121,112,101,100,101,102, 32, 61, 32,123, 10,117, - 116,121,112,101, 32, 61, 32, 39, 39, 44, 10,109,111,100, 32, - 61, 32, 39, 39, 44, 10,116,121,112,101, 32, 61, 32, 39, 39, - 10,125, 10, 10, 10,102,117,110, 99,116,105,111,110, 32, 99, - 108, 97,115,115, 84,121,112,101,100,101,102, 58,112,114,105, - 110,116, 32, 40,105,100,101,110,116, 44, 99,108,111,115,101, - 41, 10,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, - 34, 84,121,112,101,100,101,102,123, 34, 41, 10,112,114,105, - 110,116, 40,105,100,101,110,116, 46, 46, 34, 32,117,116,121, - 112,101, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46,117, - 116,121,112,101, 46, 46, 34, 39, 44, 34, 41, 10,112,114,105, - 110,116, 40,105,100,101,110,116, 46, 46, 34, 32,109,111,100, - 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46,109,111,100, - 46, 46, 34, 39, 44, 34, 41, 10,112,114,105,110,116, 40,105, - 100,101,110,116, 46, 46, 34, 32,116,121,112,101, 32, 61, 32, - 39, 34, 46, 46,115,101,108,102, 46,116,121,112,101, 46, 46, - 34, 39, 44, 34, 41, 10,112,114,105,110,116, 40,105,100,101, - 110,116, 46, 46, 34,125, 34, 46, 46, 99,108,111,115,101, 41, - 10,101,110,100, 10, 10, 10,102,117,110, 99,116,105,111,110, - 32, 95, 84,121,112,101,100,101,102, 32, 40,116, 41, 10,116, - 46, 95, 98, 97,115,101, 32, 61, 32, 99,108, 97,115,115, 84, - 121,112,101,100,101,102, 10,115,101,116,116, 97,103, 40,116, - 44,116,111,108,117, 97, 95,116, 97,103, 41, 10, 97,112,112, - 101,110,100,116,121,112,101,100,101,102, 40,116, 41, 10,114, - 101,116,117,114,110, 32,116, 10,101,110,100, 10, 10, 10, 10, - 102,117,110, 99,116,105,111,110, 32, 84,121,112,101,100,101, - 102, 32, 40,115, 41, 10,105,102, 32,115,116,114,102,105,110, - 100, 40,115, 44, 39, 91, 37, 42, 38, 93, 39, 41, 32,116,104, - 101,110, 10,116,111,108,117, 97, 95,101,114,114,111,114, 40, - 34, 35,105,110,118, 97,108,105,100, 32,116,121,112,101,100, - 101,102, 58, 32,112,111,105,110,116,101,114,115, 32, 40, 97, - 110,100, 32,114,101,102,101,114,101,110, 99,101,115, 41, 32, - 97,114,101, 32,110,111,116, 32,115,117,112,112,111,114,116, - 101,100, 34, 41, 10,101,110,100, 10,108,111, 99, 97,108, 32, - 116, 32, 61, 32,115,112,108,105,116, 40,103,115,117, 98, 40, - 115, 44, 34, 37,115, 37,115, 42, 34, 44, 34, 32, 34, 41, 44, - 34, 32, 34, 41, 10,114,101,116,117,114,110, 32, 95, 84,121, - 112,101,100,101,102, 32,123, 10,117,116,121,112,101, 32, 61, - 32,116, 91,116, 46,110, 93, 44, 10,116,121,112,101, 32, 61, - 32,116, 91,116, 46,110, 45, 49, 93, 44, 10,109,111,100, 32, - 61, 32, 99,111,110, 99, 97,116, 40,116, 44, 49, 44,116, 46, - 110, 45, 50, 41, 10,125, 10,101,110,100, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 99,108, 97,115, - 115, 67,111,110,116, 97,105,110,101,114, 32, 61, 10,123, 10, - 99,117,114,114, 32, 61, 32,110,105,108, 44, 10, 95, 98, 97, - 115,101, 32, 61, 32, 99,108, 97,115,115, 70,101, 97,116,117, - 114,101, 44, 10,125, 10,115,101,116,116, 97,103, 40, 99,108, - 97,115,115, 67,111,110,116, 97,105,110,101,114, 44,116,111, - 108,117, 97, 95,116, 97,103, 41, 10, 10, 10,102,117,110, 99, - 116,105,111,110, 32, 99,108, 97,115,115, 67,111,110,116, 97, - 105,110,101,114, 58,100,101, 99,108,116, 97,103, 32, 40, 41, - 10,112,117,115,104, 40,115,101,108,102, 41, 10,108,111, 99, - 97,108, 32,105, 61, 49, 10,119,104,105,108,101, 32,115,101, - 108,102, 91,105, 93, 32,100,111, 10,115,101,108,102, 91,105, - 93, 58,100,101, 99,108,116, 97,103, 40, 41, 10,105, 32, 61, - 32,105, 43, 49, 10,101,110,100, 10,112,111,112, 40, 41, 10, - 101,110,100, 10, 10, 10, 10,102,117,110, 99,116,105,111,110, - 32, 99,108, 97,115,115, 67,111,110,116, 97,105,110,101,114, - 58,115,117,112, 99,111,100,101, 32, 40, 41, 10,112,117,115, - 104, 40,115,101,108,102, 41, 10,108,111, 99, 97,108, 32,105, - 61, 49, 10,119,104,105,108,101, 32,115,101,108,102, 91,105, - 93, 32,100,111, 10,115,101,108,102, 91,105, 93, 58,115,117, - 112, 99,111,100,101, 40, 41, 10,105, 32, 61, 32,105, 43, 49, - 10,101,110,100, 10,112,111,112, 40, 41, 10,101,110,100, 10, - 10, 10, 10,102,117,110, 99,116,105,111,110, 32, 95, 67,111, - 110,116, 97,105,110,101,114, 32, 40,115,101,108,102, 41, 10, - 115,101,108,102, 46, 95, 98, 97,115,101, 32, 61, 32, 99,108, - 97,115,115, 67,111,110,116, 97,105,110,101,114, 10,115,101, - 116,116, 97,103, 40,115,101,108,102, 44,116,111,108,117, 97, - 95,116, 97,103, 41, 10,115,101,108,102, 46,110, 32, 61, 32, - 48, 10,115,101,108,102, 46,116,121,112,101,100,101,102,115, - 32, 61, 32,123,110, 61, 48,125, 10,115,101,108,102, 46,108, - 110, 97,109,101,115, 32, 61, 32,123,125, 10,114,101,116,117, - 114,110, 32,115,101,108,102, 10,101,110,100, 10, 10, 10,102, - 117,110, 99,116,105,111,110, 32,112,117,115,104, 32, 40,116, - 41, 10, 99,108, 97,115,115, 67,111,110,116, 97,105,110,101, - 114, 46, 99,117,114,114, 32, 61, 32,116, 10,101,110,100, 10, - 10, 10,102,117,110, 99,116,105,111,110, 32,112,111,112, 32, - 40, 41, 10, 99,108, 97,115,115, 67,111,110,116, 97,105,110, - 101,114, 46, 99,117,114,114, 32, 61, 32, 99,108, 97,115,115, - 67,111,110,116, 97,105,110,101,114, 46, 99,117,114,114, 46, - 112, 97,114,101,110,116, 10,101,110,100, 10, 10, 10,102,117, - 110, 99,116,105,111,110, 32, 97,112,112,101,110,100, 32, 40, - 116, 41, 10,114,101,116,117,114,110, 32, 99,108, 97,115,115, - 67,111,110,116, 97,105,110,101,114, 46, 99,117,114,114, 58, - 97,112,112,101,110,100, 40,116, 41, 10,101,110,100, 10, 10, - 10,102,117,110, 99,116,105,111,110, 32, 97,112,112,101,110, - 100,116,121,112,101,100,101,102, 32, 40,116, 41, 10,114,101, - 116,117,114,110, 32, 99,108, 97,115,115, 67,111,110,116, 97, - 105,110,101,114, 46, 99,117,114,114, 58, 97,112,112,101,110, - 100,116,121,112,101,100,101,102, 40,116, 41, 10,101,110,100, - 10, 10, 10,102,117,110, 99,116,105,111,110, 32,102,105,110, - 100,116,121,112,101,100,101,102, 32, 40,116,121,112,101, 41, - 10,114,101,116,117,114,110, 32, 99,108, 97,115,115, 67,111, - 110,116, 97,105,110,101,114, 46, 99,117,114,114, 58,102,105, - 110,100,116,121,112,101,100,101,102, 40,116,121,112,101, 41, - 10,101,110,100, 10, 10, 10,102,117,110, 99,116,105,111,110, - 32,105,115,116,121,112,101,100,101,102, 32, 40,116,121,112, - 101, 41, 10,114,101,116,117,114,110, 32, 99,108, 97,115,115, - 67,111,110,116, 97,105,110,101,114, 46, 99,117,114,114, 58, - 105,115,116,121,112,101,100,101,102, 40,116,121,112,101, 41, - 10,101,110,100, 10, 10, 10,102,117,110, 99,116,105,111,110, - 32, 99,108, 97,115,115, 67,111,110,116, 97,105,110,101,114, - 58, 97,112,112,101,110,100, 32, 40,116, 41, 10,115,101,108, - 102, 46,110, 32, 61, 32,115,101,108,102, 46,110, 32, 43, 32, - 49, 10,115,101,108,102, 91,115,101,108,102, 46,110, 93, 32, - 61, 32,116, 10,116, 46,112, 97,114,101,110,116, 32, 61, 32, - 115,101,108,102, 10,101,110,100, 10, 10, 10,102,117,110, 99, - 116,105,111,110, 32, 99,108, 97,115,115, 67,111,110,116, 97, - 105,110,101,114, 58, 97,112,112,101,110,100,116,121,112,101, - 100,101,102, 32, 40,116, 41, 10,115,101,108,102, 46,116,121, - 112,101,100,101,102,115, 46,110, 32, 61, 32,115,101,108,102, - 46,116,121,112,101,100,101,102,115, 46,110, 32, 43, 32, 49, - 10,115,101,108,102, 46,116,121,112,101,100,101,102,115, 91, - 115,101,108,102, 46,116,121,112,101,100,101,102,115, 46,110, - 93, 32, 61, 32,116, 10,101,110,100, 10, 10, 10,102,117,110, - 99,116,105,111,110, 32, 99,108, 97,115,115, 67,111,110,116, - 97,105,110,101,114, 58,111,118,101,114,108,111, 97,100, 32, - 40,108,110, 97,109,101, 41, 10,105,102, 32,110,111,116, 32, - 115,101,108,102, 46,108,110, 97,109,101,115, 91,108,110, 97, - 109,101, 93, 32,116,104,101,110, 10,115,101,108,102, 46,108, - 110, 97,109,101,115, 91,108,110, 97,109,101, 93, 32, 61, 32, - 48, 10,101,108,115,101, 10,115,101,108,102, 46,108,110, 97, - 109,101,115, 91,108,110, 97,109,101, 93, 32, 61, 32,115,101, - 108,102, 46,108,110, 97,109,101,115, 91,108,110, 97,109,101, - 93, 32, 43, 32, 49, 10,101,110,100, 10,114,101,116,117,114, - 110, 32,102,111,114,109, 97,116, 40, 34, 37, 48, 50,100, 34, - 44,115,101,108,102, 46,108,110, 97,109,101,115, 91,108,110, - 97,109,101, 93, 41, 10,101,110,100, 10, 10,102,117,110, 99, - 116,105,111,110, 32, 99,108, 97,115,115, 67,111,110,116, 97, - 105,110,101,114, 58,102,105,110,100,116,121,112,101,100,101, - 102, 32, 40,116,121,112,101, 41, 10,108,111, 99, 97,108, 32, - 101,110,118, 32, 61, 32,115,101,108,102, 10,119,104,105,108, - 101, 32,101,110,118, 32,100,111, 10,105,102, 32,101,110,118, - 46,116,121,112,101,100,101,102,115, 32,116,104,101,110, 10, - 108,111, 99, 97,108, 32,105, 61, 49, 10,119,104,105,108,101, - 32,101,110,118, 46,116,121,112,101,100,101,102,115, 91,105, - 93, 32,100,111, 10,105,102, 32,101,110,118, 46,116,121,112, - 101,100,101,102,115, 91,105, 93, 46,117,116,121,112,101, 32, - 61, 61, 32,116,121,112,101, 32,116,104,101,110, 10,108,111, - 99, 97,108, 32,109,111,100, 49, 44,116,121,112,101, 49, 32, - 61, 32,101,110,118, 46,116,121,112,101,100,101,102,115, 91, - 105, 93, 46,109,111,100, 44,101,110,118, 46,116,121,112,101, - 100,101,102,115, 91,105, 93, 46,116,121,112,101, 10,108,111, - 99, 97,108, 32,109,111,100, 50, 44,116,121,112,101, 50, 32, - 61, 32,102,105,110,100,116,121,112,101,100,101,102, 40,116, - 121,112,101, 49, 41, 10,114,101,116,117,114,110, 32,109,111, - 100, 50, 46, 46, 39, 32, 39, 46, 46,109,111,100, 49, 44,116, - 121,112,101, 50, 10,101,110,100, 10,105, 32, 61, 32,105, 43, - 49, 10,101,110,100, 10,101,110,100, 10,101,110,118, 32, 61, - 32,101,110,118, 46,112, 97,114,101,110,116, 10,101,110,100, - 10,114,101,116,117,114,110, 32, 39, 39, 44,116,121,112,101, - 10,101,110,100, 10, 10,102,117,110, 99,116,105,111,110, 32, - 99,108, 97,115,115, 67,111,110,116, 97,105,110,101,114, 58, - 105,115,116,121,112,101,100,101,102, 32, 40,116,121,112,101, - 41, 10,108,111, 99, 97,108, 32,101,110,118, 32, 61, 32,115, - 101,108,102, 10,119,104,105,108,101, 32,101,110,118, 32,100, - 111, 10,105,102, 32,101,110,118, 46,116,121,112,101,100,101, - 102,115, 32,116,104,101,110, 10,108,111, 99, 97,108, 32,105, - 61, 49, 10,119,104,105,108,101, 32,101,110,118, 46,116,121, - 112,101,100,101,102,115, 91,105, 93, 32,100,111, 10,105,102, - 32,101,110,118, 46,116,121,112,101,100,101,102,115, 91,105, - 93, 46,117,116,121,112,101, 32, 61, 61, 32,116,121,112,101, - 32,116,104,101,110, 10,114,101,116,117,114,110, 32, 49, 10, - 101,110,100, 10,105, 32, 61, 32,105, 43, 49, 10,101,110,100, - 10,101,110,100, 10,101,110,118, 32, 61, 32,101,110,118, 46, - 112, 97,114,101,110,116, 10,101,110,100, 10,114,101,116,117, - 114,110, 32,110,105,108, 10,101,110,100, 10, 10, 10,102,117, - 110, 99,116,105,111,110, 32, 99,108, 97,115,115, 67,111,110, - 116, 97,105,110,101,114, 58,100,111,112, 97,114,115,101, 32, - 40,115, 41, 10, 10, 10,100,111, 10,108,111, 99, 97,108, 32, - 98, 44,101, 44,110, 97,109,101, 44, 98,111,100,121, 32, 61, - 32,115,116,114,102,105,110,100, 40,115, 44, 34, 94, 37,115, - 42,109,111,100,117,108,101, 37,115, 37,115, 42, 40, 91, 95, - 37,119, 93, 91, 95, 37,119, 93, 42, 41, 37,115, 42, 40, 37, - 98,123,125, 41, 37,115, 42, 34, 41, 10,105,102, 32, 98, 32, - 116,104,101,110, 10, 95, 99,117,114,114, 95, 99,111,100,101, - 32, 61, 32,115,116,114,115,117, 98, 40,115, 44, 98, 44,101, - 41, 10, 77,111,100,117,108,101, 40,110, 97,109,101, 44, 98, - 111,100,121, 41, 10,114,101,116,117,114,110, 32,115,116,114, - 115,117, 98, 40,115, 44,101, 43, 49, 41, 10,101,110,100, 10, - 101,110,100, 10, 10, 10,100,111, 10,108,111, 99, 97,108, 32, - 98, 44,101, 44,110, 97,109,101, 32, 61, 32,115,116,114,102, - 105,110,100, 40,115, 44, 34, 94, 37,115, 42, 35,100,101,102, - 105,110,101, 37,115, 37,115, 42, 40, 91, 94, 37,115, 93, 42, - 41, 91, 94, 92,110, 93, 42, 92,110, 37,115, 42, 34, 41, 10, - 105,102, 32, 98, 32,116,104,101,110, 10, 95, 99,117,114,114, - 95, 99,111,100,101, 32, 61, 32,115,116,114,115,117, 98, 40, - 115, 44, 98, 44,101, 41, 10, 68,101,102,105,110,101, 40,110, - 97,109,101, 41, 10,114,101,116,117,114,110, 32,115,116,114, - 115,117, 98, 40,115, 44,101, 43, 49, 41, 10,101,110,100, 10, - 101,110,100, 10, 10, 10,100,111, 10,108,111, 99, 97,108, 32, - 98, 44,101, 44, 98,111,100,121, 32, 61, 32,115,116,114,102, - 105,110,100, 40,115, 44, 34, 94, 37,115, 42,101,110,117,109, - 91, 94,123, 93, 42, 40, 37, 98,123,125, 41, 37,115, 42, 59, - 63, 37,115, 42, 34, 41, 10,105,102, 32, 98, 32,116,104,101, - 110, 10, 95, 99,117,114,114, 95, 99,111,100,101, 32, 61, 32, - 115,116,114,115,117, 98, 40,115, 44, 98, 44,101, 41, 10, 69, - 110,117,109,101,114, 97,116,101, 40, 98,111,100,121, 41, 10, - 114,101,116,117,114,110, 32,115,116,114,115,117, 98, 40,115, - 44,101, 43, 49, 41, 10,101,110,100, 10,101,110,100, 10, 10, - 100,111, 10,108,111, 99, 97,108, 32, 98, 44,101, 44, 98,111, - 100,121, 44,110, 97,109,101, 32, 61, 32,115,116,114,102,105, - 110,100, 40,115, 44, 34, 94, 37,115, 42,116,121,112,101,100, - 101,102, 37,115, 37,115, 42,101,110,117,109, 91, 94,123, 93, - 42, 40, 37, 98,123,125, 41, 37,115, 42, 40, 91, 37,119, 95, - 93, 91, 94, 37,115, 93, 42, 41, 37,115, 42, 59, 37,115, 42, - 34, 41, 10,105,102, 32, 98, 32,116,104,101,110, 10, 95, 99, - 117,114,114, 95, 99,111,100,101, 32, 61, 32,115,116,114,115, - 117, 98, 40,115, 44, 98, 44,101, 41, 10, 69,110,117,109,101, - 114, 97,116,101, 40, 98,111,100,121, 41, 10, 84,121,112,101, - 100,101,102, 40, 34,105,110,116, 32, 34, 46, 46,110, 97,109, - 101, 41, 10,114,101,116,117,114,110, 32,115,116,114,115,117, - 98, 40,115, 44,101, 43, 49, 41, 10,101,110,100, 10,101,110, - 100, 10, 10, 10,100,111, 10,108,111, 99, 97,108, 32, 98, 44, - 101, 44,100,101, 99,108, 44,107,105,110,100, 44, 97,114,103, - 44, 99,111,110,115,116, 32, 61, 32,115,116,114,102,105,110, - 100, 40,115, 44, 34, 94, 37,115, 42, 40, 91, 95, 37,119, 93, - 91, 95, 37,119, 37,115, 37, 42, 38, 93, 42,111,112,101,114, - 97,116,111,114, 41, 37,115, 42, 40, 91, 94, 37,115, 93, 91, - 94, 37,115, 93, 42, 41, 37,115, 42, 40, 37, 98, 40, 41, 41, - 37,115, 42, 40, 99, 63,111, 63,110, 63,115, 63,116, 63, 41, - 37,115, 42, 59, 37,115, 42, 34, 41, 10,105,102, 32, 98, 32, - 116,104,101,110, 10, 95, 99,117,114,114, 95, 99,111,100,101, - 32, 61, 32,115,116,114,115,117, 98, 40,115, 44, 98, 44,101, - 41, 10, 79,112,101,114, 97,116,111,114, 40,100,101, 99,108, - 44,107,105,110,100, 44, 97,114,103, 44, 99,111,110,115,116, - 41, 10,114,101,116,117,114,110, 32,115,116,114,115,117, 98, - 40,115, 44,101, 43, 49, 41, 10,101,110,100, 10,101,110,100, - 10, 10, 10,100,111, 10,108,111, 99, 97,108, 32, 98, 44,101, - 44,100,101, 99,108, 44, 97,114,103, 44, 99,111,110,115,116, - 32, 61, 32,115,116,114,102,105,110,100, 40,115, 44, 34, 94, - 37,115, 42, 40, 91,126, 95, 37,119, 93, 91, 95, 64, 37,119, - 37,115, 37, 42, 38, 93, 42, 91, 95, 37,119, 93, 41, 37,115, - 42, 40, 37, 98, 40, 41, 41, 37,115, 42, 40, 99, 63,111, 63, - 110, 63,115, 63,116, 63, 41, 37,115, 42, 61, 63, 37,115, 42, - 48, 63, 37,115, 42, 59, 37,115, 42, 34, 41, 10,105,102, 32, - 110,111,116, 32, 98, 32,116,104,101,110, 10, 10, 98, 44,101, - 44,100,101, 99,108, 44, 97,114,103, 44, 99,111,110,115,116, - 32, 61, 32,115,116,114,102,105,110,100, 40,115, 44, 34, 94, - 37,115, 42, 40, 91, 95, 37,119, 93, 41, 37,115, 42, 40, 37, - 98, 40, 41, 41, 37,115, 42, 40, 99, 63,111, 63,110, 63,115, - 63,116, 63, 41, 37,115, 42, 59, 37,115, 42, 34, 41, 10,101, - 110,100, 10,105,102, 32, 98, 32,116,104,101,110, 10, 95, 99, - 117,114,114, 95, 99,111,100,101, 32, 61, 32,115,116,114,115, - 117, 98, 40,115, 44, 98, 44,101, 41, 10, 70,117,110, 99,116, - 105,111,110, 40,100,101, 99,108, 44, 97,114,103, 44, 99,111, - 110,115,116, 41, 10,114,101,116,117,114,110, 32,115,116,114, - 115,117, 98, 40,115, 44,101, 43, 49, 41, 10,101,110,100, 10, - 101,110,100, 10, 10, 10,100,111, 10,108,111, 99, 97,108, 32, - 98, 44,101, 44,100,101, 99,108, 44, 97,114,103, 44, 99,111, - 110,115,116, 32, 61, 32,115,116,114,102,105,110,100, 40,115, - 44, 34, 94, 37,115, 42, 40, 91,126, 95, 37,119, 93, 91, 95, - 64, 37,119, 37,115, 37, 42, 38, 93, 42, 91, 95, 37,119, 93, - 41, 37,115, 42, 40, 37, 98, 40, 41, 41, 37,115, 42, 40, 99, - 63,111, 63,110, 63,115, 63,116, 63, 41, 37,115, 42, 37, 98, - 123,125, 37,115, 42, 34, 41, 10,105,102, 32,110,111,116, 32, - 98, 32,116,104,101,110, 10, 10, 98, 44,101, 44,100,101, 99, - 108, 44, 97,114,103, 44, 99,111,110,115,116, 32, 61, 32,115, - 116,114,102,105,110,100, 40,115, 44, 34, 94, 37,115, 42, 40, - 91, 95, 37,119, 93, 41, 37,115, 42, 40, 37, 98, 40, 41, 41, - 37,115, 42, 40, 99, 63,111, 63,110, 63,115, 63,116, 63, 41, - 37,115, 42, 37, 98,123,125, 37,115, 42, 34, 41, 10,101,110, - 100, 10,105,102, 32, 98, 32,116,104,101,110, 10, 95, 99,117, - 114,114, 95, 99,111,100,101, 32, 61, 32,115,116,114,115,117, - 98, 40,115, 44, 98, 44,101, 41, 10, 70,117,110, 99,116,105, - 111,110, 40,100,101, 99,108, 44, 97,114,103, 44, 99,111,110, - 115,116, 41, 10,114,101,116,117,114,110, 32,115,116,114,115, - 117, 98, 40,115, 44,101, 43, 49, 41, 10,101,110,100, 10,101, - 110,100, 10, 10, 10,100,111, 10,108,111, 99, 97,108, 32, 98, - 44,101, 44,110, 97,109,101, 44, 98, 97,115,101, 44, 98,111, - 100,121, 32, 61, 32,115,116,114,102,105,110,100, 40,115, 44, - 34, 94, 37,115, 42, 99,108, 97,115,115, 37,115, 42, 40, 91, - 95, 37,119, 93, 91, 95, 37,119, 93, 42, 41, 37,115, 42, 40, - 46, 45, 41, 37,115, 42, 40, 37, 98,123,125, 41, 37,115, 42, - 59, 37,115, 42, 34, 41, 10,105,102, 32,110,111,116, 32, 98, - 32,116,104,101,110, 10, 98, 44,101, 44,110, 97,109,101, 44, - 98, 97,115,101, 44, 98,111,100,121, 32, 61, 32,115,116,114, - 102,105,110,100, 40,115, 44, 34, 94, 37,115, 42,115,116,114, - 117, 99,116, 37,115, 42, 40, 91, 95, 37,119, 93, 91, 95, 37, - 119, 93, 42, 41, 37,115, 42, 40, 46, 45, 41, 37,115, 42, 40, - 37, 98,123,125, 41, 37,115, 42, 59, 37,115, 42, 34, 41, 10, - 105,102, 32,110,111,116, 32, 98, 32,116,104,101,110, 10, 98, - 97,115,101, 32, 61, 32, 39, 39, 10, 98, 44,101, 44, 98,111, - 100,121, 44,110, 97,109,101, 32, 61, 32,115,116,114,102,105, - 110,100, 40,115, 44, 34, 94, 37,115, 42,116,121,112,101,100, - 101,102, 37,115, 37,115, 42,115,116,114,117, 99,116, 37,115, - 37,115, 42, 91, 95, 37,119, 93, 42, 37,115, 42, 40, 37, 98, - 123,125, 41, 37,115, 42, 40, 91, 95, 37,119, 93, 91, 95, 37, - 119, 93, 42, 41, 37,115, 42, 59, 37,115, 42, 34, 41, 10,101, - 110,100, 10,101,110,100, 10,105,102, 32, 98, 32,116,104,101, - 110, 10,105,102, 32, 98, 97,115,101, 32,126, 61, 32, 39, 39, - 32,116,104,101,110, 10,108,111, 99, 97,108, 32, 98, 44,101, - 10, 98, 44,101, 44, 98, 97,115,101, 32, 61, 32,115,116,114, - 102,105,110,100, 40, 98, 97,115,101, 44, 34, 46, 45, 40, 91, - 95, 37,119, 93, 91, 95, 37,119, 93, 42, 41, 36, 34, 41, 10, - 101,110,100, 10, 95, 99,117,114,114, 95, 99,111,100,101, 32, - 61, 32,115,116,114,115,117, 98, 40,115, 44, 98, 44,101, 41, - 10, 67,108, 97,115,115, 40,110, 97,109,101, 44, 98, 97,115, - 101, 44, 98,111,100,121, 41, 10,114,101,116,117,114,110, 32, - 115,116,114,115,117, 98, 40,115, 44,101, 43, 49, 41, 10,101, - 110,100, 10,101,110,100, 10, 10, 10,100,111, 10,108,111, 99, - 97,108, 32, 98, 44,101, 44,116,121,112,101,115, 32, 61, 32, - 115,116,114,102,105,110,100, 40,115, 44, 34, 94, 37,115, 42, - 116,121,112,101,100,101,102, 37,115, 37,115, 42, 40, 46, 45, - 41, 37,115, 42, 59, 37,115, 42, 34, 41, 10,105,102, 32, 98, - 32,116,104,101,110, 10, 95, 99,117,114,114, 95, 99,111,100, - 101, 32, 61, 32,115,116,114,115,117, 98, 40,115, 44, 98, 44, - 101, 41, 10, 84,121,112,101,100,101,102, 40,116,121,112,101, - 115, 41, 10,114,101,116,117,114,110, 32,115,116,114,115,117, - 98, 40,115, 44,101, 43, 49, 41, 10,101,110,100, 10,101,110, - 100, 10, 10, 10,100,111, 10,108,111, 99, 97,108, 32, 98, 44, - 101, 44,100,101, 99,108, 32, 61, 32,115,116,114,102,105,110, - 100, 40,115, 44, 34, 94, 37,115, 42, 40, 91, 95, 37,119, 93, - 91, 95, 64, 37,115, 37,119, 37,100, 37, 42, 38, 93, 42, 91, - 95, 37,119, 37,100, 93, 41, 37,115, 42, 59, 37,115, 42, 34, - 41, 10,105,102, 32, 98, 32,116,104,101,110, 10, 95, 99,117, - 114,114, 95, 99,111,100,101, 32, 61, 32,115,116,114,115,117, - 98, 40,115, 44, 98, 44,101, 41, 10, 86, 97,114,105, 97, 98, - 108,101, 40,100,101, 99,108, 41, 10,114,101,116,117,114,110, - 32,115,116,114,115,117, 98, 40,115, 44,101, 43, 49, 41, 10, - 101,110,100, 10,101,110,100, 10, 10, 10,100,111, 10,108,111, - 99, 97,108, 32, 98, 44,101, 44,100,101, 99,108, 32, 61, 32, - 115,116,114,102,105,110,100, 40,115, 44, 34, 94, 37,115, 42, - 40, 91, 95, 37,119, 93, 91, 93, 91, 95, 64, 37,115, 37,119, - 37,100, 37, 42, 38, 37, 45, 37, 62, 93, 42, 91, 93, 95, 37, - 119, 37,100, 93, 41, 37,115, 42, 59, 37,115, 42, 34, 41, 10, - 105,102, 32, 98, 32,116,104,101,110, 10, 95, 99,117,114,114, - 95, 99,111,100,101, 32, 61, 32,115,116,114,115,117, 98, 40, - 115, 44, 98, 44,101, 41, 10, 65,114,114, 97,121, 40,100,101, - 99,108, 41, 10,114,101,116,117,114,110, 32,115,116,114,115, - 117, 98, 40,115, 44,101, 43, 49, 41, 10,101,110,100, 10,101, - 110,100, 10, 10, 10,100,111, 10,108,111, 99, 97,108, 32, 98, - 44,101, 44, 99,111,100,101, 32, 61, 32,115,116,114,102,105, - 110,100, 40,115, 44, 34, 94, 37,115, 42, 40, 37, 98, 92, 49, - 92, 50, 41, 34, 41, 10,105,102, 32, 98, 32,116,104,101,110, - 10, 67,111,100,101, 40,115,116,114,115,117, 98, 40, 99,111, - 100,101, 44, 50, 44, 45, 50, 41, 41, 10,114,101,116,117,114, - 110, 32,115,116,114,115,117, 98, 40,115, 44,101, 43, 49, 41, - 10,101,110,100, 10,101,110,100, 10, 10, 10,100,111, 10,108, - 111, 99, 97,108, 32, 98, 44,101, 44,108,105,110,101, 32, 61, - 32,115,116,114,102,105,110,100, 40,115, 44, 34, 94, 37,115, - 42, 37, 36, 40, 46, 45, 92,110, 41, 34, 41, 10,105,102, 32, - 98, 32,116,104,101,110, 10, 86,101,114, 98, 97,116,105,109, - 40,108,105,110,101, 41, 10,114,101,116,117,114,110, 32,115, - 116,114,115,117, 98, 40,115, 44,101, 43, 49, 41, 10,101,110, - 100, 10,101,110,100, 10, 10, 10,105,102, 32,103,115,117, 98, - 40,115, 44, 34, 37,115, 37,115, 42, 34, 44, 34, 34, 41, 32, - 126, 61, 32, 34, 34, 32,116,104,101,110, 10, 95, 99,117,114, - 114, 95, 99,111,100,101, 32, 61, 32,115, 10,101,114,114,111, - 114, 40, 34, 35,112, 97,114,115,101, 32,101,114,114,111,114, - 34, 41, 10,101,108,115,101, 10,114,101,116,117,114,110, 32, - 34, 34, 10,101,110,100, 10,101,110,100, 10, 10,102,117,110, - 99,116,105,111,110, 32, 99,108, 97,115,115, 67,111,110,116, - 97,105,110,101,114, 58,112, 97,114,115,101, 32, 40,115, 41, - 10,119,104,105,108,101, 32,115, 32,126, 61, 32, 39, 39, 32, - 100,111, 10,115, 32, 61, 32,115,101,108,102, 58,100,111,112, - 97,114,115,101, 40,115, 41, 10,101,110,100, 10,101,110,100, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 99,108, 97,115,115, 80, 97, 99,107, 97, - 103,101, 32, 61, 32,123, 10, 95, 98, 97,115,101, 32, 61, 32, - 99,108, 97,115,115, 67,111,110,116, 97,105,110,101,114, 44, - 10,116,121,112,101, 32, 61, 32, 39,112, 97, 99,107, 97,103, - 101, 39, 10,125, 10,115,101,116,116, 97,103, 40, 99,108, 97, - 115,115, 80, 97, 99,107, 97,103,101, 44,116,111,108,117, 97, - 95,116, 97,103, 41, 10, 10, 10,102,117,110, 99,116,105,111, - 110, 32, 99,108, 97,115,115, 80, 97, 99,107, 97,103,101, 58, - 112,114,105,110,116, 32, 40, 41, 10,112,114,105,110,116, 40, - 34, 80, 97, 99,107, 97,103,101, 58, 32, 34, 46, 46,115,101, - 108,102, 46,110, 97,109,101, 41, 10,108,111, 99, 97,108, 32, - 105, 61, 49, 10,119,104,105,108,101, 32,115,101,108,102, 91, - 105, 93, 32,100,111, 10,115,101,108,102, 91,105, 93, 58,112, - 114,105,110,116, 40, 34, 34, 44, 34, 34, 41, 10,105, 32, 61, - 32,105, 43, 49, 10,101,110,100, 10,101,110,100, 10, 10,102, - 117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 80, 97, - 99,107, 97,103,101, 58,112,114,101,112,114,111, 99,101,115, - 115, 32, 40, 41, 10,115,101,108,102, 46, 99,111,100,101, 32, - 61, 32, 34, 92,110, 34, 46, 46,115,101,108,102, 46, 99,111, - 100,101, 10, 10,108,111, 99, 97,108, 32, 86, 32, 61, 32,123, - 125, 10,115,101,108,102, 46, 99,111,100,101, 32, 61, 32,103, - 115,117, 98, 40,115,101,108,102, 46, 99,111,100,101, 44, 34, - 92,110, 40, 37,115, 42, 37, 36, 91, 94, 37, 91, 37, 93, 93, - 91, 94, 92,110, 93, 42, 41, 34, 44,102,117,110, 99,116,105, - 111,110, 32, 40,118, 41, 10,116,105,110,115,101,114,116, 40, - 37, 86, 44,118, 41, 10,114,101,116,117,114,110, 32, 34, 92, - 110, 36, 34, 46, 46,103,101,116,110, 40, 37, 86, 41, 46, 46, - 34, 36, 34, 10,101,110,100, 41, 10, 10,108,111, 99, 97,108, - 32, 67, 32, 61, 32,123,125, 10,115,101,108,102, 46, 99,111, - 100,101, 32, 61, 32,103,115,117, 98, 40,115,101,108,102, 46, - 99,111,100,101, 44, 34, 92,110, 37,115, 42, 37, 36, 37, 91, - 34, 44, 34, 92, 49, 34, 41, 10,115,101,108,102, 46, 99,111, - 100,101, 32, 61, 32,103,115,117, 98, 40,115,101,108,102, 46, - 99,111,100,101, 44, 34, 92,110, 37,115, 42, 37, 36, 37, 93, - 34, 44, 34, 92, 50, 34, 41, 10,115,101,108,102, 46, 99,111, - 100,101, 32, 61, 32,103,115,117, 98, 40,115,101,108,102, 46, - 99,111,100,101, 44, 34, 40, 37, 98, 92, 49, 92, 50, 41, 34, - 44, 32,102,117,110, 99,116,105,111,110, 32, 40, 99, 41, 10, - 116,105,110,115,101,114,116, 40, 37, 67, 44, 99, 41, 10,114, - 101,116,117,114,110, 32, 34, 92,110, 36, 91, 34, 46, 46,103, - 101,116,110, 40, 37, 67, 41, 46, 46, 34, 93, 36, 34, 10,101, - 110,100, 41, 10, 10, 10,115,101,108,102, 46, 99,111,100,101, - 32, 61, 32,103,115,117, 98, 40,115,101,108,102, 46, 99,111, - 100,101, 44, 34, 40, 47, 47, 91, 94, 92,110, 93, 42, 41, 34, - 44, 34, 34, 41, 10,115,101,108,102, 46, 99,111,100,101, 32, - 61, 32,103,115,117, 98, 40,115,101,108,102, 46, 99,111,100, - 101, 44, 34, 47, 37, 42, 34, 44, 34, 92, 49, 34, 41, 10,115, - 101,108,102, 46, 99,111,100,101, 32, 61, 32,103,115,117, 98, - 40,115,101,108,102, 46, 99,111,100,101, 44, 34, 37, 42, 47, - 34, 44, 34, 92, 50, 34, 41, 10,115,101,108,102, 46, 99,111, - 100,101, 32, 61, 32,103,115,117, 98, 40,115,101,108,102, 46, - 99,111,100,101, 44, 34, 37, 98, 92, 49, 92, 50, 34, 44, 34, - 34, 41, 10,115,101,108,102, 46, 99,111,100,101, 32, 61, 32, - 103,115,117, 98, 40,115,101,108,102, 46, 99,111,100,101, 44, - 34, 92, 49, 34, 44, 34, 47, 37, 42, 34, 41, 10,115,101,108, - 102, 46, 99,111,100,101, 32, 61, 32,103,115,117, 98, 40,115, - 101,108,102, 46, 99,111,100,101, 44, 34, 92, 50, 34, 44, 34, - 37, 42, 47, 34, 41, 10,115,101,108,102, 46, 99,111,100,101, - 32, 61, 32,103,115,117, 98, 40,115,101,108,102, 46, 99,111, - 100,101, 44, 34, 37,115, 42, 64, 37,115, 42, 34, 44, 34, 64, - 34, 41, 10,115,101,108,102, 46, 99,111,100,101, 32, 61, 32, - 103,115,117, 98, 40,115,101,108,102, 46, 99,111,100,101, 44, - 34, 37,115, 63,105,110,108,105,110,101, 40, 37,115, 41, 34, - 44, 34, 37, 49, 34, 41, 10,115,101,108,102, 46, 99,111,100, - 101, 32, 61, 32,103,115,117, 98, 40,115,101,108,102, 46, 99, - 111,100,101, 44, 34, 37,115, 63,101,120,116,101,114,110, 40, - 37,115, 41, 34, 44, 34, 37, 49, 34, 41, 10,115,101,108,102, - 46, 99,111,100,101, 32, 61, 32,103,115,117, 98, 40,115,101, - 108,102, 46, 99,111,100,101, 44, 34, 37,115, 63,118,105,114, - 116,117, 97,108, 40, 37,115, 41, 34, 44, 34, 37, 49, 34, 41, - 10,115,101,108,102, 46, 99,111,100,101, 32, 61, 32,103,115, - 117, 98, 40,115,101,108,102, 46, 99,111,100,101, 44, 34,112, - 117, 98,108,105, 99, 58, 34, 44, 34, 34, 41, 10,115,101,108, - 102, 46, 99,111,100,101, 32, 61, 32,103,115,117, 98, 40,115, - 101,108,102, 46, 99,111,100,101, 44, 34, 40, 91, 94, 37,119, - 95, 93, 41,118,111,105,100, 37,115, 42, 37, 42, 34, 44, 34, - 37, 49, 95,117,115,101,114,100, 97,116, 97, 32, 34, 41, 10, - 115,101,108,102, 46, 99,111,100,101, 32, 61, 32,103,115,117, - 98, 40,115,101,108,102, 46, 99,111,100,101, 44, 34, 40, 91, - 94, 37,119, 95, 93, 41,118,111,105,100, 37,115, 42, 37, 42, - 34, 44, 34, 37, 49, 95,117,115,101,114,100, 97,116, 97, 32, - 34, 41, 10,115,101,108,102, 46, 99,111,100,101, 32, 61, 32, - 103,115,117, 98, 40,115,101,108,102, 46, 99,111,100,101, 44, - 34, 40, 91, 94, 37,119, 95, 93, 41, 99,104, 97,114, 37,115, - 42, 37, 42, 34, 44, 34, 37, 49, 95, 99,115,116,114,105,110, - 103, 32, 34, 41, 10, 10, 10,115,101,108,102, 46, 99,111,100, - 101, 32, 61, 32,103,115,117, 98, 40,115,101,108,102, 46, 99, - 111,100,101, 44, 34, 37, 36, 37, 91, 40, 37,100, 43, 41, 37, - 93, 37, 36, 34, 44,102,117,110, 99,116,105,111,110, 32, 40, - 110, 41, 10,114,101,116,117,114,110, 32, 37, 67, 91,116,111, - 110,117,109, 98,101,114, 40,110, 41, 93, 10,101,110,100, 41, - 10, 10,115,101,108,102, 46, 99,111,100,101, 32, 61, 32,103, - 115,117, 98, 40,115,101,108,102, 46, 99,111,100,101, 44, 34, - 37, 36, 40, 37,100, 43, 41, 37, 36, 34, 44,102,117,110, 99, - 116,105,111,110, 32, 40,110, 41, 10,114,101,116,117,114,110, - 32, 37, 86, 91,116,111,110,117,109, 98,101,114, 40,110, 41, - 93, 10,101,110,100, 41, 10,101,110,100, 10, 10, 10,102,117, - 110, 99,116,105,111,110, 32, 99,108, 97,115,115, 80, 97, 99, - 107, 97,103,101, 58,112,114,101, 97,109, 98,108,101, 32, 40, - 41, 10,111,117,116,112,117,116, 40, 39, 47, 42, 92,110, 39, - 41, 10,111,117,116,112,117,116, 40, 39, 42, 42, 32, 76,117, - 97, 32, 98,105,110,100,105,110,103, 58, 32, 39, 46, 46,115, - 101,108,102, 46,110, 97,109,101, 46, 46, 39, 92,110, 39, 41, - 10,111,117,116,112,117,116, 40, 39, 42, 42, 32, 71,101,110, - 101,114, 97,116,101,100, 32, 97,117,116,111,109, 97,116,105, - 99, 97,108,108,121, 32, 98,121, 32, 39, 46, 46, 84, 79, 76, - 85, 65, 95, 86, 69, 82, 83, 73, 79, 78, 46, 46, 39, 32,111, - 110, 32, 39, 46, 46,100, 97,116,101, 40, 41, 46, 46, 39, 46, - 92,110, 39, 41, 10,111,117,116,112,117,116, 40, 39, 42, 47, - 92,110, 92,110, 39, 41, 10, 10,111,117,116,112,117,116, 40, - 39, 35,105,110, 99,108,117,100,101, 32, 34,108,117, 97, 47, - 116,111,108,117, 97, 46,104, 34, 92,110, 92,110, 39, 41, 10, - 10,105,102, 32,110,111,116, 32,102,108, 97,103,115, 46,104, - 32,116,104,101,110, 10,111,117,116,112,117,116, 40, 39, 47, - 42, 32, 69,120,112,111,114,116,101,100, 32,102,117,110, 99, - 116,105,111,110, 32, 42, 47, 39, 41, 10,111,117,116,112,117, - 116, 40, 39,105,110,116, 32,116,111,108,117, 97, 95, 39, 46, - 46,115,101,108,102, 46,110, 97,109,101, 46, 46, 39, 95,111, - 112,101,110, 32, 40,108,117, 97, 95, 83,116, 97,116,101, 42, - 32,116,111,108,117, 97, 95, 83, 41, 59, 39, 41, 10,111,117, - 116,112,117,116, 40, 39,118,111,105,100, 32,116,111,108,117, - 97, 95, 39, 46, 46,115,101,108,102, 46,110, 97,109,101, 46, - 46, 39, 95, 99,108,111,115,101, 32, 40,108,117, 97, 95, 83, - 116, 97,116,101, 42, 32,116,111,108,117, 97, 95, 83, 41, 59, - 39, 41, 10,111,117,116,112,117,116, 40, 39, 92,110, 39, 41, - 10,101,110,100, 10, 10,108,111, 99, 97,108, 32,105, 61, 49, - 10,119,104,105,108,101, 32,115,101,108,102, 91,105, 93, 32, - 100,111, 10,115,101,108,102, 91,105, 93, 58,112,114,101, 97, - 109, 98,108,101, 40, 41, 10,105, 32, 61, 32,105, 43, 49, 10, - 101,110,100, 10,111,117,116,112,117,116, 40, 39, 92,110, 39, - 41, 10,111,117,116,112,117,116, 40, 39, 47, 42, 32,102,117, - 110, 99,116,105,111,110, 32,116,111, 32,114,101,103,105,115, - 116,101,114, 32,116,121,112,101, 32, 42, 47, 39, 41, 10,111, - 117,116,112,117,116, 40, 39,115,116, 97,116,105, 99, 32,118, - 111,105,100, 32,116,111,108,117, 97, 73, 95,114,101,103, 95, - 116,121,112,101,115, 32, 40,108,117, 97, 95, 83,116, 97,116, - 101, 42, 32,116,111,108,117, 97, 95, 83, 41, 39, 41, 10,111, - 117,116,112,117,116, 40, 39,123, 39, 41, 10,102,111,114,101, - 97, 99,104, 40, 95,117,115,101,114,116,121,112,101, 44,102, - 117,110, 99,116,105,111,110, 40,110, 44,118, 41, 32,111,117, - 116,112,117,116, 40, 39, 32,116,111,108,117, 97, 95,117,115, - 101,114,116,121,112,101, 40,116,111,108,117, 97, 95, 83, 44, - 34, 39, 44,118, 44, 39, 34, 41, 59, 39, 41, 32,101,110,100, - 41, 10,111,117,116,112,117,116, 40, 39,125, 39, 41, 10,111, - 117,116,112,117,116, 40, 39, 92,110, 39, 41, 10, 10,111,117, - 116,112,117,116, 40, 39, 47, 42, 32,101,114,114,111,114, 32, - 109,101,115,115, 97,103,101,115, 32, 42, 47, 39, 41, 10,111, - 117,116,112,117,116, 40, 39, 35,100,101,102,105,110,101, 32, - 84, 79, 76, 85, 65, 95, 69, 82, 82, 95, 83, 69, 76, 70, 32, - 116,111,108,117, 97, 95,101,114,114,111,114, 40,116,111,108, - 117, 97, 95, 83, 44, 92, 34,105,110,118, 97,108,105,100, 32, - 92, 39,115,101,108,102, 92, 39, 92, 34, 41, 39, 41, 10,111, - 117,116,112,117,116, 40, 39, 35,100,101,102,105,110,101, 32, - 84, 79, 76, 85, 65, 95, 69, 82, 82, 95, 65, 83, 83, 73, 71, - 78, 32,116,111,108,117, 97, 95,101,114,114,111,114, 40,116, - 111,108,117, 97, 95, 83, 44, 92, 34, 35,118,105,110,118, 97, - 108,105,100, 32,116,121,112,101, 32,105,110, 32,118, 97,114, - 105, 97, 98,108,101, 32, 97,115,115,105,103,110,109,101,110, - 116, 46, 92, 34, 41, 39, 41, 10,111,117,116,112,117,116, 40, - 39, 92,110, 39, 41, 10,101,110,100, 10, 10, 10, 10,102,117, - 110, 99,116,105,111,110, 32, 99,108, 97,115,115, 80, 97, 99, - 107, 97,103,101, 58,114,101,103,105,115,116,101,114, 32, 40, - 41, 10,111,117,116,112,117,116, 40, 34, 47, 42, 32, 79,112, - 101,110, 32,102,117,110, 99,116,105,111,110, 32, 42, 47, 34, - 41, 10,111,117,116,112,117,116, 40, 34,105,110,116, 32,116, - 111,108,117, 97, 95, 34, 46, 46,115,101,108,102, 46,110, 97, - 109,101, 46, 46, 34, 95,111,112,101,110, 32, 40,108,117, 97, - 95, 83,116, 97,116,101, 42, 32,116,111,108,117, 97, 95, 83, - 41, 34, 41, 10,111,117,116,112,117,116, 40, 34,123, 34, 41, - 10,111,117,116,112,117,116, 40, 34, 32,116,111,108,117, 97, - 95,111,112,101,110, 40,116,111,108,117, 97, 95, 83, 41, 59, - 34, 41, 10,111,117,116,112,117,116, 40, 34, 32,116,111,108, - 117, 97, 73, 95,114,101,103, 95,116,121,112,101,115, 40,116, - 111,108,117, 97, 95, 83, 41, 59, 34, 41, 10,108,111, 99, 97, - 108, 32,105, 61, 49, 10,119,104,105,108,101, 32,115,101,108, - 102, 91,105, 93, 32,100,111, 10,115,101,108,102, 91,105, 93, - 58,114,101,103,105,115,116,101,114, 40, 41, 10,105, 32, 61, - 32,105, 43, 49, 10,101,110,100, 10,111,117,116,112,117,116, - 40, 34, 32,114,101,116,117,114,110, 32, 49, 59, 34, 41, 10, - 111,117,116,112,117,116, 40, 34,125, 34, 41, 10,101,110,100, - 10, 10, 10, 10,102,117,110, 99,116,105,111,110, 32, 99,108, - 97,115,115, 80, 97, 99,107, 97,103,101, 58,117,110,114,101, - 103,105,115,116,101,114, 32, 40, 41, 10,111,117,116,112,117, - 116, 40, 34, 47, 42, 32, 67,108,111,115,101, 32,102,117,110, - 99,116,105,111,110, 32, 42, 47, 34, 41, 10,111,117,116,112, - 117,116, 40, 34,118,111,105,100, 32,116,111,108,117, 97, 95, - 34, 46, 46,115,101,108,102, 46,110, 97,109,101, 46, 46, 34, - 95, 99,108,111,115,101, 32, 40,108,117, 97, 95, 83,116, 97, - 116,101, 42, 32,116,111,108,117, 97, 95, 83, 41, 34, 41, 10, - 111,117,116,112,117,116, 40, 34,123, 34, 41, 10,108,111, 99, - 97,108, 32,105, 61, 49, 10,119,104,105,108,101, 32,115,101, - 108,102, 91,105, 93, 32,100,111, 10,115,101,108,102, 91,105, - 93, 58,117,110,114,101,103,105,115,116,101,114, 40, 41, 10, - 105, 32, 61, 32,105, 43, 49, 10,101,110,100, 10,111,117,116, - 112,117,116, 40, 34,125, 34, 41, 10,101,110,100, 10, 10, 10, - 102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 80, - 97, 99,107, 97,103,101, 58,104,101, 97,100,101,114, 32, 40, - 41, 10,111,117,116,112,117,116, 40, 39, 47, 42, 92,110, 39, - 41, 32,111,117,116,112,117,116, 40, 39, 42, 42, 32, 76,117, - 97, 32, 98,105,110,100,105,110,103, 58, 32, 39, 46, 46,115, - 101,108,102, 46,110, 97,109,101, 46, 46, 39, 92,110, 39, 41, - 10,111,117,116,112,117,116, 40, 39, 42, 42, 32, 71,101,110, - 101,114, 97,116,101,100, 32, 97,117,116,111,109, 97,116,105, - 99, 97,108,108,121, 32, 98,121, 32, 39, 46, 46, 84, 79, 76, - 85, 65, 95, 86, 69, 82, 83, 73, 79, 78, 46, 46, 39, 32,111, - 110, 32, 39, 46, 46,100, 97,116,101, 40, 41, 46, 46, 39, 46, - 92,110, 39, 41, 10,111,117,116,112,117,116, 40, 39, 42, 47, - 92,110, 92,110, 39, 41, 10, 10,105,102, 32,110,111,116, 32, - 102,108, 97,103,115, 46,104, 32,116,104,101,110, 10,111,117, - 116,112,117,116, 40, 39, 47, 42, 32, 69,120,112,111,114,116, - 101,100, 32,102,117,110, 99,116,105,111,110, 32, 42, 47, 39, - 41, 10,111,117,116,112,117,116, 40, 39,105,110,116, 32,116, - 111,108,117, 97, 95, 39, 46, 46,115,101,108,102, 46,110, 97, - 109,101, 46, 46, 39, 95,111,112,101,110, 32, 40,108,117, 97, - 95, 83,116, 97,116,101, 42, 32,116,111,108,117, 97, 95, 83, - 41, 59, 39, 41, 10,111,117,116,112,117,116, 40, 39,118,111, - 105,100, 32,116,111,108,117, 97, 95, 39, 46, 46,115,101,108, - 102, 46,110, 97,109,101, 46, 46, 39, 95, 99,108,111,115,101, - 32, 40,108,117, 97, 95, 83,116, 97,116,101, 42, 32,116,111, - 108,117, 97, 95, 83, 41, 59, 39, 41, 10,111,117,116,112,117, - 116, 40, 39, 92,110, 39, 41, 10,101,110,100, 10,101,110,100, - 10, 10, 10,102,117,110, 99,116,105,111,110, 32, 95, 80, 97, - 99,107, 97,103,101, 32, 40,116, 41, 10,116, 46, 95, 98, 97, - 115,101, 32, 61, 32, 99,108, 97,115,115, 80, 97, 99,107, 97, - 103,101, 10,115,101,116,116, 97,103, 40,116, 44,116,111,108, - 117, 97, 95,116, 97,103, 41, 10,114,101,116,117,114,110, 32, - 116, 10,101,110,100, 10, 10, 10, 10, 10,102,117,110, 99,116, - 105,111,110, 32, 80, 97, 99,107, 97,103,101, 32, 40,110, 97, - 109,101, 41, 10, 10,108,111, 99, 97,108, 32, 99,111,100,101, - 32, 61, 32,114,101, 97,100, 40, 34, 42, 97, 34, 41, 10, 99, - 111,100,101, 32, 61, 32, 34, 92,110, 34, 32, 46, 46, 32, 99, - 111,100,101, 10, 10,108,111, 99, 97,108, 32,110,115,117, 98, - 115,116, 10,114,101,112,101, 97,116, 10, 99,111,100,101, 44, - 110,115,117, 98,115,116, 32, 61, 32,103,115,117, 98, 40, 99, - 111,100,101, 44, 34, 92,110, 37,115, 42, 37, 36, 60, 40, 46, - 45, 41, 62, 37,115, 42, 92,110, 34, 44,102,117,110, 99,116, - 105,111,110, 32, 40,102,110, 41, 10,108,111, 99, 97,108, 32, - 102,112, 44,109,115,103, 32, 61, 32,111,112,101,110,102,105, - 108,101, 40,102,110, 44, 39,114, 39, 41, 10,105,102, 32,110, - 111,116, 32,102,112, 32,116,104,101,110, 10,101,114,114,111, - 114, 40, 39, 35, 39, 46, 46,109,115,103, 46, 46, 39, 58, 32, - 39, 46, 46,102,110, 41, 10,101,110,100, 10,108,111, 99, 97, - 108, 32,115, 32, 61, 32,114,101, 97,100, 40,102,112, 44, 39, - 42, 97, 39, 41, 10, 99,108,111,115,101,102,105,108,101, 40, - 102,112, 41, 10,114,101,116,117,114,110, 32, 34, 92,110, 34, - 32, 46, 46, 32,115, 10,101,110,100, 41, 10,117,110,116,105, - 108, 32,110,115,117, 98,115,116, 61, 61, 48, 10, 10, 10,108, - 111, 99, 97,108, 32,110,115,117, 98,115,116, 10,114,101,112, - 101, 97,116, 10, 99,111,100,101, 44,110,115,117, 98,115,116, - 32, 61, 10,103,115,117, 98, 40, 99,111,100,101, 44, 34, 92, - 110, 37,115, 42, 37, 36,123, 40, 46, 45, 41,125, 37,115, 42, - 92,110, 34, 44, 10,102,117,110, 99,116,105,111,110, 32, 40, - 102,110, 41, 10,108,111, 99, 97,108, 32,102,112, 44,109,115, - 103, 32, 61, 32,111,112,101,110,102,105,108,101, 40,102,110, - 44, 39,114, 39, 41, 10,105,102, 32,110,111,116, 32,102,112, - 32,116,104,101,110, 10,101,114,114,111,114, 40, 39, 35, 39, - 46, 46,109,115,103, 46, 46, 39, 58, 32, 39, 46, 46,102,110, - 41, 10,101,110,100, 10,108,111, 99, 97,108, 32,115, 32, 61, - 32,114,101, 97,100, 40,102,112, 44, 39, 42, 97, 39, 41, 10, - 99,108,111,115,101,102,105,108,101, 40,102,112, 41, 10, 10, - 108,111, 99, 97,108, 32, 84, 32, 61, 32,123, 99,111,100,101, - 61, 34, 92,110, 34,125, 10,115, 61, 32, 34, 92,110, 34, 32, - 46, 46, 32,115, 32, 46, 46, 32, 34, 92,110, 34, 10, 10,103, - 115,117, 98, 40,115, 44, 34, 92,110, 40, 46, 45, 41, 91, 84, - 116, 93, 91, 79,111, 93, 91, 76,108, 93, 91, 85,117, 93, 91, - 65, 97, 93, 95, 91, 69,101, 93, 91, 88,120, 93, 91, 80,112, - 93, 91, 79,111, 93, 91, 82,114, 93, 91, 84,116, 93, 91, 94, - 92,110, 93, 42, 92,110, 34, 44, 10,102,117,110, 99,116,105, - 111,110, 32, 40, 99, 41, 32, 37, 84, 46, 99,111,100,101, 32, - 61, 32, 37, 84, 46, 99,111,100,101, 32, 46, 46, 32, 99, 32, - 46, 46, 32, 34, 92,110, 34, 32,101,110,100, 10, 41, 10, 10, - 103,115,117, 98, 40,115, 44, 34, 92,110, 91, 94, 92,110, 93, - 42, 91, 84,116, 93, 91, 79,111, 93, 91, 76,108, 93, 91, 85, - 117, 93, 91, 65, 97, 93, 95, 91, 66, 98, 93, 91, 69,101, 93, - 91, 71,103, 93, 91, 73,105, 93, 91, 78,110, 93, 91, 94, 92, - 110, 93, 42, 34, 46, 46, 10, 34, 40, 46, 45, 41, 34, 32, 46, - 46, 10, 34, 92,110, 91, 94, 92,110, 93, 42, 91, 84,116, 93, - 91, 79,111, 93, 91, 76,108, 93, 91, 85,117, 93, 91, 65, 97, - 93, 95, 91, 69,101, 93, 91, 78,110, 93, 91, 68,100, 93, 91, - 94, 92,110, 93, 42, 92,110, 34, 44, 10,102,117,110, 99,116, - 105,111,110, 32, 40, 99, 41, 32, 37, 84, 46, 99,111,100,101, - 32, 61, 32, 37, 84, 46, 99,111,100,101, 32, 46, 46, 32, 99, - 32, 46, 46, 32, 34, 92,110, 34, 32,101,110,100, 10, 41, 10, - 114,101,116,117,114,110, 32, 84, 46, 99,111,100,101, 10,101, - 110,100, 41, 10,117,110,116,105,108, 32,110,115,117, 98,115, - 116, 61, 61, 48, 10, 10,108,111, 99, 97,108, 32,116, 32, 61, - 32, 95, 80, 97, 99,107, 97,103,101, 40, 95, 67,111,110,116, - 97,105,110,101,114,123,110, 97,109,101, 61,110, 97,109,101, - 44, 32, 99,111,100,101, 61, 99,111,100,101,125, 41, 10,112, - 117,115,104, 40,116, 41, 10,116, 58,112,114,101,112,114,111, - 99,101,115,115, 40, 41, 10,116, 58,112, 97,114,115,101, 40, - 116, 46, 99,111,100,101, 41, 10,112,111,112, 40, 41, 10,114, - 101,116,117,114,110, 32,116, 10,101,110,100, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 99, - 108, 97,115,115, 77,111,100,117,108,101, 32, 61, 32,123, 10, - 95, 98, 97,115,101, 32, 61, 32, 99,108, 97,115,115, 67,111, - 110,116, 97,105,110,101,114, 44, 10,116,121,112,101, 32, 61, - 32, 39,109,111,100,117,108,101, 39, 10,125, 10,115,101,116, - 116, 97,103, 40, 99,108, 97,115,115, 77,111,100,117,108,101, - 44,116,111,108,117, 97, 95,116, 97,103, 41, 10, 10, 10,102, - 117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 77,111, - 100,117,108,101, 58,114,101,103,105,115,116,101,114, 32, 40, - 41, 10,111,117,116,112,117,116, 40, 39, 32,116,111,108,117, - 97, 95,109,111,100,117,108,101, 40,116,111,108,117, 97, 95, - 83, 44, 34, 39, 46, 46,115,101,108,102, 46,110, 97,109,101, - 46, 46, 39, 34, 41, 59, 39, 41, 10,108,111, 99, 97,108, 32, - 105, 61, 49, 10,119,104,105,108,101, 32,115,101,108,102, 91, - 105, 93, 32,100,111, 10,115,101,108,102, 91,105, 93, 58,114, - 101,103,105,115,116,101,114, 40, 41, 10,105, 32, 61, 32,105, - 43, 49, 10,101,110,100, 10,101,110,100, 10, 10, 10,102,117, - 110, 99,116,105,111,110, 32, 99,108, 97,115,115, 77,111,100, - 117,108,101, 58,117,110,114,101,103,105,115,116,101,114, 32, - 40, 41, 10,111,117,116,112,117,116, 40, 39, 32,108,117, 97, - 95,112,117,115,104,110,105,108, 40,116,111,108,117, 97, 95, - 83, 41, 59, 32,108,117, 97, 95,115,101,116,103,108,111, 98, - 97,108, 40,116,111,108,117, 97, 95, 83, 44, 34, 39, 46, 46, - 115,101,108,102, 46,110, 97,109,101, 46, 46, 39, 34, 41, 59, - 39, 41, 10,101,110,100, 10, 10, 10,102,117,110, 99,116,105, - 111,110, 32, 99,108, 97,115,115, 77,111,100,117,108,101, 58, - 112,114,105,110,116, 32, 40,105,100,101,110,116, 44, 99,108, - 111,115,101, 41, 10,112,114,105,110,116, 40,105,100,101,110, - 116, 46, 46, 34, 77,111,100,117,108,101,123, 34, 41, 10,112, - 114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32,110, - 97,109,101, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46, - 110, 97,109,101, 46, 46, 34, 39, 59, 34, 41, 10,108,111, 99, - 97,108, 32,105, 61, 49, 10,119,104,105,108,101, 32,115,101, - 108,102, 91,105, 93, 32,100,111, 10,115,101,108,102, 91,105, - 93, 58,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, - 34, 32, 34, 44, 34, 44, 34, 41, 10,105, 32, 61, 32,105, 43, - 49, 10,101,110,100, 10,112,114,105,110,116, 40,105,100,101, - 110,116, 46, 46, 34,125, 34, 46, 46, 99,108,111,115,101, 41, - 10,101,110,100, 10, 10, 10,102,117,110, 99,116,105,111,110, - 32, 95, 77,111,100,117,108,101, 32, 40,116, 41, 10,116, 46, - 95, 98, 97,115,101, 32, 61, 32, 99,108, 97,115,115, 77,111, - 100,117,108,101, 10,115,101,116,116, 97,103, 40,116, 44,116, - 111,108,117, 97, 95,116, 97,103, 41, 10, 97,112,112,101,110, - 100, 40,116, 41, 10,114,101,116,117,114,110, 32,116, 10,101, - 110,100, 10, 10, 10, 10,102,117,110, 99,116,105,111,110, 32, - 77,111,100,117,108,101, 32, 40,110, 44, 98, 41, 10,108,111, - 99, 97,108, 32,116, 32, 61, 32, 95, 77,111,100,117,108,101, - 40, 95, 67,111,110,116, 97,105,110,101,114,123,110, 97,109, - 101, 61,110,125, 41, 10,112,117,115,104, 40,116, 41, 10,116, - 58,112, 97,114,115,101, 40,115,116,114,115,117, 98, 40, 98, - 44, 50, 44,115,116,114,108,101,110, 40, 98, 41, 45, 49, 41, - 41, 10,112,111,112, 40, 41, 10,114,101,116,117,114,110, 32, - 116, 10,101,110,100, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 99,108, 97,115,115, 68, - 101,102,105,110,101, 32, 61, 32,123, 10,110, 97,109,101, 32, - 61, 32, 39, 39, 44, 10, 95, 98, 97,115,101, 32, 61, 32, 99, - 108, 97,115,115, 70,101, 97,116,117,114,101, 44, 10,125, 10, - 115,101,116,116, 97,103, 40, 99,108, 97,115,115, 68,101,102, - 105,110,101, 44,116,111,108,117, 97, 95,116, 97,103, 41, 10, - 10, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115, - 115, 68,101,102,105,110,101, 58,114,101,103,105,115,116,101, - 114, 32, 40, 41, 10,108,111, 99, 97,108, 32,112, 32, 61, 32, - 115,101,108,102, 58,105,110,109,111,100,117,108,101, 40, 41, - 10,105,102, 32,112, 32,116,104,101,110, 10,111,117,116,112, - 117,116, 40, 39, 32,116,111,108,117, 97, 95, 99,111,110,115, - 116, 97,110,116, 40,116,111,108,117, 97, 95, 83, 44, 34, 39, - 46, 46,112, 46, 46, 39, 34, 44, 34, 39, 46, 46,115,101,108, - 102, 46,108,110, 97,109,101, 46, 46, 39, 34, 44, 39, 46, 46, - 115,101,108,102, 46,110, 97,109,101, 46, 46, 39, 41, 59, 39, - 41, 10,101,108,115,101, 10,111,117,116,112,117,116, 40, 39, - 32,116,111,108,117, 97, 95, 99,111,110,115,116, 97,110,116, - 40,116,111,108,117, 97, 95, 83, 44, 78, 85, 76, 76, 44, 34, - 39, 46, 46,115,101,108,102, 46,108,110, 97,109,101, 46, 46, - 39, 34, 44, 39, 46, 46,115,101,108,102, 46,110, 97,109,101, - 46, 46, 39, 41, 59, 39, 41, 10,101,110,100, 10,101,110,100, - 10, 10, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97, - 115,115, 68,101,102,105,110,101, 58,117,110,114,101,103,105, - 115,116,101,114, 32, 40, 41, 10,105,102, 32,110,111,116, 32, - 115,101,108,102, 58,105,110,109,111,100,117,108,101, 40, 41, - 32,116,104,101,110, 10,111,117,116,112,117,116, 40, 39, 32, - 108,117, 97, 95,112,117,115,104,110,105,108, 40,116,111,108, - 117, 97, 95, 83, 41, 59, 32,108,117, 97, 95,115,101,116,103, - 108,111, 98, 97,108, 40,116,111,108,117, 97, 95, 83, 44, 34, - 39, 46, 46,115,101,108,102, 46,108,110, 97,109,101, 46, 46, - 39, 34, 41, 59, 39, 41, 10,101,110,100, 10,101,110,100, 10, - 10, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115, - 115, 68,101,102,105,110,101, 58,112,114,105,110,116, 32, 40, - 105,100,101,110,116, 44, 99,108,111,115,101, 41, 10,112,114, - 105,110,116, 40,105,100,101,110,116, 46, 46, 34, 68,101,102, - 105,110,101,123, 34, 41, 10,112,114,105,110,116, 40,105,100, - 101,110,116, 46, 46, 34, 32,110, 97,109,101, 32, 61, 32, 39, - 34, 46, 46,115,101,108,102, 46,110, 97,109,101, 46, 46, 34, - 39, 44, 34, 41, 10,112,114,105,110,116, 40,105,100,101,110, - 116, 46, 46, 34, 32,108,110, 97,109,101, 32, 61, 32, 39, 34, - 46, 46,115,101,108,102, 46,108,110, 97,109,101, 46, 46, 34, - 39, 44, 34, 41, 10,112,114,105,110,116, 40,105,100,101,110, - 116, 46, 46, 34,125, 34, 46, 46, 99,108,111,115,101, 41, 10, - 101,110,100, 10, 10, 10, 10,102,117,110, 99,116,105,111,110, - 32, 95, 68,101,102,105,110,101, 32, 40,116, 41, 10,116, 46, - 95, 98, 97,115,101, 32, 61, 32, 99,108, 97,115,115, 68,101, - 102,105,110,101, 10,115,101,116,116, 97,103, 40,116, 44,116, - 111,108,117, 97, 95,116, 97,103, 41, 10, 10,105,102, 32,116, - 46,110, 97,109,101, 32, 61, 61, 32, 39, 39, 32,116,104,101, - 110, 10,101,114,114,111,114, 40, 34, 35,105,110,118, 97,108, - 105,100, 32,100,101,102,105,110,101, 34, 41, 10,101,110,100, - 10, 10, 97,112,112,101,110,100, 40,116, 41, 10,114,101,116, - 117,114,110, 32,116, 10,101,110,100, 10, 10, 10, 10,102,117, - 110, 99,116,105,111,110, 32, 68,101,102,105,110,101, 32, 40, - 110, 41, 10,108,111, 99, 97,108, 32,116, 32, 61, 32,115,112, - 108,105,116, 40,110, 44, 39, 64, 39, 41, 10,114,101,116,117, - 114,110, 32, 95, 68,101,102,105,110,101, 32,123, 10,110, 97, - 109,101, 32, 61, 32,116, 91, 49, 93, 44, 10,108,110, 97,109, - 101, 32, 61, 32,116, 91, 50, 93, 32,111,114, 32,116, 91, 49, - 93, 10,125, 10,101,110,100, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 99,108, 97,115,115, 69, - 110,117,109,101,114, 97,116,101, 32, 61, 32,123, 10, 95, 98, - 97,115,101, 32, 61, 32, 99,108, 97,115,115, 70,101, 97,116, - 117,114,101, 44, 10,125, 10,115,101,116,116, 97,103, 40, 99, - 108, 97,115,115, 69,110,117,109,101,114, 97,116,101, 44,116, - 111,108,117, 97, 95,116, 97,103, 41, 10, 10, 10,102,117,110, - 99,116,105,111,110, 32, 99,108, 97,115,115, 69,110,117,109, - 101,114, 97,116,101, 58,114,101,103,105,115,116,101,114, 32, - 40, 41, 10,108,111, 99, 97,108, 32,112, 32, 61, 32,115,101, - 108,102, 58,105,110, 99,108, 97,115,115, 40, 41, 32,111,114, - 32,115,101,108,102, 58,105,110,109,111,100,117,108,101, 40, - 41, 10,108,111, 99, 97,108, 32,105, 61, 49, 10,119,104,105, - 108,101, 32,115,101,108,102, 91,105, 93, 32,100,111, 10,105, - 102, 32,112, 32,116,104,101,110, 10,105,102, 32,115,101,108, - 102, 58,105,110, 99,108, 97,115,115, 40, 41, 32,116,104,101, - 110, 10,111,117,116,112,117,116, 40, 39, 32,116,111,108,117, - 97, 95, 99,111,110,115,116, 97,110,116, 40,116,111,108,117, - 97, 95, 83, 44, 34, 39, 46, 46,112, 46, 46, 39, 34, 44, 34, - 39, 46, 46,115,101,108,102, 46,108,110, 97,109,101,115, 91, - 105, 93, 46, 46, 39, 34, 44, 39, 46, 46,112, 46, 46, 39, 58, - 58, 39, 46, 46,115,101,108,102, 91,105, 93, 46, 46, 39, 41, - 59, 39, 41, 10,101,108,115,101, 10,111,117,116,112,117,116, - 40, 39, 32,116,111,108,117, 97, 95, 99,111,110,115,116, 97, - 110,116, 40,116,111,108,117, 97, 95, 83, 44, 34, 39, 46, 46, - 112, 46, 46, 39, 34, 44, 34, 39, 46, 46,115,101,108,102, 46, - 108,110, 97,109,101,115, 91,105, 93, 46, 46, 39, 34, 44, 39, - 46, 46,115,101,108,102, 91,105, 93, 46, 46, 39, 41, 59, 39, - 41, 10,101,110,100, 10,101,108,115,101, 10,111,117,116,112, - 117,116, 40, 39, 32,116,111,108,117, 97, 95, 99,111,110,115, - 116, 97,110,116, 40,116,111,108,117, 97, 95, 83, 44, 78, 85, - 76, 76, 44, 34, 39, 46, 46,115,101,108,102, 46,108,110, 97, - 109,101,115, 91,105, 93, 46, 46, 39, 34, 44, 39, 46, 46,115, - 101,108,102, 91,105, 93, 46, 46, 39, 41, 59, 39, 41, 10,101, - 110,100, 10,105, 32, 61, 32,105, 43, 49, 10,101,110,100, 10, - 101,110,100, 10, 10,102,117,110, 99,116,105,111,110, 32, 99, - 108, 97,115,115, 69,110,117,109,101,114, 97,116,101, 58,117, - 110,114,101,103,105,115,116,101,114, 32, 40, 41, 10,105,102, - 32,115,101,108,102, 58,105,110, 99,108, 97,115,115, 40, 41, - 61, 61,110,105,108, 32, 97,110,100, 32,115,101,108,102, 58, - 105,110,109,111,100,117,108,101, 40, 41, 61, 61,110,105,108, - 32,116,104,101,110, 10,108,111, 99, 97,108, 32,105, 61, 49, - 10,119,104,105,108,101, 32,115,101,108,102, 91,105, 93, 32, - 100,111, 10,111,117,116,112,117,116, 40, 39, 32,108,117, 97, - 95,112,117,115,104,110,105,108, 40,116,111,108,117, 97, 95, - 83, 41, 59, 32,108,117, 97, 95,115,101,116,103,108,111, 98, - 97,108, 40,116,111,108,117, 97, 95, 83, 44, 34, 39, 46, 46, - 115,101,108,102, 46,108,110, 97,109,101,115, 91,105, 93, 46, - 46, 39, 34, 41, 59, 39, 41, 10,105, 32, 61, 32,105, 43, 49, - 10,101,110,100, 10,101,110,100, 10,101,110,100, 10, 10, 10, - 102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 69, - 110,117,109,101,114, 97,116,101, 58,112,114,105,110,116, 32, - 40,105,100,101,110,116, 44, 99,108,111,115,101, 41, 10,112, - 114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 69,110, - 117,109,101,114, 97,116,101,123, 34, 41, 10,108,111, 99, 97, - 108, 32,105, 61, 49, 10,119,104,105,108,101, 32,115,101,108, - 102, 91,105, 93, 32,100,111, 10,112,114,105,110,116, 40,105, - 100,101,110,116, 46, 46, 34, 32, 39, 34, 46, 46,115,101,108, - 102, 91,105, 93, 46, 46, 34, 39, 40, 34, 46, 46,115,101,108, - 102, 46,108,110, 97,109,101,115, 91,105, 93, 46, 46, 34, 41, - 44, 34, 41, 10,105, 32, 61, 32,105, 43, 49, 10,101,110,100, - 10,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, - 125, 34, 46, 46, 99,108,111,115,101, 41, 10,101,110,100, 10, - 10, 10,102,117,110, 99,116,105,111,110, 32, 95, 69,110,117, - 109,101,114, 97,116,101, 32, 40,116, 41, 10,116, 46, 95, 98, - 97,115,101, 32, 61, 32, 99,108, 97,115,115, 69,110,117,109, - 101,114, 97,116,101, 10,115,101,116,116, 97,103, 40,116, 44, - 116,111,108,117, 97, 95,116, 97,103, 41, 10, 97,112,112,101, - 110,100, 40,116, 41, 10,114,101,116,117,114,110, 32,116, 10, - 101,110,100, 10, 10, 10, 10,102,117,110, 99,116,105,111,110, - 32, 69,110,117,109,101,114, 97,116,101, 32, 40, 98, 41, 10, - 108,111, 99, 97,108, 32,116, 32, 61, 32,115,112,108,105,116, - 40,115,116,114,115,117, 98, 40, 98, 44, 50, 44, 45, 50, 41, - 44, 39, 44, 39, 41, 10,108,111, 99, 97,108, 32,105, 32, 61, - 32, 49, 10,108,111, 99, 97,108, 32,101, 32, 61, 32,123,110, - 61, 48,125, 10,119,104,105,108,101, 32,116, 91,105, 93, 32, - 100,111, 10,108,111, 99, 97,108, 32,116,116, 32, 61, 32,115, - 112,108,105,116, 40,116, 91,105, 93, 44, 39, 61, 39, 41, 10, - 101, 46,110, 32, 61, 32,101, 46,110, 32, 43, 32, 49, 10,101, - 91,101, 46,110, 93, 32, 61, 32,116,116, 91, 49, 93, 10,105, - 32, 61, 32,105, 43, 49, 10,101,110,100, 10, 10,105, 32, 61, - 32, 49, 10,101, 46,108,110, 97,109,101,115, 32, 61, 32,123, - 125, 10,119,104,105,108,101, 32,101, 91,105, 93, 32,100,111, - 10,108,111, 99, 97,108, 32,116, 32, 61, 32,115,112,108,105, - 116, 40,101, 91,105, 93, 44, 39, 64, 39, 41, 10,101, 91,105, - 93, 32, 61, 32,116, 91, 49, 93, 10,101, 46,108,110, 97,109, - 101,115, 91,105, 93, 32, 61, 32,116, 91, 50, 93, 32,111,114, - 32,116, 91, 49, 93, 10,105, 32, 61, 32,105, 43, 49, 10,101, - 110,100, 10,114,101,116,117,114,110, 32, 95, 69,110,117,109, - 101,114, 97,116,101, 40,101, 41, 10,101,110,100, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 99,108, 97,115,115, 68,101, 99, - 108, 97,114, 97,116,105,111,110, 32, 61, 32,123, 10, 95, 98, - 97,115,101, 32, 61, 32, 99,108, 97,115,115, 70,101, 97,116, - 117,114,101, 44, 10,109,111,100, 32, 61, 32, 39, 39, 44, 10, - 116,121,112,101, 32, 61, 32, 39, 39, 44, 10,112,116,114, 32, - 61, 32, 39, 39, 44, 10,110, 97,109,101, 32, 61, 32, 39, 39, - 44, 10,100,105,109, 32, 61, 32, 39, 39, 44, 10,114,101,116, - 32, 61, 32, 39, 39, 44, 10,100,101,102, 32, 61, 32, 39, 39, - 10,125, 10,115,101,116,116, 97,103, 40, 99,108, 97,115,115, - 68,101, 99,108, 97,114, 97,116,105,111,110, 44,116,111,108, - 117, 97, 95,116, 97,103, 41, 10, 10, 10,102,117,110, 99,116, - 105,111,110, 32, 99,114,101, 97,116,101, 95,118, 97,114,110, - 97,109,101, 32, 40, 41, 10,105,102, 32,110,111,116, 32, 95, - 118, 97,114,110,117,109, 98,101,114, 32,116,104,101,110, 32, - 95,118, 97,114,110,117,109, 98,101,114, 32, 61, 32, 48, 32, - 101,110,100, 10, 95,118, 97,114,110,117,109, 98,101,114, 32, - 61, 32, 95,118, 97,114,110,117,109, 98,101,114, 32, 43, 32, - 49, 10,114,101,116,117,114,110, 32, 34,116,111,108,117, 97, - 95,118, 97,114, 95, 34, 46, 46, 95,118, 97,114,110,117,109, - 98,101,114, 10,101,110,100, 10, 10, 10, 10,102,117,110, 99, - 116,105,111,110, 32, 99,108, 97,115,115, 68,101, 99,108, 97, - 114, 97,116,105,111,110, 58, 99,104,101, 99,107,110, 97,109, - 101, 32, 40, 41, 10, 10,105,102, 32,115,116,114,115,117, 98, - 40,115,101,108,102, 46,110, 97,109,101, 44, 49, 44, 49, 41, - 32, 61, 61, 32, 39, 91, 39, 32, 97,110,100, 32,110,111,116, - 32,105,115,116,121,112,101, 40,115,101,108,102, 46,116,121, - 112,101, 41, 32,116,104,101,110, 10,115,101,108,102, 46,110, - 97,109,101, 32, 61, 32,115,101,108,102, 46,116,121,112,101, - 46, 46,115,101,108,102, 46,110, 97,109,101, 10,108,111, 99, - 97,108, 32,109, 32, 61, 32,115,112,108,105,116, 40,115,101, - 108,102, 46,109,111,100, 44, 39, 37,115, 37,115, 42, 39, 41, - 10,115,101,108,102, 46,116,121,112,101, 32, 61, 32,109, 91, - 109, 46,110, 93, 10,115,101,108,102, 46,109,111,100, 32, 61, - 32, 99,111,110, 99, 97,116, 40,109, 44, 49, 44,109, 46,110, - 45, 49, 41, 10,101,110,100, 10, 10,108,111, 99, 97,108, 32, - 116, 32, 61, 32,115,112,108,105,116, 40,115,101,108,102, 46, - 110, 97,109,101, 44, 39, 61, 39, 41, 10,105,102, 32,116, 46, - 110, 61, 61, 50, 32,116,104,101,110, 10,115,101,108,102, 46, - 110, 97,109,101, 32, 61, 32,116, 91, 49, 93, 10,115,101,108, - 102, 46,100,101,102, 32, 61, 32,116, 91,116, 46,110, 93, 10, - 101,110,100, 10, 10,108,111, 99, 97,108, 32, 98, 44,101, 44, - 100, 32, 61, 32,115,116,114,102,105,110,100, 40,115,101,108, - 102, 46,110, 97,109,101, 44, 34, 37, 91, 40, 46, 45, 41, 37, - 93, 34, 41, 10,105,102, 32, 98, 32,116,104,101,110, 10,115, - 101,108,102, 46,110, 97,109,101, 32, 61, 32,115,116,114,115, - 117, 98, 40,115,101,108,102, 46,110, 97,109,101, 44, 49, 44, - 98, 45, 49, 41, 10,115,101,108,102, 46,100,105,109, 32, 61, - 32,100, 10,101,110,100, 10, 10, 10,105,102, 32,115,101,108, - 102, 46,116,121,112,101, 32,126, 61, 32, 39, 39, 32, 97,110, - 100, 32,115,101,108,102, 46,116,121,112,101, 32,126, 61, 32, - 39,118,111,105,100, 39, 32, 97,110,100, 32,115,101,108,102, - 46,110, 97,109,101, 32, 61, 61, 32, 39, 39, 32,116,104,101, - 110, 10,115,101,108,102, 46,110, 97,109,101, 32, 61, 32, 99, - 114,101, 97,116,101, 95,118, 97,114,110, 97,109,101, 40, 41, - 10,101,108,115,101,105,102, 32,115,101,108,102, 46,107,105, - 110,100, 61, 61, 39,118, 97,114, 39, 32,116,104,101,110, 10, - 105,102, 32,115,101,108,102, 46,116,121,112,101, 61, 61, 39, - 39, 32, 97,110,100, 32,115,101,108,102, 46,110, 97,109,101, - 126, 61, 39, 39, 32,116,104,101,110, 10,115,101,108,102, 46, - 116,121,112,101, 32, 61, 32,115,101,108,102, 46,116,121,112, - 101, 46, 46,115,101,108,102, 46,110, 97,109,101, 10,115,101, - 108,102, 46,110, 97,109,101, 32, 61, 32, 99,114,101, 97,116, - 101, 95,118, 97,114,110, 97,109,101, 40, 41, 10,101,108,115, - 101,105,102, 32,105,115,116,121,112,101, 40,115,101,108,102, - 46,110, 97,109,101, 41, 32,116,104,101,110, 10,105,102, 32, - 115,101,108,102, 46,116,121,112,101, 61, 61, 39, 39, 32,116, - 104,101,110, 32,115,101,108,102, 46,116,121,112,101, 32, 61, - 32,115,101,108,102, 46,110, 97,109,101, 10,101,108,115,101, - 32,115,101,108,102, 46,116,121,112,101, 32, 61, 32,115,101, - 108,102, 46,116,121,112,101, 46, 46, 39, 32, 39, 46, 46,115, - 101,108,102, 46,110, 97,109,101, 32,101,110,100, 10,115,101, - 108,102, 46,110, 97,109,101, 32, 61, 32, 99,114,101, 97,116, - 101, 95,118, 97,114,110, 97,109,101, 40, 41, 10,101,110,100, - 10,101,110,100, 10, 10,101,110,100, 10, 10, 10, 10,102,117, - 110, 99,116,105,111,110, 32, 99,108, 97,115,115, 68,101, 99, - 108, 97,114, 97,116,105,111,110, 58, 99,104,101, 99,107,116, - 121,112,101, 32, 40, 41, 10, 10, 10,105,102, 32,105,115, 98, - 97,115,105, 99, 40,115,101,108,102, 46,116,121,112,101, 41, - 32, 97,110,100, 32,115,101,108,102, 46,112,116,114,126, 61, - 39, 39, 32,116,104,101,110, 10,115,101,108,102, 46,114,101, - 116, 32, 61, 32,115,101,108,102, 46,112,116,114, 10,115,101, - 108,102, 46,112,116,114, 32, 61, 32,110,105,108, 10,101,110, - 100, 10, 10, 10,105,102, 32,115,101,108,102, 46,100,105,109, - 126, 61, 39, 39, 32, 97,110,100, 32,115,101,108,102, 46,114, - 101,116,126, 61, 39, 39, 32,116,104,101,110, 10,101,114,114, - 111,114, 40, 39, 35,105,110,118, 97,108,105,100, 32,112, 97, - 114, 97,109,101,116,101,114, 58, 32, 99, 97,110,110,111,116, - 32,114,101,116,117,114,110, 32, 97,110, 32, 97,114,114, 97, - 121, 32,111,102, 32,118, 97,108,117,101,115, 39, 41, 10,101, - 110,100, 10, 10, 10,105,102, 32,115,101,108,102, 46,116,121, - 112,101,126, 61, 39, 39, 32,116,104,101,110, 10,114,101,103, - 116,121,112,101, 40,115,101,108,102, 46,116,121,112,101, 41, - 10,101,110,100, 10, 10, 10,105,102, 32,115,101,108,102, 46, - 116,121,112,101, 32, 61, 61, 32, 39, 95,117,115,101,114,100, - 97,116, 97, 39, 32,116,104,101,110, 32,115,101,108,102, 46, - 116,121,112,101, 32, 61, 32, 39,118,111,105,100, 42, 39, 10, - 101,108,115,101,105,102, 32,115,101,108,102, 46,116,121,112, - 101, 32, 61, 61, 32, 39, 95, 99,115,116,114,105,110,103, 39, - 32,116,104,101,110, 32,115,101,108,102, 46,116,121,112,101, - 32, 61, 32, 39, 99,104, 97,114, 42, 39, 10,101,110,100, 10, - 10, 10, 10, 10, 10, 10, 10, 10,101,110,100, 10, 10, 10,102, - 117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 68,101, - 99,108, 97,114, 97,116,105,111,110, 58,112,114,105,110,116, - 32, 40,105,100,101,110,116, 44, 99,108,111,115,101, 41, 10, - 112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 68, - 101, 99,108, 97,114, 97,116,105,111,110,123, 34, 41, 10,112, - 114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32,109, - 111,100, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46,109, - 111,100, 46, 46, 34, 39, 44, 34, 41, 10,112,114,105,110,116, - 40,105,100,101,110,116, 46, 46, 34, 32,116,121,112,101, 32, - 61, 32, 39, 34, 46, 46,115,101,108,102, 46,116,121,112,101, - 46, 46, 34, 39, 44, 34, 41, 10,112,114,105,110,116, 40,105, - 100,101,110,116, 46, 46, 34, 32,112,116,114, 32, 61, 32, 39, - 34, 46, 46,115,101,108,102, 46,112,116,114, 46, 46, 34, 39, - 44, 34, 41, 10,112,114,105,110,116, 40,105,100,101,110,116, - 46, 46, 34, 32,110, 97,109,101, 32, 61, 32, 39, 34, 46, 46, - 115,101,108,102, 46,110, 97,109,101, 46, 46, 34, 39, 44, 34, - 41, 10,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, - 34, 32,100,105,109, 32, 61, 32, 39, 34, 46, 46,115,101,108, - 102, 46,100,105,109, 46, 46, 34, 39, 44, 34, 41, 10,112,114, - 105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32,100,101, - 102, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46,100,101, - 102, 46, 46, 34, 39, 44, 34, 41, 10,112,114,105,110,116, 40, - 105,100,101,110,116, 46, 46, 34, 32,114,101,116, 32, 61, 32, - 39, 34, 46, 46,115,101,108,102, 46,114,101,116, 46, 46, 34, - 39, 44, 34, 41, 10,112,114,105,110,116, 40,105,100,101,110, - 116, 46, 46, 34,125, 34, 46, 46, 99,108,111,115,101, 41, 10, - 101,110,100, 10, 10, 10,102,117,110, 99,116,105,111,110, 32, - 99,108, 97,115,115, 68,101, 99,108, 97,114, 97,116,105,111, - 110, 58,100,101, 99,108,116, 97,103, 32, 40, 41, 10,115,101, - 108,102, 46,105,116,121,112,101, 44, 32,115,101,108,102, 46, - 116, 97,103, 32, 61, 32,116, 97,103,118, 97,114, 40,115,101, - 108,102, 46,116,121,112,101, 44,115,116,114,102,105,110,100, - 40,115,101,108,102, 46,109,111,100, 44, 39, 99,111,110,115, - 116, 39, 41, 41, 10,101,110,100, 10, 10, 10, 10,102,117,110, - 99,116,105,111,110, 32, 99,108, 97,115,115, 68,101, 99,108, - 97,114, 97,116,105,111,110, 58,111,117,116, 99,104,101, 99, - 107,116,121,112,101, 32, 40,110, 97,114,103, 41, 10,108,111, - 99, 97,108, 32,116, 97,103, 44, 32,100,101,102, 10,105,102, - 32,115,101,108,102, 46,100,105,109, 32,126, 61, 32, 39, 39, - 32,116,104,101,110, 10,116, 97,103, 32, 61, 32, 39, 76, 85, - 65, 95, 84, 84, 65, 66, 76, 69, 39, 10,100,101,102, 32, 61, - 32, 48, 10,101,108,115,101, 10,116, 97,103, 32, 61, 32,115, - 101,108,102, 46,116, 97,103, 10,100,101,102, 32, 61, 32,115, - 101,108,102, 46,100,101,102,126, 61, 39, 39, 32,111,114, 32, - 48, 10,101,110,100, 10,114,101,116,117,114,110, 32, 39,116, - 111,108,117, 97, 95,105,115,116,121,112,101, 40,116,111,108, - 117, 97, 95, 83, 44, 39, 46, 46,110, 97,114,103, 46, 46, 39, - 44, 39, 46, 46,116, 97,103, 46, 46, 39, 44, 39, 46, 46,100, - 101,102, 46, 46, 39, 41, 39, 10,101,110,100, 10, 10, 10,102, - 117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 68,101, - 99,108, 97,114, 97,116,105,111,110, 58,100,101, 99,108, 97, - 114,101, 32, 40,110, 97,114,103, 41, 10,108,111, 99, 97,108, - 32,112,116,114, 32, 61, 32, 39, 39, 10,105,102, 32,115,101, - 108,102, 46,112,116,114,126, 61, 39, 39, 32,116,104,101,110, - 32,112,116,114, 32, 61, 32, 39, 42, 39, 32,101,110,100, 10, - 111,117,116,112,117,116, 40, 34, 32, 34, 44,115,101,108,102, - 46,109,111,100, 44,115,101,108,102, 46,116,121,112,101, 44, - 112,116,114, 41, 10,105,102, 32,115,101,108,102, 46,100,105, - 109, 32,126, 61, 32, 39, 39, 32, 97,110,100, 32,116,111,110, - 117,109, 98,101,114, 40,115,101,108,102, 46,100,105,109, 41, - 61, 61,110,105,108, 32,116,104,101,110, 10,111,117,116,112, - 117,116, 40, 39, 42, 39, 41, 10,101,110,100, 10,111,117,116, - 112,117,116, 40,115,101,108,102, 46,110, 97,109,101, 41, 10, - 105,102, 32,115,101,108,102, 46,100,105,109, 32,126, 61, 32, - 39, 39, 32,116,104,101,110, 10,105,102, 32,116,111,110,117, - 109, 98,101,114, 40,115,101,108,102, 46,100,105,109, 41,126, - 61,110,105,108, 32,116,104,101,110, 10,111,117,116,112,117, - 116, 40, 39, 91, 39, 44,115,101,108,102, 46,100,105,109, 44, - 39, 93, 59, 39, 41, 10,101,108,115,101, 10,111,117,116,112, - 117,116, 40, 39, 32, 61, 32, 40, 39, 44,115,101,108,102, 46, - 109,111,100, 44,115,101,108,102, 46,116,121,112,101, 44,112, - 116,114, 44, 39, 42, 41, 39, 44, 10, 39,109, 97,108,108,111, - 99, 40, 39, 44,115,101,108,102, 46,100,105,109, 44, 39, 42, - 115,105,122,101,111,102, 40, 39, 44,115,101,108,102, 46,116, - 121,112,101, 44,112,116,114, 44, 39, 41, 41, 59, 39, 41, 10, - 101,110,100, 10,101,108,115,101, 10,108,111, 99, 97,108, 32, - 116, 32, 61, 32,105,115, 98, 97,115,105, 99, 40,115,101,108, - 102, 46,116,121,112,101, 41, 10,111,117,116,112,117,116, 40, - 39, 32, 61, 32, 39, 41, 10,105,102, 32,110,111,116, 32,116, - 32, 97,110,100, 32,112,116,114, 61, 61, 39, 39, 32,116,104, - 101,110, 32,111,117,116,112,117,116, 40, 39, 42, 39, 41, 32, - 101,110,100, 10,111,117,116,112,117,116, 40, 39, 40, 40, 39, - 44,115,101,108,102, 46,109,111,100, 44,115,101,108,102, 46, - 116,121,112,101, 41, 10,105,102, 32,110,111,116, 32,116, 32, - 116,104,101,110, 10,111,117,116,112,117,116, 40, 39, 42, 39, - 41, 10,101,110,100, 10,111,117,116,112,117,116, 40, 39, 41, - 32, 39, 41, 10,108,111, 99, 97,108, 32,100,101,102, 32, 61, - 32, 48, 10,105,102, 32,115,101,108,102, 46,100,101,102, 32, - 126, 61, 32, 39, 39, 32,116,104,101,110, 32,100,101,102, 32, - 61, 32,115,101,108,102, 46,100,101,102, 32,101,110,100, 10, - 105,102, 32,116, 32,116,104,101,110, 10,111,117,116,112,117, - 116, 40, 39,116,111,108,117, 97, 95,103,101,116, 39, 46, 46, - 116, 44, 39, 40,116,111,108,117, 97, 95, 83, 44, 39, 44,110, - 97,114,103, 44, 39, 44, 39, 44,100,101,102, 44, 39, 41, 41, - 59, 39, 41, 10,101,108,115,101, 10,111,117,116,112,117,116, - 40, 39,116,111,108,117, 97, 95,103,101,116,117,115,101,114, - 116,121,112,101, 40,116,111,108,117, 97, 95, 83, 44, 39, 44, - 110, 97,114,103, 44, 39, 44, 39, 44,100,101,102, 44, 39, 41, - 41, 59, 39, 41, 10,101,110,100, 10,101,110,100, 10,101,110, - 100, 10, 10, 10,102,117,110, 99,116,105,111,110, 32, 99,108, - 97,115,115, 68,101, 99,108, 97,114, 97,116,105,111,110, 58, - 103,101,116, 97,114,114, 97,121, 32, 40,110, 97,114,103, 41, - 10,105,102, 32,115,101,108,102, 46,100,105,109, 32,126, 61, - 32, 39, 39, 32,116,104,101,110, 10,111,117,116,112,117,116, - 40, 39, 32,123, 39, 41, 10,108,111, 99, 97,108, 32,100,101, - 102, 32, 61, 32,115,101,108,102, 46,100,101,102,126, 61, 39, - 39, 32,111,114, 32, 48, 10,111,117,116,112,117,116, 40, 39, - 32,105,102, 32, 40, 33,116,111,108,117, 97, 95, 97,114,114, - 97,121,105,115,116,121,112,101, 40,116,111,108,117, 97, 95, - 83, 44, 39, 44,110, 97,114,103, 44, 39, 44, 39, 44,115,101, - 108,102, 46,116, 97,103, 44, 39, 44, 39, 44,115,101,108,102, - 46,100,105,109, 44, 39, 44, 39, 44,100,101,102, 44, 39, 41, - 41, 39, 41, 10,111,117,116,112,117,116, 40, 39, 32,103,111, - 116,111, 32,116,111,108,117, 97, 95,108,101,114,114,111,114, - 59, 39, 41, 10,111,117,116,112,117,116, 40, 39, 32,101,108, - 115,101, 92,110, 39, 41, 10,111,117,116,112,117,116, 40, 39, - 32,123, 39, 41, 10,111,117,116,112,117,116, 40, 39, 32,105, - 110,116, 32,105, 59, 39, 41, 10,111,117,116,112,117,116, 40, - 39, 32,102,111,114, 40,105, 61, 48, 59, 32,105, 60, 39, 46, - 46,115,101,108,102, 46,100,105,109, 46, 46, 39, 59,105, 43, - 43, 41, 39, 41, 10,108,111, 99, 97,108, 32,116, 32, 61, 32, - 105,115, 98, 97,115,105, 99, 40,115,101,108,102, 46,116,121, - 112,101, 41, 10,108,111, 99, 97,108, 32,112,116,114, 32, 61, - 32, 39, 39, 10,105,102, 32,115,101,108,102, 46,112,116,114, - 126, 61, 39, 39, 32,116,104,101,110, 32,112,116,114, 32, 61, - 32, 39, 42, 39, 32,101,110,100, 10,111,117,116,112,117,116, - 40, 39, 32, 39, 44,115,101,108,102, 46,110, 97,109,101, 46, - 46, 39, 91,105, 93, 32, 61, 32, 39, 41, 10,105,102, 32,110, - 111,116, 32,116, 32, 97,110,100, 32,112,116,114, 61, 61, 39, - 39, 32,116,104,101,110, 32,111,117,116,112,117,116, 40, 39, - 42, 39, 41, 32,101,110,100, 10,111,117,116,112,117,116, 40, - 39, 40, 40, 39, 44,115,101,108,102, 46,109,111,100, 44,115, - 101,108,102, 46,116,121,112,101, 41, 10,105,102, 32,110,111, - 116, 32,116, 32,116,104,101,110, 10,111,117,116,112,117,116, - 40, 39, 42, 39, 41, 10,101,110,100, 10,111,117,116,112,117, - 116, 40, 39, 41, 32, 39, 41, 10,108,111, 99, 97,108, 32,100, - 101,102, 32, 61, 32, 48, 10,105,102, 32,115,101,108,102, 46, - 100,101,102, 32,126, 61, 32, 39, 39, 32,116,104,101,110, 32, - 100,101,102, 32, 61, 32,115,101,108,102, 46,100,101,102, 32, - 101,110,100, 10,105,102, 32,116, 32,116,104,101,110, 10,111, - 117,116,112,117,116, 40, 39,116,111,108,117, 97, 95,103,101, - 116,102,105,101,108,100, 39, 46, 46,116, 46, 46, 39, 40,116, - 111,108,117, 97, 95, 83, 44, 39, 44,110, 97,114,103, 44, 39, - 44,105, 43, 49, 44, 39, 44,100,101,102, 44, 39, 41, 41, 59, - 39, 41, 10,101,108,115,101, 10,111,117,116,112,117,116, 40, - 39,116,111,108,117, 97, 95,103,101,116,102,105,101,108,100, - 117,115,101,114,116,121,112,101, 40,116,111,108,117, 97, 95, - 83, 44, 39, 44,110, 97,114,103, 44, 39, 44,105, 43, 49, 44, - 39, 44,100,101,102, 44, 39, 41, 41, 59, 39, 41, 10,101,110, - 100, 10,111,117,116,112,117,116, 40, 39, 32,125, 39, 41, 10, - 111,117,116,112,117,116, 40, 39, 32,125, 39, 41, 10,101,110, - 100, 10,101,110,100, 10, 10, 10,102,117,110, 99,116,105,111, - 110, 32, 99,108, 97,115,115, 68,101, 99,108, 97,114, 97,116, - 105,111,110, 58,115,101,116, 97,114,114, 97,121, 32, 40,110, - 97,114,103, 41, 10,105,102, 32,115,101,108,102, 46,100,105, - 109, 32,126, 61, 32, 39, 39, 32,116,104,101,110, 10,111,117, - 116,112,117,116, 40, 39, 32,123, 39, 41, 10,111,117,116,112, - 117,116, 40, 39, 32,105,110,116, 32,105, 59, 39, 41, 10,111, - 117,116,112,117,116, 40, 39, 32,102,111,114, 40,105, 61, 48, - 59, 32,105, 60, 39, 46, 46,115,101,108,102, 46,100,105,109, - 46, 46, 39, 59,105, 43, 43, 41, 39, 41, 10,108,111, 99, 97, - 108, 32,116, 44, 99,116, 32, 61, 32,105,115, 98, 97,115,105, - 99, 40,115,101,108,102, 46,116,121,112,101, 41, 10,105,102, - 32,116, 32,116,104,101,110, 10,111,117,116,112,117,116, 40, - 39, 32,116,111,108,117, 97, 95,112,117,115,104,102,105,101, - 108,100, 39, 46, 46,116, 46, 46, 39, 40,116,111,108,117, 97, - 95, 83, 44, 39, 44,110, 97,114,103, 44, 39, 44,105, 43, 49, - 44, 40, 39, 44, 99,116, 44, 39, 41, 39, 44,115,101,108,102, - 46,110, 97,109,101, 44, 39, 91,105, 93, 41, 59, 39, 41, 10, - 101,108,115,101, 10,105,102, 32,115,101,108,102, 46,112,116, - 114, 32, 61, 61, 32, 39, 39, 32,116,104,101,110, 10,111,117, - 116,112,117,116, 40, 39, 32,123, 39, 41, 10,111,117,116,112, - 117,116, 40, 39, 35,105,102,100,101,102, 32, 95, 95, 99,112, - 108,117,115,112,108,117,115, 92,110, 39, 41, 10,111,117,116, - 112,117,116, 40, 39, 32,118,111,105,100, 42, 32,116,111,108, - 117, 97, 73, 95, 99,108,111,110,101, 32, 61, 32,110,101,119, - 39, 44,115,101,108,102, 46,116,121,112,101, 44, 39, 40, 39, - 44,115,101,108,102, 46,110, 97,109,101, 44, 39, 91,105, 93, - 41, 59, 39, 41, 10,111,117,116,112,117,116, 40, 39, 35,101, - 108,115,101, 92,110, 39, 41, 10,111,117,116,112,117,116, 40, - 39, 32,118,111,105,100, 42, 32,116,111,108,117, 97, 73, 95, - 99,108,111,110,101, 32, 61, 32,116,111,108,117, 97, 95, 99, - 111,112,121, 40,116,111,108,117, 97, 95, 83, 44, 40,118,111, - 105,100, 42, 41, 38, 39, 44,115,101,108,102, 46,110, 97,109, - 101, 44, 39, 91,105, 93, 44,115,105,122,101,111,102, 40, 39, - 44,115,101,108,102, 46,116,121,112,101, 44, 39, 41, 41, 59, - 39, 41, 10,111,117,116,112,117,116, 40, 39, 35,101,110,100, - 105,102, 92,110, 39, 41, 10,111,117,116,112,117,116, 40, 39, - 32,116,111,108,117, 97, 95,112,117,115,104,102,105,101,108, - 100,117,115,101,114,116,121,112,101, 40,116,111,108,117, 97, - 95, 83, 44, 39, 44,110, 97,114,103, 44, 39, 44,105, 43, 49, - 44,116,111,108,117, 97, 95,100,111, 99,108,111,110,101, 40, - 116,111,108,117, 97, 95, 83, 44,116,111,108,117, 97, 73, 95, - 99,108,111,110,101, 44, 39, 44,115,101,108,102, 46,116, 97, - 103, 44, 39, 41, 44, 39, 44,115,101,108,102, 46,116, 97,103, - 44, 39, 41, 59, 39, 41, 10,111,117,116,112,117,116, 40, 39, - 32,125, 39, 41, 10, 10, 10,101,108,115,101, 10,111,117,116, - 112,117,116, 40, 39, 32,116,111,108,117, 97, 95,112,117,115, - 104,102,105,101,108,100,117,115,101,114,116,121,112,101, 40, - 116,111,108,117, 97, 95, 83, 44, 39, 44,110, 97,114,103, 44, - 39, 44,105, 43, 49, 44, 40,118,111,105,100, 42, 41, 39, 44, - 115,101,108,102, 46,110, 97,109,101, 44, 39, 91,105, 93, 44, - 39, 44,115,101,108,102, 46,116, 97,103, 44, 39, 41, 59, 39, - 41, 10,101,110,100, 10,101,110,100, 10,111,117,116,112,117, - 116, 40, 39, 32,125, 39, 41, 10,101,110,100, 10,101,110,100, - 10, 10, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97, - 115,115, 68,101, 99,108, 97,114, 97,116,105,111,110, 58,102, - 114,101,101, 97,114,114, 97,121, 32, 40, 41, 10,105,102, 32, - 115,101,108,102, 46,100,105,109, 32,126, 61, 32, 39, 39, 32, - 97,110,100, 32,116,111,110,117,109, 98,101,114, 40,115,101, - 108,102, 46,100,105,109, 41, 61, 61,110,105,108, 32,116,104, - 101,110, 10,111,117,116,112,117,116, 40, 39, 32,102,114,101, - 101, 40, 39, 44,115,101,108,102, 46,110, 97,109,101, 44, 39, - 41, 59, 39, 41, 10,101,110,100, 10,101,110,100, 10, 10, 10, - 102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 68, - 101, 99,108, 97,114, 97,116,105,111,110, 58,112, 97,115,115, - 112, 97,114, 32, 40, 41, 10,105,102, 32,115,101,108,102, 46, - 112,116,114, 61, 61, 39, 38, 39, 32,116,104,101,110, 10,111, - 117,116,112,117,116, 40, 39, 42, 39, 46, 46,115,101,108,102, - 46,110, 97,109,101, 41, 10,101,108,115,101,105,102, 32,115, - 101,108,102, 46,114,101,116, 61, 61, 39, 42, 39, 32,116,104, - 101,110, 10,111,117,116,112,117,116, 40, 39, 38, 39, 46, 46, - 115,101,108,102, 46,110, 97,109,101, 41, 10,101,108,115,101, - 10,111,117,116,112,117,116, 40,115,101,108,102, 46,110, 97, - 109,101, 41, 10,101,110,100, 10,101,110,100, 10, 10, 10,102, - 117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 68,101, - 99,108, 97,114, 97,116,105,111,110, 58,114,101,116,118, 97, - 108,117,101, 32, 40, 41, 10,105,102, 32,115,101,108,102, 46, - 114,101,116, 32,126, 61, 32, 39, 39, 32,116,104,101,110, 10, - 108,111, 99, 97,108, 32,116, 44, 99,116, 32, 61, 32,105,115, - 98, 97,115,105, 99, 40,115,101,108,102, 46,116,121,112,101, - 41, 10,105,102, 32,116, 32,116,104,101,110, 10,111,117,116, - 112,117,116, 40, 39, 32,116,111,108,117, 97, 95,112,117,115, - 104, 39, 46, 46,116, 46, 46, 39, 40,116,111,108,117, 97, 95, - 83, 44, 40, 39, 44, 99,116, 44, 39, 41, 39, 46, 46,115,101, - 108,102, 46,110, 97,109,101, 46, 46, 39, 41, 59, 39, 41, 10, - 101,108,115,101, 10,111,117,116,112,117,116, 40, 39, 32,116, - 111,108,117, 97, 95,112,117,115,104,117,115,101,114,116,121, - 112,101, 40,116,111,108,117, 97, 95, 83, 44, 40,118,111,105, - 100, 42, 41, 39, 46, 46,115,101,108,102, 46,110, 97,109,101, - 46, 46, 39, 44, 39, 44,115,101,108,102, 46,116, 97,103, 44, - 39, 41, 59, 39, 41, 10,101,110,100, 10,114,101,116,117,114, - 110, 32, 49, 10,101,110,100, 10,114,101,116,117,114,110, 32, - 48, 10,101,110,100, 10, 10, 10,102,117,110, 99,116,105,111, - 110, 32, 95, 68,101, 99,108, 97,114, 97,116,105,111,110, 32, - 40,116, 41, 10,105,102, 32,116, 46,110, 97,109,101, 32, 97, - 110,100, 32,116, 46,110, 97,109,101,126, 61, 39, 39, 32,116, - 104,101,110, 10,108,111, 99, 97,108, 32,110, 32, 61, 32,115, - 112,108,105,116, 40,116, 46,110, 97,109,101, 44, 39, 64, 39, - 41, 10,116, 46,110, 97,109,101, 32, 61, 32,110, 91, 49, 93, - 10,116, 46,108,110, 97,109,101, 32, 61, 32,103,115,117, 98, - 40,110, 91, 50, 93, 32,111,114, 32,110, 91, 49, 93, 44, 34, - 37, 91, 46, 45, 37, 93, 34, 44, 34, 34, 41, 10,101,110,100, - 10,116, 46, 95, 98, 97,115,101, 32, 61, 32, 99,108, 97,115, - 115, 68,101, 99,108, 97,114, 97,116,105,111,110, 10,115,101, - 116,116, 97,103, 40,116, 44,116,111,108,117, 97, 95,116, 97, - 103, 41, 10,116, 58, 99,104,101, 99,107,110, 97,109,101, 40, - 41, 10,116, 58, 99,104,101, 99,107,116,121,112,101, 40, 41, - 10,114,101,116,117,114,110, 32,116, 10,101,110,100, 10, 10, - 10, 10, 10,102,117,110, 99,116,105,111,110, 32, 68,101, 99, - 108, 97,114, 97,116,105,111,110, 32, 40,115, 44,107,105,110, - 100, 41, 10, 10,115, 32, 61, 32,103,115,117, 98, 40,115, 44, - 34, 37,115, 42, 61, 37,115, 42, 34, 44, 34, 61, 34, 41, 10, - 10,105,102, 32,107,105,110,100, 32, 61, 61, 32, 34,118, 97, - 114, 34, 32,116,104,101,110, 10, 10,105,102, 32,115, 32, 61, - 61, 32, 39, 39, 32,111,114, 32,115, 32, 61, 61, 32, 39,118, - 111,105,100, 39, 32,116,104,101,110, 10,114,101,116,117,114, - 110, 32, 95, 68,101, 99,108, 97,114, 97,116,105,111,110,123, - 116,121,112,101, 32, 61, 32, 39,118,111,105,100, 39, 44, 32, - 107,105,110,100, 32, 61, 32,107,105,110,100,125, 10,101,110, - 100, 10,101,110,100, 10, 10, 10,108,111, 99, 97,108, 32,116, - 32, 61, 32,115,112,108,105,116, 40,115, 44, 39, 37, 42, 37, - 115, 42, 38, 39, 41, 10,105,102, 32,116, 46,110, 32, 61, 61, - 32, 50, 32,116,104,101,110, 10,105,102, 32,107,105,110,100, - 32, 61, 61, 32, 39,102,117,110, 99, 39, 32,116,104,101,110, - 10,101,114,114,111,114, 40, 34, 35,105,110,118, 97,108,105, - 100, 32,102,117,110, 99,116,105,111,110, 32,114,101,116,117, - 114,110, 32,116,121,112,101, 58, 32, 34, 46, 46,115, 41, 10, - 101,110,100, 10,108,111, 99, 97,108, 32,109, 32, 61, 32,115, - 112,108,105,116, 40,116, 91, 49, 93, 44, 39, 37,115, 37,115, - 42, 39, 41, 10,114,101,116,117,114,110, 32, 95, 68,101, 99, - 108, 97,114, 97,116,105,111,110,123, 10,110, 97,109,101, 32, - 61, 32,116, 91, 50, 93, 44, 10,112,116,114, 32, 61, 32, 39, - 42, 39, 44, 10,114,101,116, 32, 61, 32, 39, 38, 39, 44, 10, - 116,121,112,101, 32, 61, 32,109, 91,109, 46,110, 93, 44, 10, - 109,111,100, 32, 61, 32, 99,111,110, 99, 97,116, 40,109, 44, - 49, 44,109, 46,110, 45, 49, 41, 44, 10,107,105,110,100, 32, - 61, 32,107,105,110,100, 10,125, 10,101,110,100, 10, 10, 10, - 116, 32, 61, 32,115,112,108,105,116, 40,115, 44, 39, 37, 42, - 37,115, 42, 37, 42, 39, 41, 10,105,102, 32,116, 46,110, 32, - 61, 61, 32, 50, 32,116,104,101,110, 10,105,102, 32,107,105, - 110,100, 32, 61, 61, 32, 39,102,117,110, 99, 39, 32,116,104, - 101,110, 10,101,114,114,111,114, 40, 34, 35,105,110,118, 97, - 108,105,100, 32,102,117,110, 99,116,105,111,110, 32,114,101, - 116,117,114,110, 32,116,121,112,101, 58, 32, 34, 46, 46,115, - 41, 10,101,110,100, 10,108,111, 99, 97,108, 32,109, 32, 61, - 32,115,112,108,105,116, 40,116, 91, 49, 93, 44, 39, 37,115, - 37,115, 42, 39, 41, 10,114,101,116,117,114,110, 32, 95, 68, - 101, 99,108, 97,114, 97,116,105,111,110,123, 10,110, 97,109, - 101, 32, 61, 32,116, 91, 50, 93, 44, 10,112,116,114, 32, 61, - 32, 39, 42, 39, 44, 10,114,101,116, 32, 61, 32, 39, 42, 39, - 44, 10,116,121,112,101, 32, 61, 32,109, 91,109, 46,110, 93, - 44, 10,109,111,100, 32, 61, 32, 99,111,110, 99, 97,116, 40, - 109, 44, 49, 44,109, 46,110, 45, 49, 41, 44, 10,107,105,110, - 100, 32, 61, 32,107,105,110,100, 10,125, 10,101,110,100, 10, - 10, 10,116, 32, 61, 32,115,112,108,105,116, 40,115, 44, 39, - 38, 39, 41, 10,105,102, 32,116, 46,110, 32, 61, 61, 32, 50, - 32,116,104,101,110, 10,108,111, 99, 97,108, 32,109, 32, 61, - 32,115,112,108,105,116, 40,116, 91, 49, 93, 44, 39, 37,115, - 37,115, 42, 39, 41, 10,114,101,116,117,114,110, 32, 95, 68, - 101, 99,108, 97,114, 97,116,105,111,110,123, 10,110, 97,109, - 101, 32, 61, 32,116, 91, 50, 93, 44, 10,112,116,114, 32, 61, - 32, 39, 38, 39, 44, 10,116,121,112,101, 32, 61, 32,109, 91, - 109, 46,110, 93, 44, 10,109,111,100, 32, 61, 32, 99,111,110, - 99, 97,116, 40,109, 44, 49, 44,109, 46,110, 45, 49, 41, 32, - 44, 10,107,105,110,100, 32, 61, 32,107,105,110,100, 10,125, - 10,101,110,100, 10, 10, 10,108,111, 99, 97,108, 32,115, 49, - 32, 61, 32,103,115,117, 98, 40,115, 44, 34, 40, 37, 98, 92, - 91, 92, 93, 41, 34, 44,102,117,110, 99,116,105,111,110, 32, - 40,110, 41, 32,114,101,116,117,114,110, 32,103,115,117, 98, - 40,110, 44, 39, 37, 42, 39, 44, 39, 92, 49, 39, 41, 32,101, - 110,100, 41, 10,116, 32, 61, 32,115,112,108,105,116, 40,115, - 49, 44, 39, 37, 42, 39, 41, 10,105,102, 32,116, 46,110, 32, - 61, 61, 32, 50, 32,116,104,101,110, 10,116, 91, 50, 93, 32, - 61, 32,103,115,117, 98, 40,116, 91, 50, 93, 44, 39, 92, 49, - 39, 44, 39, 37, 42, 39, 41, 10,108,111, 99, 97,108, 32,109, - 32, 61, 32,115,112,108,105,116, 40,116, 91, 49, 93, 44, 39, - 37,115, 37,115, 42, 39, 41, 10,114,101,116,117,114,110, 32, - 95, 68,101, 99,108, 97,114, 97,116,105,111,110,123, 10,110, - 97,109,101, 32, 61, 32,116, 91, 50, 93, 44, 10,112,116,114, - 32, 61, 32, 39, 42, 39, 44, 10,116,121,112,101, 32, 61, 32, - 109, 91,109, 46,110, 93, 44, 10,109,111,100, 32, 61, 32, 99, - 111,110, 99, 97,116, 40,109, 44, 49, 44,109, 46,110, 45, 49, - 41, 32, 44, 10,107,105,110,100, 32, 61, 32,107,105,110,100, - 10,125, 10,101,110,100, 10, 10,105,102, 32,107,105,110,100, - 32, 61, 61, 32, 39,118, 97,114, 39, 32,116,104,101,110, 10, - 10,116, 32, 61, 32,115,112,108,105,116, 40,115, 44, 39, 37, - 115, 37,115, 42, 39, 41, 10,108,111, 99, 97,108, 32,118, 10, - 105,102, 32,105,115,116,121,112,101, 40,116, 91,116, 46,110, - 93, 41, 32,116,104,101,110, 32,118, 32, 61, 32, 39, 39, 32, - 101,108,115,101, 32,118, 32, 61, 32,116, 91,116, 46,110, 93, - 59, 32,116, 46,110, 32, 61, 32,116, 46,110, 45, 49, 32,101, - 110,100, 10,114,101,116,117,114,110, 32, 95, 68,101, 99,108, - 97,114, 97,116,105,111,110,123, 10,110, 97,109,101, 32, 61, - 32,118, 44, 10,116,121,112,101, 32, 61, 32,116, 91,116, 46, - 110, 93, 44, 10,109,111,100, 32, 61, 32, 99,111,110, 99, 97, - 116, 40,116, 44, 49, 44,116, 46,110, 45, 49, 41, 44, 10,107, - 105,110,100, 32, 61, 32,107,105,110,100, 10,125, 10, 10,101, - 108,115,101, 10, 10, 10,116, 32, 61, 32,115,112,108,105,116, - 40,115, 44, 39, 37,115, 37,115, 42, 39, 41, 10,108,111, 99, - 97,108, 32,118, 32, 61, 32,116, 91,116, 46,110, 93, 10,108, - 111, 99, 97,108, 32,116,112, 44,109,100, 10,105,102, 32,116, - 46,110, 62, 49, 32,116,104,101,110, 10,116,112, 32, 61, 32, - 116, 91,116, 46,110, 45, 49, 93, 10,109,100, 32, 61, 32, 99, - 111,110, 99, 97,116, 40,116, 44, 49, 44,116, 46,110, 45, 50, - 41, 10,101,110,100, 10,114,101,116,117,114,110, 32, 95, 68, - 101, 99,108, 97,114, 97,116,105,111,110,123, 10,110, 97,109, - 101, 32, 61, 32,118, 44, 10,116,121,112,101, 32, 61, 32,116, - 112, 44, 10,109,111,100, 32, 61, 32,109,100, 44, 10,107,105, - 110,100, 32, 61, 32,107,105,110,100, 10,125, 10,101,110,100, - 10, 10,101,110,100, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 99,108, 97,115,115, 86, 97,114,105, - 97, 98,108,101, 32, 61, 32,123, 10, 95, 98, 97,115,101, 32, - 61, 32, 99,108, 97,115,115, 68,101, 99,108, 97,114, 97,116, - 105,111,110, 44, 10,125, 10, 10,115,101,116,116, 97,103, 40, - 99,108, 97,115,115, 86, 97,114,105, 97, 98,108,101, 44,116, - 111,108,117, 97, 95,116, 97,103, 41, 10, 10, 10,102,117,110, - 99,116,105,111,110, 32, 99,108, 97,115,115, 86, 97,114,105, - 97, 98,108,101, 58,112,114,105,110,116, 32, 40,105,100,101, - 110,116, 44, 99,108,111,115,101, 41, 10,112,114,105,110,116, - 40,105,100,101,110,116, 46, 46, 34, 86, 97,114,105, 97, 98, - 108,101,123, 34, 41, 10,112,114,105,110,116, 40,105,100,101, - 110,116, 46, 46, 34, 32,109,111,100, 32, 61, 32, 39, 34, 46, - 46,115,101,108,102, 46,109,111,100, 46, 46, 34, 39, 44, 34, - 41, 10,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, - 34, 32,116,121,112,101, 32, 61, 32, 39, 34, 46, 46,115,101, - 108,102, 46,116,121,112,101, 46, 46, 34, 39, 44, 34, 41, 10, - 112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32, - 112,116,114, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46, - 112,116,114, 46, 46, 34, 39, 44, 34, 41, 10,112,114,105,110, - 116, 40,105,100,101,110,116, 46, 46, 34, 32,110, 97,109,101, - 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46,110, 97,109, - 101, 46, 46, 34, 39, 44, 34, 41, 10,112,114,105,110,116, 40, - 105,100,101,110,116, 46, 46, 34, 32,100,101,102, 32, 61, 32, - 39, 34, 46, 46,115,101,108,102, 46,100,101,102, 46, 46, 34, - 39, 44, 34, 41, 10,112,114,105,110,116, 40,105,100,101,110, - 116, 46, 46, 34, 32,114,101,116, 32, 61, 32, 39, 34, 46, 46, - 115,101,108,102, 46,114,101,116, 46, 46, 34, 39, 44, 34, 41, - 10,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, - 125, 34, 46, 46, 99,108,111,115,101, 41, 10,101,110,100, 10, - 10, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115, - 115, 86, 97,114,105, 97, 98,108,101, 58,103,101,116,118, 97, - 108,117,101, 32, 40, 99,108, 97,115,115, 44,115,116, 97,116, - 105, 99, 41, 10,105,102, 32, 99,108, 97,115,115, 32, 97,110, - 100, 32,115,116, 97,116,105, 99, 32,116,104,101,110, 10,114, - 101,116,117,114,110, 32, 99,108, 97,115,115, 46, 46, 39, 58, - 58, 39, 46, 46,115,101,108,102, 46,110, 97,109,101, 10,101, - 108,115,101,105,102, 32, 99,108, 97,115,115, 32,116,104,101, - 110, 10,114,101,116,117,114,110, 32, 39,115,101,108,102, 45, - 62, 39, 46, 46,115,101,108,102, 46,110, 97,109,101, 10,101, - 108,115,101, 10,114,101,116,117,114,110, 32,115,101,108,102, - 46,110, 97,109,101, 10,101,110,100, 10,101,110,100, 10, 10, - 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, - 86, 97,114,105, 97, 98,108,101, 58,115,117,112, 99,111,100, - 101, 32, 40, 41, 10,108,111, 99, 97,108, 32, 99,108, 97,115, - 115, 32, 61, 32,115,101,108,102, 58,105,110, 99,108, 97,115, - 115, 40, 41, 10, 10, 10,105,102, 32, 99,108, 97,115,115, 32, - 116,104,101,110, 10,111,117,116,112,117,116, 40, 34, 47, 42, - 32,103,101,116, 32,102,117,110, 99,116,105,111,110, 58, 34, - 44,115,101,108,102, 46,110, 97,109,101, 44, 34, 32,111,102, - 32, 99,108, 97,115,115, 32, 34, 44, 99,108, 97,115,115, 44, - 34, 32, 42, 47, 34, 41, 10,101,108,115,101, 10,111,117,116, - 112,117,116, 40, 34, 47, 42, 32,103,101,116, 32,102,117,110, - 99,116,105,111,110, 58, 34, 44,115,101,108,102, 46,110, 97, - 109,101, 44, 34, 32, 42, 47, 34, 41, 10,101,110,100, 10,115, - 101,108,102, 46, 99,103,101,116,110, 97,109,101, 32, 61, 32, - 115,101,108,102, 58, 99,102,117,110, 99,110, 97,109,101, 40, - 34,116,111,108,117, 97, 73, 95,103,101,116, 34, 41, 10,111, - 117,116,112,117,116, 40, 34,115,116, 97,116,105, 99, 32,105, - 110,116, 34, 44,115,101,108,102, 46, 99,103,101,116,110, 97, - 109,101, 44, 34, 40,108,117, 97, 95, 83,116, 97,116,101, 42, - 32,116,111,108,117, 97, 95, 83, 41, 34, 41, 10,111,117,116, - 112,117,116, 40, 34,123, 34, 41, 10, 10, 10,108,111, 99, 97, - 108, 32, 95, 44, 95, 44,115,116, 97,116,105, 99, 32, 61, 32, - 115,116,114,102,105,110,100, 40,115,101,108,102, 46,109,111, - 100, 44, 39, 94, 37,115, 42, 40,115,116, 97,116,105, 99, 41, - 39, 41, 10,105,102, 32, 99,108, 97,115,115, 32, 97,110,100, - 32,115,116, 97,116,105, 99, 61, 61,110,105,108, 32,116,104, - 101,110, 10,111,117,116,112,117,116, 40, 39, 32, 39, 44, 99, - 108, 97,115,115, 44, 39, 42, 39, 44, 39,115,101,108,102, 32, - 61, 32, 39, 41, 10,111,117,116,112,117,116, 40, 39, 40, 39, - 44, 99,108, 97,115,115, 44, 39, 42, 41, 32, 39, 41, 10,111, - 117,116,112,117,116, 40, 39,116,111,108,117, 97, 95,103,101, - 116,117,115,101,114,116,121,112,101, 40,116,111,108,117, 97, - 95, 83, 44, 49, 44, 48, 41, 59, 39, 41, 10,101,108,115,101, - 105,102, 32,115,116, 97,116,105, 99, 32,116,104,101,110, 10, - 95, 44, 95, 44,115,101,108,102, 46,109,111,100, 32, 61, 32, - 115,116,114,102,105,110,100, 40,115,101,108,102, 46,109,111, - 100, 44, 39, 94, 37,115, 42,115,116, 97,116,105, 99, 37,115, - 37,115, 42, 40, 46, 42, 41, 39, 41, 10,101,110,100, 10, 10, - 10, 10,105,102, 32, 99,108, 97,115,115, 32, 97,110,100, 32, - 115,116, 97,116,105, 99, 61, 61,110,105,108, 32,116,104,101, - 110, 10,111,117,116,112,117,116, 40, 39, 32,105,102, 32, 40, - 33,115,101,108,102, 41, 32, 84, 79, 76, 85, 65, 95, 69, 82, - 82, 95, 83, 69, 76, 70, 59, 39, 41, 59, 10,101,110,100, 10, - 10, 10,108,111, 99, 97,108, 32,116, 44, 99,116, 32, 61, 32, - 105,115, 98, 97,115,105, 99, 40,115,101,108,102, 46,116,121, - 112,101, 41, 10,105,102, 32,116, 32,116,104,101,110, 10,111, - 117,116,112,117,116, 40, 39, 32,116,111,108,117, 97, 95,112, - 117,115,104, 39, 46, 46,116, 46, 46, 39, 40,116,111,108,117, - 97, 95, 83, 44, 40, 39, 44, 99,116, 44, 39, 41, 39, 46, 46, - 115,101,108,102, 58,103,101,116,118, 97,108,117,101, 40, 99, - 108, 97,115,115, 44,115,116, 97,116,105, 99, 41, 46, 46, 39, - 41, 59, 39, 41, 10,101,108,115,101, 10,105,102, 32,115,101, - 108,102, 46,112,116,114, 32, 61, 61, 32, 39, 38, 39, 32,111, - 114, 32,115,101,108,102, 46,112,116,114, 32, 61, 61, 32, 39, - 39, 32,116,104,101,110, 10,111,117,116,112,117,116, 40, 39, - 32,116,111,108,117, 97, 95,112,117,115,104,117,115,101,114, - 116,121,112,101, 40,116,111,108,117, 97, 95, 83, 44, 40,118, - 111,105,100, 42, 41, 38, 39, 46, 46,115,101,108,102, 58,103, - 101,116,118, 97,108,117,101, 40, 99,108, 97,115,115, 44,115, - 116, 97,116,105, 99, 41, 46, 46, 39, 44, 39, 44,115,101,108, - 102, 46,116, 97,103, 44, 39, 41, 59, 39, 41, 10,101,108,115, - 101, 10,111,117,116,112,117,116, 40, 39, 32,116,111,108,117, - 97, 95,112,117,115,104,117,115,101,114,116,121,112,101, 40, - 116,111,108,117, 97, 95, 83, 44, 40,118,111,105,100, 42, 41, - 39, 46, 46,115,101,108,102, 58,103,101,116,118, 97,108,117, - 101, 40, 99,108, 97,115,115, 44,115,116, 97,116,105, 99, 41, - 46, 46, 39, 44, 39, 44,115,101,108,102, 46,116, 97,103, 44, - 39, 41, 59, 39, 41, 10,101,110,100, 10,101,110,100, 10,111, - 117,116,112,117,116, 40, 39, 32,114,101,116,117,114,110, 32, - 49, 59, 39, 41, 10,111,117,116,112,117,116, 40, 39,125, 39, - 41, 10,111,117,116,112,117,116, 40, 39, 92,110, 39, 41, 10, - 10, 10,105,102, 32,110,111,116, 32,115,116,114,102,105,110, - 100, 40,115,101,108,102, 46,109,111,100, 44, 39, 99,111,110, - 115,116, 39, 41, 32,116,104,101,110, 10,105,102, 32, 99,108, - 97,115,115, 32,116,104,101,110, 10,111,117,116,112,117,116, - 40, 34, 47, 42, 32,115,101,116, 32,102,117,110, 99,116,105, - 111,110, 58, 34, 44,115,101,108,102, 46,110, 97,109,101, 44, - 34, 32,111,102, 32, 99,108, 97,115,115, 32, 34, 44, 99,108, - 97,115,115, 44, 34, 32, 42, 47, 34, 41, 10,101,108,115,101, - 10,111,117,116,112,117,116, 40, 34, 47, 42, 32,115,101,116, - 32,102,117,110, 99,116,105,111,110, 58, 34, 44,115,101,108, - 102, 46,110, 97,109,101, 44, 34, 32, 42, 47, 34, 41, 10,101, - 110,100, 10,115,101,108,102, 46, 99,115,101,116,110, 97,109, - 101, 32, 61, 32,115,101,108,102, 58, 99,102,117,110, 99,110, - 97,109,101, 40, 34,116,111,108,117, 97, 73, 95,115,101,116, - 34, 41, 10,111,117,116,112,117,116, 40, 34,115,116, 97,116, - 105, 99, 32,105,110,116, 34, 44,115,101,108,102, 46, 99,115, - 101,116,110, 97,109,101, 44, 34, 40,108,117, 97, 95, 83,116, - 97,116,101, 42, 32,116,111,108,117, 97, 95, 83, 41, 34, 41, - 10,111,117,116,112,117,116, 40, 34,123, 34, 41, 10, 10, 10, - 108,111, 99, 97,108, 32,110, 97,114,103, 61, 49, 10,105,102, - 32, 99,108, 97,115,115, 32, 97,110,100, 32,115,116, 97,116, - 105, 99, 61, 61,110,105,108, 32,116,104,101,110, 10,111,117, - 116,112,117,116, 40, 39, 32, 39, 44, 99,108, 97,115,115, 44, - 39, 42, 39, 44, 39,115,101,108,102, 32, 61, 32, 39, 41, 10, - 111,117,116,112,117,116, 40, 39, 40, 39, 44, 99,108, 97,115, - 115, 44, 39, 42, 41, 32, 39, 41, 10,111,117,116,112,117,116, - 40, 39,116,111,108,117, 97, 95,103,101,116,117,115,101,114, - 116,121,112,101, 40,116,111,108,117, 97, 95, 83, 44, 49, 44, - 48, 41, 59, 39, 41, 10, 10,111,117,116,112,117,116, 40, 39, - 32,105,102, 32, 40, 33,115,101,108,102, 41, 32, 84, 79, 76, - 85, 65, 95, 69, 82, 82, 95, 83, 69, 76, 70, 59, 39, 41, 59, - 10,110, 97,114,103, 32, 61, 32,110, 97,114,103, 43, 49, 10, - 101,108,115,101,105,102, 32,115,116, 97,116,105, 99, 32,116, - 104,101,110, 10, 95, 44, 95, 44,115,101,108,102, 46,109,111, - 100, 32, 61, 32,115,116,114,102,105,110,100, 40,115,101,108, - 102, 46,109,111,100, 44, 39, 94, 37,115, 42,115,116, 97,116, - 105, 99, 37,115, 37,115, 42, 40, 46, 42, 41, 39, 41, 10,110, - 97,114,103, 32, 61, 32,110, 97,114,103, 43, 49, 10,101,110, - 100, 10, 10, 10,111,117,116,112,117,116, 40, 39, 32,105,102, - 32, 40, 33, 39, 46, 46,115,101,108,102, 58,111,117,116, 99, - 104,101, 99,107,116,121,112,101, 40,110, 97,114,103, 41, 46, - 46, 39, 41, 39, 41, 10,111,117,116,112,117,116, 40, 39, 32, - 84, 79, 76, 85, 65, 95, 69, 82, 82, 95, 65, 83, 83, 73, 71, - 78, 59, 39, 41, 10, 10, 10,108,111, 99, 97,108, 32,112,116, - 114, 32, 61, 32, 39, 39, 10,105,102, 32,115,101,108,102, 46, - 112,116,114,126, 61, 39, 39, 32,116,104,101,110, 32,112,116, - 114, 32, 61, 32, 39, 42, 39, 32,101,110,100, 10,111,117,116, - 112,117,116, 40, 39, 32, 39, 41, 10,105,102, 32, 99,108, 97, - 115,115, 32, 97,110,100, 32,115,116, 97,116,105, 99, 32,116, - 104,101,110, 10,111,117,116,112,117,116, 40, 99,108, 97,115, - 115, 46, 46, 39, 58, 58, 39, 46, 46,115,101,108,102, 46,110, - 97,109,101, 41, 10,101,108,115,101,105,102, 32, 99,108, 97, - 115,115, 32,116,104,101,110, 10,111,117,116,112,117,116, 40, - 39,115,101,108,102, 45, 62, 39, 46, 46,115,101,108,102, 46, - 110, 97,109,101, 41, 10,101,108,115,101, 10,111,117,116,112, - 117,116, 40,115,101,108,102, 46,110, 97,109,101, 41, 10,101, - 110,100, 10,108,111, 99, 97,108, 32,116, 32, 61, 32,105,115, - 98, 97,115,105, 99, 40,115,101,108,102, 46,116,121,112,101, - 41, 10,111,117,116,112,117,116, 40, 39, 32, 61, 32, 39, 41, - 10,105,102, 32,110,111,116, 32,116, 32, 97,110,100, 32,112, - 116,114, 61, 61, 39, 39, 32,116,104,101,110, 32,111,117,116, - 112,117,116, 40, 39, 42, 39, 41, 32,101,110,100, 10,111,117, - 116,112,117,116, 40, 39, 40, 40, 39, 44,115,101,108,102, 46, - 109,111,100, 44,115,101,108,102, 46,116,121,112,101, 41, 10, - 105,102, 32,110,111,116, 32,116, 32,116,104,101,110, 10,111, - 117,116,112,117,116, 40, 39, 42, 39, 41, 10,101,110,100, 10, - 111,117,116,112,117,116, 40, 39, 41, 32, 39, 41, 10,108,111, - 99, 97,108, 32,100,101,102, 32, 61, 32, 48, 10,105,102, 32, - 115,101,108,102, 46,100,101,102, 32,126, 61, 32, 39, 39, 32, - 116,104,101,110, 32,100,101,102, 32, 61, 32,115,101,108,102, - 46,100,101,102, 32,101,110,100, 10,105,102, 32,116, 32,116, - 104,101,110, 10,111,117,116,112,117,116, 40, 39,116,111,108, - 117, 97, 95,103,101,116, 39, 46, 46,116, 44, 39, 40,116,111, - 108,117, 97, 95, 83, 44, 39, 44,110, 97,114,103, 44, 39, 44, - 39, 44,100,101,102, 44, 39, 41, 41, 59, 39, 41, 10,101,108, - 115,101, 10,111,117,116,112,117,116, 40, 39,116,111,108,117, - 97, 95,103,101,116,117,115,101,114,116,121,112,101, 40,116, - 111,108,117, 97, 95, 83, 44, 39, 44,110, 97,114,103, 44, 39, - 44, 39, 44,100,101,102, 44, 39, 41, 41, 59, 39, 41, 10,101, - 110,100, 10,111,117,116,112,117,116, 40, 39, 32,114,101,116, - 117,114,110, 32, 48, 59, 39, 41, 10,111,117,116,112,117,116, - 40, 39,125, 39, 41, 10,111,117,116,112,117,116, 40, 39, 92, - 110, 39, 41, 10,101,110,100, 10, 10,101,110,100, 10, 10,102, - 117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, 86, 97, - 114,105, 97, 98,108,101, 58,114,101,103,105,115,116,101,114, - 32, 40, 41, 10,108,111, 99, 97,108, 32,112, 97,114,101,110, - 116, 32, 61, 32,115,101,108,102, 58,105,110, 99,108, 97,115, - 115, 40, 41, 32,111,114, 32,115,101,108,102, 58,105,110,109, - 111,100,117,108,101, 40, 41, 10,105,102, 32,112, 97,114,101, - 110,116, 32,116,104,101,110, 10,105,102, 32,115,101,108,102, - 46, 99,115,101,116,110, 97,109,101, 32,116,104,101,110, 10, - 111,117,116,112,117,116, 40, 39, 32,116,111,108,117, 97, 95, - 116, 97, 98,108,101,118, 97,114, 40,116,111,108,117, 97, 95, - 83, 44, 34, 39, 46, 46,112, 97,114,101,110,116, 46, 46, 39, - 34, 44, 34, 39, 46, 46,115,101,108,102, 46,108,110, 97,109, - 101, 46, 46, 39, 34, 44, 39, 46, 46,115,101,108,102, 46, 99, - 103,101,116,110, 97,109,101, 46, 46, 39, 44, 39, 46, 46,115, - 101,108,102, 46, 99,115,101,116,110, 97,109,101, 46, 46, 39, - 41, 59, 39, 41, 10,101,108,115,101, 10,111,117,116,112,117, - 116, 40, 39, 32,116,111,108,117, 97, 95,116, 97, 98,108,101, - 118, 97,114, 40,116,111,108,117, 97, 95, 83, 44, 34, 39, 46, - 46,112, 97,114,101,110,116, 46, 46, 39, 34, 44, 34, 39, 46, - 46,115,101,108,102, 46,108,110, 97,109,101, 46, 46, 39, 34, - 44, 39, 46, 46,115,101,108,102, 46, 99,103,101,116,110, 97, - 109,101, 46, 46, 39, 44, 78, 85, 76, 76, 41, 59, 39, 41, 10, - 101,110,100, 10,101,108,115,101, 10,105,102, 32,115,101,108, - 102, 46, 99,115,101,116,110, 97,109,101, 32,116,104,101,110, - 10,111,117,116,112,117,116, 40, 39, 32,116,111,108,117, 97, - 95,103,108,111, 98, 97,108,118, 97,114, 40,116,111,108,117, - 97, 95, 83, 44, 34, 39, 46, 46,115,101,108,102, 46,108,110, - 97,109,101, 46, 46, 39, 34, 44, 39, 46, 46,115,101,108,102, - 46, 99,103,101,116,110, 97,109,101, 46, 46, 39, 44, 39, 46, - 46,115,101,108,102, 46, 99,115,101,116,110, 97,109,101, 46, - 46, 39, 41, 59, 39, 41, 10,101,108,115,101, 10,111,117,116, - 112,117,116, 40, 39, 32,116,111,108,117, 97, 95,103,108,111, - 98, 97,108,118, 97,114, 40,116,111,108,117, 97, 95, 83, 44, - 34, 39, 46, 46,115,101,108,102, 46,108,110, 97,109,101, 46, - 46, 39, 34, 44, 39, 46, 46,115,101,108,102, 46, 99,103,101, - 116,110, 97,109,101, 46, 46, 39, 44, 78, 85, 76, 76, 41, 59, - 39, 41, 10,101,110,100, 10,101,110,100, 10,101,110,100, 10, - 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, - 86, 97,114,105, 97, 98,108,101, 58,117,110,114,101,103,105, - 115,116,101,114, 32, 40, 41, 10,105,102, 32,115,101,108,102, - 58,105,110, 99,108, 97,115,115, 40, 41, 61, 61,110,105,108, - 32, 97,110,100, 32,115,101,108,102, 58,105,110,109,111,100, - 117,108,101, 40, 41, 61, 61,110,105,108, 32,116,104,101,110, - 10,111,117,116,112,117,116, 40, 39, 32,108,117, 97, 95,103, - 101,116,103,108,111, 98, 97,108,115, 40,116,111,108,117, 97, - 95, 83, 41, 59, 39, 41, 10,111,117,116,112,117,116, 40, 39, - 32,108,117, 97, 95,112,117,115,104,115,116,114,105,110,103, - 40,116,111,108,117, 97, 95, 83, 44, 34, 39, 44,115,101,108, - 102, 46,108,110, 97,109,101, 44, 39, 34, 41, 59, 32,108,117, - 97, 95,112,117,115,104,110,105,108, 40,116,111,108,117, 97, - 95, 83, 41, 59, 32,108,117, 97, 95,114, 97,119,115,101,116, - 40,116,111,108,117, 97, 95, 83, 44, 45, 51, 41, 59, 39, 41, - 10,111,117,116,112,117,116, 40, 39, 32,108,117, 97, 95,112, - 111,112, 40,116,111,108,117, 97, 95, 83, 44, 49, 41, 59, 39, - 41, 10,101,110,100, 10,101,110,100, 10, 10, 10, 10,102,117, - 110, 99,116,105,111,110, 32, 95, 86, 97,114,105, 97, 98,108, - 101, 32, 40,116, 41, 10,116, 46, 95, 98, 97,115,101, 32, 61, - 32, 99,108, 97,115,115, 86, 97,114,105, 97, 98,108,101, 10, - 115,101,116,116, 97,103, 40,116, 44,116,111,108,117, 97, 95, - 116, 97,103, 41, 10, 97,112,112,101,110,100, 40,116, 41, 10, - 114,101,116,117,114,110, 32,116, 10,101,110,100, 10, 10, 10, - 10,102,117,110, 99,116,105,111,110, 32, 86, 97,114,105, 97, - 98,108,101, 32, 40,115, 41, 10,114,101,116,117,114,110, 32, - 95, 86, 97,114,105, 97, 98,108,101, 32, 40, 68,101, 99,108, - 97,114, 97,116,105,111,110, 40,115, 44, 39,118, 97,114, 39, - 41, 41, 10,101,110,100, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 99,108, 97,115,115, 65, - 114,114, 97,121, 32, 61, 32,123, 10, 95, 98, 97,115,101, 32, - 61, 32, 99,108, 97,115,115, 68,101, 99,108, 97,114, 97,116, - 105,111,110, 44, 10,125, 10, 10,115,101,116,116, 97,103, 40, - 99,108, 97,115,115, 65,114,114, 97,121, 44,116,111,108,117, - 97, 95,116, 97,103, 41, 10, 10, 10,102,117,110, 99,116,105, - 111,110, 32, 99,108, 97,115,115, 65,114,114, 97,121, 58,112, - 114,105,110,116, 32, 40,105,100,101,110,116, 44, 99,108,111, - 115,101, 41, 10,112,114,105,110,116, 40,105,100,101,110,116, - 46, 46, 34, 65,114,114, 97,121,123, 34, 41, 10,112,114,105, - 110,116, 40,105,100,101,110,116, 46, 46, 34, 32,109,111,100, - 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46,109,111,100, - 46, 46, 34, 39, 44, 34, 41, 10,112,114,105,110,116, 40,105, - 100,101,110,116, 46, 46, 34, 32,116,121,112,101, 32, 61, 32, - 39, 34, 46, 46,115,101,108,102, 46,116,121,112,101, 46, 46, - 34, 39, 44, 34, 41, 10,112,114,105,110,116, 40,105,100,101, - 110,116, 46, 46, 34, 32,112,116,114, 32, 61, 32, 39, 34, 46, - 46,115,101,108,102, 46,112,116,114, 46, 46, 34, 39, 44, 34, - 41, 10,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, - 34, 32,110, 97,109,101, 32, 61, 32, 39, 34, 46, 46,115,101, - 108,102, 46,110, 97,109,101, 46, 46, 34, 39, 44, 34, 41, 10, - 112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32, - 100,101,102, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46, - 100,101,102, 46, 46, 34, 39, 44, 34, 41, 10,112,114,105,110, - 116, 40,105,100,101,110,116, 46, 46, 34, 32,100,105,109, 32, - 61, 32, 39, 34, 46, 46,115,101,108,102, 46,100,105,109, 46, - 46, 34, 39, 44, 34, 41, 10,112,114,105,110,116, 40,105,100, - 101,110,116, 46, 46, 34, 32,114,101,116, 32, 61, 32, 39, 34, - 46, 46,115,101,108,102, 46,114,101,116, 46, 46, 34, 39, 44, - 34, 41, 10,112,114,105,110,116, 40,105,100,101,110,116, 46, - 46, 34,125, 34, 46, 46, 99,108,111,115,101, 41, 10,101,110, - 100, 10, 10, 10,102,117,110, 99,116,105,111,110, 32, 99,108, - 97,115,115, 65,114,114, 97,121, 58,103,101,116,118, 97,108, - 117,101, 32, 40, 99,108, 97,115,115, 44,115,116, 97,116,105, - 99, 41, 10,105,102, 32, 99,108, 97,115,115, 32, 97,110,100, - 32,115,116, 97,116,105, 99, 32,116,104,101,110, 10,114,101, - 116,117,114,110, 32, 99,108, 97,115,115, 46, 46, 39, 58, 58, - 39, 46, 46,115,101,108,102, 46,110, 97,109,101, 46, 46, 39, - 91,116,111,108,117, 97, 73, 95,105,110,100,101,120, 93, 39, - 10,101,108,115,101,105,102, 32, 99,108, 97,115,115, 32,116, - 104,101,110, 10,114,101,116,117,114,110, 32, 39,115,101,108, - 102, 45, 62, 39, 46, 46,115,101,108,102, 46,110, 97,109,101, - 46, 46, 39, 91,116,111,108,117, 97, 73, 95,105,110,100,101, - 120, 93, 39, 10,101,108,115,101, 10,114,101,116,117,114,110, - 32,115,101,108,102, 46,110, 97,109,101, 46, 46, 39, 91,116, - 111,108,117, 97, 73, 95,105,110,100,101,120, 93, 39, 10,101, - 110,100, 10,101,110,100, 10, 10, 10,102,117,110, 99,116,105, - 111,110, 32, 99,108, 97,115,115, 65,114,114, 97,121, 58,115, - 117,112, 99,111,100,101, 32, 40, 41, 10,108,111, 99, 97,108, - 32, 99,108, 97,115,115, 32, 61, 32,115,101,108,102, 58,105, - 110, 99,108, 97,115,115, 40, 41, 10, 10, 10,105,102, 32, 99, - 108, 97,115,115, 32,116,104,101,110, 10,111,117,116,112,117, - 116, 40, 34, 47, 42, 32,103,101,116, 32,102,117,110, 99,116, - 105,111,110, 58, 34, 44,115,101,108,102, 46,110, 97,109,101, - 44, 34, 32,111,102, 32, 99,108, 97,115,115, 32, 34, 44, 99, - 108, 97,115,115, 44, 34, 32, 42, 47, 34, 41, 10,101,108,115, - 101, 10,111,117,116,112,117,116, 40, 34, 47, 42, 32,103,101, - 116, 32,102,117,110, 99,116,105,111,110, 58, 34, 44,115,101, - 108,102, 46,110, 97,109,101, 44, 34, 32, 42, 47, 34, 41, 10, - 101,110,100, 10,115,101,108,102, 46, 99,103,101,116,110, 97, - 109,101, 32, 61, 32,115,101,108,102, 58, 99,102,117,110, 99, - 110, 97,109,101, 40, 34,116,111,108,117, 97, 73, 95,103,101, - 116, 34, 41, 10,111,117,116,112,117,116, 40, 34,115,116, 97, - 116,105, 99, 32,105,110,116, 34, 44,115,101,108,102, 46, 99, - 103,101,116,110, 97,109,101, 44, 34, 40,108,117, 97, 95, 83, - 116, 97,116,101, 42, 32,116,111,108,117, 97, 95, 83, 41, 34, - 41, 10,111,117,116,112,117,116, 40, 34,123, 34, 41, 10, 10, - 10,111,117,116,112,117,116, 40, 39, 32,105,110,116, 32,116, - 111,108,117, 97, 73, 95,105,110,100,101,120, 59, 39, 41, 10, - 10, 10,108,111, 99, 97,108, 32, 95, 44, 95, 44,115,116, 97, - 116,105, 99, 32, 61, 32,115,116,114,102,105,110,100, 40,115, - 101,108,102, 46,109,111,100, 44, 39, 94, 37,115, 42, 40,115, - 116, 97,116,105, 99, 41, 39, 41, 10,105,102, 32, 99,108, 97, - 115,115, 32, 97,110,100, 32,115,116, 97,116,105, 99, 61, 61, - 110,105,108, 32,116,104,101,110, 10,111,117,116,112,117,116, - 40, 39, 32, 39, 44, 99,108, 97,115,115, 44, 39, 42, 39, 44, - 39,115,101,108,102, 59, 39, 41, 10,111,117,116,112,117,116, - 40, 39, 32,108,117, 97, 95,112,117,115,104,115,116,114,105, - 110,103, 40,116,111,108,117, 97, 95, 83, 44, 34, 46,115,101, - 108,102, 34, 41, 59, 39, 41, 10,111,117,116,112,117,116, 40, - 39, 32,108,117, 97, 95,114, 97,119,103,101,116, 40,116,111, - 108,117, 97, 95, 83, 44, 49, 41, 59, 39, 41, 10,111,117,116, - 112,117,116, 40, 39, 32,115,101,108,102, 32, 61, 32, 39, 41, - 10,111,117,116,112,117,116, 40, 39, 40, 39, 44, 99,108, 97, - 115,115, 44, 39, 42, 41, 32, 39, 41, 10,111,117,116,112,117, - 116, 40, 39,108,117, 97, 95,116,111,117,115,101,114,100, 97, - 116, 97, 40,116,111,108,117, 97, 95, 83, 44, 45, 49, 41, 59, - 39, 41, 10,101,108,115,101,105,102, 32,115,116, 97,116,105, - 99, 32,116,104,101,110, 10, 95, 44, 95, 44,115,101,108,102, - 46,109,111,100, 32, 61, 32,115,116,114,102,105,110,100, 40, - 115,101,108,102, 46,109,111,100, 44, 39, 94, 37,115, 42,115, - 116, 97,116,105, 99, 37,115, 37,115, 42, 40, 46, 42, 41, 39, - 41, 10,101,110,100, 10, 10, 10,111,117,116,112,117,116, 40, - 39, 32,105,102, 32, 40, 33,116,111,108,117, 97, 95,105,115, - 116,121,112,101, 40,116,111,108,117, 97, 95, 83, 44, 50, 44, - 76, 85, 65, 95, 84, 78, 85, 77, 66, 69, 82, 44, 48, 41, 41, - 39, 41, 10,111,117,116,112,117,116, 40, 39, 32,116,111,108, - 117, 97, 95,101,114,114,111,114, 40,116,111,108,117, 97, 95, - 83, 44, 34,105,110,118, 97,108,105,100, 32,116,121,112,101, - 32,105,110, 32, 97,114,114, 97,121, 32,105,110,100,101,120, - 105,110,103, 46, 34, 41, 59, 39, 41, 10,111,117,116,112,117, - 116, 40, 39, 32,116,111,108,117, 97, 73, 95,105,110,100,101, - 120, 32, 61, 32, 40,105,110,116, 41,116,111,108,117, 97, 95, - 103,101,116,110,117,109, 98,101,114, 40,116,111,108,117, 97, - 95, 83, 44, 50, 44, 48, 41, 45, 49, 59, 39, 41, 10,111,117, - 116,112,117,116, 40, 39, 32,105,102, 32, 40,116,111,108,117, - 97, 73, 95,105,110,100,101,120, 60, 48, 32,124,124, 32,116, - 111,108,117, 97, 73, 95,105,110,100,101,120, 62, 61, 39, 46, - 46,115,101,108,102, 46,100,105,109, 46, 46, 39, 41, 39, 41, - 10,111,117,116,112,117,116, 40, 39, 32,116,111,108,117, 97, - 95,101,114,114,111,114, 40,116,111,108,117, 97, 95, 83, 44, - 34, 97,114,114, 97,121, 32,105,110,100,101,120,105,110,103, - 32,111,117,116, 32,111,102, 32,114, 97,110,103,101, 46, 34, - 41, 59, 39, 41, 10, 10, 10,108,111, 99, 97,108, 32,116, 44, - 99,116, 32, 61, 32,105,115, 98, 97,115,105, 99, 40,115,101, - 108,102, 46,116,121,112,101, 41, 10,105,102, 32,116, 32,116, - 104,101,110, 10,111,117,116,112,117,116, 40, 39, 32,116,111, - 108,117, 97, 95,112,117,115,104, 39, 46, 46,116, 46, 46, 39, - 40,116,111,108,117, 97, 95, 83, 44, 40, 39, 44, 99,116, 44, - 39, 41, 39, 46, 46,115,101,108,102, 58,103,101,116,118, 97, - 108,117,101, 40, 99,108, 97,115,115, 44,115,116, 97,116,105, - 99, 41, 46, 46, 39, 41, 59, 39, 41, 10,101,108,115,101, 10, - 105,102, 32,115,101,108,102, 46,112,116,114, 32, 61, 61, 32, - 39, 38, 39, 32,111,114, 32,115,101,108,102, 46,112,116,114, - 32, 61, 61, 32, 39, 39, 32,116,104,101,110, 10,111,117,116, - 112,117,116, 40, 39, 32,116,111,108,117, 97, 95,112,117,115, - 104,117,115,101,114,116,121,112,101, 40,116,111,108,117, 97, - 95, 83, 44, 40,118,111,105,100, 42, 41, 38, 39, 46, 46,115, - 101,108,102, 58,103,101,116,118, 97,108,117,101, 40, 99,108, - 97,115,115, 44,115,116, 97,116,105, 99, 41, 46, 46, 39, 44, - 39, 44,115,101,108,102, 46,116, 97,103, 44, 39, 41, 59, 39, - 41, 10,101,108,115,101, 10,111,117,116,112,117,116, 40, 39, - 32,116,111,108,117, 97, 95,112,117,115,104,117,115,101,114, - 116,121,112,101, 40,116,111,108,117, 97, 95, 83, 44, 40,118, - 111,105,100, 42, 41, 39, 46, 46,115,101,108,102, 58,103,101, - 116,118, 97,108,117,101, 40, 99,108, 97,115,115, 44,115,116, - 97,116,105, 99, 41, 46, 46, 39, 44, 39, 44,115,101,108,102, - 46,116, 97,103, 44, 39, 41, 59, 39, 41, 10,101,110,100, 10, - 101,110,100, 10,111,117,116,112,117,116, 40, 39, 32,114,101, - 116,117,114,110, 32, 49, 59, 39, 41, 10,111,117,116,112,117, - 116, 40, 39,125, 39, 41, 10,111,117,116,112,117,116, 40, 39, - 92,110, 39, 41, 10, 10, 10,105,102, 32,110,111,116, 32,115, - 116,114,102,105,110,100, 40,115,101,108,102, 46,109,111,100, - 44, 39, 99,111,110,115,116, 39, 41, 32,116,104,101,110, 10, - 105,102, 32, 99,108, 97,115,115, 32,116,104,101,110, 10,111, - 117,116,112,117,116, 40, 34, 47, 42, 32,115,101,116, 32,102, - 117,110, 99,116,105,111,110, 58, 34, 44,115,101,108,102, 46, - 110, 97,109,101, 44, 34, 32,111,102, 32, 99,108, 97,115,115, - 32, 34, 44, 99,108, 97,115,115, 44, 34, 32, 42, 47, 34, 41, - 10,101,108,115,101, 10,111,117,116,112,117,116, 40, 34, 47, - 42, 32,115,101,116, 32,102,117,110, 99,116,105,111,110, 58, - 34, 44,115,101,108,102, 46,110, 97,109,101, 44, 34, 32, 42, - 47, 34, 41, 10,101,110,100, 10,115,101,108,102, 46, 99,115, - 101,116,110, 97,109,101, 32, 61, 32,115,101,108,102, 58, 99, - 102,117,110, 99,110, 97,109,101, 40, 34,116,111,108,117, 97, - 73, 95,115,101,116, 34, 41, 10,111,117,116,112,117,116, 40, - 34,115,116, 97,116,105, 99, 32,105,110,116, 34, 44,115,101, - 108,102, 46, 99,115,101,116,110, 97,109,101, 44, 34, 40,108, - 117, 97, 95, 83,116, 97,116,101, 42, 32,116,111,108,117, 97, - 95, 83, 41, 34, 41, 10,111,117,116,112,117,116, 40, 34,123, - 34, 41, 10, 10, 10,111,117,116,112,117,116, 40, 39, 32,105, - 110,116, 32,116,111,108,117, 97, 73, 95,105,110,100,101,120, - 59, 39, 41, 10, 10, 10,108,111, 99, 97,108, 32, 95, 44, 95, - 44,115,116, 97,116,105, 99, 32, 61, 32,115,116,114,102,105, - 110,100, 40,115,101,108,102, 46,109,111,100, 44, 39, 94, 37, - 115, 42, 40,115,116, 97,116,105, 99, 41, 39, 41, 10,105,102, - 32, 99,108, 97,115,115, 32, 97,110,100, 32,115,116, 97,116, - 105, 99, 61, 61,110,105,108, 32,116,104,101,110, 10,111,117, - 116,112,117,116, 40, 39, 32, 39, 44, 99,108, 97,115,115, 44, - 39, 42, 39, 44, 39,115,101,108,102, 59, 39, 41, 10,111,117, - 116,112,117,116, 40, 39, 32,108,117, 97, 95,112,117,115,104, - 115,116,114,105,110,103, 40,116,111,108,117, 97, 95, 83, 44, - 34, 46,115,101,108,102, 34, 41, 59, 39, 41, 10,111,117,116, - 112,117,116, 40, 39, 32,108,117, 97, 95,114, 97,119,103,101, - 116, 40,116,111,108,117, 97, 95, 83, 44, 49, 41, 59, 39, 41, - 10,111,117,116,112,117,116, 40, 39, 32,115,101,108,102, 32, - 61, 32, 39, 41, 10,111,117,116,112,117,116, 40, 39, 40, 39, - 44, 99,108, 97,115,115, 44, 39, 42, 41, 32, 39, 41, 10,111, - 117,116,112,117,116, 40, 39,108,117, 97, 95,116,111,117,115, - 101,114,100, 97,116, 97, 40,116,111,108,117, 97, 95, 83, 44, - 45, 49, 41, 59, 39, 41, 10,101,108,115,101,105,102, 32,115, - 116, 97,116,105, 99, 32,116,104,101,110, 10, 95, 44, 95, 44, - 115,101,108,102, 46,109,111,100, 32, 61, 32,115,116,114,102, - 105,110,100, 40,115,101,108,102, 46,109,111,100, 44, 39, 94, - 37,115, 42,115,116, 97,116,105, 99, 37,115, 37,115, 42, 40, - 46, 42, 41, 39, 41, 10,101,110,100, 10, 10, 10,111,117,116, - 112,117,116, 40, 39, 32,105,102, 32, 40, 33,116,111,108,117, - 97, 95,105,115,116,121,112,101, 40,116,111,108,117, 97, 95, - 83, 44, 50, 44, 76, 85, 65, 95, 84, 78, 85, 77, 66, 69, 82, - 44, 48, 41, 41, 39, 41, 10,111,117,116,112,117,116, 40, 39, - 32,116,111,108,117, 97, 95,101,114,114,111,114, 40,116,111, - 108,117, 97, 95, 83, 44, 34,105,110,118, 97,108,105,100, 32, - 116,121,112,101, 32,105,110, 32, 97,114,114, 97,121, 32,105, - 110,100,101,120,105,110,103, 46, 34, 41, 59, 39, 41, 10,111, - 117,116,112,117,116, 40, 39, 32,116,111,108,117, 97, 73, 95, - 105,110,100,101,120, 32, 61, 32, 40,105,110,116, 41,116,111, - 108,117, 97, 95,103,101,116,110,117,109, 98,101,114, 40,116, - 111,108,117, 97, 95, 83, 44, 50, 44, 48, 41, 45, 49, 59, 39, - 41, 10,111,117,116,112,117,116, 40, 39, 32,105,102, 32, 40, - 116,111,108,117, 97, 73, 95,105,110,100,101,120, 60, 48, 32, - 124,124, 32,116,111,108,117, 97, 73, 95,105,110,100,101,120, - 62, 61, 39, 46, 46,115,101,108,102, 46,100,105,109, 46, 46, - 39, 41, 39, 41, 10,111,117,116,112,117,116, 40, 39, 32,116, - 111,108,117, 97, 95,101,114,114,111,114, 40,116,111,108,117, - 97, 95, 83, 44, 34, 97,114,114, 97,121, 32,105,110,100,101, - 120,105,110,103, 32,111,117,116, 32,111,102, 32,114, 97,110, - 103,101, 46, 34, 41, 59, 39, 41, 10, 10, 10,108,111, 99, 97, - 108, 32,112,116,114, 32, 61, 32, 39, 39, 10,105,102, 32,115, - 101,108,102, 46,112,116,114,126, 61, 39, 39, 32,116,104,101, - 110, 32,112,116,114, 32, 61, 32, 39, 42, 39, 32,101,110,100, - 10,111,117,116,112,117,116, 40, 39, 32, 39, 41, 10,105,102, - 32, 99,108, 97,115,115, 32, 97,110,100, 32,115,116, 97,116, - 105, 99, 32,116,104,101,110, 10,111,117,116,112,117,116, 40, - 99,108, 97,115,115, 46, 46, 39, 58, 58, 39, 46, 46,115,101, - 108,102, 46,110, 97,109,101, 46, 46, 39, 91,116,111,108,117, - 97, 73, 95,105,110,100,101,120, 93, 39, 41, 10,101,108,115, - 101,105,102, 32, 99,108, 97,115,115, 32,116,104,101,110, 10, - 111,117,116,112,117,116, 40, 39,115,101,108,102, 45, 62, 39, - 46, 46,115,101,108,102, 46,110, 97,109,101, 46, 46, 39, 91, - 116,111,108,117, 97, 73, 95,105,110,100,101,120, 93, 39, 41, - 10,101,108,115,101, 10,111,117,116,112,117,116, 40,115,101, - 108,102, 46,110, 97,109,101, 46, 46, 39, 91,116,111,108,117, - 97, 73, 95,105,110,100,101,120, 93, 39, 41, 10,101,110,100, - 10,108,111, 99, 97,108, 32,116, 32, 61, 32,105,115, 98, 97, - 115,105, 99, 40,115,101,108,102, 46,116,121,112,101, 41, 10, - 111,117,116,112,117,116, 40, 39, 32, 61, 32, 39, 41, 10,105, - 102, 32,110,111,116, 32,116, 32, 97,110,100, 32,112,116,114, - 61, 61, 39, 39, 32,116,104,101,110, 32,111,117,116,112,117, - 116, 40, 39, 42, 39, 41, 32,101,110,100, 10,111,117,116,112, - 117,116, 40, 39, 40, 40, 39, 44,115,101,108,102, 46,109,111, - 100, 44,115,101,108,102, 46,116,121,112,101, 41, 10,105,102, - 32,110,111,116, 32,116, 32,116,104,101,110, 10,111,117,116, - 112,117,116, 40, 39, 42, 39, 41, 10,101,110,100, 10,111,117, - 116,112,117,116, 40, 39, 41, 32, 39, 41, 10,108,111, 99, 97, - 108, 32,100,101,102, 32, 61, 32, 48, 10,105,102, 32,115,101, - 108,102, 46,100,101,102, 32,126, 61, 32, 39, 39, 32,116,104, - 101,110, 32,100,101,102, 32, 61, 32,115,101,108,102, 46,100, - 101,102, 32,101,110,100, 10,105,102, 32,116, 32,116,104,101, - 110, 10,111,117,116,112,117,116, 40, 39,116,111,108,117, 97, - 95,103,101,116, 39, 46, 46,116, 44, 39, 40,116,111,108,117, - 97, 95, 83, 44, 51, 44, 39, 44,100,101,102, 44, 39, 41, 41, - 59, 39, 41, 10,101,108,115,101, 10,111,117,116,112,117,116, - 40, 39,116,111,108,117, 97, 95,103,101,116,117,115,101,114, - 116,121,112,101, 40,116,111,108,117, 97, 95, 83, 44, 51, 44, - 39, 44,100,101,102, 44, 39, 41, 41, 59, 39, 41, 10,101,110, - 100, 10,111,117,116,112,117,116, 40, 39, 32,114,101,116,117, - 114,110, 32, 48, 59, 39, 41, 10,111,117,116,112,117,116, 40, - 39,125, 39, 41, 10,111,117,116,112,117,116, 40, 39, 92,110, - 39, 41, 10,101,110,100, 10, 10,101,110,100, 10, 10,102,117, - 110, 99,116,105,111,110, 32, 99,108, 97,115,115, 65,114,114, - 97,121, 58,114,101,103,105,115,116,101,114, 32, 40, 41, 10, - 108,111, 99, 97,108, 32,112, 97,114,101,110,116, 32, 61, 32, - 115,101,108,102, 58,105,110, 99,108, 97,115,115, 40, 41, 32, - 111,114, 32,115,101,108,102, 58,105,110,109,111,100,117,108, - 101, 40, 41, 10,105,102, 32,112, 97,114,101,110,116, 32,116, - 104,101,110, 10,105,102, 32,115,101,108,102, 46, 99,115,101, - 116,110, 97,109,101, 32,116,104,101,110, 10,111,117,116,112, - 117,116, 40, 39, 32,116,111,108,117, 97, 95,116, 97, 98,108, - 101, 97,114,114, 97,121, 40,116,111,108,117, 97, 95, 83, 44, - 34, 39, 46, 46,112, 97,114,101,110,116, 46, 46, 39, 34, 44, - 34, 39, 46, 46,115,101,108,102, 46,108,110, 97,109,101, 46, - 46, 39, 34, 44, 39, 46, 46,115,101,108,102, 46, 99,103,101, - 116,110, 97,109,101, 46, 46, 39, 44, 39, 46, 46,115,101,108, - 102, 46, 99,115,101,116,110, 97,109,101, 46, 46, 39, 41, 59, - 39, 41, 10,101,108,115,101, 10,111,117,116,112,117,116, 40, - 39, 32,116,111,108,117, 97, 95,116, 97, 98,108,101, 97,114, - 114, 97,121, 40,116,111,108,117, 97, 95, 83, 44, 34, 39, 46, - 46,112, 97,114,101,110,116, 46, 46, 39, 34, 44, 34, 39, 46, - 46,115,101,108,102, 46,108,110, 97,109,101, 46, 46, 39, 34, - 44, 39, 46, 46,115,101,108,102, 46, 99,103,101,116,110, 97, - 109,101, 46, 46, 39, 44, 78, 85, 76, 76, 41, 59, 39, 41, 10, - 101,110,100, 10,101,108,115,101, 10,105,102, 32,115,101,108, - 102, 46, 99,115,101,116,110, 97,109,101, 32,116,104,101,110, - 10,111,117,116,112,117,116, 40, 39, 32,116,111,108,117, 97, - 95,103,108,111, 98, 97,108, 97,114,114, 97,121, 40,116,111, - 108,117, 97, 95, 83, 44, 34, 39, 46, 46,115,101,108,102, 46, - 108,110, 97,109,101, 46, 46, 39, 34, 44, 39, 46, 46,115,101, - 108,102, 46, 99,103,101,116,110, 97,109,101, 46, 46, 39, 44, - 39, 46, 46,115,101,108,102, 46, 99,115,101,116,110, 97,109, - 101, 46, 46, 39, 41, 59, 39, 41, 10,101,108,115,101, 10,111, - 117,116,112,117,116, 40, 39, 32,116,111,108,117, 97, 95,103, - 108,111, 98, 97,108, 97,114,114, 97,121, 40,116,111,108,117, - 97, 95, 83, 44, 34, 39, 46, 46,115,101,108,102, 46,108,110, - 97,109,101, 46, 46, 39, 34, 44, 39, 46, 46,115,101,108,102, - 46, 99,103,101,116,110, 97,109,101, 46, 46, 39, 44, 78, 85, - 76, 76, 41, 59, 39, 41, 10,101,110,100, 10,101,110,100, 10, - 101,110,100, 10, 10,102,117,110, 99,116,105,111,110, 32, 99, - 108, 97,115,115, 65,114,114, 97,121, 58,117,110,114,101,103, - 105,115,116,101,114, 32, 40, 41, 10,105,102, 32,115,101,108, - 102, 58,105,110, 99,108, 97,115,115, 40, 41, 61, 61,110,105, - 108, 32, 97,110,100, 32,115,101,108,102, 58,105,110,109,111, - 100,117,108,101, 40, 41, 61, 61,110,105,108, 32,116,104,101, - 110, 10,111,117,116,112,117,116, 40, 39, 32,108,117, 97, 95, - 112,117,115,104,110,105,108, 40,116,111,108,117, 97, 95, 83, - 41, 59, 32,108,117, 97, 95,115,101,116,103,108,111, 98, 97, - 108, 40,116,111,108,117, 97, 95, 83, 44, 34, 39, 46, 46,115, - 101,108,102, 46,108,110, 97,109,101, 46, 46, 39, 34, 41, 59, - 39, 41, 10,101,110,100, 10,101,110,100, 10, 10, 10, 10,102, - 117,110, 99,116,105,111,110, 32, 95, 65,114,114, 97,121, 32, - 40,116, 41, 10,116, 46, 95, 98, 97,115,101, 32, 61, 32, 99, - 108, 97,115,115, 65,114,114, 97,121, 10,115,101,116,116, 97, - 103, 40,116, 44,116,111,108,117, 97, 95,116, 97,103, 41, 10, - 97,112,112,101,110,100, 40,116, 41, 10,114,101,116,117,114, - 110, 32,116, 10,101,110,100, 10, 10, 10, 10,102,117,110, 99, - 116,105,111,110, 32, 65,114,114, 97,121, 32, 40,115, 41, 10, - 114,101,116,117,114,110, 32, 95, 65,114,114, 97,121, 32, 40, - 68,101, 99,108, 97,114, 97,116,105,111,110, 40,115, 44, 39, - 118, 97,114, 39, 41, 41, 10,101,110,100, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 99,108, 97,115,115, 70,117,110, 99,116,105,111, - 110, 32, 61, 32,123, 10,109,111,100, 32, 61, 32, 39, 39, 44, - 10,116,121,112,101, 32, 61, 32, 39, 39, 44, 10,112,116,114, - 32, 61, 32, 39, 39, 44, 10,110, 97,109,101, 32, 61, 32, 39, - 39, 44, 10, 97,114,103,115, 32, 61, 32,123,110, 61, 48,125, - 44, 10, 99,111,110,115,116, 32, 61, 32, 39, 39, 44, 10, 95, - 98, 97,115,101, 32, 61, 32, 99,108, 97,115,115, 70,101, 97, - 116,117,114,101, 44, 10,125, 10,115,101,116,116, 97,103, 40, - 99,108, 97,115,115, 70,117,110, 99,116,105,111,110, 44,116, - 111,108,117, 97, 95,116, 97,103, 41, 10, 10, 10,102,117,110, - 99,116,105,111,110, 32, 99,108, 97,115,115, 70,117,110, 99, - 116,105,111,110, 58,100,101, 99,108,116, 97,103, 32, 40, 41, - 10,115,101,108,102, 46,105,116,121,112,101, 44,115,101,108, - 102, 46,116, 97,103, 32, 61, 32,116, 97,103,118, 97,114, 40, - 115,101,108,102, 46,116,121,112,101, 44,115,116,114,102,105, - 110,100, 40,115,101,108,102, 46,109,111,100, 44, 39, 99,111, - 110,115,116, 39, 41, 41, 10,108,111, 99, 97,108, 32,105, 61, - 49, 10,119,104,105,108,101, 32,115,101,108,102, 46, 97,114, - 103,115, 91,105, 93, 32,100,111, 10,115,101,108,102, 46, 97, - 114,103,115, 91,105, 93, 58,100,101, 99,108,116, 97,103, 40, - 41, 10,105, 32, 61, 32,105, 43, 49, 10,101,110,100, 10,101, - 110,100, 10, 10, 10, 10, 10,102,117,110, 99,116,105,111,110, - 32, 99,108, 97,115,115, 70,117,110, 99,116,105,111,110, 58, - 115,117,112, 99,111,100,101, 32, 40, 41, 10,108,111, 99, 97, - 108, 32,110,114,101,116, 32, 61, 32, 48, 10,108,111, 99, 97, - 108, 32, 99,108, 97,115,115, 32, 61, 32,115,101,108,102, 58, - 105,110, 99,108, 97,115,115, 40, 41, 10,108,111, 99, 97,108, - 32, 95, 44, 95, 44,115,116, 97,116,105, 99, 32, 61, 32,115, - 116,114,102,105,110,100, 40,115,101,108,102, 46,109,111,100, - 44, 39, 94, 37,115, 42, 40,115,116, 97,116,105, 99, 41, 39, - 41, 10, 10,105,102, 32, 99,108, 97,115,115, 32,116,104,101, - 110, 10,111,117,116,112,117,116, 40, 34, 47, 42, 32,109,101, - 116,104,111,100, 58, 34, 44,115,101,108,102, 46,110, 97,109, - 101, 44, 34, 32,111,102, 32, 99,108, 97,115,115, 32, 34, 44, - 99,108, 97,115,115, 44, 34, 32, 42, 47, 34, 41, 10,101,108, - 115,101, 10,111,117,116,112,117,116, 40, 34, 47, 42, 32,102, - 117,110, 99,116,105,111,110, 58, 34, 44,115,101,108,102, 46, - 110, 97,109,101, 44, 34, 32, 42, 47, 34, 41, 10,101,110,100, - 10,111,117,116,112,117,116, 40, 34,115,116, 97,116,105, 99, - 32,105,110,116, 34, 44,115,101,108,102, 46, 99,110, 97,109, - 101, 44, 34, 40,108,117, 97, 95, 83,116, 97,116,101, 42, 32, - 116,111,108,117, 97, 95, 83, 41, 34, 41, 10,111,117,116,112, - 117,116, 40, 34,123, 34, 41, 10, 10, 10,111,117,116,112,117, - 116, 40, 39, 32,105,102, 32, 40, 92,110, 39, 41, 10, 10,108, - 111, 99, 97,108, 32,110, 97,114,103, 10,105,102, 32, 99,108, - 97,115,115, 32,116,104,101,110, 32,110, 97,114,103, 61, 50, - 32,101,108,115,101, 32,110, 97,114,103, 61, 49, 32,101,110, - 100, 10,105,102, 32, 99,108, 97,115,115, 32, 97,110,100, 32, - 115,101,108,102, 46,110, 97,109,101,126, 61, 39,110,101,119, - 39, 32, 97,110,100, 32,115,116, 97,116,105, 99, 61, 61,110, - 105,108, 32,116,104,101,110, 10,105,102, 32,115,101,108,102, - 46, 99,111,110,115,116, 32, 61, 61, 32, 39, 99,111,110,115, - 116, 39, 32,116,104,101,110, 10,111,117,116,112,117,116, 40, - 39, 32, 33,116,111,108,117, 97, 95,105,115,116,121,112,101, - 40,116,111,108,117, 97, 95, 83, 44, 49, 44, 39, 44,115,101, - 108,102, 46,112, 97,114,101,110,116, 46, 99,116, 97,103, 44, - 39, 44, 48, 41, 32,124,124, 92,110, 39, 41, 10,101,108,115, - 101, 10,111,117,116,112,117,116, 40, 39, 32, 33,116,111,108, - 117, 97, 95,105,115,116,121,112,101, 40,116,111,108,117, 97, - 95, 83, 44, 49, 44, 39, 44,115,101,108,102, 46,112, 97,114, - 101,110,116, 46,116, 97,103, 44, 39, 44, 48, 41, 32,124,124, - 92,110, 39, 41, 10,101,110,100, 10,101,110,100, 10, 10,105, - 102, 32,115,101,108,102, 46, 97,114,103,115, 91, 49, 93, 46, - 116,121,112,101, 32,126, 61, 32, 39,118,111,105,100, 39, 32, - 116,104,101,110, 10,108,111, 99, 97,108, 32,105, 61, 49, 10, - 119,104,105,108,101, 32,115,101,108,102, 46, 97,114,103,115, - 91,105, 93, 32,100,111, 10,105,102, 32,105,115, 98, 97,115, - 105, 99, 40,115,101,108,102, 46, 97,114,103,115, 91,105, 93, - 46,116,121,112,101, 41, 32,126, 61, 32, 39,118, 97,108,117, - 101, 39, 32,116,104,101,110, 10,111,117,116,112,117,116, 40, - 39, 32, 33, 39, 46, 46,115,101,108,102, 46, 97,114,103,115, - 91,105, 93, 58,111,117,116, 99,104,101, 99,107,116,121,112, - 101, 40,110, 97,114,103, 41, 46, 46, 39, 32,124,124, 92,110, - 39, 41, 10,101,110,100, 10,110, 97,114,103, 32, 61, 32,110, - 97,114,103, 43, 49, 10,105, 32, 61, 32,105, 43, 49, 10,101, - 110,100, 10,101,110,100, 10, 10,111,117,116,112,117,116, 40, - 39, 32, 33,116,111,108,117, 97, 95,105,115,110,111,111, 98, - 106, 40,116,111,108,117, 97, 95, 83, 44, 39, 46, 46,110, 97, - 114,103, 46, 46, 39, 41, 92,110, 32, 41, 92,110, 32,103,111, - 116,111, 32,116,111,108,117, 97, 95,108,101,114,114,111,114, - 59, 39, 41, 10, 10,111,117,116,112,117,116, 40, 39, 32,101, - 108,115,101, 92,110, 32,123, 39, 41, 10, 10, 10,108,111, 99, - 97,108, 32,110, 97,114,103, 10,105,102, 32, 99,108, 97,115, - 115, 32,116,104,101,110, 32,110, 97,114,103, 61, 50, 32,101, - 108,115,101, 32,110, 97,114,103, 61, 49, 32,101,110,100, 10, - 105,102, 32, 99,108, 97,115,115, 32, 97,110,100, 32,115,101, - 108,102, 46,110, 97,109,101,126, 61, 39,110,101,119, 39, 32, - 97,110,100, 32,115,116, 97,116,105, 99, 61, 61,110,105,108, - 32,116,104,101,110, 10,111,117,116,112,117,116, 40, 39, 32, - 39, 44,115,101,108,102, 46, 99,111,110,115,116, 44, 99,108, - 97,115,115, 44, 39, 42, 39, 44, 39,115,101,108,102, 32, 61, - 32, 39, 41, 10,111,117,116,112,117,116, 40, 39, 40, 39, 44, - 115,101,108,102, 46, 99,111,110,115,116, 44, 99,108, 97,115, - 115, 44, 39, 42, 41, 32, 39, 41, 10,111,117,116,112,117,116, - 40, 39,116,111,108,117, 97, 95,103,101,116,117,115,101,114, - 116,121,112,101, 40,116,111,108,117, 97, 95, 83, 44, 49, 44, - 48, 41, 59, 39, 41, 10,101,108,115,101,105,102, 32,115,116, - 97,116,105, 99, 32,116,104,101,110, 10, 95, 44, 95, 44,115, - 101,108,102, 46,109,111,100, 32, 61, 32,115,116,114,102,105, - 110,100, 40,115,101,108,102, 46,109,111,100, 44, 39, 94, 37, - 115, 42,115,116, 97,116,105, 99, 37,115, 37,115, 42, 40, 46, - 42, 41, 39, 41, 10,101,110,100, 10, 10,105,102, 32,115,101, - 108,102, 46, 97,114,103,115, 91, 49, 93, 46,116,121,112,101, - 32,126, 61, 32, 39,118,111,105,100, 39, 32,116,104,101,110, - 10,108,111, 99, 97,108, 32,105, 61, 49, 10,119,104,105,108, - 101, 32,115,101,108,102, 46, 97,114,103,115, 91,105, 93, 32, - 100,111, 10,115,101,108,102, 46, 97,114,103,115, 91,105, 93, - 58,100,101, 99,108, 97,114,101, 40,110, 97,114,103, 41, 10, - 110, 97,114,103, 32, 61, 32,110, 97,114,103, 43, 49, 10,105, - 32, 61, 32,105, 43, 49, 10,101,110,100, 10,101,110,100, 10, - 10, 10,105,102, 32, 99,108, 97,115,115, 32, 97,110,100, 32, - 115,101,108,102, 46,110, 97,109,101,126, 61, 39,110,101,119, - 39, 32, 97,110,100, 32,115,116, 97,116,105, 99, 61, 61,110, - 105,108, 32,116,104,101,110, 10,111,117,116,112,117,116, 40, - 39, 32,105,102, 32, 40, 33,115,101,108,102, 41, 32,116,111, - 108,117, 97, 95,101,114,114,111,114, 40,116,111,108,117, 97, - 95, 83, 44, 34,105,110,118, 97,108,105,100, 32, 92, 39,115, - 101,108,102, 92, 39, 32,105,110, 32,102,117,110, 99,116,105, - 111,110, 32, 92, 39, 39, 46, 46,115,101,108,102, 46,110, 97, - 109,101, 46, 46, 39, 92, 39, 34, 41, 59, 39, 41, 59, 10,101, - 110,100, 10, 10, 10,105,102, 32, 99,108, 97,115,115, 32,116, - 104,101,110, 32,110, 97,114,103, 61, 50, 32,101,108,115,101, - 32,110, 97,114,103, 61, 49, 32,101,110,100, 10,105,102, 32, - 115,101,108,102, 46, 97,114,103,115, 91, 49, 93, 46,116,121, - 112,101, 32,126, 61, 32, 39,118,111,105,100, 39, 32,116,104, - 101,110, 10,108,111, 99, 97,108, 32,105, 61, 49, 10,119,104, - 105,108,101, 32,115,101,108,102, 46, 97,114,103,115, 91,105, - 93, 32,100,111, 10,115,101,108,102, 46, 97,114,103,115, 91, - 105, 93, 58,103,101,116, 97,114,114, 97,121, 40,110, 97,114, - 103, 41, 10,110, 97,114,103, 32, 61, 32,110, 97,114,103, 43, - 49, 10,105, 32, 61, 32,105, 43, 49, 10,101,110,100, 10,101, - 110,100, 10, 10, 10,105,102, 32, 99,108, 97,115,115, 32, 97, - 110,100, 32,115,101,108,102, 46,110, 97,109,101, 61, 61, 39, - 100,101,108,101,116,101, 39, 32,116,104,101,110, 10,111,117, - 116,112,117,116, 40, 39, 32,100,101,108,101,116,101, 32,115, - 101,108,102, 59, 39, 41, 10,101,108,115,101,105,102, 32, 99, - 108, 97,115,115, 32, 97,110,100, 32,115,101,108,102, 46,110, - 97,109,101, 32, 61, 61, 32, 39,111,112,101,114, 97,116,111, - 114, 38, 91, 93, 39, 32,116,104,101,110, 10,111,117,116,112, - 117,116, 40, 39, 32,115,101,108,102, 45, 62,111,112,101,114, - 97,116,111,114, 91, 93, 40, 39, 44,115,101,108,102, 46, 97, - 114,103,115, 91, 49, 93, 46,110, 97,109,101, 44, 39, 41, 32, - 61, 32, 39, 44,115,101,108,102, 46, 97,114,103,115, 91, 50, - 93, 46,110, 97,109,101, 44, 39, 59, 39, 41, 10,101,108,115, - 101, 10,111,117,116,112,117,116, 40, 39, 32,123, 39, 41, 10, - 105,102, 32,115,101,108,102, 46,116,121,112,101, 32,126, 61, - 32, 39, 39, 32, 97,110,100, 32,115,101,108,102, 46,116,121, - 112,101, 32,126, 61, 32, 39,118,111,105,100, 39, 32,116,104, - 101,110, 10,111,117,116,112,117,116, 40, 39, 32, 39, 44,115, - 101,108,102, 46,109,111,100, 44,115,101,108,102, 46,116,121, - 112,101, 44,115,101,108,102, 46,112,116,114, 44, 39,116,111, - 108,117, 97, 73, 95,114,101,116, 32, 61, 32, 39, 41, 10,111, - 117,116,112,117,116, 40, 39, 40, 39, 44,115,101,108,102, 46, - 109,111,100, 44,115,101,108,102, 46,116,121,112,101, 44,115, - 101,108,102, 46,112,116,114, 44, 39, 41, 32, 39, 41, 10,101, - 108,115,101, 10,111,117,116,112,117,116, 40, 39, 32, 39, 41, - 10,101,110,100, 10,105,102, 32, 99,108, 97,115,115, 32, 97, - 110,100, 32,115,101,108,102, 46,110, 97,109,101, 61, 61, 39, - 110,101,119, 39, 32,116,104,101,110, 10,111,117,116,112,117, - 116, 40, 39,110,101,119, 39, 44, 99,108, 97,115,115, 44, 39, - 40, 39, 41, 10,101,108,115,101,105,102, 32, 99,108, 97,115, - 115, 32, 97,110,100, 32,115,116, 97,116,105, 99, 32,116,104, - 101,110, 10,111,117,116,112,117,116, 40, 99,108, 97,115,115, - 46, 46, 39, 58, 58, 39, 46, 46,115,101,108,102, 46,110, 97, - 109,101, 44, 39, 40, 39, 41, 10,101,108,115,101,105,102, 32, - 99,108, 97,115,115, 32,116,104,101,110, 10,111,117,116,112, - 117,116, 40, 39,115,101,108,102, 45, 62, 39, 46, 46,115,101, - 108,102, 46,110, 97,109,101, 44, 39, 40, 39, 41, 10,101,108, - 115,101, 10,111,117,116,112,117,116, 40,115,101,108,102, 46, - 110, 97,109,101, 44, 39, 40, 39, 41, 10,101,110,100, 10, 10, - 10,108,111, 99, 97,108, 32,105, 61, 49, 10,119,104,105,108, - 101, 32,115,101,108,102, 46, 97,114,103,115, 91,105, 93, 32, - 100,111, 10,115,101,108,102, 46, 97,114,103,115, 91,105, 93, - 58,112, 97,115,115,112, 97,114, 40, 41, 10,105, 32, 61, 32, - 105, 43, 49, 10,105,102, 32,115,101,108,102, 46, 97,114,103, - 115, 91,105, 93, 32,116,104,101,110, 10,111,117,116,112,117, - 116, 40, 39, 44, 39, 41, 10,101,110,100, 10,101,110,100, 10, - 10,111,117,116,112,117,116, 40, 39, 41, 59, 39, 41, 10, 10, - 10,105,102, 32,115,101,108,102, 46,116,121,112,101, 32,126, - 61, 32, 39, 39, 32, 97,110,100, 32,115,101,108,102, 46,116, - 121,112,101, 32,126, 61, 32, 39,118,111,105,100, 39, 32,116, - 104,101,110, 10,110,114,101,116, 32, 61, 32,110,114,101,116, - 32, 43, 32, 49, 10,108,111, 99, 97,108, 32,116, 44, 99,116, - 32, 61, 32,105,115, 98, 97,115,105, 99, 40,115,101,108,102, - 46,116,121,112,101, 41, 10,105,102, 32,116, 32,116,104,101, - 110, 10,111,117,116,112,117,116, 40, 39, 32,116,111,108,117, - 97, 95,112,117,115,104, 39, 46, 46,116, 46, 46, 39, 40,116, - 111,108,117, 97, 95, 83, 44, 40, 39, 44, 99,116, 44, 39, 41, - 116,111,108,117, 97, 73, 95,114,101,116, 41, 59, 39, 41, 10, - 101,108,115,101, 10,105,102, 32,115,101,108,102, 46,112,116, - 114, 32, 61, 61, 32, 39, 39, 32,116,104,101,110, 10,111,117, - 116,112,117,116, 40, 39, 32,123, 39, 41, 10,111,117,116,112, - 117,116, 40, 39, 35,105,102,100,101,102, 32, 95, 95, 99,112, - 108,117,115,112,108,117,115, 92,110, 39, 41, 10,111,117,116, - 112,117,116, 40, 39, 32,118,111,105,100, 42, 32,116,111,108, - 117, 97, 73, 95, 99,108,111,110,101, 32, 61, 32,110,101,119, - 39, 44,115,101,108,102, 46,116,121,112,101, 44, 39, 40,116, - 111,108,117, 97, 73, 95,114,101,116, 41, 59, 39, 41, 10,111, - 117,116,112,117,116, 40, 39, 35,101,108,115,101, 92,110, 39, - 41, 10,111,117,116,112,117,116, 40, 39, 32,118,111,105,100, - 42, 32,116,111,108,117, 97, 73, 95, 99,108,111,110,101, 32, - 61, 32,116,111,108,117, 97, 95, 99,111,112,121, 40,116,111, - 108,117, 97, 95, 83, 44, 40,118,111,105,100, 42, 41, 38,116, - 111,108,117, 97, 73, 95,114,101,116, 44,115,105,122,101,111, - 102, 40, 39, 44,115,101,108,102, 46,116,121,112,101, 44, 39, - 41, 41, 59, 39, 41, 10,111,117,116,112,117,116, 40, 39, 35, - 101,110,100,105,102, 92,110, 39, 41, 10,111,117,116,112,117, - 116, 40, 39, 32,116,111,108,117, 97, 95,112,117,115,104,117, - 115,101,114,116,121,112,101, 40,116,111,108,117, 97, 95, 83, - 44,116,111,108,117, 97, 95,100,111, 99,108,111,110,101, 40, - 116,111,108,117, 97, 95, 83, 44,116,111,108,117, 97, 73, 95, - 99,108,111,110,101, 44, 39, 44,115,101,108,102, 46,116, 97, - 103, 44, 39, 41, 44, 39, 44,115,101,108,102, 46,116, 97,103, - 44, 39, 41, 59, 39, 41, 10,111,117,116,112,117,116, 40, 39, - 32,125, 39, 41, 10, 10,101,108,115,101,105,102, 32,115,101, - 108,102, 46,112,116,114, 32, 61, 61, 32, 39, 38, 39, 32,116, - 104,101,110, 10,111,117,116,112,117,116, 40, 39, 32,116,111, - 108,117, 97, 95,112,117,115,104,117,115,101,114,116,121,112, - 101, 40,116,111,108,117, 97, 95, 83, 44, 40,118,111,105,100, - 42, 41, 38,116,111,108,117, 97, 73, 95,114,101,116, 44, 39, - 44,115,101,108,102, 46,116, 97,103, 44, 39, 41, 59, 39, 41, - 10,101,108,115,101, 10,111,117,116,112,117,116, 40, 39, 32, - 116,111,108,117, 97, 95,112,117,115,104,117,115,101,114,116, - 121,112,101, 40,116,111,108,117, 97, 95, 83, 44, 40,118,111, - 105,100, 42, 41,116,111,108,117, 97, 73, 95,114,101,116, 44, - 39, 44,115,101,108,102, 46,116, 97,103, 44, 39, 41, 59, 39, - 41, 10,101,110,100, 10,101,110,100, 10,101,110,100, 10,108, - 111, 99, 97,108, 32,105, 61, 49, 10,119,104,105,108,101, 32, - 115,101,108,102, 46, 97,114,103,115, 91,105, 93, 32,100,111, - 10,110,114,101,116, 32, 61, 32,110,114,101,116, 32, 43, 32, - 115,101,108,102, 46, 97,114,103,115, 91,105, 93, 58,114,101, - 116,118, 97,108,117,101, 40, 41, 10,105, 32, 61, 32,105, 43, - 49, 10,101,110,100, 10,111,117,116,112,117,116, 40, 39, 32, - 125, 39, 41, 10, 10, 10,105,102, 32, 99,108, 97,115,115, 32, - 116,104,101,110, 32,110, 97,114,103, 61, 50, 32,101,108,115, - 101, 32,110, 97,114,103, 61, 49, 32,101,110,100, 10,105,102, - 32,115,101,108,102, 46, 97,114,103,115, 91, 49, 93, 46,116, - 121,112,101, 32,126, 61, 32, 39,118,111,105,100, 39, 32,116, - 104,101,110, 10,108,111, 99, 97,108, 32,105, 61, 49, 10,119, - 104,105,108,101, 32,115,101,108,102, 46, 97,114,103,115, 91, - 105, 93, 32,100,111, 10,115,101,108,102, 46, 97,114,103,115, - 91,105, 93, 58,115,101,116, 97,114,114, 97,121, 40,110, 97, - 114,103, 41, 10,110, 97,114,103, 32, 61, 32,110, 97,114,103, - 43, 49, 10,105, 32, 61, 32,105, 43, 49, 10,101,110,100, 10, - 101,110,100, 10, 10, 10,105,102, 32,115,101,108,102, 46, 97, - 114,103,115, 91, 49, 93, 46,116,121,112,101, 32,126, 61, 32, - 39,118,111,105,100, 39, 32,116,104,101,110, 10,108,111, 99, - 97,108, 32,105, 61, 49, 10,119,104,105,108,101, 32,115,101, - 108,102, 46, 97,114,103,115, 91,105, 93, 32,100,111, 10,115, - 101,108,102, 46, 97,114,103,115, 91,105, 93, 58,102,114,101, - 101, 97,114,114, 97,121, 40, 41, 10,105, 32, 61, 32,105, 43, - 49, 10,101,110,100, 10,101,110,100, 10,101,110,100, 10, 10, - 111,117,116,112,117,116, 40, 39, 32,125, 39, 41, 10,111,117, - 116,112,117,116, 40, 39, 32,114,101,116,117,114,110, 32, 39, - 46, 46,110,114,101,116, 46, 46, 39, 59, 39, 41, 10, 10, 10, - 111,117,116,112,117,116, 40, 39,116,111,108,117, 97, 95,108, - 101,114,114,111,114, 58, 92,110, 39, 41, 10,108,111, 99, 97, - 108, 32,111,118,101,114,108,111, 97,100, 32, 61, 32,115,116, - 114,115,117, 98, 40,115,101,108,102, 46, 99,110, 97,109,101, - 44, 45, 50, 44, 45, 49, 41, 32, 45, 32, 49, 10,105,102, 32, - 111,118,101,114,108,111, 97,100, 32, 62, 61, 32, 48, 32,116, - 104,101,110, 10,111,117,116,112,117,116, 40, 39, 32,114,101, - 116,117,114,110, 32, 39, 46, 46,115,116,114,115,117, 98, 40, - 115,101,108,102, 46, 99,110, 97,109,101, 44, 49, 44, 45, 51, - 41, 46, 46,102,111,114,109, 97,116, 40, 34, 37, 48, 50,100, - 34, 44,111,118,101,114,108,111, 97,100, 41, 46, 46, 39, 40, - 116,111,108,117, 97, 95, 83, 41, 59, 39, 41, 10,101,108,115, - 101, 10,111,117,116,112,117,116, 40, 39, 32,116,111,108,117, - 97, 95,101,114,114,111,114, 40,116,111,108,117, 97, 95, 83, - 44, 34, 35,102,101,114,114,111,114, 32,105,110, 32,102,117, - 110, 99,116,105,111,110, 32, 92, 39, 39, 46, 46,115,101,108, - 102, 46,108,110, 97,109,101, 46, 46, 39, 92, 39, 46, 34, 41, - 59, 39, 41, 10,111,117,116,112,117,116, 40, 39, 32,114,101, - 116,117,114,110, 32, 48, 59, 39, 41, 10,101,110,100, 10, 10, - 111,117,116,112,117,116, 40, 39,125, 39, 41, 10,111,117,116, - 112,117,116, 40, 39, 92,110, 39, 41, 10,101,110,100, 10, 10, - 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115,115, - 70,117,110, 99,116,105,111,110, 58,114,101,103,105,115,116, - 101,114, 32, 40, 41, 10,108,111, 99, 97,108, 32,112, 97,114, - 101,110,116, 32, 61, 32,115,101,108,102, 58,105,110, 99,108, - 97,115,115, 40, 41, 32,111,114, 32,115,101,108,102, 58,105, - 110,109,111,100,117,108,101, 40, 41, 10,105,102, 32,112, 97, - 114,101,110,116, 32,116,104,101,110, 10,111,117,116,112,117, - 116, 40, 39, 32,116,111,108,117, 97, 95,102,117,110, 99,116, - 105,111,110, 40,116,111,108,117, 97, 95, 83, 44, 34, 39, 46, - 46,112, 97,114,101,110,116, 46, 46, 39, 34, 44, 34, 39, 46, - 46,115,101,108,102, 46,108,110, 97,109,101, 46, 46, 39, 34, - 44, 39, 46, 46,115,101,108,102, 46, 99,110, 97,109,101, 46, - 46, 39, 41, 59, 39, 41, 10,101,108,115,101, 10,111,117,116, - 112,117,116, 40, 39, 32,116,111,108,117, 97, 95,102,117,110, - 99,116,105,111,110, 40,116,111,108,117, 97, 95, 83, 44, 78, - 85, 76, 76, 44, 34, 39, 46, 46,115,101,108,102, 46,108,110, - 97,109,101, 46, 46, 39, 34, 44, 39, 46, 46,115,101,108,102, - 46, 99,110, 97,109,101, 46, 46, 39, 41, 59, 39, 41, 10,101, - 110,100, 10,101,110,100, 10, 10, 10,102,117,110, 99,116,105, - 111,110, 32, 99,108, 97,115,115, 70,117,110, 99,116,105,111, - 110, 58,117,110,114,101,103,105,115,116,101,114, 32, 40, 41, - 10,105,102, 32,115,101,108,102, 58,105,110, 99,108, 97,115, - 115, 40, 41, 61, 61,110,105,108, 32, 97,110,100, 32,115,101, - 108,102, 58,105,110,109,111,100,117,108,101, 40, 41, 61, 61, - 110,105,108, 32,116,104,101,110, 10,111,117,116,112,117,116, - 40, 39, 32,108,117, 97, 95,112,117,115,104,110,105,108, 40, - 116,111,108,117, 97, 95, 83, 41, 59, 32,108,117, 97, 95,115, - 101,116,103,108,111, 98, 97,108, 40,116,111,108,117, 97, 95, - 83, 44, 34, 39, 46, 46,115,101,108,102, 46,108,110, 97,109, - 101, 46, 46, 39, 34, 41, 59, 39, 41, 10,101,110,100, 10,101, - 110,100, 10, 10, 10, 10,102,117,110, 99,116,105,111,110, 32, - 99,108, 97,115,115, 70,117,110, 99,116,105,111,110, 58,112, - 114,105,110,116, 32, 40,105,100,101,110,116, 44, 99,108,111, - 115,101, 41, 10,112,114,105,110,116, 40,105,100,101,110,116, - 46, 46, 34, 70,117,110, 99,116,105,111,110,123, 34, 41, 10, - 112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32, - 109,111,100, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46, - 109,111,100, 46, 46, 34, 39, 44, 34, 41, 10,112,114,105,110, - 116, 40,105,100,101,110,116, 46, 46, 34, 32,116,121,112,101, - 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46,116,121,112, - 101, 46, 46, 34, 39, 44, 34, 41, 10,112,114,105,110,116, 40, - 105,100,101,110,116, 46, 46, 34, 32,112,116,114, 32, 61, 32, - 39, 34, 46, 46,115,101,108,102, 46,112,116,114, 46, 46, 34, - 39, 44, 34, 41, 10,112,114,105,110,116, 40,105,100,101,110, - 116, 46, 46, 34, 32,110, 97,109,101, 32, 61, 32, 39, 34, 46, - 46,115,101,108,102, 46,110, 97,109,101, 46, 46, 34, 39, 44, - 34, 41, 10,112,114,105,110,116, 40,105,100,101,110,116, 46, - 46, 34, 32, 99,111,110,115,116, 32, 61, 32, 39, 34, 46, 46, - 115,101,108,102, 46, 99,111,110,115,116, 46, 46, 34, 39, 44, - 34, 41, 10,112,114,105,110,116, 40,105,100,101,110,116, 46, - 46, 34, 32, 99,110, 97,109,101, 32, 61, 32, 39, 34, 46, 46, - 115,101,108,102, 46, 99,110, 97,109,101, 46, 46, 34, 39, 44, - 34, 41, 10,112,114,105,110,116, 40,105,100,101,110,116, 46, - 46, 34, 32,108,110, 97,109,101, 32, 61, 32, 39, 34, 46, 46, - 115,101,108,102, 46,108,110, 97,109,101, 46, 46, 34, 39, 44, - 34, 41, 10,112,114,105,110,116, 40,105,100,101,110,116, 46, - 46, 34, 32, 97,114,103,115, 32, 61, 32,123, 34, 41, 10,108, - 111, 99, 97,108, 32,105, 61, 49, 10,119,104,105,108,101, 32, - 115,101,108,102, 46, 97,114,103,115, 91,105, 93, 32,100,111, - 10,115,101,108,102, 46, 97,114,103,115, 91,105, 93, 58,112, - 114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32, 34, - 44, 34, 44, 34, 41, 10,105, 32, 61, 32,105, 43, 49, 10,101, - 110,100, 10,112,114,105,110,116, 40,105,100,101,110,116, 46, - 46, 34, 32,125, 34, 41, 10,112,114,105,110,116, 40,105,100, - 101,110,116, 46, 46, 34,125, 34, 46, 46, 99,108,111,115,101, - 41, 10,101,110,100, 10, 10, 10,102,117,110, 99,116,105,111, - 110, 32, 99,108, 97,115,115, 70,117,110, 99,116,105,111,110, - 58,111,118,101,114,108,111, 97,100, 32, 40, 41, 10,114,101, - 116,117,114,110, 32,115,101,108,102, 46,112, 97,114,101,110, - 116, 58,111,118,101,114,108,111, 97,100, 40,115,101,108,102, - 46,108,110, 97,109,101, 41, 10,101,110,100, 10, 10, 10, 10, - 10,102,117,110, 99,116,105,111,110, 32, 95, 70,117,110, 99, - 116,105,111,110, 32, 40,116, 41, 10,116, 46, 95, 98, 97,115, - 101, 32, 61, 32, 99,108, 97,115,115, 70,117,110, 99,116,105, - 111,110, 10,115,101,116,116, 97,103, 40,116, 44,116,111,108, - 117, 97, 95,116, 97,103, 41, 10, 10,105,102, 32,116, 46, 99, - 111,110,115,116, 32,126, 61, 32, 39, 99,111,110,115,116, 39, - 32, 97,110,100, 32,116, 46, 99,111,110,115,116, 32,126, 61, - 32, 39, 39, 32,116,104,101,110, 10,101,114,114,111,114, 40, - 34, 35,105,110,118, 97,108,105,100, 32, 39, 99,111,110,115, - 116, 39, 32,115,112,101, 99,105,102,105, 99, 97,116,105,111, - 110, 34, 41, 10,101,110,100, 10, 10, 97,112,112,101,110,100, - 40,116, 41, 10,105,102, 32,116, 58,105,110, 99,108, 97,115, - 115, 40, 41, 32,116,104,101,110, 10,105,102, 32,116, 46,110, - 97,109,101, 32, 61, 61, 32,116, 46,112, 97,114,101,110,116, - 46,110, 97,109,101, 32,116,104,101,110, 10,116, 46,110, 97, - 109,101, 32, 61, 32, 39,110,101,119, 39, 10,116, 46,108,110, - 97,109,101, 32, 61, 32, 39,110,101,119, 39, 10,116, 46,116, - 121,112,101, 32, 61, 32,116, 46,112, 97,114,101,110,116, 46, - 110, 97,109,101, 10,116, 46,112,116,114, 32, 61, 32, 39, 42, - 39, 10,101,108,115,101,105,102, 32,116, 46,110, 97,109,101, - 32, 61, 61, 32, 39,126, 39, 46, 46,116, 46,112, 97,114,101, - 110,116, 46,110, 97,109,101, 32,116,104,101,110, 10,116, 46, - 110, 97,109,101, 32, 61, 32, 39,100,101,108,101,116,101, 39, - 10,116, 46,108,110, 97,109,101, 32, 61, 32, 39,100,101,108, - 101,116,101, 39, 10,101,110,100, 10,101,110,100, 10,116, 46, - 99,110, 97,109,101, 32, 61, 32,116, 58, 99,102,117,110, 99, - 110, 97,109,101, 40, 34,116,111,108,117, 97, 73, 34, 41, 46, - 46,116, 58,111,118,101,114,108,111, 97,100, 40,116, 41, 10, - 114,101,116,117,114,110, 32,116, 10,101,110,100, 10, 10, 10, - 10, 10, 10,102,117,110, 99,116,105,111,110, 32, 70,117,110, - 99,116,105,111,110, 32, 40,100, 44, 97, 44, 99, 41, 10,108, - 111, 99, 97,108, 32,116, 32, 61, 32,115,112,108,105,116, 40, - 115,116,114,115,117, 98, 40, 97, 44, 50, 44, 45, 50, 41, 44, - 39, 44, 39, 41, 10,108,111, 99, 97,108, 32,105, 61, 49, 10, - 108,111, 99, 97,108, 32,108, 32, 61, 32,123,110, 61, 48,125, - 10,119,104,105,108,101, 32,116, 91,105, 93, 32,100,111, 10, - 108, 46,110, 32, 61, 32,108, 46,110, 43, 49, 10,108, 91,108, - 46,110, 93, 32, 61, 32, 68,101, 99,108, 97,114, 97,116,105, - 111,110, 40,116, 91,105, 93, 44, 39,118, 97,114, 39, 41, 10, - 105, 32, 61, 32,105, 43, 49, 10,101,110,100, 10,108,111, 99, - 97,108, 32,102, 32, 61, 32, 68,101, 99,108, 97,114, 97,116, - 105,111,110, 40,100, 44, 39,102,117,110, 99, 39, 41, 10,102, - 46, 97,114,103,115, 32, 61, 32,108, 10,102, 46, 99,111,110, - 115,116, 32, 61, 32, 99, 10,114,101,116,117,114,110, 32, 95, - 70,117,110, 99,116,105,111,110, 40,102, 41, 10,101,110,100, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 99,108, 97,115,115, 79,112,101,114, 97,116, - 111,114, 32, 61, 32,123, 10,107,105,110,100, 32, 61, 32, 39, - 39, 44, 10, 95, 98, 97,115,101, 32, 61, 32, 99,108, 97,115, - 115, 70,117,110, 99,116,105,111,110, 44, 10,125, 10,115,101, - 116,116, 97,103, 40, 99,108, 97,115,115, 79,112,101,114, 97, - 116,111,114, 44,116,111,108,117, 97, 95,116, 97,103, 41, 10, - 10, 10, 95, 84, 77, 32, 61, 32,123, 91, 39, 43, 39, 93, 32, - 61, 32, 39,111,112,101,114, 97,116,111,114, 95, 97,100,100, - 39, 44, 10, 91, 39, 45, 39, 93, 32, 61, 32, 39,111,112,101, - 114, 97,116,111,114, 95,115,117, 98, 39, 44, 10, 91, 39, 42, - 39, 93, 32, 61, 32, 39,111,112,101,114, 97,116,111,114, 95, - 109,117,108, 39, 44, 10, 91, 39, 47, 39, 93, 32, 61, 32, 39, - 111,112,101,114, 97,116,111,114, 95,100,105,118, 39, 44, 10, - 91, 39, 60, 39, 93, 32, 61, 32, 39,111,112,101,114, 97,116, - 111,114, 95,108,116, 39, 44, 10, 91, 39, 91, 93, 39, 93, 32, - 61, 32, 39,111,112,101,114, 97,116,111,114, 95,103,101,116, - 39, 44, 10, 91, 39, 38, 91, 93, 39, 93, 32, 61, 32, 39,111, - 112,101,114, 97,116,111,114, 95,115,101,116, 39, 44, 10,125, - 10, 10, 10, 10,102,117,110, 99,116,105,111,110, 32, 99,108, - 97,115,115, 79,112,101,114, 97,116,111,114, 58,112,114,105, - 110,116, 32, 40,105,100,101,110,116, 44, 99,108,111,115,101, - 41, 10,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, - 34, 79,112,101,114, 97,116,111,114,123, 34, 41, 10,112,114, - 105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32,107,105, - 110,100, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, 46,107, - 105,110,100, 46, 46, 34, 39, 44, 34, 41, 10,112,114,105,110, - 116, 40,105,100,101,110,116, 46, 46, 34, 32,109,111,100, 32, - 61, 32, 39, 34, 46, 46,115,101,108,102, 46,109,111,100, 46, - 46, 34, 39, 44, 34, 41, 10,112,114,105,110,116, 40,105,100, - 101,110,116, 46, 46, 34, 32,116,121,112,101, 32, 61, 32, 39, - 34, 46, 46,115,101,108,102, 46,116,121,112,101, 46, 46, 34, - 39, 44, 34, 41, 10,112,114,105,110,116, 40,105,100,101,110, - 116, 46, 46, 34, 32,112,116,114, 32, 61, 32, 39, 34, 46, 46, - 115,101,108,102, 46,112,116,114, 46, 46, 34, 39, 44, 34, 41, - 10,112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, - 32,110, 97,109,101, 32, 61, 32, 39, 34, 46, 46,115,101,108, - 102, 46,110, 97,109,101, 46, 46, 34, 39, 44, 34, 41, 10,112, - 114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32, 99, - 111,110,115,116, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, - 46, 99,111,110,115,116, 46, 46, 34, 39, 44, 34, 41, 10,112, - 114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32, 99, - 110, 97,109,101, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, - 46, 99,110, 97,109,101, 46, 46, 34, 39, 44, 34, 41, 10,112, - 114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32,108, - 110, 97,109,101, 32, 61, 32, 39, 34, 46, 46,115,101,108,102, - 46,108,110, 97,109,101, 46, 46, 34, 39, 44, 34, 41, 10,112, - 114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32, 97, - 114,103,115, 32, 61, 32,123, 34, 41, 10,108,111, 99, 97,108, - 32,105, 61, 49, 10,119,104,105,108,101, 32,115,101,108,102, - 46, 97,114,103,115, 91,105, 93, 32,100,111, 10,115,101,108, - 102, 46, 97,114,103,115, 91,105, 93, 58,112,114,105,110,116, - 40,105,100,101,110,116, 46, 46, 34, 32, 34, 44, 34, 44, 34, - 41, 10,105, 32, 61, 32,105, 43, 49, 10,101,110,100, 10,112, - 114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 32,125, - 34, 41, 10,112,114,105,110,116, 40,105,100,101,110,116, 46, - 46, 34,125, 34, 46, 46, 99,108,111,115,101, 41, 10,101,110, - 100, 10, 10, 10,102,117,110, 99,116,105,111,110, 32, 95, 79, - 112,101,114, 97,116,111,114, 32, 40,116, 41, 10,116, 46, 95, - 98, 97,115,101, 32, 61, 32, 99,108, 97,115,115, 79,112,101, - 114, 97,116,111,114, 10,115,101,116,116, 97,103, 40,116, 44, - 116,111,108,117, 97, 95,116, 97,103, 41, 10, 10,105,102, 32, - 116, 46, 99,111,110,115,116, 32,126, 61, 32, 39, 99,111,110, - 115,116, 39, 32, 97,110,100, 32,116, 46, 99,111,110,115,116, - 32,126, 61, 32, 39, 39, 32,116,104,101,110, 10,101,114,114, - 111,114, 40, 34, 35,105,110,118, 97,108,105,100, 32, 39, 99, - 111,110,115,116, 39, 32,115,112,101, 99,105,102,105, 99, 97, - 116,105,111,110, 34, 41, 10,101,110,100, 10, 10, 97,112,112, - 101,110,100, 40,116, 41, 10,105,102, 32,110,111,116, 32,116, - 58,105,110, 99,108, 97,115,115, 40, 41, 32,116,104,101,110, - 10,101,114,114,111,114, 40, 34, 35,111,112,101,114, 97,116, - 111,114, 32, 99, 97,110, 32,111,110,108,121, 32, 98,101, 32, - 100,101,102,105,110,101,100, 32, 97,115, 32, 99,108, 97,115, - 115, 32,109,101,109, 98,101,114, 34, 41, 10,101,110,100, 10, - 10,116, 46, 99,110, 97,109,101, 32, 61, 32,116, 58, 99,102, - 117,110, 99,110, 97,109,101, 40, 34,116,111,108,117, 97, 73, - 34, 41, 46, 46,116, 58,111,118,101,114,108,111, 97,100, 40, - 116, 41, 10,116, 46,110, 97,109,101, 32, 61, 32,116, 46,110, - 97,109,101, 46, 46,116, 46,107,105,110,100, 10,114,101,116, - 117,114,110, 32,116, 10,101,110,100, 10, 10, 10, 10, 10, 10, - 102,117,110, 99,116,105,111,110, 32, 79,112,101,114, 97,116, - 111,114, 32, 40,100, 44,107, 44, 97, 44, 99, 41, 10,108,111, - 99, 97,108, 32,116, 32, 61, 32,115,112,108,105,116, 40,115, - 116,114,115,117, 98, 40, 97, 44, 50, 44,115,116,114,108,101, - 110, 40, 97, 41, 45, 49, 41, 44, 39, 44, 39, 41, 10,108,111, - 99, 97,108, 32,105, 61, 49, 10,108,111, 99, 97,108, 32,108, - 32, 61, 32,123,110, 61, 48,125, 10,119,104,105,108,101, 32, - 116, 91,105, 93, 32,100,111, 10,108, 46,110, 32, 61, 32,108, - 46,110, 43, 49, 10,108, 91,108, 46,110, 93, 32, 61, 32, 68, - 101, 99,108, 97,114, 97,116,105,111,110, 40,116, 91,105, 93, - 44, 39,118, 97,114, 39, 41, 10,105, 32, 61, 32,105, 43, 49, - 10,101,110,100, 10,105,102, 32,107, 32, 61, 61, 32, 39, 91, - 93, 39, 32,116,104,101,110, 10,100, 32, 61, 32,103,115,117, - 98, 40,100, 44, 39, 38, 39, 44, 39, 39, 41, 10,101,108,115, - 101,105,102, 32,107, 61, 61, 39, 38, 91, 93, 39, 32,116,104, - 101,110, 10,108, 46,110, 32, 61, 32,108, 46,110, 43, 49, 10, - 108, 91,108, 46,110, 93, 32, 61, 32, 68,101, 99,108, 97,114, - 97,116,105,111,110, 40,100, 44, 39,118, 97,114, 39, 41, 10, - 108, 91,108, 46,110, 93, 46,110, 97,109,101, 32, 61, 32, 39, - 116,111,108,117, 97, 73, 95,118, 97,108,117,101, 39, 10,101, - 110,100, 10,108,111, 99, 97,108, 32,102, 32, 61, 32, 68,101, - 99,108, 97,114, 97,116,105,111,110, 40,100, 44, 39,102,117, - 110, 99, 39, 41, 10,105,102, 32,107, 32, 61, 61, 32, 39, 91, - 93, 39, 32, 97,110,100, 32, 40,108, 91, 49, 93, 61, 61,110, - 105,108, 32,111,114, 32,105,115, 98, 97,115,105, 99, 40,108, - 91, 49, 93, 46,116,121,112,101, 41,126, 61, 39,110,117,109, - 98,101,114, 39, 41, 32,116,104,101,110, 10,101,114,114,111, - 114, 40, 39,111,112,101,114, 97,116,111,114, 91, 93, 32, 99, - 97,110, 32,111,110,108,121, 32, 98,101, 32,100,101,102,105, - 110,101,100, 32,102,111,114, 32,110,117,109,101,114,105, 99, - 32,105,110,100,101,120, 46, 39, 41, 10,101,110,100, 10,102, - 46, 97,114,103,115, 32, 61, 32,108, 10,102, 46, 99,111,110, - 115,116, 32, 61, 32, 99, 10,102, 46,107,105,110,100, 32, 61, - 32,103,115,117, 98, 40,107, 44, 34, 37,115, 34, 44, 34, 34, - 41, 10,102, 46,108,110, 97,109,101, 32, 61, 32, 95, 84, 77, - 91,102, 46,107,105,110,100, 93, 10,105,102, 32,110,111,116, - 32,102, 46,108,110, 97,109,101, 32,116,104,101,110, 10,101, - 114,114,111,114, 40, 34,116,111,108,117, 97, 58, 32,110,111, - 32,115,117,112,112,111,114,116, 32,102,111,114, 32,111,112, - 101,114, 97,116,111,114, 34, 32, 46, 46, 32,102, 46,107,105, - 110,100, 41, 10,101,110,100, 10,105,102, 32,102, 46,107,105, - 110,100, 32, 61, 61, 32, 39, 91, 93, 39, 32, 97,110,100, 32, - 110,111,116, 32,115,116,114,102,105,110,100, 40,102, 46,109, - 111,100, 44, 39, 99,111,110,115,116, 39, 41, 32,116,104,101, - 110, 10, 79,112,101,114, 97,116,111,114, 40,100, 44, 39, 38, - 39, 46, 46,107, 44, 97, 44, 99, 41, 10,101,110,100, 10,114, - 101,116,117,114,110, 32, 95, 79,112,101,114, 97,116,111,114, - 40,102, 41, 10,101,110,100, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 99,108, 97,115, - 115, 67,108, 97,115,115, 32, 61, 32,123, 10, 95, 98, 97,115, - 101, 32, 61, 32, 99,108, 97,115,115, 67,111,110,116, 97,105, - 110,101,114, 44, 10,116,121,112,101, 32, 61, 32, 39, 99,108, - 97,115,115, 39, 44, 10,110, 97,109,101, 32, 61, 32, 39, 39, - 44, 10, 98, 97,115,101, 32, 61, 32, 39, 39, 44, 10,125, 10, - 115,101,116,116, 97,103, 40, 99,108, 97,115,115, 67,108, 97, - 115,115, 44,116,111,108,117, 97, 95,116, 97,103, 41, 10, 10, - 10, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97,115, - 115, 67,108, 97,115,115, 58,114,101,103,105,115,116,101,114, - 32, 40, 41, 10,111,117,116,112,117,116, 40, 39, 32,116,111, - 108,117, 97, 95, 99, 99,108, 97,115,115, 40,116,111,108,117, - 97, 95, 83, 44, 34, 39, 46, 46,115,101,108,102, 46,110, 97, - 109,101, 46, 46, 39, 34, 44, 34, 39, 46, 46,115,101,108,102, - 46, 98, 97,115,101, 46, 46, 39, 34, 41, 59, 39, 41, 10,108, - 111, 99, 97,108, 32,105, 61, 49, 10,119,104,105,108,101, 32, - 115,101,108,102, 91,105, 93, 32,100,111, 10,115,101,108,102, - 91,105, 93, 58,114,101,103,105,115,116,101,114, 40, 41, 10, - 105, 32, 61, 32,105, 43, 49, 10,101,110,100, 10,101,110,100, - 10, 10, 10,102,117,110, 99,116,105,111,110, 32, 99,108, 97, - 115,115, 67,108, 97,115,115, 58,117,110,114,101,103,105,115, - 116,101,114, 32, 40, 41, 10,111,117,116,112,117,116, 40, 39, - 32,108,117, 97, 95,112,117,115,104,110,105,108, 40,116,111, - 108,117, 97, 95, 83, 41, 59, 32,108,117, 97, 95,115,101,116, - 103,108,111, 98, 97,108, 40,116,111,108,117, 97, 95, 83, 44, - 34, 39, 46, 46,115,101,108,102, 46,110, 97,109,101, 46, 46, - 39, 34, 41, 59, 39, 41, 10,101,110,100, 10, 10, 10,102,117, - 110, 99,116,105,111,110, 32, 99,108, 97,115,115, 67,108, 97, - 115,115, 58,100,101, 99,108,116, 97,103, 32, 40, 41, 10,115, - 101,108,102, 46,105,116,121,112,101, 44,115,101,108,102, 46, - 116, 97,103, 32, 61, 32,116, 97,103,118, 97,114, 40,115,101, - 108,102, 46,110, 97,109,101, 41, 59, 10,115,101,108,102, 46, - 99,105,116,121,112,101, 44,115,101,108,102, 46, 99,116, 97, - 103, 32, 61, 32,116, 97,103,118, 97,114, 40,115,101,108,102, - 46,110, 97,109,101, 44, 39, 99,111,110,115,116, 39, 41, 59, - 10,108,111, 99, 97,108, 32,105, 61, 49, 10,119,104,105,108, - 101, 32,115,101,108,102, 91,105, 93, 32,100,111, 10,115,101, - 108,102, 91,105, 93, 58,100,101, 99,108,116, 97,103, 40, 41, - 10,105, 32, 61, 32,105, 43, 49, 10,101,110,100, 10,101,110, - 100, 10, 10, 10, 10,102,117,110, 99,116,105,111,110, 32, 99, - 108, 97,115,115, 67,108, 97,115,115, 58,112,114,105,110,116, - 32, 40,105,100,101,110,116, 44, 99,108,111,115,101, 41, 10, - 112,114,105,110,116, 40,105,100,101,110,116, 46, 46, 34, 67, - 108, 97,115,115,123, 34, 41, 10,112,114,105,110,116, 40,105, - 100,101,110,116, 46, 46, 34, 32,110, 97,109,101, 32, 61, 32, - 39, 34, 46, 46,115,101,108,102, 46,110, 97,109,101, 46, 46, - 34, 39, 44, 34, 41, 10,112,114,105,110,116, 40,105,100,101, - 110,116, 46, 46, 34, 32, 98, 97,115,101, 32, 61, 32, 39, 34, - 46, 46,115,101,108,102, 46, 98, 97,115,101, 46, 46, 34, 39, - 59, 34, 41, 10,108,111, 99, 97,108, 32,105, 61, 49, 10,119, - 104,105,108,101, 32,115,101,108,102, 91,105, 93, 32,100,111, - 10,115,101,108,102, 91,105, 93, 58,112,114,105,110,116, 40, - 105,100,101,110,116, 46, 46, 34, 32, 34, 44, 34, 44, 34, 41, - 10,105, 32, 61, 32,105, 43, 49, 10,101,110,100, 10,112,114, - 105,110,116, 40,105,100,101,110,116, 46, 46, 34,125, 34, 46, - 46, 99,108,111,115,101, 41, 10,101,110,100, 10, 10, 10,102, - 117,110, 99,116,105,111,110, 32, 95, 67,108, 97,115,115, 32, - 40,116, 41, 10,116, 46, 95, 98, 97,115,101, 32, 61, 32, 99, - 108, 97,115,115, 67,108, 97,115,115, 10,115,101,116,116, 97, - 103, 40,116, 44,116,111,108,117, 97, 95,116, 97,103, 41, 10, - 97,112,112,101,110,100, 40,116, 41, 10,114,101,116,117,114, - 110, 32,116, 10,101,110,100, 10, 10, 10, 10,102,117,110, 99, - 116,105,111,110, 32, 67,108, 97,115,115, 32, 40,110, 44,112, - 44, 98, 41, 10,108,111, 99, 97,108, 32, 99, 32, 61, 32, 95, - 67,108, 97,115,115, 40, 95, 67,111,110,116, 97,105,110,101, - 114,123,110, 97,109,101, 61,110, 44, 32, 98, 97,115,101, 61, - 112,125, 41, 10,112,117,115,104, 40, 99, 41, 10, 99, 58,112, - 97,114,115,101, 40,115,116,114,115,117, 98, 40, 98, 44, 50, - 44,115,116,114,108,101,110, 40, 98, 41, 45, 49, 41, 41, 10, - 112,111,112, 40, 41, 10,101,110,100, 10, 10, 10, 10, 83, 84, - 82, 49, 32, 61, 32, 34, 92, 48, 48, 49, 34, 10, 83, 84, 82, - 50, 32, 61, 32, 34, 92, 48, 48, 50, 34, 10, 83, 84, 82, 51, - 32, 61, 32, 34, 92, 48, 48, 51, 34, 10, 83, 84, 82, 52, 32, - 61, 32, 34, 92, 48, 48, 52, 34, 10, 82, 69, 77, 32, 61, 32, - 34, 92, 48, 48, 53, 34, 10, 65, 78, 89, 32, 61, 32, 34, 40, - 91, 92, 48, 48, 49, 45, 92, 48, 48, 53, 93, 41, 34, 10, 69, - 83, 67, 49, 32, 61, 32, 34, 92, 48, 48, 54, 34, 10, 69, 83, - 67, 50, 32, 61, 32, 34, 92, 48, 48, 55, 34, 10, 10, 77, 65, - 83, 75, 32, 61, 32,123, 10,123, 69, 83, 67, 49, 44, 32, 34, - 92, 92, 39, 34,125, 44, 10,123, 69, 83, 67, 50, 44, 32, 39, - 92, 92, 34, 39,125, 44, 10,123, 83, 84, 82, 49, 44, 32, 34, - 39, 34,125, 44, 10,123, 83, 84, 82, 50, 44, 32, 39, 34, 39, - 125, 44, 10,123, 83, 84, 82, 51, 44, 32, 34, 37, 91, 37, 91, - 34,125, 44, 10,123, 83, 84, 82, 52, 44, 32, 34, 37, 93, 37, - 93, 34,125, 44, 10,123, 82, 69, 77, 32, 44, 32, 34, 37, 45, - 37, 45, 34,125, 44, 10,125, 10, 10,102,117,110, 99,116,105, - 111,110, 32,109, 97,115,107, 32, 40,115, 41, 10,102,111,114, - 32,105, 32, 61, 32, 49, 44,103,101,116,110, 40, 77, 65, 83, - 75, 41, 32,100,111, 10,115, 32, 61, 32,103,115,117, 98, 40, - 115, 44, 77, 65, 83, 75, 91,105, 93, 91, 50, 93, 44, 77, 65, - 83, 75, 91,105, 93, 91, 49, 93, 41, 10,101,110,100, 10,114, - 101,116,117,114,110, 32,115, 10,101,110,100, 10, 10,102,117, - 110, 99,116,105,111,110, 32,117,110,109, 97,115,107, 32, 40, - 115, 41, 10,102,111,114, 32,105, 32, 61, 32, 49, 44,103,101, - 116,110, 40, 77, 65, 83, 75, 41, 32,100,111, 10,115, 32, 61, - 32,103,115,117, 98, 40,115, 44, 77, 65, 83, 75, 91,105, 93, - 91, 49, 93, 44, 77, 65, 83, 75, 91,105, 93, 91, 50, 93, 41, - 10,101,110,100, 10,114,101,116,117,114,110, 32,115, 10,101, - 110,100, 10, 10,102,117,110, 99,116,105,111,110, 32, 99,108, - 101, 97,110, 32, 40,115, 41, 10, 10,108,111, 99, 97,108, 32, - 99,111,100,101, 32, 61, 32, 34,114,101,116,117,114,110, 32, - 102,117,110, 99,116,105,111,110, 32, 40, 41, 32, 34, 32, 46, - 46, 32,115, 32, 46, 46, 32, 34, 32,101,110,100, 34, 10,105, - 102, 32,110,111,116, 32,100,111,115,116,114,105,110,103, 40, - 99,111,100,101, 41, 32,116,104,101,110, 10,114,101,116,117, - 114,110, 32,110,105,108, 10,101,110,100, 10, 10,108,111, 99, - 97,108, 32, 83, 32, 61, 32, 34, 34, 10, 10,115, 32, 61, 32, - 109, 97,115,107, 40,115, 41, 10, 10, 10,119,104,105,108,101, - 32, 49, 32,100,111, 10,108,111, 99, 97,108, 32, 98, 44,101, - 44,100, 32, 61, 32,115,116,114,102,105,110,100, 40,115, 44, - 65, 78, 89, 41, 10,105,102, 32, 98, 32,116,104,101,110, 10, - 83, 32, 61, 32, 83, 46, 46,115,116,114,115,117, 98, 40,115, - 44, 49, 44, 98, 45, 49, 41, 10,115, 32, 61, 32,115,116,114, - 115,117, 98, 40,115, 44, 98, 43, 49, 41, 10,105,102, 32,100, - 61, 61, 83, 84, 82, 49, 32,111,114, 32,100, 61, 61, 83, 84, - 82, 50, 32,116,104,101,110, 10,101, 32, 61, 32,115,116,114, - 102,105,110,100, 40,115, 44,100, 41, 10, 83, 32, 61, 32, 83, - 32, 46, 46,100, 46, 46,115,116,114,115,117, 98, 40,115, 44, - 49, 44,101, 41, 10,115, 32, 61, 32,115,116,114,115,117, 98, - 40,115, 44,101, 43, 49, 41, 10,101,108,115,101,105,102, 32, - 100, 61, 61, 83, 84, 82, 51, 32,116,104,101,110, 10,101, 32, - 61, 32,115,116,114,102,105,110,100, 40,115, 44, 83, 84, 82, - 52, 41, 10, 83, 32, 61, 32, 83, 46, 46,100, 46, 46,115,116, - 114,115,117, 98, 40,115, 44, 49, 44,101, 41, 10,115, 32, 61, - 32,115,116,114,115,117, 98, 40,115, 44,101, 43, 49, 41, 10, - 101,108,115,101,105,102, 32,100, 61, 61, 82, 69, 77, 32,116, - 104,101,110, 10,115, 32, 61, 32,103,115,117, 98, 40,115, 44, - 34, 91, 94, 92,110, 93, 42, 40, 92,110, 63, 41, 34, 44, 34, - 37, 49, 34, 44, 49, 41, 10,101,110,100, 10,101,108,115,101, - 10, 83, 32, 61, 32, 83, 46, 46,115, 10, 98,114,101, 97,107, - 10,101,110,100, 10,101,110,100, 10, 10, 83, 32, 61, 32,103, - 115,117, 98, 40, 83, 44, 34, 91, 32, 92,116, 93, 43, 34, 44, - 34, 32, 34, 41, 10, 83, 32, 61, 32,103,115,117, 98, 40, 83, - 44, 34, 91, 32, 92,116, 93, 42, 92,110, 91, 32, 92,116, 93, - 42, 34, 44, 34, 92,110, 34, 41, 10, 83, 32, 61, 32,117,110, - 109, 97,115,107, 40, 83, 41, 10,114,101,116,117,114,110, 32, - 83, 10,101,110,100, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, - 10, 10, 10, 10, 10,105,102, 32,102,108, 97,103,115, 46,102, - 32,116,104,101,110, 10,108,111, 99, 97,108, 32,115,116, 44, - 32,109,115,103, 32, 61, 32,114,101, 97,100,102,114,111,109, - 40,102,108, 97,103,115, 46,102, 41, 10,105,102, 32,110,111, - 116, 32,115,116, 32,116,104,101,110, 10,101,114,114,111,114, - 40, 39, 35, 39, 46, 46,109,115,103, 41, 10,101,110,100, 10, - 101,110,100, 10, 10, 10,105,102, 32,110,111,116, 32,102,108, - 97,103,115, 46,110, 32,116,104,101,110, 10,105,102, 32,102, - 108, 97,103,115, 46,102, 32,116,104,101,110, 10,102,108, 97, - 103,115, 46,110, 32, 61, 32,103,115,117, 98, 40,102,108, 97, - 103,115, 46,102, 44, 34, 37, 46, 46, 42, 34, 44, 34, 34, 41, - 10,101,108,115,101, 10,101,114,114,111,114, 40, 34, 35,110, - 111, 32,112, 97, 99,107, 97,103,101, 32,110, 97,109,101, 32, - 110,111,114, 32,105,110,112,117,116, 32,102,105,108,101, 32, - 112,114,111,118,105,100,101,100, 34, 41, 10,101,110,100, 10, - 101,110,100, 10, 10,108,111, 99, 97,108, 32,112, 32, 61, 32, - 80, 97, 99,107, 97,103,101, 40,102,108, 97,103,115, 46,110, - 41, 10, 10,105,102, 32,102,108, 97,103,115, 46,102, 32,116, - 104,101,110, 10,114,101, 97,100,102,114,111,109, 40, 41, 10, - 101,110,100, 10, 10,105,102, 32,102,108, 97,103,115, 46,112, - 32,116,104,101,110, 10,114,101,116,117,114,110, 10,101,110, - 100, 10, 10,105,102, 32,102,108, 97,103,115, 46,111, 32,116, - 104,101,110, 10,108,111, 99, 97,108, 32,115,116, 44,109,115, - 103, 32, 61, 32,119,114,105,116,101,116,111, 40,102,108, 97, - 103,115, 46,111, 41, 10,105,102, 32,110,111,116, 32,115,116, - 32,116,104,101,110, 10,101,114,114,111,114, 40, 39, 35, 39, - 46, 46,109,115,103, 41, 10,101,110,100, 10,101,110,100, 10, - 10,105,102, 32,102,108, 97,103,115, 46, 80, 32,116,104,101, - 110, 10,112, 58,112,114,105,110,116, 40, 41, 10,101,108,115, - 101, 10,112, 58,100,101, 99,108,116, 97,103, 40, 41, 10,112, - 58,112,114,101, 97,109, 98,108,101, 40, 41, 10,112, 58,115, - 117,112, 99,111,100,101, 40, 41, 10,112, 58,114,101,103,105, - 115,116,101,114, 40, 41, 10,112, 58,117,110,114,101,103,105, - 115,116,101,114, 40, 41, 10,101,110,100, 10, 10,105,102, 32, - 102,108, 97,103,115, 46,111, 32,116,104,101,110, 10,119,114, - 105,116,101,116,111, 40, 41, 10,101,110,100, 10, 10, 10,105, - 102, 32,110,111,116, 32,102,108, 97,103,115, 46, 80, 32,116, - 104,101,110, 10,105,102, 32,102,108, 97,103,115, 46, 72, 32, - 116,104,101,110, 10,108,111, 99, 97,108, 32,115,116, 44,109, - 115,103, 32, 61, 32,119,114,105,116,101,116,111, 40,102,108, - 97,103,115, 46, 72, 41, 10,105,102, 32,110,111,116, 32,115, - 116, 32,116,104,101,110, 10,101,114,114,111,114, 40, 39, 35, - 39, 46, 46,109,115,103, 41, 10,101,110,100, 10,112, 58,104, - 101, 97,100,101,114, 40, 41, 10,119,114,105,116,101,116,111, - 40, 41, 10,101,110,100, 10,101,110,100,32 - }; - lua_dobuffer(tolua_S,(char*)B,sizeof(B),"tolua: embedded Lua code"); - } /* end of embedded lua code */ - - return 1; -} -/* Close function */ -void tolua_tolualua_close (lua_State* tolua_S) -{ -} diff --git a/src/lua/tolualua.h b/src/lua/tolualua.h deleted file mode 100644 index b380dcef..00000000 --- a/src/lua/tolualua.h +++ /dev/null @@ -1,2713 +0,0 @@ -/* code automatically generated by bin2c -- DO NOT EDIT */ -{ -/* #include'ing this file in a C program is equivalent to calling - lua_dofile("basic.lo"); - lua_dofile("feature.lo"); - lua_dofile("declaration.lo"); - lua_dofile("container.lo"); - lua_dofile("package.lo"); - lua_dofile("module.lo"); - lua_dofile("class.lo"); - lua_dofile("typedef.lo"); - lua_dofile("define.lo"); - lua_dofile("enumerate.lo"); - lua_dofile("variable.lo"); - lua_dofile("array.lo"); - lua_dofile("function.lo"); - lua_dofile("operator.lo"); - lua_dofile("verbatim.lo"); - lua_dofile("code.lo"); - lua_dofile("doit.lo"); -*/ -/* basic.lo */ -static char B1[]={ - 27, 76,117, 97, 50, 0, 0, 0, 0, 0, 0, 0, 0, 11, 64, 98, 97,115,105, 99, - 46,108,117, 97, 0, 0, 0, 0,190, 25, 0, 60, 17, 22, 12, 60, 18, 11, 1, 11, - 2, 60, 19, 11, 3, 11, 4, 60, 20, 11, 5, 11, 4, 60, 21, 11, 6, 11, 4, 60, - 22, 11, 7, 11, 4, 60, 23, 11, 8, 11, 4, 60, 24, 11, 9, 11, 4, 60, 25, 11, - 10, 11, 11, 60, 26, 11, 12, 11, 13, 60, 27, 11, 14, 11, 11, 60, 28, 11, 15, 11, - 13, 60, 29, 11, 16, 11, 17, 30, 11, 60, 30, 25, 0, 60, 34, 22, 0, 25, 18, 60, - 37, 11, 20, 25, 19, 60, 45, 15, 22, 2, 1, 0, 25, 21, 60, 46, 15, 24, 15, 21, - 11, 25, 15, 19, 2, 1, 3, 25, 23, 60, 49, 11, 27, 25, 26, 60, 69, 15, 28, 15, - 26, 2, 0, 1, 60, 72, 11, 30, 25, 29, 60, 80, 22, 0, 25, 31, 60, 81, 11, 33, - 25, 32, 60, 89, 11, 35, 25, 34, 60,109, 11, 37, 25, 36, 60,115, 11, 39, 25, 38, - 60,121, 11, 41, 25, 40, 60,138, 11, 43, 25, 42, 60,150, 11, 45, 25, 44, 0, 0, - 0, 0, 0, 0, 0, 0, 46, 2, 0, 0, 0, 7, 95, 98, 97,115,105, 99, 0, 2, - 0, 0, 0, 5,118,111,105,100, 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 5, - 99,104, 97,114, 0, 2, 0, 0, 0, 7,110,117,109, 98,101,114, 0, 2, 0, 0, - 0, 4,105,110,116, 0, 2, 0, 0, 0, 6,115,104,111,114,116, 0, 2, 0, 0, - 0, 5,108,111,110,103, 0, 2, 0, 0, 0, 6,102,108,111, 97,116, 0, 2, 0, - 0, 0, 7,100,111,117, 98,108,101, 0, 2, 0, 0, 0, 9, 95, 99,115,116,114, -105,110,103, 0, 2, 0, 0, 0, 7,115,116,114,105,110,103, 0, 2, 0, 0, 0, - 10, 95,117,115,101,114,100, 97,116, 97, 0, 2, 0, 0, 0, 9,117,115,101,114, -100, 97,116, 97, 0, 2, 0, 0, 0, 6, 99,104, 97,114, 42, 0, 2, 0, 0, 0, - 6,118,111,105,100, 42, 0, 2, 0, 0, 0, 11,108,117, 97, 95, 79, 98,106,101, - 99,116, 0, 2, 0, 0, 0, 7,111, 98,106,101, 99,116, 0, 2, 0, 0, 0, 10, - 95,117,115,101,114,116,121,112,101, 0, 2, 0, 0, 0, 12,116,111,108,117, 97, - 95,105,110,100,101,120, 0, 4, 0, 0, 0, 37, 0, 0, 0, 11, 64, 98, 97,115, -105, 99, 46,108,117, 97, 0, 0, 0, 0, 40, 5, 2, 60, 38, 13, 1, 11, 2, 32, - 52, 13, 60, 39, 15, 3, 13, 0, 13, 1, 3, 2, 2, 50, 13, 60, 41, 13, 0, 18, - 2, 13, 1, 16, 1, 2, 60, 42, 60, 43, 0, 0, 0, 0, 2, 0, 0, 0, 37, 0, - 0, 0, 2,116, 0, 0, 0, 0, 37, 0, 0, 0, 2,102, 0, 0, 0, 0, 4, 2, - 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 2,102, 0, 2, 0, 0, 0, 6, 95, 98, - 97,115,101, 0, 2, 0, 0, 0, 16,116,111,108,117, 97, 95,111,108,100, 95,105, -110,100,101,120, 0, 2, 0, 0, 0, 10,116,111,108,117, 97, 95,116, 97,103, 0, - 2, 0, 0, 0, 7,110,101,119,116, 97,103, 0, 2, 0, 0, 0, 16,116,111,108, -117, 97, 95,111,108,100, 95,105,110,100,101,120, 0, 2, 0, 0, 0, 13,115,101, -116,116, 97,103,109,101,116,104,111,100, 0, 2, 0, 0, 0, 6,105,110,100,101, -120, 0, 2, 0, 0, 0, 12,116,111,108,117, 97, 95,101,114,114,111,114, 0, 4, - 0, 0, 0, 49, 0, 0, 0, 11, 64, 98, 97,115,105, 99, 46,108,117, 97, 0, 0, - 0, 0,163, 9, 1, 60, 50, 15, 2, 60, 51, 15, 3, 25, 2, 60, 52, 15, 4, 13, - 0, 7, 1, 7, 1, 2, 1, 3, 11, 5, 32, 52, 24, 60, 53, 15, 6, 11, 7, 15, - 4, 13, 0, 7, 2, 2, 1, 2, 42, 11, 8, 42, 2, 0, 1, 50, 19, 60, 55, 15, - 6, 11, 9, 13, 0, 42, 11, 8, 42, 2, 0, 1, 60, 57, 1, 2, 60, 59, 15, 10, - 52, 73, 60, 60, 15, 12, 15, 10, 11, 13, 2, 3, 2, 60, 61, 13, 4, 4, 0, 32, - 52, 4, 15, 10, 23, 4, 60, 62, 15, 14, 13, 4, 11, 15, 11, 16, 2, 1, 3, 23, - 4, 60, 63, 15, 14, 13, 4, 11, 17, 11, 18, 2, 1, 3, 23, 4, 60, 64, 15, 6, - 11, 19, 13, 4, 42, 11, 20, 42, 2, 0, 1, 5, 3, 50, 2, 60, 65, 60, 66, 13, - 1, 25, 2, 60, 67, 0, 0, 0, 0, 8, 0, 0, 0, 49, 0, 0, 0, 2,115, 0, - 0, 0, 0, 50, 0, 0, 0, 4,111,117,116, 0, 0, 0, 0, 60, 0, 0, 0, 2, - 95, 0, 0, 0, 0, 60, 0, 0, 0, 2, 95, 0, 0, 0, 0, 60, 0, 0, 0, 2, -115, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, - 0, 64, 0, 0, 0, 0, 0, 0, 0, 21, 2, 0, 0, 0, 2,115, 0, 2, 0, 0, - 0, 4,111,117,116, 0, 2, 0, 0, 0, 8, 95, 79, 85, 84, 80, 85, 84, 0, 2, - 0, 0, 0, 8, 95, 83, 84, 68, 69, 82, 82, 0, 2, 0, 0, 0, 7,115,116,114, -115,117, 98, 0, 2, 0, 0, 0, 2, 35, 0, 2, 0, 0, 0, 6,119,114,105,116, -101, 0, 2, 0, 0, 0, 12, 10, 42, 42, 32,116,111,108,117, 97, 58, 32, 0, 2, - 0, 0, 0, 4, 46, 10, 10, 0, 2, 0, 0, 0, 27, 10, 42, 42, 32,116,111,108, -117, 97, 32,105,110,116,101,114,110, 97,108, 32,101,114,114,111,114, 58, 32, 0, - 2, 0, 0, 0, 11, 95, 99,117,114,114, 95, 99,111,100,101, 0, 2, 0, 0, 0, - 2, 95, 0, 2, 0, 0, 0, 8,115,116,114,102,105,110,100, 0, 2, 0, 0, 0, - 10, 94, 37,115, 42, 40, 46, 45, 10, 41, 0, 2, 0, 0, 0, 5,103,115,117, 98, - 0, 2, 0, 0, 0, 10, 95,117,115,101,114,100, 97,116, 97, 0, 2, 0, 0, 0, - 6,118,111,105,100, 42, 0, 2, 0, 0, 0, 9, 95, 99,115,116,114,105,110,103, - 0, 2, 0, 0, 0, 6, 99,104, 97,114, 42, 0, 2, 0, 0, 0, 23, 67,111,100, -101, 32, 98,101,105,110,103, 32,112,114,111, 99,101,115,115,101,100, 58, 10, 0, - 2, 0, 0, 0, 2, 10, 0, 2, 0, 0, 0, 15,115,101,116,101,114,114,111,114, -109,101,116,104,111,100, 0, 2, 0, 0, 0, 8,114,101,103,116,121,112,101, 0, - 4, 0, 0, 0, 72, 0, 0, 0, 11, 64, 98, 97,115,105, 99, 46,108,117, 97, 0, - 0, 0, 0, 36, 4, 1, 60, 73, 15, 1, 13, 0, 2, 1, 1, 44, 52, 11, 60, 74, - 15, 2, 13, 0, 13, 0, 26, 50, 2, 60, 75, 60, 76, 13, 0, 1, 1, 60, 77, 0, - 0, 0, 0, 1, 0, 0, 0, 72, 0, 0, 0, 2,116, 0, 0, 0, 0, 3, 2, 0, - 0, 0, 2,116, 0, 2, 0, 0, 0, 7,105,115,116,121,112,101, 0, 2, 0, 0, - 0, 10, 95,117,115,101,114,116,121,112,101, 0, 2, 0, 0, 0, 10, 95,116, 97, -103,110, 97,109,101,115, 0, 2, 0, 0, 0, 8,100,101, 99,108,116, 97,103, 0, - 4, 0, 0, 0, 81, 0, 0, 0, 11, 64, 98, 97,115,105, 99, 46,108,117, 97, 0, - 0, 0, 0, 67, 5, 2, 60, 82, 13, 0, 11, 2, 31, 48, 5, 13, 1, 7, 0, 31, - 48, 8, 15, 3, 13, 0, 2, 1, 1, 44, 48, 6, 15, 4, 13, 1, 16, 44, 52, 26, - 60, 83, 15, 4, 13, 1, 13, 0, 26, 60, 84, 15, 5, 11, 6, 13, 1, 42, 11, 7, - 42, 2, 0, 1, 50, 2, 60, 85, 60, 86, 0, 0, 0, 0, 2, 0, 0, 0, 81, 0, - 0, 0, 6,105,116,121,112,101, 0, 0, 0, 0, 81, 0, 0, 0, 4,116, 97,103, - 0, 0, 0, 0, 8, 2, 0, 0, 0, 6,105,116,121,112,101, 0, 2, 0, 0, 0, - 4,116, 97,103, 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 8,105,115, 98, 97, -115,105, 99, 0, 2, 0, 0, 0, 10, 95,116, 97,103,110, 97,109,101,115, 0, 2, - 0, 0, 0, 7,111,117,116,112,117,116, 0, 2, 0, 0, 0, 12,115,116, 97,116, -105, 99, 32,105,110,116, 32, 0, 2, 0, 0, 0, 2, 59, 0, 2, 0, 0, 0, 7, -116, 97,103,118, 97,114, 0, 4, 0, 0, 0, 89, 0, 0, 0, 11, 64, 98, 97,115, -105, 99, 46,108,117, 97, 0, 0, 0, 0,155, 8, 2, 60, 90, 13, 0, 11, 2, 32, - 46, 5, 13, 0, 11, 3, 32, 52, 10, 60, 91, 13, 0, 7, 0, 1, 2, 50,124, 60, - 92, 15, 4, 13, 0, 2, 1, 1, 52, 18, 60, 93, 13, 0, 11, 5, 15, 4, 13, 0, - 2, 1, 1, 42, 1, 2, 50, 95, 60, 95, 15, 8, 13, 0, 2, 2, 1, 60, 96, 15, - 9, 13, 2, 11, 1, 2, 1, 2, 52, 4, 11, 1, 23, 1, 60, 97, 13, 3, 23, 0, - 60, 98, 15, 10, 13, 3, 2, 0, 1, 60, 99, 11, 5, 60,100, 13, 1, 48, 5, 13, - 1, 11, 2, 31, 52, 20, 60,101, 11, 12, 13, 3, 42, 23, 3, 60,102, 13, 4, 11, - 13, 42, 23, 4, 50, 2, 60,103, 60,104, 13, 3, 13, 4, 13, 0, 42, 1, 5, 5, - 3, 60,105, 60,106, 0, 0, 0, 0, 8, 0, 0, 0, 89, 0, 0, 0, 5,116,121, -112,101, 0, 0, 0, 0, 89, 0, 0, 0, 6, 99,111,110,115,116, 0, 0, 0, 0, - 95, 0, 0, 0, 2,109, 0, 0, 0, 0, 95, 0, 0, 0, 2,116, 0, 0, 0, 0, - 99, 0, 0, 0, 2,118, 0, 0, 0, 0,104, 0, 0, 0, 0, 0, 0, 0,104, 0, - 0, 0, 0, 0, 0, 0,104, 0, 0, 0, 0, 0, 0, 0, 14, 2, 0, 0, 0, 5, -116,121,112,101, 0, 2, 0, 0, 0, 6, 99,111,110,115,116, 0, 2, 0, 0, 0, - 1, 0, 2, 0, 0, 0, 5,118,111,105,100, 0, 2, 0, 0, 0, 8,105,115, 98, - 97,115,105, 99, 0, 2, 0, 0, 0, 11,116,111,108,117, 97, 95,116, 97,103, 95, - 0, 2, 0, 0, 0, 2,109, 0, 2, 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 12, -102,105,110,100,116,121,112,101,100,101,102, 0, 2, 0, 0, 0, 8,115,116,114, -102,105,110,100, 0, 2, 0, 0, 0, 8,114,101,103,116,121,112,101, 0, 2, 0, - 0, 0, 2,118, 0, 2, 0, 0, 0, 7, 99,111,110,115,116, 32, 0, 2, 0, 0, - 0, 7, 99,111,110,115,116, 95, 0, 2, 0, 0, 0, 8,105,115, 98, 97,115,105, - 99, 0, 4, 0, 0, 0,109, 0, 0, 0, 11, 64, 98, 97,115,105, 99, 46,108,117, - 97, 0, 0, 0, 0, 23, 5, 1, 60,110, 15, 3, 13, 0, 2, 2, 1, 60,111, 15, - 4, 13, 2, 16, 1, 3, 60,112, 0, 0, 0, 0, 3, 0, 0, 0,109, 0, 0, 0, - 5,116,121,112,101, 0, 0, 0, 0,110, 0, 0, 0, 2,109, 0, 0, 0, 0,110, - 0, 0, 0, 2,116, 0, 0, 0, 0, 5, 2, 0, 0, 0, 5,116,121,112,101, 0, - 2, 0, 0, 0, 2,109, 0, 2, 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 12,102, -105,110,100,116,121,112,101,100,101,102, 0, 2, 0, 0, 0, 7, 95, 98, 97,115, -105, 99, 0, 2, 0, 0, 0, 7,105,115,116,121,112,101, 0, 4, 0, 0, 0,115, - 0, 0, 0, 11, 64, 98, 97,115,105, 99, 46,108,117, 97, 0, 0, 0, 0, 30, 3, - 1, 60,116, 15, 1, 13, 0, 16, 46, 5, 15, 2, 13, 0, 16, 46, 7, 15, 3, 13, - 0, 2, 1, 1, 1, 1, 60,117, 0, 0, 0, 0, 1, 0, 0, 0,115, 0, 0, 0, - 2,116, 0, 0, 0, 0, 4, 2, 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 7, 95, - 98, 97,115,105, 99, 0, 2, 0, 0, 0, 10, 95,117,115,101,114,116,121,112,101, - 0, 2, 0, 0, 0, 10,105,115,116,121,112,101,100,101,102, 0, 2, 0, 0, 0, - 6,115,112,108,105,116, 0, 4, 0, 0, 0,121, 0, 0, 0, 11, 64, 98, 97,115, -105, 99, 46,108,117, 97, 0, 0, 0, 0,117, 11, 2, 60,122, 22, 1, 11, 3, 7, - 0, 30, 0, 60,123, 13, 2, 58, 5, 1, 60,127, 11, 7, 13, 1, 42, 11, 8, 42, - 60,128, 15, 9, 13, 0, 11, 10, 11, 11, 2, 1, 3, 23, 0, 60,129, 15, 9, 13, - 0, 11, 12, 11, 11, 2, 1, 3, 23, 0, 60,130, 15, 9, 13, 0, 13, 4, 13, 3, - 2, 1, 3, 23, 0, 60,131, 13, 2, 11, 14, 13, 2, 18, 14, 7, 1, 37, 26, 60, -132, 13, 2, 13, 2, 18, 14, 15, 9, 13, 0, 11, 15, 11, 11, 2, 1, 3, 26, 60, -133, 13, 2, 1, 5, 60,134, 0, 0, 0, 0, 5, 0, 0, 0,121, 0, 0, 0, 2, -115, 0, 0, 0, 0,121, 0, 0, 0, 2,116, 0, 0, 0, 0,122, 0, 0, 0, 2, -108, 0, 0, 0, 0,123, 0, 0, 0, 2,102, 0, 0, 0, 0,127, 0, 0, 0, 2, -112, 0, 0, 0, 0, 16, 2, 0, 0, 0, 2,115, 0, 2, 0, 0, 0, 2,116, 0, - 2, 0, 0, 0, 2,108, 0, 2, 0, 0, 0, 2,110, 0, 2, 0, 0, 0, 2,102, - 0, 4, 0, 0, 0,123, 0, 0, 0, 11, 64, 98, 97,115,105, 99, 46,108,117, 97, - 0, 0, 0, 0, 30, 5, 1, 60,124, 12, 0, 11, 2, 12, 0, 18, 2, 7, 1, 37, - 26, 60,125, 12, 0, 12, 0, 18, 2, 13, 0, 26, 60,126, 0, 0, 0, 0, 1, 0, - 0, 0,123, 0, 0, 0, 2,115, 0, 0, 0, 0, 3, 2, 0, 0, 0, 2,115, 0, - 2, 0, 0, 0, 2,108, 0, 2, 0, 0, 0, 2,110, 0, 2, 0, 0, 0, 2,112, - 0, 2, 0, 0, 0, 11, 37,115, 42, 40, 46, 45, 41, 37,115, 42, 0, 2, 0, 0, - 0, 4, 37,115, 42, 0, 2, 0, 0, 0, 5,103,115,117, 98, 0, 2, 0, 0, 0, - 5, 94, 37,115, 43, 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 5, 37,115, 43, - 36, 0, 2, 0, 0, 0, 2,108, 0, 2, 0, 0, 0, 2,110, 0, 2, 0, 0, 0, - 9, 40, 37,115, 37,115, 42, 41, 36, 0, 2, 0, 0, 0, 7, 99,111,110, 99, 97, -116, 0, 4, 0, 0, 0,138, 0, 0, 0, 11, 64, 98, 97,115,105, 99, 46,108,117, - 97, 0, 0, 0, 0, 69, 8, 3, 60,139, 11, 4, 60,140, 13, 1, 50, 39, 60,142, - 13, 3, 13, 0, 13, 4, 16, 42, 23, 3, 60,143, 13, 4, 7, 1, 37, 23, 4, 60, -144, 13, 4, 13, 2, 34, 52, 7, 13, 3, 11, 6, 42, 23, 3, 60,145, 60,141, 13, - 4, 13, 2, 34, 54, 48, 60,146, 13, 3, 1, 5, 60,147, 0, 0, 0, 0, 5, 0, - 0, 0,138, 0, 0, 0, 2,116, 0, 0, 0, 0,138, 0, 0, 0, 2,102, 0, 0, - 0, 0,138, 0, 0, 0, 2,108, 0, 0, 0, 0,139, 0, 0, 0, 2,115, 0, 0, - 0, 0,140, 0, 0, 0, 2,105, 0, 0, 0, 0, 7, 2, 0, 0, 0, 2,116, 0, - 2, 0, 0, 0, 2,102, 0, 2, 0, 0, 0, 2,108, 0, 2, 0, 0, 0, 2,115, - 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 2,105, 0, 2, 0, 0, 0, 2, 32, - 0, 2, 0, 0, 0, 7,111,117,116,112,117,116, 0, 4, 0, 0, 0,150, 0, 0, - 0, 11, 64, 98, 97,115,105, 99, 46,108,117, 97, 0, 0, 0, 0,161, 6,128, 60, -151, 7, 1, 50,104, 60,153, 15, 3, 48, 10, 15, 4, 15, 3, 11, 5, 2, 1, 2, - 44, 48, 14, 60,154, 15, 4, 13, 0, 13, 1, 16, 11, 6, 2, 1, 2, 52, 11, 60, -155, 15, 7, 11, 8, 2, 0, 1, 50, 2, 60,156, 60,157, 15, 7, 13, 0, 13, 1, - 16, 2, 0, 1, 60,158, 13, 0, 13, 1, 16, 11, 9, 31, 52, 20, 60,159, 15, 10, - 13, 0, 13, 1, 16, 9, 1, 9, 1, 2, 1, 3, 25, 3, 50, 2, 60,160, 60,161, - 13, 1, 7, 1, 37, 23, 1, 60,162, 60,152, 13, 1, 13, 0, 18, 2, 34, 54,115, - 60,163, 15, 4, 13, 0, 13, 0, 18, 2, 16, 11, 11, 2, 1, 2, 52, 15, 60,164, - 4, 0, 25, 3, 15, 7, 11, 12, 2, 0, 1, 50, 2, 60,165, 60,166, 0, 0, 0, - 0, 2, 0, 0, 0,150, 0, 0, 0, 4, 97,114,103, 0, 0, 0, 0,151, 0, 0, - 0, 2,105, 0, 0, 0, 0, 13, 2, 0, 0, 0, 2,105, 0, 2, 0, 0, 0, 4, - 97,114,103, 0, 2, 0, 0, 0, 2,110, 0, 2, 0, 0, 0, 6, 95, 99,111,110, -116, 0, 2, 0, 0, 0, 8,115,116,114,102,105,110,100, 0, 2, 0, 0, 0, 7, - 91, 37, 40, 44, 34, 93, 0, 2, 0, 0, 0, 8, 94, 91, 37, 97, 95,126, 93, 0, - 2, 0, 0, 0, 6,119,114,105,116,101, 0, 2, 0, 0, 0, 2, 32, 0, 2, 0, - 0, 0, 1, 0, 2, 0, 0, 0, 7,115,116,114,115,117, 98, 0, 2, 0, 0, 0, - 14, 91, 37, 47, 37, 41, 37, 59, 37,123, 37,125, 93, 36, 0, 2, 0, 0, 0, 2, - 10, 0, -}; - -/* feature.lo */ -static char B2[]={ - 27, 76,117, 97, 50, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64,102,101, 97,116,117, -114,101, 46,108,117, 97, 0, 0, 0, 0, 83, 3, 0, 60, 16, 22, 0, 60, 17, 25, - 0, 60, 20, 15, 0, 11, 1, 11, 2, 26, 60, 24, 15, 0, 11, 3, 11, 4, 26, 60, - 28, 15, 0, 11, 5, 11, 6, 26, 60, 32, 15, 0, 11, 7, 11, 8, 26, 60, 36, 15, - 0, 11, 9, 11, 10, 26, 60, 40, 15, 0, 11, 11, 11, 12, 26, 60, 49, 15, 0, 11, - 13, 11, 14, 26, 60, 59, 15, 0, 11, 15, 11, 16, 26, 0, 0, 0, 0, 0, 0, 0, - 0, 17, 2, 0, 0, 0, 13, 99,108, 97,115,115, 70,101, 97,116,117,114,101, 0, - 2, 0, 0, 0, 8,115,117,112, 99,111,100,101, 0, 4, 0, 0, 0, 20, 0, 0, - 0, 13, 64,102,101, 97,116,117,114,101, 46,108,117, 97, 0, 0, 0, 0, 5, 1, - 1, 60, 21, 0, 0, 0, 0, 1, 0, 0, 0, 20, 0, 0, 0, 5,115,101,108,102, - 0, 0, 0, 0, 0, 2, 0, 0, 0, 8,100,101, 99,108,116, 97,103, 0, 4, 0, - 0, 0, 24, 0, 0, 0, 13, 64,102,101, 97,116,117,114,101, 46,108,117, 97, 0, - 0, 0, 0, 5, 1, 1, 60, 25, 0, 0, 0, 0, 1, 0, 0, 0, 24, 0, 0, 0, - 5,115,101,108,102, 0, 0, 0, 0, 0, 2, 0, 0, 0, 9,114,101,103,105,115, -116,101,114, 0, 4, 0, 0, 0, 28, 0, 0, 0, 13, 64,102,101, 97,116,117,114, -101, 46,108,117, 97, 0, 0, 0, 0, 5, 1, 1, 60, 29, 0, 0, 0, 0, 1, 0, - 0, 0, 28, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 0, 2, 0, 0, 0, - 11,117,110,114,101,103,105,115,116,101,114, 0, 4, 0, 0, 0, 32, 0, 0, 0, - 13, 64,102,101, 97,116,117,114,101, 46,108,117, 97, 0, 0, 0, 0, 5, 1, 1, - 60, 33, 0, 0, 0, 0, 1, 0, 0, 0, 32, 0, 0, 0, 5,115,101,108,102, 0, - 0, 0, 0, 0, 2, 0, 0, 0, 9,112,114,101, 97,109, 98,108,101, 0, 4, 0, - 0, 0, 36, 0, 0, 0, 13, 64,102,101, 97,116,117,114,101, 46,108,117, 97, 0, - 0, 0, 0, 5, 1, 1, 60, 37, 0, 0, 0, 0, 1, 0, 0, 0, 36, 0, 0, 0, - 5,115,101,108,102, 0, 0, 0, 0, 0, 2, 0, 0, 0, 8,105,110, 99,108, 97, -115,115, 0, 4, 0, 0, 0, 40, 0, 0, 0, 13, 64,102,101, 97,116,117,114,101, - 46,108,117, 97, 0, 0, 0, 0, 44, 3, 1, 60, 41, 13, 0, 18, 1, 48, 9, 13, - 0, 18, 1, 18, 2, 11, 3, 32, 52, 12, 60, 42, 13, 0, 18, 1, 18, 4, 1, 1, - 50, 8, 60, 44, 4, 0, 1, 1, 60, 45, 60, 46, 0, 0, 0, 0, 1, 0, 0, 0, - 40, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 5, 2, 0, 0, 0, 5,115, -101,108,102, 0, 2, 0, 0, 0, 7,112, 97,114,101,110,116, 0, 2, 0, 0, 0, - 5,116,121,112,101, 0, 2, 0, 0, 0, 6, 99,108, 97,115,115, 0, 2, 0, 0, - 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 9,105,110,109,111,100,117,108,101, - 0, 4, 0, 0, 0, 49, 0, 0, 0, 13, 64,102,101, 97,116,117,114,101, 46,108, -117, 97, 0, 0, 0, 0, 44, 3, 1, 60, 50, 13, 0, 18, 1, 48, 9, 13, 0, 18, - 1, 18, 2, 11, 3, 32, 52, 12, 60, 51, 13, 0, 18, 1, 18, 4, 1, 1, 50, 8, - 60, 53, 4, 0, 1, 1, 60, 54, 60, 55, 0, 0, 0, 0, 1, 0, 0, 0, 49, 0, - 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 5, 2, 0, 0, 0, 5,115,101,108, -102, 0, 2, 0, 0, 0, 7,112, 97,114,101,110,116, 0, 2, 0, 0, 0, 5,116, -121,112,101, 0, 2, 0, 0, 0, 7,109,111,100,117,108,101, 0, 2, 0, 0, 0, - 5,110, 97,109,101, 0, 2, 0, 0, 0, 10, 99,102,117,110, 99,110, 97,109,101, - 0, 4, 0, 0, 0, 59, 0, 0, 0, 13, 64,102,101, 97,116,117,114,101, 46,108, -117, 97, 0, 0, 0, 0, 72, 5, 2, 60, 60, 13, 0, 18, 2, 52, 17, 60, 61, 13, - 0, 18, 2, 20, 3, 13, 1, 2, 1, 2, 23, 1, 50, 2, 60, 62, 60, 63, 13, 0, - 18, 4, 52, 16, 60, 64, 13, 1, 11, 5, 42, 13, 0, 18, 4, 42, 1, 2, 50, 16, - 60, 66, 13, 1, 11, 5, 42, 13, 0, 18, 6, 42, 1, 2, 60, 67, 60, 68, 0, 0, - 0, 0, 2, 0, 0, 0, 59, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 59, - 0, 0, 0, 2,110, 0, 0, 0, 0, 7, 2, 0, 0, 0, 2,110, 0, 2, 0, 0, - 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 7,112, 97,114,101,110,116, 0, 2, - 0, 0, 0, 10, 99,102,117,110, 99,110, 97,109,101, 0, 2, 0, 0, 0, 6,108, -110, 97,109,101, 0, 2, 0, 0, 0, 2, 95, 0, 2, 0, 0, 0, 5,110, 97,109, -101, 0, -}; - -/* declaration.lo */ -static char B3[]={ - 27, 76,117, 97, 50, 0, 0, 0, 0, 0, 0, 0, 0, 17, 64,100,101, 99,108, 97, -114, 97,116,105,111,110, 46,108,117, 97, 0, 0, 0, 0,193, 17, 0, 60, 24, 22, - 8, 60, 25, 11, 1, 15, 2, 11, 3, 60, 26, 11, 4, 11, 5, 60, 27, 11, 4, 11, - 6, 60, 28, 11, 4, 11, 7, 60, 29, 11, 4, 11, 8, 60, 30, 11, 4, 11, 9, 60, - 31, 11, 4, 11, 10, 60, 32, 11, 4, 30, 7, 60, 33, 25, 0, 60, 34, 15, 11, 15, - 0, 15, 12, 2, 0, 2, 60, 37, 11, 14, 25, 13, 60, 45, 15, 0, 11, 15, 11, 16, - 26, 60, 84, 15, 0, 11, 17, 11, 18, 26, 60,117, 15, 0, 11, 19, 11, 20, 26, 60, -130, 15, 0, 11, 21, 11, 22, 26, 60,136, 15, 0, 11, 23, 11, 24, 26, 60,149, 15, - 0, 11, 25, 11, 26, 26, 60,184, 15, 0, 11, 27, 11, 28, 26, 60,218, 15, 0, 11, - 29, 11, 30, 26, 60,250, 15, 0, 11, 31, 11, 32, 26, 59, 1, 1, 15, 0, 11, 33, - 11, 34, 26, 59, 1, 12, 15, 0, 11, 35, 11, 36, 26, 59, 1, 26, 11, 38, 25, 37, - 59, 1, 42, 11, 40, 25, 39, 0, 0, 0, 0, 0, 0, 0, 0, 41, 2, 0, 0, 0, - 17, 99,108, 97,115,115, 68,101, 99,108, 97,114, 97,116,105,111,110, 0, 2, 0, - 0, 0, 6, 95, 98, 97,115,101, 0, 2, 0, 0, 0, 13, 99,108, 97,115,115, 70, -101, 97,116,117,114,101, 0, 2, 0, 0, 0, 4,109,111,100, 0, 2, 0, 0, 0, - 1, 0, 2, 0, 0, 0, 5,116,121,112,101, 0, 2, 0, 0, 0, 4,112,116,114, - 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 4,100,105,109, 0, - 2, 0, 0, 0, 4,114,101,116, 0, 2, 0, 0, 0, 4,100,101,102, 0, 2, 0, - 0, 0, 7,115,101,116,116, 97,103, 0, 2, 0, 0, 0, 10,116,111,108,117, 97, - 95,116, 97,103, 0, 2, 0, 0, 0, 15, 99,114,101, 97,116,101, 95,118, 97,114, -110, 97,109,101, 0, 4, 0, 0, 0, 37, 0, 0, 0, 17, 64,100,101, 99,108, 97, -114, 97,116,105,111,110, 46,108,117, 97, 0, 0, 0, 0, 34, 2, 0, 60, 38, 15, - 0, 44, 52, 4, 7, 0, 25, 0, 60, 39, 15, 0, 7, 1, 37, 25, 0, 60, 40, 11, - 1, 15, 0, 42, 1, 0, 60, 41, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, - 0, 11, 95,118, 97,114,110,117,109, 98,101,114, 0, 2, 0, 0, 0, 11,116,111, -108,117, 97, 95,118, 97,114, 95, 0, 2, 0, 0, 0, 10, 99,104,101, 99,107,110, - 97,109,101, 0, 4, 0, 0, 0, 45, 0, 0, 0, 17, 64,100,101, 99,108, 97,114, - 97,116,105,111,110, 46,108,117, 97, 0, 0, 0, 1,140, 12, 1, 60, 47, 15, 0, - 13, 0, 18, 2, 7, 1, 7, 1, 2, 1, 3, 11, 3, 32, 48, 10, 15, 4, 13, 0, - 18, 5, 2, 1, 1, 44, 52, 70, 60, 48, 13, 0, 11, 2, 13, 0, 18, 5, 13, 0, - 18, 2, 42, 26, 60, 49, 15, 7, 13, 0, 18, 8, 11, 9, 2, 1, 2, 60, 50, 13, - 0, 11, 5, 13, 1, 13, 1, 18, 10, 16, 26, 60, 51, 13, 0, 11, 8, 15, 11, 13, - 1, 7, 1, 13, 1, 18, 10, 7, 1, 38, 2, 1, 3, 26, 5, 1, 50, 2, 60, 52, - 60, 54, 15, 7, 13, 0, 18, 2, 11, 13, 2, 1, 2, 60, 55, 13, 1, 18, 10, 7, - 2, 32, 52, 28, 60, 56, 13, 0, 11, 2, 13, 1, 7, 1, 16, 26, 60, 57, 13, 0, - 11, 14, 13, 1, 13, 1, 18, 10, 16, 26, 50, 2, 60, 58, 60, 60, 15, 18, 13, 0, - 18, 2, 11, 19, 2, 3, 2, 60, 61, 13, 2, 52, 34, 60, 62, 13, 0, 11, 2, 15, - 0, 13, 0, 18, 2, 7, 1, 13, 2, 7, 1, 38, 2, 1, 3, 26, 60, 63, 13, 0, - 11, 20, 13, 4, 26, 50, 2, 60, 64, 60, 67, 13, 0, 18, 5, 11, 21, 31, 48, 7, - 13, 0, 18, 5, 11, 22, 31, 48, 7, 13, 0, 18, 2, 11, 21, 32, 52, 14, 60, 68, - 13, 0, 11, 2, 15, 23, 2, 1, 0, 26, 50,135, 60, 69, 13, 0, 18, 24, 11, 25, - 32, 52,122, 60, 70, 13, 0, 18, 5, 11, 21, 32, 48, 7, 13, 0, 18, 2, 11, 21, - 31, 52, 30, 60, 71, 13, 0, 11, 5, 13, 0, 18, 5, 13, 0, 18, 2, 42, 26, 60, - 72, 13, 0, 11, 2, 15, 23, 2, 1, 0, 26, 50, 70, 60, 73, 15, 4, 13, 0, 18, - 2, 2, 1, 1, 52, 55, 60, 74, 13, 0, 18, 5, 11, 21, 32, 52, 11, 13, 0, 11, - 5, 13, 0, 18, 2, 26, 50, 19, 60, 75, 13, 0, 11, 5, 13, 0, 18, 5, 11, 26, - 42, 13, 0, 18, 2, 42, 26, 60, 76, 13, 0, 11, 2, 15, 23, 2, 1, 0, 26, 50, - 2, 60, 77, 50, 2, 60, 78, 60, 80, 0, 0, 0, 0, 7, 0, 0, 0, 45, 0, 0, - 0, 5,115,101,108,102, 0, 0, 0, 0, 49, 0, 0, 0, 2,109, 0, 0, 0, 0, - 51, 0, 0, 0, 0, 0, 0, 0, 54, 0, 0, 0, 2,116, 0, 0, 0, 0, 60, 0, - 0, 0, 2, 98, 0, 0, 0, 0, 60, 0, 0, 0, 2,101, 0, 0, 0, 0, 60, 0, - 0, 0, 2,100, 0, 0, 0, 0, 27, 2, 0, 0, 0, 7,115,116,114,115,117, 98, - 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 5,110, 97,109,101, - 0, 2, 0, 0, 0, 2, 91, 0, 2, 0, 0, 0, 7,105,115,116,121,112,101, 0, - 2, 0, 0, 0, 5,116,121,112,101, 0, 2, 0, 0, 0, 2,109, 0, 2, 0, 0, - 0, 6,115,112,108,105,116, 0, 2, 0, 0, 0, 4,109,111,100, 0, 2, 0, 0, - 0, 6, 37,115, 37,115, 42, 0, 2, 0, 0, 0, 2,110, 0, 2, 0, 0, 0, 7, - 99,111,110, 99, 97,116, 0, 2, 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 2, 61, - 0, 2, 0, 0, 0, 4,100,101,102, 0, 2, 0, 0, 0, 2, 98, 0, 2, 0, 0, - 0, 2,101, 0, 2, 0, 0, 0, 2,100, 0, 2, 0, 0, 0, 8,115,116,114,102, -105,110,100, 0, 2, 0, 0, 0, 9, 37, 91, 40, 46, 45, 41, 37, 93, 0, 2, 0, - 0, 0, 4,100,105,109, 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 5,118,111, -105,100, 0, 2, 0, 0, 0, 15, 99,114,101, 97,116,101, 95,118, 97,114,110, 97, -109,101, 0, 2, 0, 0, 0, 5,107,105,110,100, 0, 2, 0, 0, 0, 4,118, 97, -114, 0, 2, 0, 0, 0, 2, 32, 0, 2, 0, 0, 0, 10, 99,104,101, 99,107,116, -121,112,101, 0, 4, 0, 0, 0, 84, 0, 0, 0, 17, 64,100,101, 99,108, 97,114, - 97,116,105,111,110, 46,108,117, 97, 0, 0, 0, 0,152, 4, 1, 60, 87, 15, 0, - 13, 0, 18, 2, 2, 1, 1, 48, 7, 13, 0, 18, 3, 11, 4, 31, 52, 22, 60, 88, - 13, 0, 11, 5, 13, 0, 18, 3, 26, 60, 89, 13, 0, 11, 3, 4, 0, 26, 50, 2, - 60, 90, 60, 93, 13, 0, 18, 6, 11, 4, 31, 48, 7, 13, 0, 18, 5, 11, 4, 31, - 52, 11, 60, 94, 15, 7, 11, 8, 2, 0, 1, 50, 2, 60, 95, 60, 98, 13, 0, 18, - 2, 11, 4, 31, 52, 13, 60, 99, 15, 9, 13, 0, 18, 2, 2, 0, 1, 50, 2, 60, -100, 60,103, 13, 0, 18, 2, 11, 10, 32, 52, 9, 13, 0, 11, 2, 11, 11, 26, 50, - 22, 60,104, 13, 0, 18, 2, 11, 12, 32, 52, 9, 13, 0, 11, 2, 11, 13, 26, 50, - 2, 60,105, 60,114, 0, 0, 0, 0, 1, 0, 0, 0, 84, 0, 0, 0, 5,115,101, -108,102, 0, 0, 0, 0, 14, 2, 0, 0, 0, 8,105,115, 98, 97,115,105, 99, 0, - 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 5,116,121,112,101, 0, - 2, 0, 0, 0, 4,112,116,114, 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 4, -114,101,116, 0, 2, 0, 0, 0, 4,100,105,109, 0, 2, 0, 0, 0, 6,101,114, -114,111,114, 0, 2, 0, 0, 0, 53, 35,105,110,118, 97,108,105,100, 32,112, 97, -114, 97,109,101,116,101,114, 58, 32, 99, 97,110,110,111,116, 32,114,101,116,117, -114,110, 32, 97,110, 32, 97,114,114, 97,121, 32,111,102, 32,118, 97,108,117,101, -115, 0, 2, 0, 0, 0, 8,114,101,103,116,121,112,101, 0, 2, 0, 0, 0, 10, - 95,117,115,101,114,100, 97,116, 97, 0, 2, 0, 0, 0, 6,118,111,105,100, 42, - 0, 2, 0, 0, 0, 9, 95, 99,115,116,114,105,110,103, 0, 2, 0, 0, 0, 6, - 99,104, 97,114, 42, 0, 2, 0, 0, 0, 6,112,114,105,110,116, 0, 4, 0, 0, - 0,117, 0, 0, 0, 17, 64,100,101, 99,108, 97,114, 97,116,105,111,110, 46,108, -117, 97, 0, 0, 0, 0,172, 6, 3, 60,118, 15, 2, 13, 1, 11, 3, 42, 2, 0, - 1, 60,119, 15, 2, 13, 1, 11, 4, 42, 13, 0, 18, 6, 42, 11, 7, 42, 2, 0, - 1, 60,120, 15, 2, 13, 1, 11, 8, 42, 13, 0, 18, 9, 42, 11, 7, 42, 2, 0, - 1, 60,121, 15, 2, 13, 1, 11, 10, 42, 13, 0, 18, 11, 42, 11, 7, 42, 2, 0, - 1, 60,122, 15, 2, 13, 1, 11, 12, 42, 13, 0, 18, 13, 42, 11, 7, 42, 2, 0, - 1, 60,123, 15, 2, 13, 1, 11, 14, 42, 13, 0, 18, 15, 42, 11, 7, 42, 2, 0, - 1, 60,124, 15, 2, 13, 1, 11, 16, 42, 13, 0, 18, 17, 42, 11, 7, 42, 2, 0, - 1, 60,125, 15, 2, 13, 1, 11, 18, 42, 13, 0, 18, 19, 42, 11, 7, 42, 2, 0, - 1, 60,126, 15, 2, 13, 1, 11, 20, 42, 13, 2, 42, 2, 0, 1, 60,127, 0, 0, - 0, 0, 3, 0, 0, 0,117, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0,117, - 0, 0, 0, 6,105,100,101,110,116, 0, 0, 0, 0,117, 0, 0, 0, 6, 99,108, -111,115,101, 0, 0, 0, 0, 21, 2, 0, 0, 0, 6,105,100,101,110,116, 0, 2, - 0, 0, 0, 6, 99,108,111,115,101, 0, 2, 0, 0, 0, 6,112,114,105,110,116, - 0, 2, 0, 0, 0, 13, 68,101, 99,108, 97,114, 97,116,105,111,110,123, 0, 2, - 0, 0, 0, 10, 32,109,111,100, 32, 32, 61, 32, 39, 0, 2, 0, 0, 0, 5,115, -101,108,102, 0, 2, 0, 0, 0, 4,109,111,100, 0, 2, 0, 0, 0, 3, 39, 44, - 0, 2, 0, 0, 0, 10, 32,116,121,112,101, 32, 61, 32, 39, 0, 2, 0, 0, 0, - 5,116,121,112,101, 0, 2, 0, 0, 0, 10, 32,112,116,114, 32, 32, 61, 32, 39, - 0, 2, 0, 0, 0, 4,112,116,114, 0, 2, 0, 0, 0, 10, 32,110, 97,109,101, - 32, 61, 32, 39, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 10, - 32,100,105,109, 32, 32, 61, 32, 39, 0, 2, 0, 0, 0, 4,100,105,109, 0, 2, - 0, 0, 0, 10, 32,100,101,102, 32, 32, 61, 32, 39, 0, 2, 0, 0, 0, 4,100, -101,102, 0, 2, 0, 0, 0, 10, 32,114,101,116, 32, 32, 61, 32, 39, 0, 2, 0, - 0, 0, 4,114,101,116, 0, 2, 0, 0, 0, 2,125, 0, 2, 0, 0, 0, 8,100, -101, 99,108,116, 97,103, 0, 4, 0, 0, 0,130, 0, 0, 0, 17, 64,100,101, 99, -108, 97,114, 97,116,105,111,110, 46,108,117, 97, 0, 0, 0, 0, 56, 10, 1, 60, -131, 13, 0, 11, 1, 13, 0, 11, 2, 15, 3, 13, 0, 18, 4, 15, 5, 13, 0, 18, - 6, 11, 7, 2, 1, 2, 2, 2, 2, 27, 1, 27, 2, 5, 4, 60,132, 15, 8, 13, - 0, 18, 1, 13, 0, 18, 2, 2, 0, 2, 60,133, 0, 0, 0, 0, 1, 0, 0, 0, -130, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 9, 2, 0, 0, 0, 5,115, -101,108,102, 0, 2, 0, 0, 0, 6,105,116,121,112,101, 0, 2, 0, 0, 0, 4, -116, 97,103, 0, 2, 0, 0, 0, 7,116, 97,103,118, 97,114, 0, 2, 0, 0, 0, - 5,116,121,112,101, 0, 2, 0, 0, 0, 8,115,116,114,102,105,110,100, 0, 2, - 0, 0, 0, 4,109,111,100, 0, 2, 0, 0, 0, 6, 99,111,110,115,116, 0, 2, - 0, 0, 0, 8,100,101, 99,108,116, 97,103, 0, 2, 0, 0, 0, 13,111,117,116, - 99,104,101, 99,107,116,121,112,101, 0, 4, 0, 0, 0,136, 0, 0, 0, 17, 64, -100,101, 99,108, 97,114, 97,116,105,111,110, 46,108,117, 97, 0, 0, 0, 0, 83, - 6, 2, 60,137, 4, 1, 60,138, 13, 0, 18, 4, 11, 5, 31, 52, 14, 60,139, 11, - 6, 23, 2, 60,140, 7, 0, 23, 3, 50, 25, 60,142, 13, 0, 18, 1, 23, 2, 60, -143, 13, 0, 18, 2, 11, 5, 31, 46, 2, 7, 0, 23, 3, 60,144, 60,145, 11, 7, - 13, 1, 42, 11, 8, 42, 13, 2, 42, 11, 8, 42, 13, 3, 42, 11, 9, 42, 1, 4, - 60,146, 0, 0, 0, 0, 4, 0, 0, 0,136, 0, 0, 0, 5,115,101,108,102, 0, - 0, 0, 0,136, 0, 0, 0, 5,110, 97,114,103, 0, 0, 0, 0,137, 0, 0, 0, - 4,116, 97,103, 0, 0, 0, 0,137, 0, 0, 0, 4,100,101,102, 0, 0, 0, 0, - 10, 2, 0, 0, 0, 5,110, 97,114,103, 0, 2, 0, 0, 0, 4,116, 97,103, 0, - 2, 0, 0, 0, 4,100,101,102, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, - 0, 0, 0, 4,100,105,109, 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 16,116, -111,108,117, 97, 95,116, 97,103, 95,116, 97, 98,108,101, 0, 2, 0, 0, 0, 14, -116,111,108,117, 97, 95,105,115,116,121,112,101, 40, 0, 2, 0, 0, 0, 2, 44, - 0, 2, 0, 0, 0, 2, 41, 0, 2, 0, 0, 0, 8,100,101, 99,108, 97,114,101, - 0, 4, 0, 0, 0,149, 0, 0, 0, 17, 64,100,101, 99,108, 97,114, 97,116,105, -111,110, 46,108,117, 97, 0, 0, 0, 1, 84, 15, 2, 60,150, 11, 2, 60,151, 13, - 0, 18, 1, 11, 2, 31, 52, 4, 11, 4, 23, 2, 60,152, 15, 5, 11, 6, 13, 0, - 18, 7, 13, 0, 18, 8, 13, 2, 2, 0, 4, 60,153, 13, 0, 18, 9, 11, 2, 31, - 48, 12, 15, 10, 13, 0, 18, 9, 2, 1, 1, 4, 0, 32, 52, 11, 60,154, 15, 5, - 11, 4, 2, 0, 1, 50, 2, 60,155, 60,156, 15, 5, 13, 0, 18, 11, 2, 0, 1, - 60,157, 13, 0, 18, 9, 11, 2, 31, 52, 76, 60,158, 15, 10, 13, 0, 18, 9, 2, - 1, 1, 4, 0, 31, 52, 17, 60,159, 15, 5, 11, 12, 13, 0, 18, 9, 11, 13, 2, - 0, 3, 50, 41, 60,161, 15, 5, 11, 14, 13, 0, 18, 7, 13, 0, 18, 8, 13, 2, - 11, 15, 60,162, 11, 16, 13, 0, 18, 9, 11, 17, 13, 0, 18, 8, 13, 2, 11, 18, - 2, 0, 11, 60,163, 50,161, 60,165, 15, 20, 13, 0, 18, 8, 2, 1, 1, 60,166, - 15, 5, 11, 21, 2, 0, 1, 60,167, 13, 3, 44, 48, 5, 13, 2, 11, 2, 32, 52, - 7, 15, 5, 11, 4, 2, 0, 1, 60,168, 15, 5, 11, 22, 13, 0, 18, 7, 13, 0, - 18, 8, 2, 0, 3, 60,169, 13, 3, 44, 52, 11, 60,170, 15, 5, 11, 4, 2, 0, - 1, 50, 2, 60,171, 60,172, 15, 5, 11, 23, 2, 0, 1, 60,173, 7, 0, 60,174, - 13, 0, 18, 24, 11, 2, 31, 52, 6, 13, 0, 18, 24, 23, 4, 60,175, 13, 3, 52, - 24, 60,176, 15, 5, 11, 25, 13, 3, 42, 11, 26, 13, 1, 11, 27, 13, 4, 11, 18, - 2, 0, 6, 50, 19, 60,178, 15, 5, 11, 28, 13, 1, 11, 27, 13, 4, 11, 18, 2, - 0, 5, 60,179, 5, 2, 60,180, 60,181, 0, 0, 0, 0, 7, 0, 0, 0,149, 0, - 0, 0, 5,115,101,108,102, 0, 0, 0, 0,149, 0, 0, 0, 5,110, 97,114,103, - 0, 0, 0, 0,150, 0, 0, 0, 4,112,116,114, 0, 0, 0, 0,165, 0, 0, 0, - 2,116, 0, 0, 0, 0,173, 0, 0, 0, 4,100,101,102, 0, 0, 0, 0,179, 0, - 0, 0, 0, 0, 0, 0,179, 0, 0, 0, 0, 0, 0, 0, 29, 2, 0, 0, 0, 5, -110, 97,114,103, 0, 2, 0, 0, 0, 4,112,116,114, 0, 2, 0, 0, 0, 1, 0, - 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 2, 42, 0, 2, 0, 0, - 0, 7,111,117,116,112,117,116, 0, 2, 0, 0, 0, 2, 32, 0, 2, 0, 0, 0, - 4,109,111,100, 0, 2, 0, 0, 0, 5,116,121,112,101, 0, 2, 0, 0, 0, 4, -100,105,109, 0, 2, 0, 0, 0, 9,116,111,110,117,109, 98,101,114, 0, 2, 0, - 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 2, 91, 0, 2, 0, 0, 0, 3, - 93, 59, 0, 2, 0, 0, 0, 5, 32, 61, 32, 40, 0, 2, 0, 0, 0, 3, 42, 41, - 0, 2, 0, 0, 0, 8,109, 97,108,108,111, 99, 40, 0, 2, 0, 0, 0, 9, 42, -115,105,122,101,111,102, 40, 0, 2, 0, 0, 0, 4, 41, 41, 59, 0, 2, 0, 0, - 0, 2,116, 0, 2, 0, 0, 0, 8,105,115, 98, 97,115,105, 99, 0, 2, 0, 0, - 0, 4, 32, 61, 32, 0, 2, 0, 0, 0, 3, 40, 40, 0, 2, 0, 0, 0, 3, 41, - 32, 0, 2, 0, 0, 0, 4,100,101,102, 0, 2, 0, 0, 0, 10,116,111,108,117, - 97, 95,103,101,116, 0, 2, 0, 0, 0, 2, 40, 0, 2, 0, 0, 0, 2, 44, 0, - 2, 0, 0, 0, 19,116,111,108,117, 97, 95,103,101,116,117,115,101,114,116,121, -112,101, 40, 0, 2, 0, 0, 0, 9,103,101,116, 97,114,114, 97,121, 0, 4, 0, - 0, 0,184, 0, 0, 0, 17, 64,100,101, 99,108, 97,114, 97,116,105,111,110, 46, -108,117, 97, 0, 0, 0, 1, 78, 13, 2, 60,185, 13, 0, 18, 2, 11, 3, 31, 51, - 1, 59, 60,186, 15, 4, 11, 5, 2, 0, 1, 60,187, 13, 0, 18, 6, 11, 3, 31, - 46, 2, 7, 0, 60,188, 15, 4, 11, 7, 13, 1, 11, 8, 13, 0, 18, 9, 11, 8, - 13, 0, 18, 2, 11, 8, 13, 2, 11, 10, 2, 0, 9, 60,189, 15, 4, 11, 11, 2, - 0, 1, 60,190, 15, 4, 11, 12, 2, 0, 1, 60,191, 15, 4, 11, 13, 2, 0, 1, - 60,192, 15, 4, 11, 14, 2, 0, 1, 60,193, 15, 4, 11, 15, 13, 1, 11, 16, 2, - 0, 3, 60,194, 15, 4, 11, 17, 13, 0, 18, 2, 42, 11, 18, 42, 2, 0, 1, 60, -195, 15, 20, 13, 0, 18, 21, 2, 1, 1, 60,196, 11, 3, 60,197, 13, 0, 18, 22, - 11, 3, 31, 52, 4, 11, 23, 23, 4, 60,198, 15, 4, 11, 24, 13, 0, 18, 25, 11, - 26, 42, 2, 0, 2, 60,199, 13, 3, 44, 48, 5, 13, 4, 11, 3, 32, 52, 7, 15, - 4, 11, 23, 2, 0, 1, 60,200, 15, 4, 11, 27, 13, 0, 18, 28, 13, 0, 18, 21, - 2, 0, 3, 60,201, 13, 3, 44, 52, 11, 60,202, 15, 4, 11, 23, 2, 0, 1, 50, - 2, 60,203, 60,204, 15, 4, 11, 29, 2, 0, 1, 60,205, 7, 0, 60,206, 13, 0, - 18, 6, 11, 3, 31, 52, 6, 13, 0, 18, 6, 23, 5, 60,207, 13, 3, 52, 21, 60, -208, 15, 4, 11, 30, 13, 3, 42, 11, 31, 42, 13, 5, 11, 32, 2, 0, 3, 50, 15, - 60,210, 15, 4, 11, 33, 13, 5, 11, 32, 2, 0, 3, 60,211, 60,212, 15, 4, 11, - 34, 2, 0, 1, 60,213, 15, 4, 11, 35, 2, 0, 1, 5, 4, 50, 2, 60,214, 60, -215, 0, 0, 0, 0, 10, 0, 0, 0,184, 0, 0, 0, 5,115,101,108,102, 0, 0, - 0, 0,184, 0, 0, 0, 5,110, 97,114,103, 0, 0, 0, 0,187, 0, 0, 0, 4, -100,101,102, 0, 0, 0, 0,195, 0, 0, 0, 2,116, 0, 0, 0, 0,196, 0, 0, - 0, 4,112,116,114, 0, 0, 0, 0,205, 0, 0, 0, 4,100,101,102, 0, 0, 0, - 0,213, 0, 0, 0, 0, 0, 0, 0,213, 0, 0, 0, 0, 0, 0, 0,213, 0, 0, - 0, 0, 0, 0, 0,213, 0, 0, 0, 0, 0, 0, 0, 36, 2, 0, 0, 0, 5,110, - 97,114,103, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 4,100, -105,109, 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 7,111,117,116,112,117,116, - 0, 2, 0, 0, 0, 4, 32, 32,123, 0, 2, 0, 0, 0, 4,100,101,102, 0, 2, - 0, 0, 0, 27, 32, 32, 32,105,102, 32, 40, 33,116,111,108,117, 97, 95, 97,114, -114, 97,121,105,115,116,121,112,101, 40, 0, 2, 0, 0, 0, 2, 44, 0, 2, 0, - 0, 0, 4,116, 97,103, 0, 2, 0, 0, 0, 3, 41, 41, 0, 2, 0, 0, 0, 16, - 32, 32, 32, 32,103,111,116,111, 32,101,114,114,111,114, 59, 0, 2, 0, 0, 0, - 9, 32, 32, 32,101,108,115,101, 10, 0, 2, 0, 0, 0, 5, 32, 32, 32,123, 0, - 2, 0, 0, 0, 11, 32, 32, 32, 32,105,110,116, 32,105, 59, 0, 2, 0, 0, 0, - 34, 32, 32, 32, 32,108,117, 97, 95, 79, 98,106,101, 99,116, 32,108,111, 32, 61, - 32,108,117, 97, 95,103,101,116,112, 97,114, 97,109, 40, 0, 2, 0, 0, 0, 3, - 41, 59, 0, 2, 0, 0, 0, 16, 32, 32, 32, 32,102,111,114, 40,105, 61, 48, 59, - 32,105, 60, 0, 2, 0, 0, 0, 6, 59,105, 43, 43, 41, 0, 2, 0, 0, 0, 2, -116, 0, 2, 0, 0, 0, 8,105,115, 98, 97,115,105, 99, 0, 2, 0, 0, 0, 5, -116,121,112,101, 0, 2, 0, 0, 0, 4,112,116,114, 0, 2, 0, 0, 0, 2, 42, - 0, 2, 0, 0, 0, 4, 32, 32, 32, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, - 2, 0, 0, 0, 7, 91,105, 93, 32, 61, 32, 0, 2, 0, 0, 0, 3, 40, 40, 0, - 2, 0, 0, 0, 4,109,111,100, 0, 2, 0, 0, 0, 3, 41, 32, 0, 2, 0, 0, - 0, 15,116,111,108,117, 97, 95,103,101,116,102,105,101,108,100, 0, 2, 0, 0, - 0, 9, 40,108,111, 44,105, 43, 49, 44, 0, 2, 0, 0, 0, 4, 41, 41, 59, 0, - 2, 0, 0, 0, 31,116,111,108,117, 97, 95,103,101,116,102,105,101,108,100,117, -115,101,114,116,121,112,101, 40,108,111, 44,105, 43, 49, 44, 0, 2, 0, 0, 0, - 5, 32, 32, 32,125, 0, 2, 0, 0, 0, 4, 32, 32,125, 0, 2, 0, 0, 0, 9, -115,101,116, 97,114,114, 97,121, 0, 4, 0, 0, 0,218, 0, 0, 0, 17, 64,100, -101, 99,108, 97,114, 97,116,105,111,110, 46,108,117, 97, 0, 0, 0, 1, 42, 9, - 2, 60,219, 13, 0, 18, 2, 11, 3, 31, 51, 1, 23, 60,220, 15, 4, 11, 5, 2, - 0, 1, 60,221, 15, 4, 11, 6, 2, 0, 1, 60,222, 15, 4, 11, 7, 13, 1, 11, - 8, 2, 0, 3, 60,223, 15, 4, 11, 9, 13, 0, 18, 2, 42, 11, 10, 42, 2, 0, - 1, 60,224, 15, 12, 13, 0, 18, 13, 2, 1, 1, 60,225, 13, 2, 11, 14, 32, 52, - 23, 60,226, 15, 4, 11, 15, 13, 2, 42, 11, 16, 42, 13, 0, 18, 17, 11, 18, 2, - 0, 3, 50,175, 60,227, 13, 2, 52, 23, 60,228, 15, 4, 11, 15, 13, 2, 42, 11, - 19, 42, 13, 0, 18, 17, 11, 18, 2, 0, 3, 50,146, 60,230, 13, 0, 18, 20, 11, - 3, 32, 52,110, 60,231, 15, 4, 11, 21, 2, 0, 1, 60,232, 15, 4, 11, 22, 2, - 0, 1, 60,233, 15, 4, 11, 23, 13, 0, 18, 13, 11, 24, 13, 0, 18, 17, 11, 18, - 2, 0, 5, 60,234, 15, 4, 11, 25, 2, 0, 1, 60,235, 15, 4, 11, 26, 13, 0, - 18, 17, 11, 27, 13, 0, 18, 13, 11, 28, 2, 0, 5, 60,236, 15, 4, 11, 29, 2, - 0, 1, 60,237, 15, 4, 11, 30, 13, 0, 18, 31, 11, 32, 13, 0, 18, 31, 11, 8, - 2, 0, 5, 60,238, 15, 4, 11, 33, 2, 0, 1, 50, 23, 60,242, 15, 4, 11, 34, - 13, 0, 18, 17, 11, 35, 13, 0, 18, 31, 11, 8, 2, 0, 5, 60,243, 60,244, 60, -245, 15, 4, 11, 36, 2, 0, 1, 5, 1, 50, 2, 60,246, 60,247, 0, 0, 0, 0, - 4, 0, 0, 0,218, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0,218, 0, 0, - 0, 5,110, 97,114,103, 0, 0, 0, 0,224, 0, 0, 0, 2,116, 0, 0, 0, 0, -245, 0, 0, 0, 0, 0, 0, 0, 37, 2, 0, 0, 0, 5,110, 97,114,103, 0, 2, - 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 4,100,105,109, 0, 2, 0, - 0, 0, 1, 0, 2, 0, 0, 0, 7,111,117,116,112,117,116, 0, 2, 0, 0, 0, - 4, 32, 32,123, 0, 2, 0, 0, 0, 10, 32, 32, 32,105,110,116, 32,105, 59, 0, - 2, 0, 0, 0, 33, 32, 32, 32,108,117, 97, 95, 79, 98,106,101, 99,116, 32,108, -111, 32, 61, 32,108,117, 97, 95,103,101,116,112, 97,114, 97,109, 40, 0, 2, 0, - 0, 0, 3, 41, 59, 0, 2, 0, 0, 0, 15, 32, 32, 32,102,111,114, 40,105, 61, - 48, 59, 32,105, 60, 0, 2, 0, 0, 0, 6, 59,105, 43, 43, 41, 0, 2, 0, 0, - 0, 2,116, 0, 2, 0, 0, 0, 8,105,115, 98, 97,115,105, 99, 0, 2, 0, 0, - 0, 5,116,121,112,101, 0, 2, 0, 0, 0, 7,110,117,109, 98,101,114, 0, 2, - 0, 0, 0, 19, 32, 32, 32,116,111,108,117, 97, 95,112,117,115,104,102,105,101, -108,100, 0, 2, 0, 0, 0, 17, 40,108,111, 44,105, 43, 49, 44, 40,100,111,117, - 98,108,101, 41, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 6, - 91,105, 93, 41, 59, 0, 2, 0, 0, 0, 9, 40,108,111, 44,105, 43, 49, 44, 0, - 2, 0, 0, 0, 4,112,116,114, 0, 2, 0, 0, 0, 5, 32, 32, 32,123, 0, 2, - 0, 0, 0, 20, 35,105,102,100,101,102, 32, 95, 95, 99,112,108,117,115,112,108, -117,115, 10, 0, 2, 0, 0, 0, 29, 32, 32, 32, 32,118,111,105,100, 42, 32,116, -111,108,117, 97, 73, 95, 99,108,111,110,101, 32, 61, 32,110,101,119, 0, 2, 0, - 0, 0, 2, 40, 0, 2, 0, 0, 0, 7, 35,101,108,115,101, 10, 0, 2, 0, 0, - 0, 45, 32, 32, 32, 32,118,111,105,100, 42, 32,116,111,108,117, 97, 73, 95, 99, -108,111,110,101, 32, 61, 32,116,111,108,117, 97, 95, 99,111,112,121, 40, 40,118, -111,105,100, 42, 41, 38, 0, 2, 0, 0, 0, 12, 91,105, 93, 44,115,105,122,101, -111,102, 40, 0, 2, 0, 0, 0, 4, 41, 41, 59, 0, 2, 0, 0, 0, 8, 35,101, -110,100,105,102, 10, 0, 2, 0, 0, 0, 63, 32, 32, 32, 32,116,111,108,117, 97, - 95,112,117,115,104,102,105,101,108,100,117,115,101,114,116,121,112,101, 40,108, -111, 44,105, 43, 49, 44,116,111,108,117, 97, 95,100,111, 99,108,111,110,101, 40, -116,111,108,117, 97, 73, 95, 99,108,111,110,101, 44, 0, 2, 0, 0, 0, 4,116, - 97,103, 0, 2, 0, 0, 0, 3, 41, 44, 0, 2, 0, 0, 0, 5, 32, 32, 32,125, - 0, 2, 0, 0, 0, 42, 32, 32, 32,116,111,108,117, 97, 95,112,117,115,104,102, -105,101,108,100,117,115,101,114,116,121,112,101, 40,108,111, 44,105, 43, 49, 44, - 40,118,111,105,100, 42, 41, 0, 2, 0, 0, 0, 5, 91,105, 93, 44, 0, 2, 0, - 0, 0, 4, 32, 32,125, 0, 2, 0, 0, 0, 10,102,114,101,101, 97,114,114, 97, -121, 0, 4, 0, 0, 0,250, 0, 0, 0, 17, 64,100,101, 99,108, 97,114, 97,116, -105,111,110, 46,108,117, 97, 0, 0, 0, 0, 49, 5, 1, 60,251, 13, 0, 18, 1, - 11, 2, 31, 48, 12, 15, 3, 13, 0, 18, 1, 2, 1, 1, 4, 0, 32, 52, 17, 60, -252, 15, 4, 11, 5, 13, 0, 18, 6, 11, 7, 2, 0, 3, 50, 2, 60,253, 60,254, - 0, 0, 0, 0, 1, 0, 0, 0,250, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, - 0, 8, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 4,100,105,109, - 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 9,116,111,110,117,109, 98,101,114, - 0, 2, 0, 0, 0, 7,111,117,116,112,117,116, 0, 2, 0, 0, 0, 8, 32, 32, -102,114,101,101, 40, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, - 3, 41, 59, 0, 2, 0, 0, 0, 8,112, 97,115,115,112, 97,114, 0, 4, 0, 0, - 1, 1, 0, 0, 0, 17, 64,100,101, 99,108, 97,114, 97,116,105,111,110, 46,108, -117, 97, 0, 0, 0, 0, 79, 4, 1, 59, 1, 2, 13, 0, 18, 1, 11, 2, 32, 52, - 17, 59, 1, 3, 15, 3, 11, 4, 13, 0, 18, 5, 42, 2, 0, 1, 50, 44, 59, 1, - 4, 13, 0, 18, 6, 11, 4, 32, 52, 17, 59, 1, 5, 15, 3, 11, 2, 13, 0, 18, - 5, 42, 2, 0, 1, 50, 15, 59, 1, 7, 15, 3, 13, 0, 18, 5, 2, 0, 1, 59, - 1, 8, 59, 1, 9, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 5,115,101, -108,102, 0, 0, 0, 0, 7, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, - 0, 4,112,116,114, 0, 2, 0, 0, 0, 2, 38, 0, 2, 0, 0, 0, 7,111,117, -116,112,117,116, 0, 2, 0, 0, 0, 2, 42, 0, 2, 0, 0, 0, 5,110, 97,109, -101, 0, 2, 0, 0, 0, 4,114,101,116, 0, 2, 0, 0, 0, 9,114,101,116,118, - 97,108,117,101, 0, 4, 0, 0, 1, 12, 0, 0, 0, 17, 64,100,101, 99,108, 97, -114, 97,116,105,111,110, 46,108,117, 97, 0, 0, 0, 0,133, 6, 1, 59, 1, 13, - 13, 0, 18, 1, 11, 2, 31, 52,112, 59, 1, 14, 15, 4, 13, 0, 18, 5, 2, 1, - 1, 59, 1, 15, 13, 1, 11, 6, 32, 52, 26, 59, 1, 16, 15, 7, 11, 8, 13, 1, - 42, 11, 9, 42, 13, 0, 18, 10, 42, 11, 11, 42, 2, 0, 1, 50, 60, 59, 1, 17, - 13, 1, 52, 26, 59, 1, 18, 15, 7, 11, 8, 13, 1, 42, 11, 12, 42, 13, 0, 18, - 10, 42, 11, 11, 42, 2, 0, 1, 50, 27, 59, 1, 20, 15, 7, 11, 13, 13, 0, 18, - 10, 42, 11, 14, 42, 13, 0, 18, 15, 11, 11, 2, 0, 3, 59, 1, 21, 5, 1, 50, - 3, 59, 1, 22, 59, 1, 23, 0, 0, 0, 0, 3, 0, 0, 1, 12, 0, 0, 0, 5, -115,101,108,102, 0, 0, 0, 1, 14, 0, 0, 0, 2,116, 0, 0, 0, 1, 21, 0, - 0, 0, 0, 0, 0, 0, 16, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, - 0, 4,114,101,116, 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 2,116, 0, 2, - 0, 0, 0, 8,105,115, 98, 97,115,105, 99, 0, 2, 0, 0, 0, 5,116,121,112, -101, 0, 2, 0, 0, 0, 7,110,117,109, 98,101,114, 0, 2, 0, 0, 0, 7,111, -117,116,112,117,116, 0, 2, 0, 0, 0, 14, 32, 32, 32,116,111,108,117, 97, 95, -112,117,115,104, 0, 2, 0, 0, 0, 10, 40, 40,100,111,117, 98,108,101, 41, 0, - 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 3, 41, 59, 0, 2, 0, - 0, 0, 2, 40, 0, 2, 0, 0, 0, 30, 32, 32, 32,116,111,108,117, 97, 95,112, -117,115,104,117,115,101,114,116,121,112,101, 40, 40,118,111,105,100, 42, 41, 0, - 2, 0, 0, 0, 2, 44, 0, 2, 0, 0, 0, 4,116, 97,103, 0, 2, 0, 0, 0, - 13, 95, 68,101, 99,108, 97,114, 97,116,105,111,110, 0, 4, 0, 0, 1, 26, 0, - 0, 0, 17, 64,100,101, 99,108, 97,114, 97,116,105,111,110, 46,108,117, 97, 0, - 0, 0, 0,136, 8, 1, 59, 1, 27, 13, 0, 18, 1, 48, 7, 13, 0, 18, 1, 11, - 2, 31, 52, 60, 59, 1, 28, 15, 4, 13, 0, 18, 1, 11, 5, 2, 1, 2, 59, 1, - 29, 13, 0, 11, 1, 13, 1, 7, 1, 16, 26, 59, 1, 30, 13, 0, 11, 6, 15, 7, - 13, 1, 7, 2, 16, 46, 5, 13, 1, 7, 1, 16, 11, 8, 11, 2, 2, 1, 3, 26, - 5, 1, 50, 3, 59, 1, 31, 59, 1, 32, 13, 0, 11, 9, 15, 10, 26, 59, 1, 33, - 15, 11, 13, 0, 15, 12, 2, 0, 2, 59, 1, 34, 13, 0, 20, 13, 2, 0, 1, 59, - 1, 35, 13, 0, 20, 14, 2, 0, 1, 59, 1, 36, 13, 0, 1, 1, 59, 1, 37, 0, - 0, 0, 0, 3, 0, 0, 1, 26, 0, 0, 0, 2,116, 0, 0, 0, 1, 28, 0, 0, - 0, 2,110, 0, 0, 0, 1, 30, 0, 0, 0, 0, 0, 0, 0, 15, 2, 0, 0, 0, - 2,116, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 1, 0, 2, - 0, 0, 0, 2,110, 0, 2, 0, 0, 0, 6,115,112,108,105,116, 0, 2, 0, 0, - 0, 2, 64, 0, 2, 0, 0, 0, 6,108,110, 97,109,101, 0, 2, 0, 0, 0, 5, -103,115,117, 98, 0, 2, 0, 0, 0, 7, 37, 91, 46, 45, 37, 93, 0, 2, 0, 0, - 0, 6, 95, 98, 97,115,101, 0, 2, 0, 0, 0, 17, 99,108, 97,115,115, 68,101, - 99,108, 97,114, 97,116,105,111,110, 0, 2, 0, 0, 0, 7,115,101,116,116, 97, -103, 0, 2, 0, 0, 0, 10,116,111,108,117, 97, 95,116, 97,103, 0, 2, 0, 0, - 0, 10, 99,104,101, 99,107,110, 97,109,101, 0, 2, 0, 0, 0, 10, 99,104,101, - 99,107,116,121,112,101, 0, 2, 0, 0, 0, 12, 68,101, 99,108, 97,114, 97,116, -105,111,110, 0, 4, 0, 0, 1, 42, 0, 0, 0, 17, 64,100,101, 99,108, 97,114, - 97,116,105,111,110, 46,108,117, 97, 0, 0, 0, 3,164, 20, 2, 59, 1, 44, 15, - 2, 13, 0, 11, 3, 11, 4, 2, 1, 3, 23, 0, 59, 1, 46, 13, 1, 11, 5, 32, - 52, 44, 59, 1, 48, 13, 0, 11, 6, 32, 46, 5, 13, 0, 11, 7, 32, 52, 22, 59, - 1, 49, 15, 8, 22, 2, 11, 9, 11, 7, 11, 1, 13, 1, 30, 1, 3, 2, 1, 50, - 3, 59, 1, 50, 50, 3, 59, 1, 51, 59, 1, 54, 15, 11, 13, 0, 11, 12, 2, 1, - 2, 59, 1, 55, 13, 2, 18, 13, 7, 2, 32, 52,126, 59, 1, 56, 13, 1, 11, 14, - 32, 52, 15, 59, 1, 57, 15, 15, 11, 16, 13, 0, 42, 2, 0, 1, 50, 3, 59, 1, - 58, 59, 1, 59, 15, 11, 13, 2, 7, 1, 16, 11, 18, 2, 1, 2, 59, 1, 60, 15, - 8, 22, 6, 59, 1, 61, 11, 19, 13, 2, 7, 2, 16, 11, 20, 59, 1, 62, 11, 21, - 11, 22, 59, 1, 63, 11, 23, 11, 9, 59, 1, 64, 13, 3, 13, 3, 18, 13, 16, 11, - 24, 59, 1, 65, 15, 25, 13, 3, 7, 1, 13, 3, 18, 13, 7, 1, 38, 2, 1, 3, - 11, 1, 59, 1, 66, 13, 1, 30, 5, 59, 1, 67, 3, 4, 1, 5, 1, 50, 3, 59, - 1, 68, 59, 1, 71, 15, 11, 13, 0, 11, 26, 2, 1, 2, 23, 2, 59, 1, 72, 13, - 2, 18, 13, 7, 2, 32, 52,126, 59, 1, 73, 13, 1, 11, 14, 32, 52, 15, 59, 1, - 74, 15, 15, 11, 16, 13, 0, 42, 2, 0, 1, 50, 3, 59, 1, 75, 59, 1, 76, 15, - 11, 13, 2, 7, 1, 16, 11, 18, 2, 1, 2, 59, 1, 77, 15, 8, 22, 6, 59, 1, - 78, 11, 19, 13, 2, 7, 2, 16, 11, 20, 59, 1, 79, 11, 21, 11, 22, 59, 1, 80, - 11, 21, 11, 9, 59, 1, 81, 13, 3, 13, 3, 18, 13, 16, 11, 24, 59, 1, 82, 15, - 25, 13, 3, 7, 1, 13, 3, 18, 13, 7, 1, 38, 2, 1, 3, 11, 1, 59, 1, 83, - 13, 1, 30, 5, 59, 1, 84, 3, 4, 1, 5, 1, 50, 3, 59, 1, 85, 59, 1, 88, - 15, 11, 13, 0, 11, 23, 2, 1, 2, 23, 2, 59, 1, 89, 13, 2, 18, 13, 7, 2, - 32, 52, 91, 59, 1, 90, 15, 11, 13, 2, 7, 1, 16, 11, 18, 2, 1, 2, 59, 1, - 91, 15, 8, 22, 5, 59, 1, 92, 11, 19, 13, 2, 7, 2, 16, 11, 20, 59, 1, 93, - 11, 23, 11, 9, 59, 1, 94, 13, 3, 13, 3, 18, 13, 16, 11, 24, 59, 1, 95, 15, - 25, 13, 3, 7, 1, 13, 3, 18, 13, 7, 1, 38, 2, 1, 3, 11, 1, 59, 1, 96, - 13, 1, 30, 4, 59, 1, 97, 3, 4, 1, 5, 1, 50, 3, 59, 1, 98, 59, 1,101, - 15, 2, 13, 0, 11, 28, 11, 29, 2, 1, 3, 59, 1,102, 15, 11, 13, 3, 11, 30, - 2, 1, 2, 23, 2, 59, 1,103, 13, 2, 18, 31, 7, 2, 32, 52,113, 59, 1,104, - 13, 2, 7, 2, 15, 32, 13, 2, 7, 2, 16, 11, 33, 11, 30, 2, 1, 3, 26, 59, - 1,105, 15, 11, 13, 2, 7, 1, 16, 11, 18, 2, 1, 2, 59, 1,106, 15, 8, 22, - 5, 59, 1,107, 11, 19, 13, 2, 7, 2, 16, 11, 20, 59, 1,108, 11, 21, 11, 9, - 59, 1,109, 13, 4, 13, 4, 18, 31, 16, 11, 24, 59, 1,110, 15, 25, 13, 4, 7, - 1, 13, 4, 18, 31, 7, 1, 38, 2, 1, 3, 11, 1, 59, 1,111, 13, 1, 30, 4, - 59, 1,112, 3, 5, 1, 5, 1, 50, 3, 59, 1,113, 59, 1,115, 13, 1, 11, 5, - 32, 52,129, 59, 1,117, 15, 11, 13, 0, 11, 18, 2, 1, 2, 23, 2, 59, 1,118, - 4, 0, 59, 1,119, 15, 35, 13, 2, 13, 2, 18, 31, 16, 2, 1, 1, 52, 6, 11, - 6, 23, 4, 50, 21, 13, 2, 13, 2, 18, 31, 16, 23, 4, 13, 2, 11, 31, 13, 2, - 18, 31, 7, 1, 38, 26, 59, 1,120, 15, 8, 22, 4, 59, 1,121, 11, 19, 13, 4, - 11, 9, 59, 1,122, 13, 2, 13, 2, 18, 31, 16, 11, 24, 59, 1,123, 15, 25, 13, - 2, 7, 1, 13, 2, 18, 31, 7, 1, 38, 2, 1, 3, 11, 1, 59, 1,124, 13, 1, - 30, 3, 59, 1,125, 3, 5, 1, 5, 1, 50,130, 59, 1,130, 15, 11, 13, 0, 11, - 18, 2, 1, 2, 23, 2, 59, 1,131, 13, 2, 13, 2, 18, 31, 16, 59, 1,132, 4, - 1, 59, 1,133, 13, 2, 18, 31, 7, 1, 35, 52, 38, 59, 1,134, 13, 2, 13, 2, - 18, 31, 7, 1, 38, 16, 23, 5, 59, 1,135, 15, 25, 13, 2, 7, 1, 13, 2, 18, - 31, 7, 2, 38, 2, 1, 3, 23, 6, 50, 3, 59, 1,136, 59, 1,137, 15, 8, 22, - 4, 59, 1,138, 11, 19, 13, 4, 11, 9, 59, 1,139, 13, 5, 11, 24, 59, 1,140, - 13, 6, 11, 1, 59, 1,141, 13, 1, 30, 3, 59, 1,142, 3, 7, 1, 5, 3, 59, - 1,143, 59, 1,145, 0, 0, 0, 0, 20, 0, 0, 1, 42, 0, 0, 0, 2,115, 0, - 0, 0, 1, 42, 0, 0, 0, 5,107,105,110,100, 0, 0, 0, 1, 54, 0, 0, 0, - 2,116, 0, 0, 0, 1, 59, 0, 0, 0, 2,109, 0, 0, 0, 1, 67, 0, 0, 0, - 0, 0, 0, 1, 76, 0, 0, 0, 2,109, 0, 0, 0, 1, 84, 0, 0, 0, 0, 0, - 0, 1, 90, 0, 0, 0, 2,109, 0, 0, 0, 1, 97, 0, 0, 0, 0, 0, 0, 1, -101, 0, 0, 0, 3,115, 49, 0, 0, 0, 1,105, 0, 0, 0, 2,109, 0, 0, 0, - 1,112, 0, 0, 0, 0, 0, 0, 1,118, 0, 0, 0, 2,118, 0, 0, 0, 1,125, - 0, 0, 0, 0, 0, 0, 1,131, 0, 0, 0, 2,118, 0, 0, 0, 1,132, 0, 0, - 0, 3,116,112, 0, 0, 0, 1,132, 0, 0, 0, 3,109,100, 0, 0, 0, 1,142, - 0, 0, 0, 0, 0, 0, 1,142, 0, 0, 0, 0, 0, 0, 1,142, 0, 0, 0, 0, - 0, 0, 0, 38, 2, 0, 0, 0, 2,115, 0, 2, 0, 0, 0, 5,107,105,110,100, - 0, 2, 0, 0, 0, 5,103,115,117, 98, 0, 2, 0, 0, 0, 8, 37,115, 42, 61, - 37,115, 42, 0, 2, 0, 0, 0, 2, 61, 0, 2, 0, 0, 0, 4,118, 97,114, 0, - 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 5,118,111,105,100, 0, 2, 0, 0, 0, - 13, 95, 68,101, 99,108, 97,114, 97,116,105,111,110, 0, 2, 0, 0, 0, 5,116, -121,112,101, 0, 2, 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 6,115,112,108,105, -116, 0, 2, 0, 0, 0, 7, 37, 42, 37,115, 42, 38, 0, 2, 0, 0, 0, 2,110, - 0, 2, 0, 0, 0, 5,102,117,110, 99, 0, 2, 0, 0, 0, 6,101,114,114,111, -114, 0, 2, 0, 0, 0, 32, 35,105,110,118, 97,108,105,100, 32,102,117,110, 99, -116,105,111,110, 32,114,101,116,117,114,110, 32,116,121,112,101, 58, 32, 0, 2, - 0, 0, 0, 2,109, 0, 2, 0, 0, 0, 6, 37,115, 37,115, 42, 0, 2, 0, 0, - 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 4,112,116,114, 0, 2, 0, 0, 0, - 2, 42, 0, 2, 0, 0, 0, 4,114,101,116, 0, 2, 0, 0, 0, 2, 38, 0, 2, - 0, 0, 0, 4,109,111,100, 0, 2, 0, 0, 0, 7, 99,111,110, 99, 97,116, 0, - 2, 0, 0, 0, 8, 37, 42, 37,115, 42, 37, 42, 0, 2, 0, 0, 0, 3,115, 49, - 0, 2, 0, 0, 0, 7, 40, 37, 98, 91, 93, 41, 0, 4, 0, 0, 1,101, 0, 0, - 0, 17, 64,100,101, 99,108, 97,114, 97,116,105,111,110, 46,108,117, 97, 0, 0, - 0, 0, 17, 5, 1, 59, 1,101, 15, 1, 13, 0, 11, 2, 11, 3, 3, 1, 3, 0, - 0, 0, 0, 1, 0, 0, 1,101, 0, 0, 0, 2,110, 0, 0, 0, 0, 4, 2, 0, - 0, 0, 2,110, 0, 2, 0, 0, 0, 5,103,115,117, 98, 0, 2, 0, 0, 0, 3, - 37, 42, 0, 2, 0, 0, 0, 2, 1, 0, 2, 0, 0, 0, 3, 37, 42, 0, 2, 0, - 0, 0, 2,110, 0, 2, 0, 0, 0, 5,103,115,117, 98, 0, 2, 0, 0, 0, 2, - 1, 0, 2, 0, 0, 0, 2,118, 0, 2, 0, 0, 0, 7,105,115,116,121,112,101, - 0, 2, 0, 0, 0, 3,116,112, 0, 2, 0, 0, 0, 3,109,100, 0, -}; - -/* container.lo */ -static char B4[]={ - 27, 76,117, 97, 50, 0, 0, 0, 0, 0, 0, 0, 0, 15, 64, 99,111,110,116, 97, -105,110,101,114, 46,108,117, 97, 0, 0, 0, 0,162, 5, 0, 60, 17, 60, 18, 22, - 2, 60, 19, 11, 1, 4, 0, 11, 2, 60, 20, 15, 3, 30, 1, 60, 21, 25, 0, 60, - 22, 15, 4, 15, 0, 15, 5, 2, 0, 2, 60, 25, 15, 0, 11, 6, 11, 7, 26, 60, - 36, 15, 0, 11, 8, 11, 9, 26, 60, 48, 11, 11, 25, 10, 60, 58, 11, 13, 25, 12, - 60, 63, 11, 15, 25, 14, 60, 68, 11, 17, 25, 16, 60, 73, 11, 19, 25, 18, 60, 78, - 11, 21, 25, 20, 60, 83, 11, 23, 25, 22, 60, 88, 15, 24, 11, 25, 11, 26, 26, 60, - 95, 15, 24, 11, 27, 11, 28, 26, 60,101, 15, 24, 11, 29, 11, 30, 26, 60,110, 15, - 24, 11, 31, 11, 32, 26, 60,129, 15, 24, 11, 33, 11, 34, 26, 60,147, 15, 24, 11, - 35, 11, 36, 26, 59, 1, 49, 15, 24, 11, 37, 11, 38, 26, 0, 0, 0, 0, 0, 0, - 0, 0, 39, 2, 0, 0, 0, 15, 99,108, 97,115,115, 67,111,110,116, 97,105,110, -101,114, 0, 2, 0, 0, 0, 5, 99,117,114,114, 0, 2, 0, 0, 0, 6, 95, 98, - 97,115,101, 0, 2, 0, 0, 0, 13, 99,108, 97,115,115, 70,101, 97,116,117,114, -101, 0, 2, 0, 0, 0, 7,115,101,116,116, 97,103, 0, 2, 0, 0, 0, 10,116, -111,108,117, 97, 95,116, 97,103, 0, 2, 0, 0, 0, 8,100,101, 99,108,116, 97, -103, 0, 4, 0, 0, 0, 25, 0, 0, 0, 15, 64, 99,111,110,116, 97,105,110,101, -114, 46,108,117, 97, 0, 0, 0, 0, 59, 4, 1, 60, 26, 15, 0, 13, 0, 2, 0, - 1, 60, 27, 7, 1, 50, 23, 60, 29, 13, 0, 13, 1, 16, 20, 3, 2, 0, 1, 60, - 30, 13, 1, 7, 1, 37, 23, 1, 60, 31, 60, 28, 13, 0, 13, 1, 16, 54, 32, 60, - 32, 15, 4, 2, 0, 0, 60, 33, 0, 0, 0, 0, 2, 0, 0, 0, 25, 0, 0, 0, - 5,115,101,108,102, 0, 0, 0, 0, 27, 0, 0, 0, 2,105, 0, 0, 0, 0, 5, - 2, 0, 0, 0, 5,112,117,115,104, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, - 2, 0, 0, 0, 2,105, 0, 2, 0, 0, 0, 8,100,101, 99,108,116, 97,103, 0, - 2, 0, 0, 0, 4,112,111,112, 0, 2, 0, 0, 0, 8,115,117,112, 99,111,100, -101, 0, 4, 0, 0, 0, 36, 0, 0, 0, 15, 64, 99,111,110,116, 97,105,110,101, -114, 46,108,117, 97, 0, 0, 0, 0, 59, 4, 1, 60, 37, 15, 0, 13, 0, 2, 0, - 1, 60, 38, 7, 1, 50, 23, 60, 40, 13, 0, 13, 1, 16, 20, 3, 2, 0, 1, 60, - 41, 13, 1, 7, 1, 37, 23, 1, 60, 42, 60, 39, 13, 0, 13, 1, 16, 54, 32, 60, - 43, 15, 4, 2, 0, 0, 60, 44, 0, 0, 0, 0, 2, 0, 0, 0, 36, 0, 0, 0, - 5,115,101,108,102, 0, 0, 0, 0, 38, 0, 0, 0, 2,105, 0, 0, 0, 0, 5, - 2, 0, 0, 0, 5,112,117,115,104, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, - 2, 0, 0, 0, 2,105, 0, 2, 0, 0, 0, 8,115,117,112, 99,111,100,101, 0, - 2, 0, 0, 0, 4,112,111,112, 0, 2, 0, 0, 0, 11, 95, 67,111,110,116, 97, -105,110,101,114, 0, 4, 0, 0, 0, 48, 0, 0, 0, 15, 64, 99,111,110,116, 97, -105,110,101,114, 46,108,117, 97, 0, 0, 0, 0, 64, 6, 1, 60, 49, 13, 0, 11, - 1, 15, 2, 26, 60, 50, 15, 3, 13, 0, 15, 4, 2, 0, 2, 60, 51, 13, 0, 11, - 5, 7, 0, 26, 60, 52, 13, 0, 11, 6, 22, 1, 11, 5, 7, 0, 30, 0, 26, 60, - 53, 13, 0, 11, 7, 22, 0, 26, 60, 54, 13, 0, 1, 1, 60, 55, 0, 0, 0, 0, - 1, 0, 0, 0, 48, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 8, 2, 0, - 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 6, 95, 98, 97,115,101, 0, 2, - 0, 0, 0, 15, 99,108, 97,115,115, 67,111,110,116, 97,105,110,101,114, 0, 2, - 0, 0, 0, 7,115,101,116,116, 97,103, 0, 2, 0, 0, 0, 10,116,111,108,117, - 97, 95,116, 97,103, 0, 2, 0, 0, 0, 2,110, 0, 2, 0, 0, 0, 9,116,121, -112,101,100,101,102,115, 0, 2, 0, 0, 0, 7,108,110, 97,109,101,115, 0, 2, - 0, 0, 0, 5,112,117,115,104, 0, 4, 0, 0, 0, 58, 0, 0, 0, 15, 64, 99, -111,110,116, 97,105,110,101,114, 46,108,117, 97, 0, 0, 0, 0, 14, 4, 1, 60, - 59, 15, 1, 11, 2, 13, 0, 26, 60, 60, 0, 0, 0, 0, 1, 0, 0, 0, 58, 0, - 0, 0, 2,116, 0, 0, 0, 0, 3, 2, 0, 0, 0, 2,116, 0, 2, 0, 0, 0, - 15, 99,108, 97,115,115, 67,111,110,116, 97,105,110,101,114, 0, 2, 0, 0, 0, - 5, 99,117,114,114, 0, 2, 0, 0, 0, 4,112,111,112, 0, 4, 0, 0, 0, 63, - 0, 0, 0, 15, 64, 99,111,110,116, 97,105,110,101,114, 46,108,117, 97, 0, 0, - 0, 0, 18, 3, 0, 60, 64, 15, 0, 11, 1, 15, 0, 18, 1, 18, 2, 26, 60, 65, - 0, 0, 0, 0, 0, 0, 0, 0, 3, 2, 0, 0, 0, 15, 99,108, 97,115,115, 67, -111,110,116, 97,105,110,101,114, 0, 2, 0, 0, 0, 5, 99,117,114,114, 0, 2, - 0, 0, 0, 7,112, 97,114,101,110,116, 0, 2, 0, 0, 0, 7, 97,112,112,101, -110,100, 0, 4, 0, 0, 0, 68, 0, 0, 0, 15, 64, 99,111,110,116, 97,105,110, -101,114, 46,108,117, 97, 0, 0, 0, 0, 18, 4, 1, 60, 69, 15, 1, 18, 2, 20, - 3, 13, 0, 3, 1, 2, 60, 70, 0, 0, 0, 0, 1, 0, 0, 0, 68, 0, 0, 0, - 2,116, 0, 0, 0, 0, 4, 2, 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 15, 99, -108, 97,115,115, 67,111,110,116, 97,105,110,101,114, 0, 2, 0, 0, 0, 5, 99, -117,114,114, 0, 2, 0, 0, 0, 7, 97,112,112,101,110,100, 0, 2, 0, 0, 0, - 14, 97,112,112,101,110,100,116,121,112,101,100,101,102, 0, 4, 0, 0, 0, 73, - 0, 0, 0, 15, 64, 99,111,110,116, 97,105,110,101,114, 46,108,117, 97, 0, 0, - 0, 0, 18, 4, 1, 60, 74, 15, 1, 18, 2, 20, 3, 13, 0, 3, 1, 2, 60, 75, - 0, 0, 0, 0, 1, 0, 0, 0, 73, 0, 0, 0, 2,116, 0, 0, 0, 0, 4, 2, - 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 15, 99,108, 97,115,115, 67,111,110,116, - 97,105,110,101,114, 0, 2, 0, 0, 0, 5, 99,117,114,114, 0, 2, 0, 0, 0, - 14, 97,112,112,101,110,100,116,121,112,101,100,101,102, 0, 2, 0, 0, 0, 12, -102,105,110,100,116,121,112,101,100,101,102, 0, 4, 0, 0, 0, 78, 0, 0, 0, - 15, 64, 99,111,110,116, 97,105,110,101,114, 46,108,117, 97, 0, 0, 0, 0, 18, - 4, 1, 60, 79, 15, 1, 18, 2, 20, 3, 13, 0, 3, 1, 2, 60, 80, 0, 0, 0, - 0, 1, 0, 0, 0, 78, 0, 0, 0, 5,116,121,112,101, 0, 0, 0, 0, 4, 2, - 0, 0, 0, 5,116,121,112,101, 0, 2, 0, 0, 0, 15, 99,108, 97,115,115, 67, -111,110,116, 97,105,110,101,114, 0, 2, 0, 0, 0, 5, 99,117,114,114, 0, 2, - 0, 0, 0, 12,102,105,110,100,116,121,112,101,100,101,102, 0, 2, 0, 0, 0, - 10,105,115,116,121,112,101,100,101,102, 0, 4, 0, 0, 0, 83, 0, 0, 0, 15, - 64, 99,111,110,116, 97,105,110,101,114, 46,108,117, 97, 0, 0, 0, 0, 18, 4, - 1, 60, 84, 15, 1, 18, 2, 20, 3, 13, 0, 3, 1, 2, 60, 85, 0, 0, 0, 0, - 1, 0, 0, 0, 83, 0, 0, 0, 5,116,121,112,101, 0, 0, 0, 0, 4, 2, 0, - 0, 0, 5,116,121,112,101, 0, 2, 0, 0, 0, 15, 99,108, 97,115,115, 67,111, -110,116, 97,105,110,101,114, 0, 2, 0, 0, 0, 5, 99,117,114,114, 0, 2, 0, - 0, 0, 10,105,115,116,121,112,101,100,101,102, 0, 2, 0, 0, 0, 15, 99,108, - 97,115,115, 67,111,110,116, 97,105,110,101,114, 0, 2, 0, 0, 0, 7, 97,112, -112,101,110,100, 0, 4, 0, 0, 0, 88, 0, 0, 0, 15, 64, 99,111,110,116, 97, -105,110,101,114, 46,108,117, 97, 0, 0, 0, 0, 39, 6, 2, 60, 89, 13, 0, 11, - 2, 13, 0, 18, 2, 7, 1, 37, 26, 60, 90, 13, 0, 13, 0, 18, 2, 13, 1, 26, - 60, 91, 13, 1, 11, 3, 13, 0, 26, 60, 92, 0, 0, 0, 0, 2, 0, 0, 0, 88, - 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 88, 0, 0, 0, 2,116, 0, 0, - 0, 0, 4, 2, 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, - 2, 0, 0, 0, 2,110, 0, 2, 0, 0, 0, 7,112, 97,114,101,110,116, 0, 2, - 0, 0, 0, 14, 97,112,112,101,110,100,116,121,112,101,100,101,102, 0, 4, 0, - 0, 0, 95, 0, 0, 0, 15, 64, 99,111,110,116, 97,105,110,101,114, 46,108,117, - 97, 0, 0, 0, 0, 38, 6, 2, 60, 96, 13, 0, 18, 2, 11, 3, 13, 0, 18, 2, - 18, 3, 7, 1, 37, 26, 60, 97, 13, 0, 18, 2, 13, 0, 18, 2, 18, 3, 13, 1, - 26, 60, 98, 0, 0, 0, 0, 2, 0, 0, 0, 95, 0, 0, 0, 5,115,101,108,102, - 0, 0, 0, 0, 95, 0, 0, 0, 2,116, 0, 0, 0, 0, 4, 2, 0, 0, 0, 2, -116, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 9,116,121,112, -101,100,101,102,115, 0, 2, 0, 0, 0, 2,110, 0, 2, 0, 0, 0, 9,111,118, -101,114,108,111, 97,100, 0, 4, 0, 0, 0,101, 0, 0, 0, 15, 64, 99,111,110, -116, 97,105,110,101,114, 46,108,117, 97, 0, 0, 0, 0, 67, 6, 2, 60,102, 13, - 0, 18, 2, 13, 1, 16, 44, 52, 13, 60,103, 13, 0, 18, 2, 13, 1, 7, 0, 26, - 50, 21, 60,105, 13, 0, 18, 2, 13, 1, 13, 0, 18, 2, 13, 1, 16, 7, 1, 37, - 26, 60,106, 60,107, 15, 3, 11, 4, 13, 0, 18, 2, 13, 1, 16, 3, 2, 2, 60, -108, 0, 0, 0, 0, 2, 0, 0, 0,101, 0, 0, 0, 5,115,101,108,102, 0, 0, - 0, 0,101, 0, 0, 0, 6,108,110, 97,109,101, 0, 0, 0, 0, 5, 2, 0, 0, - 0, 6,108,110, 97,109,101, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, - 0, 0, 7,108,110, 97,109,101,115, 0, 2, 0, 0, 0, 7,102,111,114,109, 97, -116, 0, 2, 0, 0, 0, 5, 37, 48, 50,100, 0, 2, 0, 0, 0, 12,102,105,110, -100,116,121,112,101,100,101,102, 0, 4, 0, 0, 0,110, 0, 0, 0, 15, 64, 99, -111,110,116, 97,105,110,101,114, 46,108,117, 97, 0, 0, 0, 0,142, 10, 2, 60, -111, 13, 0, 50,117, 60,113, 13, 2, 18, 3, 52, 97, 60,114, 7, 1, 50, 76, 60, -116, 13, 2, 18, 3, 13, 3, 16, 18, 5, 13, 1, 32, 52, 47, 60,117, 13, 2, 18, - 3, 13, 3, 16, 18, 8, 13, 2, 18, 3, 13, 3, 16, 18, 0, 60,118, 15, 11, 13, - 5, 2, 2, 1, 60,119, 13, 6, 11, 12, 42, 13, 4, 42, 13, 7, 1, 8, 5, 4, - 50, 2, 60,120, 60,121, 13, 3, 7, 1, 37, 23, 3, 60,122, 60,115, 13, 2, 18, - 3, 13, 3, 16, 54, 87, 5, 1, 50, 2, 60,123, 60,124, 13, 2, 18, 13, 23, 2, - 60,125, 60,112, 13, 2, 54,123, 60,126, 11, 14, 13, 1, 1, 3, 60,127, 0, 0, - 0, 0, 13, 0, 0, 0,110, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0,110, - 0, 0, 0, 5,116,121,112,101, 0, 0, 0, 0,111, 0, 0, 0, 4,101,110,118, - 0, 0, 0, 0,114, 0, 0, 0, 2,105, 0, 0, 0, 0,117, 0, 0, 0, 5,109, -111,100, 49, 0, 0, 0, 0,117, 0, 0, 0, 6,116,121,112,101, 49, 0, 0, 0, - 0,118, 0, 0, 0, 5,109,111,100, 50, 0, 0, 0, 0,118, 0, 0, 0, 6,116, -121,112,101, 50, 0, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0,119, 0, 0, 0, - 0, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0,119, 0, 0, 0, 0, 0, 0, 0, -122, 0, 0, 0, 0, 0, 0, 0, 15, 2, 0, 0, 0, 5,116,121,112,101, 0, 2, - 0, 0, 0, 4,101,110,118, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, - 0, 0, 9,116,121,112,101,100,101,102,115, 0, 2, 0, 0, 0, 2,105, 0, 2, - 0, 0, 0, 6,117,116,121,112,101, 0, 2, 0, 0, 0, 5,109,111,100, 49, 0, - 2, 0, 0, 0, 6,116,121,112,101, 49, 0, 2, 0, 0, 0, 4,109,111,100, 0, - 2, 0, 0, 0, 5,109,111,100, 50, 0, 2, 0, 0, 0, 6,116,121,112,101, 50, - 0, 2, 0, 0, 0, 12,102,105,110,100,116,121,112,101,100,101,102, 0, 2, 0, - 0, 0, 2, 32, 0, 2, 0, 0, 0, 7,112, 97,114,101,110,116, 0, 2, 0, 0, - 0, 1, 0, 2, 0, 0, 0, 10,105,115,116,121,112,101,100,101,102, 0, 4, 0, - 0, 0,129, 0, 0, 0, 15, 64, 99,111,110,116, 97,105,110,101,114, 46,108,117, - 97, 0, 0, 0, 0,101, 6, 2, 60,130, 13, 0, 50, 78, 60,132, 13, 2, 18, 3, - 52, 58, 60,133, 7, 1, 50, 37, 60,135, 13, 2, 18, 3, 13, 3, 16, 18, 5, 13, - 1, 32, 52, 8, 60,136, 7, 1, 1, 4, 50, 2, 60,137, 60,138, 13, 3, 7, 1, - 37, 23, 3, 60,139, 60,134, 13, 2, 18, 3, 13, 3, 16, 54, 48, 5, 1, 50, 2, - 60,140, 60,141, 13, 2, 18, 6, 23, 2, 60,142, 60,131, 13, 2, 54, 84, 60,143, - 4, 0, 1, 3, 60,144, 0, 0, 0, 0, 5, 0, 0, 0,129, 0, 0, 0, 5,115, -101,108,102, 0, 0, 0, 0,129, 0, 0, 0, 5,116,121,112,101, 0, 0, 0, 0, -130, 0, 0, 0, 4,101,110,118, 0, 0, 0, 0,133, 0, 0, 0, 2,105, 0, 0, - 0, 0,139, 0, 0, 0, 0, 0, 0, 0, 7, 2, 0, 0, 0, 5,116,121,112,101, - 0, 2, 0, 0, 0, 4,101,110,118, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, - 2, 0, 0, 0, 9,116,121,112,101,100,101,102,115, 0, 2, 0, 0, 0, 2,105, - 0, 2, 0, 0, 0, 6,117,116,121,112,101, 0, 2, 0, 0, 0, 7,112, 97,114, -101,110,116, 0, 2, 0, 0, 0, 8,100,111,112, 97,114,115,101, 0, 4, 0, 0, - 0,147, 0, 0, 0, 15, 64, 99,111,110,116, 97,105,110,101,114, 46,108,117, 97, - 0, 0, 0, 4, 55, 13, 2, 60,151, 15, 5, 13, 1, 11, 6, 2, 4, 2, 60,152, - 13, 2, 52, 42, 60,153, 15, 8, 13, 1, 13, 2, 13, 3, 2, 1, 3, 25, 7, 60, -154, 15, 9, 13, 4, 13, 5, 2, 0, 2, 60,155, 15, 8, 13, 1, 13, 3, 7, 1, - 37, 3, 6, 2, 50, 2, 60,156, 5, 4, 60,157, 60,161, 15, 5, 13, 1, 11, 10, - 2, 3, 2, 60,162, 13, 2, 52, 40, 60,163, 15, 8, 13, 1, 13, 2, 13, 3, 2, - 1, 3, 25, 7, 60,164, 15, 11, 13, 4, 2, 0, 1, 60,165, 15, 8, 13, 1, 13, - 3, 7, 1, 37, 3, 5, 2, 50, 2, 60,166, 5, 3, 60,167, 60,171, 15, 5, 13, - 1, 11, 12, 2, 3, 2, 60,172, 13, 2, 52, 40, 60,173, 15, 8, 13, 1, 13, 2, - 13, 3, 2, 1, 3, 25, 7, 60,174, 15, 13, 13, 4, 2, 0, 1, 60,175, 15, 8, - 13, 1, 13, 3, 7, 1, 37, 3, 5, 2, 50, 2, 60,176, 5, 3, 60,177, 60,180, - 15, 5, 13, 1, 11, 14, 2, 4, 2, 60,181, 13, 2, 52, 52, 60,182, 15, 8, 13, - 1, 13, 2, 13, 3, 2, 1, 3, 25, 7, 60,183, 15, 13, 13, 4, 2, 0, 1, 60, -184, 15, 15, 11, 16, 13, 5, 42, 2, 0, 1, 60,185, 15, 8, 13, 1, 13, 3, 7, - 1, 37, 3, 6, 2, 50, 2, 60,186, 5, 4, 60,187, 60,191, 15, 5, 13, 1, 11, - 21, 2, 6, 2, 60,192, 13, 2, 52, 46, 60,193, 15, 8, 13, 1, 13, 2, 13, 3, - 2, 1, 3, 25, 7, 60,194, 15, 22, 13, 4, 13, 5, 13, 6, 13, 7, 2, 0, 4, - 60,195, 15, 8, 13, 1, 13, 3, 7, 1, 37, 3, 8, 2, 50, 2, 60,196, 5, 6, - 60,197, 60,201, 15, 5, 13, 1, 11, 23, 2, 5, 2, 60,202, 13, 2, 44, 52, 23, - 60,204, 15, 5, 13, 1, 11, 24, 2, 5, 2, 23, 6, 23, 5, 23, 4, 23, 3, 23, - 2, 50, 2, 60,205, 60,206, 13, 2, 52, 44, 60,207, 15, 8, 13, 1, 13, 2, 13, - 3, 2, 1, 3, 25, 7, 60,208, 15, 25, 13, 4, 13, 5, 13, 6, 2, 0, 3, 60, -209, 15, 8, 13, 1, 13, 3, 7, 1, 37, 3, 7, 2, 50, 2, 60,210, 5, 5, 60, -211, 60,215, 15, 5, 13, 1, 11, 26, 2, 5, 2, 60,216, 13, 2, 44, 52, 23, 60, -218, 15, 5, 13, 1, 11, 27, 2, 5, 2, 23, 6, 23, 5, 23, 4, 23, 3, 23, 2, - 50, 2, 60,219, 60,220, 13, 2, 52, 44, 60,221, 15, 8, 13, 1, 13, 2, 13, 3, - 2, 1, 3, 25, 7, 60,222, 15, 25, 13, 4, 13, 5, 13, 6, 2, 0, 3, 60,223, - 15, 8, 13, 1, 13, 3, 7, 1, 37, 3, 7, 2, 50, 2, 60,224, 5, 5, 60,225, - 60,229, 15, 5, 13, 1, 11, 29, 2, 5, 2, 60,230, 13, 2, 44, 52, 59, 60,231, - 15, 5, 13, 1, 11, 30, 2, 5, 2, 23, 6, 23, 5, 23, 4, 23, 3, 23, 2, 60, -232, 13, 2, 44, 52, 27, 60,233, 11, 31, 23, 5, 60,234, 15, 5, 13, 1, 11, 32, - 2, 4, 2, 23, 4, 23, 6, 23, 3, 23, 2, 50, 2, 60,235, 50, 2, 60,236, 60, -237, 13, 2, 52, 80, 60,238, 13, 5, 11, 31, 31, 52, 25, 60,239, 4, 1, 60,240, - 15, 5, 13, 5, 11, 33, 2, 3, 2, 23, 5, 23, 8, 23, 7, 5, 2, 50, 2, 60, -241, 60,242, 15, 8, 13, 1, 13, 2, 13, 3, 2, 1, 3, 25, 7, 60,243, 15, 34, - 13, 4, 13, 5, 13, 6, 2, 0, 3, 60,244, 15, 8, 13, 1, 13, 3, 7, 1, 37, - 3, 7, 2, 50, 2, 60,245, 5, 5, 60,246, 60,250, 15, 5, 13, 1, 11, 36, 2, - 3, 2, 60,251, 13, 2, 52, 40, 60,252, 15, 8, 13, 1, 13, 2, 13, 3, 2, 1, - 3, 25, 7, 60,253, 15, 15, 13, 4, 2, 0, 1, 60,254, 15, 8, 13, 1, 13, 3, - 7, 1, 37, 3, 5, 2, 50, 2, 60,255, 5, 3, 59, 1, 0, 59, 1, 4, 15, 5, - 13, 1, 11, 37, 2, 3, 2, 59, 1, 5, 13, 2, 52, 43, 59, 1, 6, 15, 8, 13, - 1, 13, 2, 13, 3, 2, 1, 3, 25, 7, 59, 1, 7, 15, 38, 13, 4, 2, 0, 1, - 59, 1, 8, 15, 8, 13, 1, 13, 3, 7, 1, 37, 3, 5, 2, 50, 3, 59, 1, 9, - 5, 3, 59, 1, 10, 59, 1, 14, 15, 5, 13, 1, 11, 39, 2, 3, 2, 59, 1, 15, - 13, 2, 52, 43, 59, 1, 16, 15, 8, 13, 1, 13, 2, 13, 3, 2, 1, 3, 25, 7, - 59, 1, 17, 15, 40, 13, 4, 2, 0, 1, 59, 1, 18, 15, 8, 13, 1, 13, 3, 7, - 1, 37, 3, 5, 2, 50, 3, 59, 1, 19, 5, 3, 59, 1, 20, 59, 1, 24, 15, 5, - 13, 1, 11, 42, 2, 3, 2, 59, 1, 25, 13, 2, 52, 36, 59, 1, 26, 15, 43, 15, - 8, 13, 4, 7, 2, 9, 2, 2, 1, 3, 2, 0, 1, 59, 1, 27, 15, 8, 13, 1, - 13, 3, 7, 1, 37, 3, 5, 2, 50, 3, 59, 1, 28, 5, 3, 59, 1, 29, 59, 1, - 33, 15, 5, 13, 1, 11, 45, 2, 3, 2, 59, 1, 34, 13, 2, 52, 27, 59, 1, 35, - 15, 46, 13, 4, 2, 0, 1, 59, 1, 36, 15, 8, 13, 1, 13, 3, 7, 1, 37, 3, - 5, 2, 50, 3, 59, 1, 37, 5, 3, 59, 1, 38, 59, 1, 41, 15, 47, 13, 1, 11, - 48, 11, 31, 2, 1, 3, 11, 31, 31, 52, 19, 59, 1, 42, 13, 1, 25, 7, 59, 1, - 43, 15, 49, 11, 50, 2, 0, 1, 50, 10, 59, 1, 45, 11, 31, 1, 2, 59, 1, 46, - 59, 1, 47, 0, 0, 0, 0,106, 0, 0, 0,147, 0, 0, 0, 5,115,101,108,102, - 0, 0, 0, 0,147, 0, 0, 0, 2,115, 0, 0, 0, 0,151, 0, 0, 0, 2, 98, - 0, 0, 0, 0,151, 0, 0, 0, 2,101, 0, 0, 0, 0,151, 0, 0, 0, 5,110, - 97,109,101, 0, 0, 0, 0,151, 0, 0, 0, 5, 98,111,100,121, 0, 0, 0, 0, -156, 0, 0, 0, 0, 0, 0, 0,156, 0, 0, 0, 0, 0, 0, 0,156, 0, 0, 0, - 0, 0, 0, 0,156, 0, 0, 0, 0, 0, 0, 0,161, 0, 0, 0, 2, 98, 0, 0, - 0, 0,161, 0, 0, 0, 2,101, 0, 0, 0, 0,161, 0, 0, 0, 5,110, 97,109, -101, 0, 0, 0, 0,166, 0, 0, 0, 0, 0, 0, 0,166, 0, 0, 0, 0, 0, 0, - 0,166, 0, 0, 0, 0, 0, 0, 0,171, 0, 0, 0, 2, 98, 0, 0, 0, 0,171, - 0, 0, 0, 2,101, 0, 0, 0, 0,171, 0, 0, 0, 5, 98,111,100,121, 0, 0, - 0, 0,176, 0, 0, 0, 0, 0, 0, 0,176, 0, 0, 0, 0, 0, 0, 0,176, 0, - 0, 0, 0, 0, 0, 0,180, 0, 0, 0, 2, 98, 0, 0, 0, 0,180, 0, 0, 0, - 2,101, 0, 0, 0, 0,180, 0, 0, 0, 5, 98,111,100,121, 0, 0, 0, 0,180, - 0, 0, 0, 5,110, 97,109,101, 0, 0, 0, 0,186, 0, 0, 0, 0, 0, 0, 0, -186, 0, 0, 0, 0, 0, 0, 0,186, 0, 0, 0, 0, 0, 0, 0,186, 0, 0, 0, - 0, 0, 0, 0,191, 0, 0, 0, 2, 98, 0, 0, 0, 0,191, 0, 0, 0, 2,101, - 0, 0, 0, 0,191, 0, 0, 0, 5,100,101, 99,108, 0, 0, 0, 0,191, 0, 0, - 0, 5,107,105,110,100, 0, 0, 0, 0,191, 0, 0, 0, 4, 97,114,103, 0, 0, - 0, 0,191, 0, 0, 0, 6, 99,111,110,115,116, 0, 0, 0, 0,196, 0, 0, 0, - 0, 0, 0, 0,196, 0, 0, 0, 0, 0, 0, 0,196, 0, 0, 0, 0, 0, 0, 0, -196, 0, 0, 0, 0, 0, 0, 0,196, 0, 0, 0, 0, 0, 0, 0,196, 0, 0, 0, - 0, 0, 0, 0,201, 0, 0, 0, 2, 98, 0, 0, 0, 0,201, 0, 0, 0, 2,101, - 0, 0, 0, 0,201, 0, 0, 0, 5,100,101, 99,108, 0, 0, 0, 0,201, 0, 0, - 0, 4, 97,114,103, 0, 0, 0, 0,201, 0, 0, 0, 6, 99,111,110,115,116, 0, - 0, 0, 0,210, 0, 0, 0, 0, 0, 0, 0,210, 0, 0, 0, 0, 0, 0, 0,210, - 0, 0, 0, 0, 0, 0, 0,210, 0, 0, 0, 0, 0, 0, 0,210, 0, 0, 0, 0, - 0, 0, 0,215, 0, 0, 0, 2, 98, 0, 0, 0, 0,215, 0, 0, 0, 2,101, 0, - 0, 0, 0,215, 0, 0, 0, 5,100,101, 99,108, 0, 0, 0, 0,215, 0, 0, 0, - 4, 97,114,103, 0, 0, 0, 0,215, 0, 0, 0, 6, 99,111,110,115,116, 0, 0, - 0, 0,224, 0, 0, 0, 0, 0, 0, 0,224, 0, 0, 0, 0, 0, 0, 0,224, 0, - 0, 0, 0, 0, 0, 0,224, 0, 0, 0, 0, 0, 0, 0,224, 0, 0, 0, 0, 0, - 0, 0,229, 0, 0, 0, 2, 98, 0, 0, 0, 0,229, 0, 0, 0, 2,101, 0, 0, - 0, 0,229, 0, 0, 0, 5,110, 97,109,101, 0, 0, 0, 0,229, 0, 0, 0, 5, - 98, 97,115,101, 0, 0, 0, 0,229, 0, 0, 0, 5, 98,111,100,121, 0, 0, 0, - 0,239, 0, 0, 0, 2, 98, 0, 0, 0, 0,239, 0, 0, 0, 2,101, 0, 0, 0, - 0,240, 0, 0, 0, 0, 0, 0, 0,240, 0, 0, 0, 0, 0, 0, 0,245, 0, 0, - 0, 0, 0, 0, 0,245, 0, 0, 0, 0, 0, 0, 0,245, 0, 0, 0, 0, 0, 0, - 0,245, 0, 0, 0, 0, 0, 0, 0,245, 0, 0, 0, 0, 0, 0, 0,250, 0, 0, - 0, 2, 98, 0, 0, 0, 0,250, 0, 0, 0, 2,101, 0, 0, 0, 0,250, 0, 0, - 0, 6,116,121,112,101,115, 0, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 0,255, - 0, 0, 0, 0, 0, 0, 0,255, 0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 2, - 98, 0, 0, 0, 1, 4, 0, 0, 0, 2,101, 0, 0, 0, 1, 4, 0, 0, 0, 5, -100,101, 99,108, 0, 0, 0, 1, 9, 0, 0, 0, 0, 0, 0, 1, 9, 0, 0, 0, - 0, 0, 0, 1, 9, 0, 0, 0, 0, 0, 0, 1, 14, 0, 0, 0, 2, 98, 0, 0, - 0, 1, 14, 0, 0, 0, 2,101, 0, 0, 0, 1, 14, 0, 0, 0, 5,100,101, 99, -108, 0, 0, 0, 1, 19, 0, 0, 0, 0, 0, 0, 1, 19, 0, 0, 0, 0, 0, 0, - 1, 19, 0, 0, 0, 0, 0, 0, 1, 24, 0, 0, 0, 2, 98, 0, 0, 0, 1, 24, - 0, 0, 0, 2,101, 0, 0, 0, 1, 24, 0, 0, 0, 5, 99,111,100,101, 0, 0, - 0, 1, 28, 0, 0, 0, 0, 0, 0, 1, 28, 0, 0, 0, 0, 0, 0, 1, 28, 0, - 0, 0, 0, 0, 0, 1, 33, 0, 0, 0, 2, 98, 0, 0, 0, 1, 33, 0, 0, 0, - 2,101, 0, 0, 0, 1, 33, 0, 0, 0, 5,108,105,110,101, 0, 0, 0, 1, 37, - 0, 0, 0, 0, 0, 0, 1, 37, 0, 0, 0, 0, 0, 0, 1, 37, 0, 0, 0, 0, - 0, 0, 0, 51, 2, 0, 0, 0, 2,115, 0, 2, 0, 0, 0, 2, 98, 0, 2, 0, - 0, 0, 2,101, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 5, - 98,111,100,121, 0, 2, 0, 0, 0, 8,115,116,114,102,105,110,100, 0, 2, 0, - 0, 0, 41, 94, 37,115, 42,109,111,100,117,108,101, 37,115, 37,115, 42, 40, 91, - 95, 37,119, 93, 91, 95, 37,119, 93, 42, 41, 37,115, 42, 40, 37, 98,123,125, 41, - 37,115, 42, 0, 2, 0, 0, 0, 11, 95, 99,117,114,114, 95, 99,111,100,101, 0, - 2, 0, 0, 0, 7,115,116,114,115,117, 98, 0, 2, 0, 0, 0, 7, 77,111,100, -117,108,101, 0, 2, 0, 0, 0, 34, 94, 37,115, 42, 35,100,101,102,105,110,101, - 37,115, 37,115, 42, 40, 91, 94, 37,115, 93, 42, 41, 91, 94, 10, 93, 42, 10, 37, -115, 42, 0, 2, 0, 0, 0, 7, 68,101,102,105,110,101, 0, 2, 0, 0, 0, 28, - 94, 37,115, 42,101,110,117,109, 91, 94,123, 93, 42, 40, 37, 98,123,125, 41, 37, -115, 42, 59, 63, 37,115, 42, 0, 2, 0, 0, 0, 10, 69,110,117,109,101,114, 97, -116,101, 0, 2, 0, 0, 0, 55, 94, 37,115, 42,116,121,112,101,100,101,102, 37, -115, 37,115, 42,101,110,117,109, 91, 94,123, 93, 42, 40, 37, 98,123,125, 41, 37, -115, 42, 40, 91, 37,119, 95, 93, 91, 94, 37,115, 93, 42, 41, 37,115, 42, 59, 37, -115, 42, 0, 2, 0, 0, 0, 8, 84,121,112,101,100,101,102, 0, 2, 0, 0, 0, - 5,105,110,116, 32, 0, 2, 0, 0, 0, 5,100,101, 99,108, 0, 2, 0, 0, 0, - 5,107,105,110,100, 0, 2, 0, 0, 0, 4, 97,114,103, 0, 2, 0, 0, 0, 6, - 99,111,110,115,116, 0, 2, 0, 0, 0, 78, 94, 37,115, 42, 40, 91, 95, 37,119, - 93, 91, 95, 37,119, 37,115, 37, 42, 38, 93, 42,111,112,101,114, 97,116,111,114, - 41, 37,115, 42, 40, 91, 94, 37,115, 93, 91, 94, 37,115, 93, 42, 41, 37,115, 42, - 40, 37, 98, 40, 41, 41, 37,115, 42, 40, 99, 63,111, 63,110, 63,115, 63,116, 63, - 41, 37,115, 42, 59, 37,115, 42, 0, 2, 0, 0, 0, 9, 79,112,101,114, 97,116, -111,114, 0, 2, 0, 0, 0, 71, 94, 37,115, 42, 40, 91,126, 95, 37,119, 93, 91, - 95, 64, 37,119, 37,115, 37, 42, 38, 93, 42, 91, 95, 37,119, 93, 41, 37,115, 42, - 40, 37, 98, 40, 41, 41, 37,115, 42, 40, 99, 63,111, 63,110, 63,115, 63,116, 63, - 41, 37,115, 42, 61, 63, 37,115, 42, 48, 63, 37,115, 42, 59, 37,115, 42, 0, 2, - 0, 0, 0, 43, 94, 37,115, 42, 40, 91, 95, 37,119, 93, 41, 37,115, 42, 40, 37, - 98, 40, 41, 41, 37,115, 42, 40, 99, 63,111, 63,110, 63,115, 63,116, 63, 41, 37, -115, 42, 59, 37,115, 42, 0, 2, 0, 0, 0, 9, 70,117,110, 99,116,105,111,110, - 0, 2, 0, 0, 0, 64, 94, 37,115, 42, 40, 91,126, 95, 37,119, 93, 91, 95, 64, - 37,119, 37,115, 37, 42, 38, 93, 42, 91, 95, 37,119, 93, 41, 37,115, 42, 40, 37, - 98, 40, 41, 41, 37,115, 42, 40, 99, 63,111, 63,110, 63,115, 63,116, 63, 41, 37, -115, 42, 37, 98,123,125, 37,115, 42, 0, 2, 0, 0, 0, 46, 94, 37,115, 42, 40, - 91, 95, 37,119, 93, 41, 37,115, 42, 40, 37, 98, 40, 41, 41, 37,115, 42, 40, 99, - 63,111, 63,110, 63,115, 63,116, 63, 41, 37,115, 42, 37, 98,123,125, 37,115, 42, - 0, 2, 0, 0, 0, 5, 98, 97,115,101, 0, 2, 0, 0, 0, 49, 94, 37,115, 42, - 99,108, 97,115,115, 37,115, 42, 40, 91, 95, 37,119, 93, 91, 95, 37,119, 93, 42, - 41, 37,115, 42, 40, 46, 45, 41, 37,115, 42, 40, 37, 98,123,125, 41, 37,115, 42, - 59, 37,115, 42, 0, 2, 0, 0, 0, 50, 94, 37,115, 42,115,116,114,117, 99,116, - 37,115, 42, 40, 91, 95, 37,119, 93, 91, 95, 37,119, 93, 42, 41, 37,115, 42, 40, - 46, 45, 41, 37,115, 42, 40, 37, 98,123,125, 41, 37,115, 42, 59, 37,115, 42, 0, - 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 66, 94, 37,115, 42,116,121,112,101,100, -101,102, 37,115, 37,115, 42,115,116,114,117, 99,116, 37,115, 37,115, 42, 91, 95, - 37,119, 93, 42, 37,115, 42, 40, 37, 98,123,125, 41, 37,115, 42, 40, 91, 95, 37, -119, 93, 91, 95, 37,119, 93, 42, 41, 37,115, 42, 59, 37,115, 42, 0, 2, 0, 0, - 0, 17, 46, 45, 40, 91, 95, 37,119, 93, 91, 95, 37,119, 93, 42, 41, 36, 0, 2, - 0, 0, 0, 6, 67,108, 97,115,115, 0, 2, 0, 0, 0, 6,116,121,112,101,115, - 0, 2, 0, 0, 0, 28, 94, 37,115, 42,116,121,112,101,100,101,102, 37,115, 37, -115, 42, 40, 46, 45, 41, 37,115, 42, 59, 37,115, 42, 0, 2, 0, 0, 0, 40, 94, - 37,115, 42, 40, 91, 95, 37,119, 93, 91, 95, 64, 37,115, 37,119, 37,100, 37, 42, - 38, 93, 42, 91, 95, 37,119, 37,100, 93, 41, 37,115, 42, 59, 37,115, 42, 0, 2, - 0, 0, 0, 9, 86, 97,114,105, 97, 98,108,101, 0, 2, 0, 0, 0, 43, 94, 37, -115, 42, 40, 91, 95, 37,119, 93, 91, 93, 91, 95, 64, 37,115, 37,119, 37,100, 37, - 42, 38, 93, 42, 91, 93, 95, 37,119, 37,100, 93, 41, 37,115, 42, 59, 37,115, 42, - 0, 2, 0, 0, 0, 6, 65,114,114, 97,121, 0, 2, 0, 0, 0, 5, 99,111,100, -101, 0, 2, 0, 0, 0, 11, 94, 37,115, 42, 40, 37, 98, 1, 2, 41, 0, 2, 0, - 0, 0, 5, 67,111,100,101, 0, 2, 0, 0, 0, 5,108,105,110,101, 0, 2, 0, - 0, 0, 12, 94, 37,115, 42, 37, 36, 40, 46, 45, 10, 41, 0, 2, 0, 0, 0, 9, - 86,101,114, 98, 97,116,105,109, 0, 2, 0, 0, 0, 5,103,115,117, 98, 0, 2, - 0, 0, 0, 6, 37,115, 37,115, 42, 0, 2, 0, 0, 0, 6,101,114,114,111,114, - 0, 2, 0, 0, 0, 13, 35,112, 97,114,115,101, 32,101,114,114,111,114, 0, 2, - 0, 0, 0, 6,112, 97,114,115,101, 0, 4, 0, 0, 1, 49, 0, 0, 0, 15, 64, - 99,111,110,116, 97,105,110,101,114, 46,108,117, 97, 0, 0, 0, 0, 35, 5, 2, - 50, 17, 59, 1, 51, 13, 0, 20, 3, 13, 1, 2, 1, 2, 23, 1, 59, 1, 52, 59, - 1, 50, 13, 1, 11, 1, 31, 54, 27, 59, 1, 53, 0, 0, 0, 0, 2, 0, 0, 1, - 49, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 1, 49, 0, 0, 0, 2,115, 0, - 0, 0, 0, 4, 2, 0, 0, 0, 2,115, 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, - 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 8,100,111,112, 97,114,115,101, 0, - -}; - -/* package.lo */ -static char B5[]={ - 27, 76,117, 97, 50, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64,112, 97, 99,107, 97, -103,101, 46,108,117, 97, 0, 0, 0, 0,102, 5, 0, 60, 20, 22, 2, 60, 21, 11, - 1, 15, 2, 11, 3, 60, 22, 11, 4, 30, 1, 60, 23, 25, 0, 60, 24, 15, 5, 15, - 0, 15, 6, 2, 0, 2, 60, 27, 15, 0, 11, 7, 11, 8, 26, 60, 36, 15, 0, 11, - 9, 11, 10, 26, 60, 60, 15, 0, 11, 11, 11, 12, 26, 60,100, 15, 0, 11, 13, 11, - 14, 26, 60,119, 15, 0, 11, 15, 11, 16, 26, 60,132, 15, 0, 11, 17, 11, 18, 26, - 60,146, 11, 20, 25, 19, 60,155, 11, 22, 25, 21, 0, 0, 0, 0, 0, 0, 0, 0, - 23, 2, 0, 0, 0, 13, 99,108, 97,115,115, 80, 97, 99,107, 97,103,101, 0, 2, - 0, 0, 0, 6, 95, 98, 97,115,101, 0, 2, 0, 0, 0, 15, 99,108, 97,115,115, - 67,111,110,116, 97,105,110,101,114, 0, 2, 0, 0, 0, 5,116,121,112,101, 0, - 2, 0, 0, 0, 8,112, 97, 99,107, 97,103,101, 0, 2, 0, 0, 0, 7,115,101, -116,116, 97,103, 0, 2, 0, 0, 0, 10,116,111,108,117, 97, 95,116, 97,103, 0, - 2, 0, 0, 0, 6,112,114,105,110,116, 0, 4, 0, 0, 0, 27, 0, 0, 0, 13, - 64,112, 97, 99,107, 97,103,101, 46,108,117, 97, 0, 0, 0, 0, 61, 6, 1, 60, - 28, 15, 0, 11, 1, 13, 0, 18, 3, 42, 2, 0, 1, 60, 29, 7, 1, 50, 27, 60, - 31, 13, 0, 13, 1, 16, 20, 0, 11, 5, 11, 5, 2, 0, 3, 60, 32, 13, 1, 7, - 1, 37, 23, 1, 60, 33, 60, 30, 13, 0, 13, 1, 16, 54, 36, 60, 34, 0, 0, 0, - 0, 2, 0, 0, 0, 27, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 29, 0, - 0, 0, 2,105, 0, 0, 0, 0, 6, 2, 0, 0, 0, 6,112,114,105,110,116, 0, - 2, 0, 0, 0, 10, 80, 97, 99,107, 97,103,101, 58, 32, 0, 2, 0, 0, 0, 5, -115,101,108,102, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 2, -105, 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 11,112,114,101,112,114,111, 99, -101,115,115, 0, 4, 0, 0, 0, 36, 0, 0, 0, 13, 64,112, 97, 99,107, 97,103, -101, 46,108,117, 97, 0, 0, 0, 1, 83, 7, 1, 60, 38, 13, 0, 11, 1, 11, 2, - 13, 0, 18, 1, 42, 26, 60, 40, 13, 0, 11, 1, 15, 3, 13, 0, 18, 1, 11, 4, - 11, 5, 2, 1, 3, 26, 60, 41, 13, 0, 11, 1, 15, 3, 13, 0, 18, 1, 11, 6, - 11, 7, 2, 1, 3, 26, 60, 42, 13, 0, 11, 1, 15, 3, 13, 0, 18, 1, 11, 8, - 11, 9, 2, 1, 3, 26, 60, 43, 13, 0, 11, 1, 15, 3, 13, 0, 18, 1, 11, 10, - 11, 5, 2, 1, 3, 26, 60, 44, 13, 0, 11, 1, 15, 3, 13, 0, 18, 1, 11, 7, - 11, 6, 2, 1, 3, 26, 60, 45, 13, 0, 11, 1, 15, 3, 13, 0, 18, 1, 11, 9, - 11, 8, 2, 1, 3, 26, 60, 46, 13, 0, 11, 1, 15, 3, 13, 0, 18, 1, 11, 11, - 11, 12, 2, 1, 3, 26, 60, 47, 13, 0, 11, 1, 15, 3, 13, 0, 18, 1, 11, 13, - 11, 14, 2, 1, 3, 26, 60, 48, 13, 0, 11, 1, 15, 3, 13, 0, 18, 1, 11, 15, - 11, 14, 2, 1, 3, 26, 60, 49, 13, 0, 11, 1, 15, 3, 13, 0, 18, 1, 11, 16, - 11, 14, 2, 1, 3, 26, 60, 50, 13, 0, 11, 1, 15, 3, 13, 0, 18, 1, 11, 17, - 11, 5, 2, 1, 3, 26, 60, 51, 13, 0, 11, 1, 15, 3, 13, 0, 18, 1, 11, 18, - 11, 19, 2, 1, 3, 26, 60, 52, 13, 0, 11, 1, 15, 3, 13, 0, 18, 1, 11, 18, - 11, 19, 2, 1, 3, 26, 60, 53, 13, 0, 11, 1, 15, 3, 13, 0, 18, 1, 11, 20, - 11, 21, 2, 1, 3, 26, 60, 55, 13, 0, 11, 1, 15, 3, 13, 0, 18, 1, 11, 22, - 11, 7, 2, 1, 3, 26, 60, 56, 13, 0, 11, 1, 15, 3, 13, 0, 18, 1, 11, 23, - 11, 9, 2, 1, 3, 26, 60, 57, 0, 0, 0, 0, 1, 0, 0, 0, 36, 0, 0, 0, - 5,115,101,108,102, 0, 0, 0, 0, 24, 2, 0, 0, 0, 5,115,101,108,102, 0, - 2, 0, 0, 0, 5, 99,111,100,101, 0, 2, 0, 0, 0, 2, 32, 0, 2, 0, 0, - 0, 5,103,115,117, 98, 0, 2, 0, 0, 0, 10, 40, 47, 47, 91, 94, 10, 93, 42, - 41, 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 4, 47, 37, 42, 0, 2, 0, 0, - 0, 2, 1, 0, 2, 0, 0, 0, 4, 37, 42, 47, 0, 2, 0, 0, 0, 2, 2, 0, - 2, 0, 0, 0, 5, 37, 98, 1, 2, 0, 2, 0, 0, 0, 8, 37,115, 42, 64, 37, -115, 42, 0, 2, 0, 0, 0, 2, 64, 0, 2, 0, 0, 0, 14, 37,115, 63,105,110, -108,105,110,101, 40, 37,115, 41, 0, 2, 0, 0, 0, 3, 37, 49, 0, 2, 0, 0, - 0, 14, 37,115, 63,101,120,116,101,114,110, 40, 37,115, 41, 0, 2, 0, 0, 0, - 15, 37,115, 63,118,105,114,116,117, 97,108, 40, 37,115, 41, 0, 2, 0, 0, 0, - 8,112,117, 98,108,105, 99, 58, 0, 2, 0, 0, 0, 18, 40, 91, 94, 37,119, 95, - 93, 41,118,111,105,100, 37,115, 42, 37, 42, 0, 2, 0, 0, 0, 13, 37, 49, 95, -117,115,101,114,100, 97,116, 97, 32, 0, 2, 0, 0, 0, 18, 40, 91, 94, 37,119, - 95, 93, 41, 99,104, 97,114, 37,115, 42, 37, 42, 0, 2, 0, 0, 0, 12, 37, 49, - 95, 99,115,116,114,105,110,103, 32, 0, 2, 0, 0, 0, 5, 37, 36, 37, 91, 0, - 2, 0, 0, 0, 5, 37, 36, 37, 93, 0, 2, 0, 0, 0, 9,112,114,101, 97,109, - 98,108,101, 0, 4, 0, 0, 0, 60, 0, 0, 0, 13, 64,112, 97, 99,107, 97,103, -101, 46,108,117, 97, 0, 0, 0, 1, 79, 5, 1, 60, 61, 15, 0, 11, 1, 2, 0, - 1, 60, 62, 15, 0, 11, 2, 13, 0, 18, 4, 42, 11, 5, 42, 2, 0, 1, 60, 63, - 15, 0, 11, 6, 15, 7, 42, 11, 8, 42, 15, 9, 2, 1, 0, 42, 11, 10, 42, 2, - 0, 1, 60, 64, 15, 0, 11, 11, 2, 0, 1, 60, 66, 15, 12, 18, 13, 44, 52, 54, - 60, 67, 15, 0, 11, 14, 2, 0, 1, 60, 68, 15, 0, 11, 15, 13, 0, 18, 4, 42, - 11, 16, 42, 2, 0, 1, 60, 69, 15, 0, 11, 17, 13, 0, 18, 4, 42, 11, 18, 42, - 2, 0, 1, 60, 70, 15, 0, 11, 5, 2, 0, 1, 50, 2, 60, 71, 60, 73, 15, 12, - 18, 19, 52, 46, 60, 74, 15, 0, 11, 20, 2, 0, 1, 60, 75, 15, 0, 11, 21, 2, - 0, 1, 60, 76, 15, 0, 11, 22, 13, 0, 18, 4, 42, 11, 23, 42, 2, 0, 1, 60, - 77, 15, 0, 11, 24, 2, 0, 1, 50, 2, 60, 78, 60, 79, 15, 0, 11, 25, 2, 0, - 1, 60, 80, 7, 1, 50, 23, 60, 82, 13, 0, 13, 1, 16, 20, 27, 2, 0, 1, 60, - 83, 13, 1, 7, 1, 37, 23, 1, 60, 84, 60, 81, 13, 0, 13, 1, 16, 54, 32, 60, - 85, 15, 0, 11, 5, 2, 0, 1, 60, 86, 15, 0, 11, 28, 2, 0, 1, 60, 87, 13, - 0, 20, 29, 2, 0, 1, 60, 88, 15, 0, 11, 5, 2, 0, 1, 60, 89, 15, 0, 11, - 30, 2, 0, 1, 60, 90, 15, 0, 11, 31, 2, 0, 1, 60, 91, 15, 0, 11, 32, 2, - 0, 1, 60, 92, 15, 33, 15, 34, 11, 35, 2, 0, 2, 60, 93, 15, 33, 15, 36, 11, - 37, 2, 0, 2, 60, 94, 15, 38, 11, 39, 2, 0, 1, 60, 95, 15, 38, 11, 5, 2, - 0, 1, 60, 96, 0, 0, 0, 0, 2, 0, 0, 0, 60, 0, 0, 0, 5,115,101,108, -102, 0, 0, 0, 0, 80, 0, 0, 0, 2,105, 0, 0, 0, 0, 40, 2, 0, 0, 0, - 7,111,117,116,112,117,116, 0, 2, 0, 0, 0, 4, 47, 42, 10, 0, 2, 0, 0, - 0, 17, 42, 42, 32, 76,117, 97, 32, 98,105,110,100,105,110,103, 58, 32, 0, 2, - 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, - 0, 0, 0, 2, 10, 0, 2, 0, 0, 0, 31, 42, 42, 32, 71,101,110,101,114, 97, -116,101,100, 32, 97,117,116,111,109, 97,116,105, 99, 97,108,108,121, 32, 98,121, - 32, 0, 2, 0, 0, 0, 14, 84, 79, 76, 85, 65, 95, 86, 69, 82, 83, 73, 79, 78, - 0, 2, 0, 0, 0, 5, 32,111,110, 32, 0, 2, 0, 0, 0, 5,100, 97,116,101, - 0, 2, 0, 0, 0, 3, 46, 10, 0, 2, 0, 0, 0, 5, 42, 47, 10, 10, 0, 2, - 0, 0, 0, 6,102,108, 97,103,115, 0, 2, 0, 0, 0, 2,104, 0, 2, 0, 0, - 0, 24, 47, 42, 32, 69,120,112,111,114,116,101,100, 32,102,117,110, 99,116,105, -111,110, 32, 42, 47, 0, 2, 0, 0, 0, 12,105,110,116, 32, 32,116,111,108,117, - 97, 95, 0, 2, 0, 0, 0, 14, 95,111,112,101,110, 32, 40,118,111,105,100, 41, - 59, 0, 2, 0, 0, 0, 12,118,111,105,100, 32,116,111,108,117, 97, 95, 0, 2, - 0, 0, 0, 15, 95, 99,108,111,115,101, 32, 40,118,111,105,100, 41, 59, 0, 2, - 0, 0, 0, 2, 97, 0, 2, 0, 0, 0, 45, 47, 42, 32, 65,117,116,111,109, 97, -116,105, 99, 32,105,110,105,116,105, 97,108,105,122, 97,116,105,111,110, 32,102, -111,114, 32, 67, 43, 43, 32, 99,111,100,101, 32, 42, 47, 10, 0, 2, 0, 0, 0, - 20, 35,105,102,100,101,102, 32, 95, 95, 99,112,108,117,115,112,108,117,115, 10, - 0, 2, 0, 0, 0, 26,115,116, 97,116,105, 99, 32,105,110,116, 32,100,117,109, -109,121, 32, 61, 32,116,111,108,117, 97, 95, 0, 2, 0, 0, 0, 10, 95,111,112, -101,110, 32, 40, 41, 59, 0, 2, 0, 0, 0, 9, 35,101,110,100,105,102, 10, 10, - 0, 2, 0, 0, 0, 21, 35,105,110, 99,108,117,100,101, 32, 34,116,111,108,117, - 97, 46,104, 34, 10, 10, 0, 2, 0, 0, 0, 2,105, 0, 2, 0, 0, 0, 9,112, -114,101, 97,109, 98,108,101, 0, 2, 0, 0, 0, 20, 47, 42, 32,116, 97,103, 32, -118, 97,114,105, 97, 98,108,101,115, 32, 42, 47, 0, 2, 0, 0, 0, 8,100,101, - 99,108,116, 97,103, 0, 2, 0, 0, 0, 51, 47, 42, 32,102,117,110, 99,116,105, -111,110, 32,116,111, 32,114,101,103,105,115,116,101,114, 32,116,121,112,101, 32, - 97,110,100, 32,105,110,105,116,105, 97,108,105,122,101, 32,116, 97,103, 32, 42, - 47, 0, 2, 0, 0, 0, 35,115,116, 97,116,105, 99, 32,118,111,105,100, 32,116, -111,108,117, 97, 73, 95,105,110,105,116, 95,116, 97,103, 32, 40,118,111,105,100, - 41, 0, 2, 0, 0, 0, 2,123, 0, 2, 0, 0, 0, 8,102,111,114,101, 97, 99, -104, 0, 2, 0, 0, 0, 10, 95,117,115,101,114,116,121,112,101, 0, 4, 0, 0, - 0, 92, 0, 0, 0, 13, 64,112, 97, 99,107, 97,103,101, 46,108,117, 97, 0, 0, - 0, 0, 16, 6, 2, 60, 92, 15, 2, 11, 3, 13, 1, 11, 4, 2, 0, 3, 0, 0, - 0, 0, 2, 0, 0, 0, 92, 0, 0, 0, 2,110, 0, 0, 0, 0, 92, 0, 0, 0, - 2,118, 0, 0, 0, 0, 5, 2, 0, 0, 0, 2,110, 0, 2, 0, 0, 0, 2,118, - 0, 2, 0, 0, 0, 7,111,117,116,112,117,116, 0, 2, 0, 0, 0, 18, 32,116, -111,108,117, 97, 95,117,115,101,114,116,121,112,101, 40, 34, 0, 2, 0, 0, 0, - 4, 34, 41, 59, 0, 2, 0, 0, 0, 10, 95,116, 97,103,110, 97,109,101,115, 0, - 4, 0, 0, 0, 93, 0, 0, 0, 13, 64,112, 97, 99,107, 97,103,101, 46,108,117, - 97, 0, 0, 0, 0, 21, 7, 2, 60, 93, 15, 2, 11, 3, 13, 1, 11, 4, 13, 0, - 42, 11, 5, 2, 0, 4, 0, 0, 0, 0, 2, 0, 0, 0, 93, 0, 0, 0, 2,110, - 0, 0, 0, 0, 93, 0, 0, 0, 2,118, 0, 0, 0, 0, 6, 2, 0, 0, 0, 2, -110, 0, 2, 0, 0, 0, 2,118, 0, 2, 0, 0, 0, 7,111,117,116,112,117,116, - 0, 2, 0, 0, 0, 16, 32,116,111,108,117, 97, 95,115,101,116,116, 97,103, 40, - 34, 0, 2, 0, 0, 0, 4, 34, 44, 38, 0, 2, 0, 0, 0, 3, 41, 59, 0, 2, - 0, 0, 0, 7,111,117,116,112,117,116, 0, 2, 0, 0, 0, 2,125, 0, 2, 0, - 0, 0, 9,114,101,103,105,115,116,101,114, 0, 4, 0, 0, 0,100, 0, 0, 0, - 13, 64,112, 97, 99,107, 97,103,101, 46,108,117, 97, 0, 0, 0, 0,132, 4, 1, - 60,101, 15, 0, 11, 1, 2, 0, 1, 60,102, 15, 0, 11, 2, 13, 0, 18, 4, 42, - 11, 5, 42, 2, 0, 1, 60,103, 15, 0, 11, 6, 2, 0, 1, 60,104, 15, 0, 11, - 7, 2, 0, 1, 60,105, 15, 0, 11, 8, 2, 0, 1, 60,106, 15, 0, 11, 9, 2, - 0, 1, 60,107, 7, 1, 50, 23, 60,109, 13, 0, 13, 1, 16, 20, 11, 2, 0, 1, - 60,110, 13, 1, 7, 1, 37, 23, 1, 60,111, 60,108, 13, 0, 13, 1, 16, 54, 32, - 60,112, 15, 0, 11, 12, 2, 0, 1, 60,113, 15, 0, 11, 13, 2, 0, 1, 60,114, - 15, 0, 11, 14, 2, 0, 1, 60,115, 0, 0, 0, 0, 2, 0, 0, 0,100, 0, 0, - 0, 5,115,101,108,102, 0, 0, 0, 0,107, 0, 0, 0, 2,105, 0, 0, 0, 0, - 15, 2, 0, 0, 0, 7,111,117,116,112,117,116, 0, 2, 0, 0, 0, 20, 47, 42, - 32, 79,112,101,110, 32,102,117,110, 99,116,105,111,110, 32, 42, 47, 0, 2, 0, - 0, 0, 11,105,110,116, 32,116,111,108,117, 97, 95, 0, 2, 0, 0, 0, 5,115, -101,108,102, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 13, 95, -111,112,101,110, 32, 40,118,111,105,100, 41, 0, 2, 0, 0, 0, 2,123, 0, 2, - 0, 0, 0, 15, 32,116,111,108,117, 97, 95,111,112,101,110, 40, 41, 59, 0, 2, - 0, 0, 0, 19, 32,108,117, 97, 95, 98,101,103,105,110, 98,108,111, 99,107, 40, - 41, 59, 0, 2, 0, 0, 0, 20, 32,116,111,108,117, 97, 73, 95,105,110,105,116, - 95,116, 97,103, 40, 41, 59, 0, 2, 0, 0, 0, 2,105, 0, 2, 0, 0, 0, 9, -114,101,103,105,115,116,101,114, 0, 2, 0, 0, 0, 17, 32,108,117, 97, 95,101, -110,100, 98,108,111, 99,107, 40, 41, 59, 0, 2, 0, 0, 0, 11, 32,114,101,116, -117,114,110, 32, 49, 59, 0, 2, 0, 0, 0, 2,125, 0, 2, 0, 0, 0, 11,117, -110,114,101,103,105,115,116,101,114, 0, 4, 0, 0, 0,119, 0, 0, 0, 13, 64, -112, 97, 99,107, 97,103,101, 46,108,117, 97, 0, 0, 0, 0, 87, 4, 1, 60,120, - 15, 0, 11, 1, 2, 0, 1, 60,121, 15, 0, 11, 2, 13, 0, 18, 4, 42, 11, 5, - 42, 2, 0, 1, 60,122, 15, 0, 11, 6, 2, 0, 1, 60,123, 7, 1, 50, 23, 60, -125, 13, 0, 13, 1, 16, 20, 8, 2, 0, 1, 60,126, 13, 1, 7, 1, 37, 23, 1, - 60,127, 60,124, 13, 0, 13, 1, 16, 54, 32, 60,128, 15, 0, 11, 9, 2, 0, 1, - 60,129, 0, 0, 0, 0, 2, 0, 0, 0,119, 0, 0, 0, 5,115,101,108,102, 0, - 0, 0, 0,123, 0, 0, 0, 2,105, 0, 0, 0, 0, 10, 2, 0, 0, 0, 7,111, -117,116,112,117,116, 0, 2, 0, 0, 0, 21, 47, 42, 32, 67,108,111,115,101, 32, -102,117,110, 99,116,105,111,110, 32, 42, 47, 0, 2, 0, 0, 0, 12,118,111,105, -100, 32,116,111,108,117, 97, 95, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, - 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 14, 95, 99,108,111,115,101, - 32, 40,118,111,105,100, 41, 0, 2, 0, 0, 0, 2,123, 0, 2, 0, 0, 0, 2, -105, 0, 2, 0, 0, 0, 11,117,110,114,101,103,105,115,116,101,114, 0, 2, 0, - 0, 0, 2,125, 0, 2, 0, 0, 0, 7,104,101, 97,100,101,114, 0, 4, 0, 0, - 0,132, 0, 0, 0, 13, 64,112, 97, 99,107, 97,103,101, 46,108,117, 97, 0, 0, - 0, 0,127, 4, 1, 60,133, 15, 0, 11, 1, 2, 0, 1, 15, 0, 11, 2, 13, 0, - 18, 4, 42, 11, 5, 42, 2, 0, 1, 60,134, 15, 0, 11, 6, 15, 7, 42, 11, 8, - 42, 15, 9, 2, 1, 0, 42, 11, 10, 42, 2, 0, 1, 60,135, 15, 0, 11, 11, 2, - 0, 1, 60,137, 15, 12, 18, 13, 44, 52, 54, 60,138, 15, 0, 11, 14, 2, 0, 1, - 60,139, 15, 0, 11, 15, 13, 0, 18, 4, 42, 11, 16, 42, 2, 0, 1, 60,140, 15, - 0, 11, 17, 13, 0, 18, 4, 42, 11, 18, 42, 2, 0, 1, 60,141, 15, 0, 11, 5, - 2, 0, 1, 50, 2, 60,142, 60,143, 0, 0, 0, 0, 1, 0, 0, 0,132, 0, 0, - 0, 5,115,101,108,102, 0, 0, 0, 0, 19, 2, 0, 0, 0, 7,111,117,116,112, -117,116, 0, 2, 0, 0, 0, 4, 47, 42, 10, 0, 2, 0, 0, 0, 17, 42, 42, 32, - 76,117, 97, 32, 98,105,110,100,105,110,103, 58, 32, 0, 2, 0, 0, 0, 5,115, -101,108,102, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 2, 10, - 0, 2, 0, 0, 0, 31, 42, 42, 32, 71,101,110,101,114, 97,116,101,100, 32, 97, -117,116,111,109, 97,116,105, 99, 97,108,108,121, 32, 98,121, 32, 0, 2, 0, 0, - 0, 14, 84, 79, 76, 85, 65, 95, 86, 69, 82, 83, 73, 79, 78, 0, 2, 0, 0, 0, - 5, 32,111,110, 32, 0, 2, 0, 0, 0, 5,100, 97,116,101, 0, 2, 0, 0, 0, - 3, 46, 10, 0, 2, 0, 0, 0, 5, 42, 47, 10, 10, 0, 2, 0, 0, 0, 6,102, -108, 97,103,115, 0, 2, 0, 0, 0, 2,104, 0, 2, 0, 0, 0, 24, 47, 42, 32, - 69,120,112,111,114,116,101,100, 32,102,117,110, 99,116,105,111,110, 32, 42, 47, - 0, 2, 0, 0, 0, 12,105,110,116, 32, 32,116,111,108,117, 97, 95, 0, 2, 0, - 0, 0, 14, 95,111,112,101,110, 32, 40,118,111,105,100, 41, 59, 0, 2, 0, 0, - 0, 12,118,111,105,100, 32,116,111,108,117, 97, 95, 0, 2, 0, 0, 0, 15, 95, - 99,108,111,115,101, 32, 40,118,111,105,100, 41, 59, 0, 2, 0, 0, 0, 9, 95, - 80, 97, 99,107, 97,103,101, 0, 4, 0, 0, 0,146, 0, 0, 0, 13, 64,112, 97, - 99,107, 97,103,101, 46,108,117, 97, 0, 0, 0, 0, 31, 4, 1, 60,147, 13, 0, - 11, 1, 15, 2, 26, 60,148, 15, 3, 13, 0, 15, 4, 2, 0, 2, 60,149, 13, 0, - 1, 1, 60,150, 0, 0, 0, 0, 1, 0, 0, 0,146, 0, 0, 0, 2,116, 0, 0, - 0, 0, 5, 2, 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 6, 95, 98, 97,115,101, - 0, 2, 0, 0, 0, 13, 99,108, 97,115,115, 80, 97, 99,107, 97,103,101, 0, 2, - 0, 0, 0, 7,115,101,116,116, 97,103, 0, 2, 0, 0, 0, 10,116,111,108,117, - 97, 95,116, 97,103, 0, 2, 0, 0, 0, 8, 80, 97, 99,107, 97,103,101, 0, 4, - 0, 0, 0,155, 0, 0, 0, 13, 64,112, 97, 99,107, 97,103,101, 46,108,117, 97, - 0, 0, 0, 0,114, 10, 1, 60,157, 15, 2, 11, 3, 2, 1, 1, 60,159, 4, 0, - 60,161, 15, 5, 13, 1, 11, 6, 11, 7, 60,169, 2, 2, 3, 23, 2, 23, 1, 60, -170, 13, 2, 7, 0, 32, 56, 28, 60,172, 15, 9, 15, 10, 22, 2, 11, 0, 13, 0, - 11, 1, 13, 1, 30, 1, 2, 1, 1, 2, 1, 1, 60,173, 15, 11, 13, 3, 2, 0, - 1, 60,174, 13, 3, 20, 12, 2, 0, 1, 60,175, 13, 3, 20, 13, 13, 3, 18, 1, - 2, 0, 2, 60,176, 15, 14, 2, 0, 0, 60,177, 13, 3, 1, 4, 60,178, 0, 0, - 0, 0, 4, 0, 0, 0,155, 0, 0, 0, 5,110, 97,109,101, 0, 0, 0, 0,157, - 0, 0, 0, 5, 99,111,100,101, 0, 0, 0, 0,159, 0, 0, 0, 7,110,115,117, - 98,115,116, 0, 0, 0, 0,172, 0, 0, 0, 2,116, 0, 0, 0, 0, 15, 2, 0, - 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 5, 99,111,100,101, 0, 2, 0, - 0, 0, 5,114,101, 97,100, 0, 2, 0, 0, 0, 3, 46, 42, 0, 2, 0, 0, 0, - 7,110,115,117, 98,115,116, 0, 2, 0, 0, 0, 5,103,115,117, 98, 0, 2, 0, - 0, 0, 13, 37, 36, 60, 40, 46, 45, 41, 62, 37,115, 42, 10, 0, 4, 0, 0, 0, -161, 0, 0, 0, 13, 64,112, 97, 99,107, 97,103,101, 46,108,117, 97, 0, 0, 0, - 0, 71, 6, 1, 60,162, 15, 3, 13, 0, 11, 4, 2, 2, 2, 60,163, 13, 1, 44, - 52, 20, 60,164, 15, 5, 11, 6, 13, 2, 42, 11, 7, 42, 13, 0, 42, 2, 0, 1, - 50, 2, 60,165, 60,166, 15, 9, 13, 1, 11, 10, 2, 1, 2, 60,167, 15, 11, 13, - 1, 2, 0, 1, 60,168, 13, 3, 1, 4, 60,169, 0, 0, 0, 0, 4, 0, 0, 0, -161, 0, 0, 0, 3,102,110, 0, 0, 0, 0,162, 0, 0, 0, 3,102,112, 0, 0, - 0, 0,162, 0, 0, 0, 4,109,115,103, 0, 0, 0, 0,166, 0, 0, 0, 2,115, - 0, 0, 0, 0, 12, 2, 0, 0, 0, 3,102,110, 0, 2, 0, 0, 0, 3,102,112, - 0, 2, 0, 0, 0, 4,109,115,103, 0, 2, 0, 0, 0, 9,111,112,101,110,102, -105,108,101, 0, 2, 0, 0, 0, 2,114, 0, 2, 0, 0, 0, 6,101,114,114,111, -114, 0, 2, 0, 0, 0, 2, 35, 0, 2, 0, 0, 0, 3, 58, 32, 0, 2, 0, 0, - 0, 2,115, 0, 2, 0, 0, 0, 5,114,101, 97,100, 0, 2, 0, 0, 0, 3, 46, - 42, 0, 2, 0, 0, 0, 10, 99,108,111,115,101,102,105,108,101, 0, 2, 0, 0, - 0, 2,116, 0, 2, 0, 0, 0, 9, 95, 80, 97, 99,107, 97,103,101, 0, 2, 0, - 0, 0, 11, 95, 67,111,110,116, 97,105,110,101,114, 0, 2, 0, 0, 0, 5,112, -117,115,104, 0, 2, 0, 0, 0, 11,112,114,101,112,114,111, 99,101,115,115, 0, - 2, 0, 0, 0, 6,112, 97,114,115,101, 0, 2, 0, 0, 0, 4,112,111,112, 0, - -}; - -/* module.lo */ -static char B6[]={ - 27, 76,117, 97, 50, 0, 0, 0, 0, 0, 0, 0, 0, 12, 64,109,111,100,117,108, -101, 46,108,117, 97, 0, 0, 0, 0, 75, 5, 0, 60, 19, 22, 2, 60, 20, 11, 1, - 15, 2, 11, 3, 60, 21, 11, 4, 30, 1, 60, 22, 25, 0, 60, 23, 15, 5, 15, 0, - 15, 6, 2, 0, 2, 60, 26, 15, 0, 11, 7, 11, 8, 26, 60, 36, 15, 0, 11, 9, - 11, 10, 26, 60, 41, 15, 0, 11, 11, 11, 12, 26, 60, 53, 11, 14, 25, 13, 60, 62, - 11, 16, 25, 15, 0, 0, 0, 0, 0, 0, 0, 0, 17, 2, 0, 0, 0, 12, 99,108, - 97,115,115, 77,111,100,117,108,101, 0, 2, 0, 0, 0, 6, 95, 98, 97,115,101, - 0, 2, 0, 0, 0, 15, 99,108, 97,115,115, 67,111,110,116, 97,105,110,101,114, - 0, 2, 0, 0, 0, 5,116,121,112,101, 0, 2, 0, 0, 0, 7,109,111,100,117, -108,101, 0, 2, 0, 0, 0, 7,115,101,116,116, 97,103, 0, 2, 0, 0, 0, 10, -116,111,108,117, 97, 95,116, 97,103, 0, 2, 0, 0, 0, 9,114,101,103,105,115, -116,101,114, 0, 4, 0, 0, 0, 26, 0, 0, 0, 12, 64,109,111,100,117,108,101, - 46,108,117, 97, 0, 0, 0, 0, 60, 4, 1, 60, 27, 15, 0, 11, 1, 13, 0, 18, - 3, 42, 11, 4, 42, 2, 0, 1, 60, 28, 7, 1, 50, 23, 60, 30, 13, 0, 13, 1, - 16, 20, 6, 2, 0, 1, 60, 31, 13, 1, 7, 1, 37, 23, 1, 60, 32, 60, 29, 13, - 0, 13, 1, 16, 54, 32, 60, 33, 0, 0, 0, 0, 2, 0, 0, 0, 26, 0, 0, 0, - 5,115,101,108,102, 0, 0, 0, 0, 28, 0, 0, 0, 2,105, 0, 0, 0, 0, 7, - 2, 0, 0, 0, 7,111,117,116,112,117,116, 0, 2, 0, 0, 0, 16, 32,116,111, -108,117, 97, 95,109,111,100,117,108,101, 40, 34, 0, 2, 0, 0, 0, 5,115,101, -108,102, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 4, 34, 41, - 59, 0, 2, 0, 0, 0, 2,105, 0, 2, 0, 0, 0, 9,114,101,103,105,115,116, -101,114, 0, 2, 0, 0, 0, 11,117,110,114,101,103,105,115,116,101,114, 0, 4, - 0, 0, 0, 36, 0, 0, 0, 12, 64,109,111,100,117,108,101, 46,108,117, 97, 0, - 0, 0, 0, 22, 4, 1, 60, 37, 15, 0, 11, 1, 13, 0, 18, 3, 42, 11, 4, 42, - 2, 0, 1, 60, 38, 0, 0, 0, 0, 1, 0, 0, 0, 36, 0, 0, 0, 5,115,101, -108,102, 0, 0, 0, 0, 5, 2, 0, 0, 0, 7,111,117,116,112,117,116, 0, 2, - 0, 0, 0, 32, 32,108,117, 97, 95,112,117,115,104,110,105,108, 40, 41, 59, 32, -108,117, 97, 95,115,101,116,103,108,111, 98, 97,108, 40, 34, 0, 2, 0, 0, 0, - 5,115,101,108,102, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, - 4, 34, 41, 59, 0, 2, 0, 0, 0, 6,112,114,105,110,116, 0, 4, 0, 0, 0, - 41, 0, 0, 0, 12, 64,109,111,100,117,108,101, 46,108,117, 97, 0, 0, 0, 0, - 97, 8, 3, 60, 42, 15, 2, 13, 1, 11, 3, 42, 2, 0, 1, 60, 43, 15, 2, 13, - 1, 11, 4, 42, 13, 0, 18, 6, 42, 11, 7, 42, 2, 0, 1, 60, 44, 7, 1, 50, - 30, 60, 46, 13, 0, 13, 3, 16, 20, 2, 13, 1, 11, 9, 42, 11, 10, 2, 0, 3, - 60, 47, 13, 3, 7, 1, 37, 23, 3, 60, 48, 60, 45, 13, 0, 13, 3, 16, 54, 39, - 60, 49, 15, 2, 13, 1, 11, 11, 42, 13, 2, 42, 2, 0, 1, 60, 50, 0, 0, 0, - 0, 4, 0, 0, 0, 41, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 41, 0, - 0, 0, 6,105,100,101,110,116, 0, 0, 0, 0, 41, 0, 0, 0, 6, 99,108,111, -115,101, 0, 0, 0, 0, 44, 0, 0, 0, 2,105, 0, 0, 0, 0, 12, 2, 0, 0, - 0, 6,105,100,101,110,116, 0, 2, 0, 0, 0, 6, 99,108,111,115,101, 0, 2, - 0, 0, 0, 6,112,114,105,110,116, 0, 2, 0, 0, 0, 8, 77,111,100,117,108, -101,123, 0, 2, 0, 0, 0, 10, 32,110, 97,109,101, 32, 61, 32, 39, 0, 2, 0, - 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, - 0, 0, 3, 39, 59, 0, 2, 0, 0, 0, 2,105, 0, 2, 0, 0, 0, 2, 32, 0, - 2, 0, 0, 0, 2, 44, 0, 2, 0, 0, 0, 2,125, 0, 2, 0, 0, 0, 8, 95, - 77,111,100,117,108,101, 0, 4, 0, 0, 0, 53, 0, 0, 0, 12, 64,109,111,100, -117,108,101, 46,108,117, 97, 0, 0, 0, 0, 40, 4, 1, 60, 54, 13, 0, 11, 1, - 15, 2, 26, 60, 55, 15, 3, 13, 0, 15, 4, 2, 0, 2, 60, 56, 15, 5, 13, 0, - 2, 0, 1, 60, 57, 13, 0, 1, 1, 60, 58, 0, 0, 0, 0, 1, 0, 0, 0, 53, - 0, 0, 0, 2,116, 0, 0, 0, 0, 6, 2, 0, 0, 0, 2,116, 0, 2, 0, 0, - 0, 6, 95, 98, 97,115,101, 0, 2, 0, 0, 0, 12, 99,108, 97,115,115, 77,111, -100,117,108,101, 0, 2, 0, 0, 0, 7,115,101,116,116, 97,103, 0, 2, 0, 0, - 0, 10,116,111,108,117, 97, 95,116, 97,103, 0, 2, 0, 0, 0, 7, 97,112,112, -101,110,100, 0, 2, 0, 0, 0, 7, 77,111,100,117,108,101, 0, 4, 0, 0, 0, - 62, 0, 0, 0, 12, 64,109,111,100,117,108,101, 46,108,117, 97, 0, 0, 0, 0, - 75, 10, 2, 60, 63, 15, 3, 15, 4, 22, 1, 11, 5, 13, 0, 30, 0, 2, 1, 1, - 2, 1, 1, 60, 64, 15, 6, 13, 2, 2, 0, 1, 60, 65, 13, 2, 20, 7, 15, 8, - 13, 1, 7, 2, 15, 9, 13, 1, 2, 1, 1, 7, 1, 38, 2, 1, 3, 2, 0, 2, - 60, 66, 15, 10, 2, 0, 0, 60, 67, 13, 2, 1, 3, 60, 68, 0, 0, 0, 0, 3, - 0, 0, 0, 62, 0, 0, 0, 2,110, 0, 0, 0, 0, 62, 0, 0, 0, 2, 98, 0, - 0, 0, 0, 63, 0, 0, 0, 2,116, 0, 0, 0, 0, 11, 2, 0, 0, 0, 2,110, - 0, 2, 0, 0, 0, 2, 98, 0, 2, 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 8, - 95, 77,111,100,117,108,101, 0, 2, 0, 0, 0, 11, 95, 67,111,110,116, 97,105, -110,101,114, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 5,112, -117,115,104, 0, 2, 0, 0, 0, 6,112, 97,114,115,101, 0, 2, 0, 0, 0, 7, -115,116,114,115,117, 98, 0, 2, 0, 0, 0, 7,115,116,114,108,101,110, 0, 2, - 0, 0, 0, 4,112,111,112, 0, -}; - -/* class.lo */ -static char B7[]={ - 27, 76,117, 97, 50, 0, 0, 0, 0, 0, 0, 0, 0, 11, 64, 99,108, 97,115,115, - 46,108,117, 97, 0, 0, 0, 0, 96, 9, 0, 60, 20, 22, 4, 60, 21, 11, 1, 15, - 2, 11, 3, 60, 22, 11, 4, 11, 5, 60, 23, 11, 6, 11, 7, 60, 24, 11, 6, 30, - 3, 60, 25, 25, 0, 60, 26, 15, 8, 15, 0, 15, 9, 2, 0, 2, 60, 30, 15, 0, - 11, 10, 11, 11, 26, 60, 40, 15, 0, 11, 12, 11, 13, 26, 60, 45, 15, 0, 11, 14, - 11, 15, 26, 60, 57, 15, 0, 11, 16, 11, 17, 26, 60, 70, 11, 19, 25, 18, 60, 79, - 11, 21, 25, 20, 0, 0, 0, 0, 0, 0, 0, 0, 22, 2, 0, 0, 0, 11, 99,108, - 97,115,115, 67,108, 97,115,115, 0, 2, 0, 0, 0, 6, 95, 98, 97,115,101, 0, - 2, 0, 0, 0, 15, 99,108, 97,115,115, 67,111,110,116, 97,105,110,101,114, 0, - 2, 0, 0, 0, 5,116,121,112,101, 0, 2, 0, 0, 0, 6, 99,108, 97,115,115, - 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, - 0, 5, 98, 97,115,101, 0, 2, 0, 0, 0, 7,115,101,116,116, 97,103, 0, 2, - 0, 0, 0, 10,116,111,108,117, 97, 95,116, 97,103, 0, 2, 0, 0, 0, 9,114, -101,103,105,115,116,101,114, 0, 4, 0, 0, 0, 30, 0, 0, 0, 11, 64, 99,108, - 97,115,115, 46,108,117, 97, 0, 0, 0, 0, 68, 4, 1, 60, 31, 15, 0, 11, 1, - 13, 0, 18, 3, 42, 11, 4, 42, 13, 0, 18, 5, 42, 11, 6, 42, 2, 0, 1, 60, - 32, 7, 1, 50, 23, 60, 34, 13, 0, 13, 1, 16, 20, 8, 2, 0, 1, 60, 35, 13, - 1, 7, 1, 37, 23, 1, 60, 36, 60, 33, 13, 0, 13, 1, 16, 54, 32, 60, 37, 0, - 0, 0, 0, 2, 0, 0, 0, 30, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, - 32, 0, 0, 0, 2,105, 0, 0, 0, 0, 9, 2, 0, 0, 0, 7,111,117,116,112, -117,116, 0, 2, 0, 0, 0, 16, 32,116,111,108,117, 97, 95, 99, 99,108, 97,115, -115, 40, 34, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 5,110, - 97,109,101, 0, 2, 0, 0, 0, 4, 34, 44, 34, 0, 2, 0, 0, 0, 5, 98, 97, -115,101, 0, 2, 0, 0, 0, 4, 34, 41, 59, 0, 2, 0, 0, 0, 2,105, 0, 2, - 0, 0, 0, 9,114,101,103,105,115,116,101,114, 0, 2, 0, 0, 0, 11,117,110, -114,101,103,105,115,116,101,114, 0, 4, 0, 0, 0, 40, 0, 0, 0, 11, 64, 99, -108, 97,115,115, 46,108,117, 97, 0, 0, 0, 0, 22, 4, 1, 60, 41, 15, 0, 11, - 1, 13, 0, 18, 3, 42, 11, 4, 42, 2, 0, 1, 60, 42, 0, 0, 0, 0, 1, 0, - 0, 0, 40, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 5, 2, 0, 0, 0, - 7,111,117,116,112,117,116, 0, 2, 0, 0, 0, 32, 32,108,117, 97, 95,112,117, -115,104,110,105,108, 40, 41, 59, 32,108,117, 97, 95,115,101,116,103,108,111, 98, - 97,108, 40, 34, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 5, -110, 97,109,101, 0, 2, 0, 0, 0, 4, 34, 41, 59, 0, 2, 0, 0, 0, 8,100, -101, 99,108,116, 97,103, 0, 4, 0, 0, 0, 45, 0, 0, 0, 11, 64, 99,108, 97, -115,115, 46,108,117, 97, 0, 0, 0, 0,128, 8, 1, 60, 46, 13, 0, 11, 1, 13, - 0, 11, 2, 15, 3, 13, 0, 18, 4, 2, 2, 1, 27, 1, 27, 2, 5, 4, 15, 5, - 13, 0, 18, 1, 13, 0, 18, 2, 2, 0, 2, 60, 47, 13, 0, 11, 6, 13, 0, 11, - 7, 15, 3, 13, 0, 18, 4, 11, 8, 2, 2, 2, 27, 1, 27, 2, 5, 4, 60, 48, - 15, 3, 13, 0, 18, 10, 2, 2, 1, 15, 5, 13, 1, 13, 2, 2, 0, 2, 60, 49, - 7, 1, 50, 23, 60, 51, 13, 0, 13, 3, 16, 20, 5, 2, 0, 1, 60, 52, 13, 3, - 7, 1, 37, 23, 3, 60, 53, 60, 50, 13, 0, 13, 3, 16, 54, 32, 60, 54, 0, 0, - 0, 0, 4, 0, 0, 0, 45, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 48, - 0, 0, 0, 5,116,121,112,101, 0, 0, 0, 0, 48, 0, 0, 0, 4,116, 97,103, - 0, 0, 0, 0, 49, 0, 0, 0, 2,105, 0, 0, 0, 0, 12, 2, 0, 0, 0, 5, -115,101,108,102, 0, 2, 0, 0, 0, 6,105,116,121,112,101, 0, 2, 0, 0, 0, - 4,116, 97,103, 0, 2, 0, 0, 0, 7,116, 97,103,118, 97,114, 0, 2, 0, 0, - 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 8,100,101, 99,108,116, 97,103, 0, - 2, 0, 0, 0, 7, 99,105,116,121,112,101, 0, 2, 0, 0, 0, 5, 99,116, 97, -103, 0, 2, 0, 0, 0, 6, 99,111,110,115,116, 0, 2, 0, 0, 0, 5,116,121, -112,101, 0, 2, 0, 0, 0, 5, 98, 97,115,101, 0, 2, 0, 0, 0, 2,105, 0, - 2, 0, 0, 0, 6,112,114,105,110,116, 0, 4, 0, 0, 0, 57, 0, 0, 0, 11, - 64, 99,108, 97,115,115, 46,108,117, 97, 0, 0, 0, 0,117, 8, 3, 60, 58, 15, - 2, 13, 1, 11, 3, 42, 2, 0, 1, 60, 59, 15, 2, 13, 1, 11, 4, 42, 13, 0, - 18, 6, 42, 11, 7, 42, 2, 0, 1, 60, 60, 15, 2, 13, 1, 11, 8, 42, 13, 0, - 18, 9, 42, 11, 10, 42, 2, 0, 1, 60, 61, 7, 1, 50, 30, 60, 63, 13, 0, 13, - 3, 16, 20, 2, 13, 1, 11, 12, 42, 11, 13, 2, 0, 3, 60, 64, 13, 3, 7, 1, - 37, 23, 3, 60, 65, 60, 62, 13, 0, 13, 3, 16, 54, 39, 60, 66, 15, 2, 13, 1, - 11, 14, 42, 13, 2, 42, 2, 0, 1, 60, 67, 0, 0, 0, 0, 4, 0, 0, 0, 57, - 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 57, 0, 0, 0, 6,105,100,101, -110,116, 0, 0, 0, 0, 57, 0, 0, 0, 6, 99,108,111,115,101, 0, 0, 0, 0, - 61, 0, 0, 0, 2,105, 0, 0, 0, 0, 15, 2, 0, 0, 0, 6,105,100,101,110, -116, 0, 2, 0, 0, 0, 6, 99,108,111,115,101, 0, 2, 0, 0, 0, 6,112,114, -105,110,116, 0, 2, 0, 0, 0, 7, 67,108, 97,115,115,123, 0, 2, 0, 0, 0, - 10, 32,110, 97,109,101, 32, 61, 32, 39, 0, 2, 0, 0, 0, 5,115,101,108,102, - 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 3, 39, 44, 0, 2, - 0, 0, 0, 10, 32, 98, 97,115,101, 32, 61, 32, 39, 0, 2, 0, 0, 0, 5, 98, - 97,115,101, 0, 2, 0, 0, 0, 3, 39, 59, 0, 2, 0, 0, 0, 2,105, 0, 2, - 0, 0, 0, 2, 32, 0, 2, 0, 0, 0, 2, 44, 0, 2, 0, 0, 0, 2,125, 0, - 2, 0, 0, 0, 7, 95, 67,108, 97,115,115, 0, 4, 0, 0, 0, 70, 0, 0, 0, - 11, 64, 99,108, 97,115,115, 46,108,117, 97, 0, 0, 0, 0, 40, 4, 1, 60, 71, - 13, 0, 11, 1, 15, 2, 26, 60, 72, 15, 3, 13, 0, 15, 4, 2, 0, 2, 60, 73, - 15, 5, 13, 0, 2, 0, 1, 60, 74, 13, 0, 1, 1, 60, 75, 0, 0, 0, 0, 1, - 0, 0, 0, 70, 0, 0, 0, 2,116, 0, 0, 0, 0, 6, 2, 0, 0, 0, 2,116, - 0, 2, 0, 0, 0, 6, 95, 98, 97,115,101, 0, 2, 0, 0, 0, 11, 99,108, 97, -115,115, 67,108, 97,115,115, 0, 2, 0, 0, 0, 7,115,101,116,116, 97,103, 0, - 2, 0, 0, 0, 10,116,111,108,117, 97, 95,116, 97,103, 0, 2, 0, 0, 0, 7, - 97,112,112,101,110,100, 0, 2, 0, 0, 0, 6, 67,108, 97,115,115, 0, 4, 0, - 0, 0, 79, 0, 0, 0, 11, 64, 99,108, 97,115,115, 46,108,117, 97, 0, 0, 0, - 0, 73, 11, 3, 60, 80, 15, 4, 15, 5, 22, 2, 11, 6, 13, 0, 11, 7, 13, 1, - 30, 1, 2, 1, 1, 2, 1, 1, 60, 81, 15, 8, 13, 3, 2, 0, 1, 60, 82, 13, - 3, 20, 9, 15, 10, 13, 2, 7, 2, 15, 11, 13, 2, 2, 1, 1, 7, 1, 38, 2, - 1, 3, 2, 0, 2, 60, 83, 15, 12, 2, 0, 0, 60, 84, 0, 0, 0, 0, 4, 0, - 0, 0, 79, 0, 0, 0, 2,110, 0, 0, 0, 0, 79, 0, 0, 0, 2,112, 0, 0, - 0, 0, 79, 0, 0, 0, 2, 98, 0, 0, 0, 0, 80, 0, 0, 0, 2, 99, 0, 0, - 0, 0, 13, 2, 0, 0, 0, 2,110, 0, 2, 0, 0, 0, 2,112, 0, 2, 0, 0, - 0, 2, 98, 0, 2, 0, 0, 0, 2, 99, 0, 2, 0, 0, 0, 7, 95, 67,108, 97, -115,115, 0, 2, 0, 0, 0, 11, 95, 67,111,110,116, 97,105,110,101,114, 0, 2, - 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 5, 98, 97,115,101, 0, 2, - 0, 0, 0, 5,112,117,115,104, 0, 2, 0, 0, 0, 6,112, 97,114,115,101, 0, - 2, 0, 0, 0, 7,115,116,114,115,117, 98, 0, 2, 0, 0, 0, 7,115,116,114, -108,101,110, 0, 2, 0, 0, 0, 4,112,111,112, 0, -}; - -/* typedef.lo */ -static char B8[]={ - 27, 76,117, 97, 50, 0, 0, 0, 0, 0, 0, 0, 0, 13, 64,116,121,112,101,100, -101,102, 46,108,117, 97, 0, 0, 0, 0, 52, 7, 0, 60, 24, 22, 3, 60, 25, 11, - 1, 11, 2, 11, 3, 60, 26, 11, 2, 11, 4, 60, 27, 11, 2, 30, 2, 60, 28, 25, - 0, 60, 31, 15, 0, 11, 5, 11, 6, 26, 60, 40, 11, 8, 25, 7, 60, 49, 11, 10, - 25, 9, 0, 0, 0, 0, 0, 0, 0, 0, 11, 2, 0, 0, 0, 13, 99,108, 97,115, -115, 84,121,112,101,100,101,102, 0, 2, 0, 0, 0, 6,117,116,121,112,101, 0, - 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 4,109,111,100, 0, 2, 0, 0, 0, 5, -116,121,112,101, 0, 2, 0, 0, 0, 6,112,114,105,110,116, 0, 4, 0, 0, 0, - 31, 0, 0, 0, 13, 64,116,121,112,101,100,101,102, 46,108,117, 97, 0, 0, 0, - 0, 92, 6, 3, 60, 32, 15, 2, 13, 1, 11, 3, 42, 2, 0, 1, 60, 33, 15, 2, - 13, 1, 11, 4, 42, 13, 0, 18, 6, 42, 11, 7, 42, 2, 0, 1, 60, 34, 15, 2, - 13, 1, 11, 8, 42, 13, 0, 18, 9, 42, 11, 7, 42, 2, 0, 1, 60, 35, 15, 2, - 13, 1, 11, 10, 42, 13, 0, 18, 11, 42, 11, 7, 42, 2, 0, 1, 60, 36, 15, 2, - 13, 1, 11, 12, 42, 13, 2, 42, 2, 0, 1, 60, 37, 0, 0, 0, 0, 3, 0, 0, - 0, 31, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 31, 0, 0, 0, 6,105, -100,101,110,116, 0, 0, 0, 0, 31, 0, 0, 0, 6, 99,108,111,115,101, 0, 0, - 0, 0, 13, 2, 0, 0, 0, 6,105,100,101,110,116, 0, 2, 0, 0, 0, 6, 99, -108,111,115,101, 0, 2, 0, 0, 0, 6,112,114,105,110,116, 0, 2, 0, 0, 0, - 9, 84,121,112,101,100,101,102,123, 0, 2, 0, 0, 0, 11, 32,117,116,121,112, -101, 32, 61, 32, 39, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, - 6,117,116,121,112,101, 0, 2, 0, 0, 0, 3, 39, 44, 0, 2, 0, 0, 0, 9, - 32,109,111,100, 32, 61, 32, 39, 0, 2, 0, 0, 0, 4,109,111,100, 0, 2, 0, - 0, 0, 10, 32,116,121,112,101, 32, 61, 32, 39, 0, 2, 0, 0, 0, 5,116,121, -112,101, 0, 2, 0, 0, 0, 2,125, 0, 2, 0, 0, 0, 9, 95, 84,121,112,101, -100,101,102, 0, 4, 0, 0, 0, 40, 0, 0, 0, 13, 64,116,121,112,101,100,101, -102, 46,108,117, 97, 0, 0, 0, 0, 40, 4, 1, 60, 41, 13, 0, 11, 1, 15, 2, - 26, 60, 42, 15, 3, 13, 0, 15, 4, 2, 0, 2, 60, 43, 15, 5, 13, 0, 2, 0, - 1, 60, 44, 13, 0, 1, 1, 60, 45, 0, 0, 0, 0, 1, 0, 0, 0, 40, 0, 0, - 0, 2,116, 0, 0, 0, 0, 6, 2, 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 6, - 95, 98, 97,115,101, 0, 2, 0, 0, 0, 13, 99,108, 97,115,115, 84,121,112,101, -100,101,102, 0, 2, 0, 0, 0, 7,115,101,116,116, 97,103, 0, 2, 0, 0, 0, - 10,116,111,108,117, 97, 95,116, 97,103, 0, 2, 0, 0, 0, 14, 97,112,112,101, -110,100,116,121,112,101,100,101,102, 0, 2, 0, 0, 0, 8, 84,121,112,101,100, -101,102, 0, 4, 0, 0, 0, 49, 0, 0, 0, 13, 64,116,121,112,101,100,101,102, - 46,108,117, 97, 0, 0, 0, 0,109, 14, 1, 60, 50, 15, 1, 13, 0, 11, 2, 2, - 1, 2, 52, 11, 60, 51, 15, 3, 11, 4, 2, 0, 1, 50, 2, 60, 52, 60, 53, 15, - 6, 15, 7, 13, 0, 11, 8, 11, 9, 2, 1, 3, 11, 9, 2, 1, 2, 60, 54, 15, - 10, 22, 3, 60, 55, 11, 11, 13, 1, 13, 1, 18, 12, 16, 11, 13, 60, 56, 13, 1, - 13, 1, 18, 12, 7, 1, 38, 16, 11, 14, 60, 57, 15, 15, 13, 1, 7, 1, 13, 1, - 18, 12, 7, 2, 38, 2, 1, 3, 30, 2, 60, 58, 3, 2, 1, 60, 59, 0, 0, 0, - 0, 2, 0, 0, 0, 49, 0, 0, 0, 2,115, 0, 0, 0, 0, 53, 0, 0, 0, 2, -116, 0, 0, 0, 0, 16, 2, 0, 0, 0, 2,115, 0, 2, 0, 0, 0, 8,115,116, -114,102,105,110,100, 0, 2, 0, 0, 0, 6, 91, 37, 42, 38, 93, 0, 2, 0, 0, - 0, 12,116,111,108,117, 97, 95,101,114,114,111,114, 0, 2, 0, 0, 0, 62, 35, -105,110,118, 97,108,105,100, 32,116,121,112,101,100,101,102, 58, 32,112,111,105, -110,116,101,114,115, 32, 40, 97,110,100, 32,114,101,102,101,114,101,110, 99,101, -115, 41, 32, 97,114,101, 32,110,111,116, 32,115,117,112,112,111,114,116,101,100, - 0, 2, 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 6,115,112,108,105,116, 0, 2, - 0, 0, 0, 5,103,115,117, 98, 0, 2, 0, 0, 0, 6, 37,115, 37,115, 42, 0, - 2, 0, 0, 0, 2, 32, 0, 2, 0, 0, 0, 9, 95, 84,121,112,101,100,101,102, - 0, 2, 0, 0, 0, 6,117,116,121,112,101, 0, 2, 0, 0, 0, 2,110, 0, 2, - 0, 0, 0, 5,116,121,112,101, 0, 2, 0, 0, 0, 4,109,111,100, 0, 2, 0, - 0, 0, 7, 99,111,110, 99, 97,116, 0, -}; - -/* define.lo */ -static char B9[]={ - 27, 76,117, 97, 50, 0, 0, 0, 0, 0, 0, 0, 0, 12, 64,100,101,102,105,110, -101, 46,108,117, 97, 0, 0, 0, 0, 75, 5, 0, 60, 18, 22, 2, 60, 19, 11, 1, - 11, 2, 11, 3, 60, 20, 15, 4, 30, 1, 60, 21, 25, 0, 60, 22, 15, 5, 15, 0, - 15, 6, 2, 0, 2, 60, 25, 15, 0, 11, 7, 11, 8, 26, 60, 35, 15, 0, 11, 9, - 11, 10, 26, 60, 42, 15, 0, 11, 11, 11, 12, 26, 60, 51, 11, 14, 25, 13, 60, 65, - 11, 16, 25, 15, 0, 0, 0, 0, 0, 0, 0, 0, 17, 2, 0, 0, 0, 12, 99,108, - 97,115,115, 68,101,102,105,110,101, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, - 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 6, 95, 98, 97,115,101, 0, 2, 0, 0, - 0, 13, 99,108, 97,115,115, 70,101, 97,116,117,114,101, 0, 2, 0, 0, 0, 7, -115,101,116,116, 97,103, 0, 2, 0, 0, 0, 10,116,111,108,117, 97, 95,116, 97, -103, 0, 2, 0, 0, 0, 9,114,101,103,105,115,116,101,114, 0, 4, 0, 0, 0, - 25, 0, 0, 0, 12, 64,100,101,102,105,110,101, 46,108,117, 97, 0, 0, 0, 0, - 80, 5, 1, 60, 26, 13, 0, 20, 2, 2, 1, 1, 60, 27, 13, 1, 52, 33, 60, 28, - 15, 3, 11, 4, 13, 1, 42, 11, 5, 42, 13, 0, 18, 6, 42, 11, 7, 42, 13, 0, - 18, 8, 42, 11, 9, 42, 2, 0, 1, 50, 27, 60, 30, 15, 3, 11, 10, 13, 0, 18, - 6, 42, 11, 7, 42, 13, 0, 18, 8, 42, 11, 9, 42, 2, 0, 1, 60, 31, 60, 32, - 0, 0, 0, 0, 2, 0, 0, 0, 25, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, - 0, 26, 0, 0, 0, 2,112, 0, 0, 0, 0, 11, 2, 0, 0, 0, 2,112, 0, 2, - 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 9,105,110,109,111,100,117, -108,101, 0, 2, 0, 0, 0, 7,111,117,116,112,117,116, 0, 2, 0, 0, 0, 18, - 32,116,111,108,117, 97, 95, 99,111,110,115,116, 97,110,116, 40, 34, 0, 2, 0, - 0, 0, 4, 34, 44, 34, 0, 2, 0, 0, 0, 6,108,110, 97,109,101, 0, 2, 0, - 0, 0, 3, 34, 44, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, - 3, 41, 59, 0, 2, 0, 0, 0, 23, 32,116,111,108,117, 97, 95, 99,111,110,115, -116, 97,110,116, 40, 78, 85, 76, 76, 44, 34, 0, 2, 0, 0, 0, 11,117,110,114, -101,103,105,115,116,101,114, 0, 4, 0, 0, 0, 35, 0, 0, 0, 12, 64,100,101, -102,105,110,101, 46,108,117, 97, 0, 0, 0, 0, 38, 4, 1, 60, 36, 13, 0, 20, - 1, 2, 1, 1, 44, 52, 19, 60, 37, 15, 2, 11, 3, 13, 0, 18, 4, 42, 11, 5, - 42, 2, 0, 1, 50, 2, 60, 38, 60, 39, 0, 0, 0, 0, 1, 0, 0, 0, 35, 0, - 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 6, 2, 0, 0, 0, 5,115,101,108, -102, 0, 2, 0, 0, 0, 9,105,110,109,111,100,117,108,101, 0, 2, 0, 0, 0, - 7,111,117,116,112,117,116, 0, 2, 0, 0, 0, 32, 32,108,117, 97, 95,112,117, -115,104,110,105,108, 40, 41, 59, 32,108,117, 97, 95,115,101,116,103,108,111, 98, - 97,108, 40, 34, 0, 2, 0, 0, 0, 6,108,110, 97,109,101, 0, 2, 0, 0, 0, - 4, 34, 41, 59, 0, 2, 0, 0, 0, 6,112,114,105,110,116, 0, 4, 0, 0, 0, - 42, 0, 0, 0, 12, 64,100,101,102,105,110,101, 46,108,117, 97, 0, 0, 0, 0, - 72, 6, 3, 60, 43, 15, 2, 13, 1, 11, 3, 42, 2, 0, 1, 60, 44, 15, 2, 13, - 1, 11, 4, 42, 13, 0, 18, 6, 42, 11, 7, 42, 2, 0, 1, 60, 45, 15, 2, 13, - 1, 11, 8, 42, 13, 0, 18, 9, 42, 11, 7, 42, 2, 0, 1, 60, 46, 15, 2, 13, - 1, 11, 10, 42, 13, 2, 42, 2, 0, 1, 60, 47, 0, 0, 0, 0, 3, 0, 0, 0, - 42, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 42, 0, 0, 0, 6,105,100, -101,110,116, 0, 0, 0, 0, 42, 0, 0, 0, 6, 99,108,111,115,101, 0, 0, 0, - 0, 11, 2, 0, 0, 0, 6,105,100,101,110,116, 0, 2, 0, 0, 0, 6, 99,108, -111,115,101, 0, 2, 0, 0, 0, 6,112,114,105,110,116, 0, 2, 0, 0, 0, 8, - 68,101,102,105,110,101,123, 0, 2, 0, 0, 0, 10, 32,110, 97,109,101, 32, 61, - 32, 39, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 5,110, 97, -109,101, 0, 2, 0, 0, 0, 3, 39, 44, 0, 2, 0, 0, 0, 11, 32,108,110, 97, -109,101, 32, 61, 32, 39, 0, 2, 0, 0, 0, 6,108,110, 97,109,101, 0, 2, 0, - 0, 0, 2,125, 0, 2, 0, 0, 0, 8, 95, 68,101,102,105,110,101, 0, 4, 0, - 0, 0, 51, 0, 0, 0, 12, 64,100,101,102,105,110,101, 46,108,117, 97, 0, 0, - 0, 0, 64, 4, 1, 60, 52, 13, 0, 11, 1, 15, 2, 26, 60, 53, 15, 3, 13, 0, - 15, 4, 2, 0, 2, 60, 55, 13, 0, 18, 5, 11, 6, 32, 52, 11, 60, 56, 15, 7, - 11, 8, 2, 0, 1, 50, 2, 60, 57, 60, 59, 15, 9, 13, 0, 2, 0, 1, 60, 60, - 13, 0, 1, 1, 60, 61, 0, 0, 0, 0, 1, 0, 0, 0, 51, 0, 0, 0, 2,116, - 0, 0, 0, 0, 10, 2, 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 6, 95, 98, 97, -115,101, 0, 2, 0, 0, 0, 12, 99,108, 97,115,115, 68,101,102,105,110,101, 0, - 2, 0, 0, 0, 7,115,101,116,116, 97,103, 0, 2, 0, 0, 0, 10,116,111,108, -117, 97, 95,116, 97,103, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, - 0, 1, 0, 2, 0, 0, 0, 6,101,114,114,111,114, 0, 2, 0, 0, 0, 16, 35, -105,110,118, 97,108,105,100, 32,100,101,102,105,110,101, 0, 2, 0, 0, 0, 7, - 97,112,112,101,110,100, 0, 2, 0, 0, 0, 7, 68,101,102,105,110,101, 0, 4, - 0, 0, 0, 65, 0, 0, 0, 12, 64,100,101,102,105,110,101, 46,108,117, 97, 0, - 0, 0, 0, 54, 9, 1, 60, 66, 15, 2, 13, 0, 11, 3, 2, 1, 2, 60, 67, 15, - 4, 22, 2, 60, 68, 11, 5, 13, 1, 7, 1, 16, 11, 6, 60, 69, 13, 1, 7, 2, - 16, 46, 5, 13, 1, 7, 1, 16, 30, 1, 60, 70, 3, 2, 1, 60, 71, 0, 0, 0, - 0, 2, 0, 0, 0, 65, 0, 0, 0, 2,110, 0, 0, 0, 0, 66, 0, 0, 0, 2, -116, 0, 0, 0, 0, 7, 2, 0, 0, 0, 2,110, 0, 2, 0, 0, 0, 2,116, 0, - 2, 0, 0, 0, 6,115,112,108,105,116, 0, 2, 0, 0, 0, 2, 64, 0, 2, 0, - 0, 0, 8, 95, 68,101,102,105,110,101, 0, 2, 0, 0, 0, 5,110, 97,109,101, - 0, 2, 0, 0, 0, 6,108,110, 97,109,101, 0, -}; - -/* enumerate.lo */ -static char B10[]={ - 27, 76,117, 97, 50, 0, 0, 0, 0, 0, 0, 0, 0, 15, 64,101,110,117,109,101, -114, 97,116,101, 46,108,117, 97, 0, 0, 0, 0, 69, 3, 0, 60, 19, 22, 1, 60, - 20, 11, 1, 15, 2, 30, 0, 60, 21, 25, 0, 60, 22, 15, 3, 15, 0, 15, 4, 2, - 0, 2, 60, 25, 15, 0, 11, 5, 11, 6, 26, 60, 42, 15, 0, 11, 7, 11, 8, 26, - 60, 53, 15, 0, 11, 9, 11, 10, 26, 60, 64, 11, 12, 25, 11, 60, 73, 11, 14, 25, - 13, 0, 0, 0, 0, 0, 0, 0, 0, 15, 2, 0, 0, 0, 15, 99,108, 97,115,115, - 69,110,117,109,101,114, 97,116,101, 0, 2, 0, 0, 0, 6, 95, 98, 97,115,101, - 0, 2, 0, 0, 0, 13, 99,108, 97,115,115, 70,101, 97,116,117,114,101, 0, 2, - 0, 0, 0, 7,115,101,116,116, 97,103, 0, 2, 0, 0, 0, 10,116,111,108,117, - 97, 95,116, 97,103, 0, 2, 0, 0, 0, 9,114,101,103,105,115,116,101,114, 0, - 4, 0, 0, 0, 25, 0, 0, 0, 15, 64,101,110,117,109,101,114, 97,116,101, 46, -108,117, 97, 0, 0, 0, 0,179, 7, 1, 60, 26, 13, 0, 20, 2, 2, 1, 1, 46, - 7, 13, 0, 20, 3, 2, 1, 1, 60, 27, 7, 1, 50,141, 60, 29, 13, 1, 52, 93, - 60, 30, 13, 0, 20, 2, 2, 1, 1, 52, 43, 60, 31, 15, 5, 11, 6, 13, 1, 42, - 11, 7, 42, 13, 0, 18, 8, 13, 2, 16, 42, 11, 9, 42, 13, 1, 42, 11, 10, 42, - 13, 0, 13, 2, 16, 42, 11, 11, 42, 2, 0, 1, 50, 37, 60, 33, 15, 5, 11, 6, - 13, 1, 42, 11, 7, 42, 13, 0, 18, 8, 13, 2, 16, 42, 11, 9, 42, 13, 0, 13, - 2, 16, 42, 11, 11, 42, 2, 0, 1, 60, 34, 50, 31, 60, 36, 15, 5, 11, 12, 13, - 0, 18, 8, 13, 2, 16, 42, 11, 9, 42, 13, 0, 13, 2, 16, 42, 11, 11, 42, 2, - 0, 1, 60, 37, 60, 38, 13, 2, 7, 1, 37, 23, 2, 60, 39, 60, 28, 13, 0, 13, - 2, 16, 54,150, 60, 40, 0, 0, 0, 0, 3, 0, 0, 0, 25, 0, 0, 0, 5,115, -101,108,102, 0, 0, 0, 0, 26, 0, 0, 0, 2,112, 0, 0, 0, 0, 27, 0, 0, - 0, 2,105, 0, 0, 0, 0, 13, 2, 0, 0, 0, 2,112, 0, 2, 0, 0, 0, 5, -115,101,108,102, 0, 2, 0, 0, 0, 8,105,110, 99,108, 97,115,115, 0, 2, 0, - 0, 0, 9,105,110,109,111,100,117,108,101, 0, 2, 0, 0, 0, 2,105, 0, 2, - 0, 0, 0, 7,111,117,116,112,117,116, 0, 2, 0, 0, 0, 18, 32,116,111,108, -117, 97, 95, 99,111,110,115,116, 97,110,116, 40, 34, 0, 2, 0, 0, 0, 4, 34, - 44, 34, 0, 2, 0, 0, 0, 7,108,110, 97,109,101,115, 0, 2, 0, 0, 0, 3, - 34, 44, 0, 2, 0, 0, 0, 3, 58, 58, 0, 2, 0, 0, 0, 3, 41, 59, 0, 2, - 0, 0, 0, 23, 32,116,111,108,117, 97, 95, 99,111,110,115,116, 97,110,116, 40, - 78, 85, 76, 76, 44, 34, 0, 2, 0, 0, 0, 11,117,110,114,101,103,105,115,116, -101,114, 0, 4, 0, 0, 0, 42, 0, 0, 0, 15, 64,101,110,117,109,101,114, 97, -116,101, 46,108,117, 97, 0, 0, 0, 0, 83, 6, 1, 60, 43, 13, 0, 20, 1, 2, - 1, 1, 4, 0, 32, 48, 10, 13, 0, 20, 2, 2, 1, 1, 4, 0, 32, 52, 50, 60, - 44, 7, 1, 50, 31, 60, 46, 15, 4, 11, 5, 13, 0, 18, 6, 13, 1, 16, 42, 11, - 7, 42, 2, 0, 1, 60, 47, 13, 1, 7, 1, 37, 23, 1, 60, 48, 60, 45, 13, 0, - 13, 1, 16, 54, 40, 5, 1, 50, 2, 60, 49, 60, 50, 0, 0, 0, 0, 3, 0, 0, - 0, 42, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 44, 0, 0, 0, 2,105, - 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 8, 2, 0, 0, 0, 5,115,101, -108,102, 0, 2, 0, 0, 0, 8,105,110, 99,108, 97,115,115, 0, 2, 0, 0, 0, - 9,105,110,109,111,100,117,108,101, 0, 2, 0, 0, 0, 2,105, 0, 2, 0, 0, - 0, 7,111,117,116,112,117,116, 0, 2, 0, 0, 0, 32, 32,108,117, 97, 95,112, -117,115,104,110,105,108, 40, 41, 59, 32,108,117, 97, 95,115,101,116,103,108,111, - 98, 97,108, 40, 34, 0, 2, 0, 0, 0, 7,108,110, 97,109,101,115, 0, 2, 0, - 0, 0, 4, 34, 41, 59, 0, 2, 0, 0, 0, 6,112,114,105,110,116, 0, 4, 0, - 0, 0, 53, 0, 0, 0, 15, 64,101,110,117,109,101,114, 97,116,101, 46,108,117, - 97, 0, 0, 0, 0, 90, 8, 3, 60, 54, 15, 2, 13, 1, 11, 3, 42, 2, 0, 1, - 60, 55, 7, 1, 50, 43, 60, 57, 15, 2, 13, 1, 11, 6, 42, 13, 0, 13, 3, 16, - 42, 11, 7, 42, 13, 0, 18, 8, 13, 3, 16, 42, 11, 9, 42, 2, 0, 1, 60, 58, - 13, 3, 7, 1, 37, 23, 3, 60, 59, 60, 56, 13, 0, 13, 3, 16, 54, 52, 60, 60, - 15, 2, 13, 1, 11, 10, 42, 13, 2, 42, 2, 0, 1, 60, 61, 0, 0, 0, 0, 4, - 0, 0, 0, 53, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 53, 0, 0, 0, - 6,105,100,101,110,116, 0, 0, 0, 0, 53, 0, 0, 0, 6, 99,108,111,115,101, - 0, 0, 0, 0, 55, 0, 0, 0, 2,105, 0, 0, 0, 0, 11, 2, 0, 0, 0, 6, -105,100,101,110,116, 0, 2, 0, 0, 0, 6, 99,108,111,115,101, 0, 2, 0, 0, - 0, 6,112,114,105,110,116, 0, 2, 0, 0, 0, 11, 69,110,117,109,101,114, 97, -116,101,123, 0, 2, 0, 0, 0, 2,105, 0, 2, 0, 0, 0, 5,115,101,108,102, - 0, 2, 0, 0, 0, 3, 32, 39, 0, 2, 0, 0, 0, 3, 39, 40, 0, 2, 0, 0, - 0, 7,108,110, 97,109,101,115, 0, 2, 0, 0, 0, 3, 41, 44, 0, 2, 0, 0, - 0, 2,125, 0, 2, 0, 0, 0, 11, 95, 69,110,117,109,101,114, 97,116,101, 0, - 4, 0, 0, 0, 64, 0, 0, 0, 15, 64,101,110,117,109,101,114, 97,116,101, 46, -108,117, 97, 0, 0, 0, 0, 40, 4, 1, 60, 65, 13, 0, 11, 1, 15, 2, 26, 60, - 66, 15, 3, 13, 0, 15, 4, 2, 0, 2, 60, 67, 15, 5, 13, 0, 2, 0, 1, 60, - 68, 13, 0, 1, 1, 60, 69, 0, 0, 0, 0, 1, 0, 0, 0, 64, 0, 0, 0, 2, -116, 0, 0, 0, 0, 6, 2, 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 6, 95, 98, - 97,115,101, 0, 2, 0, 0, 0, 15, 99,108, 97,115,115, 69,110,117,109,101,114, - 97,116,101, 0, 2, 0, 0, 0, 7,115,101,116,116, 97,103, 0, 2, 0, 0, 0, - 10,116,111,108,117, 97, 95,116, 97,103, 0, 2, 0, 0, 0, 7, 97,112,112,101, -110,100, 0, 2, 0, 0, 0, 10, 69,110,117,109,101,114, 97,116,101, 0, 4, 0, - 0, 0, 73, 0, 0, 0, 15, 64,101,110,117,109,101,114, 97,116,101, 46,108,117, - 97, 0, 0, 0, 0,200, 9, 1, 60, 74, 15, 2, 15, 3, 13, 0, 7, 2, 9, 2, - 2, 1, 3, 11, 4, 2, 1, 2, 60, 75, 7, 1, 60, 76, 22, 1, 11, 7, 7, 0, - 30, 0, 50, 55, 60, 78, 15, 2, 13, 1, 13, 2, 16, 11, 9, 2, 1, 2, 60, 79, - 13, 3, 11, 7, 13, 3, 18, 7, 7, 1, 37, 26, 60, 80, 13, 3, 13, 3, 18, 7, - 13, 4, 7, 1, 16, 26, 60, 81, 13, 2, 7, 1, 37, 23, 2, 5, 1, 60, 82, 60, - 77, 13, 1, 13, 2, 16, 54, 64, 60, 84, 7, 1, 23, 2, 60, 85, 13, 3, 11, 10, - 22, 0, 26, 50, 60, 60, 87, 15, 2, 13, 3, 13, 2, 16, 11, 11, 2, 1, 2, 60, - 88, 13, 3, 13, 2, 13, 4, 7, 1, 16, 26, 60, 89, 13, 3, 18, 10, 13, 2, 13, - 4, 7, 2, 16, 46, 5, 13, 4, 7, 1, 16, 26, 60, 90, 13, 2, 7, 1, 37, 23, - 2, 5, 1, 60, 91, 60, 86, 13, 3, 13, 2, 16, 54, 69, 60, 92, 15, 12, 13, 3, - 3, 4, 1, 60, 93, 0, 0, 0, 0, 8, 0, 0, 0, 73, 0, 0, 0, 2, 98, 0, - 0, 0, 0, 74, 0, 0, 0, 2,116, 0, 0, 0, 0, 75, 0, 0, 0, 2,105, 0, - 0, 0, 0, 76, 0, 0, 0, 2,101, 0, 0, 0, 0, 78, 0, 0, 0, 3,116,116, - 0, 0, 0, 0, 81, 0, 0, 0, 0, 0, 0, 0, 87, 0, 0, 0, 2,116, 0, 0, - 0, 0, 90, 0, 0, 0, 0, 0, 0, 0, 13, 2, 0, 0, 0, 2, 98, 0, 2, 0, - 0, 0, 2,116, 0, 2, 0, 0, 0, 6,115,112,108,105,116, 0, 2, 0, 0, 0, - 7,115,116,114,115,117, 98, 0, 2, 0, 0, 0, 2, 44, 0, 2, 0, 0, 0, 2, -105, 0, 2, 0, 0, 0, 2,101, 0, 2, 0, 0, 0, 2,110, 0, 2, 0, 0, 0, - 3,116,116, 0, 2, 0, 0, 0, 2, 61, 0, 2, 0, 0, 0, 7,108,110, 97,109, -101,115, 0, 2, 0, 0, 0, 2, 64, 0, 2, 0, 0, 0, 11, 95, 69,110,117,109, -101,114, 97,116,101, 0, -}; - -/* variable.lo */ -static char B11[]={ - 27, 76,117, 97, 50, 0, 0, 0, 0, 0, 0, 0, 0, 14, 64,118, 97,114,105, 97, - 98,108,101, 46,108,117, 97, 0, 0, 0, 0, 87, 3, 0, 60, 18, 22, 1, 60, 19, - 11, 1, 15, 2, 30, 0, 60, 20, 25, 0, 60, 22, 15, 3, 15, 0, 15, 4, 2, 0, - 2, 60, 25, 15, 0, 11, 5, 11, 6, 26, 60, 37, 15, 0, 11, 7, 11, 8, 26, 60, - 48, 15, 0, 11, 9, 11, 10, 26, 60,154, 15, 0, 11, 11, 11, 12, 26, 60,171, 15, - 0, 11, 13, 11, 14, 26, 60,179, 11, 16, 25, 15, 60,188, 11, 18, 25, 17, 0, 0, - 0, 0, 0, 0, 0, 0, 19, 2, 0, 0, 0, 14, 99,108, 97,115,115, 86, 97,114, -105, 97, 98,108,101, 0, 2, 0, 0, 0, 6, 95, 98, 97,115,101, 0, 2, 0, 0, - 0, 17, 99,108, 97,115,115, 68,101, 99,108, 97,114, 97,116,105,111,110, 0, 2, - 0, 0, 0, 7,115,101,116,116, 97,103, 0, 2, 0, 0, 0, 10,116,111,108,117, - 97, 95,116, 97,103, 0, 2, 0, 0, 0, 6,112,114,105,110,116, 0, 4, 0, 0, - 0, 25, 0, 0, 0, 14, 64,118, 97,114,105, 97, 98,108,101, 46,108,117, 97, 0, - 0, 0, 0,152, 6, 3, 60, 26, 15, 2, 13, 1, 11, 3, 42, 2, 0, 1, 60, 27, - 15, 2, 13, 1, 11, 4, 42, 13, 0, 18, 6, 42, 11, 7, 42, 2, 0, 1, 60, 28, - 15, 2, 13, 1, 11, 8, 42, 13, 0, 18, 9, 42, 11, 7, 42, 2, 0, 1, 60, 29, - 15, 2, 13, 1, 11, 10, 42, 13, 0, 18, 11, 42, 11, 7, 42, 2, 0, 1, 60, 30, - 15, 2, 13, 1, 11, 12, 42, 13, 0, 18, 13, 42, 11, 7, 42, 2, 0, 1, 60, 31, - 15, 2, 13, 1, 11, 14, 42, 13, 0, 18, 15, 42, 11, 7, 42, 2, 0, 1, 60, 32, - 15, 2, 13, 1, 11, 16, 42, 13, 0, 18, 17, 42, 11, 7, 42, 2, 0, 1, 60, 33, - 15, 2, 13, 1, 11, 18, 42, 13, 2, 42, 2, 0, 1, 60, 34, 0, 0, 0, 0, 3, - 0, 0, 0, 25, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 25, 0, 0, 0, - 6,105,100,101,110,116, 0, 0, 0, 0, 25, 0, 0, 0, 6, 99,108,111,115,101, - 0, 0, 0, 0, 19, 2, 0, 0, 0, 6,105,100,101,110,116, 0, 2, 0, 0, 0, - 6, 99,108,111,115,101, 0, 2, 0, 0, 0, 6,112,114,105,110,116, 0, 2, 0, - 0, 0, 10, 86, 97,114,105, 97, 98,108,101,123, 0, 2, 0, 0, 0, 10, 32,109, -111,100, 32, 32, 61, 32, 39, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, - 0, 0, 4,109,111,100, 0, 2, 0, 0, 0, 3, 39, 44, 0, 2, 0, 0, 0, 10, - 32,116,121,112,101, 32, 61, 32, 39, 0, 2, 0, 0, 0, 5,116,121,112,101, 0, - 2, 0, 0, 0, 10, 32,112,116,114, 32, 32, 61, 32, 39, 0, 2, 0, 0, 0, 4, -112,116,114, 0, 2, 0, 0, 0, 10, 32,110, 97,109,101, 32, 61, 32, 39, 0, 2, - 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 10, 32,100,101,102, 32, 32, - 61, 32, 39, 0, 2, 0, 0, 0, 4,100,101,102, 0, 2, 0, 0, 0, 10, 32,114, -101,116, 32, 32, 61, 32, 39, 0, 2, 0, 0, 0, 4,114,101,116, 0, 2, 0, 0, - 0, 2,125, 0, 2, 0, 0, 0, 9,103,101,116,118, 97,108,117,101, 0, 4, 0, - 0, 0, 37, 0, 0, 0, 14, 64,118, 97,114,105, 97, 98,108,101, 46,108,117, 97, - 0, 0, 0, 0, 60, 5, 3, 60, 38, 13, 1, 48, 2, 13, 2, 52, 16, 60, 39, 13, - 1, 11, 2, 42, 13, 0, 18, 4, 42, 1, 3, 50, 29, 60, 40, 13, 1, 52, 13, 60, - 41, 11, 5, 13, 0, 18, 4, 42, 1, 3, 50, 10, 60, 43, 13, 0, 18, 4, 1, 3, - 60, 44, 60, 45, 0, 0, 0, 0, 3, 0, 0, 0, 37, 0, 0, 0, 5,115,101,108, -102, 0, 0, 0, 0, 37, 0, 0, 0, 6, 99,108, 97,115,115, 0, 0, 0, 0, 37, - 0, 0, 0, 7,115,116, 97,116,105, 99, 0, 0, 0, 0, 6, 2, 0, 0, 0, 6, - 99,108, 97,115,115, 0, 2, 0, 0, 0, 7,115,116, 97,116,105, 99, 0, 2, 0, - 0, 0, 3, 58, 58, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, - 5,110, 97,109,101, 0, 2, 0, 0, 0, 7,115,101,108,102, 45, 62, 0, 2, 0, - 0, 0, 8,115,117,112, 99,111,100,101, 0, 4, 0, 0, 0, 48, 0, 0, 0, 14, - 64,118, 97,114,105, 97, 98,108,101, 46,108,117, 97, 0, 0, 0, 3,189, 17, 1, - 60, 49, 13, 0, 20, 2, 2, 1, 1, 60, 52, 13, 1, 52, 21, 60, 53, 15, 3, 11, - 4, 13, 0, 18, 5, 11, 6, 13, 1, 11, 7, 2, 0, 5, 50, 17, 60, 55, 15, 3, - 11, 4, 13, 0, 18, 5, 11, 7, 2, 0, 3, 60, 56, 60, 57, 13, 0, 11, 8, 13, - 0, 20, 9, 11, 10, 2, 1, 2, 26, 60, 58, 15, 3, 11, 11, 13, 0, 18, 8, 11, - 12, 2, 0, 3, 60, 59, 15, 3, 11, 13, 2, 0, 1, 60, 62, 15, 16, 13, 0, 18, - 17, 11, 18, 2, 3, 2, 60, 63, 13, 1, 48, 5, 13, 4, 4, 0, 32, 52, 39, 60, - 64, 15, 3, 11, 19, 13, 1, 11, 20, 11, 21, 2, 0, 4, 60, 65, 15, 3, 11, 22, - 13, 1, 11, 23, 2, 0, 3, 60, 66, 15, 3, 11, 24, 2, 0, 1, 50, 35, 60, 67, - 13, 4, 52, 27, 60, 68, 13, 0, 11, 17, 15, 16, 13, 0, 18, 17, 11, 25, 2, 3, - 2, 27, 2, 23, 3, 23, 3, 5, 2, 50, 2, 60, 69, 60, 73, 13, 1, 48, 5, 13, - 4, 4, 0, 32, 52, 19, 60, 74, 15, 3, 11, 26, 13, 0, 18, 5, 42, 11, 27, 42, - 2, 0, 1, 50, 2, 60, 75, 60, 78, 15, 29, 13, 0, 18, 30, 2, 1, 1, 60, 79, - 13, 5, 11, 31, 32, 52, 32, 60, 80, 15, 3, 11, 32, 13, 5, 42, 11, 33, 42, 13, - 0, 20, 34, 13, 1, 13, 4, 2, 1, 3, 42, 11, 35, 42, 2, 0, 1, 50,124, 60, - 81, 13, 5, 52, 32, 60, 82, 15, 3, 11, 32, 13, 5, 42, 11, 22, 42, 13, 0, 20, - 34, 13, 1, 13, 4, 2, 1, 3, 42, 11, 35, 42, 2, 0, 1, 50, 86, 60, 84, 13, - 0, 18, 36, 11, 37, 32, 46, 7, 13, 0, 18, 36, 11, 38, 32, 52, 32, 60, 85, 15, - 3, 11, 39, 13, 0, 20, 34, 13, 1, 13, 4, 2, 1, 3, 42, 11, 40, 42, 13, 0, - 18, 41, 11, 35, 2, 0, 3, 50, 32, 60, 87, 15, 3, 11, 42, 13, 0, 20, 34, 13, - 1, 13, 4, 2, 1, 3, 42, 11, 40, 42, 13, 0, 18, 41, 11, 35, 2, 0, 3, 60, - 88, 60, 89, 60, 90, 15, 3, 11, 43, 2, 0, 1, 60, 91, 15, 3, 11, 44, 2, 0, - 1, 60, 94, 15, 16, 13, 0, 18, 17, 11, 45, 2, 1, 2, 44, 51, 2, 0, 60, 95, - 13, 1, 52, 21, 60, 96, 15, 3, 11, 46, 13, 0, 18, 5, 11, 6, 13, 1, 11, 7, - 2, 0, 5, 50, 17, 60, 98, 15, 3, 11, 46, 13, 0, 18, 5, 11, 7, 2, 0, 3, - 60, 99, 60,100, 13, 0, 11, 47, 13, 0, 20, 9, 11, 48, 2, 1, 2, 26, 60,101, - 15, 3, 11, 11, 13, 0, 18, 47, 11, 12, 2, 0, 3, 60,102, 15, 3, 11, 13, 2, - 0, 1, 60,105, 7, 1, 60,106, 13, 1, 48, 5, 13, 4, 4, 0, 32, 52, 65, 60, -107, 15, 3, 11, 19, 13, 1, 11, 20, 11, 21, 2, 0, 4, 60,108, 15, 3, 11, 22, - 13, 1, 11, 23, 2, 0, 3, 60,109, 15, 3, 11, 24, 2, 0, 1, 60,111, 15, 3, - 11, 26, 13, 0, 18, 5, 42, 11, 27, 42, 2, 0, 1, 60,112, 13, 6, 7, 1, 37, - 23, 6, 50, 44, 60,113, 13, 4, 52, 36, 60,114, 13, 0, 11, 17, 15, 16, 13, 0, - 18, 17, 11, 25, 2, 3, 2, 27, 2, 23, 3, 23, 3, 5, 2, 60,115, 13, 6, 7, - 1, 37, 23, 6, 50, 2, 60,116, 60,119, 15, 3, 11, 50, 13, 0, 20, 51, 13, 6, - 2, 1, 2, 42, 11, 52, 42, 2, 0, 1, 60,120, 15, 3, 11, 53, 2, 0, 1, 60, -123, 11, 38, 60,124, 13, 0, 18, 36, 11, 38, 31, 52, 4, 11, 20, 23, 7, 60,125, - 15, 3, 11, 19, 2, 0, 1, 60,126, 13, 1, 48, 2, 13, 4, 52, 19, 60,127, 15, - 3, 13, 1, 11, 54, 42, 13, 0, 18, 5, 42, 2, 0, 1, 50, 35, 60,128, 13, 1, - 52, 16, 60,129, 15, 3, 11, 55, 13, 0, 18, 5, 42, 2, 0, 1, 50, 13, 60,131, - 15, 3, 13, 0, 18, 5, 2, 0, 1, 60,132, 60,133, 15, 29, 13, 0, 18, 30, 2, - 1, 1, 60,134, 15, 3, 11, 56, 2, 0, 1, 60,135, 13, 8, 44, 48, 5, 13, 7, - 11, 38, 32, 52, 7, 15, 3, 11, 20, 2, 0, 1, 60,136, 15, 3, 11, 57, 13, 0, - 18, 17, 13, 0, 18, 30, 2, 0, 3, 60,137, 13, 8, 44, 52, 11, 60,138, 15, 3, - 11, 20, 2, 0, 1, 50, 2, 60,139, 60,140, 15, 3, 11, 58, 2, 0, 1, 60,141, - 7, 0, 60,142, 13, 0, 18, 59, 11, 38, 31, 52, 6, 13, 0, 18, 59, 23, 9, 60, -143, 13, 8, 52, 24, 60,144, 15, 3, 11, 60, 13, 8, 42, 11, 22, 13, 6, 11, 40, - 13, 9, 11, 61, 2, 0, 6, 50, 19, 60,146, 15, 3, 11, 62, 13, 6, 11, 40, 13, - 9, 11, 61, 2, 0, 5, 60,147, 60,148, 15, 3, 11, 43, 2, 0, 1, 60,149, 15, - 3, 11, 44, 2, 0, 1, 5, 4, 50, 2, 60,150, 60,152, 0, 0, 0, 0, 14, 0, - 0, 0, 48, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 49, 0, 0, 0, 6, - 99,108, 97,115,115, 0, 0, 0, 0, 62, 0, 0, 0, 2, 95, 0, 0, 0, 0, 62, - 0, 0, 0, 2, 95, 0, 0, 0, 0, 62, 0, 0, 0, 7,115,116, 97,116,105, 99, - 0, 0, 0, 0, 78, 0, 0, 0, 2,116, 0, 0, 0, 0,105, 0, 0, 0, 5,110, - 97,114,103, 0, 0, 0, 0,123, 0, 0, 0, 4,112,116,114, 0, 0, 0, 0,133, - 0, 0, 0, 2,116, 0, 0, 0, 0,141, 0, 0, 0, 4,100,101,102, 0, 0, 0, - 0,149, 0, 0, 0, 0, 0, 0, 0,149, 0, 0, 0, 0, 0, 0, 0,149, 0, 0, - 0, 0, 0, 0, 0,149, 0, 0, 0, 0, 0, 0, 0, 63, 2, 0, 0, 0, 6, 99, -108, 97,115,115, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 8, -105,110, 99,108, 97,115,115, 0, 2, 0, 0, 0, 7,111,117,116,112,117,116, 0, - 2, 0, 0, 0, 17, 47, 42, 32,103,101,116, 32,102,117,110, 99,116,105,111,110, - 58, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 11, 32,111,102, - 32, 99,108, 97,115,115, 32, 0, 2, 0, 0, 0, 4, 32, 42, 47, 0, 2, 0, 0, - 0, 9, 99,103,101,116,110, 97,109,101, 0, 2, 0, 0, 0, 10, 99,102,117,110, - 99,110, 97,109,101, 0, 2, 0, 0, 0, 11,116,111,108,117, 97, 73, 95,103,101, -116, 0, 2, 0, 0, 0, 12,115,116, 97,116,105, 99, 32,118,111,105,100, 0, 2, - 0, 0, 0, 7, 40,118,111,105,100, 41, 0, 2, 0, 0, 0, 2,123, 0, 2, 0, - 0, 0, 2, 95, 0, 2, 0, 0, 0, 7,115,116, 97,116,105, 99, 0, 2, 0, 0, - 0, 8,115,116,114,102,105,110,100, 0, 2, 0, 0, 0, 4,109,111,100, 0, 2, - 0, 0, 0, 13, 94, 37,115, 42, 40,115,116, 97,116,105, 99, 41, 0, 2, 0, 0, - 0, 2, 32, 0, 2, 0, 0, 0, 2, 42, 0, 2, 0, 0, 0, 8,115,101,108,102, - 32, 61, 32, 0, 2, 0, 0, 0, 2, 40, 0, 2, 0, 0, 0, 4, 42, 41, 32, 0, - 2, 0, 0, 0, 24,116,111,108,117, 97, 95,103,101,116,117,115,101,114,116,121, -112,101, 40, 49, 44, 48, 41, 59, 0, 2, 0, 0, 0, 20, 94, 37,115, 42,115,116, - 97,116,105, 99, 37,115, 37,115, 42, 40, 46, 42, 41, 0, 2, 0, 0, 0, 65, 32, - 32,105,102, 32, 40, 33,115,101,108,102, 41, 32,116,111,108,117, 97, 95,101,114, -114,111,114, 40, 34,105,110,118, 97,108,105,100, 32, 39,115,101,108,102, 39, 32, -105,110, 32, 97, 99, 99,101,115,115,105,110,103, 32,118, 97,114,105, 97, 98,108, -101, 32, 39, 0, 2, 0, 0, 0, 5, 39, 34, 41, 59, 0, 2, 0, 0, 0, 2,116, - 0, 2, 0, 0, 0, 8,105,115, 98, 97,115,105, 99, 0, 2, 0, 0, 0, 5,116, -121,112,101, 0, 2, 0, 0, 0, 7,110,117,109, 98,101,114, 0, 2, 0, 0, 0, - 13, 32, 32,116,111,108,117, 97, 95,112,117,115,104, 0, 2, 0, 0, 0, 10, 40, - 40,100,111,117, 98,108,101, 41, 0, 2, 0, 0, 0, 9,103,101,116,118, 97,108, -117,101, 0, 2, 0, 0, 0, 3, 41, 59, 0, 2, 0, 0, 0, 4,112,116,114, 0, - 2, 0, 0, 0, 2, 38, 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 30, 32, 32, -116,111,108,117, 97, 95,112,117,115,104,117,115,101,114,116,121,112,101, 40, 40, -118,111,105,100, 42, 41, 38, 0, 2, 0, 0, 0, 2, 44, 0, 2, 0, 0, 0, 4, -116, 97,103, 0, 2, 0, 0, 0, 29, 32, 32,116,111,108,117, 97, 95,112,117,115, -104,117,115,101,114,116,121,112,101, 40, 40,118,111,105,100, 42, 41, 0, 2, 0, - 0, 0, 2,125, 0, 2, 0, 0, 0, 2, 10, 0, 2, 0, 0, 0, 6, 99,111,110, -115,116, 0, 2, 0, 0, 0, 17, 47, 42, 32,115,101,116, 32,102,117,110, 99,116, -105,111,110, 58, 0, 2, 0, 0, 0, 9, 99,115,101,116,110, 97,109,101, 0, 2, - 0, 0, 0, 11,116,111,108,117, 97, 73, 95,115,101,116, 0, 2, 0, 0, 0, 5, -110, 97,114,103, 0, 2, 0, 0, 0, 8, 32, 32,105,102, 32, 40, 33, 0, 2, 0, - 0, 0, 13,111,117,116, 99,104,101, 99,107,116,121,112,101, 0, 2, 0, 0, 0, - 2, 41, 0, 2, 0, 0, 0, 58, 32, 32, 32,116,111,108,117, 97, 95,101,114,114, -111,114, 40, 34, 35,118,105,110,118, 97,108,105,100, 32,116,121,112,101, 32,105, -110, 32,118, 97,114,105, 97, 98,108,101, 32, 97,115,115,105,103,110,109,101,110, -116, 46, 34, 41, 59, 0, 2, 0, 0, 0, 3, 58, 58, 0, 2, 0, 0, 0, 7,115, -101,108,102, 45, 62, 0, 2, 0, 0, 0, 4, 32, 61, 32, 0, 2, 0, 0, 0, 3, - 40, 40, 0, 2, 0, 0, 0, 3, 41, 32, 0, 2, 0, 0, 0, 4,100,101,102, 0, - 2, 0, 0, 0, 10,116,111,108,117, 97, 95,103,101,116, 0, 2, 0, 0, 0, 4, - 41, 41, 59, 0, 2, 0, 0, 0, 19,116,111,108,117, 97, 95,103,101,116,117,115, -101,114,116,121,112,101, 40, 0, 2, 0, 0, 0, 9,114,101,103,105,115,116,101, -114, 0, 4, 0, 0, 0,154, 0, 0, 0, 14, 64,118, 97,114,105, 97, 98,108,101, - 46,108,117, 97, 0, 0, 0, 0,185, 5, 1, 60,155, 13, 0, 20, 2, 2, 1, 1, - 46, 7, 13, 0, 20, 3, 2, 1, 1, 60,156, 13, 1, 52, 84, 60,157, 13, 0, 18, - 4, 52, 41, 60,158, 15, 5, 11, 6, 13, 1, 42, 11, 7, 42, 13, 0, 18, 8, 42, - 11, 9, 42, 13, 0, 18, 10, 42, 11, 11, 42, 13, 0, 18, 4, 42, 11, 12, 42, 2, - 0, 1, 50, 33, 60,160, 15, 5, 11, 6, 13, 1, 42, 11, 7, 42, 13, 0, 18, 8, - 42, 11, 9, 42, 13, 0, 18, 10, 42, 11, 13, 42, 2, 0, 1, 60,161, 50, 72, 60, -163, 13, 0, 18, 4, 52, 35, 60,164, 15, 5, 11, 14, 13, 0, 18, 8, 42, 11, 9, - 42, 13, 0, 18, 10, 42, 11, 11, 42, 13, 0, 18, 4, 42, 11, 12, 42, 2, 0, 1, - 50, 27, 60,166, 15, 5, 11, 14, 13, 0, 18, 8, 42, 11, 9, 42, 13, 0, 18, 10, - 42, 11, 13, 42, 2, 0, 1, 60,167, 60,168, 60,169, 0, 0, 0, 0, 2, 0, 0, - 0,154, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0,155, 0, 0, 0, 7,112, - 97,114,101,110,116, 0, 0, 0, 0, 15, 2, 0, 0, 0, 7,112, 97,114,101,110, -116, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 8,105,110, 99, -108, 97,115,115, 0, 2, 0, 0, 0, 9,105,110,109,111,100,117,108,101, 0, 2, - 0, 0, 0, 9, 99,115,101,116,110, 97,109,101, 0, 2, 0, 0, 0, 7,111,117, -116,112,117,116, 0, 2, 0, 0, 0, 18, 32,116,111,108,117, 97, 95,116, 97, 98, -108,101,118, 97,114, 40, 34, 0, 2, 0, 0, 0, 4, 34, 44, 34, 0, 2, 0, 0, - 0, 6,108,110, 97,109,101, 0, 2, 0, 0, 0, 3, 34, 44, 0, 2, 0, 0, 0, - 9, 99,103,101,116,110, 97,109,101, 0, 2, 0, 0, 0, 2, 44, 0, 2, 0, 0, - 0, 3, 41, 59, 0, 2, 0, 0, 0, 8, 44, 78, 85, 76, 76, 41, 59, 0, 2, 0, - 0, 0, 19, 32,116,111,108,117, 97, 95,103,108,111, 98, 97,108,118, 97,114, 40, - 34, 0, 2, 0, 0, 0, 11,117,110,114,101,103,105,115,116,101,114, 0, 4, 0, - 0, 0,171, 0, 0, 0, 14, 64,118, 97,114,105, 97, 98,108,101, 46,108,117, 97, - 0, 0, 0, 0, 52, 4, 1, 60,172, 13, 0, 20, 1, 2, 1, 1, 4, 0, 32, 48, - 10, 13, 0, 20, 2, 2, 1, 1, 4, 0, 32, 52, 19, 60,173, 15, 3, 11, 4, 13, - 0, 18, 5, 42, 11, 6, 42, 2, 0, 1, 50, 2, 60,174, 60,175, 0, 0, 0, 0, - 1, 0, 0, 0,171, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 7, 2, 0, - 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 8,105,110, 99,108, 97,115,115, - 0, 2, 0, 0, 0, 9,105,110,109,111,100,117,108,101, 0, 2, 0, 0, 0, 7, -111,117,116,112,117,116, 0, 2, 0, 0, 0, 35, 32,108,117, 97, 95,112,117,115, -104,110,105,108, 40, 41, 59, 32,108,117, 97, 95,114, 97,119,115,101,116,103,108, -111, 98, 97,108, 40, 34, 0, 2, 0, 0, 0, 6,108,110, 97,109,101, 0, 2, 0, - 0, 0, 4, 34, 41, 59, 0, 2, 0, 0, 0, 10, 95, 86, 97,114,105, 97, 98,108, -101, 0, 4, 0, 0, 0,179, 0, 0, 0, 14, 64,118, 97,114,105, 97, 98,108,101, - 46,108,117, 97, 0, 0, 0, 0, 40, 4, 1, 60,180, 13, 0, 11, 1, 15, 2, 26, - 60,181, 15, 3, 13, 0, 15, 4, 2, 0, 2, 60,182, 15, 5, 13, 0, 2, 0, 1, - 60,183, 13, 0, 1, 1, 60,184, 0, 0, 0, 0, 1, 0, 0, 0,179, 0, 0, 0, - 2,116, 0, 0, 0, 0, 6, 2, 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 6, 95, - 98, 97,115,101, 0, 2, 0, 0, 0, 14, 99,108, 97,115,115, 86, 97,114,105, 97, - 98,108,101, 0, 2, 0, 0, 0, 7,115,101,116,116, 97,103, 0, 2, 0, 0, 0, - 10,116,111,108,117, 97, 95,116, 97,103, 0, 2, 0, 0, 0, 7, 97,112,112,101, -110,100, 0, 2, 0, 0, 0, 9, 86, 97,114,105, 97, 98,108,101, 0, 4, 0, 0, - 0,188, 0, 0, 0, 14, 64,118, 97,114,105, 97, 98,108,101, 46,108,117, 97, 0, - 0, 0, 0, 21, 5, 1, 60,189, 15, 1, 15, 2, 13, 0, 11, 3, 2, 1, 2, 3, - 1, 1, 60,190, 0, 0, 0, 0, 1, 0, 0, 0,188, 0, 0, 0, 2,115, 0, 0, - 0, 0, 4, 2, 0, 0, 0, 2,115, 0, 2, 0, 0, 0, 10, 95, 86, 97,114,105, - 97, 98,108,101, 0, 2, 0, 0, 0, 12, 68,101, 99,108, 97,114, 97,116,105,111, -110, 0, 2, 0, 0, 0, 4,118, 97,114, 0, -}; - -/* array.lo */ -static char B12[]={ - 27, 76,117, 97, 50, 0, 0, 0, 0, 0, 0, 0, 0, 11, 64, 97,114,114, 97,121, - 46,108,117, 97, 0, 0, 0, 0, 87, 3, 0, 60, 18, 22, 1, 60, 19, 11, 1, 15, - 2, 30, 0, 60, 20, 25, 0, 60, 22, 15, 3, 15, 0, 15, 4, 2, 0, 2, 60, 25, - 15, 0, 11, 5, 11, 6, 26, 60, 38, 15, 0, 11, 7, 11, 8, 26, 60, 49, 15, 0, - 11, 9, 11, 10, 26, 60,167, 15, 0, 11, 11, 11, 12, 26, 60,184, 15, 0, 11, 13, - 11, 14, 26, 60,192, 11, 16, 25, 15, 60,201, 11, 18, 25, 17, 0, 0, 0, 0, 0, - 0, 0, 0, 19, 2, 0, 0, 0, 11, 99,108, 97,115,115, 65,114,114, 97,121, 0, - 2, 0, 0, 0, 6, 95, 98, 97,115,101, 0, 2, 0, 0, 0, 17, 99,108, 97,115, -115, 68,101, 99,108, 97,114, 97,116,105,111,110, 0, 2, 0, 0, 0, 7,115,101, -116,116, 97,103, 0, 2, 0, 0, 0, 10,116,111,108,117, 97, 95,116, 97,103, 0, - 2, 0, 0, 0, 6,112,114,105,110,116, 0, 4, 0, 0, 0, 25, 0, 0, 0, 11, - 64, 97,114,114, 97,121, 46,108,117, 97, 0, 0, 0, 0,172, 6, 3, 60, 26, 15, - 2, 13, 1, 11, 3, 42, 2, 0, 1, 60, 27, 15, 2, 13, 1, 11, 4, 42, 13, 0, - 18, 6, 42, 11, 7, 42, 2, 0, 1, 60, 28, 15, 2, 13, 1, 11, 8, 42, 13, 0, - 18, 9, 42, 11, 7, 42, 2, 0, 1, 60, 29, 15, 2, 13, 1, 11, 10, 42, 13, 0, - 18, 11, 42, 11, 7, 42, 2, 0, 1, 60, 30, 15, 2, 13, 1, 11, 12, 42, 13, 0, - 18, 13, 42, 11, 7, 42, 2, 0, 1, 60, 31, 15, 2, 13, 1, 11, 14, 42, 13, 0, - 18, 15, 42, 11, 7, 42, 2, 0, 1, 60, 32, 15, 2, 13, 1, 11, 16, 42, 13, 0, - 18, 17, 42, 11, 7, 42, 2, 0, 1, 60, 33, 15, 2, 13, 1, 11, 18, 42, 13, 0, - 18, 19, 42, 11, 7, 42, 2, 0, 1, 60, 34, 15, 2, 13, 1, 11, 20, 42, 13, 2, - 42, 2, 0, 1, 60, 35, 0, 0, 0, 0, 3, 0, 0, 0, 25, 0, 0, 0, 5,115, -101,108,102, 0, 0, 0, 0, 25, 0, 0, 0, 6,105,100,101,110,116, 0, 0, 0, - 0, 25, 0, 0, 0, 6, 99,108,111,115,101, 0, 0, 0, 0, 21, 2, 0, 0, 0, - 6,105,100,101,110,116, 0, 2, 0, 0, 0, 6, 99,108,111,115,101, 0, 2, 0, - 0, 0, 6,112,114,105,110,116, 0, 2, 0, 0, 0, 7, 65,114,114, 97,121,123, - 0, 2, 0, 0, 0, 10, 32,109,111,100, 32, 32, 61, 32, 39, 0, 2, 0, 0, 0, - 5,115,101,108,102, 0, 2, 0, 0, 0, 4,109,111,100, 0, 2, 0, 0, 0, 3, - 39, 44, 0, 2, 0, 0, 0, 10, 32,116,121,112,101, 32, 61, 32, 39, 0, 2, 0, - 0, 0, 5,116,121,112,101, 0, 2, 0, 0, 0, 10, 32,112,116,114, 32, 32, 61, - 32, 39, 0, 2, 0, 0, 0, 4,112,116,114, 0, 2, 0, 0, 0, 10, 32,110, 97, -109,101, 32, 61, 32, 39, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, - 0, 10, 32,100,101,102, 32, 32, 61, 32, 39, 0, 2, 0, 0, 0, 4,100,101,102, - 0, 2, 0, 0, 0, 10, 32,100,105,109, 32, 32, 61, 32, 39, 0, 2, 0, 0, 0, - 4,100,105,109, 0, 2, 0, 0, 0, 10, 32,114,101,116, 32, 32, 61, 32, 39, 0, - 2, 0, 0, 0, 4,114,101,116, 0, 2, 0, 0, 0, 2,125, 0, 2, 0, 0, 0, - 9,103,101,116,118, 97,108,117,101, 0, 4, 0, 0, 0, 38, 0, 0, 0, 11, 64, - 97,114,114, 97,121, 46,108,117, 97, 0, 0, 0, 0, 69, 5, 3, 60, 39, 13, 1, - 48, 2, 13, 2, 52, 19, 60, 40, 13, 1, 11, 2, 42, 13, 0, 18, 4, 42, 11, 5, - 42, 1, 3, 50, 35, 60, 41, 13, 1, 52, 16, 60, 42, 11, 6, 13, 0, 18, 4, 42, - 11, 5, 42, 1, 3, 50, 13, 60, 44, 13, 0, 18, 4, 11, 5, 42, 1, 3, 60, 45, - 60, 46, 0, 0, 0, 0, 3, 0, 0, 0, 38, 0, 0, 0, 5,115,101,108,102, 0, - 0, 0, 0, 38, 0, 0, 0, 6, 99,108, 97,115,115, 0, 0, 0, 0, 38, 0, 0, - 0, 7,115,116, 97,116,105, 99, 0, 0, 0, 0, 7, 2, 0, 0, 0, 6, 99,108, - 97,115,115, 0, 2, 0, 0, 0, 7,115,116, 97,116,105, 99, 0, 2, 0, 0, 0, - 3, 58, 58, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 5,110, - 97,109,101, 0, 2, 0, 0, 0, 15, 91,116,111,108,117, 97, 73, 95,105,110,100, -101,120, 93, 0, 2, 0, 0, 0, 7,115,101,108,102, 45, 62, 0, 2, 0, 0, 0, - 8,115,117,112, 99,111,100,101, 0, 4, 0, 0, 0, 49, 0, 0, 0, 11, 64, 97, -114,114, 97,121, 46,108,117, 97, 0, 0, 0, 4, 21, 17, 1, 60, 50, 13, 0, 20, - 2, 2, 1, 1, 60, 53, 13, 1, 52, 21, 60, 54, 15, 3, 11, 4, 13, 0, 18, 5, - 11, 6, 13, 1, 11, 7, 2, 0, 5, 50, 17, 60, 56, 15, 3, 11, 4, 13, 0, 18, - 5, 11, 7, 2, 0, 3, 60, 57, 60, 58, 13, 0, 11, 8, 13, 0, 20, 9, 11, 10, - 2, 1, 2, 26, 60, 59, 15, 3, 11, 11, 13, 0, 18, 8, 11, 12, 2, 0, 3, 60, - 60, 15, 3, 11, 13, 2, 0, 1, 60, 63, 15, 3, 11, 14, 2, 0, 1, 60, 66, 15, - 17, 13, 0, 18, 18, 11, 19, 2, 3, 2, 60, 67, 13, 1, 48, 5, 13, 4, 4, 0, - 32, 52, 66, 60, 68, 15, 3, 11, 20, 13, 1, 11, 21, 11, 22, 2, 0, 4, 60, 69, - 15, 3, 11, 23, 2, 0, 1, 60, 70, 15, 3, 11, 24, 2, 0, 1, 60, 71, 15, 3, - 11, 25, 2, 0, 1, 60, 72, 15, 3, 11, 26, 13, 1, 11, 27, 2, 0, 3, 60, 73, - 15, 3, 11, 28, 2, 0, 1, 50, 35, 60, 74, 13, 4, 52, 27, 60, 75, 13, 0, 11, - 18, 15, 17, 13, 0, 18, 18, 11, 29, 2, 3, 2, 27, 2, 23, 3, 23, 3, 5, 2, - 50, 2, 60, 76, 60, 79, 15, 3, 11, 30, 2, 0, 1, 60, 80, 15, 3, 11, 31, 2, - 0, 1, 60, 81, 15, 3, 11, 32, 2, 0, 1, 60, 82, 15, 3, 11, 33, 13, 0, 18, - 34, 42, 11, 35, 42, 2, 0, 1, 60, 83, 15, 3, 11, 36, 2, 0, 1, 60, 86, 15, - 38, 13, 0, 18, 39, 2, 1, 1, 60, 87, 13, 5, 11, 40, 32, 52, 32, 60, 88, 15, - 3, 11, 41, 13, 5, 42, 11, 42, 42, 13, 0, 20, 43, 13, 1, 13, 4, 2, 1, 3, - 42, 11, 44, 42, 2, 0, 1, 50,124, 60, 89, 13, 5, 52, 32, 60, 90, 15, 3, 11, - 41, 13, 5, 42, 11, 26, 42, 13, 0, 20, 43, 13, 1, 13, 4, 2, 1, 3, 42, 11, - 44, 42, 2, 0, 1, 50, 86, 60, 92, 13, 0, 18, 45, 11, 46, 32, 46, 7, 13, 0, - 18, 45, 11, 47, 32, 52, 32, 60, 93, 15, 3, 11, 48, 13, 0, 20, 43, 13, 1, 13, - 4, 2, 1, 3, 42, 11, 49, 42, 13, 0, 18, 50, 11, 44, 2, 0, 3, 50, 32, 60, - 95, 15, 3, 11, 51, 13, 0, 20, 43, 13, 1, 13, 4, 2, 1, 3, 42, 11, 49, 42, - 13, 0, 18, 50, 11, 44, 2, 0, 3, 60, 96, 60, 97, 60, 98, 15, 3, 11, 52, 2, - 0, 1, 60, 99, 15, 3, 11, 53, 2, 0, 1, 60,102, 15, 17, 13, 0, 18, 18, 11, - 54, 2, 1, 2, 44, 51, 2, 33, 60,103, 13, 1, 52, 21, 60,104, 15, 3, 11, 55, - 13, 0, 18, 5, 11, 6, 13, 1, 11, 7, 2, 0, 5, 50, 17, 60,106, 15, 3, 11, - 55, 13, 0, 18, 5, 11, 7, 2, 0, 3, 60,107, 60,108, 13, 0, 11, 56, 13, 0, - 20, 9, 11, 57, 2, 1, 2, 26, 60,109, 15, 3, 11, 11, 13, 0, 18, 56, 11, 12, - 2, 0, 3, 60,110, 15, 3, 11, 13, 2, 0, 1, 60,113, 15, 3, 11, 14, 2, 0, - 1, 60,116, 15, 17, 13, 0, 18, 18, 11, 19, 2, 3, 2, 60,117, 13, 1, 48, 5, - 13, 8, 4, 0, 32, 52, 66, 60,118, 15, 3, 11, 20, 13, 1, 11, 21, 11, 22, 2, - 0, 4, 60,119, 15, 3, 11, 23, 2, 0, 1, 60,120, 15, 3, 11, 24, 2, 0, 1, - 60,121, 15, 3, 11, 25, 2, 0, 1, 60,122, 15, 3, 11, 26, 13, 1, 11, 27, 2, - 0, 3, 60,123, 15, 3, 11, 28, 2, 0, 1, 50, 35, 60,124, 13, 8, 52, 27, 60, -125, 13, 0, 11, 18, 15, 17, 13, 0, 18, 18, 11, 29, 2, 3, 2, 27, 2, 23, 7, - 23, 7, 5, 2, 50, 2, 60,126, 60,129, 15, 3, 11, 30, 2, 0, 1, 60,130, 15, - 3, 11, 31, 2, 0, 1, 60,131, 15, 3, 11, 32, 2, 0, 1, 60,132, 15, 3, 11, - 33, 13, 0, 18, 34, 42, 11, 35, 42, 2, 0, 1, 60,133, 15, 3, 11, 36, 2, 0, - 1, 60,136, 11, 47, 60,137, 13, 0, 18, 45, 11, 47, 31, 52, 4, 11, 21, 23, 9, - 60,138, 15, 3, 11, 20, 2, 0, 1, 60,139, 13, 1, 48, 2, 13, 8, 52, 22, 60, -140, 15, 3, 13, 1, 11, 58, 42, 13, 0, 18, 5, 42, 11, 59, 42, 2, 0, 1, 50, - 41, 60,141, 13, 1, 52, 19, 60,142, 15, 3, 11, 60, 13, 0, 18, 5, 42, 11, 59, - 42, 2, 0, 1, 50, 16, 60,144, 15, 3, 13, 0, 18, 5, 11, 59, 42, 2, 0, 1, - 60,145, 60,146, 15, 38, 13, 0, 18, 39, 2, 1, 1, 60,147, 15, 3, 11, 61, 2, - 0, 1, 60,148, 13, 10, 44, 48, 5, 13, 9, 11, 47, 32, 52, 7, 15, 3, 11, 21, - 2, 0, 1, 60,149, 15, 3, 11, 62, 13, 0, 18, 18, 13, 0, 18, 39, 2, 0, 3, - 60,150, 13, 10, 44, 52, 11, 60,151, 15, 3, 11, 21, 2, 0, 1, 50, 2, 60,152, - 60,153, 15, 3, 11, 63, 2, 0, 1, 60,154, 7, 0, 60,155, 13, 0, 18, 64, 11, - 47, 31, 52, 6, 13, 0, 18, 64, 23, 11, 60,156, 13, 10, 52, 20, 60,157, 15, 3, - 11, 65, 13, 10, 42, 11, 66, 13, 11, 11, 67, 2, 0, 4, 50, 15, 60,159, 15, 3, - 11, 68, 13, 11, 11, 67, 2, 0, 3, 60,160, 60,161, 15, 3, 11, 52, 2, 0, 1, - 60,162, 15, 3, 11, 53, 2, 0, 1, 5, 6, 50, 2, 60,163, 60,165, 0, 0, 0, - 0, 18, 0, 0, 0, 49, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 50, 0, - 0, 0, 6, 99,108, 97,115,115, 0, 0, 0, 0, 66, 0, 0, 0, 2, 95, 0, 0, - 0, 0, 66, 0, 0, 0, 2, 95, 0, 0, 0, 0, 66, 0, 0, 0, 7,115,116, 97, -116,105, 99, 0, 0, 0, 0, 86, 0, 0, 0, 2,116, 0, 0, 0, 0,116, 0, 0, - 0, 2, 95, 0, 0, 0, 0,116, 0, 0, 0, 2, 95, 0, 0, 0, 0,116, 0, 0, - 0, 7,115,116, 97,116,105, 99, 0, 0, 0, 0,136, 0, 0, 0, 4,112,116,114, - 0, 0, 0, 0,146, 0, 0, 0, 2,116, 0, 0, 0, 0,154, 0, 0, 0, 4,100, -101,102, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, - 0, 0,162, 0, 0, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0,162, 0, - 0, 0, 0, 0, 0, 0,162, 0, 0, 0, 0, 0, 0, 0, 69, 2, 0, 0, 0, 6, - 99,108, 97,115,115, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, - 8,105,110, 99,108, 97,115,115, 0, 2, 0, 0, 0, 7,111,117,116,112,117,116, - 0, 2, 0, 0, 0, 17, 47, 42, 32,103,101,116, 32,102,117,110, 99,116,105,111, -110, 58, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 11, 32,111, -102, 32, 99,108, 97,115,115, 32, 0, 2, 0, 0, 0, 4, 32, 42, 47, 0, 2, 0, - 0, 0, 9, 99,103,101,116,110, 97,109,101, 0, 2, 0, 0, 0, 10, 99,102,117, -110, 99,110, 97,109,101, 0, 2, 0, 0, 0, 11,116,111,108,117, 97, 73, 95,103, -101,116, 0, 2, 0, 0, 0, 12,115,116, 97,116,105, 99, 32,118,111,105,100, 0, - 2, 0, 0, 0, 7, 40,118,111,105,100, 41, 0, 2, 0, 0, 0, 2,123, 0, 2, - 0, 0, 0, 19, 32,105,110,116, 32,116,111,108,117, 97, 73, 95,105,110,100,101, -120, 59, 0, 2, 0, 0, 0, 2, 95, 0, 2, 0, 0, 0, 7,115,116, 97,116,105, - 99, 0, 2, 0, 0, 0, 8,115,116,114,102,105,110,100, 0, 2, 0, 0, 0, 4, -109,111,100, 0, 2, 0, 0, 0, 13, 94, 37,115, 42, 40,115,116, 97,116,105, 99, - 41, 0, 2, 0, 0, 0, 2, 32, 0, 2, 0, 0, 0, 2, 42, 0, 2, 0, 0, 0, - 6,115,101,108,102, 59, 0, 2, 0, 0, 0, 34, 32,108,117, 97, 95,112,117,115, -104,111, 98,106,101, 99,116, 40,108,117, 97, 95,103,101,116,112, 97,114, 97,109, - 40, 49, 41, 41, 59, 0, 2, 0, 0, 0, 26, 32,108,117, 97, 95,112,117,115,104, -115,116,114,105,110,103, 40, 34, 46,115,101,108,102, 34, 41, 59, 0, 2, 0, 0, - 0, 9, 32,115,101,108,102, 32, 61, 32, 0, 2, 0, 0, 0, 2, 40, 0, 2, 0, - 0, 0, 4, 42, 41, 32, 0, 2, 0, 0, 0, 36,108,117, 97, 95,103,101,116,117, -115,101,114,100, 97,116, 97, 40,108,117, 97, 95,114, 97,119,103,101,116,116, 97, - 98,108,101, 40, 41, 41, 59, 0, 2, 0, 0, 0, 20, 94, 37,115, 42,115,116, 97, -116,105, 99, 37,115, 37,115, 42, 40, 46, 42, 41, 0, 2, 0, 0, 0, 42, 32,105, -102, 32, 40, 33,116,111,108,117, 97, 95,105,115,116,121,112,101, 40, 50, 44,116, -111,108,117, 97, 95,116, 97,103, 95,110,117,109, 98,101,114, 44, 48, 41, 41, 0, - 2, 0, 0, 0, 50, 32, 32,116,111,108,117, 97, 95,101,114,114,111,114, 40, 34, -105,110,118, 97,108,105,100, 32,116,121,112,101, 32,105,110, 32, 97,114,114, 97, -121, 32,105,110,100,101,120,105,110,103, 46, 34, 41, 59, 0, 2, 0, 0, 0, 45, - 32,116,111,108,117, 97, 73, 95,105,110,100,101,120, 32, 61, 32, 40,105,110,116, - 41,116,111,108,117, 97, 95,103,101,116,110,117,109, 98,101,114, 40, 50, 44, 48, - 41, 45, 49, 59, 0, 2, 0, 0, 0, 38, 32,105,102, 32, 40,116,111,108,117, 97, - 73, 95,105,110,100,101,120, 60, 48, 32,124,124, 32,116,111,108,117, 97, 73, 95, -105,110,100,101,120, 62, 61, 0, 2, 0, 0, 0, 4,100,105,109, 0, 2, 0, 0, - 0, 2, 41, 0, 2, 0, 0, 0, 47, 32, 32,116,111,108,117, 97, 95,101,114,114, -111,114, 40, 34, 97,114,114, 97,121, 32,105,110,100,101,120,105,110,103, 32,111, -117,116, 32,111,102, 32,114, 97,110,103,101, 46, 34, 41, 59, 0, 2, 0, 0, 0, - 2,116, 0, 2, 0, 0, 0, 8,105,115, 98, 97,115,105, 99, 0, 2, 0, 0, 0, - 5,116,121,112,101, 0, 2, 0, 0, 0, 7,110,117,109, 98,101,114, 0, 2, 0, - 0, 0, 13, 32, 32,116,111,108,117, 97, 95,112,117,115,104, 0, 2, 0, 0, 0, - 10, 40, 40,100,111,117, 98,108,101, 41, 0, 2, 0, 0, 0, 9,103,101,116,118, - 97,108,117,101, 0, 2, 0, 0, 0, 3, 41, 59, 0, 2, 0, 0, 0, 4,112,116, -114, 0, 2, 0, 0, 0, 2, 38, 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 30, - 32, 32,116,111,108,117, 97, 95,112,117,115,104,117,115,101,114,116,121,112,101, - 40, 40,118,111,105,100, 42, 41, 38, 0, 2, 0, 0, 0, 2, 44, 0, 2, 0, 0, - 0, 4,116, 97,103, 0, 2, 0, 0, 0, 29, 32, 32,116,111,108,117, 97, 95,112, -117,115,104,117,115,101,114,116,121,112,101, 40, 40,118,111,105,100, 42, 41, 0, - 2, 0, 0, 0, 2,125, 0, 2, 0, 0, 0, 2, 10, 0, 2, 0, 0, 0, 6, 99, -111,110,115,116, 0, 2, 0, 0, 0, 17, 47, 42, 32,115,101,116, 32,102,117,110, - 99,116,105,111,110, 58, 0, 2, 0, 0, 0, 9, 99,115,101,116,110, 97,109,101, - 0, 2, 0, 0, 0, 11,116,111,108,117, 97, 73, 95,115,101,116, 0, 2, 0, 0, - 0, 3, 58, 58, 0, 2, 0, 0, 0, 15, 91,116,111,108,117, 97, 73, 95,105,110, -100,101,120, 93, 0, 2, 0, 0, 0, 7,115,101,108,102, 45, 62, 0, 2, 0, 0, - 0, 4, 32, 61, 32, 0, 2, 0, 0, 0, 3, 40, 40, 0, 2, 0, 0, 0, 3, 41, - 32, 0, 2, 0, 0, 0, 4,100,101,102, 0, 2, 0, 0, 0, 10,116,111,108,117, - 97, 95,103,101,116, 0, 2, 0, 0, 0, 4, 40, 51, 44, 0, 2, 0, 0, 0, 4, - 41, 41, 59, 0, 2, 0, 0, 0, 21,116,111,108,117, 97, 95,103,101,116,117,115, -101,114,116,121,112,101, 40, 51, 44, 0, 2, 0, 0, 0, 9,114,101,103,105,115, -116,101,114, 0, 4, 0, 0, 0,167, 0, 0, 0, 11, 64, 97,114,114, 97,121, 46, -108,117, 97, 0, 0, 0, 0,185, 5, 1, 60,168, 13, 0, 20, 2, 2, 1, 1, 46, - 7, 13, 0, 20, 3, 2, 1, 1, 60,169, 13, 1, 52, 84, 60,170, 13, 0, 18, 4, - 52, 41, 60,171, 15, 5, 11, 6, 13, 1, 42, 11, 7, 42, 13, 0, 18, 8, 42, 11, - 9, 42, 13, 0, 18, 10, 42, 11, 11, 42, 13, 0, 18, 4, 42, 11, 12, 42, 2, 0, - 1, 50, 33, 60,173, 15, 5, 11, 6, 13, 1, 42, 11, 7, 42, 13, 0, 18, 8, 42, - 11, 9, 42, 13, 0, 18, 10, 42, 11, 13, 42, 2, 0, 1, 60,174, 50, 72, 60,176, - 13, 0, 18, 4, 52, 35, 60,177, 15, 5, 11, 14, 13, 0, 18, 8, 42, 11, 9, 42, - 13, 0, 18, 10, 42, 11, 11, 42, 13, 0, 18, 4, 42, 11, 12, 42, 2, 0, 1, 50, - 27, 60,179, 15, 5, 11, 14, 13, 0, 18, 8, 42, 11, 9, 42, 13, 0, 18, 10, 42, - 11, 13, 42, 2, 0, 1, 60,180, 60,181, 60,182, 0, 0, 0, 0, 2, 0, 0, 0, -167, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0,168, 0, 0, 0, 7,112, 97, -114,101,110,116, 0, 0, 0, 0, 15, 2, 0, 0, 0, 7,112, 97,114,101,110,116, - 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 8,105,110, 99,108, - 97,115,115, 0, 2, 0, 0, 0, 9,105,110,109,111,100,117,108,101, 0, 2, 0, - 0, 0, 9, 99,115,101,116,110, 97,109,101, 0, 2, 0, 0, 0, 7,111,117,116, -112,117,116, 0, 2, 0, 0, 0, 20, 32,116,111,108,117, 97, 95,116, 97, 98,108, -101, 97,114,114, 97,121, 40, 34, 0, 2, 0, 0, 0, 4, 34, 44, 34, 0, 2, 0, - 0, 0, 6,108,110, 97,109,101, 0, 2, 0, 0, 0, 3, 34, 44, 0, 2, 0, 0, - 0, 9, 99,103,101,116,110, 97,109,101, 0, 2, 0, 0, 0, 2, 44, 0, 2, 0, - 0, 0, 3, 41, 59, 0, 2, 0, 0, 0, 8, 44, 78, 85, 76, 76, 41, 59, 0, 2, - 0, 0, 0, 21, 32,116,111,108,117, 97, 95,103,108,111, 98, 97,108, 97,114,114, - 97,121, 40, 34, 0, 2, 0, 0, 0, 11,117,110,114,101,103,105,115,116,101,114, - 0, 4, 0, 0, 0,184, 0, 0, 0, 11, 64, 97,114,114, 97,121, 46,108,117, 97, - 0, 0, 0, 0, 52, 4, 1, 60,185, 13, 0, 20, 1, 2, 1, 1, 4, 0, 32, 48, - 10, 13, 0, 20, 2, 2, 1, 1, 4, 0, 32, 52, 19, 60,186, 15, 3, 11, 4, 13, - 0, 18, 5, 42, 11, 6, 42, 2, 0, 1, 50, 2, 60,187, 60,188, 0, 0, 0, 0, - 1, 0, 0, 0,184, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 7, 2, 0, - 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 8,105,110, 99,108, 97,115,115, - 0, 2, 0, 0, 0, 9,105,110,109,111,100,117,108,101, 0, 2, 0, 0, 0, 7, -111,117,116,112,117,116, 0, 2, 0, 0, 0, 32, 32,108,117, 97, 95,112,117,115, -104,110,105,108, 40, 41, 59, 32,108,117, 97, 95,115,101,116,103,108,111, 98, 97, -108, 40, 34, 0, 2, 0, 0, 0, 6,108,110, 97,109,101, 0, 2, 0, 0, 0, 4, - 34, 41, 59, 0, 2, 0, 0, 0, 7, 95, 65,114,114, 97,121, 0, 4, 0, 0, 0, -192, 0, 0, 0, 11, 64, 97,114,114, 97,121, 46,108,117, 97, 0, 0, 0, 0, 40, - 4, 1, 60,193, 13, 0, 11, 1, 15, 2, 26, 60,194, 15, 3, 13, 0, 15, 4, 2, - 0, 2, 60,195, 15, 5, 13, 0, 2, 0, 1, 60,196, 13, 0, 1, 1, 60,197, 0, - 0, 0, 0, 1, 0, 0, 0,192, 0, 0, 0, 2,116, 0, 0, 0, 0, 6, 2, 0, - 0, 0, 2,116, 0, 2, 0, 0, 0, 6, 95, 98, 97,115,101, 0, 2, 0, 0, 0, - 11, 99,108, 97,115,115, 65,114,114, 97,121, 0, 2, 0, 0, 0, 7,115,101,116, -116, 97,103, 0, 2, 0, 0, 0, 10,116,111,108,117, 97, 95,116, 97,103, 0, 2, - 0, 0, 0, 7, 97,112,112,101,110,100, 0, 2, 0, 0, 0, 6, 65,114,114, 97, -121, 0, 4, 0, 0, 0,201, 0, 0, 0, 11, 64, 97,114,114, 97,121, 46,108,117, - 97, 0, 0, 0, 0, 21, 5, 1, 60,202, 15, 1, 15, 2, 13, 0, 11, 3, 2, 1, - 2, 3, 1, 1, 60,203, 0, 0, 0, 0, 1, 0, 0, 0,201, 0, 0, 0, 2,115, - 0, 0, 0, 0, 4, 2, 0, 0, 0, 2,115, 0, 2, 0, 0, 0, 7, 95, 65,114, -114, 97,121, 0, 2, 0, 0, 0, 12, 68,101, 99,108, 97,114, 97,116,105,111,110, - 0, 2, 0, 0, 0, 4,118, 97,114, 0, -}; - -/* function.lo */ -static char B13[]={ - 27, 76,117, 97, 50, 0, 0, 0, 0, 0, 0, 0, 0, 14, 64,102,117,110, 99,116, -105,111,110, 46,108,117, 97, 0, 0, 0, 0,141, 15, 0, 60, 24, 22, 7, 60, 25, - 11, 1, 11, 2, 11, 3, 60, 26, 11, 2, 11, 4, 60, 27, 11, 2, 11, 5, 60, 28, - 11, 2, 11, 6, 60, 29, 22, 1, 11, 7, 7, 0, 30, 0, 11, 8, 60, 30, 11, 2, - 11, 9, 60, 31, 15, 10, 30, 6, 60, 32, 25, 0, 60, 33, 15, 11, 15, 0, 15, 12, - 2, 0, 2, 60, 36, 15, 0, 11, 13, 11, 14, 26, 60, 51, 15, 0, 11, 15, 11, 16, - 26, 60,232, 15, 0, 11, 17, 11, 18, 26, 60,242, 15, 0, 11, 19, 11, 20, 26, 60, -250, 15, 0, 11, 21, 11, 22, 26, 59, 1, 14, 15, 0, 11, 23, 11, 24, 26, 59, 1, - 21, 11, 26, 25, 25, 59, 1, 49, 11, 28, 25, 27, 0, 0, 0, 0, 0, 0, 0, 0, - 29, 2, 0, 0, 0, 14, 99,108, 97,115,115, 70,117,110, 99,116,105,111,110, 0, - 2, 0, 0, 0, 4,109,111,100, 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 5, -116,121,112,101, 0, 2, 0, 0, 0, 4,112,116,114, 0, 2, 0, 0, 0, 5,110, - 97,109,101, 0, 2, 0, 0, 0, 5, 97,114,103,115, 0, 2, 0, 0, 0, 2,110, - 0, 2, 0, 0, 0, 6, 99,111,110,115,116, 0, 2, 0, 0, 0, 6, 95, 98, 97, -115,101, 0, 2, 0, 0, 0, 13, 99,108, 97,115,115, 70,101, 97,116,117,114,101, - 0, 2, 0, 0, 0, 7,115,101,116,116, 97,103, 0, 2, 0, 0, 0, 10,116,111, -108,117, 97, 95,116, 97,103, 0, 2, 0, 0, 0, 8,100,101, 99,108,116, 97,103, - 0, 4, 0, 0, 0, 36, 0, 0, 0, 14, 64,102,117,110, 99,116,105,111,110, 46, -108,117, 97, 0, 0, 0, 0,141, 10, 1, 60, 37, 13, 0, 20, 1, 2, 1, 1, 48, - 7, 13, 0, 18, 2, 11, 2, 32, 52, 21, 60, 38, 15, 3, 13, 0, 18, 4, 18, 5, - 13, 0, 18, 4, 18, 6, 2, 0, 2, 50, 2, 60, 39, 60, 40, 13, 0, 11, 7, 13, - 0, 11, 8, 15, 9, 13, 0, 18, 10, 15, 11, 13, 0, 18, 12, 11, 2, 2, 1, 2, - 2, 2, 2, 27, 1, 27, 2, 5, 4, 60, 41, 15, 3, 13, 0, 18, 7, 13, 0, 18, - 8, 2, 0, 2, 60, 42, 7, 1, 50, 25, 60, 44, 13, 0, 18, 14, 13, 1, 16, 20, - 3, 2, 0, 1, 60, 45, 13, 1, 7, 1, 37, 23, 1, 60, 46, 60, 43, 13, 0, 18, - 14, 13, 1, 16, 54, 36, 60, 47, 0, 0, 0, 0, 2, 0, 0, 0, 36, 0, 0, 0, - 5,115,101,108,102, 0, 0, 0, 0, 42, 0, 0, 0, 2,105, 0, 0, 0, 0, 15, - 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 8,105,110, 99,108, 97, -115,115, 0, 2, 0, 0, 0, 6, 99,111,110,115,116, 0, 2, 0, 0, 0, 8,100, -101, 99,108,116, 97,103, 0, 2, 0, 0, 0, 7,112, 97,114,101,110,116, 0, 2, - 0, 0, 0, 7, 99,105,116,121,112,101, 0, 2, 0, 0, 0, 5, 99,116, 97,103, - 0, 2, 0, 0, 0, 6,105,116,121,112,101, 0, 2, 0, 0, 0, 4,116, 97,103, - 0, 2, 0, 0, 0, 7,116, 97,103,118, 97,114, 0, 2, 0, 0, 0, 5,116,121, -112,101, 0, 2, 0, 0, 0, 8,115,116,114,102,105,110,100, 0, 2, 0, 0, 0, - 4,109,111,100, 0, 2, 0, 0, 0, 2,105, 0, 2, 0, 0, 0, 5, 97,114,103, -115, 0, 2, 0, 0, 0, 8,115,117,112, 99,111,100,101, 0, 4, 0, 0, 0, 51, - 0, 0, 0, 14, 64,102,117,110, 99,116,105,111,110, 46,108,117, 97, 0, 0, 0, - 6, 51, 15, 1, 60, 52, 13, 0, 20, 2, 2, 1, 1, 60, 53, 15, 5, 13, 0, 18, - 6, 11, 7, 2, 3, 2, 60, 55, 13, 1, 52, 21, 60, 56, 15, 8, 11, 9, 13, 0, - 18, 10, 11, 11, 13, 1, 11, 12, 2, 0, 5, 50, 17, 60, 58, 15, 8, 11, 13, 13, - 0, 18, 10, 11, 12, 2, 0, 3, 60, 59, 60, 60, 15, 8, 11, 14, 13, 0, 18, 15, - 11, 16, 2, 0, 3, 60, 61, 15, 8, 11, 17, 2, 0, 1, 60, 64, 15, 8, 11, 18, - 2, 0, 1, 60, 66, 4, 0, 60, 67, 13, 1, 52, 6, 7, 2, 23, 5, 50, 4, 7, - 1, 23, 5, 60, 68, 13, 1, 48, 7, 13, 0, 18, 10, 11, 20, 31, 48, 5, 13, 4, - 4, 0, 32, 52, 51, 60, 69, 13, 0, 18, 21, 11, 21, 32, 52, 19, 60, 70, 15, 8, - 11, 22, 13, 0, 18, 23, 18, 24, 11, 25, 2, 0, 3, 50, 19, 60, 72, 15, 8, 11, - 22, 13, 0, 18, 23, 18, 26, 11, 25, 2, 0, 3, 60, 73, 50, 2, 60, 74, 60, 76, - 13, 0, 18, 27, 7, 1, 16, 18, 28, 11, 29, 31, 52, 93, 60, 77, 7, 1, 50, 72, - 60, 79, 15, 31, 13, 0, 18, 27, 13, 6, 16, 18, 28, 2, 1, 1, 11, 32, 31, 52, - 29, 60, 80, 15, 8, 11, 33, 13, 0, 18, 27, 13, 6, 16, 20, 34, 13, 5, 2, 1, - 2, 42, 11, 35, 42, 2, 0, 1, 50, 2, 60, 81, 60, 82, 13, 5, 7, 1, 37, 23, - 5, 60, 83, 13, 6, 7, 1, 37, 23, 6, 60, 84, 60, 78, 13, 0, 18, 27, 13, 6, - 16, 54, 83, 5, 1, 50, 2, 60, 85, 60, 87, 15, 8, 11, 36, 13, 5, 42, 11, 37, - 42, 2, 0, 1, 60, 89, 15, 8, 11, 38, 2, 0, 1, 60, 92, 4, 0, 60, 93, 13, - 1, 52, 6, 7, 2, 23, 6, 50, 4, 7, 1, 23, 6, 60, 94, 13, 1, 48, 7, 13, - 0, 18, 10, 11, 20, 31, 48, 5, 13, 4, 4, 0, 32, 52, 47, 60, 95, 15, 8, 11, - 39, 13, 0, 18, 21, 13, 1, 11, 40, 11, 41, 2, 0, 5, 60, 96, 15, 8, 11, 42, - 13, 0, 18, 21, 13, 1, 11, 43, 2, 0, 4, 60, 97, 15, 8, 11, 44, 2, 0, 1, - 50, 35, 60, 98, 13, 4, 52, 27, 60, 99, 13, 0, 11, 6, 15, 5, 13, 0, 18, 6, - 11, 45, 2, 3, 2, 27, 2, 23, 3, 23, 3, 5, 2, 50, 2, 60,100, 60,102, 13, - 0, 18, 27, 7, 1, 16, 18, 28, 11, 29, 31, 52, 57, 60,103, 7, 1, 50, 36, 60, -105, 13, 0, 18, 27, 13, 7, 16, 20, 46, 13, 6, 2, 0, 2, 60,106, 13, 6, 7, - 1, 37, 23, 6, 60,107, 13, 7, 7, 1, 37, 23, 7, 60,108, 60,104, 13, 0, 18, - 27, 13, 7, 16, 54, 47, 5, 1, 50, 2, 60,109, 60,112, 13, 1, 48, 7, 13, 0, - 18, 10, 11, 20, 31, 48, 5, 13, 4, 4, 0, 32, 52, 19, 60,113, 15, 8, 11, 47, - 13, 0, 18, 10, 42, 11, 48, 42, 2, 0, 1, 50, 2, 60,114, 60,117, 13, 1, 52, - 6, 7, 2, 23, 6, 50, 4, 7, 1, 23, 6, 60,118, 13, 0, 18, 27, 7, 1, 16, - 18, 28, 11, 29, 31, 52, 57, 60,119, 7, 1, 50, 36, 60,121, 13, 0, 18, 27, 13, - 7, 16, 20, 49, 13, 6, 2, 0, 2, 60,122, 13, 6, 7, 1, 37, 23, 6, 60,123, - 13, 7, 7, 1, 37, 23, 7, 60,124, 60,120, 13, 0, 18, 27, 13, 7, 16, 54, 47, - 5, 1, 50, 2, 60,125, 60,128, 13, 1, 48, 7, 13, 0, 18, 10, 11, 50, 32, 52, - 12, 60,129, 15, 8, 11, 51, 2, 0, 1, 49, 2,252, 60,130, 13, 1, 48, 7, 13, - 0, 18, 10, 11, 52, 32, 52, 34, 60,131, 15, 8, 11, 53, 13, 0, 18, 27, 7, 1, - 16, 18, 10, 11, 54, 13, 0, 18, 27, 7, 2, 16, 18, 10, 11, 55, 2, 0, 5, 49, - 2,203, 60,133, 15, 8, 11, 56, 2, 0, 1, 60,134, 13, 0, 18, 28, 11, 57, 31, - 48, 7, 13, 0, 18, 28, 11, 29, 31, 52, 48, 60,135, 15, 8, 11, 58, 13, 0, 18, - 6, 13, 0, 18, 28, 13, 0, 18, 59, 11, 60, 2, 0, 5, 60,136, 15, 8, 11, 42, - 13, 0, 18, 6, 13, 0, 18, 28, 13, 0, 18, 59, 11, 61, 2, 0, 5, 50, 11, 60, -138, 15, 8, 11, 58, 2, 0, 1, 60,139, 60,140, 13, 1, 48, 7, 13, 0, 18, 10, - 11, 20, 32, 52, 15, 60,141, 15, 8, 11, 20, 13, 1, 11, 42, 2, 0, 3, 50, 70, - 60,142, 13, 1, 48, 2, 13, 4, 52, 21, 60,143, 15, 8, 13, 1, 11, 62, 42, 13, - 0, 18, 10, 42, 11, 42, 2, 0, 2, 50, 39, 60,144, 13, 1, 52, 18, 60,145, 15, - 8, 11, 63, 13, 0, 18, 10, 42, 11, 42, 2, 0, 2, 50, 15, 60,147, 15, 8, 13, - 0, 18, 10, 11, 42, 2, 0, 2, 60,148, 60,151, 7, 1, 50, 49, 60,153, 13, 0, - 18, 27, 13, 7, 16, 20, 64, 2, 0, 1, 60,154, 13, 7, 7, 1, 37, 23, 7, 60, -155, 13, 0, 18, 27, 13, 7, 16, 52, 11, 60,156, 15, 8, 11, 65, 2, 0, 1, 50, - 2, 60,157, 60,158, 60,152, 13, 0, 18, 27, 13, 7, 16, 54, 60, 60,160, 15, 8, - 11, 66, 2, 0, 1, 60,163, 13, 0, 18, 28, 11, 57, 31, 48, 7, 13, 0, 18, 28, - 11, 29, 31, 52,220, 60,164, 15, 31, 13, 0, 18, 28, 2, 1, 1, 60,165, 13, 8, - 11, 68, 32, 52, 17, 60,166, 15, 8, 11, 69, 13, 8, 42, 11, 70, 42, 2, 0, 1, - 50,179, 60,167, 13, 8, 52, 17, 60,168, 15, 8, 11, 69, 13, 8, 42, 11, 71, 42, - 2, 0, 1, 50,156, 60,170, 13, 0, 18, 59, 11, 57, 32, 52, 98, 60,171, 15, 8, - 11, 72, 2, 0, 1, 60,172, 15, 8, 11, 73, 2, 0, 1, 60,173, 15, 8, 11, 74, - 13, 0, 18, 28, 11, 71, 2, 0, 3, 60,174, 15, 8, 11, 75, 2, 0, 1, 60,175, - 15, 8, 11, 76, 13, 0, 18, 28, 11, 77, 2, 0, 3, 60,176, 15, 8, 11, 78, 2, - 0, 1, 60,177, 15, 8, 11, 79, 13, 0, 18, 26, 11, 80, 13, 0, 18, 26, 11, 66, - 2, 0, 5, 60,178, 15, 8, 11, 81, 2, 0, 1, 50, 45, 60,180, 13, 0, 18, 59, - 11, 82, 32, 52, 17, 60,181, 15, 8, 11, 83, 13, 0, 18, 26, 11, 66, 2, 0, 3, - 50, 17, 60,183, 15, 8, 11, 84, 13, 0, 18, 26, 11, 66, 2, 0, 3, 60,184, 60, -185, 5, 1, 50, 2, 60,186, 60,187, 7, 1, 50, 25, 60,189, 13, 0, 18, 27, 13, - 8, 16, 20, 85, 2, 0, 1, 60,190, 13, 8, 7, 1, 37, 23, 8, 60,191, 60,188, - 13, 0, 18, 27, 13, 8, 16, 54, 36, 60,192, 15, 8, 11, 86, 2, 0, 1, 60,195, - 13, 1, 52, 6, 7, 2, 23, 6, 50, 4, 7, 1, 23, 6, 60,196, 13, 0, 18, 27, - 7, 1, 16, 18, 28, 11, 29, 31, 52, 57, 60,197, 7, 1, 50, 36, 60,199, 13, 0, - 18, 27, 13, 9, 16, 20, 87, 13, 6, 2, 0, 2, 60,200, 13, 6, 7, 1, 37, 23, - 6, 60,201, 13, 9, 7, 1, 37, 23, 9, 60,202, 60,198, 13, 0, 18, 27, 13, 9, - 16, 54, 47, 5, 1, 50, 2, 60,203, 60,206, 13, 0, 18, 27, 7, 1, 16, 18, 28, - 11, 29, 31, 52, 46, 60,207, 7, 1, 50, 25, 60,209, 13, 0, 18, 27, 13, 9, 16, - 20, 88, 2, 0, 1, 60,210, 13, 9, 7, 1, 37, 23, 9, 60,211, 60,208, 13, 0, - 18, 27, 13, 9, 16, 54, 36, 5, 1, 50, 2, 60,212, 5, 2, 60,213, 60,215, 15, - 8, 11, 89, 2, 0, 1, 60,216, 15, 8, 11, 90, 2, 0, 1, 60,219, 15, 8, 11, - 91, 2, 0, 1, 60,220, 15, 93, 13, 0, 18, 15, 9, 2, 9, 1, 2, 1, 3, 7, - 1, 38, 60,221, 13, 7, 7, 0, 36, 52, 38, 60,222, 15, 8, 11, 39, 15, 93, 13, - 0, 18, 15, 7, 1, 9, 3, 2, 1, 3, 42, 15, 94, 11, 95, 13, 7, 2, 1, 2, - 42, 11, 96, 42, 2, 0, 1, 50, 19, 60,224, 15, 8, 11, 97, 13, 0, 18, 98, 42, - 11, 99, 42, 2, 0, 1, 60,225, 60,227, 15, 8, 11,100, 2, 0, 1, 60,228, 15, - 8, 11,101, 2, 0, 1, 60,229, 0, 0, 0, 0, 24, 0, 0, 0, 51, 0, 0, 0, - 5,115,101,108,102, 0, 0, 0, 0, 52, 0, 0, 0, 6, 99,108, 97,115,115, 0, - 0, 0, 0, 53, 0, 0, 0, 2, 95, 0, 0, 0, 0, 53, 0, 0, 0, 2, 95, 0, - 0, 0, 0, 53, 0, 0, 0, 7,115,116, 97,116,105, 99, 0, 0, 0, 0, 66, 0, - 0, 0, 5,110, 97,114,103, 0, 0, 0, 0, 77, 0, 0, 0, 2,105, 0, 0, 0, - 0, 84, 0, 0, 0, 0, 0, 0, 0, 92, 0, 0, 0, 5,110, 97,114,103, 0, 0, - 0, 0,103, 0, 0, 0, 2,105, 0, 0, 0, 0,108, 0, 0, 0, 0, 0, 0, 0, -119, 0, 0, 0, 2,105, 0, 0, 0, 0,124, 0, 0, 0, 0, 0, 0, 0,151, 0, - 0, 0, 2,105, 0, 0, 0, 0,164, 0, 0, 0, 2,116, 0, 0, 0, 0,185, 0, - 0, 0, 0, 0, 0, 0,187, 0, 0, 0, 2,105, 0, 0, 0, 0,197, 0, 0, 0, - 2,105, 0, 0, 0, 0,202, 0, 0, 0, 0, 0, 0, 0,207, 0, 0, 0, 2,105, - 0, 0, 0, 0,211, 0, 0, 0, 0, 0, 0, 0,212, 0, 0, 0, 0, 0, 0, 0, -212, 0, 0, 0, 0, 0, 0, 0,220, 0, 0, 0, 9,111,118,101,114,108,111, 97, -100, 0, 0, 0, 0,102, 2, 0, 0, 0, 6, 99,108, 97,115,115, 0, 2, 0, 0, - 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 8,105,110, 99,108, 97,115,115, 0, - 2, 0, 0, 0, 2, 95, 0, 2, 0, 0, 0, 7,115,116, 97,116,105, 99, 0, 2, - 0, 0, 0, 8,115,116,114,102,105,110,100, 0, 2, 0, 0, 0, 4,109,111,100, - 0, 2, 0, 0, 0, 13, 94, 37,115, 42, 40,115,116, 97,116,105, 99, 41, 0, 2, - 0, 0, 0, 7,111,117,116,112,117,116, 0, 2, 0, 0, 0, 11, 47, 42, 32,109, -101,116,104,111,100, 58, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, - 0, 11, 32,111,102, 32, 99,108, 97,115,115, 32, 0, 2, 0, 0, 0, 4, 32, 42, - 47, 0, 2, 0, 0, 0, 13, 47, 42, 32,102,117,110, 99,116,105,111,110, 58, 0, - 2, 0, 0, 0, 12,115,116, 97,116,105, 99, 32,118,111,105,100, 0, 2, 0, 0, - 0, 6, 99,110, 97,109,101, 0, 2, 0, 0, 0, 7, 40,118,111,105,100, 41, 0, - 2, 0, 0, 0, 2,123, 0, 2, 0, 0, 0, 7, 32,105,102, 32, 40, 10, 0, 2, - 0, 0, 0, 5,110, 97,114,103, 0, 2, 0, 0, 0, 4,110,101,119, 0, 2, 0, - 0, 0, 6, 99,111,110,115,116, 0, 2, 0, 0, 0, 22, 32, 32, 32, 32, 32, 33, -116,111,108,117, 97, 95,105,115,116,121,112,101, 40, 49, 44, 0, 2, 0, 0, 0, - 7,112, 97,114,101,110,116, 0, 2, 0, 0, 0, 5, 99,116, 97,103, 0, 2, 0, - 0, 0, 8, 44, 48, 41, 32,124,124, 10, 0, 2, 0, 0, 0, 4,116, 97,103, 0, - 2, 0, 0, 0, 5, 97,114,103,115, 0, 2, 0, 0, 0, 5,116,121,112,101, 0, - 2, 0, 0, 0, 5,118,111,105,100, 0, 2, 0, 0, 0, 2,105, 0, 2, 0, 0, - 0, 8,105,115, 98, 97,115,105, 99, 0, 2, 0, 0, 0, 7,111, 98,106,101, 99, -116, 0, 2, 0, 0, 0, 7, 32, 32, 32, 32, 32, 33, 0, 2, 0, 0, 0, 13,111, -117,116, 99,104,101, 99,107,116,121,112,101, 0, 2, 0, 0, 0, 5, 32,124,124, - 10, 0, 2, 0, 0, 0, 21, 32, 32, 32, 32, 32, 33,116,111,108,117, 97, 95,105, -115,110,111,111, 98,106, 40, 0, 2, 0, 0, 0, 19, 41, 10, 32, 41, 10, 32, 32, -103,111,116,111, 32,101,114,114,111,114, 59, 0, 2, 0, 0, 0, 9, 32,101,108, -115,101, 10, 32,123, 0, 2, 0, 0, 0, 2, 32, 0, 2, 0, 0, 0, 2, 42, 0, - 2, 0, 0, 0, 8,115,101,108,102, 32, 61, 32, 0, 2, 0, 0, 0, 2, 40, 0, - 2, 0, 0, 0, 3, 42, 41, 0, 2, 0, 0, 0, 24,116,111,108,117, 97, 95,103, -101,116,117,115,101,114,116,121,112,101, 40, 49, 44, 48, 41, 59, 0, 2, 0, 0, - 0, 20, 94, 37,115, 42,115,116, 97,116,105, 99, 37,115, 37,115, 42, 40, 46, 42, - 41, 0, 2, 0, 0, 0, 8,100,101, 99,108, 97,114,101, 0, 2, 0, 0, 0, 55, - 32, 32,105,102, 32, 40, 33,115,101,108,102, 41, 32,116,111,108,117, 97, 95,101, -114,114,111,114, 40, 34,105,110,118, 97,108,105,100, 32, 39,115,101,108,102, 39, - 32,105,110, 32,102,117,110, 99,116,105,111,110, 32, 39, 0, 2, 0, 0, 0, 5, - 39, 34, 41, 59, 0, 2, 0, 0, 0, 9,103,101,116, 97,114,114, 97,121, 0, 2, - 0, 0, 0, 7,100,101,108,101,116,101, 0, 2, 0, 0, 0, 15, 32, 32,100,101, -108,101,116,101, 32,115,101,108,102, 59, 0, 2, 0, 0, 0, 12,111,112,101,114, - 97,116,111,114, 38, 91, 93, 0, 2, 0, 0, 0, 20, 32, 32,115,101,108,102, 45, - 62,111,112,101,114, 97,116,111,114, 91, 93, 40, 0, 2, 0, 0, 0, 5, 41, 32, - 61, 32, 0, 2, 0, 0, 0, 2, 59, 0, 2, 0, 0, 0, 4, 32, 32,123, 0, 2, - 0, 0, 0, 1, 0, 2, 0, 0, 0, 3, 32, 32, 0, 2, 0, 0, 0, 4,112,116, -114, 0, 2, 0, 0, 0, 14,116,111,108,117, 97, 73, 95,114,101,116, 32, 61, 32, - 0, 2, 0, 0, 0, 3, 41, 32, 0, 2, 0, 0, 0, 3, 58, 58, 0, 2, 0, 0, - 0, 7,115,101,108,102, 45, 62, 0, 2, 0, 0, 0, 8,112, 97,115,115,112, 97, -114, 0, 2, 0, 0, 0, 2, 44, 0, 2, 0, 0, 0, 3, 41, 59, 0, 2, 0, 0, - 0, 2,116, 0, 2, 0, 0, 0, 7,110,117,109, 98,101,114, 0, 2, 0, 0, 0, - 14, 32, 32, 32,116,111,108,117, 97, 95,112,117,115,104, 0, 2, 0, 0, 0, 22, - 40, 40,100,111,117, 98,108,101, 41,116,111,108,117, 97, 73, 95,114,101,116, 41, - 59, 0, 2, 0, 0, 0, 14, 40,116,111,108,117, 97, 73, 95,114,101,116, 41, 59, - 0, 2, 0, 0, 0, 5, 32, 32, 32,123, 0, 2, 0, 0, 0, 20, 35,105,102,100, -101,102, 32, 95, 95, 99,112,108,117,115,112,108,117,115, 10, 0, 2, 0, 0, 0, - 29, 32, 32, 32, 32,118,111,105,100, 42, 32,116,111,108,117, 97, 73, 95, 99,108, -111,110,101, 32, 61, 32,110,101,119, 0, 2, 0, 0, 0, 7, 35,101,108,115,101, - 10, 0, 2, 0, 0, 0, 63, 32, 32, 32, 32,118,111,105,100, 42, 32,116,111,108, -117, 97, 73, 95, 99,108,111,110,101, 32, 61, 32,116,111,108,117, 97, 95, 99,111, -112,121, 40, 40,118,111,105,100, 42, 41, 38,116,111,108,117, 97, 73, 95,114,101, -116, 44,115,105,122,101,111,102, 40, 0, 2, 0, 0, 0, 4, 41, 41, 59, 0, 2, - 0, 0, 0, 8, 35,101,110,100,105,102, 10, 0, 2, 0, 0, 0, 51, 32, 32, 32, - 32,116,111,108,117, 97, 95,112,117,115,104,117,115,101,114,116,121,112,101, 40, -116,111,108,117, 97, 95,100,111, 99,108,111,110,101, 40,116,111,108,117, 97, 73, - 95, 99,108,111,110,101, 44, 0, 2, 0, 0, 0, 3, 41, 44, 0, 2, 0, 0, 0, - 5, 32, 32, 32,125, 0, 2, 0, 0, 0, 2, 38, 0, 2, 0, 0, 0, 42, 32, 32, - 32,116,111,108,117, 97, 95,112,117,115,104,117,115,101,114,116,121,112,101, 40, - 40,118,111,105,100, 42, 41, 38,116,111,108,117, 97, 73, 95,114,101,116, 44, 0, - 2, 0, 0, 0, 41, 32, 32, 32,116,111,108,117, 97, 95,112,117,115,104,117,115, -101,114,116,121,112,101, 40, 40,118,111,105,100, 42, 41,116,111,108,117, 97, 73, - 95,114,101,116, 44, 0, 2, 0, 0, 0, 9,114,101,116,118, 97,108,117,101, 0, - 2, 0, 0, 0, 4, 32, 32,125, 0, 2, 0, 0, 0, 9,115,101,116, 97,114,114, - 97,121, 0, 2, 0, 0, 0, 10,102,114,101,101, 97,114,114, 97,121, 0, 2, 0, - 0, 0, 3, 32,125, 0, 2, 0, 0, 0, 9, 32,114,101,116,117,114,110, 59, 0, - 2, 0, 0, 0, 8,101,114,114,111,114, 58, 10, 0, 2, 0, 0, 0, 9,111,118, -101,114,108,111, 97,100, 0, 2, 0, 0, 0, 7,115,116,114,115,117, 98, 0, 2, - 0, 0, 0, 7,102,111,114,109, 97,116, 0, 2, 0, 0, 0, 5, 37, 48, 50,100, - 0, 2, 0, 0, 0, 4, 40, 41, 59, 0, 2, 0, 0, 0, 36, 32,116,111,108,117, - 97, 95,101,114,114,111,114, 40, 34, 35,102,101,114,114,111,114, 32,105,110, 32, -102,117,110, 99,116,105,111,110, 32, 39, 0, 2, 0, 0, 0, 6,108,110, 97,109, -101, 0, 2, 0, 0, 0, 6, 39, 46, 34, 41, 59, 0, 2, 0, 0, 0, 2,125, 0, - 2, 0, 0, 0, 2, 10, 0, 2, 0, 0, 0, 9,114,101,103,105,115,116,101,114, - 0, 4, 0, 0, 0,232, 0, 0, 0, 14, 64,102,117,110, 99,116,105,111,110, 46, -108,117, 97, 0, 0, 0, 0, 89, 5, 1, 60,233, 13, 0, 20, 2, 2, 1, 1, 46, - 7, 13, 0, 20, 3, 2, 1, 1, 60,234, 13, 1, 52, 33, 60,235, 15, 4, 11, 5, - 13, 1, 42, 11, 6, 42, 13, 0, 18, 7, 42, 11, 8, 42, 13, 0, 18, 9, 42, 11, - 10, 42, 2, 0, 1, 50, 27, 60,237, 15, 4, 11, 11, 13, 0, 18, 7, 42, 11, 8, - 42, 13, 0, 18, 9, 42, 11, 10, 42, 2, 0, 1, 60,238, 60,239, 0, 0, 0, 0, - 2, 0, 0, 0,232, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0,233, 0, 0, - 0, 7,112, 97,114,101,110,116, 0, 0, 0, 0, 12, 2, 0, 0, 0, 7,112, 97, -114,101,110,116, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 8, -105,110, 99,108, 97,115,115, 0, 2, 0, 0, 0, 9,105,110,109,111,100,117,108, -101, 0, 2, 0, 0, 0, 7,111,117,116,112,117,116, 0, 2, 0, 0, 0, 18, 32, -116,111,108,117, 97, 95,102,117,110, 99,116,105,111,110, 40, 34, 0, 2, 0, 0, - 0, 4, 34, 44, 34, 0, 2, 0, 0, 0, 6,108,110, 97,109,101, 0, 2, 0, 0, - 0, 3, 34, 44, 0, 2, 0, 0, 0, 6, 99,110, 97,109,101, 0, 2, 0, 0, 0, - 3, 41, 59, 0, 2, 0, 0, 0, 23, 32,116,111,108,117, 97, 95,102,117,110, 99, -116,105,111,110, 40, 78, 85, 76, 76, 44, 34, 0, 2, 0, 0, 0, 11,117,110,114, -101,103,105,115,116,101,114, 0, 4, 0, 0, 0,242, 0, 0, 0, 14, 64,102,117, -110, 99,116,105,111,110, 46,108,117, 97, 0, 0, 0, 0, 52, 4, 1, 60,243, 13, - 0, 20, 1, 2, 1, 1, 4, 0, 32, 48, 10, 13, 0, 20, 2, 2, 1, 1, 4, 0, - 32, 52, 19, 60,244, 15, 3, 11, 4, 13, 0, 18, 5, 42, 11, 6, 42, 2, 0, 1, - 50, 2, 60,245, 60,246, 0, 0, 0, 0, 1, 0, 0, 0,242, 0, 0, 0, 5,115, -101,108,102, 0, 0, 0, 0, 7, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, - 0, 0, 8,105,110, 99,108, 97,115,115, 0, 2, 0, 0, 0, 9,105,110,109,111, -100,117,108,101, 0, 2, 0, 0, 0, 7,111,117,116,112,117,116, 0, 2, 0, 0, - 0, 32, 32,108,117, 97, 95,112,117,115,104,110,105,108, 40, 41, 59, 32,108,117, - 97, 95,115,101,116,103,108,111, 98, 97,108, 40, 34, 0, 2, 0, 0, 0, 6,108, -110, 97,109,101, 0, 2, 0, 0, 0, 4, 34, 41, 59, 0, 2, 0, 0, 0, 6,112, -114,105,110,116, 0, 4, 0, 0, 0,250, 0, 0, 0, 14, 64,102,117,110, 99,116, -105,111,110, 46,108,117, 97, 0, 0, 0, 1, 1, 8, 3, 60,251, 15, 2, 13, 1, - 11, 3, 42, 2, 0, 1, 60,252, 15, 2, 13, 1, 11, 4, 42, 13, 0, 18, 6, 42, - 11, 7, 42, 2, 0, 1, 60,253, 15, 2, 13, 1, 11, 8, 42, 13, 0, 18, 9, 42, - 11, 7, 42, 2, 0, 1, 60,254, 15, 2, 13, 1, 11, 10, 42, 13, 0, 18, 11, 42, - 11, 7, 42, 2, 0, 1, 60,255, 15, 2, 13, 1, 11, 12, 42, 13, 0, 18, 13, 42, - 11, 7, 42, 2, 0, 1, 59, 1, 0, 15, 2, 13, 1, 11, 14, 42, 13, 0, 18, 15, - 42, 11, 7, 42, 2, 0, 1, 59, 1, 1, 15, 2, 13, 1, 11, 16, 42, 13, 0, 18, - 17, 42, 11, 7, 42, 2, 0, 1, 59, 1, 2, 15, 2, 13, 1, 11, 18, 42, 13, 0, - 18, 19, 42, 11, 7, 42, 2, 0, 1, 59, 1, 3, 15, 2, 13, 1, 11, 20, 42, 2, - 0, 1, 59, 1, 4, 7, 1, 50, 35, 59, 1, 6, 13, 0, 18, 22, 13, 3, 16, 20, - 2, 13, 1, 11, 23, 42, 11, 24, 2, 0, 3, 59, 1, 7, 13, 3, 7, 1, 37, 23, - 3, 59, 1, 8, 59, 1, 5, 13, 0, 18, 22, 13, 3, 16, 54, 47, 59, 1, 9, 15, - 2, 13, 1, 11, 25, 42, 2, 0, 1, 59, 1, 10, 15, 2, 13, 1, 11, 26, 42, 13, - 2, 42, 2, 0, 1, 59, 1, 11, 0, 0, 0, 0, 4, 0, 0, 0,250, 0, 0, 0, - 5,115,101,108,102, 0, 0, 0, 0,250, 0, 0, 0, 6,105,100,101,110,116, 0, - 0, 0, 0,250, 0, 0, 0, 6, 99,108,111,115,101, 0, 0, 0, 1, 4, 0, 0, - 0, 2,105, 0, 0, 0, 0, 27, 2, 0, 0, 0, 6,105,100,101,110,116, 0, 2, - 0, 0, 0, 6, 99,108,111,115,101, 0, 2, 0, 0, 0, 6,112,114,105,110,116, - 0, 2, 0, 0, 0, 10, 70,117,110, 99,116,105,111,110,123, 0, 2, 0, 0, 0, - 10, 32,109,111,100, 32, 32, 61, 32, 39, 0, 2, 0, 0, 0, 5,115,101,108,102, - 0, 2, 0, 0, 0, 4,109,111,100, 0, 2, 0, 0, 0, 3, 39, 44, 0, 2, 0, - 0, 0, 10, 32,116,121,112,101, 32, 61, 32, 39, 0, 2, 0, 0, 0, 5,116,121, -112,101, 0, 2, 0, 0, 0, 10, 32,112,116,114, 32, 32, 61, 32, 39, 0, 2, 0, - 0, 0, 4,112,116,114, 0, 2, 0, 0, 0, 10, 32,110, 97,109,101, 32, 61, 32, - 39, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 11, 32, 99,111, -110,115,116, 32, 61, 32, 39, 0, 2, 0, 0, 0, 6, 99,111,110,115,116, 0, 2, - 0, 0, 0, 11, 32, 99,110, 97,109,101, 32, 61, 32, 39, 0, 2, 0, 0, 0, 6, - 99,110, 97,109,101, 0, 2, 0, 0, 0, 11, 32,108,110, 97,109,101, 32, 61, 32, - 39, 0, 2, 0, 0, 0, 6,108,110, 97,109,101, 0, 2, 0, 0, 0, 10, 32, 97, -114,103,115, 32, 61, 32,123, 0, 2, 0, 0, 0, 2,105, 0, 2, 0, 0, 0, 5, - 97,114,103,115, 0, 2, 0, 0, 0, 3, 32, 32, 0, 2, 0, 0, 0, 2, 44, 0, - 2, 0, 0, 0, 3, 32,125, 0, 2, 0, 0, 0, 2,125, 0, 2, 0, 0, 0, 9, -111,118,101,114,108,111, 97,100, 0, 4, 0, 0, 1, 14, 0, 0, 0, 14, 64,102, -117,110, 99,116,105,111,110, 46,108,117, 97, 0, 0, 0, 0, 22, 4, 1, 59, 1, - 15, 13, 0, 18, 1, 20, 2, 13, 0, 18, 3, 3, 1, 2, 59, 1, 16, 0, 0, 0, - 0, 1, 0, 0, 1, 14, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 4, 2, - 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 7,112, 97,114,101,110,116, - 0, 2, 0, 0, 0, 9,111,118,101,114,108,111, 97,100, 0, 2, 0, 0, 0, 6, -108,110, 97,109,101, 0, 2, 0, 0, 0, 10, 95, 70,117,110, 99,116,105,111,110, - 0, 4, 0, 0, 1, 21, 0, 0, 0, 14, 64,102,117,110, 99,116,105,111,110, 46, -108,117, 97, 0, 0, 0, 0,231, 7, 1, 59, 1, 22, 13, 0, 11, 1, 15, 2, 26, - 59, 1, 23, 15, 3, 13, 0, 15, 4, 2, 0, 2, 59, 1, 25, 13, 0, 18, 5, 11, - 5, 31, 48, 7, 13, 0, 18, 5, 11, 6, 31, 52, 12, 59, 1, 26, 15, 7, 11, 8, - 2, 0, 1, 50, 3, 59, 1, 27, 59, 1, 29, 15, 9, 13, 0, 2, 0, 1, 59, 1, - 30, 13, 0, 20, 10, 2, 1, 1, 52,108, 59, 1, 31, 13, 0, 18, 11, 13, 0, 18, - 12, 18, 11, 32, 52, 46, 59, 1, 32, 13, 0, 11, 11, 11, 13, 26, 59, 1, 33, 13, - 0, 11, 14, 11, 13, 26, 59, 1, 34, 13, 0, 11, 15, 13, 0, 18, 12, 18, 11, 26, - 59, 1, 35, 13, 0, 11, 16, 11, 17, 26, 50, 44, 59, 1, 36, 13, 0, 18, 11, 11, - 18, 13, 0, 18, 12, 18, 11, 42, 32, 52, 22, 59, 1, 37, 13, 0, 11, 11, 11, 19, - 26, 59, 1, 38, 13, 0, 11, 14, 11, 19, 26, 50, 3, 59, 1, 39, 50, 3, 59, 1, - 40, 59, 1, 41, 13, 0, 11, 20, 13, 0, 20, 21, 11, 22, 2, 1, 2, 13, 0, 20, - 23, 13, 0, 2, 1, 2, 42, 26, 59, 1, 42, 13, 0, 1, 1, 59, 1, 43, 0, 0, - 0, 0, 1, 0, 0, 1, 21, 0, 0, 0, 2,116, 0, 0, 0, 0, 24, 2, 0, 0, - 0, 2,116, 0, 2, 0, 0, 0, 6, 95, 98, 97,115,101, 0, 2, 0, 0, 0, 14, - 99,108, 97,115,115, 70,117,110, 99,116,105,111,110, 0, 2, 0, 0, 0, 7,115, -101,116,116, 97,103, 0, 2, 0, 0, 0, 10,116,111,108,117, 97, 95,116, 97,103, - 0, 2, 0, 0, 0, 6, 99,111,110,115,116, 0, 2, 0, 0, 0, 1, 0, 2, 0, - 0, 0, 6,101,114,114,111,114, 0, 2, 0, 0, 0, 31, 35,105,110,118, 97,108, -105,100, 32, 39, 99,111,110,115,116, 39, 32,115,112,101, 99,105,102,105, 99, 97, -116,105,111,110, 0, 2, 0, 0, 0, 7, 97,112,112,101,110,100, 0, 2, 0, 0, - 0, 8,105,110, 99,108, 97,115,115, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, - 2, 0, 0, 0, 7,112, 97,114,101,110,116, 0, 2, 0, 0, 0, 4,110,101,119, - 0, 2, 0, 0, 0, 6,108,110, 97,109,101, 0, 2, 0, 0, 0, 5,116,121,112, -101, 0, 2, 0, 0, 0, 4,112,116,114, 0, 2, 0, 0, 0, 2, 42, 0, 2, 0, - 0, 0, 2,126, 0, 2, 0, 0, 0, 7,100,101,108,101,116,101, 0, 2, 0, 0, - 0, 6, 99,110, 97,109,101, 0, 2, 0, 0, 0, 10, 99,102,117,110, 99,110, 97, -109,101, 0, 2, 0, 0, 0, 7,116,111,108,117, 97, 73, 0, 2, 0, 0, 0, 9, -111,118,101,114,108,111, 97,100, 0, 2, 0, 0, 0, 9, 70,117,110, 99,116,105, -111,110, 0, 4, 0, 0, 1, 49, 0, 0, 0, 14, 64,102,117,110, 99,116,105,111, -110, 46,108,117, 97, 0, 0, 0, 0,147, 11, 3, 59, 1, 50, 15, 4, 15, 5, 13, - 1, 7, 2, 9, 2, 2, 1, 3, 11, 6, 2, 1, 2, 59, 1, 51, 7, 1, 59, 1, - 52, 22, 1, 11, 9, 7, 0, 30, 0, 50, 50, 59, 1, 54, 13, 5, 11, 9, 13, 5, - 18, 9, 7, 1, 37, 26, 59, 1, 55, 13, 5, 13, 5, 18, 9, 15, 10, 13, 3, 13, - 4, 16, 11, 11, 2, 1, 2, 26, 59, 1, 56, 13, 4, 7, 1, 37, 23, 4, 59, 1, - 57, 59, 1, 53, 13, 3, 13, 4, 16, 54, 60, 59, 1, 58, 15, 10, 13, 0, 11, 13, - 2, 1, 2, 59, 1, 59, 13, 6, 11, 14, 13, 5, 26, 59, 1, 60, 13, 6, 11, 15, - 13, 2, 26, 59, 1, 61, 15, 16, 13, 6, 3, 7, 1, 59, 1, 62, 0, 0, 0, 0, - 7, 0, 0, 1, 49, 0, 0, 0, 2,100, 0, 0, 0, 1, 49, 0, 0, 0, 2, 97, - 0, 0, 0, 1, 49, 0, 0, 0, 2, 99, 0, 0, 0, 1, 50, 0, 0, 0, 2,116, - 0, 0, 0, 1, 51, 0, 0, 0, 2,105, 0, 0, 0, 1, 52, 0, 0, 0, 2,108, - 0, 0, 0, 1, 58, 0, 0, 0, 2,102, 0, 0, 0, 0, 17, 2, 0, 0, 0, 2, -100, 0, 2, 0, 0, 0, 2, 97, 0, 2, 0, 0, 0, 2, 99, 0, 2, 0, 0, 0, - 2,116, 0, 2, 0, 0, 0, 6,115,112,108,105,116, 0, 2, 0, 0, 0, 7,115, -116,114,115,117, 98, 0, 2, 0, 0, 0, 2, 44, 0, 2, 0, 0, 0, 2,105, 0, - 2, 0, 0, 0, 2,108, 0, 2, 0, 0, 0, 2,110, 0, 2, 0, 0, 0, 12, 68, -101, 99,108, 97,114, 97,116,105,111,110, 0, 2, 0, 0, 0, 4,118, 97,114, 0, - 2, 0, 0, 0, 2,102, 0, 2, 0, 0, 0, 5,102,117,110, 99, 0, 2, 0, 0, - 0, 5, 97,114,103,115, 0, 2, 0, 0, 0, 6, 99,111,110,115,116, 0, 2, 0, - 0, 0, 10, 95, 70,117,110, 99,116,105,111,110, 0, -}; - -/* operator.lo */ -static char B14[]={ - 27, 76,117, 97, 50, 0, 0, 0, 0, 0, 0, 0, 0, 14, 64,111,112,101,114, 97, -116,111,114, 46,108,117, 97, 0, 0, 0, 0,125, 21, 0, 60, 18, 22, 2, 60, 19, - 11, 1, 11, 2, 11, 3, 60, 20, 15, 4, 30, 1, 60, 21, 25, 0, 60, 22, 15, 5, - 15, 0, 15, 6, 2, 0, 2, 60, 25, 22, 10, 11, 8, 11, 9, 60, 26, 11, 10, 11, - 11, 60, 27, 11, 12, 11, 13, 60, 28, 11, 14, 11, 15, 60, 29, 11, 16, 11, 17, 60, - 30, 11, 18, 11, 19, 60, 31, 11, 20, 11, 21, 60, 32, 11, 22, 11, 23, 60, 33, 11, - 24, 11, 25, 60, 34, 11, 26, 11, 27, 30, 9, 60, 35, 25, 7, 60, 39, 15, 0, 11, - 28, 11, 29, 26, 60, 60, 11, 31, 25, 30, 60, 82, 11, 33, 25, 32, 0, 0, 0, 0, - 0, 0, 0, 0, 34, 2, 0, 0, 0, 14, 99,108, 97,115,115, 79,112,101,114, 97, -116,111,114, 0, 2, 0, 0, 0, 5,107,105,110,100, 0, 2, 0, 0, 0, 1, 0, - 2, 0, 0, 0, 6, 95, 98, 97,115,101, 0, 2, 0, 0, 0, 14, 99,108, 97,115, -115, 70,117,110, 99,116,105,111,110, 0, 2, 0, 0, 0, 7,115,101,116,116, 97, -103, 0, 2, 0, 0, 0, 10,116,111,108,117, 97, 95,116, 97,103, 0, 2, 0, 0, - 0, 4, 95, 84, 77, 0, 2, 0, 0, 0, 2, 43, 0, 2, 0, 0, 0, 13,111,112, -101,114, 97,116,111,114, 95, 97,100,100, 0, 2, 0, 0, 0, 2, 45, 0, 2, 0, - 0, 0, 13,111,112,101,114, 97,116,111,114, 95,115,117, 98, 0, 2, 0, 0, 0, - 2, 42, 0, 2, 0, 0, 0, 13,111,112,101,114, 97,116,111,114, 95,109,117,108, - 0, 2, 0, 0, 0, 2, 47, 0, 2, 0, 0, 0, 13,111,112,101,114, 97,116,111, -114, 95,100,105,118, 0, 2, 0, 0, 0, 2, 60, 0, 2, 0, 0, 0, 12,111,112, -101,114, 97,116,111,114, 95,108,116, 0, 2, 0, 0, 0, 2, 62, 0, 2, 0, 0, - 0, 12,111,112,101,114, 97,116,111,114, 95,103,116, 0, 2, 0, 0, 0, 3, 60, - 61, 0, 2, 0, 0, 0, 12,111,112,101,114, 97,116,111,114, 95,108,101, 0, 2, - 0, 0, 0, 3, 62, 61, 0, 2, 0, 0, 0, 12,111,112,101,114, 97,116,111,114, - 95,103,101, 0, 2, 0, 0, 0, 3, 91, 93, 0, 2, 0, 0, 0, 13,111,112,101, -114, 97,116,111,114, 95,103,101,116, 0, 2, 0, 0, 0, 4, 38, 91, 93, 0, 2, - 0, 0, 0, 13,111,112,101,114, 97,116,111,114, 95,115,101,116, 0, 2, 0, 0, - 0, 6,112,114,105,110,116, 0, 4, 0, 0, 0, 39, 0, 0, 0, 14, 64,111,112, -101,114, 97,116,111,114, 46,108,117, 97, 0, 0, 0, 1, 9, 8, 3, 60, 40, 15, - 2, 13, 1, 11, 3, 42, 2, 0, 1, 60, 41, 15, 2, 13, 1, 11, 4, 42, 13, 0, - 18, 6, 42, 11, 7, 42, 2, 0, 1, 60, 42, 15, 2, 13, 1, 11, 8, 42, 13, 0, - 18, 9, 42, 11, 7, 42, 2, 0, 1, 60, 43, 15, 2, 13, 1, 11, 10, 42, 13, 0, - 18, 11, 42, 11, 7, 42, 2, 0, 1, 60, 44, 15, 2, 13, 1, 11, 12, 42, 13, 0, - 18, 13, 42, 11, 7, 42, 2, 0, 1, 60, 45, 15, 2, 13, 1, 11, 14, 42, 13, 0, - 18, 15, 42, 11, 7, 42, 2, 0, 1, 60, 46, 15, 2, 13, 1, 11, 16, 42, 13, 0, - 18, 17, 42, 11, 7, 42, 2, 0, 1, 60, 47, 15, 2, 13, 1, 11, 18, 42, 13, 0, - 18, 19, 42, 11, 7, 42, 2, 0, 1, 60, 48, 15, 2, 13, 1, 11, 20, 42, 13, 0, - 18, 21, 42, 11, 7, 42, 2, 0, 1, 60, 49, 15, 2, 13, 1, 11, 22, 42, 2, 0, - 1, 60, 50, 7, 1, 50, 32, 60, 52, 13, 0, 18, 24, 13, 3, 16, 20, 2, 13, 1, - 11, 25, 42, 11, 26, 2, 0, 3, 60, 53, 13, 3, 7, 1, 37, 23, 3, 60, 54, 60, - 51, 13, 0, 18, 24, 13, 3, 16, 54, 43, 60, 55, 15, 2, 13, 1, 11, 27, 42, 2, - 0, 1, 60, 56, 15, 2, 13, 1, 11, 28, 42, 13, 2, 42, 2, 0, 1, 60, 57, 0, - 0, 0, 0, 4, 0, 0, 0, 39, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, - 39, 0, 0, 0, 6,105,100,101,110,116, 0, 0, 0, 0, 39, 0, 0, 0, 6, 99, -108,111,115,101, 0, 0, 0, 0, 50, 0, 0, 0, 2,105, 0, 0, 0, 0, 29, 2, - 0, 0, 0, 6,105,100,101,110,116, 0, 2, 0, 0, 0, 6, 99,108,111,115,101, - 0, 2, 0, 0, 0, 6,112,114,105,110,116, 0, 2, 0, 0, 0, 10, 79,112,101, -114, 97,116,111,114,123, 0, 2, 0, 0, 0, 11, 32,107,105,110,100, 32, 32, 61, - 32, 39, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 5,107,105, -110,100, 0, 2, 0, 0, 0, 3, 39, 44, 0, 2, 0, 0, 0, 10, 32,109,111,100, - 32, 32, 61, 32, 39, 0, 2, 0, 0, 0, 4,109,111,100, 0, 2, 0, 0, 0, 10, - 32,116,121,112,101, 32, 61, 32, 39, 0, 2, 0, 0, 0, 5,116,121,112,101, 0, - 2, 0, 0, 0, 10, 32,112,116,114, 32, 32, 61, 32, 39, 0, 2, 0, 0, 0, 4, -112,116,114, 0, 2, 0, 0, 0, 10, 32,110, 97,109,101, 32, 61, 32, 39, 0, 2, - 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, 0, 0, 11, 32, 99,111,110,115,116, - 32, 61, 32, 39, 0, 2, 0, 0, 0, 6, 99,111,110,115,116, 0, 2, 0, 0, 0, - 11, 32, 99,110, 97,109,101, 32, 61, 32, 39, 0, 2, 0, 0, 0, 6, 99,110, 97, -109,101, 0, 2, 0, 0, 0, 11, 32,108,110, 97,109,101, 32, 61, 32, 39, 0, 2, - 0, 0, 0, 6,108,110, 97,109,101, 0, 2, 0, 0, 0, 10, 32, 97,114,103,115, - 32, 61, 32,123, 0, 2, 0, 0, 0, 2,105, 0, 2, 0, 0, 0, 5, 97,114,103, -115, 0, 2, 0, 0, 0, 3, 32, 32, 0, 2, 0, 0, 0, 2, 44, 0, 2, 0, 0, - 0, 3, 32,125, 0, 2, 0, 0, 0, 2,125, 0, 2, 0, 0, 0, 10, 95, 79,112, -101,114, 97,116,111,114, 0, 4, 0, 0, 0, 60, 0, 0, 0, 14, 64,111,112,101, -114, 97,116,111,114, 46,108,117, 97, 0, 0, 0, 0,140, 7, 1, 60, 61, 13, 0, - 11, 1, 15, 2, 26, 60, 62, 15, 3, 13, 0, 15, 4, 2, 0, 2, 60, 64, 13, 0, - 18, 5, 11, 5, 31, 48, 7, 13, 0, 18, 5, 11, 6, 31, 52, 11, 60, 65, 15, 7, - 11, 8, 2, 0, 1, 50, 2, 60, 66, 60, 68, 15, 9, 13, 0, 2, 0, 1, 60, 69, - 13, 0, 20, 10, 2, 1, 1, 44, 52, 11, 60, 70, 15, 7, 11, 11, 2, 0, 1, 50, - 2, 60, 71, 60, 73, 13, 0, 11, 12, 13, 0, 20, 13, 11, 14, 2, 1, 2, 13, 0, - 20, 15, 13, 0, 2, 1, 2, 42, 26, 60, 74, 13, 0, 11, 16, 13, 0, 18, 16, 13, - 0, 18, 17, 42, 26, 60, 75, 13, 0, 1, 1, 60, 76, 0, 0, 0, 0, 1, 0, 0, - 0, 60, 0, 0, 0, 2,116, 0, 0, 0, 0, 18, 2, 0, 0, 0, 2,116, 0, 2, - 0, 0, 0, 6, 95, 98, 97,115,101, 0, 2, 0, 0, 0, 14, 99,108, 97,115,115, - 79,112,101,114, 97,116,111,114, 0, 2, 0, 0, 0, 7,115,101,116,116, 97,103, - 0, 2, 0, 0, 0, 10,116,111,108,117, 97, 95,116, 97,103, 0, 2, 0, 0, 0, - 6, 99,111,110,115,116, 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 6,101,114, -114,111,114, 0, 2, 0, 0, 0, 31, 35,105,110,118, 97,108,105,100, 32, 39, 99, -111,110,115,116, 39, 32,115,112,101, 99,105,102,105, 99, 97,116,105,111,110, 0, - 2, 0, 0, 0, 7, 97,112,112,101,110,100, 0, 2, 0, 0, 0, 8,105,110, 99, -108, 97,115,115, 0, 2, 0, 0, 0, 46, 35,111,112,101,114, 97,116,111,114, 32, - 99, 97,110, 32,111,110,108,121, 32, 98,101, 32,100,101,102,105,110,101,100, 32, - 97,115, 32, 99,108, 97,115,115, 32,109,101,109, 98,101,114, 0, 2, 0, 0, 0, - 6, 99,110, 97,109,101, 0, 2, 0, 0, 0, 10, 99,102,117,110, 99,110, 97,109, -101, 0, 2, 0, 0, 0, 7,116,111,108,117, 97, 73, 0, 2, 0, 0, 0, 9,111, -118,101,114,108,111, 97,100, 0, 2, 0, 0, 0, 5,110, 97,109,101, 0, 2, 0, - 0, 0, 5,107,105,110,100, 0, 2, 0, 0, 0, 9, 79,112,101,114, 97,116,111, -114, 0, 4, 0, 0, 0, 82, 0, 0, 0, 14, 64,111,112,101,114, 97,116,111,114, - 46,108,117, 97, 0, 0, 0, 1, 99, 14, 4, 60, 83, 15, 5, 15, 6, 13, 2, 7, - 2, 15, 7, 13, 2, 2, 1, 1, 7, 1, 38, 2, 1, 3, 11, 8, 2, 1, 2, 60, - 84, 7, 1, 60, 85, 22, 1, 11, 11, 7, 0, 30, 0, 50, 46, 60, 87, 13, 6, 11, - 11, 13, 6, 18, 11, 7, 1, 37, 26, 60, 88, 13, 6, 13, 6, 18, 11, 15, 12, 13, - 4, 13, 5, 16, 11, 13, 2, 1, 2, 26, 60, 89, 13, 5, 7, 1, 37, 23, 5, 60, - 90, 60, 86, 13, 4, 13, 5, 16, 54, 55, 60, 91, 13, 1, 11, 14, 32, 52, 17, 60, - 92, 15, 15, 13, 0, 11, 16, 11, 17, 2, 1, 3, 23, 0, 50, 59, 60, 93, 13, 1, - 11, 18, 32, 52, 48, 60, 94, 13, 6, 11, 11, 13, 6, 18, 11, 7, 1, 37, 26, 60, - 95, 13, 6, 13, 6, 18, 11, 15, 12, 13, 0, 11, 13, 2, 1, 2, 26, 60, 96, 13, - 6, 13, 6, 18, 11, 16, 11, 19, 11, 20, 26, 50, 2, 60, 97, 60, 98, 15, 12, 13, - 0, 11, 22, 2, 1, 2, 60, 99, 13, 1, 11, 14, 32, 48, 25, 13, 6, 7, 1, 16, - 4, 0, 32, 46, 15, 15, 23, 13, 6, 7, 1, 16, 18, 24, 2, 1, 1, 11, 25, 31, - 52, 11, 60,100, 15, 26, 11, 27, 2, 0, 1, 50, 2, 60,101, 60,102, 13, 7, 11, - 28, 13, 6, 26, 60,103, 13, 7, 11, 29, 13, 3, 26, 60,104, 13, 7, 11, 30, 15, - 15, 13, 1, 11, 31, 11, 17, 2, 1, 3, 26, 60,105, 13, 7, 11, 32, 15, 33, 13, - 7, 18, 30, 16, 26, 60,106, 13, 7, 18, 30, 11, 14, 32, 48, 12, 15, 34, 13, 7, - 18, 35, 11, 29, 2, 1, 2, 44, 52, 20, 60,107, 15, 36, 13, 0, 11, 16, 13, 1, - 42, 13, 2, 13, 3, 2, 0, 4, 50, 2, 60,108, 60,109, 15, 37, 13, 7, 3, 8, - 1, 60,110, 0, 0, 0, 0, 8, 0, 0, 0, 82, 0, 0, 0, 2,100, 0, 0, 0, - 0, 82, 0, 0, 0, 2,107, 0, 0, 0, 0, 82, 0, 0, 0, 2, 97, 0, 0, 0, - 0, 82, 0, 0, 0, 2, 99, 0, 0, 0, 0, 83, 0, 0, 0, 2,116, 0, 0, 0, - 0, 84, 0, 0, 0, 2,105, 0, 0, 0, 0, 85, 0, 0, 0, 2,108, 0, 0, 0, - 0, 98, 0, 0, 0, 2,102, 0, 0, 0, 0, 38, 2, 0, 0, 0, 2,100, 0, 2, - 0, 0, 0, 2,107, 0, 2, 0, 0, 0, 2, 97, 0, 2, 0, 0, 0, 2, 99, 0, - 2, 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 6,115,112,108,105,116, 0, 2, 0, - 0, 0, 7,115,116,114,115,117, 98, 0, 2, 0, 0, 0, 7,115,116,114,108,101, -110, 0, 2, 0, 0, 0, 2, 44, 0, 2, 0, 0, 0, 2,105, 0, 2, 0, 0, 0, - 2,108, 0, 2, 0, 0, 0, 2,110, 0, 2, 0, 0, 0, 12, 68,101, 99,108, 97, -114, 97,116,105,111,110, 0, 2, 0, 0, 0, 4,118, 97,114, 0, 2, 0, 0, 0, - 3, 91, 93, 0, 2, 0, 0, 0, 5,103,115,117, 98, 0, 2, 0, 0, 0, 2, 38, - 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 4, 38, 91, 93, 0, 2, 0, 0, 0, - 5,110, 97,109,101, 0, 2, 0, 0, 0, 13,116,111,108,117, 97, 73, 95,118, 97, -108,117,101, 0, 2, 0, 0, 0, 2,102, 0, 2, 0, 0, 0, 5,102,117,110, 99, - 0, 2, 0, 0, 0, 8,105,115, 98, 97,115,105, 99, 0, 2, 0, 0, 0, 5,116, -121,112,101, 0, 2, 0, 0, 0, 7,110,117,109, 98,101,114, 0, 2, 0, 0, 0, - 6,101,114,114,111,114, 0, 2, 0, 0, 0, 50,111,112,101,114, 97,116,111,114, - 91, 93, 32, 99, 97,110, 32,111,110,108,121, 32, 98,101, 32,100,101,102,105,110, -101,100, 32,102,111,114, 32,110,117,109,101,114,105, 99, 32,105,110,100,101,120, - 46, 0, 2, 0, 0, 0, 5, 97,114,103,115, 0, 2, 0, 0, 0, 6, 99,111,110, -115,116, 0, 2, 0, 0, 0, 5,107,105,110,100, 0, 2, 0, 0, 0, 3, 37,115, - 0, 2, 0, 0, 0, 6,108,110, 97,109,101, 0, 2, 0, 0, 0, 4, 95, 84, 77, - 0, 2, 0, 0, 0, 8,115,116,114,102,105,110,100, 0, 2, 0, 0, 0, 4,109, -111,100, 0, 2, 0, 0, 0, 9, 79,112,101,114, 97,116,111,114, 0, 2, 0, 0, - 0, 10, 95, 79,112,101,114, 97,116,111,114, 0, -}; - -/* verbatim.lo */ -static char B15[]={ - 27, 76,117, 97, 50, 0, 0, 0, 0, 0, 0, 0, 0, 14, 64,118,101,114, 98, 97, -116,105,109, 46,108,117, 97, 0, 0, 0, 0, 84, 5, 0, 60, 20, 22, 2, 60, 21, - 11, 1, 11, 2, 11, 3, 60, 22, 15, 4, 30, 1, 60, 23, 25, 0, 60, 24, 15, 5, - 15, 0, 15, 6, 2, 0, 2, 60, 27, 15, 0, 11, 7, 11, 8, 26, 60, 34, 15, 0, - 11, 9, 11, 10, 26, 60, 42, 15, 0, 11, 11, 11, 12, 26, 60, 50, 15, 0, 11, 13, - 11, 14, 26, 60, 58, 11, 16, 25, 15, 60, 67, 11, 18, 25, 17, 0, 0, 0, 0, 0, - 0, 0, 0, 19, 2, 0, 0, 0, 14, 99,108, 97,115,115, 86,101,114, 98, 97,116, -105,109, 0, 2, 0, 0, 0, 5,108,105,110,101, 0, 2, 0, 0, 0, 1, 0, 2, - 0, 0, 0, 6, 95, 98, 97,115,101, 0, 2, 0, 0, 0, 13, 99,108, 97,115,115, - 70,101, 97,116,117,114,101, 0, 2, 0, 0, 0, 7,115,101,116,116, 97,103, 0, - 2, 0, 0, 0, 10,116,111,108,117, 97, 95,116, 97,103, 0, 2, 0, 0, 0, 9, -112,114,101, 97,109, 98,108,101, 0, 4, 0, 0, 0, 27, 0, 0, 0, 14, 64,118, -101,114, 98, 97,116,105,109, 46,108,117, 97, 0, 0, 0, 0, 29, 3, 1, 60, 28, - 13, 0, 18, 1, 44, 52, 13, 60, 29, 15, 2, 13, 0, 18, 3, 2, 0, 1, 50, 2, - 60, 30, 60, 31, 0, 0, 0, 0, 1, 0, 0, 0, 27, 0, 0, 0, 5,115,101,108, -102, 0, 0, 0, 0, 4, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, - 5, 99,111,110,100, 0, 2, 0, 0, 0, 6,119,114,105,116,101, 0, 2, 0, 0, - 0, 5,108,105,110,101, 0, 2, 0, 0, 0, 8,115,117,112, 99,111,100,101, 0, - 4, 0, 0, 0, 34, 0, 0, 0, 14, 64,118,101,114, 98, 97,116,105,109, 46,108, -117, 97, 0, 0, 0, 0, 37, 3, 1, 60, 35, 13, 0, 18, 1, 52, 22, 60, 36, 15, - 2, 13, 0, 18, 3, 2, 0, 1, 60, 37, 15, 2, 11, 4, 2, 0, 1, 50, 2, 60, - 38, 60, 39, 0, 0, 0, 0, 1, 0, 0, 0, 34, 0, 0, 0, 5,115,101,108,102, - 0, 0, 0, 0, 5, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 5, - 99,111,110,100, 0, 2, 0, 0, 0, 6,119,114,105,116,101, 0, 2, 0, 0, 0, - 5,108,105,110,101, 0, 2, 0, 0, 0, 2, 10, 0, 2, 0, 0, 0, 9,114,101, -103,105,115,116,101,114, 0, 4, 0, 0, 0, 42, 0, 0, 0, 14, 64,118,101,114, - 98, 97,116,105,109, 46,108,117, 97, 0, 0, 0, 0, 28, 3, 1, 60, 43, 13, 0, - 18, 1, 52, 13, 60, 44, 15, 2, 13, 0, 18, 3, 2, 0, 1, 50, 2, 60, 45, 60, - 46, 0, 0, 0, 0, 1, 0, 0, 0, 42, 0, 0, 0, 5,115,101,108,102, 0, 0, - 0, 0, 4, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, 5, 99,111, -110,100, 0, 2, 0, 0, 0, 6,119,114,105,116,101, 0, 2, 0, 0, 0, 5,108, -105,110,101, 0, 2, 0, 0, 0, 6,112,114,105,110,116, 0, 4, 0, 0, 0, 50, - 0, 0, 0, 14, 64,118,101,114, 98, 97,116,105,109, 46,108,117, 97, 0, 0, 0, - 0, 52, 6, 3, 60, 51, 15, 2, 13, 1, 11, 3, 42, 2, 0, 1, 60, 52, 15, 2, - 13, 1, 11, 4, 42, 13, 0, 18, 6, 42, 11, 7, 42, 2, 0, 1, 60, 53, 15, 2, - 13, 1, 11, 8, 42, 13, 2, 42, 2, 0, 1, 60, 54, 0, 0, 0, 0, 3, 0, 0, - 0, 50, 0, 0, 0, 5,115,101,108,102, 0, 0, 0, 0, 50, 0, 0, 0, 6,105, -100,101,110,116, 0, 0, 0, 0, 50, 0, 0, 0, 6, 99,108,111,115,101, 0, 0, - 0, 0, 9, 2, 0, 0, 0, 6,105,100,101,110,116, 0, 2, 0, 0, 0, 6, 99, -108,111,115,101, 0, 2, 0, 0, 0, 6,112,114,105,110,116, 0, 2, 0, 0, 0, - 10, 86,101,114, 98, 97,116,105,109,123, 0, 2, 0, 0, 0, 10, 32,108,105,110, -101, 32, 61, 32, 39, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, 2, 0, 0, 0, - 5,108,105,110,101, 0, 2, 0, 0, 0, 3, 39, 44, 0, 2, 0, 0, 0, 2,125, - 0, 2, 0, 0, 0, 10, 95, 86,101,114, 98, 97,116,105,109, 0, 4, 0, 0, 0, - 58, 0, 0, 0, 14, 64,118,101,114, 98, 97,116,105,109, 46,108,117, 97, 0, 0, - 0, 0, 40, 4, 1, 60, 59, 13, 0, 11, 1, 15, 2, 26, 60, 60, 15, 3, 13, 0, - 15, 4, 2, 0, 2, 60, 61, 15, 5, 13, 0, 2, 0, 1, 60, 62, 13, 0, 1, 1, - 60, 63, 0, 0, 0, 0, 1, 0, 0, 0, 58, 0, 0, 0, 2,116, 0, 0, 0, 0, - 6, 2, 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 6, 95, 98, 97,115,101, 0, 2, - 0, 0, 0, 14, 99,108, 97,115,115, 86,101,114, 98, 97,116,105,109, 0, 2, 0, - 0, 0, 7,115,101,116,116, 97,103, 0, 2, 0, 0, 0, 10,116,111,108,117, 97, - 95,116, 97,103, 0, 2, 0, 0, 0, 7, 97,112,112,101,110,100, 0, 2, 0, 0, - 0, 9, 86,101,114, 98, 97,116,105,109, 0, 4, 0, 0, 0, 67, 0, 0, 0, 14, - 64,118,101,114, 98, 97,116,105,109, 46,108,117, 97, 0, 0, 0, 0, 75, 8, 1, - 60, 68, 4, 0, 60, 69, 15, 2, 13, 0, 7, 1, 7, 1, 2, 1, 3, 11, 3, 32, - 52, 21, 60, 70, 7, 1, 23, 1, 60, 71, 15, 2, 13, 0, 7, 2, 2, 1, 2, 23, - 0, 50, 2, 60, 72, 60, 73, 15, 4, 22, 2, 60, 74, 11, 5, 13, 0, 11, 6, 60, - 75, 13, 1, 30, 1, 60, 76, 3, 2, 1, 60, 77, 0, 0, 0, 0, 2, 0, 0, 0, - 67, 0, 0, 0, 2,108, 0, 0, 0, 0, 68, 0, 0, 0, 2, 99, 0, 0, 0, 0, - 7, 2, 0, 0, 0, 2,108, 0, 2, 0, 0, 0, 2, 99, 0, 2, 0, 0, 0, 7, -115,116,114,115,117, 98, 0, 2, 0, 0, 0, 2, 36, 0, 2, 0, 0, 0, 10, 95, - 86,101,114, 98, 97,116,105,109, 0, 2, 0, 0, 0, 5,108,105,110,101, 0, 2, - 0, 0, 0, 5, 99,111,110,100, 0, -}; - -/* code.lo */ -static char B16[]={ - 27, 76,117, 97, 50, 0, 0, 0, 0, 0, 0, 0, 0, 10, 64, 99,111,100,101, 46, -108,117, 97, 0, 0, 0, 0, 66, 5, 0, 60, 19, 22, 2, 60, 20, 11, 1, 11, 2, - 11, 3, 60, 21, 15, 4, 30, 1, 60, 22, 25, 0, 60, 23, 15, 5, 15, 0, 15, 6, - 2, 0, 2, 60, 26, 15, 0, 11, 7, 11, 8, 26, 60, 63, 15, 0, 11, 9, 11, 10, - 26, 60, 71, 11, 12, 25, 11, 60, 80, 11, 14, 25, 13, 0, 0, 0, 0, 0, 0, 0, - 0, 15, 2, 0, 0, 0, 10, 99,108, 97,115,115, 67,111,100,101, 0, 2, 0, 0, - 0, 5,116,101,120,116, 0, 2, 0, 0, 0, 1, 0, 2, 0, 0, 0, 6, 95, 98, - 97,115,101, 0, 2, 0, 0, 0, 13, 99,108, 97,115,115, 70,101, 97,116,117,114, -101, 0, 2, 0, 0, 0, 7,115,101,116,116, 97,103, 0, 2, 0, 0, 0, 10,116, -111,108,117, 97, 95,116, 97,103, 0, 2, 0, 0, 0, 9,114,101,103,105,115,116, -101,114, 0, 4, 0, 0, 0, 26, 0, 0, 0, 10, 64, 99,111,100,101, 46,108,117, - 97, 0, 0, 0, 0,239, 13, 1, 60, 27, 15, 1, 2, 1, 0, 60, 28, 15, 1, 2, - 1, 0, 60, 29, 15, 4, 13, 2, 11, 5, 2, 1, 2, 60, 30, 13, 3, 44, 52, 11, - 60, 31, 15, 6, 11, 7, 2, 0, 1, 50, 2, 60, 32, 60, 34, 15, 8, 13, 3, 13, - 0, 18, 10, 2, 0, 2, 60, 35, 15, 11, 13, 3, 2, 0, 1, 60, 36, 15, 12, 11, - 13, 13, 1, 42, 11, 14, 42, 13, 2, 42, 2, 0, 1, 60, 37, 15, 15, 13, 2, 2, - 0, 1, 60, 40, 15, 4, 13, 1, 11, 17, 2, 1, 2, 60, 41, 13, 4, 4, 0, 32, - 52, 11, 60, 42, 15, 6, 11, 7, 2, 0, 1, 50, 2, 60, 43, 60, 44, 15, 19, 13, - 4, 11, 20, 2, 1, 2, 60, 45, 15, 11, 13, 4, 2, 0, 1, 60, 46, 15, 15, 13, - 1, 2, 0, 1, 60, 48, 15, 21, 11, 22, 2, 0, 1, 60, 49, 15, 21, 11, 23, 2, - 0, 1, 60, 50, 22, 1, 11, 2, 7, 0, 30, 0, 60, 51, 15, 21, 15, 25, 13, 5, - 11, 26, 13, 6, 58, 27, 1, 60, 55, 2, 1, 3, 2, 0, 1, 60, 56, 15, 21, 11, - 28, 2, 0, 1, 60, 57, 15, 21, 11, 29, 2, 0, 1, 60, 58, 15, 21, 11, 30, 2, - 0, 1, 60, 59, 0, 0, 0, 0, 7, 0, 0, 0, 26, 0, 0, 0, 5,115,101,108, -102, 0, 0, 0, 0, 27, 0, 0, 0, 2,111, 0, 0, 0, 0, 28, 0, 0, 0, 2, -110, 0, 0, 0, 0, 29, 0, 0, 0, 2,102, 0, 0, 0, 0, 40, 0, 0, 0, 3, -102,112, 0, 0, 0, 0, 44, 0, 0, 0, 2,115, 0, 0, 0, 0, 50, 0, 0, 0, - 2,116, 0, 0, 0, 0, 31, 2, 0, 0, 0, 2,111, 0, 2, 0, 0, 0, 8,116, -109,112,110, 97,109,101, 0, 2, 0, 0, 0, 2,110, 0, 2, 0, 0, 0, 2,102, - 0, 2, 0, 0, 0, 9,111,112,101,110,102,105,108,101, 0, 2, 0, 0, 0, 2, -119, 0, 2, 0, 0, 0, 6,101,114,114,111,114, 0, 2, 0, 0, 0, 61, 10, 32, - 32, 32, 99, 97,110,110,111,116, 32,111,112,101,110, 32,116,101,109,112,111,114, - 97,114,121, 32,102,105,108,101, 32,116,111, 32,112,114,111, 99, 99,101,115,115, - 32,101,109, 98,101,100,100,101,100, 32, 76,117, 97, 32, 99,111,100,101, 0, 2, - 0, 0, 0, 6,119,114,105,116,101, 0, 2, 0, 0, 0, 5,115,101,108,102, 0, - 2, 0, 0, 0, 5,116,101,120,116, 0, 2, 0, 0, 0, 10, 99,108,111,115,101, -102,105,108,101, 0, 2, 0, 0, 0, 8,101,120,101, 99,117,116,101, 0, 2, 0, - 0, 0, 9,108,117, 97, 99, 32, 45,111, 32, 0, 2, 0, 0, 0, 2, 32, 0, 2, - 0, 0, 0, 7,114,101,109,111,118,101, 0, 2, 0, 0, 0, 3,102,112, 0, 2, - 0, 0, 0, 3,114, 98, 0, 2, 0, 0, 0, 2,115, 0, 2, 0, 0, 0, 5,114, -101, 97,100, 0, 2, 0, 0, 0, 3, 46, 42, 0, 2, 0, 0, 0, 7,111,117,116, -112,117,116, 0, 2, 0, 0, 0, 35, 10, 32,123, 32, 47, 42, 32, 98,101,103,105, -110, 32,101,109, 98,101,100,100,101,100, 32,108,117, 97, 32, 99,111,100,101, 32, - 42, 47, 10, 0, 2, 0, 0, 0, 35, 32, 32,115,116, 97,116,105, 99, 32,117,110, -115,105,103,110,101,100, 32, 99,104, 97,114, 32, 66, 91, 93, 32, 61, 32,123, 10, - 32, 32, 32, 0, 2, 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 5,103,115,117, 98, - 0, 2, 0, 0, 0, 4, 40, 46, 41, 0, 4, 0, 0, 0, 51, 0, 0, 0, 10, 64, - 99,111,100,101, 46,108,117, 97, 0, 0, 0, 0, 61, 6, 1, 60, 52, 11, 2, 60, - 53, 12, 0, 11, 4, 12, 0, 18, 4, 7, 1, 37, 26, 12, 0, 18, 4, 7, 20, 32, - 52, 11, 12, 0, 11, 4, 7, 0, 26, 11, 5, 23, 1, 60, 54, 15, 6, 11, 7, 15, - 8, 13, 0, 2, 1, 1, 13, 1, 3, 2, 3, 60, 55, 0, 0, 0, 0, 2, 0, 0, - 0, 51, 0, 0, 0, 2, 99, 0, 0, 0, 0, 52, 0, 0, 0, 2,101, 0, 0, 0, - 0, 9, 2, 0, 0, 0, 2, 99, 0, 2, 0, 0, 0, 2,101, 0, 2, 0, 0, 0, - 1, 0, 2, 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 2,110, 0, 2, 0, 0, 0, - 5, 10, 32, 32, 32, 0, 2, 0, 0, 0, 7,102,111,114,109, 97,116, 0, 2, 0, - 0, 0, 7, 37, 51,117, 44, 37,115, 0, 2, 0, 0, 0, 8,115,116,114, 98,121, -116,101, 0, 2, 0, 0, 0, 6, 32, 32,125, 59, 10, 0, 2, 0, 0, 0, 56, 32, - 32,108,117, 97, 95,100,111, 98,117,102,102,101,114, 40, 66, 44,115,105,122,101, -111,102, 40, 66, 41, 44, 34,116,111,108,117, 97, 58, 32,101,109, 98,101,100,100, -101,100, 32, 76,117, 97, 32, 99,111,100,101, 34, 41, 59, 0, 2, 0, 0, 0, 36, - 32,125, 32, 47, 42, 32,101,110,100, 32,111,102, 32,101,109, 98,101,100,100,101, -100, 32,108,117, 97, 32, 99,111,100,101, 32, 42, 47, 10, 10, 0, 2, 0, 0, 0, - 6,112,114,105,110,116, 0, 4, 0, 0, 0, 63, 0, 0, 0, 10, 64, 99,111,100, -101, 46,108,117, 97, 0, 0, 0, 0, 52, 6, 3, 60, 64, 15, 2, 13, 1, 11, 3, - 42, 2, 0, 1, 60, 65, 15, 2, 13, 1, 11, 4, 42, 13, 0, 18, 6, 42, 11, 7, - 42, 2, 0, 1, 60, 66, 15, 2, 13, 1, 11, 8, 42, 13, 2, 42, 2, 0, 1, 60, - 67, 0, 0, 0, 0, 3, 0, 0, 0, 63, 0, 0, 0, 5,115,101,108,102, 0, 0, - 0, 0, 63, 0, 0, 0, 6,105,100,101,110,116, 0, 0, 0, 0, 63, 0, 0, 0, - 6, 99,108,111,115,101, 0, 0, 0, 0, 9, 2, 0, 0, 0, 6,105,100,101,110, -116, 0, 2, 0, 0, 0, 6, 99,108,111,115,101, 0, 2, 0, 0, 0, 6,112,114, -105,110,116, 0, 2, 0, 0, 0, 6, 67,111,100,101,123, 0, 2, 0, 0, 0, 11, - 32,116,101,120,116, 32, 61, 32, 91, 91, 0, 2, 0, 0, 0, 5,115,101,108,102, - 0, 2, 0, 0, 0, 5,116,101,120,116, 0, 2, 0, 0, 0, 4, 93, 93, 44, 0, - 2, 0, 0, 0, 2,125, 0, 2, 0, 0, 0, 6, 95, 67,111,100,101, 0, 4, 0, - 0, 0, 71, 0, 0, 0, 10, 64, 99,111,100,101, 46,108,117, 97, 0, 0, 0, 0, - 40, 4, 1, 60, 72, 13, 0, 11, 1, 15, 2, 26, 60, 73, 15, 3, 13, 0, 15, 4, - 2, 0, 2, 60, 74, 15, 5, 13, 0, 2, 0, 1, 60, 75, 13, 0, 1, 1, 60, 76, - 0, 0, 0, 0, 1, 0, 0, 0, 71, 0, 0, 0, 2,116, 0, 0, 0, 0, 6, 2, - 0, 0, 0, 2,116, 0, 2, 0, 0, 0, 6, 95, 98, 97,115,101, 0, 2, 0, 0, - 0, 10, 99,108, 97,115,115, 67,111,100,101, 0, 2, 0, 0, 0, 7,115,101,116, -116, 97,103, 0, 2, 0, 0, 0, 10,116,111,108,117, 97, 95,116, 97,103, 0, 2, - 0, 0, 0, 7, 97,112,112,101,110,100, 0, 2, 0, 0, 0, 5, 67,111,100,101, - 0, 4, 0, 0, 0, 80, 0, 0, 0, 10, 64, 99,111,100,101, 46,108,117, 97, 0, - 0, 0, 0, 24, 5, 1, 60, 81, 15, 1, 22, 1, 60, 82, 11, 2, 13, 0, 30, 0, - 60, 83, 3, 1, 1, 60, 84, 0, 0, 0, 0, 1, 0, 0, 0, 80, 0, 0, 0, 2, -108, 0, 0, 0, 0, 3, 2, 0, 0, 0, 2,108, 0, 2, 0, 0, 0, 6, 95, 67, -111,100,101, 0, 2, 0, 0, 0, 5,116,101,120,116, 0, -}; - -/* doit.lo */ -static char B17[]={ - 27, 76,117, 97, 50, 0, 0, 0, 0, 0, 0, 0, 0, 10, 64,100,111,105,116, 46, -108,117, 97, 0, 0, 0, 1, 92, 6, 0, 60, 17, 15, 0, 18, 1, 52, 38, 60, 18, - 15, 4, 15, 0, 18, 1, 2, 2, 1, 60, 19, 13, 0, 44, 52, 14, 60, 20, 15, 5, - 11, 6, 13, 1, 42, 2, 0, 1, 50, 2, 60, 21, 5, 2, 50, 2, 60, 22, 60, 25, - 15, 0, 18, 7, 44, 52, 43, 60, 26, 15, 0, 18, 1, 52, 22, 60, 27, 15, 0, 11, - 7, 15, 8, 15, 0, 18, 1, 11, 9, 11, 10, 2, 1, 3, 26, 50, 11, 60, 29, 15, - 5, 11, 11, 2, 0, 1, 60, 30, 50, 2, 60, 31, 60, 33, 15, 13, 15, 0, 18, 7, - 2, 1, 1, 60, 35, 15, 0, 18, 1, 52, 9, 60, 36, 15, 4, 2, 0, 0, 50, 2, - 60, 37, 60, 39, 15, 0, 18, 12, 52, 4, 60, 41, 1, 1, 60, 43, 15, 0, 18, 14, - 52, 38, 60, 44, 15, 15, 15, 0, 18, 14, 2, 2, 1, 60, 45, 13, 1, 44, 52, 14, - 60, 46, 15, 5, 11, 6, 13, 2, 42, 2, 0, 1, 50, 2, 60, 47, 5, 2, 50, 2, - 60, 48, 60, 50, 15, 0, 18, 16, 52, 11, 60, 51, 13, 0, 20, 17, 2, 0, 1, 50, - 38, 60, 53, 13, 0, 20, 18, 2, 0, 1, 60, 54, 13, 0, 20, 19, 2, 0, 1, 60, - 55, 13, 0, 20, 20, 2, 0, 1, 60, 56, 13, 0, 20, 21, 2, 0, 1, 60, 57, 60, - 59, 15, 0, 18, 14, 52, 9, 60, 60, 15, 15, 2, 0, 0, 50, 2, 60, 61, 60, 64, - 15, 0, 18, 16, 44, 52, 66, 60, 65, 15, 0, 18, 22, 52, 54, 60, 66, 15, 15, 15, - 0, 18, 22, 2, 2, 1, 60, 67, 13, 1, 44, 52, 14, 60, 68, 15, 5, 11, 6, 13, - 2, 42, 2, 0, 1, 50, 2, 60, 69, 60, 70, 13, 0, 20, 23, 2, 0, 1, 60, 71, - 15, 15, 2, 0, 0, 5, 2, 50, 2, 60, 72, 50, 2, 60, 73, 0, 0, 0, 0, 0, - 0, 0, 0, 24, 2, 0, 0, 0, 6,102,108, 97,103,115, 0, 2, 0, 0, 0, 2, -102, 0, 2, 0, 0, 0, 3,115,116, 0, 2, 0, 0, 0, 4,109,115,103, 0, 2, - 0, 0, 0, 9,114,101, 97,100,102,114,111,109, 0, 2, 0, 0, 0, 6,101,114, -114,111,114, 0, 2, 0, 0, 0, 2, 35, 0, 2, 0, 0, 0, 2,110, 0, 2, 0, - 0, 0, 5,103,115,117, 98, 0, 2, 0, 0, 0, 5, 37, 46, 46, 42, 0, 2, 0, - 0, 0, 1, 0, 2, 0, 0, 0, 41, 35,110,111, 32,112, 97, 99,107, 97,103,101, - 32,110, 97,109,101, 32,110,111,114, 32,105,110,112,117,116, 32,102,105,108,101, - 32,112,114,111,118,105,100,101,100, 0, 2, 0, 0, 0, 2,112, 0, 2, 0, 0, - 0, 8, 80, 97, 99,107, 97,103,101, 0, 2, 0, 0, 0, 2,111, 0, 2, 0, 0, - 0, 8,119,114,105,116,101,116,111, 0, 2, 0, 0, 0, 2, 80, 0, 2, 0, 0, - 0, 6,112,114,105,110,116, 0, 2, 0, 0, 0, 9,112,114,101, 97,109, 98,108, -101, 0, 2, 0, 0, 0, 8,115,117,112, 99,111,100,101, 0, 2, 0, 0, 0, 9, -114,101,103,105,115,116,101,114, 0, 2, 0, 0, 0, 11,117,110,114,101,103,105, -115,116,101,114, 0, 2, 0, 0, 0, 2, 72, 0, 2, 0, 0, 0, 7,104,101, 97, -100,101,114, 0, -}; - - lua_dobuffer(B1,sizeof(B1),"basic.lo"); - lua_dobuffer(B2,sizeof(B2),"feature.lo"); - lua_dobuffer(B3,sizeof(B3),"declaration.lo"); - lua_dobuffer(B4,sizeof(B4),"container.lo"); - lua_dobuffer(B5,sizeof(B5),"package.lo"); - lua_dobuffer(B6,sizeof(B6),"module.lo"); - lua_dobuffer(B7,sizeof(B7),"class.lo"); - lua_dobuffer(B8,sizeof(B8),"typedef.lo"); - lua_dobuffer(B9,sizeof(B9),"define.lo"); - lua_dobuffer(B10,sizeof(B10),"enumerate.lo"); - lua_dobuffer(B11,sizeof(B11),"variable.lo"); - lua_dobuffer(B12,sizeof(B12),"array.lo"); - lua_dobuffer(B13,sizeof(B13),"function.lo"); - lua_dobuffer(B14,sizeof(B14),"operator.lo"); - lua_dobuffer(B15,sizeof(B15),"verbatim.lo"); - lua_dobuffer(B16,sizeof(B16),"code.lo"); - lua_dobuffer(B17,sizeof(B17),"doit.lo"); -} diff --git a/src/lua/tolualua.pkg b/src/lua/tolualua.pkg deleted file mode 100644 index 1694c2c1..00000000 --- a/src/lua/tolualua.pkg +++ /dev/null @@ -1,21 +0,0 @@ -$[ -$ -$ -$ -$ -$ -$ -$ -$ -$ -$ -$ -$ -$ -$ -$ -$ -$ -$ -$] - diff --git a/src/lua/typedef.lua b/src/lua/typedef.lua deleted file mode 100644 index 1633f3e6..00000000 --- a/src/lua/typedef.lua +++ /dev/null @@ -1,59 +0,0 @@ --- tolua: typedef class --- Written by Waldemar Celes --- TeCGraf/PUC-Rio --- Jul 1998 --- $Id: typedef.lua,v 1.2 2001/11/26 23:00:27 darkgod Exp $ - --- This code is free software; you can redistribute it and/or modify it. --- The software provided hereunder is on an "as is" basis, and --- the author has no obligation to provide maintenance, support, updates, --- enhancements, or modifications. - - - --- Typedef class --- Represents a type synonym. --- The 'de facto' type replaces the typedef before the --- remaining code is parsed. --- The following fields are stored: --- utype = typedef name --- type = 'de facto' type --- mod = modifiers to the 'de facto' type -classTypedef = { - utype = '', - mod = '', - type = '' -} - --- Print method -function classTypedef:print (ident,close) - print(ident.."Typedef{") - print(ident.." utype = '"..self.utype.."',") - print(ident.." mod = '"..self.mod.."',") - print(ident.." type = '"..self.type.."',") - print(ident.."}"..close) -end - --- Internal constructor -function _Typedef (t) - t._base = classTypedef - settag(t,tolua_tag) - appendtypedef(t) - return t -end - --- Constructor --- Expects one string representing the type definition. -function Typedef (s) - if strfind(s,'[%*&]') then - tolua_error("#invalid typedef: pointers (and references) are not supported") - end - local t = split(gsub(s,"%s%s*"," ")," ") - return _Typedef { - utype = t[t.n], - type = t[t.n-1], - mod = concat(t,1,t.n-2) - } -end - - diff --git a/src/lua/variable.lua b/src/lua/variable.lua deleted file mode 100644 index 310808b8..00000000 --- a/src/lua/variable.lua +++ /dev/null @@ -1,192 +0,0 @@ --- tolua: variable class --- Written by Waldemar Celes --- TeCGraf/PUC-Rio --- Jul 1998 --- $Id: variable.lua,v 1.4 2004/06/04 13:42:10 neil Exp $ - --- This code is free software; you can redistribute it and/or modify it. --- The software provided hereunder is on an "as is" basis, and --- the author has no obligation to provide maintenance, support, updates, --- enhancements, or modifications. - - --- Variable class --- Represents a extern variable or a public member of a class. --- Stores all fields present in a declaration. -classVariable = { - _base = classDeclaration, -} - -settag(classVariable,tolua_tag) - --- Print method -function classVariable:print (ident,close) - print(ident.."Variable{") - print(ident.." mod = '"..self.mod.."',") - print(ident.." type = '"..self.type.."',") - print(ident.." ptr = '"..self.ptr.."',") - print(ident.." name = '"..self.name.."',") - print(ident.." def = '"..self.def.."',") - print(ident.." ret = '"..self.ret.."',") - print(ident.."}"..close) -end - --- get variable value -function classVariable:getvalue (class,static) - if class and static then - return class..'::'..self.name - elseif class then - return 'self->'..self.name - else - return self.name - end -end - --- Write binding functions -function classVariable:supcode () - local class = self:inclass() - - -- get function ------------------------------------------------ - if class then - output("/* get function:",self.name," of class ",class," */") - else - output("/* get function:",self.name," */") - end - self.cgetname = self:cfuncname("toluaI_get") - output("static int",self.cgetname,"(lua_State* tolua_S)") - output("{") - - -- declare self, if the case - local _,_,static = strfind(self.mod,'^%s*(static)') - if class and static==nil then - output(' ',class,'*','self = ') - output('(',class,'*) ') - output('tolua_getusertype(tolua_S,1,0);') - elseif static then - _,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)') - end - - - -- check self value - if class and static==nil then - output(' if (!self) TOLUA_ERR_SELF;'); - end - - -- return value - local t,ct = isbasic(self.type) - if t then - output(' tolua_push'..t..'(tolua_S,(',ct,')'..self:getvalue(class,static)..');') - else - if self.ptr == '&' or self.ptr == '' then - output(' tolua_pushusertype(tolua_S,(void*)&'..self:getvalue(class,static)..',',self.tag,');') - else - output(' tolua_pushusertype(tolua_S,(void*)'..self:getvalue(class,static)..',',self.tag,');') - end - end - output(' return 1;') - output('}') - output('\n') - - -- set function ------------------------------------------------ - if not strfind(self.mod,'const') then - if class then - output("/* set function:",self.name," of class ",class," */") - else - output("/* set function:",self.name," */") - end - self.csetname = self:cfuncname("toluaI_set") - output("static int",self.csetname,"(lua_State* tolua_S)") - output("{") - - -- declare self, if the case - local narg=1 - if class and static==nil then - output(' ',class,'*','self = ') - output('(',class,'*) ') - output('tolua_getusertype(tolua_S,1,0);') - -- check self value - output(' if (!self) TOLUA_ERR_SELF;'); - narg = narg+1 - elseif static then - _,_,self.mod = strfind(self.mod,'^%s*static%s%s*(.*)') - narg = narg+1 - end - - -- check type - output(' if (!'..self:outchecktype(narg)..')') - output(' TOLUA_ERR_ASSIGN;') - - -- assign value - local ptr = '' - if self.ptr~='' then ptr = '*' end - output(' ') - if class and static then - output(class..'::'..self.name) - elseif class then - output('self->'..self.name) - else - output(self.name) - end - local t = isbasic(self.type) - output(' = ') - if not t and ptr=='' then output('*') end - output('((',self.mod,self.type) - if not t then - output('*') - end - output(') ') - local def = 0 - if self.def ~= '' then def = self.def end - if t then - output('tolua_get'..t,'(tolua_S,',narg,',',def,'));') - else - output('tolua_getusertype(tolua_S,',narg,',',def,'));') - end - output(' return 0;') - output('}') - output('\n') - end - -end - -function classVariable:register () - local parent = self:inclass() or self:inmodule() - if parent then - if self.csetname then - output(' tolua_tablevar(tolua_S,"'..parent..'","'..self.lname..'",'..self.cgetname..','..self.csetname..');') - else - output(' tolua_tablevar(tolua_S,"'..parent..'","'..self.lname..'",'..self.cgetname..',NULL);') - end - else - if self.csetname then - output(' tolua_globalvar(tolua_S,"'..self.lname..'",'..self.cgetname..','..self.csetname..');') - else - output(' tolua_globalvar(tolua_S,"'..self.lname..'",'..self.cgetname..',NULL);') - end - end -end - -function classVariable:unregister () - if self:inclass()==nil and self:inmodule()==nil then - output(' lua_getglobals(tolua_S);') - output(' lua_pushstring(tolua_S,"',self.lname,'"); lua_pushnil(tolua_S); lua_rawset(tolua_S,-3);') - output(' lua_pop(tolua_S,1);') - end -end - - --- Internal constructor -function _Variable (t) - t._base = classVariable - settag(t,tolua_tag) - append(t) - return t -end - --- Constructor --- Expects a string representing the variable declaration. -function Variable (s) - return _Variable (Declaration(s,'var')) -end - - diff --git a/src/lua/verbatim.lua b/src/lua/verbatim.lua deleted file mode 100644 index 9dae0dc3..00000000 --- a/src/lua/verbatim.lua +++ /dev/null @@ -1,77 +0,0 @@ --- tolua: verbatim class --- Written by Waldemar Celes --- TeCGraf/PUC-Rio --- Jul 1998 --- $Id: verbatim.lua,v 1.2 2001/11/26 23:00:27 darkgod Exp $ - --- This code is free software; you can redistribute it and/or modify it. --- The software provided hereunder is on an "as is" basis, and --- the author has no obligation to provide maintenance, support, updates, --- enhancements, or modifications. - - - --- Verbatim class --- Represents a line translated directed to the binding file. --- The following filds are stored: --- line = line text -classVerbatim = { - line = '', - _base = classFeature, -} -settag(classVerbatim,tolua_tag) - --- preamble verbatim -function classVerbatim:preamble () - if not self.cond then - write(self.line) - end -end - --- support code -function classVerbatim:supcode () - if self.cond then - write(self.line) - write('\n') - end -end - --- register code -function classVerbatim:register () - if self.cond then - write(self.line) - end -end - - --- Print method -function classVerbatim:print (ident,close) - print(ident.."Verbatim{") - print(ident.." line = '"..self.line.."',") - print(ident.."}"..close) -end - - --- Internal constructor -function _Verbatim (t) - t._base = classVerbatim - settag(t,tolua_tag) - append(t) - return t -end - --- Constructor --- Expects a string representing the text line -function Verbatim (l) - local c - if strsub(l,1,1) == '$' then - c = 1 - l = strsub(l,2) - end - return _Verbatim { - line = l, - cond = c - } -end - - diff --git a/src/lua_bind.c b/src/lua_bind.c index 3d9038d1..076404cf 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -13,10 +13,6 @@ #include "angband.h" #include -#include "lua.h" -#include "tolua.h" -extern lua_State *L; - s16b can_spell_random(s16b spell_idx) { return spell_at(spell_idx)->random_type; diff --git a/src/main.c b/src/main.c index 48ab3f04..8dc87a2a 100644 --- a/src/main.c +++ b/src/main.c @@ -397,7 +397,8 @@ int main(int argc, char *argv[]) char *s; int j; - init_lua(); + init_lua_init(); + for (j = i + 1; j < argc; j++) { s = argv[j]; diff --git a/src/modules.c b/src/modules.c index 9376cc3d..60128f79 100644 --- a/src/modules.c +++ b/src/modules.c @@ -202,9 +202,6 @@ bool_ select_module() { s32b k, sel, max; - /* Init some lua */ - init_lua(); - /* How many modules? */ max = MAX_MODULES; diff --git a/src/monster.pkg b/src/monster.pkg deleted file mode 100644 index bf0f4661..00000000 --- a/src/monster.pkg +++ /dev/null @@ -1,2301 +0,0 @@ -/* File: monster.pkg */ - -/* - * Purpose: Lua interface defitions for monsters. - * To be processed by tolua to generate C source code. - */ - -$#include "angband.h" - -/** @typedef cptr - * @note String - */ -typedef char* cptr; -/** @typedef errr - * @note Number - */ -typedef int errr; -/** @typedef bool - * @note Boolean - */ -typedef unsigned char bool; -/** @typedef byte - * @note Number - */ -typedef unsigned char byte; -/** @typedef s16b - * @note Number - */ -typedef signed short s16b; -/** @typedef u16b - * @note Number - */ -typedef unsigned short u16b; -/** @typedef s32b - * @note Number - */ -typedef signed int s32b; -/** @typedef u32b - * @note Number - */ -typedef unsigned int u32b; - -/* To make easy object creations */ -$static monster_type lua_monster_forge; -/** @var monster_forge; - * @brief monster_type - */ -static monster_type lua_monster_forge @ monster_forge; - -/** @name Monster status - * @note Player POV - * @{ */ -/** @def MSTATUS_ENEMY */ -#define MSTATUS_ENEMY -2 - -/** @def MSTATUS_NEUTRAL_M */ -#define MSTATUS_NEUTRAL_M -1 - -/** @def MSTATUS_NEUTRAL */ -#define MSTATUS_NEUTRAL 0 - -/** @def MSTATUS_NEUTRAL_P */ -#define MSTATUS_NEUTRAL_P 1 - -/** @def MSTATUS_FRIEND */ -#define MSTATUS_FRIEND 2 - -/** @def MSTATUS_PET */ -#define MSTATUS_PET 3 - -/** @def MSTATUS_COMPANION */ -#define MSTATUS_COMPANION 4 -/** @} */ - -/** @name Race flags #1 - * @{ */ -/** @def RF1_UNIQUE - * @note Unique Monster - */ -#define RF1_UNIQUE 0x00000001 -/** @def RF1_QUESTOR - * @note Quest Monster - */ -#define RF1_QUESTOR 0x00000002 -/** @def RF1_MALE - * @note Male gender - */ -#define RF1_MALE 0x00000004 -/** @def RF1_FEMALE - * @note Female gender - */ -#define RF1_FEMALE 0x00000008 -/** @def RF1_CHAR_CLEAR - * @note Absorbs symbol - */ -#define RF1_CHAR_CLEAR 0x00000010 -/** @def RF1_CHAR_MULTI - * @note Changes symbol - */ -#define RF1_CHAR_MULTI 0x00000020 -/** @def RF1_ATTR_CLEAR - * @note Absorbs color - */ -#define RF1_ATTR_CLEAR 0x00000040 -/** @def RF1_ATTR_MULTI - * @note Changes color - */ -#define RF1_ATTR_MULTI 0x00000080 -/** @def RF1_FORCE_DEPTH - * @note Start at "correct" depth - */ -#define RF1_FORCE_DEPTH 0x00000100 -/** @def RF1_FORCE_MAXHP - * @note Start with max hitpoints - */ -#define RF1_FORCE_MAXHP 0x00000200 -/** @def RF1_FORCE_SLEEP - * @note Start out sleeping - */ -#define RF1_FORCE_SLEEP 0x00000400 -/** @def RF1_FORCE_EXTRA - * @note Start out something - */ -#define RF1_FORCE_EXTRA 0x00000800 -/** @def RF1_FRIEND - * @note Arrive with a friend - */ -#define RF1_FRIEND 0x00001000 -/** @def RF1_FRIENDS - * @note Arrive with some friends - */ -#define RF1_FRIENDS 0x00002000 -/** @def RF1_ESCORT - * @note Arrive with an escort - */ -#define RF1_ESCORT 0x00004000 -/** @def RF1_ESCORTS - * @note Arrive with some escorts - */ -#define RF1_ESCORTS 0x00008000 -/** @def RF1_NEVER_BLOW - * @note Never make physical blow - */ -#define RF1_NEVER_BLOW 0x00010000 -/** @def RF1_NEVER_MOVE - * @note Never make physical move - */ -#define RF1_NEVER_MOVE 0x00020000 -/** @def RF1_RAND_25 - * @note Moves randomly (25%) - */ -#define RF1_RAND_25 0x00040000 -/** @def RF1_RAND_50 - * @note Moves randomly (50%) - */ -#define RF1_RAND_50 0x00080000 -/** @def RF1_ONLY_GOLD - * @note Drop only gold - */ -#define RF1_ONLY_GOLD 0x00100000 -/** @def RF1_ONLY_ITEM - * @note Drop only items - */ -#define RF1_ONLY_ITEM 0x00200000 -/** @def RF1_DROP_60 - * @note Drop an item/gold (60%) - */ -#define RF1_DROP_60 0x00400000 -/** @def RF1_DROP_90 - * @note Drop an item/gold (90%) - */ -#define RF1_DROP_90 0x00800000 -/** @def RF1_DROP_1D2 - * @note Drop 1d2 items/gold - */ -#define RF1_DROP_1D2 0x01000000 -/** @def RF1_DROP_2D2 - * @note Drop 2d2 items/gold - */ -#define RF1_DROP_2D2 0x02000000 -/** @def RF1_DROP_3D2 - * @note Drop 3d2 items/gold - */ -#define RF1_DROP_3D2 0x04000000 -/** @def RF1_DROP_4D2 - * @note Drop 4d2 items/gold - */ -#define RF1_DROP_4D2 0x08000000 -/** @def RF1_DROP_GOOD - * @note Drop good items - */ -#define RF1_DROP_GOOD 0x10000000 -/** @def RF1_DROP_GREAT - * @note Drop great items - */ -#define RF1_DROP_GREAT 0x20000000 -/** @def RF1_DROP_USEFUL - * @note Drop "useful" items - */ -#define RF1_DROP_USEFUL 0x40000000 -/** @def RF1_DROP_CHOSEN - * @note Drop "chosen" items - */ -#define RF1_DROP_CHOSEN 0x80000000 -/** @} */ - -/** @name Race flags #2 - * @note New monster race bit flags - * @{ */ -/** @def RF2_STUPID - * @note Monster is stupid - */ -#define RF2_STUPID 0x00000001 -/** @def RF2_SMART - * @note Monster is smart - */ -#define RF2_SMART 0x00000002 -/** @def RF2_CAN_SPEAK - * @note TY: can speak - */ -#define RF2_CAN_SPEAK 0x00000004 -/** @def RF2_REFLECTING - * @note Reflects bolts - */ -#define RF2_REFLECTING 0x00000008 -/** @def RF2_INVISIBLE - * @note Monster avoids vision - */ -#define RF2_INVISIBLE 0x00000010 -/** @def RF2_COLD_BLOOD - * @note Monster avoids infra - */ -#define RF2_COLD_BLOOD 0x00000020 -/** @def RF2_EMPTY_MIND - * @note Monster avoids telepathy - */ -#define RF2_EMPTY_MIND 0x00000040 -/** @def RF2_WEIRD_MIND - * @note Monster avoids telepathy? - */ -#define RF2_WEIRD_MIND 0x00000080 -/** @def RF2_DEATH_ORB - * @note Death Orb - */ -#define RF2_DEATH_ORB 0x00000100 -/** @def RF2_REGENERATE - * @note Monster regenerates - */ -#define RF2_REGENERATE 0x00000200 -/** @def RF2_SHAPECHANGER - * @note TY: shapechanger - */ -#define RF2_SHAPECHANGER 0x00000400 -/** @def RF2_ATTR_ANY - * @note TY: Attr_any - */ -#define RF2_ATTR_ANY 0x00000800 -/** @def RF2_POWERFUL - * @note Monster has strong breath - */ -#define RF2_POWERFUL 0x00001000 -/** @def RF2_ELDRITCH_HORROR - * @note Sanity-blasting horror - */ -#define RF2_ELDRITCH_HORROR 0x00002000 -/** @def RF2_AURA_FIRE - * @note Burns in melee - */ -#define RF2_AURA_FIRE 0x00004000 -/** @def RF2_AURA_ELEC - * @note Shocks in melee - */ -#define RF2_AURA_ELEC 0x00008000 -/** @def RF2_OPEN_DOOR - * @note Monster can open doors - */ -#define RF2_OPEN_DOOR 0x00010000 -/** @def RF2_BASH_DOOR - * @note Monster can bash doors - */ -#define RF2_BASH_DOOR 0x00020000 -/** @def RF2_PASS_WALL - * @note Monster can pass walls - */ -#define RF2_PASS_WALL 0x00040000 -/** @def RF2_KILL_WALL - * @note Monster can destroy walls - */ -#define RF2_KILL_WALL 0x00080000 -/** @def RF2_MOVE_BODY - * @note Monster can move monsters - */ -#define RF2_MOVE_BODY 0x00100000 -/** @def RF2_KILL_BODY - * @note Monster can kill monsters - */ -#define RF2_KILL_BODY 0x00200000 -/** @def RF2_TAKE_ITEM - * @note Monster can pick up items - */ -#define RF2_TAKE_ITEM 0x00400000 -/** @def RF2_KILL_ITEM - * @note Monster can crush items - */ -#define RF2_KILL_ITEM 0x00800000 -/** @def RF2_BRAIN_1 */ -#define RF2_BRAIN_1 0x01000000 - -/** @def RF2_BRAIN_2 */ -#define RF2_BRAIN_2 0x02000000 - -/** @def RF2_BRAIN_3 */ -#define RF2_BRAIN_3 0x04000000 - -/** @def RF2_BRAIN_4 */ -#define RF2_BRAIN_4 0x08000000 - -/** @def RF2_BRAIN_5 */ -#define RF2_BRAIN_5 0x10000000 - -/** @def RF2_BRAIN_6 */ -#define RF2_BRAIN_6 0x20000000 - -/** @def RF2_BRAIN_7 */ -#define RF2_BRAIN_7 0x40000000 - -/** @def RF2_BRAIN_8 */ -#define RF2_BRAIN_8 0x80000000 -/** @} */ - -/** @name Race flags #3 - * @note New monster race bit flags - * @{ */ -/** @def RF3_ORC - * @note Orc - */ -#define RF3_ORC 0x00000001 -/** @def RF3_TROLL - * @note Troll - */ -#define RF3_TROLL 0x00000002 -/** @def RF3_GIANT - * @note Giant - */ -#define RF3_GIANT 0x00000004 -/** @def RF3_DRAGON - * @note Dragon - */ -#define RF3_DRAGON 0x00000008 -/** @def RF3_DEMON - * @note Demon - */ -#define RF3_DEMON 0x00000010 -/** @def RF3_UNDEAD - * @note Undead - */ -#define RF3_UNDEAD 0x00000020 -/** @def RF3_EVIL - * @note Evil - */ -#define RF3_EVIL 0x00000040 -/** @def RF3_ANIMAL - * @note Animal - */ -#define RF3_ANIMAL 0x00000080 -/** @def RF3_THUNDERLORD - * @note DG: Thunderlord - */ -#define RF3_THUNDERLORD 0x00000100 -/** @def RF3_GOOD - * @note Good - */ -#define RF3_GOOD 0x00000200 -/** @def RF3_AURA_COLD - * @note Freezes in melee - */ -#define RF3_AURA_COLD 0x00000400 -/** @def RF3_NONLIVING - * @note TY: Non-Living (?) - */ -#define RF3_NONLIVING 0x00000800 -/** @def RF3_HURT_LITE - * @note Hurt by lite - */ -#define RF3_HURT_LITE 0x00001000 -/** @def RF3_HURT_ROCK - * @note Hurt by rock remover - */ -#define RF3_HURT_ROCK 0x00002000 -/** @def RF3_SUSCEP_FIRE - * @note Hurt badly by fire - */ -#define RF3_SUSCEP_FIRE 0x00004000 -/** @def RF3_SUSCEP_COLD - * @note Hurt badly by cold - */ -#define RF3_SUSCEP_COLD 0x00008000 -/** @def RF3_IM_ACID - * @note Resist acid a lot - */ -#define RF3_IM_ACID 0x00010000 -/** @def RF3_IM_ELEC - * @note Resist elec a lot - */ -#define RF3_IM_ELEC 0x00020000 -/** @def RF3_IM_FIRE - * @note Resist fire a lot - */ -#define RF3_IM_FIRE 0x00040000 -/** @def RF3_IM_COLD - * @note Resist cold a lot - */ -#define RF3_IM_COLD 0x00080000 -/** @def RF3_IM_POIS - * @note Resist poison a lot - */ -#define RF3_IM_POIS 0x00100000 -/** @def RF3_RES_TELE - * @note Resist teleportation - */ -#define RF3_RES_TELE 0x00200000 -/** @def RF3_RES_NETH - * @note Resist nether a lot - */ -#define RF3_RES_NETH 0x00400000 -/** @def RF3_RES_WATE - * @note Resist water - */ -#define RF3_RES_WATE 0x00800000 -/** @def RF3_RES_PLAS - * @note Resist plasma - */ -#define RF3_RES_PLAS 0x01000000 -/** @def RF3_RES_NEXU - * @note Resist nexus - */ -#define RF3_RES_NEXU 0x02000000 -/** @def RF3_RES_DISE - * @note Resist disenchantment - */ -#define RF3_RES_DISE 0x04000000 -/** @def RF3_UNIQUE_4 - * @note Is a "Nazgul" unique - */ -#define RF3_UNIQUE_4 0x08000000 -/** @def RF3_NO_FEAR - * @note Cannot be scared - */ -#define RF3_NO_FEAR 0x10000000 -/** @def RF3_NO_STUN - * @note Cannot be stunned - */ -#define RF3_NO_STUN 0x20000000 -/** @def RF3_NO_CONF - * @note Cannot be confused - */ -#define RF3_NO_CONF 0x40000000 -/** @def RF3_NO_SLEEP - * @note Cannot be slept - */ -#define RF3_NO_SLEEP 0x80000000 -/** @} */ - -/** @name Race flags #4 - * @note New monster race bit flags - * @{ */ -/** @def RF4_SHRIEK - * @note Shriek for help - */ -#define RF4_SHRIEK 0x00000001 -/** @def RF4_MULTIPLY - * @note Monster reproduces - */ -#define RF4_MULTIPLY 0x00000002 -/** @def RF4_S_ANIMAL - * @note Summon animals - */ -#define RF4_S_ANIMAL 0x00000004 -/** @def RF4_ROCKET - * @note TY: Rocket - */ -#define RF4_ROCKET 0x00000008 -/** @def RF4_ARROW_1 - * @note Fire an arrow (light) - */ -#define RF4_ARROW_1 0x00000010 -/** @def RF4_ARROW_2 - * @note Fire an arrow (heavy) - */ -#define RF4_ARROW_2 0x00000020 -/** @def RF4_ARROW_3 - * @note Fire missiles (light) - */ -#define RF4_ARROW_3 0x00000040 -/** @def RF4_ARROW_4 - * @note Fire missiles (heavy) - */ -#define RF4_ARROW_4 0x00000080 -/** @def RF4_BR_ACID - * @note Breathe Acid - */ -#define RF4_BR_ACID 0x00000100 -/** @def RF4_BR_ELEC - * @note Breathe Elec - */ -#define RF4_BR_ELEC 0x00000200 -/** @def RF4_BR_FIRE - * @note Breathe Fire - */ -#define RF4_BR_FIRE 0x00000400 -/** @def RF4_BR_COLD - * @note Breathe Cold - */ -#define RF4_BR_COLD 0x00000800 -/** @def RF4_BR_POIS - * @note Breathe Poison - */ -#define RF4_BR_POIS 0x00001000 -/** @def RF4_BR_NETH - * @note Breathe Nether - */ -#define RF4_BR_NETH 0x00002000 -/** @def RF4_BR_LITE - * @note Breathe Lite - */ -#define RF4_BR_LITE 0x00004000 -/** @def RF4_BR_DARK - * @note Breathe Dark - */ -#define RF4_BR_DARK 0x00008000 -/** @def RF4_BR_CONF - * @note Breathe Confusion - */ -#define RF4_BR_CONF 0x00010000 -/** @def RF4_BR_SOUN - * @note Breathe Sound - */ -#define RF4_BR_SOUN 0x00020000 -/** @def RF4_BR_CHAO - * @note Breathe Chaos - */ -#define RF4_BR_CHAO 0x00040000 -/** @def RF4_BR_DISE - * @note Breathe Disenchant - */ -#define RF4_BR_DISE 0x00080000 -/** @def RF4_BR_NEXU - * @note Breathe Nexus - */ -#define RF4_BR_NEXU 0x00100000 -/** @def RF4_BR_TIME - * @note Breathe Time - */ -#define RF4_BR_TIME 0x00200000 -/** @def RF4_BR_INER - * @note Breathe Inertia - */ -#define RF4_BR_INER 0x00400000 -/** @def RF4_BR_GRAV - * @note Breathe Gravity - */ -#define RF4_BR_GRAV 0x00800000 -/** @def RF4_BR_SHAR - * @note Breathe Shards - */ -#define RF4_BR_SHAR 0x01000000 -/** @def RF4_BR_PLAS - * @note Breathe Plasma - */ -#define RF4_BR_PLAS 0x02000000 -/** @def RF4_BR_WALL - * @note Breathe Force - */ -#define RF4_BR_WALL 0x04000000 -/** @def RF4_BR_MANA - * @note Breathe Mana - */ -#define RF4_BR_MANA 0x08000000 -/** @def RF4_BA_NUKE - * @note TY: Nuke Ball - */ -#define RF4_BA_NUKE 0x10000000 -/** @def RF4_BR_NUKE - * @note TY: Toxic Breath - */ -#define RF4_BR_NUKE 0x20000000 -/** @def RF4_BA_CHAO - * @note Chaos Ball - */ -#define RF4_BA_CHAO 0x40000000 -/** @def RF4_BR_DISI - * @note Breathe Disintegration - */ -#define RF4_BR_DISI 0x80000000 -/** @} */ - -/** @name Race flags #5 - * @note New monster race bit flags - * @{ */ -/** @def RF5_BA_ACID - * @note Acid Ball - */ -#define RF5_BA_ACID 0x00000001 -/** @def RF5_BA_ELEC - * @note Elec Ball - */ -#define RF5_BA_ELEC 0x00000002 -/** @def RF5_BA_FIRE - * @note Fire Ball - */ -#define RF5_BA_FIRE 0x00000004 -/** @def RF5_BA_COLD - * @note Cold Ball - */ -#define RF5_BA_COLD 0x00000008 -/** @def RF5_BA_POIS - * @note Poison Ball - */ -#define RF5_BA_POIS 0x00000010 -/** @def RF5_BA_NETH - * @note Nether Ball - */ -#define RF5_BA_NETH 0x00000020 -/** @def RF5_BA_WATE - * @note Water Ball - */ -#define RF5_BA_WATE 0x00000040 -/** @def RF5_BA_MANA - * @note Mana Storm - */ -#define RF5_BA_MANA 0x00000080 -/** @def RF5_BA_DARK - * @note Darkness Storm - */ -#define RF5_BA_DARK 0x00000100 -/** @def RF5_DRAIN_MANA - * @note Drain Mana - */ -#define RF5_DRAIN_MANA 0x00000200 -/** @def RF5_MIND_BLAST - * @note Blast Mind - */ -#define RF5_MIND_BLAST 0x00000400 -/** @def RF5_BRAIN_SMASH - * @note Smash Brain - */ -#define RF5_BRAIN_SMASH 0x00000800 -/** @def RF5_CAUSE_1 - * @note Cause Light Wound - */ -#define RF5_CAUSE_1 0x00001000 -/** @def RF5_CAUSE_2 - * @note Cause Serious Wound - */ -#define RF5_CAUSE_2 0x00002000 -/** @def RF5_CAUSE_3 - * @note Cause Critical Wound - */ -#define RF5_CAUSE_3 0x00004000 -/** @def RF5_CAUSE_4 - * @note Cause Mortal Wound - */ -#define RF5_CAUSE_4 0x00008000 -/** @def RF5_BO_ACID - * @note Acid Bolt - */ -#define RF5_BO_ACID 0x00010000 -/** @def RF5_BO_ELEC - * @note Elec Bolt (unused) - */ -#define RF5_BO_ELEC 0x00020000 -/** @def RF5_BO_FIRE - * @note Fire Bolt - */ -#define RF5_BO_FIRE 0x00040000 -/** @def RF5_BO_COLD - * @note Cold Bolt - */ -#define RF5_BO_COLD 0x00080000 -/** @def RF5_BO_POIS - * @note Poison Bolt (unused) - */ -#define RF5_BO_POIS 0x00100000 -/** @def RF5_BO_NETH - * @note Nether Bolt - */ -#define RF5_BO_NETH 0x00200000 -/** @def RF5_BO_WATE - * @note Water Bolt - */ -#define RF5_BO_WATE 0x00400000 -/** @def RF5_BO_MANA - * @note Mana Bolt - */ -#define RF5_BO_MANA 0x00800000 -/** @def RF5_BO_PLAS - * @note Plasma Bolt - */ -#define RF5_BO_PLAS 0x01000000 -/** @def RF5_BO_ICEE - * @note Ice Bolt - */ -#define RF5_BO_ICEE 0x02000000 -/** @def RF5_MISSILE - * @note Magic Missile - */ -#define RF5_MISSILE 0x04000000 -/** @def RF5_SCARE - * @note Frighten Player - */ -#define RF5_SCARE 0x08000000 -/** @def RF5_BLIND - * @note Blind Player - */ -#define RF5_BLIND 0x10000000 -/** @def RF5_CONF - * @note Confuse Player - */ -#define RF5_CONF 0x20000000 -/** @def RF5_SLOW - * @note Slow Player - */ -#define RF5_SLOW 0x40000000 -/** @def RF5_HOLD - * @note Paralyze Player - */ -#define RF5_HOLD 0x80000000 -/** @} */ - -/** @name Race flags #6 - * @note New monster race bit flags - * @{ */ -/** @def RF6_HASTE - * @note Speed self - */ -#define RF6_HASTE 0x00000001 -/** @def RF6_HAND_DOOM - * @note Hand of Doom - */ -#define RF6_HAND_DOOM 0x00000002 -/** @def RF6_HEAL - * @note Heal self - */ -#define RF6_HEAL 0x00000004 -/** @def RF6_S_ANIMALS - * @note Summon animals - */ -#define RF6_S_ANIMALS 0x00000008 -/** @def RF6_BLINK - * @note Teleport Short - */ -#define RF6_BLINK 0x00000010 -/** @def RF6_TPORT - * @note Teleport Long - */ -#define RF6_TPORT 0x00000020 -/** @def RF6_TELE_TO - * @note Move player to monster - */ -#define RF6_TELE_TO 0x00000040 -/** @def RF6_TELE_AWAY - * @note Move player far away - */ -#define RF6_TELE_AWAY 0x00000080 -/** @def RF6_TELE_LEVEL - * @note Move player vertically - */ -#define RF6_TELE_LEVEL 0x00000100 -/** @def RF6_DARKNESS - * @note Create Darkness - */ -#define RF6_DARKNESS 0x00000200 -/** @def RF6_TRAPS - * @note Create Traps - */ -#define RF6_TRAPS 0x00000400 -/** @def RF6_FORGET - * @note Cause amnesia - */ -#define RF6_FORGET 0x00000800 -/** @def RF6_RAISE_DEAD - * @note Raise Dead - */ -#define RF6_RAISE_DEAD 0x00001000 -/** @def RF6_S_BUG - * @note Summon Software bug - */ -#define RF6_S_BUG 0x00002000 -/** @def RF6_S_RNG - * @note Summon RNG - */ -#define RF6_S_RNG 0x00004000 -/** @def RF6_S_THUNDERLORD - * @note Summon Thunderlords - */ -#define RF6_S_THUNDERLORD 0x00008000 -/** @def RF6_S_KIN - * @note Summon "kin" - */ -#define RF6_S_KIN 0x00010000 -/** @def RF6_S_HI_DEMON - * @note Summon greater demons! - */ -#define RF6_S_HI_DEMON 0x00020000 -/** @def RF6_S_MONSTER - * @note Summon Monster - */ -#define RF6_S_MONSTER 0x00040000 -/** @def RF6_S_MONSTERS - * @note Summon Monsters - */ -#define RF6_S_MONSTERS 0x00080000 -/** @def RF6_S_ANT - * @note Summon Ants - */ -#define RF6_S_ANT 0x00100000 -/** @def RF6_S_SPIDER - * @note Summon Spiders - */ -#define RF6_S_SPIDER 0x00200000 -/** @def RF6_S_HOUND - * @note Summon Hounds - */ -#define RF6_S_HOUND 0x00400000 -/** @def RF6_S_HYDRA - * @note Summon Hydras - */ -#define RF6_S_HYDRA 0x00800000 -/** @def RF6_S_ANGEL - * @note Summon Angel - */ -#define RF6_S_ANGEL 0x01000000 -/** @def RF6_S_DEMON - * @note Summon Demon - */ -#define RF6_S_DEMON 0x02000000 -/** @def RF6_S_UNDEAD - * @note Summon Undead - */ -#define RF6_S_UNDEAD 0x04000000 -/** @def RF6_S_DRAGON - * @note Summon Dragon - */ -#define RF6_S_DRAGON 0x08000000 -/** @def RF6_S_HI_UNDEAD - * @note Summon Greater Undead - */ -#define RF6_S_HI_UNDEAD 0x10000000 -/** @def RF6_S_HI_DRAGON - * @note Summon Ancient Dragon - */ -#define RF6_S_HI_DRAGON 0x20000000 -/** @def RF6_S_WRAITH - * @note Summon Unique Wraith - */ -#define RF6_S_WRAITH 0x40000000 -/** @def RF6_S_UNIQUE - * @note Summon Unique Monster - */ -#define RF6_S_UNIQUE 0x80000000 -/** @} */ - -/** @name Race flags #7 - * @note New monster race bit flags - * @{ */ -/** @def RF7_AQUATIC - * @note Aquatic monster - */ -#define RF7_AQUATIC 0x00000001 -/** @def RF7_CAN_SWIM - * @note Monster can swim - */ -#define RF7_CAN_SWIM 0x00000002 -/** @def RF7_CAN_FLY - * @note Monster can fly - */ -#define RF7_CAN_FLY 0x00000004 -/** @def RF7_FRIENDLY - * @note Monster is friendly - */ -#define RF7_FRIENDLY 0x00000008 -/** @def RF7_PET - * @note Monster is a pet - */ -#define RF7_PET 0x00000010 -/** @def RF7_MORTAL - * @note Monster is a mortal being - */ -#define RF7_MORTAL 0x00000020 -/** @def RF7_SPIDER - * @note Monster is a spider (can pass webs) - */ -#define RF7_SPIDER 0x00000040 -/** @def RF7_NAZGUL - * @note Monster is a Nazgul - */ -#define RF7_NAZGUL 0x00000080 -/** @def RF7_DG_CURSE - * @note If killed the monster grant a DG Curse to the player - */ -#define RF7_DG_CURSE 0x00000100 -/** @def RF7_POSSESSOR - * @note Is it a dreaded possessor monster ? - */ -#define RF7_POSSESSOR 0x00000200 -/** @def RF7_NO_DEATH - * @note Cannot be killed - */ -#define RF7_NO_DEATH 0x00000400 -/** @def RF7_NO_TARGET - * @note Cannot be targeted - */ -#define RF7_NO_TARGET 0x00000800 -/** @def RF7_AI_ANNOY - * @note Try to tease the player - */ -#define RF7_AI_ANNOY 0x00001000 -/** @def RF7_AI_SPECIAL - * @note For quests - */ -#define RF7_AI_SPECIAL 0x00002000 -/** @def RF7_NO_THEFT - * @note Monster is immune to theft - */ -#define RF7_NO_THEFT 0x00040000 -/** @def RF7_SPIRIT - * @note This is a Spirit, coming from the Void - */ -#define RF7_SPIRIT 0x00080000 -/** @def RF7_IM_MELEE - * @note IM melee - */ -#define RF7_IM_MELEE 0x00100000 -/** @} */ - -/** @name Race flags #8 - * @note New monster race bit flags - * @{ */ -/** @def RF8_DUNGEON */ -#define RF8_DUNGEON 0x00000001 - -/** @def RF8_WILD_TOWN */ -#define RF8_WILD_TOWN 0x00000002 - -/** @def RF8_XXX8X02 */ -#define RF8_XXX8X02 0x00000004 - -/** @def RF8_WILD_SHORE */ -#define RF8_WILD_SHORE 0x00000008 - -/** @def RF8_WILD_OCEAN */ -#define RF8_WILD_OCEAN 0x00000010 - -/** @def RF8_WILD_WASTE */ -#define RF8_WILD_WASTE 0x00000020 - -/** @def RF8_WILD_WOOD */ -#define RF8_WILD_WOOD 0x00000040 - -/** @def RF8_WILD_VOLCANO */ -#define RF8_WILD_VOLCANO 0x00000080 - -/** @def RF8_XXX8X08 */ -#define RF8_XXX8X08 0x00000100 - -/** @def RF8_WILD_MOUNTAIN */ -#define RF8_WILD_MOUNTAIN 0x00000200 - -/** @def RF8_WILD_GRASS */ -#define RF8_WILD_GRASS 0x00000400 - -/********* FREE *********/ -/** @def RF8_CTHANGBAND */ -#define RF8_CTHANGBAND 0x00001000 - -/********* FREE *********/ -/** @def RF8_ZANGBAND */ -#define RF8_ZANGBAND 0x00004000 - -/** @def RF8_JOKEANGBAND */ -#define RF8_JOKEANGBAND 0x00008000 - -/** @def RF8_ANGBAND */ -#define RF8_ANGBAND 0x00010000 - - -/** @def RF8_WILD_TOO */ -#define RF8_WILD_TOO 0x80000000 -/** @} */ - -/** @name Race flags #9 - * @note New monster race bit flags - * @{ */ -/** @def RF9_DROP_CORPSE */ -#define RF9_DROP_CORPSE 0x00000001 - -/** @def RF9_DROP_SKELETON */ -#define RF9_DROP_SKELETON 0x00000002 - -/** @def RF9_HAS_LITE - * @note Carries a lite - */ -#define RF9_HAS_LITE 0x00000004 -/** @def RF9_MIMIC - * @note *REALLY* looks like an object ... only nastier - */ -#define RF9_MIMIC 0x00000008 -/** @def RF9_HAS_EGG - * @note Can be monster's eggs - */ -#define RF9_HAS_EGG 0x00000010 -/** @def RF9_IMPRESED - * @note The monster can follow you on each level until he dies - */ -#define RF9_IMPRESED 0x00000020 -/** @def RF9_SUSCEP_ACID - * @note Susceptible to acid - */ -#define RF9_SUSCEP_ACID 0x00000040 -/** @def RF9_SUSCEP_ELEC - * @note Susceptible to lightning - */ -#define RF9_SUSCEP_ELEC 0x00000080 -/** @def RF9_SUSCEP_POIS - * @note Susceptible to poison - */ -#define RF9_SUSCEP_POIS 0x00000100 -/** @def RF9_KILL_TREES - * @note Monster can eat trees - */ -#define RF9_KILL_TREES 0x00000200 -/** @def RF9_WYRM_PROTECT - * @note The monster is protected by great wyrms of power: They'll be summoned if it's killed - */ -#define RF9_WYRM_PROTECT 0x00000400 -/** @def RF9_DOPPLEGANGER - * @note The monster looks like you - */ -#define RF9_DOPPLEGANGER 0x00000800 -/** @def RF9_ONLY_DEPTH - * @note The monster can only be generated at the GIVEN depth - */ -#define RF9_ONLY_DEPTH 0x00001000 -/** @def RF9_SPECIAL_GENE - * @note The monster can only be generated in special conditions like quests, special dungeons, ... - */ -#define RF9_SPECIAL_GENE 0x00002000 -/** @def RF9_NEVER_GENE - * @note The monster cannot be normaly generated - */ -#define RF9_NEVER_GENE 0x00004000 -/** @} */ - -/** @name Monster flags - * @{ */ -/** @def MFLAG_VIEW - * @note Monster is in line of sight - */ -#define MFLAG_VIEW 0x00000001 -/** @def MFLAG_QUEST - * @note Monster is subject to a quest - */ -#define MFLAG_QUEST 0x00000002 -/** @def MFLAG_PARTIAL - * @note Monster is a partial summon - */ -#define MFLAG_PARTIAL 0x00000004 -/** @def MFLAG_CONTROL - * @note Monster is controlled - */ -#define MFLAG_CONTROL 0x00000008 -/** @def MFLAG_BORN - * @note Monster is still being born - */ -#define MFLAG_BORN 0x00000010 -/** @def MFLAG_NICE - * @note Monster is still being nice - */ -#define MFLAG_NICE 0x00000020 -/** @def MFLAG_SHOW - * @note Monster is recently memorized - */ -#define MFLAG_SHOW 0x00000040 -/** @def MFLAG_MARK - * @note Monster is currently memorized - */ -#define MFLAG_MARK 0x00000080 -/** @def MFLAG_NO_DROP - * @note Monster wont drop obj/corpse - */ -#define MFLAG_NO_DROP 0x00000100 -/** @def MFLAG_QUEST2 - * @note Monster is subject to a quest - */ -#define MFLAG_QUEST2 0x00000200 -/** @} */ - -/** @struct monster_blow - * @brief Monster blows (attacks) - */ -struct monster_blow -{ - /** @structvar method - * @brief Number - */ - byte method; - /** @structvar effect - * @brief Number - */ - byte effect; - /** @structvar d_dice - * @brief Number - */ - byte d_dice; - /** @structvar d_side - * @brief Number - */ - byte d_side; -}; - -/** @struct monster_race - * @brief Monster race - */ -struct monster_race -{ - /** @structvar name - * @brief Number - * @note Name (offset) - */ - u32b name; - /** @structvar text - * @brief Number - * @note Text (offset) - */ - u32b text; - - /** @structvar hdice - * @brief Number - * @note Creatures hit dice count - */ - byte hdice; - /** @structvar hside - * @brief Number - * @note Creatures hit dice sides - */ - byte hside; - - /** @structvar ac - * @brief Number - * @note Armour Class - */ - s16b ac; - - /** @structvar sleep - * @brief Number - * @note Inactive counter (base) - */ - s16b sleep; - /** @structvar aaf - * @brief Number - * @note Area affect radius (1-100) - */ - byte aaf; - /** @structvar speed - * @brief Number - * @note Speed (normally 110) - */ - byte speed; - - /** @structvar mexp - * @brief Number - * @note Exp value for kill - */ - s32b mexp; - - /** @structvar weight - * @brief Number - * @note Weight of the monster - */ - s32b weight; - - /** @structvar freq_inate - * @brief Number - * @note Inate spell frequency - */ - byte freq_inate; - /** @structvar freq_spell - * @brief Number - * @note Other spell frequency - */ - byte freq_spell; - - /** @structvar flags1 - * @brief Number - * @note Flags 1 (general) - */ - u32b flags1; - /** @structvar flags2 - * @brief Number - * @note Flags 2 (abilities) - */ - u32b flags2; - /** @structvar flags3 - * @brief Number - * @note Flags 3 (race/resist) - */ - u32b flags3; - /** @structvar flags4 - * @brief Number - * @note Flags 4 (inate/breath) - */ - u32b flags4; - /** @structvar flags5 - * @brief Number - * @note Flags 5 (normal spells) - */ - u32b flags5; - /** @structvar flags6 - * @brief Number - * @note Flags 6 (special spells) - */ - u32b flags6; - /** @structvar flags7 - * @brief Number - * @note Flags 7 (movement related abilities) - */ - u32b flags7; - /** @structvar flags8 - * @brief Number - * @note Flags 8 (wilderness info) - */ - u32b flags8; - /** @structvar flags9 - * @brief Number - * @note Flags 9 (drops info) - */ - u32b flags9; - - /** @structvar blow[4] - * @brief magic_power - * @note Up to four blows per round - */ - monster_blow blow[4]; - - /** @structvar body_parts[BODY_MAX] - * @brief Number - * @note To help to decide what to use when body changing - */ - byte body_parts[BODY_MAX]; - - /** @structvar level - * @brief Number - * @note Level of creature - */ - byte level; - /** @structvar rarity - * @brief Number - * @note Rarity of creature - */ - byte rarity; - - - /** @structvar d_attr - * @brief Number - * @note Default monster attribute - */ - byte d_attr; - /** @structvar d_char - * @brief String - * @note Default monster character - */ - char d_char; - - - /** @structvar x_attr - * @brief Number - * @note Desired monster attribute - */ - byte x_attr; - /** @structvar x_char - * @brief String - * @note Desired monster character - */ - char x_char; - - - /** @structvar max_num - * @brief Number - * @note Maximum population allowed per level - */ - s16b max_num; - - /** @structvar cur_num - * @brief Number - * @note Monster population on current level - */ - byte cur_num; - - - /** @structvar r_sights - * @brief Number - * @note Count sightings of this monster - */ - s16b r_sights; - /** @structvar r_deaths - * @brief Number - * @note Count deaths from this monster - */ - s16b r_deaths; - - /** @structvar r_pkills - * @brief Number - * @note Count monsters killed in this life - */ - s16b r_pkills; - /** @structvar r_tkills - * @brief Number - * @note Count monsters killed in all lives - */ - s16b r_tkills; - - /** @structvar r_wake - * @brief Number - * @note Number of times woken up (?) - */ - byte r_wake; - /** @structvar r_ignore - * @brief Number - * @note Number of times ignored (?) - */ - byte r_ignore; - - /** @structvar r_xtra1 - * @brief Number - * @note Something (unused) - */ - byte r_xtra1; - /** @structvar r_xtra2 - * @brief Number - * @note Something (unused) - */ - byte r_xtra2; - - /** @structvar r_drop_gold - * @brief Number - * @note Max number of gold dropped at once - */ - byte r_drop_gold; - /** @structvar r_drop_item - * @brief Number - * @note Max number of item dropped at once - */ - byte r_drop_item; - - /** @structvar r_cast_inate - * @brief Number - * @note Max number of inate spells seen - */ - byte r_cast_inate; - /** @structvar r_cast_spell - * @brief Number - * @note Max number of other spells seen - */ - byte r_cast_spell; - - /** @structvar r_blows[4] - * @brief Number - * @note Number of times each blow type was seen - */ - byte r_blows[4]; - - /** @structvar r_flags1 - * @brief Number - * @note Observed racial flags - */ - u32b r_flags1; - /** @structvar r_flags2 - * @brief Number - * @note Observed racial flags - */ - u32b r_flags2; - /** @structvar r_flags3 - * @brief Number - * @note Observed racial flags - */ - u32b r_flags3; - /** @structvar r_flags4 - * @brief Number - * @note Observed racial flags - */ - u32b r_flags4; - /** @structvar r_flags5 - * @brief Number - * @note Observed racial flags - */ - u32b r_flags5; - /** @structvar r_flags6 - * @brief Number - * @note Observed racial flags - */ - u32b r_flags6; - /** @structvar r_flags7 - * @brief Number - * @note Observed racial flags - */ - u32b r_flags7; - /** @structvar r_flags8 - * @brief Number - * @note Observed racial flags - */ - u32b r_flags8; - /** @structvar r_flags9 - * @brief Number - * @note Observed racial flags - */ - u32b r_flags9; - - /** @structvar on_saved - * @brief Boolean - * @note Is the (unique) on a saved level ? - */ - bool on_saved; - - /** @structvar total_visible - * @brief Number - * @note Amount of this race that are visible - */ - byte total_visible; - - /** @structvar drops - * @brief obj_theme - * @note The drops type - */ - obj_theme drops; -}; - -/** @struct monster_type - * @brief Monster type - */ -struct monster_type -{ - /** @structvar r_idx - * @brief Number - * @note Monster race index - */ - s16b r_idx; - - /** @structvar ego - * @brief Number - * @note Ego monster type - */ - u16b ego; - - /** @structvar fy - * @brief Number - * @note Y location on map - */ - byte fy; - /** @structvar fx - * @brief Number - * @note X location on map - */ - byte fx; - - /** @structvar hp - * @brief Number - * @note Current Hit points - */ - s16b hp; - /** @structvar maxhp - * @brief Number - * @note Max Hit points - */ - s16b maxhp; - - /** @structvar blow[4] - * @brief magic_power - * @note Up to four blows per round - */ - monster_blow blow[4]; - - /** @structvar speed - * @brief Number - * @note Speed (normally 110) - */ - byte speed; - /** @structvar level - * @brief Number - * @note Level of creature - */ - byte level; - /** @structvar ac - * @brief Number - * @note Armour Class - */ - s16b ac; - /** @structvar exp - * @brief Number - * @note Experience - */ - u32b exp; - - /** @structvar csleep - * @brief Number - * @note Inactive counter - */ - s16b csleep; - - /** @structvar mspeed - * @brief Number - * @note Monster "speed" - */ - byte mspeed; - /** @structvar energy - * @brief Number - * @note Monster "energy" - */ - byte energy; - - /** @structvar stunned - * @brief Number - * @note Monster is stunned - */ - byte stunned; - /** @structvar confused - * @brief Number - * @note Monster is confused - */ - byte confused; - /** @structvar monfear - * @brief Number - * @note Monster is afraid - */ - byte monfear; - - /** @structvar bleeding - * @brief Number - * @note Monster is bleeding - */ - s16b bleeding; - /** @structvar poisoned - * @brief Number - * @note Monster is poisoned - */ - s16b poisoned; - - /** @structvar cdis - * @brief Number - * @note Current dis from player - */ - byte cdis; - - /** @structvar mflag - * @brief Number - * @note Extra monster flags - */ - s32b mflag; - - /** @structvar ml - * @brief Boolean - * @note Monster is "visible" - */ - bool ml; - - /** @structvar hold_o_idx - * @brief Number - * @note Object being held (if any) - */ - s16b hold_o_idx; - - /** @structvar smart - * @brief Number - * @note Field for "smart_learn" - */ - u32b smart; - - /** @structvar status - * @brief Number - * @note Status(friendly, pet, companion, ..) - */ - s16b status; - - /** @structvar target - * @brief Number - * @note Monster target - */ - s16b target; - - /** @structvar possessor - * @brief Number - * @note Is it under the control of a possessor ? - */ - s16b possessor; -}; - -$static monster_type *lua_get_monster(int m_idx){return (&m_list[m_idx]);} -/** @fn monster(int m_idx); - * @brief Return the monster with index "m_idx" in the monster list.\n - * @param m_idx Number \n the index of the monster in the monster list - * @brief Monster index - * @return monster_type \n The monster. - * @note (see file w_mnster.c) - */ -static monster_type *lua_get_monster @ monster(int m_idx); - -/** @var m_list[max_m_idx] - * @brief monster_type - * @note List of monsters - */ -extern monster_type m_list[max_m_idx]; - -/** @fn race_info_idx(int r_idx, int ego) - * @brief Get monster info and ego info for monster with monster index "r_idx" - * and monster ego "ego".\n - * @param r_idx Number \n the index of the race in the monster race array - * @brief Race index - * @param ego Number \n the index of the ego in the monster ego array - * @brief Ego index - * @return monster_race \n The monster race. - * @note - * If "ego" > 0, the ego information is applied to the monster information and - * the new monster information is returned. - * @note - * For example, race_info_idx(141,7) will create a brown yeek (monster) - * shaman (ego). - * @note (see file monster2.c) - */ -extern monster_race* race_info_idx(int r_idx, int ego); - -/** @fn delete_monster_idx(int i) - * @brief Delete monster "i" from the monster array.\n - * @param i Number \n the index of the monster in the monster list - * @brief Monster index - * @note (see file monster2.c) - */ -extern void delete_monster_idx(int i); - -/** @fn m_pop(void) - * @brief Get an empty slot in the monster list. - * @return Number \n The index of an empty slot the monster list. - * @note - * If there are no empty slots, a slot will be reclaimed from a "dead" - * monster. If all slots are full, 0 is returned, which means the function - * has failed ("Too many monsters!"). - * @note (see file monster2.c) - */ -extern s16b m_pop(void); - -/** @fn get_mon_num_prep(void) - * @brief Apply a "monster restriction function" to the "monster allocation - * table". - * @return Number \n 0 (success) always. - * @note - * There are no parameters, but there are some other variables which will - * need to be set. They are get_mon_num_hook and get_mon_num2_hook. They - * are pointers to functions. - * @note - * For example, get_mon_num_hook = monster_volcano means when - * get_mon_num_hook is called (*get_mon_num_hook)(index), the actual - * function called is monster_volcano(index). This particular function - * returns TRUE if the monster indicated by "index" has the - * RF8_WILD_VOLCANO flag set. - * @note - * It is a good idea to store the old value of get_mon_num_hook before - * setting a new one, and restoring it when your function is finished. - * @note - * Following is a list of functions which can be assigned to - * get_mon_num_hook:\n - * create_molds_hook\n - * create_townpeople_hook\n - * mon_hook_bounty\n - * monster_dungeon\n - * monster_grass\n - * monster_mountain\n - * monster_ocean\n - * monster_quest\n - * monster_shore\n - * monster_town\n - * monster_volcano\n - * monster_waste\n - * monster_wood\n - * mutate_monster_okay\n - * place_monster_okay\n - * summon_specific_okay\n - * vault_aux_animal\n - * vault_aux_chapel\n - * vault_aux_clone\n - * vault_aux_demon\n - * vault_aux_dragon\n - * vault_aux_giant\n - * vault_aux_jelly\n - * vault_aux_kennel\n - * vault_aux_orc\n - * vault_aux_symbol\n - * vault_aux_treasure\n - * vault_aux_troll\n - * vault_aux_undead - * @note - * Or you can write your own. The function must take an integer (index) - * as a parameter and return boolean (TRUE if the monster is selected, - * or FALSE if it is not). - * @note (see file monster2.c) - */ -extern errr get_mon_num_prep(void); - -/** @fn get_mon_num(int level) - * @brief For the given level "level", return the index of an appropriate - * monster race.\n - * @param level Number \n a dungeon level (which is adjusted before - * it is used). - * @brief Dungeon level - * @return Number \n The index of a monster race in the monster race array. - * @note - * This function uses the "prob2" field of the "monster allocation table", - * and various local information, to calculate the "prob3" field of the - * same table, which is then used to choose an "appropriate" monster, in - * a relatively efficient manner. - * @note - * Note that "town" monsters will *only* be created in the town, and - * "normal" monsters will *never* be created in the town, unless the - * "level" is "modified", for example, by polymorph or summoning. - * @note - * There is a small chance (1/50) of "boosting" the given depth by - * a small amount (up to four levels), except in the town. - * @note - * It is (slightly) more likely to acquire a monster of the given level - * than one of a lower level. This is done by choosing several monsters - * appropriate to the given level and keeping the "hardest" one. - * @note - * Note that if no monsters are "appropriate", then this function will - * fail, and return zero, but this should *almost* never happen. - * @note (see file monster2.c) - */ -extern s16b get_mon_num(int level); - -$static char *lua_monster_desc(monster_type *m_ptr, int mode){static char buf[200]; monster_desc(buf, m_ptr, mode); return buf;} -/** @fn monster_desc(monster_type *m_ptr, int mode); - * @brief Return a monster description for monster "monster_type" using flag - * "mode".\n - * @param *m_ptr monster_type \n the monster - * @brief Monster - * @param mode Number \n description mode (see below) - * @brief Description mode - * @return String \n The description of the monster. - * @note - * We can correctly describe monsters based on their visibility.\n - * We can force all monsters to be treated as visible or invisible.\n - * We can build nominatives, objectives, possessives, or reflexives.\n - * We can selectively pronominalize hidden, visible, or all monsters.\n - * We can use definite or indefinite descriptions for hidden monsters.\n - * We can use definite or indefinite descriptions for visible monsters. - * @note - * Pronominalization involves the gender whenever possible and allowed, - * so that by cleverly requesting pronominalization / visibility, you - * can get messages like "You hit someone. She screams in agony!". - * @note - * Reflexives are acquired by requesting Objective plus Possessive. - * @note - * If no m_ptr arg is given (?), the monster is assumed to be hidden, - * unless the "Assume Visible" mode is requested. - * @note - * If no r_ptr arg is given, it is extracted from m_ptr and r_info - * If neither m_ptr nor r_ptr is given, the monster is assumed to - * be neuter, singular, and hidden (unless "Assume Visible" is set), - * in which case you may be in trouble... :-) - * @note - * I am assuming that no monster name is more than 70 characters long, - * so that "char desc[80];" is sufficiently large for any result. - * @note - * Mode Flags:\n - * 0x01 --> Objective (or Reflexive)\n - * 0x02 --> Possessive (or Reflexive)\n - * 0x04 --> Use indefinites for hidden monsters ("something")\n - * 0x08 --> Use indefinites for visible monsters ("a kobold")\n - * 0x10 --> Pronominalize hidden monsters\n - * 0x20 --> Pronominalize visible monsters\n - * 0x40 --> Assume the monster is hidden\n - * 0x80 --> Assume the monster is visible - * @note - * Useful Modes:\n - * 0x00 --> Full nominative name ("the kobold") or "it"\n - * 0x04 --> Full nominative name ("the kobold") or "something"\n - * 0x80 --> Genocide resistance name ("the kobold")\n - * 0x88 --> Killing name ("a kobold")\n - * 0x22 --> Possessive, genderized if visible ("his") or "its"\n - * 0x23 --> Reflexive, genderized if visible ("himself") or "itself" - * @note (see file monster2.c) - */ -static char *lua_monster_desc @ monster_desc(monster_type *m_ptr, int mode); - -$static char *lua_monster_race_desc(int r_idx, int ego){static char buf[200]; monster_race_desc(buf, r_idx, ego); return buf;} -/** @fn monster_race_desc(int r_idx, int ego); - * @brief Return the monster description for monster with monster index - * "r_idx" and monster ego "ego".\n - * @param r_idx Number \n the index of the race in the monster race array - * @brief Race index - * @param ego Number \n the index of the ego in the monster ego array - * @brief Ego index - * @return String \n The description of the monster race. - * @note - * The monster description is made up of the ego name (if any) and monster - * name, or the unique name. - * @note (see file w_mnster.c) - */ -static char *lua_monster_race_desc @ monster_race_desc(int r_idx, int ego); - -/** @fn monster_race_desc(char *desc, int r_idx, int ego) - * @brief Return the monster description "desc" for monster with monster index - * "r_idx" and monster ego "ego".\n - * @param *desc String - * @brief Description - * @param r_idx Number \n the index of the race in the monster race array - * @brief Race index - * @param ego Number \n the index of the ego in the monster ego array - * @brief Ego index - * @return *desc String \n The description of the monster race. - * @note - * The monster description is made up of the ego name (if any) and monster - * name, or the unique name. - * @note (see file monster2.c) - */ -extern void monster_race_desc(char *desc, int r_idx, int ego); - -/** @fn monster_carry(monster_type *m_ptr, int m_idx, object_type *q_ptr) - * @brief Allow monster "m_ptr" with monster index "m_idx" to carry object - * "q_ptr".\n - * @param *m_ptr monster_type \n the monster - * @brief Monster - * @param m_idx Number \n the index of the monster in the monster list - * @brief Monster index - * @param *q_ptr object_type \n the object - * @brief Object - * @note - * The monster can only carry the object if there is room for the object in the - * object list. - * @note (see file monster2.c) - */ -extern void monster_carry(monster_type *m_ptr, int m_idx, object_type *q_ptr); - -/** @fn place_monster_aux(int y, int x, int r_idx, bool slp, bool grp, int status) - * @brief Attempt to place a monster with monster race index "r_idx" and status - * "status" at grid "y", "x". The monster may be asleep ("slp") or surrounded - * by a group of identical monsters ("grp").\n - * @param y Number \n the y coordinate of the target grid - * @brief Y-coordinate - * @param x Number \n the x coordinate of the target grid - * @brief X-coordinate - * @param r_idx Number \n the index of the race in the monster race array - * @brief Race index - * @param slp Boolean \n TRUE if monster is asleep, otherwise FALSE - * @brief Asleep? - * @param grp Boolean \n TRUE if monster appears in a group, otherwise FALSE - * @brief Group? - * @param status Number \n the status of the monster from the player's point - * of view (see MSTATUS_foo flags) - * @brief Monster status - * @return Boolean \n TRUE if the monster is placed successfully, otherwise - * FALSE. - * @note - * Note that certain monsters are now marked as requiring "friends". - * These monsters, if successfully placed, and if the "grp" parameter - * is TRUE, will be surrounded by a "group" of identical monsters. - * @note - * Note that certain monsters are now marked as requiring an "escort", - * which is a collection of monsters with similar "race" but lower - * level. - * @note - * Some monsters induce a fake "group" flag on their escorts. - * @note - * Note the "bizarre" use of non-recursion to prevent annoying output - * when running a code profiler. - * @note - * Note the use of the new "monster allocation table" code to restrict - * the "get_mon_num()" function to "legal" escort types. - * @note (see file monster2.c) - */ -extern bool place_monster_aux(int y, int x, int r_idx, bool slp, bool grp, int status); - -/** @fn place_monster(int y, int x, bool slp, bool grp) - * @brief Attempt to place a monster at grid "y", "x". The monster may be - * asleep ("slp") or surrounded by a group of identical monsters ("grp").\n - * @param y Number \n the y coordinate of the target grid - * @brief Y-coordinate - * @param x Number \n the x coordinate of the target grid - * @brief X-coordinate - * @param slp Boolean \n TRUE if monster is asleep, otherwise FALSE - * @brief Asleep? - * @param grp Boolean \n TRUE if monster appears in a group, otherwise FALSE - * @brief Group? - * @return Boolean \n TRUE if the monster is placed successfully, otherwise - * FALSE. - * @note - * Attempt to find a monster appropriate to the "monster_level" - * @note (see file monster2.c) - */ -extern bool place_monster(int y, int x, bool slp, bool grp); - -/** @fn place_monster_one(int y, int x, int r_idx, int ego, bool slp, int status) - * @brief Attempt to place a monster with monster race index "r_idx", monster - * ego "ego" and status "status" at grid "y", "x". The monster may be asleep - * ("slp").\n - * @param y Number \n the y coordinate of the target grid - * @brief Y-coordinate - * @param x Number \n the x coordinate of the target grid - * @brief X-coordinate - * @param r_idx Number \n the index of the race in the monster race array - * @brief Race index - * @param ego Number \n the index of the ego in the monster ego array - * @brief Ego index - * @param slp Boolean \n TRUE if monster is asleep, otherwise FALSE - * @brief Asleep? - * @param status Number \n the status of the monster from the player's point - * of view (see MSTATUS_foo flags) - * @brief Monster status - * @return Number \n The index of the placed monster in the monster list. - * @note - * To give the player a sporting chance, any monster that appears in - * line-of-sight and is extremely dangerous can be marked as - * "FORCE_SLEEP", which will cause them to be placed with low energy, - * which often (but not always) lets the player move before they do. - * @note - * This routine refuses to place out-of-depth "FORCE_DEPTH" monsters. - * @note - * XXX XXX XXX Use special "here" and "dead" flags for unique monsters, - * remove old "cur_num" and "max_num" fields. - * @note - * XXX XXX XXX Actually, do something similar for artifacts, to simplify - * the "preserve" mode, and to make the "what artifacts" flag more useful. - * @note - * This is the only function which may place a monster in the dungeon, - * except for the savefile loading code. - * @note (see file monster2.c) - */ -extern s16b place_monster_one(int y, int x, int r_idx, int ego, bool slp, int status); - -/** @fn is_friend(monster_type *m_ptr) - * @brief Return a value to indicate the status of monster "m_ptr".\n - * @param *m_ptr monster_type \n the monster - * @brief Monster - * @return Number \n -1 if monster is an enemy, 0 if it is neutral, and 1 if - * it is friendly. - * @note (see file monster3.c) - */ -extern int is_friend(monster_type *m_ptr); - -/** @fn is_enemy(monster_type *m_ptr, monster_type *t_ptr) - * @brief Determine if monster "m_ptr" should attack monster "t_ptr".\n - * @param *m_ptr monster_type \n the monster - * @brief Monster - * @param *t_ptr monster_type \n the target monster - * @brief Target monster - * @return Boolean \n TRUE if monster "m_ptr" should attack monster "t_ptr", - * otherwise FALSE. - * @note - * If "m_ptr" is stupid and "r_ptr" is a different type of monster then the - * function will return TRUE.\n - * If "m_ptr" is not neutral and "r_ptr" is a breeder, and "r_ptr" is a - * different type of monster then the function will return TRUE (and vice - * versa).\n - * If both monsters are not neutral and one is friendly and the other isn't - * then the function will return TRUE. - * @note (see file monster3.c) - */ -extern bool is_enemy(monster_type *m_ptr, monster_type *t_ptr); - -/** @fn change_side(monster_type *m_ptr) - * @brief Change the status of monster "m_ptr" from friendly to unfriendly and - * vice versa. - * @param *m_ptr monster_type \n the monster - * @brief Monster - * @return Boolean \n TRUE if the status changed, otherwise FALSE. - * @note - * Friends and pets become enemies.\n - * Neutral monsters become neutral pets and vice versa.\n - * Companions are unaffected. - * @note (see file monster3.c) - */ -extern bool change_side(monster_type *m_ptr); - -/** @fn find_position(int y, int x, int *yy = 0, int *xx = 0) - * @brief Find a new grid "yy", "xx" within 6 grids of target grid "y", "x".\n - * @param y Number \n the y coordinate of the origin grid - * @brief Origin y-coordinate - * @param x Number \n the x coordinate of the origin grid - * @brief Origin x-coordinate - * @param yy Number \n the y coordinate of the target grid - * @brief Target y-coordinate - * @param xx Number \n the x coordinate of the target grid - * @brief Target x-coordinate - * @note - * The new grid must be within line-of-sight of the target grid. A - * maximum of 5000 attempts is made. - * @note (see file lua_bind.c) - */ -extern void find_position(int y, int x, int *yy = 0, int *xx = 0); - -/** @var summon_specific_level - * @brief Number - * @note - * Force summoned monsters to be at this level. - */ -extern int summon_specific_level; - -/** @var summon_kin_type - * @brief String - * @note - * The monster character for those monsters who can summon kin. - */ -extern char summon_kin_type; - -/** @fn summon_specific(int y1, int x1, int lev, int type) - * @brief Place a monster of type "type" near grid "y","x".\n - * @param y1 Number \n the y coordinate of the target grid - * @brief Y-coordinate - * @param x1 Number \n the x coordinate of the target grid - * @brief X-coordinate - * @param lev Number \n the monster level of the summoning monster - * @brief Summoner level - * @param type Number \n the type of summoned monster - * @brief Monster type - * @return Boolean \n TRUE if a monster was summoned, otherwise FALSE. - * @note - * We will attempt to place the monster up to 20 times before giving up. - * @note - * Note: SUMMON_UNIQUE and SUMMON_WRAITH (XXX) will summon Unique's\n - * Note: SUMMON_HI_UNDEAD and SUMMON_HI_DRAGON may summon Unique's\n - * Note: None of the other summon codes will ever summon Unique's. - * @note - * This function has been changed. We now take the "monster level" - * of the summoning monster as a parameter, and use that, along with - * the current dungeon level, to help determine the level of the - * desired monster. Note that this is an upper bound, and also - * tends to "prefer" monsters of that level. Currently, we use - * the average of the dungeon and monster levels, and then add - * five to allow slight increases in monster power. - * @note - * Note that we use the new "monster allocation table" creation code - * to restrict the "get_mon_num()" function to the set of "legal" - * monsters, making this function much faster and more reliable. - * @note - * Note that this function may not succeed, though this is very rare. - * @note (see file monster2.c) - */ -extern bool summon_specific(int y1, int x1, int lev, int type); - -/** @fn summon_specific_friendly(int y1, int x1, int lev, int type, bool Group_ok) - * @brief Place a friendly monster of type "type" near grid "y","x". The - * monster may be surrounded by a group of identical monsters ("Group_ok").\n - * @param y1 Number \n the y coordinate of the target grid - * @brief Y-coordinate - * @param x1 Number \n the x coordinate of the target grid - * @brief X-coordinate - * @param lev Number \n the monster level of the summoning monster - * @brief Summoner level - * @param type Number \n the type of summoned monster - * @brief Monster type - * @param Group_ok Boolean \n TRUE if monster appears in a group, otherwise - * FALSE - * @brief Group? - * @return Boolean \n TRUE if a monster was summoned, otherwise FALSE. - * @note (see file monster2.c) - */ -extern bool summon_specific_friendly(int y1, int x1, int lev, int type, bool Group_ok); - -/** @fn can_create_companion() - * @brief Determine if a companion can be created. - * @return Boolean \n TRUE if a companion can be created, otherwise FALSE. - * @note - * The companions are counted. If this is less than the number allowed by - * the player monster lore skill, the function returns TRUE, otherwise the - * function returns FALSE. - * @note (see file monster3.c) - */ -extern bool can_create_companion(); - -/** @fn monster_set_level(int m_idx, int level) - * @brief Set a new level for monster with monster index "m_idx".\n - * @param m_idx Number \n the index of the monster in the monster list - * @brief Monster index - * @param level Number \n the new level of the monster - * @brief Monster level - * @note - * The new level can not exceed 150. If the new level is higher than the - * monster level, the monster experience value is recalculated. - * @note (see file monster2.c) - */ -extern void monster_set_level(int m_idx, int level); - -/** @name Summon types - * @note Legal restrictions for "summon_specific()" - */ -/** @def SUMMON_ANT - * @note Summon giant ant (a) excluding uniques. - */ -#define SUMMON_ANT 11 - -/** @def SUMMON_SPIDER - * @note Summon spider/scorpion/tick (S) excluding uniques. - */ -#define SUMMON_SPIDER 12 - -/** @def SUMMON_HOUND - * @note Summon canine (C) or zephyr hound (Z) excluding uniques. - */ -#define SUMMON_HOUND 13 - -/** @def SUMMON_HYDRA - * @note Summon multi-headed hydra (M) excluding uniques. - */ -#define SUMMON_HYDRA 14 - -/** @def SUMMON_ANGEL - * @note Summon angelic being (A) excluding uniques. - */ -#define SUMMON_ANGEL 15 - -/** @def SUMMON_DEMON - * @note Summon demon (RF3_DEMON) excluding uniques. - */ -#define SUMMON_DEMON 16 - -/** @def SUMMON_UNDEAD - * @note Summon undead (RF3_UNDEAD) excluding uniques. - */ -#define SUMMON_UNDEAD 17 - -/** @def SUMMON_DRAGON - * @note Summon dragon (RF3_DRAGON) excluding uniques. - */ -#define SUMMON_DRAGON 18 - -/** @def SUMMON_HI_UNDEAD - * @note Summon lich (L) or vampire (V) or wight/wraith (W) including uniques. - */ -#define SUMMON_HI_UNDEAD 21 - -/** @def SUMMON_HI_DRAGON - * @note Summon ancient dragon (D) including uniques. - */ -#define SUMMON_HI_DRAGON 22 - -/** @def SUMMON_WRAITH - * @note Summon wight/wraith (W) including uniques. - */ -#define SUMMON_WRAITH 31 - -/** @def SUMMON_UNIQUE - * @note Summon unique (RF1_UNIQUE). - */ -#define SUMMON_UNIQUE 32 - -/** @def SUMMON_BIZARRE1 - * @note Summon mold (m) excluding uniques. - */ -#define SUMMON_BIZARRE1 33 - -/** @def SUMMON_BIZARRE2 - * @note Summon giant bat (b) excluding uniques. - */ -#define SUMMON_BIZARRE2 34 - -/** @def SUMMON_BIZARRE3 - * @note Summon quylthulg (Q) excluding uniques. - */ -#define SUMMON_BIZARRE3 35 - -/** @def SUMMON_BIZARRE4 - * @note Summon vortex (v) excluding uniques. - */ -#define SUMMON_BIZARRE4 36 - -/** @def SUMMON_BIZARRE5 - * @note Summon creeping coins ($) excluding uniques. - */ -#define SUMMON_BIZARRE5 37 - -/** @def SUMMON_BIZARRE6 - * @note Summon mimic (!?=$|) excluding uniques. - */ -#define SUMMON_BIZARRE6 38 - -/** @def SUMMON_HI_DEMON - * @note Summon demon (RF3_DEMON) and major demon (U) excluding uniques. - */ -#define SUMMON_HI_DEMON 39 - -/** @def SUMMON_KIN - * @note Summon monster of the same character type excluding uniques. - */ -#define SUMMON_KIN 40 - -/** @def SUMMON_DAWN - * @note Summon monster with "the Dawn" in the name excluding uniques. - */ -#define SUMMON_DAWN 41 - -/** @def SUMMON_ANIMAL - * @note Summon animal (RF3_ANIMAL) excluding uniques. - */ -#define SUMMON_ANIMAL 42 - -/** @def SUMMON_ANIMAL_RANGER - * @note Summon animal (RF3_ANIMAL) and giant ant, giant bat, centipede, - * feline,giant louse, quadruped, rodent, worm or worm mass, bird, canine, - * insect, snake, killer beetle, multi-headed hydra, reptile/amphibian, - * spider/scorpion/tick (abcflqrwBCIJKMRS) and not dragon (RF3_DRAGON) and not - * evil (RF3_EVIL) and not undead (RF3_UNDEAD) and not demon (RF3_DEMON) and - * not inate/breath and not normal spells and not special spells excluding - * uniques. - */ -#define SUMMON_ANIMAL_RANGER 43 - -/** @def SUMMON_HI_UNDEAD_NO_UNIQUES - * @note Summon lich (L) or vampire (V) or wight/wraith (W) excluding uniques. - */ -#define SUMMON_HI_UNDEAD_NO_UNIQUES 44 - -/** @def SUMMON_HI_DRAGON_NO_UNIQUES - * @note Summon ancient dragon (D) excluding uniques. - */ -#define SUMMON_HI_DRAGON_NO_UNIQUES 45 - -/** @def SUMMON_NO_UNIQUES - * @note Summon non-uniques (not RF1_UNIQUE). - */ -#define SUMMON_NO_UNIQUES 46 - -/** @def SUMMON_PHANTOM - * @note Summon monster with "Phantom" in the name excluding uniques. - */ -#define SUMMON_PHANTOM 47 - -/** @def SUMMON_ELEMENTAL - * @note Summon monster with "lemental" in the name excluding uniques. - */ -#define SUMMON_ELEMENTAL 48 - -/** @def SUMMON_THUNDERLORD - * @note Summon thunderlords (RF3_THUNDERLORD) including uniques. - */ -#define SUMMON_THUNDERLORD 49 - -/** @def SUMMON_BLUE_HORROR - * @note Summon monster with "lue horror" in the name excluding uniques. - */ -#define SUMMON_BLUE_HORROR 50 - -/** @def SUMMON_BUG - * @note Summon monster with "Software bug" in the name excluding uniques. - */ -#define SUMMON_BUG 51 - -/** @def SUMMON_RNG - * @note Summon monster with "Random Number Generator" in the name excluding - * uniques. - */ -#define SUMMON_RNG 52 - -/** @def SUMMON_MINE - * @note Summon mines (RF1_NEVER_MOVE) including uniques. - */ -#define SUMMON_MINE 53 - -/** @def SUMMON_HUMAN - * @note Summon (p) excluding uniques. - */ -#define SUMMON_HUMAN 54 - -/** @def SUMMON_SHADOWS - * @note Summon ghost (G) excluding uniques. - */ -#define SUMMON_SHADOWS 55 - -/** @def SUMMON_GHOST - * @note Summon ghost (G) including uniques. - */ -#define SUMMON_GHOST 56 - -/** @def SUMMON_QUYLTHULG - * @note Summon (Q) excluding uniques. - */ -#define SUMMON_QUYLTHULG 57 - -/** @} */ - -/** @fn do_control_reconnect() - * @brief Find the controlled monster and reconnect to it. - * @return Boolean \n TRUE if there is a controlled monster, otherwise FALSE. - * @note - * The monster list is scanned for a monster with MFLAG_CONTROL. If it is - * found, the function returns TRUE. - * @note (see file monster3.c) - */ -extern bool do_control_reconnect(); - -/* monster thing */ -/** @var m_max - * @brief Number - * @note The number of monsters currently in the monster list. - */ -extern s16b m_max; diff --git a/src/object.pkg b/src/object.pkg deleted file mode 100644 index 05ea9c1a..00000000 --- a/src/object.pkg +++ /dev/null @@ -1,1161 +0,0 @@ -/* File: object.pkg */ - -/* - * Purpose: Lua interface defitions for objects. - * To be processed by tolua to generate C source code. - */ - -$#include "angband.h" - -typedef char* cptr; -typedef int errr; -typedef unsigned char bool; -typedef unsigned char byte; -typedef signed short s16b; -typedef unsigned short u16b; -typedef signed int s32b; -typedef unsigned int u32b; - -/* To make easy object creations */ -$static object_type lua_obj_forge; -static object_type lua_obj_forge @ obj_forge; -$static obj_theme lua_obj_theme; -static obj_theme lua_obj_theme @ theme_forge; - -#define TR1_STR 0x00000001L /* STR += "pval" */ -#define TR1_INT 0x00000002L /* INT += "pval" */ -#define TR1_WIS 0x00000004L /* WIS += "pval" */ -#define TR1_DEX 0x00000008L /* DEX += "pval" */ -#define TR1_CON 0x00000010L /* CON += "pval" */ -#define TR1_CHR 0x00000020L /* CHR += "pval" */ -#define TR1_MANA 0x00000040L /* Mana multipler */ -#define TR1_SPELL 0x00000080L /* Spell power increase */ -#define TR1_STEALTH 0x00000100L /* Stealth += "pval" */ -#define TR1_SEARCH 0x00000200L /* Search += "pval" */ -#define TR1_INFRA 0x00000400L /* Infra += "pval" */ -#define TR1_TUNNEL 0x00000800L /* Tunnel += "pval" */ -#define TR1_SPEED 0x00001000L /* Speed += "pval" */ -#define TR1_BLOWS 0x00002000L /* Blows += "pval" */ -#define TR1_CHAOTIC 0x00004000L -#define TR1_VAMPIRIC 0x00008000L -#define TR1_SLAY_ANIMAL 0x00010000L -#define TR1_SLAY_EVIL 0x00020000L -#define TR1_SLAY_UNDEAD 0x00040000L -#define TR1_SLAY_DEMON 0x00080000L -#define TR1_SLAY_ORC 0x00100000L -#define TR1_SLAY_TROLL 0x00200000L -#define TR1_SLAY_GIANT 0x00400000L -#define TR1_SLAY_DRAGON 0x00800000L -#define TR1_KILL_DRAGON 0x01000000L /* Execute Dragon */ -#define TR1_VORPAL 0x02000000L /* Later */ -#define TR1_IMPACT 0x04000000L /* Cause Earthquakes */ -#define TR1_BRAND_POIS 0x08000000L -#define TR1_BRAND_ACID 0x10000000L -#define TR1_BRAND_ELEC 0x20000000L -#define TR1_BRAND_FIRE 0x40000000L -#define TR1_BRAND_COLD 0x80000000L -#define TR1_NULL_MASK 0x00000000L - -#define TR2_SUST_STR 0x00000001L -#define TR2_SUST_INT 0x00000002L -#define TR2_SUST_WIS 0x00000004L -#define TR2_SUST_DEX 0x00000008L -#define TR2_SUST_CON 0x00000010L -#define TR2_SUST_CHR 0x00000020L -#define TR2_INVIS 0x00000040L /* Invisibility */ -#define TR2_LIFE 0x00000080L /* Life multiplier */ -#define TR2_IM_ACID 0x00000100L -#define TR2_IM_ELEC 0x00000200L -#define TR2_IM_FIRE 0x00000400L -#define TR2_IM_COLD 0x00000800L -#define TR2_SENS_FIRE 0x00001000L /* Sensibility to fire */ -#define TR2_REFLECT 0x00002000L /* Reflect 'bolts' */ -#define TR2_FREE_ACT 0x00004000L /* Free Action */ -#define TR2_HOLD_LIFE 0x00008000L /* Hold Life */ -#define TR2_RES_ACID 0x00010000L -#define TR2_RES_ELEC 0x00020000L -#define TR2_RES_FIRE 0x00040000L -#define TR2_RES_COLD 0x00080000L -#define TR2_RES_POIS 0x00100000L -#define TR2_RES_FEAR 0x00200000L -#define TR2_RES_LITE 0x00400000L -#define TR2_RES_DARK 0x00800000L -#define TR2_RES_BLIND 0x01000000L -#define TR2_RES_CONF 0x02000000L -#define TR2_RES_SOUND 0x04000000L -#define TR2_RES_SHARDS 0x08000000L -#define TR2_RES_NETHER 0x10000000L -#define TR2_RES_NEXUS 0x20000000L -#define TR2_RES_CHAOS 0x40000000L -#define TR2_RES_DISEN 0x80000000L -#define TR2_NULL_MASK 0x00000000L - -#define TR3_SH_FIRE 0x00000001L /* Immolation (Fire) */ -#define TR3_SH_ELEC 0x00000002L /* Electric Sheath */ -#define TR3_AUTO_CURSE 0x00000004L /* The obj will recurse itself */ -#define TR3_DECAY 0x00000008L /* Decay */ -#define TR3_NO_TELE 0x00000010L /* Anti-teleportation */ -#define TR3_NO_MAGIC 0x00000020L /* Anti-magic */ -#define TR3_WRAITH 0x00000040L /* Wraithform */ -#define TR3_TY_CURSE 0x00000080L /* The Ancient Curse */ -#define TR3_EASY_KNOW 0x00000100L /* Aware -> Known */ -#define TR3_HIDE_TYPE 0x00000200L /* Hide "pval" description */ -#define TR3_SHOW_MODS 0x00000400L /* Always show Tohit/Todam */ -#define TR3_INSTA_ART 0x00000800L /* Item must be an artifact */ -#define TR3_FEATHER 0x00001000L /* Feather Falling */ -#define TR3_LITE1 0x00002000L /* lite radius 1 */ -#define TR3_SEE_INVIS 0x00004000L /* See Invisible */ -#define TR3_NORM_ART 0x00008000L /* Artifact in k_info */ -#define TR3_SLOW_DIGEST 0x00010000L /* Item slows down digestion */ -#define TR3_REGEN 0x00020000L /* Item induces regeneration */ -#define TR3_XTRA_MIGHT 0x00040000L /* Bows get extra multiplier */ -#define TR3_XTRA_SHOTS 0x00080000L /* Bows get extra shots */ -#define TR3_IGNORE_ACID 0x00100000L /* Item ignores Acid Damage */ -#define TR3_IGNORE_ELEC 0x00200000L /* Item ignores Elec Damage */ -#define TR3_IGNORE_FIRE 0x00400000L /* Item ignores Fire Damage */ -#define TR3_IGNORE_COLD 0x00800000L /* Item ignores Cold Damage */ -#define TR3_ACTIVATE 0x01000000L /* Item can be activated */ -#define TR3_DRAIN_EXP 0x02000000L /* Item drains Experience */ -#define TR3_TELEPORT 0x04000000L /* Item teleports player */ -#define TR3_AGGRAVATE 0x08000000L /* Item aggravates monsters */ -#define TR3_BLESSED 0x10000000L /* Item is Blessed */ -#define TR3_CURSED 0x20000000L /* Item is Cursed */ -#define TR3_HEAVY_CURSE 0x40000000L /* Item is Heavily Cursed */ -#define TR3_PERMA_CURSE 0x80000000L /* Item is Perma Cursed */ -#define TR3_NULL_MASK 0x00000000L - -#define TR4_NEVER_BLOW 0x00000001L /* Weapon can't attack */ -#define TR4_PRECOGNITION 0x00000002L /* Like activating the cheat mode */ -#define TR4_BLACK_BREATH 0x00000004L /* Tolkien's Black Breath */ -#define TR4_RECHARGE 0x00000008L /* For artifact Wands and Staffs */ -#define TR4_FLY 0x00000010L /* This one and ONLY this one allow you to fly over trees */ -#define TR4_DG_CURSE 0x00000020L /* The Ancient Morgothian Curse */ -#define TR4_COULD2H 0x00000040L /* Can wield it 2 Handed */ -#define TR4_MUST2H 0x00000080L /* Must wield it 2 Handed */ -#define TR4_LEVELS 0x00000100L /* Can gain exp/exp levels !! */ -#define TR4_CLONE 0x00000200L /* Can clone monsters */ -#define TR4_SPECIAL_GENE 0x00000400L /* The object can only be generated in special conditions like quests, special dungeons, ... */ -#define TR4_CLIMB 0x00000800L /* Allow climbing mountains */ -#define TR4_FAST_CAST 0x00001000L /* Rod is x2 time faster to use */ -#define TR4_CAPACITY 0x00002000L /* Rod can take x2 mana */ -#define TR4_CHARGING 0x00004000L /* Rod recharge faster */ -#define TR4_CHEAPNESS 0x00008000L /* Rod spells are cheaper(in mana cost) to cast */ -#define TR4_FOUNTAIN 0x00010000L /* Available as fountain (for potions) */ -#define TR4_ANTIMAGIC_50 0x00020000L /* Forbid magic */ -#define TR4_ANTIMAGIC_30 0x00040000L /* Forbid magic */ -#define TR4_ANTIMAGIC_20 0x00080000L /* Forbid magic */ -#define TR4_ANTIMAGIC_10 0x00100000L /* Forbid magic */ -#define TR4_EASY_USE 0x00200000L /* Easily activable */ -#define TR4_IM_NETHER 0x00400000L /* Immunity to nether */ -#define TR4_RECHARGED 0x00800000L /* Object has been recharged once */ -#define TR4_ULTIMATE 0x01000000L /* ULTIMATE artifact */ -#define TR4_AUTO_ID 0x02000000L /* Id stuff on floor */ -#define TR4_LITE2 0x04000000L /* lite radius 2 */ -#define TR4_LITE3 0x08000000L /* lite radius 3 */ -#define TR4_FUEL_LITE 0x10000000L /* fuelable lite */ -#define TR4_ART_EXP 0x20000000L /* Will accumulate xp */ -#define TR4_CURSE_NO_DROP 0x40000000L /* The obj wont be dropped */ -#define TR4_NO_RECHARGE 0x80000000L /* Object Cannot be recharged */ -#define TR4_NULL_MASK 0xFFFFFFFCL - -#define TR5_TEMPORARY 0x00000001L /* In timeout turns it is destroyed */ -#define TR5_DRAIN_MANA 0x00000002L /* Drains mana */ -#define TR5_DRAIN_HP 0x00000004L /* Drains hp */ -#define TR5_KILL_DEMON 0x00000008L /* Execute Demon */ -#define TR5_KILL_UNDEAD 0x00000010L /* Execute Undead */ -#define TR5_CRIT 0x00000020L /* More critical hits */ -#define TR5_ATTR_MULTI 0x00000040L /* Object shimmer -- only allowed in k_info */ -#define TR5_WOUNDING 0x00000080L /* Wounds monsters */ -#define TR5_FULL_NAME 0x00000100L /* Uses direct name from k_info */ -#define TR5_LUCK 0x00000200L /* Luck += pval */ -#define TR5_IMMOVABLE 0x00000400L /* Cannot move */ -#define TR5_SPELL_CONTAIN 0x00000800L /* Can contain a spell */ -#define TR5_RES_MORGUL 0x00001000L /* Is not shattered by morgul fiends(nazguls) */ -#define TR5_ACTIVATE_NO_WIELD 0x00002000L /* Can be 'A'ctivated without being wielded */ -#define TR5_MAGIC_BREATH 0x00004000L /* Can breath anywere */ -#define TR5_WATER_BREATH 0x00008000L /* Can breath underwater */ -#define TR5_WIELD_CAST 0x00010000L /* Need to be wielded to cast spelsl fomr it(if it can be wiekded) */ - -#define ESP_ORC 0x00000001L -#define ESP_TROLL 0x00000002L -#define ESP_DRAGON 0x00000004L -#define ESP_GIANT 0x00000008L -#define ESP_DEMON 0x00000010L -#define ESP_UNDEAD 0x00000020L -#define ESP_EVIL 0x00000040L -#define ESP_ANIMAL 0x00000080L -#define ESP_THUNDERLORD 0x00000100L -#define ESP_GOOD 0x00000200L -#define ESP_NONLIVING 0x00000400L -#define ESP_UNIQUE 0x00000800L -#define ESP_SPIDER 0x00001000L -#define ESP_ALL 0x80000000L - -/* - * Bit flags for the "get_item" function - */ -#define USE_EQUIP 0x01 /* Allow equip items */ -#define USE_INVEN 0x02 /* Allow inven items */ -#define USE_FLOOR 0x04 /* Allow floor items */ -#define USE_EXTRA 0x08 /* Allow extra items */ - -#define INVEN_WIELD 24 /* 3 weapons -- WEAPONS */ -#define INVEN_BOW 27 /* 1 bow -- WEAPON */ -#define INVEN_RING 28 /* 6 rings -- FINGER */ -#define INVEN_NECK 34 /* 2 amulets -- HEAD */ -#define INVEN_LITE 36 /* 1 lite -- TORSO */ -#define INVEN_BODY 37 /* 1 body -- TORSO */ -#define INVEN_OUTER 38 /* 1 cloak -- TORSO */ -#define INVEN_ARM 39 /* 3 arms -- ARMS */ -#define INVEN_HEAD 42 /* 2 heads -- HEAD */ -#define INVEN_HANDS 44 /* 3 hands -- ARMS */ -#define INVEN_FEET 47 /* 2 feets -- LEGS */ -#define INVEN_CARRY 49 /* 1 carried monster -- TORSO */ -#define INVEN_AMMO 50 /* 1 quiver -- TORSO */ -#define INVEN_TOOL 51 /* 1 tool -- ARMS */ -#define INVEN_TOTAL 52 -#define INVEN_EQ (INVEN_TOTAL - INVEN_WIELD) - -#define TV_SKELETON 1 /* Skeletons ('s') */ -#define TV_BOTTLE 2 /* Empty bottles ('!') */ -#define TV_BATERIE 4 /* For the Alchemists */ -#define TV_SPIKE 5 /* Spikes ('~') */ -#define TV_MSTAFF 6 /* Mage Staffs */ -#define TV_CHEST 7 /* Chests ('~') */ -#define TV_PARCHMENT 8 /* Parchments from Kamband */ -#define TV_PARCHEMENT 8 /* compatibility define */ -#define TV_CORPSE 9 /* Monster corpses */ -#define TV_EGG 10 /* Monster Eggs */ -#define TV_JUNK 11 /* Sticks, Pottery, etc ('~') */ -#define TV_TOOL 12 /* Tools */ -#define TV_INSTRUMENT 14 /* Musical instruments */ -#define TV_BOOMERANG 15 /* Boomerangs */ -#define TV_SHOT 16 /* Ammo for slings */ -#define TV_ARROW 17 /* Ammo for bows */ -#define TV_BOLT 18 /* Ammo for x-bows */ -#define TV_BOW 19 /* Slings/Bows/Xbows */ -#define TV_DIGGING 20 /* Shovels/Picks */ -#define TV_HAFTED 21 /* Priest Weapons */ -#define TV_POLEARM 22 /* Pikes/Glaives/Spears/etc. */ -#define TV_SWORD 23 /* Edged Weapons */ -#define TV_AXE 24 /* Axes/Cleavers */ -#define TV_BOOTS 30 /* Boots */ -#define TV_GLOVES 31 /* Gloves */ -#define TV_HELM 32 /* Helms */ -#define TV_CROWN 33 /* Crowns */ -#define TV_SHIELD 34 /* Shields */ -#define TV_CLOAK 35 /* Cloaks */ -#define TV_SOFT_ARMOR 36 /* Soft Armor */ -#define TV_HARD_ARMOR 37 /* Hard Armor */ -#define TV_DRAG_ARMOR 38 /* Dragon Scale Mail */ -#define TV_LITE 39 /* Lites (including Specials) */ -#define TV_AMULET 40 /* Amulets (including Specials) */ -#define TV_RING 45 /* Rings (including Specials) */ -#define TV_TRAPKIT 46 /* Trapkits */ -#define TV_TOTEM 54 /* Summoner totems */ -#define TV_STAFF 55 -#define TV_WAND 65 -#define TV_ROD 66 -#define TV_ROD_MAIN 67 -#define TV_SCROLL 70 -#define TV_POTION 71 -#define TV_POTION2 72 /* Second set of potion */ -#define TV_FLASK 77 -#define TV_FOOD 80 -#define TV_HYPNOS 99 /* To wield monsters !:) */ -#define TV_GOLD 100 /* Gold can only be picked up by players */ -#define TV_RANDART 102 /* Random Artifacts */ -#define TV_RUNE1 104 /* Base runes */ -#define TV_RUNE2 105 /* Modifier runes */ - -#define TV_BOOK 111 -#define TV_SYMBIOTIC_BOOK 112 -#define TV_MUSIC_BOOK 113 -#define TV_DRUID_BOOK 114 -#define TV_DAEMON_BOOK 115 - -/* The "sval" codes for TV_TOOL */ -#define SV_TOOL_CLIMB 0 -#define SV_PORTABLE_HOLE 1 - -/* The "sval" codes for TV_MSTAFF */ -#define SV_MSTAFF 1 - -/* The "sval" codes for TV_SHOT/TV_ARROW/TV_BOLT */ -#define SV_AMMO_LIGHT 0 /* pebbles */ -#define SV_AMMO_NORMAL 1 /* shots, arrows, bolts */ -#define SV_AMMO_HEAVY 2 /* seeker arrows and bolts, mithril shots */ - -/* The "sval" codes for TV_INSTRUMENT */ -#define SV_DRUM 58 -#define SV_HARP 59 -#define SV_HORN 60 - -/* The "sval" codes for TV_TRAPKIT */ -#define SV_TRAPKIT_SLING 1 -#define SV_TRAPKIT_BOW 2 -#define SV_TRAPKIT_XBOW 3 -#define SV_TRAPKIT_POTION 4 -#define SV_TRAPKIT_SCROLL 5 -#define SV_TRAPKIT_DEVICE 6 - -/* The "sval" codes for TV_BOOMERANG */ -#define SV_BOOM_S_WOOD 1 /* 1d4 */ -#define SV_BOOM_WOOD 2 /* 1d9 */ -#define SV_BOOM_S_METAL 3 /* 1d8 */ -#define SV_BOOM_METAL 4 /* 2d4 */ - -/* The "sval" codes for TV_BOW (note information in "sval") */ -#define SV_SLING 2 /* (x2) */ -#define SV_SHORT_BOW 12 /* (x2) */ -#define SV_LONG_BOW 13 /* (x3) */ -#define SV_LIGHT_XBOW 23 /* (x3) */ -#define SV_HEAVY_XBOW 24 /* (x4) */ - -/* The "sval" codes for TV_DIGGING */ -#define SV_SHOVEL 1 -#define SV_GNOMISH_SHOVEL 2 -#define SV_DWARVEN_SHOVEL 3 -#define SV_PICK 4 -#define SV_ORCISH_PICK 5 -#define SV_DWARVEN_PICK 6 -#define SV_MATTOCK 7 - -/* The "sval" values for TV_HAFTED */ -#define SV_CLUB 1 /* 1d4 */ -#define SV_WHIP 2 /* 1d6 */ -#define SV_QUARTERSTAFF 3 /* 1d9 */ -#define SV_NUNCHAKU 4 /* 2d3 */ -#define SV_MACE 5 /* 2d4 */ -#define SV_BALL_AND_CHAIN 6 /* 2d4 */ -#define SV_WAR_HAMMER 8 /* 3d3 */ -#define SV_LUCERN_HAMMER 10 /* 2d5 */ -#define SV_THREE_PIECE_ROD 11 /* 3d3 */ -#define SV_MORNING_STAR 12 /* 2d6 */ -#define SV_FLAIL 13 /* 2d6 */ -#define SV_LEAD_FILLED_MACE 15 /* 3d4 */ -#define SV_TWO_HANDED_FLAIL 18 /* 3d6 */ -#define SV_GREAT_HAMMER 19 /* 4d6 */ -#define SV_MACE_OF_DISRUPTION 20 /* 5d8 */ -#define SV_GROND 50 /* 3d4 */ - -/* The "sval" values for TV_AXE */ -#define SV_HATCHET 1 /* 1d5 */ -#define SV_CLEAVER 2 /* 2d4 */ -#define SV_LIGHT_WAR_AXE 8 /* 2d5 */ -#define SV_BEAKED_AXE 10 /* 2d6 */ -#define SV_BROAD_AXE 11 /* 2d6 */ -#define SV_BATTLE_AXE 22 /* 2d8 */ -#define SV_GREAT_AXE 25 /* 4d4 */ -#define SV_LOCHABER_AXE 28 /* 3d8 */ -#define SV_SLAUGHTER_AXE 30 /* 5d7 */ - -/* The "sval" values for TV_POLEARM */ -#define SV_SPEAR 2 /* 1d6 */ -#define SV_SICKLE 3 /* 2d3 */ -#define SV_AWL_PIKE 4 /* 1d8 */ -#define SV_TRIDENT 5 /* 1d9 */ -#define SV_FAUCHARD 6 /* 1d10 */ -#define SV_BROAD_SPEAR 7 /* 1d9 */ -#define SV_PIKE 8 /* 2d5 */ -#define SV_GLAIVE 13 /* 2d6 */ -#define SV_HALBERD 15 /* 3d4 */ -#define SV_GUISARME 16 /* 2d5 */ -#define SV_SCYTHE 17 /* 5d3 */ -#define SV_LANCE 20 /* 2d8 */ -#define SV_TRIFURCATE_SPEAR 26 /* 2d9 */ -#define SV_HEAVY_LANCE 29 /* 4d8 */ -#define SV_SCYTHE_OF_SLICING 30 /* 8d4 */ - -/* The "sval" codes for TV_SWORD */ -#define SV_BROKEN_DAGGER 1 /* 1d1 */ -#define SV_BROKEN_SWORD 2 /* 1d2 */ -#define SV_DAGGER 4 /* 1d4 */ -#define SV_MAIN_GAUCHE 5 /* 1d5 */ -#define SV_RAPIER 7 /* 1d6 */ -#define SV_SMALL_SWORD 8 /* 1d6 */ -#define SV_BASILLARD 9 /* 1d8 */ -#define SV_SHORT_SWORD 10 /* 1d7 */ -#define SV_SABRE 11 /* 1d7 */ -#define SV_CUTLASS 12 /* 1d7 */ -#define SV_KHOPESH 14 /* 2d4 */ -#define SV_TULWAR 15 /* 2d4 */ -#define SV_BROAD_SWORD 16 /* 2d5 */ -#define SV_LONG_SWORD 17 /* 2d5 */ -#define SV_SCIMITAR 18 /* 2d5 */ -#define SV_KATANA 20 /* 3d4 */ -#define SV_BASTARD_SWORD 21 /* 3d4 */ -#define SV_GREAT_SCIMITAR 22 /* 4d5 */ -#define SV_CLAYMORE 23 /* 2d8 */ -#define SV_ESPADON 24 /* 2d9 */ -#define SV_TWO_HANDED_SWORD 25 /* 3d6 */ -#define SV_FLAMBERGE 26 /* 3d7 */ -#define SV_EXECUTIONERS_SWORD 28 /* 4d5 */ -#define SV_ZWEIHANDER 29 /* 4d6 */ -#define SV_BLADE_OF_CHAOS 30 /* 6d5 */ -#define SV_BLUESTEEL_BLADE 31 /* 3d9 */ -#define SV_SHADOW_BLADE 32 /* 4d4 */ -#define SV_DARK_SWORD 33 /* 3d7 */ - -/* The "sval" codes for TV_SHIELD */ -#define SV_SMALL_LEATHER_SHIELD 2 -#define SV_SMALL_METAL_SHIELD 3 -#define SV_LARGE_LEATHER_SHIELD 4 -#define SV_LARGE_METAL_SHIELD 5 -#define SV_DRAGON_SHIELD 6 -#define SV_SHIELD_OF_DEFLECTION 10 - -/* The "sval" codes for TV_HELM */ -#define SV_HARD_LEATHER_CAP 2 -#define SV_METAL_CAP 3 -#define SV_IRON_HELM 5 -#define SV_STEEL_HELM 6 -#define SV_DRAGON_HELM 7 -#define SV_IRON_CROWN 10 -#define SV_GOLDEN_CROWN 11 -#define SV_JEWELED_CROWN 12 -#define SV_MORGOTH 50 - -/* The "sval" codes for TV_BOOTS */ -#define SV_PAIR_OF_SOFT_LEATHER_BOOTS 2 -#define SV_PAIR_OF_HARD_LEATHER_BOOTS 3 -#define SV_PAIR_OF_METAL_SHOD_BOOTS 6 - -/* The "sval" codes for TV_CLOAK */ -#define SV_CLOAK 1 -#define SV_ELVEN_CLOAK 2 -#define SV_FUR_CLOAK 3 -#define SV_SHADOW_CLOAK 6 - -/* The "sval" codes for TV_GLOVES */ -#define SV_SET_OF_LEATHER_GLOVES 1 -#define SV_SET_OF_GAUNTLETS 2 -#define SV_SET_OF_CESTI 5 - -/* The "sval" codes for TV_SOFT_ARMOR */ -#define SV_FILTHY_RAG 1 -#define SV_ROBE 2 -#define SV_PAPER_ARMOR 3 /* 4 */ -#define SV_SOFT_LEATHER_ARMOR 4 -#define SV_SOFT_STUDDED_LEATHER 5 -#define SV_HARD_LEATHER_ARMOR 6 -#define SV_HARD_STUDDED_LEATHER 7 -#define SV_RHINO_HIDE_ARMOR 8 -#define SV_CORD_ARMOR 9 /* 6 */ -#define SV_PADDED_ARMOR 10 /* 4 */ -#define SV_LEATHER_SCALE_MAIL 11 -#define SV_LEATHER_JACK 12 -#define SV_STONE_AND_HIDE_ARMOR 15 /* 15 */ -#define SV_THUNDERLORD_SUIT 16 - -/* The "sval" codes for TV_HARD_ARMOR */ -#define SV_RUSTY_CHAIN_MAIL 1 /* 14- */ -#define SV_RING_MAIL 2 /* 12 */ -#define SV_METAL_SCALE_MAIL 3 /* 13 */ -#define SV_CHAIN_MAIL 4 /* 14 */ -#define SV_DOUBLE_RING_MAIL 5 /* 15 */ -#define SV_AUGMENTED_CHAIN_MAIL 6 /* 16 */ -#define SV_DOUBLE_CHAIN_MAIL 7 /* 16 */ -#define SV_BAR_CHAIN_MAIL 8 /* 18 */ -#define SV_METAL_BRIGANDINE_ARMOUR 9 /* 19 */ -#define SV_SPLINT_MAIL 10 /* 19 */ -#define SV_PARTIAL_PLATE_ARMOUR 12 /* 22 */ -#define SV_METAL_LAMELLAR_ARMOUR 13 /* 23 */ -#define SV_FULL_PLATE_ARMOUR 15 /* 25 */ -#define SV_RIBBED_PLATE_ARMOUR 18 /* 28 */ -#define SV_MITHRIL_CHAIN_MAIL 20 /* 28+ */ -#define SV_MITHRIL_PLATE_MAIL 25 /* 35+ */ -#define SV_ADAMANTITE_PLATE_MAIL 30 /* 40+ */ - -/* The "sval" codes for TV_DRAG_ARMOR */ -#define SV_DRAGON_BLACK 1 -#define SV_DRAGON_BLUE 2 -#define SV_DRAGON_WHITE 3 -#define SV_DRAGON_RED 4 -#define SV_DRAGON_GREEN 5 -#define SV_DRAGON_MULTIHUED 6 -#define SV_DRAGON_SHINING 10 -#define SV_DRAGON_LAW 12 -#define SV_DRAGON_BRONZE 14 -#define SV_DRAGON_GOLD 16 -#define SV_DRAGON_CHAOS 18 -#define SV_DRAGON_BALANCE 20 -#define SV_DRAGON_POWER 30 - -/* The sval codes for TV_LITE */ -#define SV_LITE_TORCH 0 -#define SV_LITE_LANTERN 1 -#define SV_LITE_TORCH_EVER 2 -#define SV_LITE_DWARVEN 3 -#define SV_LITE_FEANORIAN 4 -#define SV_LITE_GALADRIEL 100 -#define SV_LITE_ELENDIL 101 -#define SV_LITE_THRAIN 102 -#define SV_LITE_UNDEATH 103 -#define SV_LITE_PALANTIR 104 -#define SV_ANCHOR_SPACETIME 105 -#define SV_STONE_LORE 106 - - -/* The "sval" codes for TV_AMULET */ -#define SV_AMULET_DOOM 0 -#define SV_AMULET_TELEPORT 1 -#define SV_AMULET_ADORNMENT 2 -#define SV_AMULET_SLOW_DIGEST 3 -#define SV_AMULET_RESIST_ACID 4 -#define SV_AMULET_SEARCHING 5 -#define SV_AMULET_BRILLANCE 6 -#define SV_AMULET_CHARISMA 7 -#define SV_AMULET_THE_MAGI 8 -#define SV_AMULET_REFLECTION 9 -#define SV_AMULET_CARLAMMAS 10 -#define SV_AMULET_INGWE 11 -#define SV_AMULET_DWARVES 12 -#define SV_AMULET_NO_MAGIC 13 -#define SV_AMULET_NO_TELE 14 -#define SV_AMULET_RESISTANCE 15 -#define SV_AMULET_NOTHING 16 -#define SV_AMULET_SERPENT 17 -#define SV_AMULET_TORIS_MEJISTOS 18 -#define SV_AMULET_TRICKERY 23 -#define SV_AMULET_DEVOTION 25 -#define SV_AMULET_WEAPONMASTERY 24 -#define SV_AMULET_WISDOM 28 -#define SV_AMULET_INFRA 26 -#define SV_AMULET_SPELL 27 - -/* The sval codes for TV_RING */ -#define SV_RING_WOE 0 -#define SV_RING_AGGRAVATION 1 -#define SV_RING_WEAKNESS 2 -#define SV_RING_STUPIDITY 3 -#define SV_RING_TELEPORTATION 4 -#define SV_RING_SPECIAL 5 -#define SV_RING_SLOW_DIGESTION 6 -#define SV_RING_FEATHER_FALL 7 -#define SV_RING_RESIST_FIRE 8 -#define SV_RING_RESIST_COLD 9 -#define SV_RING_SUSTAIN_STR 10 -#define SV_RING_SUSTAIN_INT 11 -#define SV_RING_SUSTAIN_WIS 12 -#define SV_RING_SUSTAIN_DEX 13 -#define SV_RING_SUSTAIN_CON 14 -#define SV_RING_SUSTAIN_CHR 15 -#define SV_RING_PROTECTION 16 -#define SV_RING_ACID 17 -#define SV_RING_FLAMES 18 -#define SV_RING_ICE 19 -#define SV_RING_RESIST_POIS 20 -#define SV_RING_FREE_ACTION 21 -#define SV_RING_SEE_INVIS 22 -#define SV_RING_SEARCHING 23 -#define SV_RING_STR 24 -#define SV_RING_INT 25 -#define SV_RING_DEX 26 -#define SV_RING_CON 27 -#define SV_RING_ACCURACY 28 -#define SV_RING_DAMAGE 29 -#define SV_RING_SLAYING 30 -#define SV_RING_SPEED 31 -#define SV_RING_BARAHIR 32 -#define SV_RING_TULKAS 33 -#define SV_RING_NARYA 34 -#define SV_RING_NENYA 35 -#define SV_RING_VILYA 36 -#define SV_RING_POWER 37 -#define SV_RING_RES_FEAR 38 -#define SV_RING_RES_LD 39 -#define SV_RING_RES_NETHER 40 -#define SV_RING_RES_NEXUS 41 -#define SV_RING_RES_SOUND 42 -#define SV_RING_RES_CONFUSION 43 -#define SV_RING_RES_SHARDS 44 -#define SV_RING_RES_DISENCHANT 45 -#define SV_RING_RES_CHAOS 46 -#define SV_RING_RES_BLINDNESS 47 -#define SV_RING_LORDLY 48 -#define SV_RING_ATTACKS 49 -#define SV_RING_NOTHING 50 -#define SV_RING_PRECONITION 51 -#define SV_RING_FLAR 52 -#define SV_RING_INVIS 53 -#define SV_RING_FLYING 54 -#define SV_RING_WRAITH 55 -#define SV_RING_ELEC 56 -#define SV_RING_CRIT 57 -#define SV_RING_SPELL 58 - -/* The "sval" codes for TV_STAFF */ -#define SV_STAFF_SCHOOL 1 -#define SV_STAFF_NOTHING 2 - -/* The "sval" codes for TV_WAND */ -#define SV_WAND_SCHOOL 1 -#define SV_WAND_NOTHING 2 - -/* The "sval" codes for TV_ROD(Rod Tips) */ -#define SV_ROD_NOTHING 0 -#define SV_ROD_DETECT_DOOR 1 -#define SV_ROD_IDENTIFY 2 -#define SV_ROD_RECALL 3 -#define SV_ROD_ILLUMINATION 4 -#define SV_ROD_MAPPING 5 -#define SV_ROD_DETECTION 6 -#define SV_ROD_PROBING 7 -#define SV_ROD_CURING 8 -#define SV_ROD_HEALING 9 -#define SV_ROD_RESTORATION 10 -#define SV_ROD_SPEED 11 -/* xxx (aimed) */ -#define SV_ROD_TELEPORT_AWAY 13 -#define SV_ROD_DISARMING 14 -#define SV_ROD_LITE 15 -#define SV_ROD_SLEEP_MONSTER 16 -#define SV_ROD_SLOW_MONSTER 17 -#define SV_ROD_DRAIN_LIFE 18 -#define SV_ROD_POLYMORPH 19 -#define SV_ROD_ACID_BOLT 20 -#define SV_ROD_ELEC_BOLT 21 -#define SV_ROD_FIRE_BOLT 22 -#define SV_ROD_COLD_BOLT 23 -#define SV_ROD_ACID_BALL 24 -#define SV_ROD_ELEC_BALL 25 -#define SV_ROD_FIRE_BALL 26 -#define SV_ROD_COLD_BALL 27 -#define SV_ROD_HAVOC 28 -#define SV_ROD_DETECT_TRAP 29 -#define SV_ROD_HOME 30 - - -/* The "sval" codes for TV_ROD_MAIN(Rods) */ -/* Note that the sval is the max mana capacity of the rod */ - -#define SV_ROD_WOODEN 10 -#define SV_ROD_COPPER 20 -#define SV_ROD_IRON 50 -#define SV_ROD_ALUMINIUM 75 -#define SV_ROD_SILVER 100 -#define SV_ROD_GOLDEN 125 -#define SV_ROD_MITHRIL 160 -#define SV_ROD_ADMANTITE 200 - - -/* The "sval" codes for TV_SCROLL */ - -#define SV_SCROLL_DARKNESS 0 -#define SV_SCROLL_AGGRAVATE_MONSTER 1 -#define SV_SCROLL_CURSE_ARMOR 2 -#define SV_SCROLL_CURSE_WEAPON 3 -#define SV_SCROLL_SUMMON_MONSTER 4 -#define SV_SCROLL_SUMMON_UNDEAD 5 -#define SV_SCROLL_SUMMON_MINE 6 -#define SV_SCROLL_TRAP_CREATION 7 -#define SV_SCROLL_PHASE_DOOR 8 -#define SV_SCROLL_TELEPORT 9 -#define SV_SCROLL_TELEPORT_LEVEL 10 -#define SV_SCROLL_WORD_OF_RECALL 11 -#define SV_SCROLL_IDENTIFY 12 -#define SV_SCROLL_STAR_IDENTIFY 13 -#define SV_SCROLL_REMOVE_CURSE 14 -#define SV_SCROLL_STAR_REMOVE_CURSE 15 -#define SV_SCROLL_ENCHANT_ARMOR 16 -#define SV_SCROLL_ENCHANT_WEAPON_TO_HIT 17 -#define SV_SCROLL_ENCHANT_WEAPON_TO_DAM 18 -#define SV_SCROLL_ENCHANT_WEAPON_PVAL 19 -#define SV_SCROLL_STAR_ENCHANT_ARMOR 20 -#define SV_SCROLL_STAR_ENCHANT_WEAPON 21 -#define SV_SCROLL_RECHARGING 22 -#define SV_SCROLL_RESET_RECALL 23 -#define SV_SCROLL_LIGHT 24 -#define SV_SCROLL_MAPPING 25 -#define SV_SCROLL_DETECT_GOLD 26 -#define SV_SCROLL_DETECT_ITEM 27 -#define SV_SCROLL_DETECT_TRAP 28 -#define SV_SCROLL_DETECT_DOOR 29 -#define SV_SCROLL_DETECT_INVIS 30 -#define SV_SCROLL_DIVINATION 31 -#define SV_SCROLL_SATISFY_HUNGER 32 -#define SV_SCROLL_BLESSING 33 -#define SV_SCROLL_HOLY_CHANT 34 -#define SV_SCROLL_HOLY_PRAYER 35 -#define SV_SCROLL_MONSTER_CONFUSION 36 -#define SV_SCROLL_PROTECTION_FROM_EVIL 37 -#define SV_SCROLL_RUNE_OF_PROTECTION 38 -#define SV_SCROLL_TRAP_DOOR_DESTRUCTION 39 -#define SV_SCROLL_DEINCARNATION 40 -#define SV_SCROLL_STAR_DESTRUCTION 41 -#define SV_SCROLL_DISPEL_UNDEAD 42 -#define SV_SCROLL_MASS_RESURECTION 43 -#define SV_SCROLL_GENOCIDE 44 -#define SV_SCROLL_MASS_GENOCIDE 45 -#define SV_SCROLL_ACQUIREMENT 46 -#define SV_SCROLL_STAR_ACQUIREMENT 47 -#define SV_SCROLL_FIRE 48 -#define SV_SCROLL_ICE 49 -#define SV_SCROLL_CHAOS 50 -#define SV_SCROLL_RUMOR 51 -#define SV_SCROLL_ARTIFACT 52 -#define SV_SCROLL_NOTHING 53 - -/* The "sval" codes for TV_POTION */ -#define SV_POTION_WATER 0 -#define SV_POTION_APPLE_JUICE 1 -#define SV_POTION_SLIME_MOLD 2 -#define SV_POTION_BLOOD 3 -#define SV_POTION_SLOWNESS 4 -#define SV_POTION_SALT_WATER 5 -#define SV_POTION_POISON 6 -#define SV_POTION_BLINDNESS 7 -#define SV_POTION_INVIS 8 -#define SV_POTION_CONFUSION 9 -#define SV_POTION_MUTATION 10 -#define SV_POTION_SLEEP 11 -#define SV_POTION_LEARNING 12 -#define SV_POTION_LOSE_MEMORIES 13 -/* xxx */ -#define SV_POTION_RUINATION 15 -#define SV_POTION_DEC_STR 16 -#define SV_POTION_DEC_INT 17 -#define SV_POTION_DEC_WIS 18 -#define SV_POTION_DEC_DEX 19 -#define SV_POTION_DEC_CON 20 -#define SV_POTION_DEC_CHR 21 -#define SV_POTION_DETONATIONS 22 -#define SV_POTION_DEATH 23 -#define SV_POTION_INFRAVISION 24 -#define SV_POTION_DETECT_INVIS 25 -#define SV_POTION_SLOW_POISON 26 -#define SV_POTION_CURE_POISON 27 -#define SV_POTION_BOLDNESS 28 -#define SV_POTION_SPEED 29 -#define SV_POTION_RESIST_HEAT 30 -#define SV_POTION_RESIST_COLD 31 -#define SV_POTION_HEROISM 32 -#define SV_POTION_BESERK_STRENGTH 33 -#define SV_POTION_CURE_LIGHT 34 -#define SV_POTION_CURE_SERIOUS 35 -#define SV_POTION_CURE_CRITICAL 36 -#define SV_POTION_HEALING 37 -#define SV_POTION_STAR_HEALING 38 -#define SV_POTION_LIFE 39 -#define SV_POTION_RESTORE_MANA 40 -#define SV_POTION_RESTORE_EXP 41 -#define SV_POTION_RES_STR 42 -#define SV_POTION_RES_INT 43 -#define SV_POTION_RES_WIS 44 -#define SV_POTION_RES_DEX 45 -#define SV_POTION_RES_CON 46 -#define SV_POTION_RES_CHR 47 -#define SV_POTION_INC_STR 48 -#define SV_POTION_INC_INT 49 -#define SV_POTION_INC_WIS 50 -#define SV_POTION_INC_DEX 51 -#define SV_POTION_INC_CON 52 -#define SV_POTION_INC_CHR 53 -/* xxx */ -#define SV_POTION_AUGMENTATION 55 -#define SV_POTION_ENLIGHTENMENT 56 -#define SV_POTION_STAR_ENLIGHTENMENT 57 -#define SV_POTION_SELF_KNOWLEDGE 58 -#define SV_POTION_EXPERIENCE 59 -#define SV_POTION_RESISTANCE 60 -#define SV_POTION_CURING 61 -#define SV_POTION_INVULNERABILITY 62 -#define SV_POTION_NEW_LIFE 63 - -#define SV_POTION_LAST 63 - -/* The "sval" codes for TV_POTION2 */ -#define SV_POTION2_MIMIC 1 -#define SV_POTION2_CURE_LIGHT_SANITY 14 -#define SV_POTION2_CURE_SERIOUS_SANITY 15 -#define SV_POTION2_CURE_CRITICAL_SANITY 16 -#define SV_POTION2_CURE_SANITY 17 -#define SV_POTION2_CURE_WATER 18 - -#define SV_POTION2_LAST 18 - -/* The "sval" codes for TV_FOOD */ -#define SV_FOOD_POISON 0 -#define SV_FOOD_BLINDNESS 1 -#define SV_FOOD_PARANOIA 2 -#define SV_FOOD_CONFUSION 3 -#define SV_FOOD_HALLUCINATION 4 -#define SV_FOOD_PARALYSIS 5 -#define SV_FOOD_WEAKNESS 6 -#define SV_FOOD_SICKNESS 7 -#define SV_FOOD_STUPIDITY 8 -#define SV_FOOD_NAIVETY 9 -#define SV_FOOD_UNHEALTH 10 -#define SV_FOOD_DISEASE 11 -#define SV_FOOD_CURE_POISON 12 -#define SV_FOOD_CURE_BLINDNESS 13 -#define SV_FOOD_CURE_PARANOIA 14 -#define SV_FOOD_CURE_CONFUSION 15 -#define SV_FOOD_CURE_SERIOUS 16 -#define SV_FOOD_RESTORE_STR 17 -#define SV_FOOD_RESTORE_CON 18 -#define SV_FOOD_RESTORING 19 -/* many missing mushrooms */ -#define SV_FOOD_BISCUIT 32 -#define SV_FOOD_JERKY 33 -#define SV_FOOD_RATION 35 -#define SV_FOOD_SLIME_MOLD 36 -#define SV_FOOD_WAYBREAD 37 -#define SV_FOOD_PINT_OF_ALE 38 -#define SV_FOOD_PINT_OF_WINE 39 -#define SV_FOOD_ATHELAS 40 -#define SV_FOOD_GREAT_HEALTH 41 -#define SV_FOOD_FORTUNE_COOKIE 42 - -/* The "sval" codes for TV_BATERIE */ -#define SV_BATERIE_POISON 1 -#define SV_BATERIE_EXPLOSION 2 -#define SV_BATERIE_TELEPORT 3 -#define SV_BATERIE_COLD 4 -#define SV_BATERIE_FIRE 5 -#define SV_BATERIE_ACID 6 -#define SV_BATERIE_LIFE 7 -#define SV_BATERIE_CONFUSION 8 -#define SV_BATERIE_LITE 9 -#define SV_BATERIE_CHAOS 10 -#define SV_BATERIE_TIME 11 -#define SV_BATERIE_MAGIC 12 -#define SV_BATERIE_XTRA_LIFE 13 -#define SV_BATERIE_DARKNESS 14 -#define SV_BATERIE_KNOWLEDGE 15 -#define SV_BATERIE_FORCE 16 -#define SV_BATERIE_LIGHTNING 17 -#define SV_BATERIE_MANA 18 - -/* The "sval" codes for TV_CORPSE */ -#define SV_CORPSE_CORPSE 1 -#define SV_CORPSE_SKELETON 2 -#define SV_CORPSE_HEAD 3 -#define SV_CORPSE_SKULL 4 -#define SV_CORPSE_MEAT 5 - -/* - * Special Object Flags - */ -#define IDENT_SENSE 0x01 /* Item has been "sensed" */ -#define IDENT_FIXED 0x02 /* Item has been "haggled" */ -#define IDENT_EMPTY 0x04 /* Item charges are known */ -#define IDENT_KNOWN 0x08 /* Item abilities are known */ -#define IDENT_STOREB 0x10 /* Item is storebought !!!! */ -#define IDENT_MENTAL 0x20 /* Item information is known */ -#define IDENT_CURSED 0x40 /* Item is temporarily cursed */ - -/* - * Location of objects when they were found - */ -#define OBJ_FOUND_MONSTER 1 -#define OBJ_FOUND_FLOOR 2 -#define OBJ_FOUND_VAULT 3 -#define OBJ_FOUND_SPECIAL 4 -#define OBJ_FOUND_RUBBLE 5 -#define OBJ_FOUND_REWARD 6 -#define OBJ_FOUND_STORE 7 -#define OBJ_FOUND_STOLEN 8 -#define OBJ_FOUND_SELFMADE 9 - -struct obj_theme -{ - byte treasure; - byte combat; - byte magic; - byte tools; -}; - -struct object_kind -{ - u32b name; /* Name (offset) */ - u32b text; /* Text (offset) */ - - byte tval; /* Object type */ - byte sval; /* Object sub type */ - - s32b pval; /* Object extra info */ - s32b pval2; /* Object extra info */ - - s16b to_h; /* Bonus to hit */ - s16b to_d; /* Bonus to damage */ - s16b to_a; /* Bonus to armor */ - - s16b ac; /* Base armor */ - - byte dd; - byte ds; /* Damage dice/sides */ - - s32b weight; /* Weight */ - - s32b cost; /* Object "base cost" */ - - u32b flags1; /* Flags, set 1 */ - u32b flags2; /* Flags, set 2 */ - u32b flags3; /* Flags, set 3 */ - u32b flags4; /* Flags, set 4 */ - u32b flags5; /* Flags, set 5 */ - - byte locale[4]; /* Allocation level(s) */ - byte chance[4]; /* Allocation chance(s) */ - - byte level; /* Level */ - byte extra; /* Something */ - - - byte d_attr; /* Default object attribute */ - char d_char; /* Default object character */ - - - byte x_attr; /* Desired object attribute */ - char x_char; /* Desired object character */ - - - byte flavor; /* Special object flavor (or zero) */ - - bool easy_know; /* This object is always known (if aware) */ - - - bool aware; /* The player is "aware" of the item's effects */ - - bool tried; /* The player has "tried" one of the items */ - - bool know; /* extractable flag for the alchemist */ - - u32b esp; /* ESP flags */ - - byte btval; /* Become Object type */ - byte bsval; /* Become Object sub type */ - bool artifact; /* Is it a normal artifact(already generated) */ - - s16b power; /* Power granted(if any) */ -}; - -struct artifact_type -{ - u32b name; /* Name (offset) */ - u32b text; /* Text (offset) */ - - byte tval; /* Artifact type */ - byte sval; /* Artifact sub type */ - - s16b pval; /* Artifact extra info */ - - s16b to_h; /* Bonus to hit */ - s16b to_d; /* Bonus to damage */ - s16b to_a; /* Bonus to armor */ - - s16b ac; /* Base armor */ - - byte dd; - byte ds; /* Damage when hits */ - - s16b weight; /* Weight */ - - s32b cost; /* Artifact "cost" */ - - u32b flags1; /* Artifact Flags, set 1 */ - u32b flags2; /* Artifact Flags, set 2 */ - u32b flags3; /* Artifact Flags, set 3 */ - u32b flags4; /* Artifact Flags, set 4 */ - u32b flags5; /* Artifact Flags, set 5 */ - - byte level; /* Artifact level */ - byte rarity; /* Artifact rarity */ - - byte cur_num; /* Number created (0 or 1) */ - byte max_num; /* Unused (should be "1") */ - - u32b esp; /* ESP flags */ - - s16b power; /* Power granted(if any) */ -}; - -struct ego_item_type -{ - u32b name; /* Name (offset) */ - u32b text; /* Text (offset) */ - - bool before; /* Before or after the object name ? */ - - byte tval[6]; - byte min_sval[6]; - byte max_sval[6]; - - byte rating; /* Rating boost */ - - byte level; /* Minimum level */ - byte rarity; /* Object rarity */ - byte mrarity; /* Object rarity */ - - s16b max_to_h; /* Maximum to-hit bonus */ - s16b max_to_d; /* Maximum to-dam bonus */ - s16b max_to_a; /* Maximum to-ac bonus */ - - s32b max_pval; /* Maximum pval */ - - s32b cost; /* Ego-item "cost" */ - - byte rar[5]; - u32b flags1[5]; /* Ego-Item Flags, set 1 */ - u32b flags2[5]; /* Ego-Item Flags, set 2 */ - u32b flags3[5]; /* Ego-Item Flags, set 3 */ - u32b flags4[5]; /* Ego-Item Flags, set 4 */ - u32b flags5[5]; /* Ego-Item Flags, set 5 */ - u32b esp[5]; /* ESP flags */ - u32b fego[5]; /* ego flags */ - - s16b power; /* Power granted(if any) */ -}; - -struct object_type -{ - s16b k_idx; /* Kind index (zero if "dead") */ - - byte iy; /* Y-position on map, or zero */ - byte ix; /* X-position on map, or zero */ - - byte tval; /* Item type (from kind) */ - byte sval; /* Item sub-type (from kind) */ - - s32b pval; /* Item extra-parameter */ - s16b pval2; /* Item extra-parameter for some special - items*/ - s32b pval3; /* Item extra-parameter for some special - items*/ - - byte discount; /* Discount (if any) */ - - byte number; /* Number of items */ - - s32b weight; /* Item weight */ - - byte elevel; /* Item exp level */ - s32b exp; /* Item exp */ - - byte name1; /* Artifact type, if any */ - s16b name2; /* Ego-Item type, if any */ - s16b name2b; /* Second Ego-Item type, if any */ - - byte xtra1; /* Extra info type */ - s16b xtra2; /* Extra info index */ - - s16b to_h; /* Plusses to hit */ - s16b to_d; /* Plusses to damage */ - s16b to_a; /* Plusses to AC */ - - s16b ac; /* Normal AC */ - - byte dd; - byte ds; /* Damage dice/sides */ - - s16b timeout; /* Timeout Counter */ - - byte ident; /* Special flags */ - - byte marked; /* Object is marked */ - - u16b note; /* Inscription index */ - u16b art_name; /* Artifact name (random artifacts) */ - - u32b art_flags1; /* Flags, set 1 Alas, these were necessary */ - u32b art_flags2; /* Flags, set 2 for the random artifacts of*/ - u32b art_flags3; /* Flags, set 3 Zangband */ - u32b art_flags4; /* Flags, set 4 PernAngband */ - u32b art_flags5; /* Flags, set 5 PernAngband */ - u32b art_esp; /* Flags, set esp PernAngband */ - - s16b next_o_idx; /* Next object in stack (if any) */ - - s16b held_m_idx; /* Monster holding us (if any) */ - - byte sense; /* Pseudo-id status */ - - byte found; /* How did we find it */ - s16b found_aux1; /* Stores info for found */ - s16b found_aux2; /* Stores info for found */ -}; - -/* Pseudo-id defines */ -#define SENSE_NONE 0 -#define SENSE_CURSED 1 -#define SENSE_AVERAGE 2 -#define SENSE_GOOD_LIGHT 3 -#define SENSE_GOOD_HEAVY 4 -#define SENSE_EXCELLENT 5 -#define SENSE_WORTHLESS 6 -#define SENSE_TERRIBLE 7 -#define SENSE_SPECIAL 8 -#define SENSE_BROKEN 9 -#define SENSE_UNCURSED 10 - -extern object_type o_list[max_o_idx]; -extern object_kind k_info[max_k_idx]; -extern char *k_name; -extern char *k_text; -extern artifact_type a_info[max_a_idx]; -extern char *a_name; -extern char *a_text; -extern header *e_head; -extern ego_item_type e_info[max_e_idx]; -extern char *e_name; -extern char *e_text; - -extern s16b m_bonus(int max, int level); -extern s16b wield_slot_ideal(object_type *o_ptr, bool ideal); -extern s16b wield_slot(object_type *o_ptr); -extern void object_flags(object_type *o_ptr, u32b *f1 = 0, u32b *f2 = 0, u32b *f3 = 0, u32b *f4 = 0, u32b *f5 = 0, u32b *esp = 0); -extern char *lua_object_desc @ object_desc(object_type *o_ptr, int pref, int mode); -extern bool object_out_desc(object_type *o_ptr, FILE *fff, bool trim_down, bool wait_for_it); -extern void inven_item_describe(int item); -extern void inven_item_increase(int item, int num); -extern bool inven_item_optimize(int item); -extern void floor_item_describe(int item); -extern void floor_item_increase(int item, int num); -extern void floor_item_optimize(int item); -extern void delete_object_idx(int o_idx); -extern s16b o_pop(void); -extern errr get_obj_num_prep(void); -extern bool ident_all(void); -extern s16b get_obj_num(int level); -extern s16b lookup_kind(int tval, int sval); -extern void object_wipe(object_type *o_ptr); -extern void object_prep(object_type *o_ptr, int k_idx); -extern void object_copy(object_type *o_ptr, object_type *j_ptr); -extern bool inven_carry_okay(object_type *o_ptr); -extern void apply_magic(object_type *o_ptr, int lev, bool okay, bool good, bool great); -extern bool make_object(object_type *j_ptr, bool good, bool great, obj_theme theme); -extern s16b drop_near(object_type *o_ptr, int chance, int y, int x); -extern object_type *get_object(int item); -extern object_type *new_object(); -extern void end_object(object_type *o_ptr); -extern void identify_pack_fully(void); -extern s16b inven_carry(object_type *o_ptr, bool final); -extern s32b calc_total_weight(void); -extern int get_slot(int slot); -extern bool is_blessed(object_type *o_ptr); -extern cptr sense_desc[1000]; /* 1000 is just a hack for tolua */ -extern void object_pickup(int this_o_idx); - -$static bool lua_is_artifact(object_type *o_ptr) { return artifact_p(o_ptr); } -static bool lua_is_artifact@is_artifact(object_type *o_ptr); - -$static bool lua_is_aware(object_type *o_ptr) { return object_aware_p(o_ptr); } -static bool lua_is_aware@is_aware(object_type *o_ptr); - -$static bool lua_is_known(object_type *o_ptr) { return object_known_p(o_ptr); } -static bool lua_is_known@is_known(object_type *o_ptr); - -$static void lua_set_aware(object_type *o_ptr) { object_aware(o_ptr); } -static void lua_set_aware@set_aware(object_type *o_ptr); - -$static void lua_set_known(object_type *o_ptr) { object_known(o_ptr); } -static void lua_set_known@set_known(object_type *o_ptr); - -extern byte value_check_aux1(object_type *o_ptr); -extern byte value_check_aux1_magic(object_type *o_ptr); -extern byte value_check_aux2(object_type *o_ptr); -extern byte value_check_aux2_magic(object_type *o_ptr); - -extern bool remove_curse_object(object_type *o_ptr, bool all); diff --git a/src/player.pkg b/src/player.pkg deleted file mode 100644 index 9115d7cf..00000000 --- a/src/player.pkg +++ /dev/null @@ -1,3446 +0,0 @@ -/* File: player.pkg */ - -/* - * Purpose: Lua interface defitions for the player. - * To be processed by tolua to generate C source code. - */ - -$#include "angband.h" - -/** @typedef cptr - * @note String - */ -typedef char* cptr; -/** @typedef errr - * @note Number - */ -typedef int errr; -/** @typedef bool - * @note Boolean - */ -typedef unsigned char bool; -/** @typedef byte - * @note Number - */ -typedef unsigned char byte; -/** @typedef s16b - * @note Number - */ -typedef signed short s16b; -/** @typedef u16b - * @note Number - */ -typedef unsigned short u16b; -/** @typedef s32b - * @note Number - */ -typedef signed int s32b; -/** @typedef u32b - * @note Number - */ -typedef unsigned int u32b; - -/** @def PY_MAX_LEVEL - * @note Maximum level - */ -#define PY_MAX_LEVEL 50 - -/** @var player_exp[PY_MAX_LEVEL] - * @brief Number - * @note Array of experience points per level. - */ -extern s32b player_exp[PY_MAX_LEVEL]; - -/** @name Attributes - * @brief Indexes of the various "stats" (hard-coded by savefiles, etc). - * @{ */ -/** @def A_STR - * @note Strength */ -#define A_STR 0 - -/** @def A_INT - * @note Intelligence */ -#define A_INT 1 - -/** @def A_WIS - * @note Wisdom */ -#define A_WIS 2 - -/** @def A_DEX - * @note Dexterity */ -#define A_DEX 3 - -/** @def A_CON - * @note Constitution */ -#define A_CON 4 - -/** @def A_CHR - * @note Charisma */ -#define A_CHR 5 -/** @} */ - -/* Ugly hack, should be in foo-info, the subrace saved to the savefile */ -/** @def SUBRACE_SAVE */ -#define SUBRACE_SAVE 9 - - -/** @name Sex - * @brief Player sex constants (hard-coded by save-files, arrays, etc) - * @{ */ -/** @def SEX_FEMALE */ -#define SEX_FEMALE 0 - -/** @def SEX_MALE */ -#define SEX_MALE 1 - -/** @def SEX_NEUTER */ -#define SEX_NEUTER 2 - - -/** @def MAX_SEXES */ -#define MAX_SEXES 3 -/** @} */ - -/** @name Race flags - * @{ */ -/** @def PR1_EXPERIMENTAL - * @note Is still under developemnt - */ -#define PR1_EXPERIMENTAL 0x00000001L -/* XXX */ -/** @def PR1_RESIST_BLACK_BREATH - * @note Resist black breath - */ -#define PR1_RESIST_BLACK_BREATH 0x00000004L -/** @def PR1_NO_STUN - * @note Never stunned - */ -#define PR1_NO_STUN 0x00000008L -/** @def PR1_XTRA_MIGHT_BOW - * @note Xtra might with bows - */ -#define PR1_XTRA_MIGHT_BOW 0x00000010L -/** @def PR1_XTRA_MIGHT_XBOW - * @note Xtra might with xbows - */ -#define PR1_XTRA_MIGHT_XBOW 0x00000020L -/** @def PR1_XTRA_MIGHT_SLING - * @note Xtra might with slings - */ -#define PR1_XTRA_MIGHT_SLING 0x00000040L -/** @def PR1_AC_LEVEL - * @note More AC with levels - */ -#define PR1_AC_LEVEL 0x00000080L -/** @def PR1_HURT_LITE - * @note Hurt by light - */ -#define PR1_HURT_LITE 0x00000100L -/** @def PR1_VAMPIRE - * @note Vampire - */ -#define PR1_VAMPIRE 0x00000200L -/** @def PR1_UNDEAD - * @note Undead - */ -#define PR1_UNDEAD 0x00000400L -/** @def PR1_NO_CUT - * @note no cuts - */ -#define PR1_NO_CUT 0x00000800L -/** @def PR1_CORRUPT - * @note hack-- corrupted - */ -#define PR1_CORRUPT 0x00001000L -/** @def PR1_NO_FOOD - * @note little gain from food - */ -#define PR1_NO_FOOD 0x00002000L -/** @def PR1_NO_GOD - * @note cannot worship - */ -#define PR1_NO_GOD 0x00004000L -/* XXX */ -/** @def PR1_ELF - * @note Is an elf - */ -#define PR1_ELF 0x00010000L -/** @def PR1_SEMI_WRAITH - * @note Takes damage when going in walls - */ -#define PR1_SEMI_WRAITH 0x00020000L -/** @def PR1_NO_SUBRACE_CHANGE - * @note Impossible to change subrace - */ -#define PR1_NO_SUBRACE_CHANGE 0x00040000L -/* XXX */ -/** @def PR1_ANTIMAGIC - * @note antimagic ... hack - */ -#define PR1_ANTIMAGIC 0x00100000L -/** @def PR1_MOLD_FRIEND - * @note Not attacked by molds wielded - */ -#define PR1_MOLD_FRIEND 0x00200000L -/** @def PR1_GOD_FRIEND - * @note Better grace - */ -#define PR1_GOD_FRIEND 0x00400000L -/* XXX */ -/** @def PR1_INNATE_SPELLS - * @note KNown all spells, only need books - */ -#define PR1_INNATE_SPELLS 0x01000000L -/* XXX */ -/* XXX */ -/** @def PR1_EASE_STEAL - * @note Gain xp by stealing - */ -#define PR1_EASE_STEAL 0x08000000L -/* XXX */ -/* XXX */ -/* XXX */ -/* XXX */ - -/* XXX */ -/** @def PR2_ASTRAL - * @note Is it an astral being coming from th halls of mandos ? - */ -#define PR2_ASTRAL 0x00000002L -/* XXX */ -/** @} */ - -/** @name Notice flags - * @brief Bit flags for the "p_ptr->notice" variable - * @{ */ -/** @def PN_COMBINE - * @note Combine the pack - */ -#define PN_COMBINE 0x00000001L -/** @def PN_REORDER - * @note Reorder the pack - */ -#define PN_REORDER 0x00000002L -/* xxx (many) */ -/** @} */ - - -/** @name Update flags - * @brief Bit flags for the "p_ptr->update" variable - * @{ */ -/** @def PU_BONUS - * @note Calculate bonuses - */ -#define PU_BONUS 0x00000001L -/** @def PU_TORCH - * @note Calculate torch radius - */ -#define PU_TORCH 0x00000002L -/** @def PU_BODY - * @note Calculate body parts - */ -#define PU_BODY 0x00000004L -/** @def PU_SANITY - * @note Calculate csan and msan - */ -#define PU_SANITY 0x00000008L -/** @def PU_HP - * @note Calculate chp and mhp - */ -#define PU_HP 0x00000010L -/** @def PU_MANA - * @note Calculate csp and msp - */ -#define PU_MANA 0x00000020L -/** @def PU_SPELLS - * @note Calculate spells - */ -#define PU_SPELLS 0x00000040L -/** @def PU_POWERS - * @note Calculate powers - */ -#define PU_POWERS 0x00000080L -/* xxx (many) */ -/** @def PU_UN_VIEW - * @note Forget view - */ -#define PU_UN_VIEW 0x00010000L -/* xxx (many) */ -/** @def PU_VIEW - * @note Update view - */ -#define PU_VIEW 0x00100000L -/** @def PU_MON_LITE - * @note Update monster light - */ -#define PU_MON_LITE 0x00200000L -/* xxx */ -/** @def PU_MONSTERS - * @note Update monsters - */ -#define PU_MONSTERS 0x01000000L -/** @def PU_DISTANCE - * @note Update distances - */ -#define PU_DISTANCE 0x02000000L -/* xxx */ -/** @def PU_FLOW - * @note Update flow - */ -#define PU_FLOW 0x10000000L -/* xxx (many) */ -/** @} */ - - -/** @name Redraw flags - * @brief Bit flags for the "p_ptr->redraw" variable - * @{ */ -/** @def PR_MISC - * @note Display Race/Class - */ -#define PR_MISC 0x00000001L -/** @def PR_TITLE - * @note Display Title - */ -#define PR_TITLE 0x00000002L -/** @def PR_LEV - * @note Display Level - */ -#define PR_LEV 0x00000004L -/** @def PR_EXP - * @note Display Experience - */ -#define PR_EXP 0x00000008L -/** @def PR_STATS - * @note Display Stats - */ -#define PR_STATS 0x00000010L -/** @def PR_ARMOR - * @note Display Armor - */ -#define PR_ARMOR 0x00000020L -/** @def PR_HP - * @note Display Hitpoints - */ -#define PR_HP 0x00000040L -/** @def PR_MANA - * @note Display Mana - */ -#define PR_MANA 0x00000080L -/** @def PR_GOLD - * @note Display Gold - */ -#define PR_GOLD 0x00000100L -/** @def PR_DEPTH - * @note Display Depth - */ -#define PR_DEPTH 0x00000200L -/****/ -/** @def PR_HEALTH - * @note Display Health Bar - */ -#define PR_HEALTH 0x00000800L -/** @def PR_CUT - * @note Display Extra (Cut) - */ -#define PR_CUT 0x00001000L -/** @def PR_STUN - * @note Display Extra (Stun) - */ -#define PR_STUN 0x00002000L -/** @def PR_HUNGER - * @note Display Extra (Hunger) - */ -#define PR_HUNGER 0x00004000L -/** @def PR_PIETY - * @note Display Piety - */ -#define PR_PIETY 0x00008000L -/** @def PR_BLIND - * @note Display Extra (Blind) - */ -#define PR_BLIND 0x00010000L -/** @def PR_CONFUSED - * @note Display Extra (Confused) - */ -#define PR_CONFUSED 0x00020000L -/** @def PR_AFRAID - * @note Display Extra (Afraid) - */ -#define PR_AFRAID 0x00040000L -/** @def PR_POISONED - * @note Display Extra (Poisoned) - */ -#define PR_POISONED 0x00080000L -/** @def PR_STATE - * @note Display Extra (State) - */ -#define PR_STATE 0x00100000L -/** @def PR_SPEED - * @note Display Extra (Speed) - */ -#define PR_SPEED 0x00200000L -/** @def PR_STUDY - * @note Display Extra (Study) - */ -#define PR_STUDY 0x00400000L -/** @def PR_SANITY - * @note Display Sanity - */ -#define PR_SANITY 0x00800000L -/** @def PR_EXTRA - * @note Display Extra Info - */ -#define PR_EXTRA 0x01000000L -/** @def PR_BASIC - * @note Display Basic Info - */ -#define PR_BASIC 0x02000000L -/** @def PR_MAP - * @note Display Map - */ -#define PR_MAP 0x04000000L -/** @def PR_WIPE - * @note Hack -- Total Redraw - */ -#define PR_WIPE 0x08000000L -/** @def PR_MH - * @note Display Monster hitpoints - */ -#define PR_MH 0x10000000L -/** @def PR_MH - * @note Display Monster hitpoints - */ -#define PR_MH 0x10000000L -/** @def PR_DTRAP - * @note Display Extra (DTrap) - */ -#define PR_DTRAP 0x20000000L -/* xxx */ -/* xxx */ -/** @} */ - - -/** @name Window flags - * @brief Bit flags for the "p_ptr->window" variable (etc) - * @{ */ -/** @def PW_INVEN - * @note Display inven/equip - */ -#define PW_INVEN 0x00000001L -/** @def PW_EQUIP - * @note Display equip/inven - */ -#define PW_EQUIP 0x00000002L -/* xxx */ -/** @def PW_PLAYER - * @note Display character - */ -#define PW_PLAYER 0x00000008L -/** @def PW_M_LIST - * @note Show monster list - */ -#define PW_M_LIST 0x00000010L -/* xxx */ -/** @def PW_MESSAGE - * @note Display messages - */ -#define PW_MESSAGE 0x00000040L -/** @def PW_OVERHEAD - * @note Display overhead view - */ -#define PW_OVERHEAD 0x00000080L -/** @def PW_MONSTER - * @note Display monster recall - */ -#define PW_MONSTER 0x00000100L -/** @def PW_OBJECT - * @note Display object recall - */ -#define PW_OBJECT 0x00000200L -/* xxx */ -/** @def PW_SNAPSHOT - * @note Display snap-shot - */ -#define PW_SNAPSHOT 0x00000800L -/* xxx */ -/* xxx */ -/** @def PW_BORG_1 - * @note Display borg messages - */ -#define PW_BORG_1 0x00004000L -/** @def PW_BORG_2 - * @note Display borg status - */ -#define PW_BORG_2 0x00008000L -/** @} */ - -/** @name Body parts - * @{ */ -/** @def BODY_WEAPON */ -#define BODY_WEAPON 0 - -/** @def BODY_TORSO */ -#define BODY_TORSO 1 - -/** @def BODY_ARMS */ -#define BODY_ARMS 2 - -/** @def BODY_FINGER */ -#define BODY_FINGER 3 - -/** @def BODY_HEAD */ -#define BODY_HEAD 4 - -/** @def BODY_LEGS */ -#define BODY_LEGS 5 - -/** @def BODY_MAX */ -#define BODY_MAX 6 -/** @} */ - - -/** @struct player_type - */ -struct player_type -{ - /** @structvar lives - * @brief Number - * @note How many times we resurected - */ - s32b lives; - - /** @structvar oldpy - * @brief Number - * @note Previous player location -KMW- - */ - s16b oldpy; - /** @structvar oldpx - * @brief Number - * @note Previous player location -KMW- - */ - s16b oldpx; - - /** @structvar py - * @brief Number - * @note Player location - */ - s16b py; - /** @structvar px - * @brief Number - * @note Player location - */ - s16b px; - - /** @structvar psex - * @brief Number - * @note Sex index - */ - byte psex; - /** @structvar prace - * @brief Number - * @note Race index - */ - byte prace; - /** @structvar pracem - * @brief Number - * @note Race Mod index - */ - byte pracem; - /** @structvar pclass - * @brief Number - * @note Class index - */ - byte pclass; - /** @structvar mimic_form - * @brief Number - * @note Actualy transformation - */ - byte mimic_form; - /** @structvar mimic_level - * @brief Number - * @note Level of the mimic effect - */ - s16b mimic_level; - /** @structvar oops - * @brief Number - * @note Unused - */ - byte oops; - - object_type inventory[INVEN_TOTAL] @inventory_real; - - /** @structvar hitdie - * @brief Number - * @note Hit dice (sides) - */ - byte hitdie; - /** @structvar expfact - * @brief Number - * @note Experience factor - */ - u16b expfact; - - /** @structvar allow_one_death - * @brief Number - * @note Blood of life - */ - byte allow_one_death; - - /** @structvar age - * @brief Number - * @note Characters age - */ - s16b age; - /** @structvar ht - * @brief Number - * @note Height - */ - s16b ht; - /** @structvar wt - * @brief Number - * @note Weight - */ - s16b wt; - /** @structvar sc - * @brief Number - * @note Social Class - */ - s16b sc; - - - /** @structvar au - * @brief Number - * @note Current Gold - */ - s32b au; - - /** @structvar max_exp - * @brief Number - * @note Max experience - */ - s32b max_exp; - /** @structvar exp - * @brief Number - * @note Cur experience - */ - s32b exp; - /** @structvar exp_frac - * @brief Number - * @note Cur exp frac (times 2^16) - */ - u16b exp_frac; - - /** @structvar lev - * @brief Number - * @note Level - */ - s16b lev; - - /** @structvar town_num - * @brief Number - * @note Current town number - */ - s16b town_num; - /** @structvar inside_quest - * @brief Number - * @note Inside quest level - */ - s16b inside_quest; - /** @structvar exit_bldg - * @brief Boolean - * @note Goal obtained in arena? -KMW- - */ - bool exit_bldg; - - /** @structvar wilderness_x - * @brief Number - * @note Coordinates in the wilderness - */ - s32b wilderness_x; - /** @structvar wilderness_y - * @brief Number - */ - s32b wilderness_y; - /** @structvar wild_mode - * @brief Boolean - * @note TRUE = Small map, FLASE = Big map - */ - bool wild_mode; - /** @structvar old_wild_mode - * @brief Boolean - * @note TRUE = Small map, FLASE = Big map - */ - bool old_wild_mode; - - /** @structvar mhp - * @brief Number - * @note Max hit pts - */ - s16b mhp; - /** @structvar chp - * @brief Number - * @note Cur hit pts - */ - s16b chp; - /** @structvar chp_frac - * @brief Number - * @note Cur hit frac (times 2^16) - */ - u16b chp_frac; - /** @structvar hp_mod - * @brief Number - * @note A modificator(permanent) - */ - s16b hp_mod; - - /** @structvar msp - * @brief Number - * @note Max mana pts - */ - s16b msp; - /** @structvar csp - * @brief Number - * @note Cur mana pts - */ - s16b csp; - /** @structvar csp_frac - * @brief Number - * @note Cur mana frac (times 2^16) - */ - u16b csp_frac; - - /** @structvar msane - * @brief Number - * @note Max sanity - */ - s16b msane; - /** @structvar csane - * @brief Number - * @note Cur sanity - */ - s16b csane; - /** @structvar csane_frac - * @brief Number - * @note Cur sanity frac - */ - u16b csane_frac; - - /** @structvar grace - * @brief Number - * @note Your God's appreciation factor. - */ - s32b grace; - /** @structvar pgod - * @brief Number - * @note Your God. - */ - byte pgod; - /** @structvar praying - * @brief Boolean - * @note Praying to your god. - */ - bool praying; - - /** @structvar max_plv - * @brief Number - * @note Max Player Level - */ - s16b max_plv; - - /** @structvar stat_max[6] - * @brief Number - * @note Current "maximal" stat values - */ - s16b stat_max[6]; - /** @structvar stat_cur[6] - * @brief Number - * @note Current "natural" stat values - */ - s16b stat_cur[6]; - - /** @structvar luck_cur - * @brief Number - * @note Current "natural" luck value (range -30 <> 30) - */ - s16b luck_cur; - /** @structvar luck_max - * @brief Number - * @note Current "maximal base" luck value (range -30 <> 30) - */ - s16b luck_max; - /** @structvar luck_base - * @brief Number - * @note Current "base" luck value (range -30 <> 30) - */ - s16b luck_base; - - /** @structvar fast - * @brief Number - * @note Timed -- Fast - */ - s16b fast; - /** @structvar lightspeed - * @brief Number - * @note Timed -- Light Speed - */ - s16b lightspeed; - /** @structvar slow - * @brief Number - * @note Timed -- Slow - */ - s16b slow; - /** @structvar blind - * @brief Number - * @note Timed -- Blindness - */ - s16b blind; - /** @structvar paralyzed - * @brief Number - * @note Timed -- Paralysis - */ - s16b paralyzed; - /** @structvar confused - * @brief Number - * @note Timed -- Confusion - */ - s16b confused; - /** @structvar afraid - * @brief Number - * @note Timed -- Fear - */ - s16b afraid; - /** @structvar image - * @brief Number - * @note Timed -- Hallucination - */ - s16b image; - /** @structvar poisoned - * @brief Number - * @note Timed -- Poisoned - */ - s16b poisoned; - /** @structvar cut - * @brief Number - * @note Timed -- Cut - */ - s16b cut; - /** @structvar stun - * @brief Number - * @note Timed -- Stun - */ - s16b stun; - - /** @structvar protevil - * @brief Number - * @note Timed -- Protection from Evil - */ - s16b protevil; - /** @structvar protgood - * @brief Number - * @note Timed -- Protection from Good - */ - s16b protgood; - /** @structvar protundead - * @brief Number - * @note Timed -- Protection from Undead - */ - s16b protundead; - /** @structvar invuln - * @brief Number - * @note Timed -- Invulnerable - */ - s16b invuln; - /** @structvar hero - * @brief Number - * @note Timed -- Heroism - */ - s16b hero; - /** @structvar shero - * @brief Number - * @note Timed -- Super Heroism - */ - s16b shero; - /** @structvar shield - * @brief Number - * @note Timed -- Shield Spell - */ - s16b shield; - /** @structvar shield_power - * @brief Number - * @note Timed -- Shield Spell Power - */ - s16b shield_power; - /** @structvar shield_opt - * @brief Number - * @note Timed -- Shield Spell options - */ - s16b shield_opt; - /** @structvar blessed - * @brief Number - * @note Timed -- Blessed - */ - s16b blessed; - /** @structvar tim_invis - * @brief Number - * @note Timed -- See Invisible - */ - s16b tim_invis; - /** @structvar tim_infra - * @brief Number - * @note Timed -- Infra Vision - */ - s16b tim_infra; - - /** @structvar oppose_acid - * @brief Number - * @note Timed -- oppose acid - */ - s16b oppose_acid; - /** @structvar oppose_elec - * @brief Number - * @note Timed -- oppose lightning - */ - s16b oppose_elec; - /** @structvar oppose_fire - * @brief Number - * @note Timed -- oppose heat - */ - s16b oppose_fire; - /** @structvar oppose_cold - * @brief Number - * @note Timed -- oppose cold - */ - s16b oppose_cold; - /** @structvar oppose_pois - * @brief Number - * @note Timed -- oppose poison - */ - s16b oppose_pois; - /** @structvar oppose_ld - * @brief Number - * @note Timed -- oppose light & dark - */ - s16b oppose_ld; - /** @structvar oppose_cc - * @brief Number - * @note Timed -- oppose chaos & confusion - */ - s16b oppose_cc; - /** @structvar oppose_ss - * @brief Number - * @note Timed -- oppose sound & shards - */ - s16b oppose_ss; - /** @structvar oppose_nex - * @brief Number - * @note Timed -- oppose nexus - */ - s16b oppose_nex; - - - /** @structvar tim_esp - * @brief Number - * @note Timed ESP - */ - s16b tim_esp; - /** @structvar tim_wraith - * @brief Number - * @note Timed wraithform - */ - s16b tim_wraith; - /** @structvar tim_ffall - * @brief Number - * @note Timed Levitation - */ - s16b tim_ffall; - /** @structvar tim_fly - * @brief Number - * @note Timed Levitation - */ - s16b tim_fly; - /** @structvar tim_fire_aura - * @brief Number - * @note Timed Fire Aura - */ - s16b tim_fire_aura; - /** @structvar tim_regen - * @brief Number - * @note Timed regen - */ - s16b tim_regen; - /** @structvar tim_regen_pow - * @brief Number - * @note Timed regen - */ - s16b tim_regen_pow; - /** @structvar tim_poison - * @brief Number - * @note Timed poison hands - */ - s16b tim_poison; - /** @structvar tim_thunder - * @brief Number - * @note Timed thunderstorm - */ - s16b tim_thunder; - /** @structvar tim_thunder_p1 - * @brief Number - * @note Timed thunderstorm - */ - s16b tim_thunder_p1; - /** @structvar tim_thunder_p2 - * @brief Number - * @note Timed thunderstorm - */ - s16b tim_thunder_p2; - - /** @structvar resist_magic - * @brief Number - * @note Timed Resist Magic (later) - */ - s16b resist_magic; - /** @structvar tim_invisible - * @brief Number - * @note Timed Invisibility - */ - s16b tim_invisible; - /** @structvar tim_inv_pow - * @brief Number - * @note Power of timed invisibility - */ - s16b tim_inv_pow; - /** @structvar tim_mimic - * @brief Number - * @note Timed Mimic - */ - s16b tim_mimic; - /** @structvar tim_lite - * @brief Number - * @note Timed Lite - */ - s16b tim_lite; - /** @structvar holy - * @brief Number - * @note Holy Aura - */ - s16b holy; - /** @structvar walk_water - * @brief Number - * @note Walk over water as a god - */ - s16b walk_water; - /** @structvar tim_mental_barrier - * @brief Number - * @note Sustain Int&Wis - */ - s16b tim_mental_barrier; - /** @structvar strike - * @brief Number - * @note True Strike(+25 hit) - */ - s16b strike; - /** @structvar meditation - * @brief Number - * @note Meditation(+50 mana -25 to hit/to dam) - */ - s16b meditation; - /** @structvar tim_reflect - * @brief Number - * @note Timed Reflection - */ - s16b tim_reflect; - /** @structvar tim_res_time - * @brief Number - * @note Timed Resistance to Time - */ - s16b tim_res_time; - /** @structvar tim_deadly - * @brief Number - * @note Timed deadly blow - */ - s16b tim_deadly; - /** @structvar prob_travel - * @brief Number - * @note Timed probability travel - */ - s16b prob_travel; - /** @structvar disrupt_shield - * @brief Number - * @note Timed disruption shield - */ - s16b disrupt_shield; - /** @structvar parasite - * @brief Number - * @note Timed parasite - */ - s16b parasite; - /** @structvar parasite_r_idx - * @brief Number - * @note Timed parasite monster - */ - s16b parasite_r_idx; - /** @structvar loan - * @brief Number - */ - u32b loan; - /** @structvar loan_time - * @brief Number - * @note Timer -- loan - */ - u32b loan_time; - /** @structvar tim_magic_breath - * @brief Number - * @note Magical breathing -- can breath anywhere - */ - s16b tim_magic_breath; - /** @structvar tim_water_breath - * @brief Number - * @note Water breathing -- can breath underwater - */ - s16b tim_water_breath; - - /** @structvar immov_cntr - * @brief Number - * @note Timed -- Last ``immovable'' command. - */ - s16b immov_cntr; - - /** @structvar music_extra - * @brief Number - * @note Music songs - */ - u32b music_extra; - /** @structvar music_extra2 - * @brief Number - * @note Music songs - */ - u32b music_extra2; - - /** @structvar chaos_patron - * @brief Number - */ - s16b chaos_patron; - - /** @structvar recall_dungeon - * @brief Number - * @note Recall in which dungeon - */ - s16b recall_dungeon; - /** @structvar word_recall - * @brief Number - * @note Word of recall counter - */ - s16b word_recall; - - /** @structvar energy - * @brief Number - * @note Current energy - */ - s32b energy; - - /** @structvar food - * @brief Number - * @note Current nutrition - */ - s16b food; - - /** @structvar confusing - * @brief Number - * @note Glowing hands - */ - byte confusing; - /** @structvar searching - * @brief Number - * @note Currently searching - */ - byte searching; - - /** @structvar new_spells - * @brief Number - * @note Number of spells available - */ - s16b new_spells; - - /** @structvar old_spells - * @brief Number - */ - s16b old_spells; - - /** @structvar xtra_spells - * @brief Number - * @note Number of xtra spell learned(via potion) - */ - s16b xtra_spells; - - /** @structvar cur_lite - * @brief Number - * @note Radius of lite (if any) - */ - s16b cur_lite; - - /*** Extra flags -- used for lua and easying stuff ***/ - /** @structvar xtra_f1 - * @brief Number - */ - u32b xtra_f1; - /** @structvar xtra_f2 - * @brief Number - */ - u32b xtra_f2; - /** @structvar xtra_f3 - * @brief Number - */ - u32b xtra_f3; - /** @structvar xtra_f4 - * @brief Number - */ - u32b xtra_f4; - /** @structvar xtra_f5 - * @brief Number - */ - u32b xtra_f5; - /** @structvar xtra_esp - * @brief Number - */ - u32b xtra_esp; - - /** @structvar pspeed - * @brief Number - * @note Current speed - */ - s16b pspeed; - - /** @structvar notice - * @brief Number - * @note Special Updates (bit flags) - */ - u32b notice; - /** @structvar update - * @brief Number - * @note Pending Updates (bit flags) - */ - u32b update; - /** @structvar redraw - * @brief Number - * @note Normal Redraws (bit flags) - */ - u32b redraw; - /** @structvar window - * @brief Number - * @note Window Redraws (bit flags) - */ - u32b window; - - /** @structvar stat_use[6] - * @brief Number - * @note Current modified stats - */ - s16b stat_use[6]; - /** @structvar stat_top[6] - * @brief Number - * @note Maximal modified stats - */ - s16b stat_top[6]; - - /** @structvar stat_add[6] - * @brief Number - * @note Modifiers to stat values - */ - s16b stat_add[6]; - /** @structvar stat_ind[6] - * @brief Number - * @note Indexes into stat tables - */ - s16b stat_ind[6]; - /** @structvar stat_cnt[6] - * @brief Number - * @note Counter for temporary drains - */ - s16b stat_cnt[6]; - /** @structvar stat_los[6] - * @brief Number - * @note Amount of temporary drains - */ - s16b stat_los[6]; - - /** @structvar immune_acid - * @brief Boolean - * @note Immunity to acid - */ - bool immune_acid; - /** @structvar immune_elec - * @brief Boolean - * @note Immunity to lightning - */ - bool immune_elec; - /** @structvar immune_fire - * @brief Boolean - * @note Immunity to fire - */ - bool immune_fire; - /** @structvar immune_cold - * @brief Boolean - * @note Immunity to cold - */ - bool immune_cold; - /** @structvar immune_neth - * @brief Boolean - * @note Immunity to nether - */ - bool immune_neth; - - /** @structvar resist_acid - * @brief Boolean - * @note Resist acid - */ - bool resist_acid; - /** @structvar resist_elec - * @brief Boolean - * @note Resist lightning - */ - bool resist_elec; - /** @structvar resist_fire - * @brief Boolean - * @note Resist fire - */ - bool resist_fire; - /** @structvar resist_cold - * @brief Boolean - * @note Resist cold - */ - bool resist_cold; - /** @structvar resist_pois - * @brief Boolean - * @note Resist poison - */ - bool resist_pois; - - /** @structvar resist_conf - * @brief Boolean - * @note Resist confusion - */ - bool resist_conf; - /** @structvar resist_sound - * @brief Boolean - * @note Resist sound - */ - bool resist_sound; - /** @structvar resist_lite - * @brief Boolean - * @note Resist light - */ - bool resist_lite; - /** @structvar resist_dark - * @brief Boolean - * @note Resist darkness - */ - bool resist_dark; - /** @structvar resist_chaos - * @brief Boolean - * @note Resist chaos - */ - bool resist_chaos; - /** @structvar resist_disen - * @brief Boolean - * @note Resist disenchant - */ - bool resist_disen; - /** @structvar resist_shard - * @brief Boolean - * @note Resist shards - */ - bool resist_shard; - /** @structvar resist_nexus - * @brief Boolean - * @note Resist nexus - */ - bool resist_nexus; - /** @structvar resist_blind - * @brief Boolean - * @note Resist blindness - */ - bool resist_blind; - /** @structvar resist_neth - * @brief Boolean - * @note Resist nether - */ - bool resist_neth; - /** @structvar resist_fear - * @brief Boolean - * @note Resist fear - */ - bool resist_fear; - /** @structvar resist_continuum - * @brief Boolean - * @note Resist space-time continuum disruption - */ - bool resist_continuum; - - /** @structvar sensible_fire - * @brief Boolean - * @note Fire does more damage on the player - */ - bool sensible_fire; - /** @structvar sensible_lite - * @brief Boolean - * @note Lite does more damage on the player and blinds her/him - */ - bool sensible_lite; - - /** @structvar reflect - * @brief Boolean - * @note Reflect 'bolt' attacks - */ - bool reflect; - /** @structvar sh_fire - * @brief Boolean - * @note Fiery 'immolation' effect - */ - bool sh_fire; - /** @structvar sh_elec - * @brief Boolean - * @note Electric 'immolation' effect - */ - bool sh_elec; - /** @structvar wraith_form - * @brief Boolean - * @note wraithform - */ - bool wraith_form; - - /** @structvar anti_magic - * @brief Boolean - * @note Anti-magic - */ - bool anti_magic; - /** @structvar anti_tele - * @brief Boolean - * @note Prevent teleportation - */ - bool anti_tele; - - /** @structvar sustain_str - * @brief Boolean - * @note Keep strength - */ - bool sustain_str; - /** @structvar sustain_int - * @brief Boolean - * @note Keep intelligence - */ - bool sustain_int; - /** @structvar sustain_wis - * @brief Boolean - * @note Keep wisdom - */ - bool sustain_wis; - /** @structvar sustain_dex - * @brief Boolean - * @note Keep dexterity - */ - bool sustain_dex; - /** @structvar sustain_con - * @brief Boolean - * @note Keep constitution - */ - bool sustain_con; - /** @structvar sustain_chr - * @brief Boolean - * @note Keep charisma - */ - bool sustain_chr; - - /** @structvar aggravate - * @brief Boolean - * @note Aggravate monsters - */ - bool aggravate; - /** @structvar teleport - * @brief Boolean - * @note Random teleporting - */ - bool teleport; - - /** @structvar exp_drain - * @brief Boolean - * @note Experience draining - */ - bool exp_drain; - /** @structvar drain_mana - * @brief Number - * @note mana draining - */ - byte drain_mana; - /** @structvar drain_life - * @brief Number - * @note hp draining - */ - byte drain_life; - - /** @structvar magical_breath - * @brief Boolean - * @note Magical breathing -- can breath anywhere - */ - bool magical_breath; - /** @structvar water_breath - * @brief Boolean - * @note Water breathing -- can breath underwater - */ - bool water_breath; - /** @structvar climb - * @brief Boolean - * @note Can climb mountains - */ - bool climb; - /** @structvar fly - * @brief Boolean - * @note Can fly over some features - */ - bool fly; - /** @structvar ffall - * @brief Boolean - * @note No damage falling - */ - bool ffall; - /** @structvar lite - * @brief Boolean - * @note Permanent light - */ - bool lite; - /** @structvar free_act - * @brief Boolean - * @note Never paralyzed - */ - bool free_act; - /** @structvar see_inv - * @brief Boolean - * @note Can see invisible - */ - bool see_inv; - /** @structvar regenerate - * @brief Boolean - * @note Regenerate hit pts - */ - bool regenerate; - /** @structvar hold_life - * @brief Boolean - * @note Resist life draining - */ - bool hold_life; - /** @structvar telepathy - * @brief Number - * @note Telepathy - */ - u32b telepathy; - /** @structvar slow_digest - * @brief Boolean - * @note Slower digestion - */ - bool slow_digest; - /** @structvar bless_blade - * @brief Boolean - * @note Blessed blade - */ - bool bless_blade; - /** @structvar xtra_might - * @brief Number - * @note Extra might bow - */ - byte xtra_might; - /** @structvar impact - * @brief Boolean - * @note Earthquake blows - */ - bool impact; - /** @structvar auto_id - * @brief Boolean - * @note Auto id items - */ - bool auto_id; - - /** @structvar dis_to_h - * @brief Number - * @note Known bonus to hit - */ - s16b dis_to_h; - /** @structvar dis_to_d - * @brief Number - * @note Known bonus to dam - */ - s16b dis_to_d; - /** @structvar dis_to_a - * @brief Number - * @note Known bonus to ac - */ - s16b dis_to_a; - - /** @structvar dis_ac - * @brief Number - * @note Known base ac - */ - s16b dis_ac; - - /** @structvar to_m - * @brief Number - * @note Bonus to mana - */ - s16b to_m; - /** @structvar to_s - * @brief Number - * @note Bonus to spell - */ - s16b to_s; - /** @structvar to_h - * @brief Number - * @note Bonus to hit - */ - s16b to_h; - /** @structvar to_d - * @brief Number - * @note Bonus to dam - */ - s16b to_d; - /** @structvar to_a - * @brief Number - * @note Bonus to ac - */ - s16b to_a; - - /** @structvar to_h_melee - * @brief Number - * @note Bonus to hit - */ - s16b to_h_melee; - /** @structvar to_d_melee - * @brief Number - * @note Bonus to dam - */ - s16b to_d_melee; - - /** @structvar to_h_ranged - * @brief Number - * @note Bonus to hit - */ - s16b to_h_ranged; - /** @structvar to_d_ranged - * @brief Number - * @note Bonus to dam - */ - s16b to_d_ranged; - - /** @structvar num_blow - * @brief Number - * @note Number of blows - */ - s16b num_blow; - /** @structvar num_fire - * @brief Number - * @note Number of shots - */ - s16b num_fire; - - /** @structvar ac - * @brief Number - * @note Base ac - */ - s16b ac; - - /** @structvar antimagic - * @brief Number - * @note Power of the anti magic field - */ - byte antimagic; - /** @structvar antimagic_dis - * @brief Number - * @note Radius of the anti magic field - */ - byte antimagic_dis; - - /** @structvar see_infra - * @brief Number - * @note Infravision range - */ - s16b see_infra; - - /** @structvar skill_dis - * @brief Number - * @note Skill: Disarming - */ - s16b skill_dis; - /** @structvar skill_dev - * @brief Number - * @note Skill: Magic Devices - */ - s16b skill_dev; - /** @structvar skill_sav - * @brief Number - * @note Skill: Saving throw - */ - s16b skill_sav; - /** @structvar skill_stl - * @brief Number - * @note Skill: Stealth factor - */ - s16b skill_stl; - /** @structvar skill_srh - * @brief Number - * @note Skill: Searching ability - */ - s16b skill_srh; - /** @structvar skill_fos - * @brief Number - * @note Skill: Searching frequency - */ - s16b skill_fos; - /** @structvar skill_thn - * @brief Number - * @note Skill: To hit (normal) - */ - s16b skill_thn; - /** @structvar skill_thb - * @brief Number - * @note Skill: To hit (shooting) - */ - s16b skill_thb; - /** @structvar skill_tht - * @brief Number - * @note Skill: To hit (throwing) - */ - s16b skill_tht; - /** @structvar skill_dig - * @brief Number - * @note Skill: Digging - */ - s16b skill_dig; - - /** @structvar skill_points - * @brief Number - */ - s16b skill_points; - - /** @structvar control - * @brief Number - * @note Controlled monster - */ - s16b control; - /** @structvar control_dir - * @brief Number - * @note Controlled monster - */ - byte control_dir; - /** @structvar companion_killed - * @brief Number - * @note Number of companion death - */ - s16b companion_killed; - /** @structvar black_breath - * @brief Boolean - * @note The Tolkien's Black Breath - */ - bool black_breath; - /** @structvar body_monster - * @brief Number - * @note In which body is the player - */ - u16b body_monster; - - /** @structvar body_parts[28] - * @brief Number - * @note Various body modifiers - */ - byte body_parts[28]; - - /** @structvar powers_mod[POWER_MAX] - * @brief Boolean - * @note Intrinsinc powers - */ - bool powers_mod[POWER_MAX]; - /** @structvar powers[POWER_MAX] - * @brief Boolean - */ - bool powers[POWER_MAX]; - - /* Corruptions */ - bool corrupt_anti_teleport_stopped; - - /* Astral */ - /** @structvar astral - * @brief Boolean - * @note We started at the bottom ? - */ - bool astral; - - /*** Temporary fields ***/ - - /** @structvar leaving - * @brief Boolean - * @note True if player is leaving - */ - bool leaving; -}; - -/** - * Corruptions - */ -#define CORRUPT_BALROG_AURA 0 -#define CORRUPT_BALROG_WINGS 1 -#define CORRUPT_BALROG_STRENGTH 2 -#define CORRUPT_BALROG_FORM 3 -#define CORRUPT_DEMON_SPIRIT 4 -#define CORRUPT_DEMON_HIDE 5 -#define CORRUPT_DEMON_BREATH 6 -#define CORRUPT_DEMON_REALM 7 -#define CORRUPT_RANDOM_TELEPORT 8 -#define CORRUPT_ANTI_TELEPORT 9 -#define CORRUPT_TROLL_BLOOD 10 -#define CORRUPT_VAMPIRE_TEETH 11 -#define CORRUPT_VAMPIRE_STRENGTH 12 -#define CORRUPT_VAMPIRE_VAMPIRE 13 -#define MUT1_SPIT_ACID 14 -#define MUT1_BR_FIRE 15 -#define MUT1_HYPN_GAZE 16 -#define MUT1_TELEKINES 17 -#define MUT1_VTELEPORT 18 -#define MUT1_MIND_BLST 19 -#define MUT1_VAMPIRISM 20 -#define MUT1_SMELL_MET 21 -#define MUT1_SMELL_MON 22 -#define MUT1_BLINK 23 -#define MUT1_EAT_ROCK 24 -#define MUT1_SWAP_POS 25 -#define MUT1_SHRIEK 26 -#define MUT1_ILLUMINE 27 -#define MUT1_DET_CURSE 28 -#define MUT1_BERSERK 29 -#define MUT1_MIDAS_TCH 30 -#define MUT1_GROW_MOLD 31 -#define MUT1_RESIST 32 -#define MUT1_EARTHQUAKE 33 -#define CORRUPTIONS_MAX 34 - -extern bool player_has_corruption(int corruption_idx); -extern void player_gain_corruption(int corruption_idx); - -/** @name Spellbinder triggers - * @{ */ -/** @def SPELLBINDER_HP75 - * @note Trigger spellbinder at 75% maximum hit points */ -#define SPELLBINDER_HP75 1 - -/** @def SPELLBINDER_HP50 - * @note Trigger spellbinder at 50% maximum hit points */ -#define SPELLBINDER_HP50 2 - -/** @def SPELLBINDER_HP25 - * @note Trigger spellbinder at 25% maximum hit points */ -#define SPELLBINDER_HP25 3 -/** @} */ - - -/** @struct player_race - */ -struct player_race -{ - /** @structvar title - * @brief Number - * @note Type of race - */ - s32b title; - /** @structvar desc - * @brief Number - */ - s32b desc; - - /** @structvar infra - * @brief Number - * @note Infra-vision range - */ - byte infra; -}; - -/** @struct player_race_mod - */ -struct player_race_mod -{ - /** @structvar title - * @brief Number - * @note Type of race mod - */ - s32b title; - /** @structvar desc - * @brief Number - * @note Desc - */ - s32b desc; - /** @structvar place - * @brief Boolean - * @note TRUE = race race modifier, FALSE = Race modifier race - */ - bool place; - - /** @structvar r_adj[6] - * @brief Number - * @note (+) Racial stat bonuses - */ - s16b r_adj[6]; - - /** @structvar luck - * @brief String - * @note Luck - */ - char luck; - /** @structvar mana - * @brief Number - * @note Mana % - */ - s16b mana; - - /** @structvar r_dis - * @brief Number - * @note (+) disarming - */ - s16b r_dis; - /** @structvar r_dev - * @brief Number - * @note (+) magic devices - */ - s16b r_dev; - /** @structvar r_sav - * @brief Number - * @note (+) saving throw - */ - s16b r_sav; - /** @structvar r_stl - * @brief Number - * @note (+) stealth - */ - s16b r_stl; - /** @structvar r_srh - * @brief Number - * @note (+) search ability - */ - s16b r_srh; - /** @structvar r_fos - * @brief Number - * @note (+) search frequency - */ - s16b r_fos; - /** @structvar r_thn - * @brief Number - * @note (+) combat (normal) - */ - s16b r_thn; - /** @structvar r_thb - * @brief Number - * @note (+) combat (shooting) - */ - s16b r_thb; - - /** @structvar r_mhp - * @brief String - * @note (+) Race mod hit-dice modifier - */ - char r_mhp; - /** @structvar r_exp - * @brief Number - * @note (+) Race mod experience factor - */ - s16b r_exp; - - /** @structvar b_age - * @brief String - * @note (+) base age - */ - char b_age; - /** @structvar m_age - * @brief String - * @note (+) mod age - */ - char m_age; - - /** @structvar m_b_ht - * @brief String - * @note (+) base height (males) - */ - char m_b_ht; - /** @structvar m_m_ht - * @brief String - * @note (+) mod height (males) - */ - char m_m_ht; - /** @structvar m_b_wt - * @brief String - * @note (+) base weight (males) - */ - char m_b_wt; - /** @structvar m_m_wt - * @brief String - * @note (+) mod weight (males) - */ - char m_m_wt; - - /** @structvar f_b_ht - * @brief String - * @note (+) base height (females) - */ - char f_b_ht; - /** @structvar f_m_ht - * @brief String - * @note (+) mod height (females) - */ - char f_m_ht; - /** @structvar f_b_wt - * @brief String - * @note (+) base weight (females) - */ - char f_b_wt; - /** @structvar f_m_wt - * @brief String - * @note (+) mod weight (females) - */ - char f_m_wt; - - /** @structvar infra - * @brief String - * @note (+) Infra-vision range - */ - char infra; - - /** @structvar choice[2] - * @brief Number - * @note Legal race choices - */ - u32b choice[2]; - - /** @structvar pclass[2] - * @brief Number - * @note Classes allowed - */ - u32b pclass[2]; - /** @structvar mclass[2] - * @brief Number - * @note Classes restricted - */ - u32b mclass[2]; - - /** @structvar powers[4] - * @brief Number - * @note Powers of the subrace - */ - s16b powers[4]; - - /** @structvar body_parts[BODY_MAX] - * @brief String - * @note To help to decide what to use when body changing - */ - char body_parts[BODY_MAX]; - - /** @structvar flags1 - * @brief Number - */ - u32b flags1; - /** @structvar flags2 - * @brief Number - * @note flags - */ - u32b flags2; - - /** @structvar oflags1[51] - * @brief Number - */ - u32b oflags1[51]; - /** @structvar oflags2[51] - * @brief Number - */ - u32b oflags2[51]; - /** @structvar oflags3[51] - * @brief Number - */ - u32b oflags3[51]; - /** @structvar oflags4[51] - * @brief Number - */ - u32b oflags4[51]; - /** @structvar oflags5[51] - * @brief Number - */ - u32b oflags5[51]; - /** @structvar oesp[51] - * @brief Number - */ - u32b oesp[51]; - /** @structvar opval[51] - * @brief Number - */ - s16b opval[51]; - - /** @structvar g_attr - * @brief Number - * @note Overlay graphic attribute - */ - byte g_attr; - /** @structvar g_char - * @brief String - * @note Overlay graphic character - */ - char g_char; - - /** @structvar skill_basem[MAX_SKILLS] - * @brief String - */ - char skill_basem[MAX_SKILLS]; - /** @structvar skill_base[MAX_SKILLS] - * @brief Number - */ - u32b skill_base[MAX_SKILLS]; - /** @structvar skill_modm[MAX_SKILLS] - * @brief String - */ - char skill_modm[MAX_SKILLS]; - /** @structvar skill_mod[MAX_SKILLS] - * @brief Number - */ - s16b skill_mod[MAX_SKILLS]; -}; - -/** @var energy_use - * @brief Number - * @note Energy use for an action (0 if action does not take a turn). - */ -extern s32b energy_use; - -/** @var player; - * @brief player_type - * @note The player. - */ -extern player_type *p_ptr @ player; - -/** @var max_rp_idx - * @brief Number - * @note Maximum number of entries in player race array. - */ -extern u16b max_rp_idx; - -/** @var race_info[max_rp_idx] - * @brief player_race - * @note Array of player races. - */ -extern player_race race_info[max_rp_idx]; - -/** @var *rp_name - * @brief String - * @note Name of player race. - */ -extern char *rp_name; - -/** @var *rp_text - * @brief String - */ -extern char *rp_text; - -/** @var max_rmp_idx - * @brief Number - * @note Maximum number of player subraces. - */ -extern u16b max_rmp_idx; - -/** @var _mod race_mod_info[max_rmp_idx] - * @brief player_race - * @note Array of player subraces. - */ -extern player_race_mod race_mod_info[max_rmp_idx]; - -/** @var *rmp_name - * @brief String - * @note Name of player subrace. - */ -extern char *rmp_name; - -/** @var *rmp_text - * @brief String - */ -extern char *rmp_text; - -/** @var class_info[max_c_idx] - * @brief player_class - * @note Array of classes. - */ -extern player_class class_info[max_c_idx]; - -/** @var *c_name - * @brief String - * @note Name of player class. - */ -extern char *c_name; - -/** @var *c_text - * @brief String - */ -extern char *c_text; - -/** @var flush_failure - * @brief Boolean - * @note TRUE if flush input on any failure, otherwise FALSE. - */ -extern bool flush_failure; - -/** @fn set_roots(int v, s16b ac, s16b dam) - * @brief Player has timed roots.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @param ac Number \n bonus to AC - * @brief AC bonus - * @param dam Number \n bonus to melee to-damage - * @brief To-damage bonus - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_roots(int v, s16b ac, s16b dam); - -/** @fn set_shadow(int v) - * @brief Player has wraith form.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_shadow(int v); - -/** @fn set_parasite(int v, int r) - * @brief Player has timed parasite.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @param r Number \n index of race in monster race array - * @brief Parasite race index - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note - * When the time remaining reaches 0, there is an 80% chance the parasite will - * be born, otherwise it will die away. - * @note (see file xtra2.c) - */ -extern bool set_parasite(int v, int r); - -/** @fn set_disrupt_shield(int v) - * @brief Player has timed disrupt shield (feels invulnerable).\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_disrupt_shield(int v); - -/** @fn set_prob_travel(int v) - * @brief Player has timed probability travel.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_prob_travel(int v); - -/** @fn set_project(int v, s16b gf, s16b dam, s16b rad, s16b flag) - * @brief Player's weapon has a spell effect.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @param gf Number \n spell effect - * @brief Spell effect - * @param dam Number \n damage caused by spell effect - * @brief Spell damage - * @param rad Number \n radius of spell effect - * @brief Spell radius - * @param flag Number \n spell projection effect - * @brief Spell properties - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_project(int v, s16b gf, s16b dam, s16b rad, s16b flag); - -/** @fn set_tim_deadly(int v) - * @brief Player has deadly accuracy.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_tim_deadly(int v); - -/** @fn set_tim_res_time(int v) - * @brief Player has timed time resistance.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_tim_res_time(int v); - -/** @fn set_tim_reflect(int v) - * @brief Player has timed reflection.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_tim_reflect(int v); - -/** @fn set_meditation(int v) - * @brief Player can meditate (forcibly pseudo-id).\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_meditation(int v); - -/** @fn set_strike(int v) - * @brief Player has true strike.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_strike(int v); - -/** @fn set_walk_water(int v) - * @brief Player can walk on water.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_walk_water(int v); - -/** @fn set_tim_ffall(int v) - * @brief Player has timed levitation (feather-fall).\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_tim_ffall(int v); - -/** @fn set_tim_fire_aura(int v) - * @brief Player has a timed fiery aura.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_tim_fire_aura(int v); - -/** @fn set_tim_regen(int v, int p) - * @brief Player has timed regeneration.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @param p Number \n power of regeneration - * @brief Regeneration power - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_tim_regen(int v, int p); - -/** @fn set_holy(int v) - * @brief Player has a timed holy aura.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_holy(int v); - -/** @fn set_grace(s32b v) - * @brief Set the amount of grace a player has with a god.\n - * @param v Number \n time remaining until effect expires - * (must be in the range -30,000 to 30,000) - * @brief Grace - * @note (see file xtra2.c) - */ -extern void set_grace(s32b v); - -/** @fn set_mimic(int v, int p, int level) - * @brief Player has mimic form.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @param p Number \n the mimic form - * @brief Mimic form - * @param level Number \n the level of the mimic form - * @brief Mimic level - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_mimic(int v, int p, int level); - -/** @fn set_no_breeders(int v) - * @brief Player has timed breeder prevention.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_no_breeders(int v); - -/** @fn set_tim_esp(int v) - * @brief Player has timed ESP.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_tim_esp(int v); - -/** @fn set_invis(int v, int p) - * @brief Player has timed invisibility.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @param p Number \n power of invisibility - * @brief Invisibility power - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_invis(int v, int p); - -/** @fn set_lite(int v) - * @brief Player has timed light.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note - * Note the use of "PU_VIEW", which is needed to - * memorize any terrain features which suddenly become "visible". - * @note - * Note that blindness is currently the only thing which can affect - * "player_can_see_bold()". - * @note (see file xtra2.c) - */ -extern bool set_lite(int v); - -/** @fn set_blind(int v) - * @brief Player has timed blindness.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note - * Note the use of "PU_UN_VIEW", which is needed to memorize any terrain - * features which suddenly become "visible". - * @note - * Note that blindness is currently the only thing which can affect - * "player_can_see_bold()". - * @note (see file xtra2.c) - */ -extern bool set_blind(int v); - -/** @fn set_confused(int v) - * @brief Player has timed confusion.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_confused(int v); - -/** @fn set_poisoned(int v) - * @brief Player has timed poisoning.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_poisoned(int v); - -/** @fn set_afraid(int v) - * @brief Player has timed fear.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_afraid(int v); - -/** @fn set_paralyzed(int v) - * @brief Player has timed paralysis.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_paralyzed(int v); - -/** @fn set_image(int v) - * @brief Player has timed hallucination.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note - * Note that we must redraw the map when hallucination changes. - * @note (see file xtra2.c) - */ -extern bool set_image(int v); - -/** @fn set_fast(int v, int p) - * @brief Player has timed speed boost.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @param p Number \n speed factor - * @brief Speed factor - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_fast(int v, int p); - -/** @fn set_light_speed(int v) - * @brief Player has timed light speed.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_light_speed(int v); - -/** @fn set_slow(int v) - * @brief Player has timed slowness.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_slow(int v); - -/** @fn set_shield(int v, int p, s16b o, s16b d1, s16b d2) - * @brief Player has timed mystic shield.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @param p Number \n bonus to AC - * @brief AC bonus - * @param o Number \n type of shield (see SHIELD_foo fields) - * @brief Shield type - * @param d1 Number \n number of dice for damage roll - * @brief Damage dice - * @param d2 Number \n number of sides per die for damage roll - * @brief Damage sides - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_shield(int v, int p, s16b o, s16b d1, s16b d2); - -/* For calc_bonus hooks */ -/** @fn apply_flags(u32b f1, u32b f2, u32b f3, u32b f4, u32b f5, u32b esp, s16b pval = 0, s16b tval = 0, s16b to_h = 0, s16b to_d = 0, s16b to_a = 0) - * @brief Apply flags and values to the player.\n - * @param f1 Number \n flags to be applied to the player - * @brief Flag1 - * @param f2 Number \n flags to be applied to the player - * @brief Flag2 - * @param f3 Number \n flags to be applied to the player - * @brief Flag3 - * @param f4 Number \n flags to be applied to the player - * @brief Flag4 - * @param f5 Number \n flags to be applied to the player - * @brief Flag5 - * @param esp Number \n ESP flag - * @brief Esp flag - * @param pval Number \n PVal to be applied to the player - * @brief Pval - * @param tval Number \n TVal to be applied to the player - * @brief Tval - * @param to_h Number \n to-hit bonus to be applied to the player - * @brief To-hit - * @param to_d Number \n to-damage bonus to be applied to the player - * @brief To-damage - * @param to_a Number \n AC bonus to be applied to the player - * @brief AC - * @note - * f1 can apply to attribuets, spell power, mana capacity, stealth, searching - * ability and frequency, infravision, digging, speed, extra blows, and - * earthquakes. - * @note - * f2 can apply to life capacity, sensible fire, invisibility, free action, - * hold life, immunities (except neither), resistances, reflection, and - * sustains. - * @note - * f3 can apply to extra shots, aggravate, teleport, drain XP, blessed, extra - * might, slow digestion, regeneration, lite, see invisible, wraith form, - * feather fall, fire sheath, electricity sheath, anti magic, and anti - * teleport. - * @note - * f4 can apply to lite, flying, climbing, nether immunity, precognition, and - * anti-magic power and radius. - * @note - * f5 can apply to luck, critical hits, drain mana, drain life, immovable, - * water breath, and magic breath. - * @note - * esp can apply to, well, just telepathy. - * @note - * pval can apply to attributes, luck, spell power, mana capacity, life - * capacity, stealth, search ability and frequency (x 5), infravision, digging - * (x 20), speed, extra blows, critical blows, invisibility (x 10), extra - * might, anti-magic power and radius. - * @note - * tval can apply to lite - * @note - * to_h, to_d, and to_ac can apply to anti-magic power and radius. - * @note (see file xtra1.c) - */ -extern void apply_flags(u32b f1, u32b f2, u32b f3, u32b f4, u32b f5, u32b esp, s16b pval = 0, s16b tval = 0, s16b to_h = 0, s16b to_d = 0, s16b to_a = 0); - -/** @name Shield effect options - * @{ */ -/** @def SHIELD_NONE */ -#define SHIELD_NONE 0x0000 - -/** @def SHIELD_COUNTER */ -#define SHIELD_COUNTER 0x0001 - -/** @def SHIELD_FIRE */ -#define SHIELD_FIRE 0x0002 - -/** @def SHIELD_GREAT_FIRE */ -#define SHIELD_GREAT_FIRE 0x0004 - -/** @def SHIELD_FEAR */ -#define SHIELD_FEAR 0x0008 -/** @} */ - -/** - * Timered precognition - */ - - -/** @fn set_tim_thunder(int v, int p1, int p2) - * @brief Player has timed thunderstorm.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @param p1 Number \n number of dice for damage roll - * @brief Damage dice - * @param p2 Number \n number of sides per die for damage roll - * @brief Damage sides - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_tim_thunder(int v, int p1, int p2); - -/** @fn set_tim_breath(int v, bool magical) - * @brief Player has timed magic/water breath.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @param magical Boolean \n TRUE if player has magic breath, or FALSE if the - * player has water breath - * @brief Magic breath? - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_tim_breath(int v, bool magical); - -/** @fn set_tim_fly(int v) - * @brief Player has timed flight.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_tim_fly(int v); - -/** @fn set_blessed(int v) - * @brief Player has timed blessing.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note - * Blessing gives +5 bonus AC and +10 bonus to-hit. - * @note (see file xtra2.c) - */ -extern bool set_blessed(int v); - -/** @fn set_hero(int v) - * @brief Player has timed heroism.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note - * Heroism gives +10 bonus max HP, +12 bonus to-hit, and resist fear. - * @note (see file xtra2.c) - */ -extern bool set_hero(int v); - -/** @fn set_shero(int v) - * @brief Player has timed berserk strength.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note - * Berserk strength gives +30 bonus max HP, +24 bonus to-hit, -10 penalty AC, - * and resist fear. - * @note (see file xtra2.c) - */ -extern bool set_shero(int v); - -/** @fn set_protevil(int v) - * @brief Player has timed protection from evil.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note - * Protection from evil gives the player a chance to repel evil monsters. - * @note (see file xtra2.c) - */ -extern bool set_protevil(int v); - -/** @fn set_protgood(int v) - * @brief Player has timed protection from good.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note - * Protection from good gives the player a chance to repel good monsters. - * @note (see file xtra2.c) - */ -extern bool set_protgood(int v); - -/** @fn set_protundead(int v) - * @brief Player has timed protection from undead.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note - * Protection from undead protects against getting the Black Breath in a melee - * attack. - * @note (see file xtra2.c) - */ -extern bool set_protundead(int v); - -/** @fn set_invuln(int v) - * @brief Player has timed invulnerability.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note - * Invulnerability prevents damage from walking on lava, walking the Straight - * Road, poison, cuts, and starvation. It gives +100 bonus to AC. - * @note - * It can be ended by the player attacking a monster, firing a missile, - * throwing an object, or activating a power. - * @note (see file xtra2.c) - */ -extern bool set_invuln(int v); - -/** @fn set_tim_invis(int v) - * @brief Player has timed "see invisibile".\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_tim_invis(int v); - -/** @fn set_tim_infra(int v) - * @brief Player has timed infravision.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_tim_infra(int v); - -/** @fn set_mental_barrier(int v) - * @brief Player has timed mental barrier.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note - * Mental barrier sustains intelligence and wisdom. - * @note (see file xtra2.c) - */ -extern bool set_mental_barrier(int v); - -/** @fn set_poison(int v) - * @brief Player has timed poison hands.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_poison(int v); - -/** @fn set_oppose_acid(int v) - * @brief Player has timed acid resistance.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_oppose_acid(int v); - -/** @fn set_oppose_elec(int v) - * @brief Player has timed electricity resistance.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_oppose_elec(int v); - -/** @fn set_oppose_fire(int v) - * @brief Player has timed fire resistance.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_oppose_fire(int v); - -/** @fn set_oppose_cold(int v) - * @brief Player has timed cold resistance.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_oppose_cold(int v); - -/** @fn set_oppose_pois(int v) - * @brief Player has timed poison resistance.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_oppose_pois(int v); - -/** @fn set_oppose_ld(int v) - * @brief Player has timed light and dark resistance.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_oppose_ld(int v); - -/** @fn set_oppose_cc(int v) - * @brief Player has timed chaos and confusion resistance.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_oppose_cc(int v); - -/** @fn set_oppose_ss(int v) - * @brief Player has timed sound and shard resistance.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_oppose_ss(int v); - -/** @fn set_oppose_nex(int v) - * @brief Player has timed nexus resistance.\n - * @param v Number \n time remaining until effect expires - * (must be in the range 0 to 10,000) - * @brief Time remaining - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note (see file xtra2.c) - */ -extern bool set_oppose_nex(int v); - -/** @fn set_stun(int v) - * @brief Player stun level changes.\n - * @param v Number \n the level of stun (must be in the range 0 to 10,000) - * @brief Stun level - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note - * Note the special code to only notice "range" changes. - * @note - * Some races resist stunning. - * @note - * There is a v chance in 1000 or 1 in 16 that a stun will be the result of - * a vicious blow to the head. If so, the player will lose a point of - * intelligence, or wisdom, or both unless the stat is sustained. - * @note (see file xtra2.c) - */ -extern bool set_stun(int v); - -/** @fn set_cut(int v) - * @brief Player cut level changes.\n - * @param v Number \n the level of cut (must be in the range 0 to 10,000) - * @brief Cut level - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note - * Note the special code to only notice "range" changes. - * @note - * Some races resist cutting. - * @note - * There is a v chance in 1000 or 1 in 16 that a cut will result in scarrring. - * If so, the player will lose a point of charisma unless it is sustained. - * @note (see file xtra2.c) - */ -extern bool set_cut(int v); - -/** @fn set_food(int v) - * @brief Player hunger level changes.\n - * @param v Number \n the level of cut (must be in the range 0 to 10,000) - * @brief Cut level - * @return Boolean \n TRUE if player notices the effect, otherwise FALSE. - * @note - * The "p_ptr->food" variable can get as large as 20000, allowing the - * addition of the most "filling" item, Elvish Waybread, which adds - * 7500 food units, without overflowing the 32767 maximum limit. - * @note - * Perhaps we should disturb the player with various messages, - * especially messages about hunger status changes. XXX XXX XXX - * @note - * Digestion of food is handled in "dungeon.c", in which, normally, - * the player digests about 20 food units per 100 game turns, more - * when "fast", more when "regenerating", less with "slow digestion", - * but when the player is "gorged", he digests 100 food units per 10 - * game turns, or a full 1000 food units per 100 game turns. - * @note - * Note that the player's speed is reduced by 10 units while gorged, - * so if the player eats a single food ration (5000 food units) when - * full (15000 food units), he will be gorged for (5000/100)*10 = 500 - * game turns, or 500/(100/5) = 25 player turns (if nothing else is - * affecting the player speed). - * @note (see file xtra2.c) - */ -extern bool set_food(int v); - -/** @name Hunger flags - * @brief Player "food" crucial values - * @{ */ -/** @def PY_FOOD_MAX - * @note Food value (Bloated) - */ -#define PY_FOOD_MAX 15000 -/** @def PY_FOOD_FULL - * @note Food value (Normal) - */ -#define PY_FOOD_FULL 10000 -/** @def PY_FOOD_ALERT - * @note Food value (Hungry) - */ -#define PY_FOOD_ALERT 2000 -/** @def PY_FOOD_WEAK - * @note Food value (Weak) - */ -#define PY_FOOD_WEAK 1000 -/** @def PY_FOOD_FAINT - * @note Food value (Fainting) - */ -#define PY_FOOD_FAINT 500 -/** @def PY_FOOD_STARVE - * @note Food value (Starving) - */ -#define PY_FOOD_STARVE 100 -/** @} */ - -/** @fn check_experience(void) - * @brief Check if player experience level has changed.\n - * @note - * If a player has achieved a level for the first time, give a corruption - * (1 chance in 3) if it applies, increase skill points, check ability levels, - * and add a note if notes are taken. - * @note (see file xtra2.c) - */ -extern void check_experience(void); - -/** @fn check_experience_obj(object_type *o_ptr) - * @brief Check if object "o_ptr" experience level has changed.\n - * @param *o_ptr object_type \n the object - * @brief Object - * @note - * If an object has achieved a level for the first time, apply gains. - * @note (see file xtra2.c) - */ -extern void check_experience_obj(object_type *o_ptr); - -/** @fn gain_exp(s32b amount) - * @brief Gain "amount" of experience.\n - * @param amount Number \n the experience points to gain. - * @brief Experience - * @note - * Count the number of objects which will gain experience. The objects share - * equally 2/3 of "amount". Give corruption if it applies. Gain experience. - * If experience is less than maximum, then increase maximum experience by 20% - * of "amount". Check for level change and print experience (check_experience). - * @note (see file xtra2.c) - */ -extern void gain_exp(s32b amount); - -/** @fn lose_exp(s32b amount) - * @brief Decrease experience by "amount".\n - * @param amount Number \n the experience points to lose. - * @brief Experience - * @note - * Experience can not fall below zero. Check for level change and print - * experience (check_experience). - * @note (see file xtra2.c) - */ -extern void lose_exp(s32b amount); - -/** @fn no_lite(void) - * @brief Return true if the player's grid is dark. - * @return Boolean \n TRUE if the player's grid is dark, otherwise FALSE. - * @note (see file cave.c) - */ -extern bool no_lite(void); - -/** @var dun_level - * @brief Number - * @note Current dungeon level - */ -extern s16b dun_level; - - -/** @name Gods - * @{ */ -/** @def GOD_ALL */ -#define GOD_ALL -1 - -/** @def GOD_NONE */ -#define GOD_NONE 0 - -/** @def GOD_ERU */ -#define GOD_ERU 1 - -/** @def GOD_MANWE */ -#define GOD_MANWE 2 - -/** @def GOD_TULKAS */ -#define GOD_TULKAS 3 - -/** @def GOD_MELKOR */ -#define GOD_MELKOR 4 - -/** @def GOD_YAVANNA */ -#define GOD_YAVANNA 5 -/** @} */ - -#define GOD_AULE 6 -#define GOD_VARDA 7 -#define GOD_ULMO 8 -#define GOD_MANDOS 9 - - -/** @fn inc_piety(int god, s32b amt) - * @brief Increase piety for god "god" by amount "amt".\n - * @param god Number \n the god - * @brief God - * @param amt Number \n the amount of piety - * @brief Piety - * @note - * If the player worships all gods, or "god", the piety (grace) will increase. - * @note (see file gods.c) - */ -extern void inc_piety(int god, s32b amt); - -/** @fn abandon_god(int god) - * @brief Player renounces their religion.\n - * @param god Number \n the god - * @brief God - * @note - * If the player worships all gods or "god", the player worships no god and - * the piety score is set to 0. - * @note (see file gods.c) - */ -extern void abandon_god(int god); - -/** @fn wisdom_scale(int max) - * @brief Rescale the wisdom value to a 0 <-> max range.\n - * @param max Number \n the new maximum value of the rescaled wisdom - * @brief New maximum wisdom - * @return Number \n The rescaled value of player wisdom. - * @note (see file gods.c) - */ -extern int wisdom_scale(int max); - -/** @name Powers - * @{ */ -/** @def PWR_SPIT_ACID - * @note Spit acid (GF_ACID) */ -#define PWR_SPIT_ACID 0 - -/** @def PWR_BR_FIRE - * @note Breathe fire (GF_FIRE) */ -#define PWR_BR_FIRE 1 - -/** @def PWR_HYPN_GAZE - * @note Hypnotic gaze */ -#define PWR_HYPN_GAZE 2 - -/** @def PWR_TELEKINES - * @note Telekinesis (fetch an object) */ -#define PWR_TELEKINES 3 - -/** @def PWR_VTELEPORT - * @note Teleport */ -#define PWR_VTELEPORT 4 - -/** @def PWR_MIND_BLST - * @note Mind blast (GF_PSI) */ -#define PWR_MIND_BLST 5 - -/** @def PWR_RADIATION - * @note Emit radiation (GF_NUKE) */ -#define PWR_RADIATION 6 - -/** @def PWR_VAMPIRISM - * @note Vampire bite */ -#define PWR_VAMPIRISM 7 - -/** @def PWR_SMELL_MET - * @note Detect treasure */ -#define PWR_SMELL_MET 8 - -/** @def PWR_SMELL_MON - * @note Detect normal monsters */ -#define PWR_SMELL_MON 9 - -/** @def PWR_BLINK - * @note Short teleport (up to 10 grids) */ -#define PWR_BLINK 10 - -/** @def PWR_EAT_ROCK - * @note Eat rock for food (wall to mud) */ -#define PWR_EAT_ROCK 11 - -/** @def PWR_SWAP_POS - * @note Swap position with a monster */ -#define PWR_SWAP_POS 12 - -/** @def PWR_SHRIEK - * @note Shriek (GF_SOUND and aggravate) */ -#define PWR_SHRIEK 13 - -/** @def PWR_ILLUMINE - * @note Lite area */ -#define PWR_ILLUMINE 14 - -/** @def PWR_DET_CURSE - * @note Detect cursed items in inventory */ -#define PWR_DET_CURSE 15 - -/** @def PWR_BERSERK - * @note Berserk rage */ -#define PWR_BERSERK 16 - -/** @def PWR_POLYMORPH - * @note Polymorph self */ -#define PWR_POLYMORPH 17 - -/** @def PWR_MIDAS_TCH - * @note Midas touch - turn an item into gold */ -#define PWR_MIDAS_TCH 18 - -/** @def PWR_GROW_MOLD - * @note Summon mold */ -#define PWR_GROW_MOLD 19 - -/** @def PWR_RESIST - * @note Temporary elemental resist */ -#define PWR_RESIST 20 - -/** @def PWR_EARTHQUAKE - * @note Cause an earthquake (destruction) */ -#define PWR_EARTHQUAKE 21 - -/** @def PWR_EAT_MAGIC - * @note Absorb energy from magic items */ -#define PWR_EAT_MAGIC 22 - -/** @def PWR_WEIGH_MAG - * @note Report magic affecting player */ -#define PWR_WEIGH_MAG 23 - -/** @def PWR_STERILITY - * @note Player experiences forced abstinence */ -#define PWR_STERILITY 24 - -/** @def PWR_PANIC_HIT - * @note Hit a monster and run away */ -#define PWR_PANIC_HIT 25 - -/** @def PWR_DAZZLE - * @note Stun, confuse, and turn monsters */ -#define PWR_DAZZLE 26 - -/** @def PWR_DARKRAY - * @note Fire a beam of light (GF_LITE) */ -#define PWR_DARKRAY 27 - -/** @def PWR_RECALL - * @note Recall to dungeon/town */ -#define PWR_RECALL 28 - -/** @def PWR_BANISH - * @note Banish evil creatures */ -#define PWR_BANISH 29 - -/** @def PWR_COLD_TOUCH - * @note Bolt of cold (GF_COLD) */ -#define PWR_COLD_TOUCH 30 - -/** @def PWR_LAUNCHER - * @note Increase the multiplier for a thrown object */ -#define PWR_LAUNCHER 31 - -/** @def PWR_PASSWALL - * @note Walk through a wall */ -#define PWR_PASSWALL 32 - -/** @def PWR_DETECT_TD - * @note Detect traps, doors, and stairs */ -#define PWR_DETECT_TD 33 - -/** @def PWR_COOK_FOOD - * @note Create some food */ -#define PWR_COOK_FOOD 34 - -/** @def PWR_UNFEAR - * @note Remove fear */ -#define PWR_UNFEAR 35 - -/** @def PWR_EXPL_RUNE - * @note Set an explosive rune */ -#define PWR_EXPL_RUNE 36 - -/** @def PWR_STM - * @note Bash a wall (stone to mud) */ -#define PWR_STM 37 - -/** @def PWR_POIS_DART - * @note Throw a poison dart (GF_POIS) */ -#define PWR_POIS_DART 38 - -/** @def PWR_MAGIC_MISSILE - * @note Fire a magic missile (GF_MISSILE) */ -#define PWR_MAGIC_MISSILE 39 - -/** @def PWR_GROW_TREE - * @note Grow trees around the player */ -#define PWR_GROW_TREE 40 - -/** @def PWR_BR_COLD - * @note Breathe cold (GF_COLD) */ -#define PWR_BR_COLD 41 - -/** @def PWR_BR_CHAOS - * @note Breathe chaos (GF_CHAOS) */ -#define PWR_BR_CHAOS 42 - -/** @def PWR_BR_ELEM - * @note Breath elements (GF_MISSILE) */ -#define PWR_BR_ELEM 43 - -/** @def PWR_WRECK_WORLD - * @note Change the world (new level) */ -#define PWR_WRECK_WORLD 44 - -/** @def PWR_SCARE - * @note Howl to scare monsters */ -#define PWR_SCARE 45 - -/** @def PWR_REST_LIFE - * @note Restore life levels */ -#define PWR_REST_LIFE 46 - -/** @def PWR_SUMMON_MONSTER - * @note Beastmaster powers (summon pets) */ -#define PWR_SUMMON_MONSTER 47 - -/** @def PWR_NECRO - * @note Cast a necromancy spell */ -#define PWR_NECRO 48 - -/** @def PWR_ROHAN - * @note Use flash aura or light speed jump */ -#define PWR_ROHAN 49 - -/** @def PWR_THUNDER - * @note Use thunder strike, ride the straight road, or go back in town */ -#define PWR_THUNDER 50 - -/** @def PWR_DEATHMOLD - * @note Use deathmold powers:\n - * (a) Teleport to a specific place\n - * (b) Fetch an item\n - * (c) Go up 50'\n - * (d) Go down 50' - */ -#define PWR_DEATHMOLD 51 - -/** @def PWR_HYPNO - * @note Hypnotise a pet */ -#define PWR_HYPNO 52 - -/** @def PWR_UNHYPNO - * @note Unhypnotise a pet */ -#define PWR_UNHYPNO 53 - -/** @def PWR_INCARNATE - * @note Incarnate into a body */ -#define PWR_INCARNATE 54 - -/** @def PWR_MAGIC_MAP - * @note Magic mapping */ -#define PWR_MAGIC_MAP 55 - -/** @def PWR_LAY_TRAP - * @note Set a trap */ -#define PWR_LAY_TRAP 56 - -/** @def PWR_MERCHANT - * @note Appraise item, warp item, or identify item */ -#define PWR_MERCHANT 57 - -/** @def PWR_COMPANION - * @note Create a companion */ -#define PWR_COMPANION 58 - -/** @def PWR_BEAR - * @note Mimic a bear */ -#define PWR_BEAR 59 - -/** @def PWR_DODGE - * @note Report chance of dodging a monster */ -#define PWR_DODGE 60 - -/** @def PWR_BALROG - * @note Mimic a balrog */ -#define PWR_BALROG 61 -/** @} */ - -#define POWER_INVISIBILITY 62 -#define POWER_WEB 63 -#define POWER_COR_SPACE_TIME 64 - - -/* Misc */ -/** @fn do_cmd_throw(void) - * @brief Throw an object from the pack or floor. - * @note - * Note: "unseen" monsters are very hard to hit. - * @note - * Should throwing a weapon do full damage? Should it allow the magic - * to hit bonus of the weapon to have an effect? Should it ever cause - * the item to be destroyed? Should it do any damage at all? - * @note (see file cmd2.c) - */ -extern void do_cmd_throw(void); - -/** @fn change_wild_mode() - * @brief Toggle between big map and little map. - * @note - * If the player is immovable, and the map is big, the player receives a - * warning and is allowed to proceed. - * @note - * If the player is about to be recalled, and the map is big, the map is - * not changed. - * @note - * The map is changed. The game is saved if autosave is set to "levels". - * @note (see file spells2.c) - */ -extern void change_wild_mode(); - -/* Player race flags */ -$static bool lua_test_race_flags(int slot, u32b flags) { if (slot == 1) return (PRACE_FLAG(flags)) ? TRUE : FALSE; else return (PRACE_FLAG2(flags)) ? TRUE : FALSE; } -/** @fn test_race_flags(int slot, u32b flags); - * @brief Test flag "flags" against race flags, race modifier flags, class - * flags, and specialist flags.\n - * @param slot Number \n 1 if testing against first set of flags (PRACE_FLAG), - * 2 if testing against second set of flags (PRACE_FLAG2) - * @brief Flag selecter. - * @param flags Number \n the flags to be tested - * @brief Test flags - * @return Boolean \n TRUE if test flags match any of the corresponding race, - * race modifier, class, and specialist flags. - * @note (see file w_player.c) - */ -static bool lua_test_race_flags@test_race_flags(int slot, u32b flags); - -/** @name Winner states - * @{ */ -/** @def WINNER_NORMAL - * @note Player has killed Morgoth */ -#define WINNER_NORMAL 1 - -/** @def WINNER_ULTRA - * @note Player has killed Melkor */ -#define WINNER_ULTRA 2 -/** @} */ - -/** @var wizard - * @brief Boolean - * @note TRUE if player currently in Wizard mode, otherwise FALSE. - */ -extern bool wizard; - -/** @var total_winner - * @brief Number - * @note Game has been won (see WINNER_foo fields). - */ -extern u16b total_winner; - -/** @var has_won - * @brief Number - * @note Game has been won (see WINNER_foo fields). - */ -extern u16b has_won; - -/** @var joke_monsters - * @brief Boolean - * @note TRUE if allowing joke monsters, otherwise FALSE. - */ -extern bool joke_monsters; - -extern s16b max_dlv[999999]; diff --git a/src/player_c.pkg b/src/player_c.pkg deleted file mode 100644 index f55f9325..00000000 --- a/src/player_c.pkg +++ /dev/null @@ -1,1060 +0,0 @@ -/* File: player_c.pkg */ - -/* - * Purpose: Lua interface defitions for player classes. - * To be processed by tolua to generate C source code. - */ - -$#include "angband.h" - -/** @typedef cptr - * @note String - */ -typedef char* cptr; -/** @typedef errr - * @note Number - */ -typedef int errr; -/** @typedef bool - * @note Boolean - */ -typedef unsigned char bool; -/** @typedef byte - * @note Number - */ -typedef unsigned char byte; -/** @typedef s16b - * @note Number - */ -typedef signed short s16b; -/** @typedef u16b - * @note Number - */ -typedef unsigned short u16b; -/** @typedef s32b - * @note Number - */ -typedef signed int s32b; -/** @typedef u32b - * @note Number - */ -typedef unsigned int u32b; - -/** @struct player_class - * @brief Player class - */ -struct player_class -{ - /** @structvar title - * @brief Number - * @note Type of class - */ - s32b title; - /** @structvar desc - * @brief Number - * @note Small desc of the class - */ - s32b desc; - /** @structvar titles[10] - * @brief Number - */ - s32b titles[10]; - - /** @structvar c_adj[6] - * @brief Number - * @note Class stat modifier - */ - s16b c_adj[6]; - - /** @structvar c_dis - * @brief Number - * @note class disarming - */ - s16b c_dis; - /** @structvar c_dev - * @brief Number - * @note class magic devices - */ - s16b c_dev; - /** @structvar c_sav - * @brief Number - * @note class saving throws - */ - s16b c_sav; - /** @structvar c_stl - * @brief Number - * @note class stealth - */ - s16b c_stl; - /** @structvar c_srh - * @brief Number - * @note class searching ability - */ - s16b c_srh; - /** @structvar c_fos - * @brief Number - * @note class searching frequency - */ - s16b c_fos; - /** @structvar c_thn - * @brief Number - * @note class to hit (normal) - */ - s16b c_thn; - /** @structvar c_thb - * @brief Number - * @note class to hit (bows) - */ - s16b c_thb; - - /** @structvar x_dis - * @brief Number - * @note extra disarming - */ - s16b x_dis; - /** @structvar x_dev - * @brief Number - * @note extra magic devices - */ - s16b x_dev; - /** @structvar x_sav - * @brief Number - * @note extra saving throws - */ - s16b x_sav; - /** @structvar x_stl - * @brief Number - * @note extra stealth - */ - s16b x_stl; - /** @structvar x_srh - * @brief Number - * @note extra searching ability - */ - s16b x_srh; - /** @structvar x_fos - * @brief Number - * @note extra searching frequency - */ - s16b x_fos; - /** @structvar x_thn - * @brief Number - * @note extra to hit (normal) - */ - s16b x_thn; - /** @structvar x_thb - * @brief Number - * @note extra to hit (bows) - */ - s16b x_thb; - - /** @structvar c_mhp - * @brief Number - * @note Class hit-dice adjustment - */ - s16b c_mhp; - /** @structvar c_exp - * @brief Number - * @note Class experience factor - */ - s16b c_exp; - - /** @structvar powers[4] - * @brief Number - * @note Powers of the class - */ - s16b powers[4]; - - /** @structvar spell_book - * @brief Number - * @note Tval of spell books (if any) - */ - s16b spell_book; - /** @structvar spell_stat - * @brief Number - * @note Stat for spells (if any) - */ - s16b spell_stat; - /** @structvar spell_lev - * @brief Number - * @note The higher it is the higher the spells level are - */ - s16b spell_lev; - /** @structvar spell_fail - * @brief Number - * @note The higher it is the higher the spells failure are - */ - s16b spell_fail; - /** @structvar spell_mana - * @brief Number - * @note The higher it is the higher the spells mana are - */ - s16b spell_mana; - /** @structvar spell_first - * @brief Number - * @note Level of first spell - */ - s16b spell_first; - /** @structvar spell_weight - * @brief Number - * @note Weight that hurts spells - */ - s16b spell_weight; - /** @structvar max_spell_level - * @brief Number - * @note Maximun spell level - */ - byte max_spell_level; - /** @structvar magic_max_spell - * @brief Number - * @note Maximun numbner of spells one can learn by natural means - */ - byte magic_max_spell; - - /** @structvar flags1 - * @brief Number - * @note flags - */ - s32b flags1; - - /** @structvar mana - * @brief Number - */ - s16b mana; - /** @structvar blow_num - * @brief Number - */ - s16b blow_num; - /** @structvar blow_wgt - * @brief Number - */ - s16b blow_wgt; - /** @structvar blow_mul - * @brief Number - */ - s16b blow_mul; - /** @structvar extra_blows - * @brief Number - */ - s16b extra_blows; - - /** @structvar sense_base - * @brief Number - */ - s32b sense_base; - /** @structvar sense_pl - * @brief Number - */ - s32b sense_pl; - /** @structvar sense_plus - * @brief Number - */ - s32b sense_plus; - /** @structvar sense_heavy - * @brief Number - */ - byte sense_heavy; - /** @structvar sense_heavy_magic - * @brief Number - */ - byte sense_heavy_magic; -}; - -/** @var *cp_ptr - * @brief player_class - * @note Player class information - */ -extern player_class *cp_ptr; - - - -/** @struct skill_type - * @brief Skills - */ -struct skill_type -{ - /** @structvar name - * @brief Number - * @note Name - */ - u32b name; - /** @structvar desc - * @brief Number - * @note Description - */ - u32b desc; - /** @structvar action_desc - * @brief Number - * @note Action Description - */ - u32b action_desc; - - /** @structvar action_mkey - * @brief Number - * @note Action do to - */ - s16b action_mkey; - - /** @structvar i_value - * @brief Number - * @note Actual value - */ - u32b i_value; - /** @structvar i_mod - * @brief Number - * @note Modifier(1 skill point = modifier skill) - */ - u16b i_mod; - - /** @structvar value - * @brief Number - * @note Actual value - */ - u32b value; - /** @structvar mod - * @brief Number - * @note Modifier(1 skill point = modifier skill) - */ - u16b mod; - /** @structvar rate - * @brief Number - * @note Modifier decreasing rate - */ - s16b rate; - - /** @structvar uses - * @brief Number - * @note Number of times used - */ - u32b uses; - - /** @structvar action[9999] - * @brief Number - * @note List of actions against other skills - */ - s16b action[9999]; - - /** @structvar father - * @brief Number - * @note Father in the skill tree - */ - s16b father; - /** @structvar dev - * @brief Boolean - * @note Is the branch developped ? - */ - bool dev; - /** @structvar order - * @brief Number - * @note Order in the tree - */ - s16b order; - /** @structvar hidden - * @brief Boolean - * @note Innactive - */ - bool hidden; -}; - -/** @def MAX_SKILLS - * @brief Maximum number of skills - */ -#define MAX_SKILLS 100 - - -$static cptr get_skill_name(int i) { return s_name + s_info[i].name; } -/** @fn get_skill_name(int i) - * @brief Return name of skill with index "i" in skill array.\n - * @param i Number \n the index of skill in skill array. - * @brief Skill index - * @return String \n The name of the skill with index "i" in the skill array. - * @note (see file w_play_c.c) - */ -static cptr get_skill_name(int i); - -/** @var old_max_s_idx - * @brief Number - * @note Previous maximum skill index - */ -extern u16b old_max_s_idx; -/** @var max_s_idx - * @brief Number - * @note Current maximum skill index - */ -extern u16b max_s_idx; -/** @var s_info[MAX_SKILLS] - * @brief skill_type - * @note Array of player skills - */ -skill_type s_info[MAX_SKILLS]; - -/** @name Skills - * @{ */ -/** @def SKILL_CONVEYANCE - * @brief Conveyance - * @note - * Ability to learn and use spells from the Conveyance school - */ -#define SKILL_CONVEYANCE 1 - -/** @def SKILL_MANA - * @brief Mana - * @note - * Ability to learn and use spells from the Mana school - */ -#define SKILL_MANA 2 - -/** @def SKILL_FIRE - * @brief Fire - * @note - * Ability to learn and use spells from the Fire school - */ -#define SKILL_FIRE 3 - -/** @def SKILL_AIR - * @brief Air - * @note - * Ability to learn and use spells from the Air school - */ -#define SKILL_AIR 4 - -/** @def SKILL_WATER - * @brief Water - * @note - * Ability to learn and use spells from the Water school - */ -#define SKILL_WATER 5 - -/** @def SKILL_NATURE - * @brief Nature - * @note - * Ability to learn and use spells from the Nature school - */ -#define SKILL_NATURE 6 - -/** @def SKILL_EARTH - * @brief Earth - * @note - * Ability to learn and use spells from the Earth school - */ -#define SKILL_EARTH 7 - -/** @def SKILL_SYMBIOTIC - * @brief Symbiosis - * @note - * Ability to enter in symbiosis with monsters unable to move by themselves - */ -#define SKILL_SYMBIOTIC 8 - -/** @def SKILL_MUSIC - * @brief Music - * @note - * Ability to learn and sing songs - */ -#define SKILL_MUSIC 9 - -/** @def SKILL_DIVINATION - * @brief Divination - * @note - * Ability to learn and use spells from the Divination school - */ -#define SKILL_DIVINATION 10 - -/** @def SKILL_TEMPORAL - * @brief Temporal - * @note - * Ability to learn and use spells from the Temporal school - */ -#define SKILL_TEMPORAL 11 - -/** @def SKILL_DRUID - * @brief Druidistic - * @note - * Ability to learn and use prayers from the Druidistic realm - */ -#define SKILL_DRUID 12 - -/** @def SKILL_DAEMON - * @brief Demonology - * @note - * Ability to use incantations from the Demonblades - */ -#define SKILL_DAEMON 13 - -/** @def SKILL_META - * @brief Meta - * @note - * Ability to learn and use spells from the Meta school - */ -#define SKILL_META 14 - -/** @def SKILL_MAGIC - * @brief Magic - * @note - * General ability to do magic, also affect mana reserves and - * magic device ability. Helps pseudo-id of magic objects - */ -#define SKILL_MAGIC 15 - -/** @def SKILL_COMBAT - * @brief Combat - * @note - * General ability to fight and to pseudo-id armours and weapons. - * It also allows to use heavier armours without penalties - */ -#define SKILL_COMBAT 16 - -/** @def SKILL_MASTERY - * @brief Weaponmastery - * @note - * General ability to use melee weapons - */ -#define SKILL_MASTERY 17 - -/** @def SKILL_SWORD - * @brief Sword-mastery - * @note - * Ability to use swords - */ -#define SKILL_SWORD 18 - -/** @def SKILL_AXE - * @brief Axe-mastery - * @note - * Ability to use axes - */ -#define SKILL_AXE 19 - -/** @def SKILL_POLEARM - * @brief Polearm-mastery - * @note - * Ability to use polearms - */ -#define SKILL_POLEARM 20 - -/** @def SKILL_HAFTED - * @brief Hafted-mastery - * @note - * Ability to use hafted weapons - */ -#define SKILL_HAFTED 21 - -/** @def SKILL_BACKSTAB - * @brief Backstab - * @note - * Ability to backstab fleeing and sleeping monsters to increase damage - */ -#define SKILL_BACKSTAB 22 - -/** @def SKILL_ARCHERY - * @brief Archery - * @note - * General ability to use ranged weapons - */ -#define SKILL_ARCHERY 23 - -/** @def SKILL_SLING - * @brief Sling-mastery - * @note - * Ability to use slings - */ -#define SKILL_SLING 24 - -/** @def SKILL_BOW - * @brief Bow-mastery - * @note - * Ability to use bows - */ -#define SKILL_BOW 25 - -/** @def SKILL_XBOW - * @brief Crossbow-mastery - * @note - * Ability to use crossbows - */ -#define SKILL_XBOW 26 - -/** @def SKILL_BOOMERANG - * @brief Boomerang-mastery - * @note - * Ability to use boomerangs - */ -#define SKILL_BOOMERANG 27 - -/** @def SKILL_SPIRITUALITY - * @brief Spirituality - * @note - * General ability to use spiritual skills and also influence Saving Throw - */ -#define SKILL_SPIRITUALITY 28 - -/** @def SKILL_MINDCRAFT - * @brief Mindcraft - * @note - * Ability to focus the powers of the mind - */ -#define SKILL_MINDCRAFT 29 - -/** @def SKILL_MISC - * @brief Misc - * @note - * Not a real skill, it is only used to regroup some skills - */ -#define SKILL_MISC 30 - -/** @def SKILL_NECROMANCY - * @brief Necromancy - * @note - * Ability to harness the powers of the dead - */ -#define SKILL_NECROMANCY 31 - -/** @def SKILL_MIMICRY - * @brief Mimicry - * @note - * Ability to use cloaks of mimicry to change form - */ -#define SKILL_MIMICRY 32 - -/** @def SKILL_ANTIMAGIC - * @brief Antimagic - * @note - * Ability to generates an antimagic field - */ -#define SKILL_ANTIMAGIC 33 - -/** @def SKILL_RUNECRAFT - * @brief Runecraft - * @note - * Ability to combine magic runes to create your own spells - */ -#define SKILL_RUNECRAFT 34 - -/** @def SKILL_SNEAK - * @brief Sneakiness - * @note - * General ability at the sneakiness skills - */ -#define SKILL_SNEAK 35 - -/** @def SKILL_STEALTH - * @brief Stealth - * @note - * Ability to move unnoticed, silently - */ -#define SKILL_STEALTH 36 - -/** @def SKILL_DISARMING - * @brief Disarming - * @note - * Ability to disarm the various traps - */ -#define SKILL_DISARMING 37 - -/* XXX */ - -/** @def SKILL_ALCHEMY - * @brief Alchemy - * @note - * Ability to use essences to modify/create magic items - */ -#define SKILL_ALCHEMY 39 - -/** @def SKILL_STEALING - * @brief Stealing - * @note - * Ability to steal objects - */ -#define SKILL_STEALING 40 - -/** @def SKILL_SORCERY - * @brief Sorcery - * @note - * Ability to use all the magic schools as if their skill was sorcery - */ -#define SKILL_SORCERY 41 - -/** @def SKILL_HAND - * @brief Barehand-combat - * @note - * Ability to fight barehanded - */ -#define SKILL_HAND 42 - -/** @def SKILL_THAUMATURGY - * @brief Thaumaturgy - * @note - * Ability to gain and cast innate spells - */ -#define SKILL_THAUMATURGY 43 - -/** @def SKILL_SUMMON - * @brief Summoning - * @note - * Ability to create totems from monsters and use them to summon monsters - */ -#define SKILL_SUMMON 44 - -/** @def SKILL_SPELL - * @brief Spell-power - * @note - * Ability to increase the power of spells - */ -#define SKILL_SPELL 45 - -/** @def SKILL_DODGE - * @brief Dodging - * @note - * Ability to dodge blows and bolts - */ -#define SKILL_DODGE 46 - -/** @def SKILL_BEAR - * @brief Bearform-combat - * @note - * Ability to fight in bear form - */ -#define SKILL_BEAR 47 - -/** @def SKILL_LORE - * @brief Monster-lore - * @note - * General ability at the monster related skills, ability to gain experience - * from friendly kills. It also affects the number of companions the player - * can have - */ -#define SKILL_LORE 48 - -/** @def SKILL_PRESERVATION - * @brief Corpse-preservation - * @note - * Ability to not destroy the monster corpse when killing them - */ -#define SKILL_PRESERVATION 49 - -/** @def SKILL_POSSESSION - * @brief Possession - * @note - * Ability to incarnate into monsters - */ -#define SKILL_POSSESSION 50 - -/** @def SKILL_MIND - * @brief Mind - * @note - * Ability to learn and use spells from the Mind school - */ -#define SKILL_MIND 51 - -/** @def SKILL_CRITS - * @brief Critical-hits - * @note - * Ability to deal critical hits with swords < 5lb - */ -#define SKILL_CRITS 52 - -/** @def SKILL_PRAY - * @brief Prayer - * @note - * Ability to learn and use spells from the gods schools - */ -#define SKILL_PRAY 53 - -/** @def SKILL_LEARN - * @brief Spell-learning - * @note - * You should not see that ! that is a BUG! - */ -#define SKILL_LEARN 54 - -/** @def SKILL_UDUN - * @brief Udun - * @note - * Ability to learn and use spells from the Udun school - */ -#define SKILL_UDUN 55 - -/** @def SKILL_DEVICE - * @brief Magic-Device - * @note - * Ease the use of magical devices, such as wands, staves and rods. - * It also helps pseudo-id of magic objects - */ -#define SKILL_DEVICE 56 - -/** @def SKILL_STUN - * @brief Stunning-blows - * @note - * Ability to stun opponents when doing critical hits with hafted weapons > 5lb - */ -#define SKILL_STUN 57 - -/** @def SKILL_BOULDER - * @brief Boulder-throwing - * @note - * Ability to make and throw boulders - */ -#define SKILL_BOULDER 58 - -/** @def SKILL_GEOMANCY - * @brief Geomancy - * @note - * Ability to understand the raw elemental forces of nature and use - * them to advantage. Most spells need Fire/Water/Earth/Air skills - */ -#define SKILL_GEOMANCY 59 - - -/** @def SKILL_MAX - * @note Maximun skill value - */ -#define SKILL_MAX 50000 -/** @def SKILL_STEP - * @note 1 skill point - */ -#define SKILL_STEP 1000 - -/** @} */ - -/** @fn get_skill(int skill) - * @brief Return the value of skill with index "skill" in skill array.\n - * @param skill Number \n the index of skill in skill array. - * @brief Skill index - * @return Number \n The value of the skill with index "skill" in the skill - * array. - * @note (see file skills.c) - */ -extern s16b get_skill(int skill); - -/** @fn get_skill_scale(int skill, u32b scale) - * @brief Return the value of skill with index "skill" in skill array rescaled - * to a maximum of "scale".\n - * @param skill Number \n the index of skill in skill array. - * @brief Skill index - * @param scale Number \n the maximum rescaled skill value. - * @brief Scaled maximum - * @return Number \n The rescaled value of the skill with index "skill" in the - * skill array. - * @note (see file skills.c) - */ -extern s16b get_skill_scale(int skill, u32b scale); - -/** @fn do_get_new_skill() - * @brief Player select one of four new skills. - * @note (see file skills.c) - */ -extern void do_get_new_skill(); - -/** @fn get_melee_skills() - * @brief Return the number of melee skills the player has. - * @return Number \n The number of melee skills. - * @note - * A skill is counted if the value > 0 and the skill is not hidden. - * @note (see file skills.c) - */ -extern s16b get_melee_skills(); - -/** @fn find_skill(cptr name) - * @brief Return the index of skill with name "name".\n - * @param name String \n the name of the skill. - * @brief Skill name - * @return Number \n The index of the skill with name "name" in the skill - * array. - * @note - * The search is case sensitive.\n - * If no skills match the name, -1 is returned. - * @note (see file skills.c) - */ -extern s16b find_skill(cptr name); - -/** @fn find_skill_i(cptr name) - * @brief Return the index of skill with name "name".\n - * @param name String \n the name of the skill. - * @brief Skill name - * @return Number \n The index of the skill with name "name" in the skill - * array. - * @note - * The search ignores case.\n - * If no skills match the name, -1 is returned. - * @note (see file skills.c) - */ -extern s16b find_skill_i(cptr name); - -$static char *get_class_name() {return spp_ptr->title + c_name;} -/** @fn *get_class_name() - * @brief Return the player's class. - * @return String \n The player's type of class + class name - * @note (see file w_play_c.c) - */ -char *get_class_name(); - -$static char *get_race_name() {return rp_ptr->title + rp_name;} -/** @fn *get_race_name() - * @brief Return the player's race. - * @return String \n The player's type of race + race name - * @note (see file w_play_c.c) - */ -char *get_race_name(); - -$static char *get_subrace_name() {return rmp_ptr->title + rmp_name;} -/** @fn *get_subrace_name() - * @brief Return the player's subrace. - * @return String \n The player's type of subrace + subrace name - * @note (see file w_play_c.c) - */ -char *get_subrace_name(); - -/** @struct ability_type - * @brief Abilities - */ -struct ability_type -{ - /** @structvar action_mkey - * @brief Number - * @note Action do to - */ - s16b action_mkey; - - /** @structvar cost - * @brief Number - * @note Skill points cost - */ - s16b cost; - - /** @structvar acquired - * @brief Boolean - * @note Do the player actualylg ot it ? - */ - bool acquired; -}; - -/** @fn find_ability(cptr name) - * @brief Return the index of ability with name "name".\n - * @param name String \n the name of the ability. - * @brief Ability name - * @return Number \n The index of the ability with name "name" in the ability - * array. - * @note - * The search is case sensitive.\n - * If no abilities match the name, -1 is returned. - * @note (see file skills.c) - */ -extern s16b find_ability(cptr name); - -/** @fn do_cmd_ability() - * @brief Allow the user to interact with abilities. - * @note - * This screen is typically used to view abilities, and increase them. - * @note (see file skills.c) - */ -extern void do_cmd_ability(); - -/** @fn has_ability(int ab) - * @brief Does the player have ability "ab"? - * @param ab Number \n the index of ability in ability array. - * @brief Ability index - * @return Boolean \n TRUE if player has the ability, otherwise FALSE. - * @note (see file skills.c) - */ -extern bool has_ability(int ab); - -/** @var max_ab_idx - * @brief Number - * @note Maximum ability index - */ -extern s16b max_ab_idx; -/** @var ab_info[max_ab_idx] - * @brief ability_type - * @note Array of player abilities - */ -extern ability_type ab_info[max_ab_idx]; - -/** @name Abilities - * @{ */ -/** @def AB_SPREAD_BLOWS - * @brief Spread blows - * @note - * If a monster dies to an attack but the player still has blows left - * they won't lose the full turn, allowing them to attack some other - * monster in the same turn. - */ -#define AB_SPREAD_BLOWS 0 - -/** @def AB_TREE_WALK - * @brief Tree walking - * @note - * Allows player to walk in dense forest. - */ -#define AB_TREE_WALK 1 - -/** @def AB_PERFECT_CASTING - * @brief Perfect casting - * @note - * Allows player to reach 0% failure rate on spells. - */ -#define AB_PERFECT_CASTING 2 - -/** @def AB_MAX_BLOW1 - * @brief Extra Max Blow(1) - * @note - * Increases player "maximum possible blows" number by 1. - */ -#define AB_MAX_BLOW1 3 - -/** @def AB_MAX_BLOW2 - * @brief Extra Max Blow(2) - * @note - * Increases player "maximum possible blows" number by 1 - * (Cumulative with Extra Max Blow(1)). - */ -#define AB_MAX_BLOW2 4 - -/** @def AB_AMMO_CREATION - * @brief Ammo creation - * @note - * Allows player to create shots, arrows and bolts from various materials. - */ -#define AB_AMMO_CREATION 5 - -/** @def AB_DEATH_TOUCH - * @brief Touch of death - * @note - * Player melee blows can insta-kill, but they only receive 1/3 of the - * experience for that kill. - */ -#define AB_DEATH_TOUCH 6 - -/** @def AB_CREATE_ART - * @brief Artifact creation - * @note - * In combination with a high alchemy skill this ability will let the player - * design their very own artifacts. - */ -#define AB_CREATE_ART 7 - -/** @def AB_FAR_REACHING - * @brief Far reaching attack - * @note - * The player can attack an enemy one square far using a polearm. - * At high levels of polearm skill, they can even hit two enemies at once. - */ -#define AB_FAR_REACHING 8 - -/** @def AB_TRAPPING - * @brief Trapping - * @note - * Enables player to set traps which harm monsters. - */ -#define AB_TRAPPING 9 - -/** @def AB_UNDEAD_FORM - * @brief Undead form - * @note - * Ability to turn into a weak undead being when you "die". - * You must then kill enough monsters to absorb enough life energy - * to come back to life. - */ -#define AB_UNDEAD_FORM 10 - -/** @} */ - diff --git a/src/plots.c b/src/plots.c index 2fb592b0..f5801ec3 100644 --- a/src/plots.c +++ b/src/plots.c @@ -13,10 +13,6 @@ #include "angband.h" #include -#include "lua/lua.h" -#include "tolua.h" -extern lua_State* L; - /* #define DEBUG_HOOK */ /******** Hooks stuff *********/ @@ -117,16 +113,6 @@ void add_hook_new(int h_idx, bool_ (*hook_f)(void *, void *, void *), cptr name, c->type = HOOK_TYPE_NEW; } -void add_hook_script(int h_idx, char *script, cptr name) -{ - hooks_chain *c = add_hook(h_idx, NULL, name); -#ifdef DEBUG_HOOK - if (wizard) cmsg_format(TERM_VIOLET, "HOOK LUA ADD: %s : %s", name, script); -#endif - sprintf(c->script, "%s", script); - c->type = HOOK_TYPE_LUA; -} - /* Remove a hook */ void del_hook(int h_idx, hook_type hook) { @@ -299,102 +285,6 @@ static bool_ vprocess_hooks_return (int h_idx, char *ret, char *fmt, va_list *ap c = c->next; } } - else if (c->type == HOOK_TYPE_LUA) - { - int i = 0, nb = 0, nbr = 1; - int oldtop = lua_gettop(L), size; - - /* Push the function */ - lua_getglobal(L, c->script); - - /* Push and count the arguments */ - COPY(&real_ap, ap, va_list); - while (fmt[i]) - { - switch (fmt[i++]) - { - case 'd': - case 'l': - tolua_pushnumber(L, va_arg(real_ap, s32b)); - nb++; - break; - case 's': - tolua_pushstring(L, va_arg(real_ap, char*)); - nb++; - break; - case 'O': - tolua_pushusertype(L, (void*)va_arg(real_ap, object_type*), tolua_tag(L, "object_type")); - nb++; - break; - case 'M': - tolua_pushusertype(L, (void*)va_arg(real_ap, monster_type*), tolua_tag(L, "monster_type")); - nb++; - break; - case '(': - case ')': - case ',': - break; - } - } - - /* Count returns */ - nbr += strlen(ret); - - /* Call the function */ - if (lua_call(L, nb, nbr)) - { - cmsg_format(TERM_VIOLET, "ERROR in lua_call while calling '%s' lua hook script. Breaking the hook chain now.", c->script); - return FALSE; - } - - /* Number of returned values, SHOULD be the same as nbr, but I'm paranoid */ - size = lua_gettop(L) - oldtop; - - /* get the extra returns if needed */ - for (i = 0; i < nbr - 1; i++) - { - if ((ret[i] == 'd') || (ret[i] == 'l')) - { - if (lua_isnumber(L, ( -size) + 1 + i)) process_hooks_return[i].num = tolua_getnumber(L, ( -size) + 1 + i, 0); - else process_hooks_return[i].num = 0; - } - else if (ret[i] == 's') - { - if (lua_isstring(L, ( -size) + 1 + i)) process_hooks_return[i].str = tolua_getstring(L, ( -size) + 1 + i, ""); - else process_hooks_return[i].str = NULL; - } - else if (ret[i] == 'O') - { - if (tolua_istype(L, ( -size) + 1 + i, tolua_tag(L, "object_type"), 0)) - process_hooks_return[i].o_ptr = (object_type*)tolua_getuserdata(L, ( -size) + 1 + i, NULL); - else - process_hooks_return[i].o_ptr = NULL; - } - else if (ret[i] == 'M') - { - if (tolua_istype(L, ( -size) + 1 + i, tolua_tag(L, "monster_type"), 0)) - process_hooks_return[i].m_ptr = (monster_type*)tolua_getuserdata(L, ( -size) + 1 + i, NULL); - else - process_hooks_return[i].m_ptr = NULL; - } - else process_hooks_return[i].num = 0; - } - - /* Get the basic return(continue or stop the hook chain) */ - if (tolua_getnumber(L, -size, 0)) - { - lua_settop(L, oldtop); - return (TRUE); - } - if (process_hooks_restart) - { - c = hooks_heads[h_idx]; - process_hooks_restart = FALSE; - } - else - c = c->next; - lua_settop(L, oldtop); - } else if (c->type == HOOK_TYPE_NEW) { /* Skip; handled in process_hooks_new */ diff --git a/src/q_fireprof.c b/src/q_fireprof.c index 35ca7d7e..4405d43b 100644 --- a/src/q_fireprof.c +++ b/src/q_fireprof.c @@ -406,7 +406,7 @@ static bool_ fireproof_stair_hook(char *fmt) } else { - bool ret; + bool_ ret; if (cave[p_ptr->py][p_ptr->px].feat != FEAT_LESS) { diff --git a/src/script.c b/src/script.c index 9a863146..40f43f95 100644 --- a/src/script.c +++ b/src/script.c @@ -12,220 +12,9 @@ #include "angband.h" -#include "lua/lua.h" -#include "lua/lualib.h" -#include "lauxlib.h" -#include "tolua.h" - -int tolua_monster_open (lua_State *L); -int tolua_player_open (lua_State *L); -int tolua_player_c_open (lua_State *L); -int tolua_util_open (lua_State *L); -int tolua_z_pack_open (lua_State *L); -int tolua_object_open (lua_State *L); -int tolua_spells_open (lua_State *L); -int tolua_dungeon_open (lua_State *L); - -/* - * Lua state - */ -lua_State* L = NULL; - -/* ToME Lua error message handler */ -static int tome_errormessage(lua_State *L) -{ - char buf[200]; - cptr str = luaL_check_string(L, 1); - int i = 0, j = 0; - - while (str[i]) - { - if (str[i] == '#') - { - buf[j++] = '$'; - } - else if (str[i] != '\n') - { - buf[j++] = str[i]; - } - else - { - buf[j] = '\0'; - cmsg_format(TERM_VIOLET, "LUA: %s", buf); - j = 0; - } - i++; - } - buf[j] = '\0'; - cmsg_format(TERM_VIOLET, "LUA: %s", buf); - return (0); -} - -static struct luaL_reg tome_iolib[] = -{ - { "_ALERT", tome_errormessage }, -}; - -#define luaL_check_bit(L, n) ((long)luaL_check_number(L, n)) -#define luaL_check_ubit(L, n) ((unsigned long)luaL_check_bit(L, n)) - - -/* - * Monadic bit negation operation - * MONADIC(not, ~) - */ -static int int_not(lua_State* L) -{ - lua_pushnumber(L, ~luaL_check_bit(L, 1)); - return 1; -} - - -/* - * Dyadic integer modulus operation - * DYADIC(mod, %) - */ -static int int_mod(lua_State* L) -{ - lua_pushnumber(L, luaL_check_bit(L, 1) % luaL_check_bit(L, 2)); - return 1; -} - - -/* - * Variable length bitwise AND operation - * VARIADIC(and, &) - */ -static int int_and(lua_State *L) -{ - int n = lua_gettop(L), i; - long w = luaL_check_bit(L, 1); - - for (i = 2; i <= n; i++) w &= luaL_check_bit(L, i); - lua_pushnumber(L, w); - - return 1; -} - - -/* - * Variable length bitwise OR operation - * VARIADIC(or, |) - */ -static int int_or(lua_State *L) -{ - int n = lua_gettop(L), i; - long w = luaL_check_bit(L, 1); - - for (i = 2; i <= n; i++) w |= luaL_check_bit(L, i); - lua_pushnumber(L, w); - - return 1; -} - - -/* - * Variable length bitwise XOR operation - * VARIADIC(xor, ^) - */ -static int int_xor(lua_State *L) -{ - int n = lua_gettop(L), i; - long w = luaL_check_bit(L, 1); - - for (i = 2; i <= n; i++) w ^= luaL_check_bit(L, i); - lua_pushnumber(L, w); - - return 1; -} - - -/* - * Binary left shift operation - * TDYADIC(lshift, <<, , u) - */ -static int int_lshift(lua_State* L) -{ - lua_pushnumber(L, luaL_check_bit(L, 1) << luaL_check_ubit(L, 2)); - return 1; -} - -/* - * Binary logical right shift operation - * TDYADIC(rshift, >>, u, u) - */ -static int int_rshift(lua_State* L) -{ - lua_pushnumber(L, luaL_check_ubit(L, 1) >> luaL_check_ubit(L, 2)); - return 1; -} - -/* - * Binary arithmetic right shift operation - * TDYADIC(arshift, >>, , u) - */ -static int int_arshift(lua_State* L) -{ - lua_pushnumber(L, luaL_check_bit(L, 1) >> luaL_check_ubit(L, 2)); - return 1; -} - - -static const struct luaL_reg bitlib[] = -{ - {"bnot", int_not}, - {"imod", int_mod}, /* "mod" already in Lua math library */ - {"band", int_and}, - {"bor", int_or}, - {"bxor", int_xor}, - {"lshift", int_lshift}, - {"rshift", int_rshift}, - {"arshift", int_arshift}, -}; - -/* - * Initialize lua scripting - */ -static bool_ init_lua_done = FALSE; -void init_lua() -{ - /* Hack -- Do not initialize more than once */ - if (init_lua_done) return; - init_lua_done = TRUE; - - /* Start the interpreter with default stack size */ - L = lua_open(0); - - /* Register the Lua base libraries */ - lua_baselibopen(L); - lua_strlibopen(L); - lua_iolibopen(L); - lua_dblibopen(L); - - /* Register tome lua debug library */ - luaL_openl(L, tome_iolib); - - /* Register the bitlib */ - luaL_openl(L, bitlib); - - /* Register the ToME main APIs */ - tolua_player_open(L); - tolua_player_c_open(L); - tolua_util_open(L); - tolua_z_pack_open(L); - tolua_object_open(L); - tolua_monster_open(L); - tolua_spells_open(L); - tolua_dungeon_open(L); -} void init_lua_init() { - int i, max; - - /* Load the first lua file */ - tome_dofile_anywhere(ANGBAND_DIR_CORE, "init.lua", TRUE); - /* Initialize schooled spells */ schools_init(); school_spells_init(); @@ -237,288 +26,3 @@ void init_lua_init() /* Finish up the corruptions */ init_corruptions(); } - -bool_ tome_dofile(char *file) -{ - char buf[1024]; - int oldtop = lua_gettop(L); - - /* Build the filename */ - path_build(buf, sizeof(buf), ANGBAND_DIR_SCPT, file); - - if (!file_exist(buf)) - { - /* No lua source(.lua), maybe a compiled one(.luo) ? */ - if (suffix(buf, ".lua")) - { - int len = strlen(buf); - buf[len - 1] = 'o'; - if (!file_exist(buf)) - { - cmsg_format(TERM_VIOLET, - "tome_dofile(): file %s(%s) doesn't exist.", file, buf); - return (FALSE); - } - } - } - - lua_dofile(L, buf); - lua_settop(L, oldtop); - - return (TRUE); -} - -bool_ tome_dofile_anywhere(cptr dir, char *file, bool_ test_exist) -{ - char buf[1024]; - int oldtop = lua_gettop(L); - - /* Build the filename */ - path_build(buf, sizeof(buf), dir, file); - - if (!file_exist(buf)) - { - /* No lua source(.lua), maybe a compiled one(.luo) ? */ - if (suffix(buf, ".lua")) - { - int len = strlen(buf); - buf[len - 1] = 'o'; - if (!file_exist(buf)) - { - if (test_exist) - cmsg_format(TERM_VIOLET, - "tome_dofile_anywhere(): file %s(%s) doesn't exist in %s.", dir, file, buf); - return (FALSE); - } - } - } - - lua_dofile(L, buf); - lua_settop(L, oldtop); - - return (TRUE); -} - -int exec_lua(char *file) -{ - int oldtop = lua_gettop(L); - int res; - - if (!lua_dostring(L, file)) - { - int size = lua_gettop(L) - oldtop; - res = tolua_getnumber(L, -size, 0); - } - else - res = 0; - - lua_settop(L, oldtop); - return (res); -} - -cptr string_exec_lua(char *file) -{ - int oldtop = lua_gettop(L); - cptr res; - - if (!lua_dostring(L, file)) - { - int size = lua_gettop(L) - oldtop; - res = tolua_getstring(L, -size, ""); - } - else - res = ""; - lua_settop(L, oldtop); - return (res); -} - -void dump_lua_stack(int min, int max) -{ - int i; - - cmsg_print(TERM_YELLOW, "lua_stack:"); - for (i = min; i <= max; i++) - { - if (lua_isnumber(L, i)) cmsg_format(TERM_YELLOW, "%d [n] = %d", i, tolua_getnumber(L, i, 0)); - else if (lua_isstring(L, i)) cmsg_format(TERM_YELLOW, "%d [s] = '%s'", i, tolua_getstring(L, i, 0)); - } - cmsg_print(TERM_YELLOW, "END lua_stack"); -} - -bool_ call_lua(cptr function, cptr args, cptr ret, ...) -{ - int i = 0, nb = 0, nbr = 0; - int oldtop = lua_gettop(L), size; - va_list ap; - - va_start(ap, ret); - - /* Push the function */ - lua_getglobal(L, function); - - /* Push and count the arguments */ - while (args[i]) - { - switch (args[i++]) - { - case 'd': - case 'l': - tolua_pushnumber(L, va_arg(ap, s32b)); - nb++; - break; - case 's': - tolua_pushstring(L, va_arg(ap, char*)); - nb++; - break; - case 'O': - tolua_pushusertype(L, (void*)va_arg(ap, object_type*), tolua_tag(L, "object_type")); - nb++; - break; - case 'M': - tolua_pushusertype(L, (void*)va_arg(ap, monster_type*), tolua_tag(L, "monster_type")); - nb++; - break; - case 'n': - lua_pushnil(L); - nb++; - break; - case '(': - case ')': - case ',': - break; - } - } - - /* Count returns */ - nbr = strlen(ret); - - /* Call the function */ - if (lua_call(L, nb, nbr)) - { - cmsg_format(TERM_VIOLET, "ERROR in lua_call while calling '%s' from call_lua. Things should start breaking up from now on!", function); - return FALSE; - } - - /* Number of returned values, SHOULD be the same as nbr, but I'm paranoid */ - size = lua_gettop(L) - oldtop; - - /* Get the returns */ - for (i = 0; ret[i]; i++) - { - switch (ret[i]) - { - case 'd': - case 'l': - { - s32b *tmp = va_arg(ap, s32b*); - - if (lua_isnumber(L, ( -size) + i)) *tmp = tolua_getnumber(L, ( -size) + i, 0); - else *tmp = 0; - break; - } - - case 's': - { - cptr *tmp = va_arg(ap, cptr*); - - if (lua_isstring(L, ( -size) + i)) *tmp = tolua_getstring(L, ( -size) + i, ""); - else *tmp = NULL; - break; - } - - case 'O': - { - object_type **tmp = va_arg(ap, object_type**); - - if (tolua_istype(L, ( -size) + i, tolua_tag(L, "object_type"), 0)) - *tmp = (object_type*)tolua_getuserdata(L, ( -size) + i, NULL); - else - *tmp = NULL; - break; - } - - case 'M': - { - monster_type **tmp = va_arg(ap, monster_type**); - - if (tolua_istype(L, ( -size) + i, tolua_tag(L, "monster_type"), 0)) - *tmp = (monster_type*)tolua_getuserdata(L, ( -size) + i, NULL); - else - *tmp = NULL; - break; - } - - default: - cmsg_format(TERM_VIOLET, "ERROR in lua_call while calling '%s' from call_lua: Unknown return type '%c'", function, ret[i]); - return FALSE; - } - } - - lua_settop(L, oldtop); - - va_end(ap); - - return TRUE; -} - -bool_ get_lua_var(cptr name, char type, void *arg) -{ - int oldtop = lua_gettop(L), size; - - /* Push the function */ - lua_getglobal(L, name); - - size = lua_gettop(L) - oldtop; - - switch (type) - { - case 'd': - case 'l': - { - s32b *tmp = (s32b*)arg; - - if (lua_isnumber(L, ( -size))) *tmp = tolua_getnumber(L, ( -size), 0); - else *tmp = 0; - break; - } - - case 's': - { - cptr *tmp = (cptr*)arg; - - if (lua_isstring(L, ( -size))) *tmp = tolua_getstring(L, ( -size), ""); - else *tmp = NULL; - break; - } - - case 'O': - { - object_type **tmp = (object_type**)arg; - - if (tolua_istype(L, ( -size), tolua_tag(L, "object_type"), 0)) - *tmp = (object_type*)tolua_getuserdata(L, ( -size), NULL); - else - *tmp = NULL; - break; - } - - case 'M': - { - monster_type **tmp = (monster_type**)arg; - - if (tolua_istype(L, ( -size), tolua_tag(L, "monster_type"), 0)) - *tmp = (monster_type*)tolua_getuserdata(L, ( -size), NULL); - else - *tmp = NULL; - break; - } - - default: - cmsg_format(TERM_VIOLET, "ERROR in get_lua_var while calling '%s': Unknown return type '%c'", name, type); - return FALSE; - } - - lua_settop(L, oldtop); - - return TRUE; -} diff --git a/src/spells.pkg b/src/spells.pkg deleted file mode 100644 index 26d7abab..00000000 --- a/src/spells.pkg +++ /dev/null @@ -1,2258 +0,0 @@ -/* File: spells.pkg */ - -/* - * Purpose: Lua interface defitions for spells. - * To be processed by tolua to generate C source code. - */ - -$#include "angband.h" -$#include "lua.h" - -/** @typedef *mcptr - * @note String - */ -typedef char *mcptr; - -/** @typedef cptr - * @note String - */ -typedef const char* cptr; - -/** @typedef errr - * @note Number - */ -typedef int errr; - -/** @typedef bool - * @note Boolean - */ -typedef unsigned char bool; - -/** @typedef byte - * @note Number - */ -typedef unsigned char byte; - -/** @typedef s16b - * @note Number - */ -typedef signed short s16b; - -/** @typedef u16b - * @note Number - */ -typedef unsigned short u16b; - -/** @typedef s32b - * @note Number - */ -typedef signed int s32b; - -/** @typedef u32b - * @note Number - */ -typedef unsigned int u32b; - -/** @def DEFAULT_RADIUS */ -#define DEFAULT_RADIUS 25 - -/** @name Spell Damage Types - * @brief Type of damage caused by spell - * @{ */ -/** @def GF_ELEC */ -#define GF_ELEC 1 - -/** @def GF_POIS */ -#define GF_POIS 2 - -/** @def GF_ACID */ -#define GF_ACID 3 - -/** @def GF_COLD */ -#define GF_COLD 4 - -/** @def GF_FIRE */ -#define GF_FIRE 5 - -/** @def GF_UNBREATH */ -#define GF_UNBREATH 6 - -/** @def GF_CORPSE_EXPL */ -#define GF_CORPSE_EXPL 7 - -/** @def GF_MISSILE */ -#define GF_MISSILE 10 - -/** @def GF_ARROW */ -#define GF_ARROW 11 - -/** @def GF_PLASMA */ -#define GF_PLASMA 12 - -/** @def GF_WAVE */ -#define GF_WAVE 13 - -/** @def GF_WATER */ -#define GF_WATER 14 - -/** @def GF_LITE */ -#define GF_LITE 15 - -/** @def GF_DARK */ -#define GF_DARK 16 - -/** @def GF_LITE_WEAK */ -#define GF_LITE_WEAK 17 - -/** @def GF_DARK_WEAK */ -#define GF_DARK_WEAK 18 - -/** @def GF_SHARDS */ -#define GF_SHARDS 20 - -/** @def GF_SOUND */ -#define GF_SOUND 21 - -/** @def GF_CONFUSION */ -#define GF_CONFUSION 22 - -/** @def GF_FORCE */ -#define GF_FORCE 23 - -/** @def GF_INERTIA */ -#define GF_INERTIA 24 - -/** @def GF_MANA */ -#define GF_MANA 26 - -/** @def GF_METEOR */ -#define GF_METEOR 27 - -/** @def GF_ICE */ -#define GF_ICE 28 - -/** @def GF_CHAOS */ -#define GF_CHAOS 30 - -/** @def GF_NETHER */ -#define GF_NETHER 31 - -/** @def GF_DISENCHANT */ -#define GF_DISENCHANT 32 - -/** @def GF_NEXUS */ -#define GF_NEXUS 33 - -/** @def GF_TIME */ -#define GF_TIME 34 - -/** @def GF_GRAVITY */ -#define GF_GRAVITY 35 - -/** @def GF_KILL_WALL */ -#define GF_KILL_WALL 40 - -/** @def GF_KILL_DOOR */ -#define GF_KILL_DOOR 41 - -/** @def GF_KILL_TRAP */ -#define GF_KILL_TRAP 42 - -/** @def GF_MAKE_WALL */ -#define GF_MAKE_WALL 45 - -/** @def GF_MAKE_DOOR */ -#define GF_MAKE_DOOR 46 - -/** @def GF_MAKE_TRAP */ -#define GF_MAKE_TRAP 47 - -/** @def GF_OLD_CLONE */ -#define GF_OLD_CLONE 51 - -/** @def GF_OLD_POLY */ -#define GF_OLD_POLY 52 - -/** @def GF_OLD_HEAL */ -#define GF_OLD_HEAL 53 - -/** @def GF_OLD_SPEED */ -#define GF_OLD_SPEED 54 - -/** @def GF_OLD_SLOW */ -#define GF_OLD_SLOW 55 - -/** @def GF_OLD_CONF */ -#define GF_OLD_CONF 56 - -/** @def GF_OLD_SLEEP */ -#define GF_OLD_SLEEP 57 - -/** @def GF_OLD_DRAIN */ -#define GF_OLD_DRAIN 58 - -/** @def GF_AWAY_UNDEAD */ -#define GF_AWAY_UNDEAD 61 - -/** @def GF_AWAY_EVIL */ -#define GF_AWAY_EVIL 62 - -/** @def GF_AWAY_ALL */ -#define GF_AWAY_ALL 63 - -/** @def GF_TURN_UNDEAD */ -#define GF_TURN_UNDEAD 64 - -/** @def GF_TURN_EVIL */ -#define GF_TURN_EVIL 65 - -/** @def GF_TURN_ALL */ -#define GF_TURN_ALL 66 - -/** @def GF_DISP_UNDEAD */ -#define GF_DISP_UNDEAD 67 - -/** @def GF_DISP_EVIL */ -#define GF_DISP_EVIL 68 - -/** @def GF_DISP_ALL */ -#define GF_DISP_ALL 69 - -/* New types for Zangband begin here... */ - -/** @def GF_DISP_DEMON */ -#define GF_DISP_DEMON 70 - -/** @def GF_DISP_LIVING */ -#define GF_DISP_LIVING 71 - -/** @def GF_ROCKET */ -#define GF_ROCKET 72 - -/** @def GF_NUKE */ -#define GF_NUKE 73 - -/** @def GF_MAKE_GLYPH */ -#define GF_MAKE_GLYPH 74 - -/** @def GF_STASIS */ -#define GF_STASIS 75 - -/** @def GF_STONE_WALL */ -#define GF_STONE_WALL 76 - -/** @def GF_DEATH_RAY */ -#define GF_DEATH_RAY 77 - -/** @def GF_STUN */ -#define GF_STUN 78 - -/** @def GF_HOLY_FIRE */ -#define GF_HOLY_FIRE 79 - -/** @def GF_HELL_FIRE */ -#define GF_HELL_FIRE 80 - -/** @def GF_DISINTEGRATE */ -#define GF_DISINTEGRATE 81 - -/** @def GF_CHARM */ -#define GF_CHARM 82 - -/** @def GF_CONTROL_UNDEAD */ -#define GF_CONTROL_UNDEAD 83 - -/** @def GF_CONTROL_ANIMAL */ -#define GF_CONTROL_ANIMAL 84 - -/** @def GF_PSI */ -#define GF_PSI 85 - -/** @def GF_PSI_DRAIN */ -#define GF_PSI_DRAIN 86 - -/** @def GF_TELEKINESIS */ -#define GF_TELEKINESIS 87 - -/** @def GF_JAM_DOOR */ -#define GF_JAM_DOOR 88 - -/** @def GF_DOMINATION */ -#define GF_DOMINATION 89 - -/** @def GF_DISP_GOOD */ -#define GF_DISP_GOOD 90 - -/** @def GF_IDENTIFY */ -#define GF_IDENTIFY 91 - -/** @def GF_RAISE */ -#define GF_RAISE 92 - -/** @def GF_STAR_IDENTIFY */ -#define GF_STAR_IDENTIFY 93 - -/** @def GF_DESTRUCTION */ -#define GF_DESTRUCTION 94 - -/** @def GF_STUN_CONF */ -#define GF_STUN_CONF 95 - -/** @def GF_STUN_DAM */ -#define GF_STUN_DAM 96 - -/** @def GF_CONF_DAM */ -#define GF_CONF_DAM 98 - -/** @def GF_STAR_CHARM */ -#define GF_STAR_CHARM 99 - -/** @def GF_IMPLOSION */ -#define GF_IMPLOSION 100 - -/** @def GF_LAVA_FLOW */ -#define GF_LAVA_FLOW 101 - -/** @def GF_FEAR */ -#define GF_FEAR 102 - -/** @def GF_BETWEEN_GATE */ -#define GF_BETWEEN_GATE 103 - -/** @def GF_WINDS_MANA */ -#define GF_WINDS_MANA 104 - -/** @def GF_DEATH */ -#define GF_DEATH 105 - -/** @def GF_CONTROL_DEMON */ -#define GF_CONTROL_DEMON 106 - -/** @def GF_RAISE_DEMON */ -#define GF_RAISE_DEMON 107 - -/** @def GF_TRAP_DEMONSOUL */ -#define GF_TRAP_DEMONSOUL 108 - -/** @def GF_ATTACK */ -#define GF_ATTACK 109 - -/** @def GF_CHARM_UNMOVING */ -#define GF_CHARM_UNMOVING 110 - -/** @def GF_INSTA_DEATH */ -#define GF_INSTA_DEATH 111 - -/** @def GF_ELEMENTAL_WALL */ -#define GF_ELEMENTAL_WALL 112 - -/** @def GF_ELEMENTAL_GROWTH */ -#define GF_ELEMENTAL_GROWTH 113 - -/** @def MAX_GF */ -#define MAX_GF 114 -/** @} */ - -/** @name Spell Projection Flags - * @brief Area affected by spell - * @{ */ -/** @def PROJECT_JUMP - * @note Jump directly to the target location (this is a hack) - */ -#define PROJECT_JUMP 0x00000001 - -/** @def PROJECT_BEAM - * @note Work as a beam weapon (affect every grid passed through) - */ -#define PROJECT_BEAM 0x00000002 - -/** @def PROJECT_THRU - * @note Continue "through" the target (used for "bolts"/"beams") - */ -#define PROJECT_THRU 0x00000004 - -/** @def PROJECT_STOP - * @note Stop as soon as we hit a monster (used for "bolts") - */ -#define PROJECT_STOP 0x00000008 - -/** @def PROJECT_GRID - * @note Affect each grid in the "blast area" in some way - */ -#define PROJECT_GRID 0x00000010 - -/** @def PROJECT_ITEM - * @note Affect each object in the "blast area" in some way - */ -#define PROJECT_ITEM 0x00000020 - -/** @def PROJECT_KILL - * @note Affect each monster in the "blast area" in some way - */ -#define PROJECT_KILL 0x00000040 - -/** @def PROJECT_HIDE - * @note Hack -- disable "visual" feedback from projection - */ -#define PROJECT_HIDE 0x00000080 - -/** @def PROJECT_VIEWABLE - * @note Affect monsters in LOS - */ -#define PROJECT_VIEWABLE 0x00000100 - -/** @def PROJECT_METEOR_SHOWER - * @note Affect random grids - */ -#define PROJECT_METEOR_SHOWER 0x00000200 - -/** @def PROJECT_BLAST - * @note Like Mega_blast, but will only affect viewable grids - */ -#define PROJECT_BLAST 0x00000400 - -/** @def PROJECT_PANEL - * @note Affect everything in the panel. - */ -#define PROJECT_PANEL 0x00000800 - -/** @def PROJECT_ALL - * @note Affect every single grid. - */ -#define PROJECT_ALL 0x00001000 - -/** @def PROJECT_WALL - * @note Continue "through" the walls - */ -#define PROJECT_WALL 0x00002000 - -/** @def PROJECT_MANA_PATH - * @note Follow a mana path. - */ -#define PROJECT_MANA_PATH 0x00004000 - -/** @def PROJECT_ABSORB_MANA - * @note The spell increase in power as it absord grid's mana. - */ -#define PROJECT_ABSORB_MANA 0x00008000 - -/** @def PROJECT_STAY */ -#define PROJECT_STAY 0x00010000 -/** @} */ - -/** @var project_time - * @brief Number - * @note The length of time a spell effect exists. - */ -extern int project_time; - -/** @fn teleport_player_directed(int rad, int dir) - * @brief Teleport a player up to "rad" grids away roughly in "dir" - * direction.\n - * @param rad Number \n rad must not exceed 200. The distance teleported is - * at least a quarter of rad. - * @brief Distance - * @param dir Number \n dir must be a value from 0 to 9. - * @brief Direction - * @note - * Teleport player, using a distance and a direction as a rough guide.\n\n - * This function is not at all obsessive about correctness.\n - * This function allows teleporting into vaults (!) - * @note (see file spells1.c) - */ -extern void teleport_player_directed(int rad, int dir); - -/** @fn teleport_away(int m_idx, int dis) - * @brief Teleport monster indicated by "m_idx" up to "dis" grids away.\n - * @param m_idx Number \n m_idx is the index of the monster in m_list[]. - * @brief Monster index - * @param dis Number \n dis must not exceed 200. The distance teleported - * is a minimum of a quarter of "dis". - * @brief Distance - * @note - * Teleport a monster, normally up to "dis" grids away.\n\n - * Attempt to move the monster at least "dis/2" grids away.\n\n - * But allow variation to prevent infinite loops. - * @note (see file spells1.c) - */ -extern void teleport_away(int m_idx, int dis); - -/** @fn teleport_player(int dis) - * @brief Teleport player up to "dis" grids away.\n - * @param dis Number \n dis must not exceed 200. The distance teleported - * is a minimum of a quarter of dis. - * @brief Distance - * @note - * Teleport the player to a location up to "dis" grids away.\n\n - * If no such spaces are readily available, the distance may increase.\n - * Try very hard to move the player at least a quarter that distance. - * @note (see file spells1.c) - */ -extern void teleport_player(int dis); - -/** @fn teleport_monster_to(int m_idx, int ny, int nx) - * @brief Teleport monster indicated by "m_idx" to a grid near coordinate - * ("ny", "nx").\n - * @param m_idx Number \n m_idx is the index of the monster in m_list[]. - * @brief Monster index - * @param ny Number \n ny is the y co-ordinate of the location. - * @brief Y coordinate - * @param nx Number \n nx is the x co-ordinate of the location. - * @brief X coordinate - * @note - * Teleport a monster to a grid near the given location\n\n - * This function is slightly obsessive about correctness.\n\n - * If the location is empty, the monster goes there, otherwise they go to - * a grid as close as possible to the location. - * @note (see file spells1.c) - */ -extern void teleport_monster_to(int m_idx, int ny, int nx); - -/** @fn teleport_monster(int dir) - * @brief Teleport away all monsters in direction "dir".\n - * @param dir Number \n dir must be a value from 0 to 9. - * @brief Direction - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * All monsters in direction "dir" are teleported away and sustain - * MAX_SIGHT (20) x 5 damage.\n\n - * If direction is 5 and a target has been selected, then the target is used. - * Otherwise, a target is calculated based on a distance of 999 grids away - * from the player in direction "dir". - * @note (see file spells2.c) - */ -extern bool teleport_monster(int dir); - -/** @fn teleport_player_level(void) - * @brief Teleport the player one level up or down at random. - * @note - * Teleport the player one level up or down (random when legal) - * @note (see file spells1.c) - */ -extern void teleport_player_level(void); - -/** @fn fetch(int dir, int wgt, bool require_los) - * @brief Fetch an item in direction "dir" with weight "wgt" possibly not in - * line of sight.\n - * @param dir Number \n dir must be a value from 0 to 9. - * @brief Direction - * @param wgt Number \n maximum weight of object. - * @brief Weight - * @param require_los Boolean \n TRUE if line of sight is required, otherwise - * FALSE. - * @brief Require-line-of-sight flag - * @note - * Fetch an item (teleport it right underneath the caster)\n\n - * If direction is 5 and a target has been selected, then the target is used. - * Otherwise, a target is calculated based on a distance of 999 grids away - * from the player in direction "dir". - * Fetch will fail if player is standing on something, or if the object is - * too far away, or if require_los is TRUE and player does not have line - * of sight to the object, or the object is too heavy. Otherwise the - * object appears at the player's feet (same grid as player). - * @note (see file cmd5.c) - */ -extern void fetch(int dir, int wgt, bool require_los); - -/** @fn recall_player(int d, int f) - * @brief Recall the player to town (if in dungeon) or dungeon (if in town).\n - * @param d Number \n Random time interval - * @brief Dice - * @param f Number \n Fixed time interval - * @brief Fixed - * @note (see file spells1.c) - */ -extern void recall_player(int d, int f); - -/** @fn take_hit(int damage, cptr kb_str) - * @brief Reduce player hit points by "damage" inflicted by "kb_str".\n - * @param damage Number \n damage is the number of hit points of damage. - * @brief Damage - * @param kb_str String \n kb_str describes what killed the player - * (in the event the player dies) - * @brief Killed by - * @note - * Decreases players hit points and sets death flag if necessary\n\n - * XXX XXX XXX Invulnerability needs to be changed into a "shield"\n\n - * XXX XXX XXX Hack -- this function allows the user to save (or quit) - * the game when he dies, since the "You die." message is shown before - * setting the player to "dead". - * @note (see file spells1.c) - */ -extern void take_hit(int damage, cptr kb_str); - -/** @fn take_sanity_hit(int damage, cptr hit_from) - * @brief Reduce player sanity points by "damage" inflicted by "hit_from".\n - * @param damage Number \n damage is the number of sanity points of damage. - * @brief Damage - * @param hit_from String \n hit_from describes what caused the damage. - * @brief Hit from - * @note - * Decrease player's sanity. This is a copy of the function above.\n\n - * Reduce the player's current sanity points by "damage" points. If the - * player dies, "hit_from" is used to record what the player was killed - * by (see high-score table). - * @note (see file spells1.c) - */ -extern void take_sanity_hit(int damage, cptr hit_from); - -/** @fn project(int who, int rad, int y, int x, int dam, int typ, int flg) - * @brief Generate a beam/bolt/ball with properties "flg" starting from "who" - * with a radius of "rad" at target grid "y,x" for "dam" points of "typ" - * damage.\n - * @param who Number \n who is > 0 (index of monster in m_list[]), < 0 and - * not -100 or -101 (player), -100 or -101 (trap). - * @brief Source - * @param rad Number \n rad is 0 for a beam/bolt and 1-9 for a ball. - * @brief Radius - * @param y Number \n y is the y coordinate of the target grid. - * @brief Y-coordinate - * @param x Number \n x is the x co-ordinate of the target grid. - * @brief X-coordinate - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @param typ Number \n typ is the type of damage (GF field). - * @brief Type - * @param flg Number \n flg is the projection effect (PROJECT field). - * @brief Properties flag - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Generic "beam"/"bolt"/"ball" projection routine.\n\n - * Input:\n - * who: Index of "source" monster (negative for "player")\n - * jk -- -2 for traps, only used with project_jump\n - * rad: Radius of explosion (0 = beam/bolt, 1 to 9 = ball)\n - * y,x: Target location (or location to travel "towards")\n - * dam: Base damage roll to apply to affected monsters (or player)\n - * typ: Type of damage to apply to monsters (and objects)\n - * flg: Extra bit flags (see PROJECT_xxxx in "defines.h")\n\n - * Return:\n - * TRUE if any "effects" of the projection were observed, else FALSE\n\n - * Allows a monster (or player) to project a beam/bolt/ball of a given kind - * towards a given location (optionally passing over the heads of interposing - * monsters), and have it do a given amount of damage to the monsters (and - * optionally objects) within the given radius of the final location.\n\n - * A "bolt" travels from source to target and affects only the target grid.\n - * A "beam" travels from source to target, affecting all grids passed through.\n - * A "ball" travels from source to the target, exploding at the target, and - * affecting everything within the given radius of the target location.\n\n - * Traditionally, a "bolt" does not affect anything on the ground, and does - * not pass over the heads of interposing monsters, much like a traditional - * missile, and will "stop" abruptly at the "target" even if no monster is - * positioned there, while a "ball", on the other hand, passes over the heads - * of monsters between the source and target, and affects everything except - * the source monster which lies within the final radius, while a "beam" - * affects every monster between the source and target, except for the casting - * monster (or player), and rarely affects things on the ground.\n\n - * Two special flags allow us to use this function in special ways, the - * "PROJECT_HIDE" flag allows us to perform "invisible" projections, while - * the "PROJECT_JUMP" flag allows us to affect a specific grid, without - * actually projecting from the source monster (or player).\n\n - * The player will only get "experience" for monsters killed by himself - * Unique monsters can only be destroyed by attacks from the player\n\n - * Only 256 grids can be affected per projection, limiting the effective - * "radius" of standard ball attacks to nine units (diameter nineteen).\n\n - * One can project in a given "direction" by combining PROJECT_THRU with small - * offsets to the initial location (see "line_spell()"), or by calculating - * "virtual targets" far away from the player.\n\n - * One can also use PROJECT_THRU to send a beam/bolt along an angled path, - * continuing until it actually hits something (useful for "stone to mud").\n\n - * Bolts and Beams explode INSIDE walls, so that they can destroy doors.\n\n - * Balls must explode BEFORE hitting walls, or they would affect monsters - * on both sides of a wall. Some bug reports indicate that this is still - * happening in 2.7.8 for Windows, though it appears to be impossible.\n\n - * We "pre-calculate" the blast area only in part for efficiency. - * More importantly, this lets us do "explosions" from the "inside" out. - * This results in a more logical distribution of "blast" treasure. - * It also produces a better (in my opinion) animation of the explosion. - * It could be (but is not) used to have the treasure dropped by monsters - * in the middle of the explosion fall "outwards", and then be damaged by - * the blast as it spreads outwards towards the treasure drop location.\n\n - * Walls and doors are included in the blast area, so that they can be - * "burned" or "melted" in later versions.\n\n - * This algorithm is intended to maximise simplicity, not necessarily - * efficiency, since this function is not a bottleneck in the code.\n\n - * We apply the blast effect from ground zero outwards, in several passes, - * first affecting features, then objects, then monsters, then the player. - * This allows walls to be removed before checking the object or monster - * in the wall, and protects objects which are dropped by monsters killed - * in the blast, and allows the player to see all affects before he is - * killed or teleported away. The semantics of this method are open to - * various interpretations, but they seem to work well in practice.\n\n - * We process the blast area from ground-zero outwards to allow for better - * distribution of treasure dropped by monsters, and because it provides a - * pleasing visual effect at low cost.\n\n - * Note that the damage done by "ball" explosions decreases with distance. - * This decrease is rapid, grids at radius "dist" take "1/dist" damage.\n\n - * Notice the "napalm" effect of "beam" weapons. First they "project" to - * the target, and then the damage "flows" along this beam of destruction. - * The damage at every grid is the same as at the "centre" of a "ball" - * explosion, since the "beam" grids are treated as if they ARE at the - * centre of a "ball" explosion.\n\n - * Currently, specifying "beam" plus "ball" means that locations which are - * covered by the initial "beam", and also covered by the final "ball", except - * for the final grid (the epicentre of the ball), will be "hit twice", once - * by the initial beam, and once by the exploding ball. For the grid right - * next to the epicentre, this results in 150% damage being done. The centre - * does not have this problem, for the same reason the final grid in a "beam" - * plus "bolt" does not -- it is explicitly removed. Simply removing "beam" - * grids which are covered by the "ball" will NOT work, as then they will - * receive LESS damage than they should. Do not combine "beam" with "ball".\n\n - * The array "gy[],gx[]" with current size "grids" is used to hold the - * collected locations of all grids in the "blast area" plus "beam path".\n\n - * Note the rather complex usage of the "gm[]" array. First, gm[0] is always - * zero. Second, for N>1, gm[N] is always the index (in gy[],gx[]) of the - * first blast grid (see above) with radius "N" from the blast centre. Note - * that only the first gm[1] grids in the blast area thus take full damage. - * Also, note that gm[rad+1] is always equal to "grids", which is the total - * number of blast grids.\n\n - * Note that once the projection is complete, (y2,x2) holds the final location - * of bolts/beams, and the "epicentre" of balls.\n\n - * Note also that "rad" specifies the "inclusive" radius of projection blast, - * so that a "rad" of "one" actually covers 5 or 9 grids, depending on the - * implementation of the "distance" function. Also, a bolt can be properly - * viewed as a "ball" with a "rad" of "zero".\n\n - * Note that if no "target" is reached before the beam/bolt/ball travels the - * maximum distance allowed (MAX_RANGE), no "blast" will be induced. This - * may be relevant even for bolts, since they have a "1x1" mini-blast.\n\n - * Note that for consistency, we "pretend" that the bolt actually takes "time" - * to move from point A to point B, even if the player cannot see part of the - * projection path. Note that in general, the player will *always* see part - * of the path, since it either starts at the player or ends on the player.\n\n - * Hack -- we assume that every "projection" is "self-illuminating".\n\n - * Hack -- when only a single monster is affected, we automatically track - * (and recall) that monster, unless "PROJECT_JUMP" is used.\n\n - * Note that all projections now "explode" at their final destination, even - * if they were being projected at a more distant destination. This means - * that "ball" spells will *always* explode.\n\n - * Note that we must call "handle_stuff()" after affecting terrain features - * in the blast radius, in case the "illumination" of the grid was changed, - * and "update_view()" and "update_monsters()" need to be called. - * @note (see file spells1.c) - */ -extern bool project(int who, int rad, int y, int x, int dam, int typ, int flg); - -/** @fn corrupt_player(void) - * @brief Swap two of the player's stats at random. - * @note (see file spells1.c) - */ -extern void corrupt_player(void); - -/** @fn grow_grass(int rad) - * @brief Grow grass within "rad" distance of the player.\n - * @param rad Number \n rad is the radius of the area where grass may grow. - * @brief Radius - * @note - * Grow grass\n\n - * Up to (rad * (rad + 11)) grass can be grown around the player. The - * grids must support growth. - * @note (see file spells2.c) - */ -extern void grow_grass(int rad); - -/** @fn grow_trees(int rad) - * @brief Grow trees within "rad" distance of the player.\n - * @param rad Number \n rad is the radius of the area where trees may grow. - * @brief Radius - * @note - * Grow trees\n\n - * Up to (rad * (rad + 11)) trees can be grown around the player. The - * grids must support growth. - * @note (see file spells2.c) - */ -extern void grow_trees(int rad); - -/** @fn hp_player(int num) - * @brief Add "num" points to the player's current hit points.\n - * @param num Number \n num is the number of points to add. - * @brief Number - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Increase players hit points, notice effects\n\n - * The total can not exceed the maximum. - * @note (see file spells2.c) - */ -extern bool hp_player(int num); - -/** @fn heal_insanity(int val) - * @brief Add "val" points to the player's current sanity points.\n - * @param val Number \n val is the number of points to add. - * @brief Value - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Heal insanity.\n\n - * The total can not exceed the maximum. - * @note (see file spells2.c) - */ -extern bool heal_insanity(int val); - -/** @fn warding_glyph(void) - * @brief Place a glyph at the player's location. - * @note - * Leave a "glyph of warding" which prevents monster movement\n\n - * The location must be bare. - * @note (see file spells2.c) - */ -extern void warding_glyph(void); - -/** @fn explosive_rune(void) - * @brief Place a minor glyph (explosive rune) at the player's location. - * @note - * The location must be bare. - * @note (see file spells2.c) - */ -extern void explosive_rune(void); - -/** @fn do_dec_stat(int stat, int mode) - * @brief Attempt to reduce the player's "stat" statistic by a point.\n - * @param stat Number \n stat is the statistic - * @brief Statistic - * @param mode Number \n mode is the type of decrease: temporary, normal, - * or permanent - * @brief Mode - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Lose a "point" - * @note (see file spells2.c) - */ -extern bool do_dec_stat(int stat, int mode); - -/** @fn do_res_stat(int stat, bool full) - * @brief Restore the player's "stat" statistic.\n - * @param stat Number \n stat is the statistic. - * @brief Statistic - * @param full Boolean \n TRUE if full restore is required, otherwise FALSE. - * @brief Full restore flag - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Restore lost "points" in a stat - * @note (see file spells2.c) - */ -extern bool do_res_stat(int stat, bool full); - -/** @fn do_inc_stat(int stat) - * @brief Increase the player's "stat" statistic by a point.\n - * @param stat Number \n stat is the statistic. - * @brief Statistic - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Gain a "point" in a stat - * @note (see file spells2.c) - */ -extern bool do_inc_stat(int stat); - -/** @fn identify_pack(void) - * @brief Identify all items in the inventory. - * @note - * Identify everything being carried.\n - * Done by a potion of "self knowledge". - * @note (see file spells2.c) - */ -extern bool identify_pack(void); - -/** @fn remove_curse(void) - * @brief Remove all curses except for heavy curses. - * @return Boolean \n TRUE if at least one item was uncursed, otherwise FALSE. - * @note - * Remove most curses\n\n - * There is a 1 in (55 - level) chance of reversing the curse effects for - * items which are not artifacts. For example, a Ring of Damage (-15) will - * become a Ring of Damage (+15). - * @note (see file spells2.c) - */ -extern bool remove_curse(void); - -/** @fn remove_all_curse(void) - * @brief Remove all curses including heavy curses. - * @return Boolean \n TRUE if at least one item was uncursed, otherwise FALSE. - * @note - * Remove all curses\n\n - * There is a 1 in (55 - level) chance of reversing the curse effects for - * items which are not artifacts. For example, a Ring of Damage (-15) will - * become a Ring of Damage (+15). - * @note (see file spells2.c) - */ -extern bool remove_all_curse(void); - -/** @fn restore_level(void) - * @brief Restore all drained experience points (if any). - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Restores any drained experience - * @note (see file spells2.c) - */ -extern bool restore_level(void); - -/** @fn self_knowledge(FILE *fff=NULL) - * @brief Show all attributes including racial powers, mutations, and - * equipment effects.\n - * @param *fff FILE \n write info to screen if fff is NULL, - * otherwise write info to file fff. - * @brief Output file - * @note - * self-knowledge... idea from nethack. Useful for determining powers and - * resistances of items. It saves the screen, clears it, then starts listing - * attributes, a screenful at a time. (There are a LOT of attributes to - * list. It will probably take 2 or 3 screens for a powerful character whose - * using several artifacts...) -CFT\n\n - * It is now a lot more efficient. -BEN-\n\n - * See also "identify_fully()".\n\n - * XXX XXX XXX Use the "show_file()" method, perhaps. - * @note (see file spells2.c) - */ -extern void self_knowledge(FILE *fff=NULL); - -/** @fn lose_all_info(void) - * @brief Forget about objects and the map. - * @return Boolean \n TRUE (always). - * @note - * Forget everything - * @note (see file spells2.c) - */ -extern bool lose_all_info(void); - -/** @fn detect_traps(int rad) - * @brief Detect all traps within radius "rad" of the player.\n - * @param rad Number \n rad is the radius of circle of detection. - * @brief Radius - * @return Boolean \n TRUE (always). - * @note - * All grids within the radius are searched.\n - * A message is displayed if traps are detected. - * @note (see file spells2.c) - */ -extern bool detect_traps(int rad); - -/** @fn detect_doors(int rad) - * @brief Detect all doors within radius "rad" of the player.\n - * @param rad Number \n rad is the radius of circle of detection. - * @brief Radius - * @return Boolean \n TRUE if doors were detected, otherwise FALSE. - * @note - * All grids within the radius are searched.\n - * A message is displayed if doors are detected. - * @note (see file spells2.c) - */ -extern bool detect_doors(int rad); - -/** @fn detect_stairs(int rad) - * @brief Detect all exits within radius "rad" of the player.\n - * @param rad Number \n rad is the radius of circle of detection. - * @brief Radius - * @return Boolean \n TRUE if exits were detected, otherwise FALSE. - * @note - * All grids within the radius are searched.\n - * A message is displayed if exits are detected. Exits can be stairs, - * shafts, and ways out. - * @note (see file spells2.c) - */ -extern bool detect_stairs(int rad); - -/** @fn detect_treasure(int rad) - * @brief Detect all buried treasure within radius "rad" of the player.\n - * @param rad Number \n rad is the radius of circle of detection. - * @brief Radius - * @return Boolean \n TRUE if buried treasure was detected, otherwise FALSE. - * @note - * All grids within the radius are searched.\n - * A message is displayed if buried treasure is detected. Treasure can be - * buried in magma, quartz, or sandwall. - * @note (see file spells2.c) - */ -extern bool detect_treasure(int rad); - -/** @var hack_no_detect_message - * @brief Boolean - * @note Suppress messages generated by "detect" spells? - */ -extern bool hack_no_detect_message; - -/** @fn detect_objects_gold(int rad) - * @brief Detect all gold within radius "rad" of the player.\n - * @param rad Number \n rad is the radius of circle of detection. - * @brief Radius - * @return Boolean \n TRUE if gold was detected, otherwise FALSE. - * @note - * All grids within the radius are searched.\n - * A message is displayed if gold is detected. Gold can be coins or mimics. - * Monsters of type "$" are detected but not shown or reported. - * @note (see file spells2.c) - */ -extern bool detect_objects_gold(int rad); - -/** @fn detect_objects_normal(int rad) - * @brief Detect all normal (not gold) items within radius "rad" of the player.\n - * @param rad Number \n rad is the radius of circle of detection. - * @brief Radius - * @return Boolean \n TRUE if normal items were detected, otherwise FALSE. - * @note - * All grids within the radius are searched.\n - * A message is displayed if normal items are detected. Items include mimics. - * Monsters of type "!=?|" are detected but not shown or reported. - * @note (see file spells2.c) - */ -extern bool detect_objects_normal(int rad); - -/** @fn detect_objects_magic(int rad) - * @brief Detect all magic (not gold) items within radius "rad" of the player.\n - * @param rad Number \n rad is the radius of circle of detection. - * @brief Radius - * @return Boolean \n TRUE if magic items were detected, otherwise FALSE. - * @note - * This will light up all spaces with "magic" items, including artifacts, - * ego-items, potions, scrolls, books, rods, wands, staves, amulets, rings, - * and "enchanted" items of the "good" variety.\n\n - * It can probably be argued that this function is now too powerful.\n\n - * All grids within the radius are searched.\n - * A message is displayed if magic items are detected. Items include mimics. - * @note (see file spells2.c) - */ -extern bool detect_objects_magic(int rad); - -/** @fn detect_monsters_normal(int rad) - * @brief Detect all non-invisible monsters within radius "rad" of the player.\n - * @param rad Number \n rad is the radius of circle of detection. - * @brief Radius - * @return Boolean \n TRUE if non-invisible monsters were detected, - * otherwise FALSE. - * @note - * A non-invisible monster is one which is visible, or one which is invisible - * but the player can see invisible monsters. - * @note (see file spells2.c) - */ -extern bool detect_monsters_normal(int rad); - -/** @fn detect_monsters_invis(int rad) - * @brief Detect all invisible monsters within radius "rad" of the player.\n - * @param rad Number \n rad is the radius of circle of detection. - * @brief Radius - * @return Boolean \n TRUE if invisible monsters were detected, - * otherwise FALSE. - * @note (see file spells2.c) - */ -extern bool detect_monsters_invis(int rad); - -/** @fn detect_monsters_evil(int rad) - * @brief Detect all evil monsters within radius "rad" of the player.\n - * @param rad Number \n rad is the radius of circle of detection. - * @brief Radius - * @return Boolean \n TRUE if evil monsters were detected, otherwise FALSE. - * @note (see file spells2.c) - */ -extern bool detect_monsters_evil(int rad); - -/** @fn detect_monsters_good(int rad) - * @brief Detect all good monsters within radius "rad" of the player.\n - * @param rad Number \n rad is the radius of circle of detection. - * @brief Radius - * @return Boolean \n TRUE if good monsters were detected, otherwise FALSE. - * @note (see file spells2.c) - */ -extern bool detect_monsters_good(int rad); - -/** @fn detect_monsters_xxx(u32b match_flag, int rad) - * @brief Detect all monsters with flag "match_flag" within radius "rad" of the - * player.\n - * @param match_flag Number \n match_flag is the type of monster. It must be - * a RF3_ flag (see defines.h). - * @brief Match flag - * @param rad Number \n rad is the radius of circle of detection. - * @brief Radius - * @return Boolean \n TRUE if monsters were detected, otherwise FALSE. - * @note - * A "generic" detect monsters routine, tagged to flags3\n\n - * This routine will work with ANY RF3 flag, but messages will only be - * printed if the following monsters are detected: demon, undead, good. - * @note (see file spells2.c) - */ -extern bool detect_monsters_xxx(u32b match_flag, int rad); - -/** @fn detect_monsters_string(cptr chars, int rad) - * @brief Detect all monsters whose monster symbol is in "chars" within - * radius "rad" of the player.\n - * @param chars String \n chars is the string of monster types. For - * available characters, see the "symbol" field of the graphics (G) - * line of r_info.txt. - * @brief Symbols - * @param rad Number \n rad is the radius of circle of detection. - * @brief Radius - * @return Boolean \n TRUE if monsters were detected, otherwise FALSE. - * @note (see file spells2.c) - */ -extern bool detect_monsters_string(cptr chars, int rad); - -/** @fn detect_monsters_nonliving(int rad) - * @brief Detect all nonliving monsters within radius "rad" of the player.\n - * @param rad Number \n rad is the radius of circle of detection. - * @brief Radius - * @return Boolean \n TRUE if nonliving monsters were detected, - * otherwise FALSE. - * @note - * Detect all "nonliving", "undead" or "demonic" monsters on current panel\n\n - * Nonliving monsters are either RF3_NONLIVING, RF3_UNDEAD, or RF3_DEMON. - * @note (see file spells2.c) - */ -extern bool detect_monsters_nonliving(int rad); - -/** @fn detect_all(int rad) - * @brief Detect everything within radius "rad" of the player.\n - * @param rad Number \n rad is the radius of circle of detection. - * @brief Radius - * @return Boolean \n TRUE if something was detected, otherwise FALSE. - * @note - * Detect everything\n\n - * Detects traps, doors, stairs, treasure, gold objects, normal objects, - * invisible monsters, non-invisible monsters. - */ -extern bool detect_all(int rad); - -/** @fn stair_creation(void) - * @brief Create stairs at the player location - * @note - * This is not allowed if the grid is not empty, the player is not in a - * dungeon, the player is on a special level, the player is in an arena - * or quest. If the player is in the town or wilderness the stairs will - * go down. If the player is on a quest level or at the bottom of a - * dungeon, the stairs will go up. Otherwise there is an even chance the - * stairs will go up or down. - */ -extern void stair_creation(void); - -/** @fn tgt_pt (int *x=0, int *y=0) - * @brief Set a target point\n - * @param *x Number - * @brief X-coordinate - * @param *y Number - * @brief Y-coordinate - * @return *x Number \n X-coordinate of target. - * @return *y Number \n Y-coordinate of target. - * @return Boolean \n True if a target was selected, otherwise FALSE. - * @note - * Allow the user to move the cursor around the screen to select a target. - * The user must press the space key to set the target. - * @note (see file xtra2.c) - */ -extern bool tgt_pt (int *x=0, int *y=0); - -/** @fn wall_stone(int y, int x) - * @brief Create a stone wall at dungeon grid ("y", "x").\n - * @param y Number \n Y-coordinate of dungeon grid. - * @brief Y-coordinate - * @param x Number \n X-coordinate of dungeon grid. - * @brief X-coordinate - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note (see file spells2.c) - */ -extern bool wall_stone(int y, int x); - -/** @fn create_artifact(object_type *o_ptr, bool a_scroll, bool get_name) - * @brief Create an artifact from object "o_ptr".\n - * @param *o_ptr object_type \n object to become an artifact - * @brief Object - * @param a_scroll Boolean \n Is a scroll used to create the artifact?\n - * TRUE if the artifact is created by reading a scroll. - * @brief Use scroll? - * @param get_name Boolean \n Get a name for the artifact?\n - * TRUE if the artifact is to be named by the player (if a_scroll is true) or - * created randomly (a_scroll is false), or FALSE if an inscription is used. - * @brief Get name? - * @return *o_ptr object_type \n The artifact. - * @return Boolean \n TRUE (always). - * @note (see file randart.c) - */ -extern bool create_artifact(object_type *o_ptr, bool a_scroll, bool get_name); - -/** @fn wall_to_mud(int dir) - * @brief Cast a wall-to-mud spell in direction "dir".\n - * @param dir Number \n dir must be a value from 0 to 9. - * @brief Direction - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * If direction is 5 and a target has been selected, then the target is used. - * Otherwise, a target is calculated based on a distance of 999 grids away - * from the player in direction "dir". - * @note (see file spells2.c) - */ -extern bool wall_to_mud(int dir); - -/** @fn ident_spell(void) - * @brief Identify an object in the inventory (or on the floor). - * @return Boolean \n TRUE if object is identified, otherwise FALSE. - * @note - * Identify an object in the inventory (or on the floor). - * This routine does *not* automatically combine objects. - * @note (see file spells2.c) - */ -extern bool ident_spell(void); - -/** @fn identify_fully(void) - * @brief Fully "identify" an object in the inventory (or on the floor). - * @return Boolean \n TRUE if object is identified, otherwise FALSE. - * @note - * Fully "identify" an object in the inventory -BEN- - * @note (see file spells2.c) - */ -extern bool identify_fully(void); - -/** @fn recharge(int num) - * @brief Recharge an object in the inventory (or on the floor) with "num" - * power.\n - * @param num Number \n num is the power used in recharging. It is compared - * to the object's level to determine whether the item is recharged - * successfully or destroyed. If it is recharged, it also determines - * how many charges are added, or how much recharge time is reduced. - * @brief Power - * @return Boolean \n TRUE if something was recharged, otherwise FALSE. - * @note - * Recharge a wand/staff/rod from the pack or on the floor.\n - * This function has been rewritten in Oangband. -LM-\n\n - * Mage -- Recharge I --> recharge(90)\n - * Mage -- Recharge II --> recharge(150)\n - * Mage -- Recharge III --> recharge(220)\n\n - * Priest or Necromancer -- Recharge --> recharge(140)\n - * Scroll of recharging --> recharge(130)\n - * Scroll of *recharging* --> recharge(200)\n\n - * It is harder to recharge high level, and highly charged wands, - * staffs, and rods. The more wands in a stack, the more easily and - * strongly they recharge. Staffs, however, each get fewer charges if - * stacked.\n\n - * XXX XXX XXX Beware of "sliding index errors". - * @note (see file spells2.c) - */ -extern bool recharge(int num); - -/** @fn aggravate_monsters(int who) - * @brief Aggravate monsters, originating from "who".\n - * @param who Number \n who is the index of monster in m_list[] - * (1 if it is the player) which triggers the aggravation. - * @brief Source - * @note - * Wake up all monsters, and speed up "los" monsters. - * @note (see file spells2.c) - */ -extern void aggravate_monsters(int who); - -/** @fn genocide_aux(bool player_cast, char typ) - * @brief Genocide a monster race.\n - * @param player_cast Boolean \n player_cast is true if the player cast the - * spell so the player can take damage. - * @param typ Char \n typ is the letetr of the genocided monsters - * @return Boolean \n TRUE if genocide was cast, otherwise FALSE. - * @note - * Genocide will not work on DF2_NO_GENO dungeon levels, or on "fated to - * die" levels. - * The player gets 4 points of damage per monster genocided. - * @note (see file spells2.c) - */ -extern bool genocide_aux(bool player_cast, char typ); - -/** @fn genocide(bool player_cast) - * @brief Genocide a monster race.\n - * @param player_cast Boolean \n player_cast is true if the player cast the - * spell so the player can take damage. - * @brief Player cast spell? - * @return Boolean \n TRUE if genocide was cast, otherwise FALSE. - * @note - * Genocide will not work on DF2_NO_GENO dungeon levels, or on "fated to - * die" levels. - * The player gets 4 points of damage per monster genocided. - * @note (see file spells2.c) - */ -extern bool genocide(bool player_cast); - -/** @fn mass_genocide(bool player_cast) - * @brief Delete all nearby (non-unique) monsters.\n - * @param player_cast Boolean \n player_cast is true if the player cast the - * spell so the player can take damage. - * @brief Player cast spell? - * @return Boolean \n TRUE (always). - * @note - * Genocide will not work on DF2_NO_GENO dungeon levels, or on "fated to - * die" levels.\n - * The player gets 3 points of damage per monster genocided. - * @note (see file spells2.c) - */ -extern bool mass_genocide(bool player_cast); - -/** @fn probing(void) - * @brief Probe all nearby monsters. - * @return Boolean \n TRUE if probe was successful, otherwise FALSE. - * @note (see file spells2.c) - */ -extern bool probing(void); - -/** @fn banish_evil(int dist) - * @brief Banish nearby evil monsters doing "dist" points of GF_AWAY_EVIL - * damage.\n - * @param dist Number \n dist is the number of hit points of damage. - * @brief Damage - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note (see file spells2.c) - */ -extern bool banish_evil(int dist); - -/** @fn dispel_evil(int dam) - * @brief Dispel nearby evil monsters doing "dam" points of GF_DISP_EVIL - * damage.\n - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note (see file spells2.c) - */ -extern bool dispel_evil(int dam); - -/** @fn dispel_good(int dam) - * @brief Dispel nearby good monsters doing "dam" points of GF_DISP_GOOD - * damage.\n - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note (see file spells2.c) - */ -extern bool dispel_good(int dam); - -/** @fn dispel_undead(int dam) - * @brief Dispel nearby undead monsters doing "dam" points of GF_DISP_UNDEAD - * damage.\n - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note (see file spells2.c) - */ -extern bool dispel_undead(int dam); - -/** @fn dispel_monsters(int dam) - * @brief Dispel all nearby monsters doing "dam" points of GF_DISP_ALL - * damage.\n - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note (see file spells2.c) - */ -extern bool dispel_monsters(int dam); - -/** @fn dispel_living(int dam) - * @brief Dispel nearby living monsters doing "dam" points of GF_DISP_LIVING - * damage.\n - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note (see file spells2.c) - */ -extern bool dispel_living(int dam); - -/** @fn dispel_demons(int dam) - * @brief Dispel nearby demon monsters doing "dam" points of GF_DISP_DEMON - * damage.\n - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note (see file spells2.c) - */ -extern bool dispel_demons(int dam); - -/** @fn turn_undead(void) - * @brief Turn nearby undead monsters doing a point of GF_TURN_UNDEAD damage - * for each player level. - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note (see file spells2.c) - */ -extern bool turn_undead(void); - -/** @fn door_creation(void) - * @brief Create doors in all grids adjacent to the player. - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note (see file spells2.c) - */ -extern bool door_creation(void); - -/** @fn trap_creation(void) - * @brief Create traps in all grids adjacent to the player. - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note (see file spells2.c) - */ -extern bool trap_creation(void); - -/** @fn glyph_creation(void) - * @brief Create glyphs in all grids adjacent to the player. - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note (see file spells2.c) - */ -extern bool glyph_creation(void); - -/** @fn wipe(int y1, int x1, int r) - * @brief Delete monsters and objects from an area of the dungeon centred at - * grid "y1,x1" for a radius "r".\n - * @param y1 Number \n Y-coordinate of dungeon grid. - * @brief Y-coordinate - * @param x1 Number \n X-coordinate of dungeon grid. - * @brief X-coordinate - * @param r Number \n rad is the radius of circle of detection. - * @brief Radius - * @note - * Wipe -- Empties a part of the dungeon\n\n - * This does not work on special levels or quests. The player may become - * blinded. The player forgets the affected area and it becomes dark. - * All grids become floor. - * @note (see file spells2.c) - */ -extern void wipe(int y1, int x1, int r); - -/** @fn destroy_area(int y1, int x1, int r, bool full, bool bypass) - * @brief Delete monsters and objects from an area of the dungeon centred at - * grid "y1,x1" for a radius "r".\n - * @param y1 Number \n Y-coordinate of dungeon grid. - * @brief Y-coordinate - * @param x1 Number \n X-coordinate of dungeon grid. - * @brief X-coordinate - * @param r Number \n rad is the radius of circle of detection. - * @brief Radius - * @param full Boolean \n unused - * @brief *Unused* - * @param bypass Boolean \n TRUE if quest levels are not destroyed, otherwise - * FALSE. - * @brief Exempt quest levels? - * @note - * The spell of destruction\n\n - * This spell "deletes" monsters (instead of "killing" them).\n\n - * Later we may use one function for both "destruction" and - * "earthquake" by using the "full" to select "destruction".\n\n - * This does not work on special levels. This does not work on quests if the - * bypass flag is set. The epicentre is NOT affected. The player may become - * blinded. The player forgets the affected area and it becomes dark. The - * grids can become granite, quartz, magma, or floor. - * @note (see file spells2.c) - */ -extern void destroy_area(int y1, int x1, int r, bool full, bool bypass); - -/** @fn earthquake(int cy, int cx, int r) - * @brief Create an earthquake centred on grid "cy,cx" with a radius of "r".\n - * @param cy Number \n Y-coordinate of dungeon grid. - * @brief Y-coordinate - * @param cx Number \n X-coordinate of dungeon grid. - * @brief X-coordinate - * @param r Number \n rad is the radius of circle of detection. - * @brief Radius - * @note - * Induce an "earthquake" of the given radius at the given location.\n\n - * This will turn some walls into floors and some floors into walls.\n\n - * The player will take damage and "jump" into a safe grid if possible, - * otherwise, he will "tunnel" through the rubble instantaneously.\n\n - * Monsters will take damage, and "jump" into a safe grid if possible, - * otherwise they will be "buried" in the rubble, disappearing from - * the level in the same way that they do when genocided.\n\n - * Note that thus the player and monsters (except eaters of walls and - * passers through walls) will never occupy the same grid as a wall. - * Note that as of now (2.7.8) no monster may occupy a "wall" grid, even - * for a single turn, unless that monster can pass_walls or kill_walls. - * This has allowed massive simplification of the "monster" code.\n\n - * This does not work on quest levels. The epicentre is NOT affected. - * Only about 15% of the grids are affected. The player takes 300 points - * of damage if they can't be moved to a safe grid, otherwise damage is - * from 10 to 40 points. The player forgets the affected area and it - * becomes dark. The grids can become granite, quartz, magma, or floor. - * @note (see file spells2.c) - */ -extern void earthquake(int cy, int cx, int r); - -/** @fn lite_room(int y1, int x1) - * @brief Lite room containing grid "y1,x1".\n - * @param y1 Number \n Y-coordinate of dungeon grid. - * @brief Y-coordinate - * @param x1 Number \n X-coordinate of dungeon grid. - * @brief X-coordinate - * @note - * Illuminate any room containing the given location. - * @note (see file spells2.c) - */ -extern void lite_room(int y1, int x1); - -/** @fn unlite_room(int y1, int x1) - * @brief Unlite room containing grid "y1,x1".\n - * @param y1 Number \n Y-coordinate of dungeon grid. - * @brief Y-coordinate - * @param x1 Number \n X-coordinate of dungeon grid. - * @brief X-coordinate - * @note - * Darken all rooms containing the given location. - * @note (see file spells2.c) - */ -extern void unlite_room(int y1, int x1); - -/** @fn lite_area(int dam, int rad) - * @brief Lite area around player of radius "rad" causing "dam" points of - * damage to monsters. - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @param rad Number \n rad is the radius of circle of lite. - * @brief Radius - * @return Boolean \n TRUE (always). - * @note - * Hack -- call light around the player\n - * Affect all monsters in the projection radius\n\n - * Generate a ball of spell type GF_LITE_WEAK.\n - * @note (see file spells2.c) - */ -extern bool lite_area(int dam, int rad); - -/** @fn unlite_area(int dam, int rad) - * @brief Unlite area around player of radius "rad" causing "dam" points of - * damage to monsters. - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @param rad Number \n rad is the radius of circle of lite. - * @brief Radius - * @return Boolean \n TRUE (always). - * @note - * Hack -- call darkness around the player\n - * Affect all monsters in the projection radius\n\n - * Generate a ball of spell type GF_DARK_WEAK.\n - * @note (see file spells2.c) - */ -extern bool unlite_area(int dam, int rad); - -/** @fn fire_ball_beam(int typ, int dir, int dam, int rad) - * @brief Generate a ball spell of type "typ" with radius "rad" aimed in - * direction "dir" for "dam" damage.\n - * @param typ Number \n typ is the type of damage (GF field). - * @brief Type - * @param dir Number \n dir must be a value from 0 to 9. - * @brief Direction - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @param rad Number \n rad is 0 for a beam/bolt and 1-16 for a ball. - * @brief Radius - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Cast a ball-beamed spell\n - * Stop if we hit a monster, act as a "ball"\n - * Allow "target" mode to pass over monsters\n - * Affect grids, objects, and monsters\n\n - * If direction is 5 and a target has been selected, then the target is used. - * Otherwise, a target is calculated based on a distance of 999 grids away - * from the player in direction "dir".\n\n - * Any radius >16 is treated as 16. - * @note (see file spells2.c) - */ -extern bool fire_ball_beam(int typ, int dir, int dam, int rad); - -/** @fn make_wish(void) - * @brief Allow the player to make a wish. - * @note (see file xtra2.c) - */ -extern void make_wish(void); - -/** @fn fire_wave(int typ, int dir, int dam, int rad, int time, s32b eff) - * @brief Generate a ball spell of type "typ" with radius "rad" and effect - * "eff" lasting "time" turns aimed in direction "dir" for "dam" damage.\n - * @param typ Number \n typ is the type of damage (GF field). - * @brief Type - * @param dir Number \n dir must be a value from 0 to 9. - * @brief Direction - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @param rad Number \n rad is 0 for a beam/bolt and 1-16 for a ball. - * @brief Radius - * @param time Number \n time is the number of turns the spell lasts. - * @brief Duration - * @param eff Number \n eff is the spell effect (EFF field) - * @brief Effect - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Cast a wave spell\n - * Stop if we hit a monster, act as a "ball"\n - * Allow "target" mode to pass over monsters\n - * Affect grids, objects, and monsters\n\n - * If direction is 5 and a target has been selected, then the target is used. - * Otherwise, a target is calculated based on a distance of 999 grids away - * from the player in direction "dir".\n\n - * Any radius >16 is treated as 16. - * @note (see file spells2.c) - */ -extern bool fire_wave(int typ, int dir, int dam, int rad, int time, s32b eff); - -/** @name Spell Effect Flags - * @brief Effect of spell - * @{ */ -/** @def EFF_WAVE - * @note A circle whose radius increase - */ -#define EFF_WAVE 0x00000001 - -/** @def EFF_LAST - * @note The wave lasts - */ -#define EFF_LAST 0x00000002 - -/** @def EFF_STORM - * @note the effect follows the player - */ -#define EFF_STORM 0x00000004 - -/** @name Spell Effect Direction Flags - * @brief Direction of the spell - * @{ */ -#define EFF_DIR1 0x00000008 /* Directed effect */ -#define EFF_DIR2 0x00000010 /* Directed effect */ -#define EFF_DIR3 0x00000020 /* Directed effect */ -#define EFF_DIR4 0x00000040 /* Directed effect */ -#define EFF_DIR6 0x00000080 /* Directed effect */ -#define EFF_DIR7 0x00000100 /* Directed effect */ -#define EFF_DIR8 0x00000200 /* Directed effect */ -#define EFF_DIR9 0x00000400 /* Directed effect */ -/** @} */ -/** @} */ - -/** @fn fire_cloud(int typ, int dir, int dam, int rad, int time) - * @brief Generate a ball spell of type "typ" with radius "rad" lasting - * "time" turns aimed in direction "dir" for "dam" damage.\n - * @param typ Number \n typ is the type of damage (GF field). - * @brief Type - * @param dir Number \n dir must be a value from 0 to 9. - * @brief Direction - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @param rad Number \n rad is 0 for a beam/bolt and 1-16 for a ball. - * @brief Radius - * @param time Number \n time is the number of turns the spell lasts. - * @brief Duration - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Cast a cloud spell\n - * Stop if we hit a monster, act as a "ball"\n - * Allow "target" mode to pass over monsters\n - * Affect grids, objects, and monsters\n\n - * If direction is 5 and a target has been selected, then the target is used. - * Otherwise, a target is calculated based on a distance of 999 grids away - * from the player in direction "dir".\n\n - * Any radius >16 is treated as 16. - * @note (see file spells2.c) - */ -extern bool fire_cloud(int typ, int dir, int dam, int rad, int time); - -/** @fn fire_wall(int typ, int dir, int dam, int time) - * @brief Generate a beam spell of type "typ" lasting "time" turns aimed in - * direction "dir" for "dam" damage.\n - * @param typ Number \n typ is the type of damage (GF field). - * @brief Type - * @param dir Number \n dir must be a value from 0 to 9. - * @brief Direction - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @param time Number \n time is the number of turns the spell lasts. - * @brief Duration - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Cast a persistant beam spell\n - * Pass through monsters, as a "beam"\n - * Affect monsters (not grids or objects)\n\n - * If direction is 5 and a target has been selected, then the target is used. - * Otherwise, a target is calculated based on a distance of 999 grids away - * from the player in direction "dir". - * @note (see file spells2.c) - */ -extern bool fire_wall(int typ, int dir, int dam, int time); - -/** @fn fire_ball(int typ, int dir, int dam, int rad) - * @brief Generate a ball spell of type "typ" with radius "rad" aimed in - * direction "dir" for "dam" damage.\n - * @param typ Number \n typ is the type of damage (GF field). - * @brief Type - * @param dir Number \n dir must be a value from 0 to 9. - * @brief Direction - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @param rad Number \n rad is 0 for a beam/bolt and 1-16 for a ball. - * @brief Radius - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Cast a ball spell\n - * Stop if we hit a monster, act as a "ball"\n - * Allow "target" mode to pass over monsters\n - * Affect grids, objects, and monsters\n\n - * If direction is 5 and a target has been selected, then the target is used. - * Otherwise, a target is calculated based on a distance of 999 grids away - * from the player in direction "dir". - * @note (see file spells2.c) - */ -extern bool fire_ball(int typ, int dir, int dam, int rad); - -/** @fn fire_bolt(int typ, int dir, int dam) - * @brief Generate a bolt spell of type "typ" aimed in direction "dir" - * for "dam" damage.\n - * @param typ Number \n typ is the type of damage (GF field). - * @brief Type - * @param dir Number \n dir must be a value from 0 to 9. - * @brief Direction - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Cast a bolt spell\n - * Stop if we hit a monster, as a "bolt"\n - * Affect monsters (not grids or objects)\n\n - * If direction is 5 and a target has been selected, then the target is used. - * Otherwise, a target is calculated based on a distance of 999 grids away - * from the player in direction "dir". - * @note (see file spells2.c) - */ -extern bool fire_bolt(int typ, int dir, int dam); - -/** @fn fire_beam(int typ, int dir, int dam) - * @brief Generate a beam spell of type "typ" aimed in direction "dir" - * for "dam" damage.\n - * @param typ Number \n typ is the type of damage (GF field). - * @brief Type - * @param dir Number \n dir must be a value from 0 to 9. - * @brief Direction - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Cast a beam spell\n - * Pass through monsters, as a "beam"\n - * Affect monsters (not grids or objects)\n\n - * If direction is 5 and a target has been selected, then the target is used. - * Otherwise, a target is calculated based on a distance of 999 grids away - * from the player in direction "dir". - * @note (see file spells2.c) - */ -extern bool fire_beam(int typ, int dir, int dam); - -/** @fn fire_druid_ball(int typ, int dir, int dam, int rad) - * @brief Generate a druid ball spell of type "typ" with radius "rad" aimed in - * direction "dir" for "dam" damage.\n - * @param typ Number \n typ is the type of damage (GF field). - * @brief Type - * @param dir Number \n dir must be a value from 0 to 9. - * @brief Direction - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @param rad Number \n rad is 0 for a beam/bolt and 1-16 for a ball. - * @brief Radius - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Cast a druidistic ball spell\n - * Stop if we hit a monster, act as a "ball"\n - * Allow "target" mode to pass over monsters\n - * Affect grids, objects, and monsters\n\n - * If direction is 5 and a target has been selected, then the target is used. - * Otherwise, a target is calculated based on a distance of 999 grids away - * from the player in direction "dir".\n\n - * The spells follows a mana path\n\n - * WARNING: This routine has been deprecated. - * @note (see file spells2.c) - */ -extern bool fire_druid_ball(int typ, int dir, int dam, int rad); - -/** @fn fire_druid_bolt(int typ, int dir, int dam) - * @brief Generate a druid bolt spell of type "typ" aimed in direction "dir" - * for "dam" damage.\n - * @param typ Number \n typ is the type of damage (GF field). - * @brief Type - * @param dir Number \n dir must be a value from 0 to 9. - * @brief Direction - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Cast a druidistic bolt spell\n - * Stop if we hit a monster, as a "bolt"\n - * Affect monsters (not grids or objects)\n\n - * If direction is 5 and a target has been selected, then the target is used. - * Otherwise, a target is calculated based on a distance of 999 grids away - * from the player in direction "dir".\n\n - * The spells follows a mana path\n\n - * WARNING: This routine has been deprecated. - * @note (see file spells2.c) - */ -extern bool fire_druid_bolt(int typ, int dir, int dam); - -/** @fn fire_druid_beam(int typ, int dir, int dam) - * @brief Generate a druid beam spell of type "typ" aimed in direction "dir" - * for "dam" damage.\n - * @param typ Number \n typ is the type of damage (GF field). - * @brief Type - * @param dir Number \n dir must be a value from 0 to 9. - * @brief Direction - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Cast a druidistic beam spell\n - * Pass through monsters, as a "beam"\n - * Affect monsters (not grids or objects)\n\n - * If direction is 5 and a target has been selected, then the target is used. - * Otherwise, a target is calculated based on a distance of 999 grids away - * from the player in direction "dir".\n\n - * The spells follows a mana path\n\n - * WARNING: This routine has been deprecated. - * @note (see file spells2.c) - */ -extern bool fire_druid_beam(int typ, int dir, int dam); - -/** @fn fire_bolt_or_beam(int prob, int typ, int dir, int dam) - * @brief Generate a bolt spell of type "typ" aimed in direction "dir" - * for "dam" damage with "prob" percent chance of a beam.\n - * @param prob Number \n prob is the percentage chance the spell will be a - * beam instead of a bolt. - * @brief Beam probability percentage - * @param typ Number \n typ is the type of damage (GF field). - * @brief Type - * @param dir Number \n dir must be a value from 0 to 9. - * @brief Direction - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Cast a bolt spell, or rarely, a beam spell\n\n - * If direction is 5 and a target has been selected, then the target is used. - * Otherwise, a target is calculated based on a distance of 999 grids away - * from the player in direction "dir".\n\n - * @note (see file spells2.c) - */ -extern bool fire_bolt_or_beam(int prob, int typ, int dir, int dam); - -/** @fn alchemy(void) - * @brief Turns an object into gold, gain some of its value in a shop - * @return Boolean \n TRUE if object turns to gold, otherwise FALSE. - * @note - * The player selects an object (and quantity if it applies) from the - * inventory or the floor and attempts to turn it into gold. If the - * price of the item is < 0 then the player gains nothing (fool's gold), - * otherwise the player gets a third of the price in gold. Artifacts are - * not affected. - * @note (see file spells2.c) - */ -extern bool alchemy(void); - -/** @fn alter_reality(void) - * @brief The player leaves the level immediately. - * @note (see file spells2.c) - */ -extern void alter_reality(void); - -/** @fn swap_position(int lty, int ltx) - * @brief Swap the position of the player with whatever is in grid "lty,ltx".\n - * @param lty Number \n Y-coordinate of target location. - * @brief Y-coordinate - * @param ltx Number \n X-coordinate of target location. - * @brief X-coordinate - * @note - * Player moves to target location. If there is a monster at the target - * location, it is moved to the player location. This is not allowed if - * the space-time continuum can not be disrupted. - * @note (see file spells2.c) - */ -extern void swap_position(int lty, int ltx); - -/** @fn teleport_swap(int dir) - * @brief Player swaps places with target in direction "dir".\n - * @param dir Number \n dir must be a value from 0 to 9. - * @brief Direction - * @note - * If direction is 5 and a target has been selected, then the target is used. - * Otherwise, the target is the grid adjacent to the player in direction - * "dir".\n\n - * The target must be a monster. It will not work if the space-time continuum - * can not be disrupted or if the monster resists teleportation. - * @note (see file spells2.c) - */ -extern void teleport_swap(int dir); - -/** @fn project_meteor(int radius, int typ, int dam, u32b flg) - * @brief Generate from "radius" to ("radius" x2) ball spells with properties - * "flg" of type "typ" for "dam" damage.\n - * @param radius Number \n rad is the minimum number of balls created. - * rad + randint("rad") balls are created. - * @brief Balls - * @param typ Number \n typ is the type of damage (GF field). - * @brief Type - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @param flg Number \n flg is the projection effect (PROJECT field). - * @brief Properties flag - * @note - * Apply a "project()" a la meteor shower\n\n - * Each ball has a radius of 2 grids. Each target grid is within 5 grids of - * the player. - * @note (see file spells2.c) - */ -extern void project_meteor(int radius, int typ, int dam, u32b flg); - -/** @fn passwall(int dir, bool safe) - * @brief Move the player through walls in direction "dir", to a "safe" - * location.\n - * @param dir Number \n dir must be a value from 0 to 9. It can not be 5. - * @brief Direction - * @param safe Boolean \n TRUE if location must be a safe one, otherwise FALSE. - * @brief Safe location? - * @return Boolean \n TRUE if move was successful, otherwise FALSE. - * @note - * Send the player shooting through walls in the given direction until - * they reach a non-wall space, or a monster, or a permanent wall.\n\n - * If the player ends up in a wall, they take 10d8 damage and the wall is - * replaced by a floor.\n\n - * This does not work in the wilderness, on quest levels, or if teleport is - * not allowed. Stopping on monsters or inside vaults is not allowed. - * @note (see file spells2.c) - */ -extern bool passwall(int dir, bool safe); - -/** @fn project_hook(int typ, int dir, int dam, int flg) - * @brief Generate a bolt/beam with properties "flg" in direction "dir" for - * "dam" points of "typ" damage.\n - * @param typ Number \n typ is the type of damage (GF field). - * @brief Type - * @param dir Number \n dir must be a value from 0 to 9. - * @brief Direction - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @param flg Number \n flg is the projection effect (PROJECT field). - * @brief Properties flag - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Hack -- apply a "projection()" in a direction (or at the target)\n\n - * If direction is 5 and a target has been selected, then the target is used. - * Otherwise, a target is calculated based on a distance of 999 grids away - * from the player in direction "dir". - * @note (see file spells2.c) - */ -extern bool project_hook(int typ, int dir, int dam, int flg); - -/** @fn wizard_lock(int dir) - * @brief Cast a wizard_lock spell in direction "dir".\n - * @param dir Number \n dir must be a value from 0 to 9. - * @brief Direction - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * If direction is 5 and a target has been selected, then the target is used. - * Otherwise, a target is calculated based on a distance of 999 grids away - * from the player in direction "dir". - * @note (see file spells2.c) - */ -extern bool wizard_lock(int dir); - -/** @fn reset_recall(bool no_trepas_max_depth) - * @brief Ask the user to set a recall level in a dungeon, possibly no - * deeper than maximum dungeon depth.\n - * @param no_trepas_max_depth Boolean \n TRUE if user can select maximum - * dungeon depth, FALSE if user can select up to player's maximum depth - * in the dungeon so far. - * @brief Allow maximum dungeon depth? - * @return Boolean \n TRUE of recall level was reset, otherwise FALSE. - * @note - * Ask the user for a dungeon and appropriate level within the dungeon.\n - * The user can not specify a dungeon the player has not gone to yet.\n - * If the depth is <1, reset fails. If depth is 99 or 100, the level is set - * to 98. - * @note (see file spells2.c) - */ -extern bool reset_recall(bool no_trepas_max_depth); - -/** @fn get_aim_dir(int *dp=0) - * @brief Get an aiming direction from the user and store it in "dp".\n - * @param *dp Number - * @brief Direction - * @return *dp Number \n Aiming direction. - * @return Boolean \n TRUE if a valid direction was returned, otherwise FALSE. - * @note - * Get an "aiming direction" from the user.\n\n - * The "dir" is loaded with 1,2,3,4,6,7,8,9 for "actual direction", and - * "0" for "current target", and "-1" for "entry aborted".\n\n - * Note that "Force Target", if set, will pre-empt user interaction, - * if there is a usable target already set.\n\n - * Note that confusion over-rides any (explicit?) user choice. - * @note (see file xtra2.c) - */ -extern bool get_aim_dir(int *dp=0); - -/** @fn get_rep_dir(int *dp=0) - * @brief Get a movement direction from the user and store it in "dp".\n - * @param *dp Number - * @brief Direction - * @return *dp Number \n Movement direction. - * @return Boolean \n TRUE if a valid direction was returned, otherwise FALSE. - * @note - * Request a "movement" direction (1,2,3,4,6,7,8,9) from the user, - * and place it into "command_dir", unless we already have one.\n\n - * This function should be used for all "repeatable" commands, such as - * run, walk, open, close, bash, disarm, spike, tunnel, etc, as well - * as all commands which must reference a grid adjacent to the player, - * and which may not reference the grid under the player. Note that, - * for example, it is no longer possible to "disarm" or "open" chests - * in the same grid as the player.\n\n - * Direction "5" is illegal and will (cleanly) abort the command.\n\n - * This function tracks and uses the "global direction", and uses - * that as the "desired direction", to which "confusion" is applied. - * @note (see file xtra2.c) - */ -extern bool get_rep_dir(int *dp=0); - -/** @fn project_los(int typ, int dam); - * @brief Generate a bolt/beam for "dam" points of "typ" damage to all - * viewable monsters in line of sight.\n - * @param typ Number \n typ is the type of damage (GF field). - * @brief Type - * @param dam Number \n dam is the number of hit points of damage. - * @brief Damage - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note - * Apply a "project()" directly to all viewable monsters\n\n - * Note that affected monsters are NOT auto-tracked by this usage. - * @note (see file spells2.c) - */ -extern bool project_hack @ project_los(int typ, int dam); - -/** @fn map_area(void) - * @brief Map current area. - * @note - * Hack -- map the current panel (plus some) ala "magic mapping"\n\n - * Up to 10 grids above and below, and up to 20 grids either side of the - * panel are mapped. - * @note (see file cave.c) - */ -extern void map_area(void); - -/** @fn wiz_lite(void) - * @brief Lite level using "clairvoyance". - * @note - * This function "illuminates" every grid in the dungeon, memorizes all - * "objects", memorizes all grids as with magic mapping, and, under the - * standard option settings (view_perma_grids but not view_torch_grids) - * memorizes all floor grids too.\n\n - * Note that if "view_perma_grids" is not set, we do not memorize floor - * grids, since this would defeat the purpose of "view_perma_grids", not - * that anyone seems to play without this option.\n\n - * Note that if "view_torch_grids" is set, we do not memorize floor grids, - * since this would prevent the use of "view_torch_grids" as a method to - * keep track of what grids have been observed directly. - * @note (see file cave.c) - */ -extern void wiz_lite(void); - -/** @fn wiz_lite_extra(void) - * @brief Lite and memorize level. - * @note (see file cave.c) - */ -extern void wiz_lite_extra(void); - -/** @fn wiz_dark(void) - * @brief Forget all grids and objects. - * @note - * Forget the dungeon map (ala "Thinking of Maud..."). - * @note (see file cave.c) - */ -extern void wiz_dark(void); - -/** @fn create_between_gate(int dist, int y, int x) - * @brief Create a between gate at grid "y,x" or at a target grid within - * distance "dist" of the player.\n - * @param dist Number \n dist is the maximum distance from the player of the - * between gate. - * @brief Distance - * @param y Number \n Y-coordinate of dungeon grid. - * @brief Y-coordinate - * @param x Number \n X-coordinate of dungeon grid. - * @brief X-coordinate - * @note - * Creates a between gate\n\n - * This will fail if teleporting is not allowed on the level.\n\n - * If the coordinates are given, a between gate is created under the player - * and at the given coordinate.\n\n - * If there are no coordinates, a target is selected. The gate will not be - * created if the grid is not empty, or the grid is in a vault, or the grid - * is too far away. There is always a chance (1 in (Conveyance Skill * - * Conveyance Skill / 2)) the gate will not be created. - * @note (see file spells2.c) - */ -extern void create_between_gate(int dist, int y, int x); - -/** @fn destroy_doors_touch(void) - * @brief Destroy all doors adjacent to the player. - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note (see file spells2.c) - */ -extern bool destroy_doors_touch(void); - -/** @fn destroy_traps_touch(void) - * @brief Destroy all traps adjacent to the player. - * @return Boolean \n TRUE if player notices, otherwise FALSE. - * @note (see file spells2.c) - */ -extern bool destroy_traps_touch(void); - -/** @struct magic_power - * @brief Innate powers - */ -struct magic_power -{ - /** @structvar min_lev - * @brief Number - */ - int min_lev; - - /** @structvar mana_cost - * @brief Number - */ - int mana_cost; - - /** @structvar fail - * @brief Number - */ - int fail; - - /** @structvar name - * @brief String - */ - cptr name; - - /** @structvar desc - * @brief String - */ - cptr desc; -}; - -/** @fn get_magic_power(magic_power *m_ptr, int num); - * @dgonly - * @brief Get magic power number "num" from array "m_ptr" of magic powers.\n - * @param *m_ptr magic_power \n m_ptr is the array of magic powers. - * @brief Powers - * @param num Number \n num is the index to the array. - * @brief Index - * @return magic_power \n A magic power. - * @note - * Note: do not call this function.\n - * By order of DG. - * @note (see file lua_bind.c) - */ -extern magic_power *grab_magic_power @ get_magic_power(magic_power *m_ptr, int num); - -extern s16b can_spell_random(s16b spell_idx); - -/* Schools */ - -/** @struct school_spell_type - * @brief Spell - * @note The spell function must provide the desc - */ -struct spell_type@school_spell_type -{ - /** @structvar name - * @brief String - */ - cptr name; - - /** @structvar skill_level - * @brief Number - * @note Required level (to learn) - */ - byte skill_level; - -}; - -/** Get level of device */ -extern s32b get_level_device(s32b s, s32b max, s32b min); - -/** Get level of spell */ -extern s32b get_level(s32b s, s32b max, s32b min); - - -/** @fn lua_spell_device_chance(s32b chance, int level, int base_level) - * @dgonly - * @brief Get the chance a device will fail.\n - * @param chance Number \n chance is the inital chance a spell will work. - * @brief Initial chance - * @param level Number \n level represents the level of player skill. - * @brief Player skill level - * @param base_level Number \n *unused* - * @brief *Unused* - * @return Number \n Chance of failure. - * @note - * Note: do not call this function directly.\n - * By order of DG. - * @note (see file lua_bind.c) - */ -extern s32b lua_spell_device_chance(s32b chance, int level, int base_level); - -/** @fn get_school_spell(cptr do_what, cptr check_fct, s16b force_book) - * @brief Get a spell from a book.\n - * @param do_what String \n what the player wants to do with the spell, - * for example "cast" or "copy". - * @brief Action - * @param check_fct String \n check_fct is the name of a function which checks - * if the player has access to the spell. - * @brief Check function - * @param force_book Number \n If it is different from 0 it for'ces the use of - * a spellbook, bypassing spellbook selection - * @brief Bypass book selection - * @return Number \n Spell number. - * @note - * Get a spell from a book\n\n - * The player must have a book to select a spell. When a book is chosen, the - * player is given a choice of spells to select. The player must be able to - * access the spell.\n\n - * If no spell is chosen, -1 is returned. - * @note (see file cmd5.c) - */ -extern s32b get_school_spell(cptr do_what, s16b force_book); - -/** @fn get_pos_player(int dis, int *ny=0, int *nx=0) - * @brief Get a grid near the player.\n - * @param dis Number \n is the maximum distance away from the player. - * This is limited to 200. - * @brief Distance from player - * @return y Number \n Y-coordinate of grid. - * @return x Number \n X-coordinate of grid. - * @note - * This function is slightly obsessive about correctness.\n\n - * Minimum distance is half the maximum distance. The function attempts to - * find a valid grid up to 500 times. If no valid grid is found, the maximum - * distance is doubled (though no more than 200) and the minimum distance is - * halved. The function does this 100 times. - * @note (see file spells1.c) - */ -extern void get_pos_player(int dis, int *ny=0, int *nx=0); - -/** - * spells4.c - */ -void init_school_books(); - -extern s32b SCHOOL_AIR; -extern s32b SCHOOL_AULE; -extern s32b SCHOOL_CONVEYANCE; -extern s32b SCHOOL_DEMON; -extern s32b SCHOOL_DEVICE; -extern s32b SCHOOL_DIVINATION; -extern s32b SCHOOL_EARTH; -extern s32b SCHOOL_ERU; -extern s32b SCHOOL_FIRE; -extern s32b SCHOOL_GEOMANCY; -extern s32b SCHOOL_MANA; -extern s32b SCHOOL_MANDOS; -extern s32b SCHOOL_MANWE; -extern s32b SCHOOL_MELKOR; -extern s32b SCHOOL_META; -extern s32b SCHOOL_MIND; -extern s32b SCHOOL_MUSIC; -extern s32b SCHOOL_NATURE; -extern s32b SCHOOL_TEMPORAL; -extern s32b SCHOOL_TULKAS; -extern s32b SCHOOL_UDUN; -extern s32b SCHOOL_ULMO; -extern s32b SCHOOL_VARDA; -extern s32b SCHOOL_WATER; -extern s32b SCHOOL_YAVANNA; - -void lua_cast_school_spell @ cast_school_spell(s32b spell_idx, bool no_cost = FALSE); -void spell_description_add_line(s32b spell_idx, cptr line); - -/** - * spells5.c - */ -void school_spells_init(); -s16b get_random_spell(s16b random_type, int lev); - -/** - * spells6.c - */ -void schools_init(); diff --git a/src/squeltch.c b/src/squeltch.c index d47f8a11..3b018834 100644 --- a/src/squeltch.c +++ b/src/squeltch.c @@ -11,8 +11,6 @@ */ #include "angband.h" -#include "lua/lua.h" -#include "tolua.h" #include #define RULES_MAX 4096 diff --git a/src/util.pkg b/src/util.pkg deleted file mode 100644 index 196aabda..00000000 --- a/src/util.pkg +++ /dev/null @@ -1,2251 +0,0 @@ -/* File: util.pkg */ - -/* - * Purpose: Lua interface defitions for miscellaneous routines. - * To be processed by tolua to generate C source code. - */ - -$#include "angband.h" -$#include "plots.h" - -/** @typedef cptr - * @note String - */ -typedef char* cptr; -/** @typedef errr - * @note Number - */ -typedef int errr; -/** @typedef bool - * @note Boolean - */ -typedef unsigned char bool; -/** @typedef byte - * @note Number - */ -typedef unsigned char byte; -/** @typedef s16b - * @note Number - */ -typedef signed short s16b; -/** @typedef u16b - * @note Number - */ -typedef unsigned short u16b; -/** @typedef s32b - * @note Number - */ -typedef signed int s32b; -/** @typedef u32b - * @note Number - */ -typedef unsigned int u32b; - -/** @def TRUE */ -#define TRUE - -/** @def FALSE */ -#define FALSE - - -/** @def ESCAPE */ -#define ESCAPE '\033' - -/** @name Terminal Colours - * @{ - */ -/** @def TERM_DARK - * @note 'd' (0,0,0) - */ -#define TERM_DARK 0 /* 'd' */ -/** @def TERM_WHITE - * @note 'w' (4,4,4) - */ -#define TERM_WHITE 1 /* 'w' */ -/** @def TERM_SLATE - * @note 's' (2,2,2) - */ -#define TERM_SLATE 2 /* 's' */ -/** @def TERM_ORANGE - * @note 'o' (4,2,0) - */ -#define TERM_ORANGE 3 /* 'o' */ -/** @def TERM_RED - * @note 'r' (3,0,0) - */ -#define TERM_RED 4 /* 'r' */ -/** @def TERM_GREEN - * @note 'g' (0,2,1) - */ -#define TERM_GREEN 5 /* 'g' */ -/** @def TERM_BLUE - * @note 'b' (0,0,4) - */ -#define TERM_BLUE 6 /* 'b' */ -/** @def TERM_UMBER - * @note 'u' (2,1,0) - */ -#define TERM_UMBER 7 /* 'u' */ -/** @def TERM_L_DARK - * @note 'D' (1,1,1) - */ -#define TERM_L_DARK 8 /* 'D' */ -/** @def TERM_L_WHITE - * @note 'W' (3,3,3) - */ -#define TERM_L_WHITE 9 /* 'W' */ -/** @def TERM_VIOLET - * @note 'v' (4,0,4) - */ -#define TERM_VIOLET 10 /* 'v' */ -/** @def TERM_YELLOW - * @note 'y' (4,4,0) - */ -#define TERM_YELLOW 11 /* 'y' */ -/** @def TERM_L_RED - * @note 'R' (4,0,0) - */ -#define TERM_L_RED 12 /* 'R' */ -/** @def TERM_L_GREEN - * @note 'G' (0,4,0) - */ -#define TERM_L_GREEN 13 /* 'G' */ -/** @def TERM_L_BLUE - * @note 'B' (0,4,4) - */ -#define TERM_L_BLUE 14 /* 'B' */ -/** @def TERM_L_UMBER - * @note 'U' (3,2,1) - */ -#define TERM_L_UMBER 15 /* 'U' */ -/** @} */ - -/** @name Event Hooks - * @{ - */ -/** @def HOOK_MONSTER_DEATH - * @brief Monster dies.\n - * @param Number m_idx \n index of monster in monster (m_list) array. - * @brief Monster index - * @note (see file xtra2.c) - */ -#define HOOK_MONSTER_DEATH 0 - -/** @def HOOK_OPEN - * @brief Open door or chest.\n - * @param Number quest \n if 0, then player is not on a quest level, - * otherwise the player is on a quest. - * @brief On quest? - * @note (see file cmd2.c) - */ -#define HOOK_OPEN 1 - -/** @def HOOK_GEN_QUEST - * @brief Generate quest level.\n - * @param Number quest \n if 0, then player is not on a quest level, - * otherwise the player is on a quest. - * @brief On quest? - * @note (see file generate.c) - */ -#define HOOK_GEN_QUEST 2 - -/** @def HOOK_END_TURN - * @brief Turn ends.\n - * @param Number quest \n if 0, then player is not on a quest level, - * otherwise the player is on a quest. - * @brief On quest? - * @note (see file dungeon.c) - */ -#define HOOK_END_TURN 3 - -/** @def HOOK_FEELING - * @brief Display level feeling.\n - * @param Number quest \n if 0, then player is not on a quest level, - * otherwise the player is on a quest. - * @brief On quest? - * @return Boolean \n TRUE if a level feeling was displayed, otherwise FALSE. - * @note - * If the hook returns TRUE, then no other feelings are displayed and - * do_cmd_feeling() returns. - * @note (see file cmd4.c) - */ -#define HOOK_FEELING 4 - -/** @def HOOK_NEW_MONSTER - * @brief Generate monster.\n - * @param Number r_idx \n index of monster in monster race (r_info) array. - * @brief Monster index - * @return Boolean \n TRUE if monster is not allowed to be created, - * otherwise FALSE. - * @note - * If the hook returns TRUE, then the monster is "killed". - * @note (see file monster2.c) - */ -#define HOOK_NEW_MONSTER 5 - -/** @def HOOK_GEN_LEVEL - * @brief Generate dungeon level.\n - * @param Number quest \n if 0, then player is not on a quest level, - * otherwise the player is on a quest. - * @brief On quest? - * @note (see file generate.c) - */ -#define HOOK_GEN_LEVEL 6 - -/** @def HOOK_BUILD_ROOM1 - * @brief Generate room (type 1 - normal rectangular room).\n - * @param Number by0 \n y-coordinate of dungeon block where room is built. - * @brief Block y-coordinate - * @param Number bx0 \n x-coordinate of dungeon block where room is built. - * @brief Block x-coordinate - * @return Boolean \n TRUE if room was created, otherwise FALSE. - * @note - * If the hook returns TRUE, then the room has been built and build_type1() - * returns. - * @note (see file generate.c) - */ -#define HOOK_BUILD_ROOM1 7 - -/** @def HOOK_NEW_LEVEL - * @brief Start dungeon level.\n - * @param Number quest \n if 0, then player is not on a quest level, - * otherwise the player is on a quest. - * @brief On quest? - * @note (see file dungeon.c) - */ -#define HOOK_NEW_LEVEL 8 - -/** @def HOOK_QUEST_FINISH - * @brief Quest finished.\n - * @param Number plot \n a plot from the plots array. - * @brief Plot - * @note (see file bldg.c) - */ -#define HOOK_QUEST_FINISH 9 - -/** @def HOOK_QUEST_FAIL - * @brief Quest failed.\n - * @param Number plot \n a plot from the plots array. - * @brief Plot - * @note (see file bldg.c) - */ -#define HOOK_QUEST_FAIL 10 - -/** @def HOOK_GIVE - * @brief Give item to monster.\n - * @param Number m_idx \n index of monster in monster (m_list) array. - * @brief Monster index - * @param Number item \n the item to be given. - * @brief Item number - * @return Boolean \n TRUE if item was given to monster, otherwise FALSE. - * @note - * If the hook returns FALSE, then the message "The monster does not want - * your item." is displayed. - * @note (see file cmd2.c) - */ -#define HOOK_GIVE 11 - -/** @def HOOK_CHAR_DUMP - * @brief Add a line to the character sheet. - * @note (see files.c) - */ -#define HOOK_CHAR_DUMP 12 - -/** @def HOOK_INIT_QUEST - * @brief Quest initialised.\n - * @param Number plot \n a plot from the plots array. - * @brief Plot - * @return Boolean \n TRUE if quest was not initialised, otherwise FALSE. - * @note - * If the hook returns TRUE, castle_quest() returns FALSE. - * @note (see file bldg.c) - */ -#define HOOK_INIT_QUEST 13 - -/** @def HOOK_WILD_GEN - * @brief Generate wilderness.\n - * @param Number wilderness \n if TRUE, then this is overhead wilderness - * processing, otherwise it is regular wilderness processing. - * @brief Overhead? - * @note (see file wild.c) - */ -#define HOOK_WILD_GEN 14 - -/** @def HOOK_DROP - * @brief Drop an item.\n - * @param Number item \n the item to drop. - * @brief Item number - * @return Boolean \n TRUE if item was dropped, otherwise FALSE. - * @note - * If the hook returns TRUE, do_cmd_drop() returns, otherwise the function - * continues. - * @note (see file cmd3.c) - */ -#define HOOK_DROP 15 - -/** @def HOOK_IDENTIFY - * @brief Identfy an item.\n - * @param Number item \n the item to identify. - * @brief Item number - * @param String type \n "normal" to identify the item, or "full" to fully - * identify an item. - * @brief Type - * @note (see files spells1.c, spells2.c) - */ -#define HOOK_IDENTIFY 16 - -/** @def HOOK_MOVE - * @brief Player moves.\n - * @param Number y \n the y-coordinate of the new location. - * @brief Y-coordinate - * @param Number x \n the x-coordinate of the new location. - * @brief X-coordinate - * @return Boolean \n TRUE if player is not allowed to move, otherwise FALSE. - * @note - * If the hook returns TRUE, move_player_aux() returns, otherwise the function - * continues. - * @note (see file cmd1.c) - */ -#define HOOK_MOVE 17 - -/** @def HOOK_STAIR - * @brief Player uses stairs.\n - * @param String direction \n "up" if the player is going up stairs, or - * "down" if the player is going down stairs. - * @brief Direction - * @return Boolean \n TRUE if player is not allowed to use stairs, otherwise - * FALSE. - * @note - * If the hook returns TRUE, do_cmd_go_up() or do_cmd_go_down() returns, - * otherwise the function continues. - * @note (see file cmd2.c) - */ -#define HOOK_STAIR 18 - -/** @def HOOK_MONSTER_AI - * @brief Monster moves.\n - * @param Number m_idx \n index of monster in monster (m_list) array. - * @brief Monster index - * @return Boolean \n TRUE if monster AI was applied, otherwise FALSE. - * @return Number y2 \n New y-coordinate of monster target. - * @return Number x2 \n New x-coordinate of monster target. - * @note - * If the hook returns TRUE, the monster moves toward the hook position. - * @note (see file melee2.c) - */ -#define HOOK_MONSTER_AI 19 - -/** @def HOOK_PLAYER_LEVEL - * @brief Player gains (or loses) a level.\n - * @param Number gained \n the number of levels gained (or lost). - * @brief Levels gained - * @note (see file xtra2.c) - */ -#define HOOK_PLAYER_LEVEL 20 - -/** @def HOOK_WIELD - * @brief Player wields an item.\n - * @param Number item \n the item to wield. - * @brief Item number - * @return Boolean \n TRUE if item was not wielded, otherwise FALSE. - * @note - * If the hook returns TRUE, do_cmd_wield() returns, otherwise the function - * continues. - * @note (see file cmd3.c) - */ -#define HOOK_WIELD 21 - -/** @def HOOK_AIM */ -#define HOOK_AIM 24 - -/** @def HOOK_USE */ -#define HOOK_USE 25 - -/** @def HOOK_ACTIVATE - * @brief Player activates an item.\n - * @param Number item \n the item to activate. - * @brief Item number - * @return Boolean \n TRUE if item was activated, otherwise FALSE. - * @note - * If the hook returns TRUE, do_cmd_activate() returns, otherwise the function - * continues. - * @note (see file cmd6.c) - */ -#define HOOK_ACTIVATE 26 - -/** @def HOOK_ZAP - * @brief Player zaps a rod.\n - * @param Number tval \n type of rod to zap. - * @brief Type - * @param Number sval \n sub-type of rod to zap. - * @brief Sub-type - * @note (see file cmd6.c) - */ -#define HOOK_ZAP 27 - -/** @def HOOK_CALC_POWERS - * @brief Calculate player powers. - * @note (see xtra1.c) - */ -#define HOOK_CALC_POWERS 30 - -/** @def HOOK_KEYPRESS - * @brief User enters a command.\n - * @param Number command \n the pressed key (command_cmd). - * @brief Command - * @return Boolean \n TRUE if special processing was done, otherwise FALSE. - * @note - * If the hook returns TRUE, process_command() returns, otherwise the function - * continues. - * @note (see file dungeon.c) - */ -#define HOOK_KEYPRESS 31 - -/** @def HOOK_CHAT - * @brief Player chats to monster.\n - * @param Number m_idx \n index of monster in monster (m_list) array. - * @brief Monster index - * @return Boolean \n TRUE if monster chats, otherwise FALSE. - * @note - * If the hook returns FALSE, the message "There is no monster there." is - * printed. - * @note (see file cmd2.c) - */ -#define HOOK_CHAT 32 - -/** @def HOOK_MON_SPEAK - * @brief Monster speaks.\n - * @param Number m_idx \n index of monster in monster (m_list) array. - * @brief Monster index - * @param String m_name \n name of the monster. - * @brief Monster name - * @return Boolean \n TRUE if monster speaks, otherwise FALSE. - * @note - * If the hook returns FALSE, the monster may say something else. - * @note (see file melee2.c) - */ -#define HOOK_MON_SPEAK 33 - -/** @def HOOK_BIRTH_OBJECTS - * @brief Player receives objects at birth. - * @note (see file birth.c) - */ -#define HOOK_BIRTH_OBJECTS 35 - -/** @def HOOK_ACTIVATE_DESC - * @brief Display activation description.\n - * @param Object o_ptr \n the item to activate. - * @brief Object - * @return Boolean \n TRUE if item has an activation, otherwise FALSE. - * @return String desc \n the activation description. - * @note - * If the hook returns TRUE, item_activation() returns the hook's activation - * description. - * @note (see file object1.c) - */ -#define HOOK_ACTIVATE_DESC 36 - -/** @def HOOK_INIT_GAME - * @brief Game initialised.\n - * @param String when \n "begin" if done at the start of game initialisation, - * or "end" if done at end of game initialisation. - * @brief When? - * @note (see file init2.c) - */ -#define HOOK_INIT_GAME 37 - -/** @def HOOK_ACTIVATE_POWER - * @brief Player activates a power.\n - * @param Number power \n the power to activate. - * @brief Power - * @return Boolean \n TRUE if power was activated, otherwise FALSE. - * @note - * If the hook returns FALSE, power_activate() displays the message - * "Warning power_activate() called with invalid power(xx)." where - * xx = power. - * @note (see file powers.c) - */ -#define HOOK_ACTIVATE_POWER 38 - -/** @def HOOK_ITEM_NAME - * @brief Get an item name.\n - * @param Object o_ptr \n the item whose name is required. - * @brief Object - * @return Boolean \n TRUE if name was found, otherwise FALSE. - * @return String basenm \n The item name. - * @return String modstr \n The item modifier string. - * @note (see file object1.c) - */ -#define HOOK_ITEM_NAME 39 - -/** @def HOOK_SAVE_GAME - * @brief Save the game. - * @note (see file loadsave.c) - */ -#define HOOK_SAVE_GAME 40 - -/** @def HOOK_LOAD_GAME - * @brief Load the game. - * @note (see file loadsave.c) - */ -#define HOOK_LOAD_GAME 41 - -/** @def HOOK_LEVEL_REGEN - * @brief Start generation of a special level. - * @note (see file generate.c) - */ -#define HOOK_LEVEL_REGEN 42 - -/** @def HOOK_LEVEL_END_GEN - * @brief End generation of a special level. - * @note (see file generate.c) - */ -#define HOOK_LEVEL_END_GEN 43 - -/** @def HOOK_BUILDING_ACTION - * @brief Player performs an action in a building.\n - * @param Number action \n the action performed in the building - * @brief Action flag - * @return Boolean \n TRUE if player performed the action, otherwise FALSE. - * @return Number paid \n TRUE if player paid to perform the action, otherwise - * FALSE. - * @return Number recreate \n TRUE if something is recreated, otherwise FALSE. - * @note - * If the hook returns TRUE, the hook sets the "paid" and "recreate" flags. - * @note (see file bldg.c) - */ -#define HOOK_BUILDING_ACTION 44 - -/** @def HOOK_WIELD_SLOT - * @brief Find equipment slot for object.\n - * @param Object o_ptr \n the object to wield. - * @brief Object - * @param Number ideal \n TRUE if current body and stuff is ignore, otherwise - * FALSE. - * @return Boolean \n TRUE if hook processed the object, otherwise FALSE. - * @return Number slot \n The equipent slot where the object will go (-1 if - * there are no available slots). - * @note - * If the hook returns TRUE, wield_slot_ideal() returns the slot from the hook. - * @note (see file objects1.c) - */ -#define HOOK_WIELD_SLOT 46 - -/** @def HOOK_STORE_STOCK - * @brief Stock a store.\n - * @param Number st_idx \n the index of the store in st_info array. - * @brief Store index - * @param String name \n the name of the store. - * @brief Store name - * @param Number level \n the "dungeon level" of the store. - * @brief Store level - * @return Boolean \n TRUE if hook has selected an object, otherwise FALSE. - * @return Object q_ptr \n The item to be stocked in the store. - * @note - * If the hook returns TRUE, store_create() will create the hook's object and - * put it in the store. - * @note (see file store.c) - */ -#define HOOK_STORE_STOCK 47 - -/** @def HOOK_GEN_LEVEL_BEGIN - * @brief Generate a random dungeon level. - * @note (see file generate.c) - */ -#define HOOK_GEN_LEVEL_BEGIN 49 - -/** @def HOOK_GET - * @brief Player gets an object.\n - * @param Object o_ptr \n the object to get. - * @brief Object - * @param Number o_idx \n the index of the object in o_list array. - * @brief Object index - * @return Boolean \n TRUE if hooks processes the object, otherwise FALSE. - * @note - * If the hook returns TRUE, object_pickup() returns, otherwise the function - * continues. - * @note (see object1.c) - */ -#define HOOK_GET 50 - -/** @def HOOK_REDRAW - * @brief Redraw the screen. - * @note (see file xtra1.c) - */ -#define HOOK_REDRAW 51 - -/** @def HOOK_RECALC_SKILLS - * @brief Recalculate player skills. - * @note (see skills.c) - */ -#define HOOK_RECALC_SKILLS 52 - -/** @def HOOK_ENTER_DUNGEON - * @brief Player goes down one dungeon level.\n - * @param Number special \n special information for player's dungeon grid. - * @brief Special info - * @return Boolean \n TRUE if the hook prevents the player going down, - * otherwise FALSE. - * @note - * If the hook returns TRUE, the player remains on the current dungeon level - * and do_cmd_go_down() returns. - * @note (see file cmd2.c) - */ -#define HOOK_ENTER_DUNGEON 53 - -/** @def HOOK_FIRE - * @brief Player fires an object (bow slot of inventory).\n - * @param Object \n the object to fire. - * @brief Object - * @return Boolean \n TRUE if the hook has fired the object, otherwise FALSE. - * @note - * If the hook returns TRUE, process_command() returns. - * @note (see file dungeon.c) - */ -#define HOOK_FIRE 54 - -/** @def HOOK_EAT - * @brief Player eats.\n - * @param Object o_ptr \n the object the player eats. - * @brief Object - * @return Boolean \n TRUE if hook processes the object, otherwise FALSE. - * @return Number ident \n TRUE if the object was identified, otherwise FALSE. - * @note - * If the hook returns TRUE, the hook sets the "food identified" flag. - * @note (see file cmd6.c) - */ -#define HOOK_EAT 55 - -/** @def HOOK_DIE - * @brief Player dies. - * @return Boolean \n TRUE if player does not die, otherwise FALSE. - * @note - * If the hook returns TRUE, the player cheats death. - * @note (see file dungeon.c) - */ -#define HOOK_DIE 56 - -/** @def HOOK_CALC_HP - * @brief Recalculate player HP (hit points).\n - * @param Number mhp \n the player's new maximum hit points. - * @brief Maximum hit points. - * @return Boolean \n TRUE if hook has processed player hit points, otherwise - * FALSE. - * @note - * If the hook returns TRUE, the player's maximum hit points are updated. - * @note (see file xtra1.c) - */ -#define HOOK_CALC_HP 57 - -/** @def HOOK_CALC_MANA - * @brief Recalculate player SP (spell points).\n - * @param Number msp \n the player's new maximum spell points. - * @brief Maximum spell points. - * @return Boolean \n TRUE if hook has processed player spell points, otherwise - * FALSE. - * @note - * If the hook returns TRUE, the player's maximum spell points are updated. - * @note (see file xtra1.c) - */ -#define HOOK_CALC_MANA 60 - -/** @def HOOK_LOAD_END - * @brief Load a savefile.\n - * @param Number death \n TRUE if the character is dead, otherwise FALSE. - * @brief Dead character? - * @return Boolean \n TRUE if hook has processed savefile, otherwise FALSE. - * @return Number death \n - * @note - * If the hook returns TRUE, then "character_loaded" (real living player) is - * set to TRUE. The player has been revived. - * @note (see file loadsave.c) - */ -#define HOOK_LOAD_END 61 - -/** @def HOOK_RECALL - * @brief Player recalls from/to dungeon/town. - * @return Boolean \n TRUE if player is not allowed to recall, otherwise - * FALSE. - * @note (see file dungeon.c) - */ -#define HOOK_RECALL 62 - -/** @def HOOK_BODY_PARTS - * @brief Calculate which body parts the player has. - * @note (see file xtra1.c) - */ -#define HOOK_BODY_PARTS 65 - -/** @def HOOK_APPLY_MAGIC - * @brief Apply magic to an item.\n - * @param Object o_ptr \n the item to which magic is applied - * @brief Object - * @param Number level \n the level of the object - * @brief Object level - * @param Number power \n the power of the object (0 = normal, 1 = good, - * 2 = great, -1 = cursed, -2 = broken) - * @brief Power - * @return Boolean \n TRUE if hook has applied magic, otherwise FALSE. - * @note - * If the hook returns TRUE, a_m_aux_n() (where n=1 to 4) returns. - * @note (see file object2.c) - */ -#define HOOK_APPLY_MAGIC 66 - -/** @def HOOK_PLAYER_EXP - * @brief Player gains/loses experience points (XP).\n - * @param Number amount \n the number of experience points to gain/lose - * @brief Points - * @note (see file xtra2.c) - */ -#define HOOK_PLAYER_EXP 67 - -/** @def HOOK_BIRTH - * @brief Player is born. - * @note (see file birth.c) - */ -#define HOOK_BIRTH 68 - -/** @def HOOK_LEARN_ABILITY - * @brief Player learns an ability.\n - * @param Number ab \n index of ability in ability (ab_info) array. - * @brief Ability index - * @return Boolean \n TRUE if player is not to gain the ability, otherwise - * FALSE. - * @note If the hook returns TRUE, can_learn_ability() returns FALSE. - * @note (see file skills.c) - */ -#define HOOK_LEARN_ABILITY 70 - -/** @def HOOK_MOVED - * @brief Player finishes moving. - * @note (see file cmd1.c) - */ -#define HOOK_MOVED 71 - -/** @def HOOK_GAME_START - * @brief Game begins. - * @note (see file dungeon.c) - */ -#define HOOK_GAME_START 72 - -/** @def HOOK_TAKEOFF - * @brief Player takes off an item.\n - * @param Number item \n the item to take off. - * @brief Item - * @return Booelan \n TRUE if item can not be taken off, otherwise FALSE. - * @note - * If the hook returns TRUE, do_cmd_takeoff() returns. - * @note (see file cmd3.c) - */ -#define HOOK_TAKEOFF 73 - -/** @def HOOK_CALC_WEIGHT - * @brief Calculate player weight limit.\n - * @param Number weight \n the current weight limit. - * @brief Weight - * @return Boolean \n TRUE if weight was processed, otherwise FALSE. - * @return Number weight \n The new maximum weight. - * @note - * If the hook returns TRUE, weight_limit() returns the hook's weight. - * @note (see file xtra1.c) - */ -#define HOOK_CALC_WEIGHT 74 - -/** @def HOOK_FORBID_TRAVEL - * @brief Check if the player may press < and travel.\n - * @return Boolean \n TRUE if travel is forbidden, otherwise FALSE. - */ -#define HOOK_FORBID_TRAVEL 75 - -/** @def HOOK_DEBUG_COMMAND - * @brief User enters a debug command.\n - * @param Number command \n the pressed key (cmd). - * @brief Command - * @return Boolean \n TRUE if special processing was done, otherwise FALSE. - */ -#define HOOK_DEBUG_COMMAND 76 - - -/** @} */ - - -/** @var turn - * @brief Number - * @note Current game turn - */ -extern s32b turn; -/** @var old_turn - * @brief Number - * @note Turn when level began (feelings) - */ -extern s32b old_turn; -/** @var cur_wid - * @brief Number - * @note Current dungeon width - */ -extern s16b cur_wid; -/** @var cur_hgt - * @brief Number - * @note Current dungeon height - */ -extern s16b cur_hgt; - -/** @fn disturb(int stop_search, int flush_output) - * @brief Disturb the player.\n - * @param stop_search Number \n if 0, this will not disturb searching, - * otherwise searching is stopped. - * @brief Stop search? - * @param flush_output Number \n *unused* - * @brief *Unused* - * @note - * Something has happened to disturb the player.\n\n - * The first arg indicates a major disturbance, which affects search.\n - * The second arg is currently unused, but could induce output flush.\n\n - * All disturbance cancels repeated commands, resting, and running. - * @note (see file cave.c) - */ -extern void disturb(int stop_search, int flush_output); - -/** @fn bst(s32b what, s32b t) - * @brief Break scalar time.\n - * @param what Number \n the unit time "t" is to be broken into. The following - * values can be used: MINUTE, HOUR, DAY, YEAR - * @brief Unit of time - * @param t Number \n the time to be broken. - * @brief Time - * @return Number \n The number of unit in time "t". - * @note (see file util.c) - */ -extern s32b bst(s32b what, s32b t); - -$static char *path_build_lua(cptr path, cptr file){static char buf[1025]; path_build(buf, 1024, path, file); return buf;} - -/** @fn path_build(cptr path, cptr file); - * @brief Create a new path by appending a file (or directory) to a path.\n - * @param path String \n the original path. - * @brief Path - * @param file String \n the file or directory to append to the path. - * @brief File or directory - * @return String \n The new path. - * @note - * This requires no special processing on simple machines, except - * for verifying the size of the filename, but note the ability to - * bypass the given "path" with certain special file-names.\n\n - * Note that the "file" may actually be a "sub-path", including - * a path and a file.\n\n - * @note (see file util.c) - */ -static char *path_build_lua@path_build(cptr path, cptr file); - -/** @fn move_cursor(int row, int col) - * @brief Move the cursor of a terminal to row "row" and column "col".\n - * @param row Number \n the target row on the screen. - * @brief Row - * @param col Number \n the target column on the screen. - * @brief Column - * @note (see file util.c) - */ -extern void move_cursor(int row, int col); - -/** @fn flush(void) - * @brief Flush all input chars. - * @note - * Actually, remember the flush, and do a "special flush" before the next - * "inkey()". - * This is not only more efficient, but also necessary to make sure - * that various "inkey()" codes are not "lost" along the way. - * @note (see file util.c) - */ -extern void flush(void); - -/** @var inkey_scan - * @brief Boolean - * @note - * If "inkey_scan" is TRUE, then we will immediately return "zero" if no - * keypress is available, instead of waiting for a keypress. - */ -extern bool inkey_scan; - -/** @fn inkey(void) - * @brief Get a keypress from the user. - * @return String \n the key pressed by the user. - * @note - * This function recognizes a few "global parameters". These are variables - * which, if set to TRUE before calling this function, will have an effect - * on this function, and which are always reset to FALSE by this function - * before this function returns. Thus they function just like normal - * parameters, except that most calls to this function can ignore - * them.\n\n - * If "inkey_xtra" is TRUE, then all pending keypresses will be flushed, - * and any macro processing in progress will be aborted. This flag is - * set by the "flush()" function, which does not actually flush anything - * itself, but rather, triggers delayed input flushing via - * "inkey_xtra".\n\n - * If "inkey_scan" is TRUE, then we will immediately return "zero" if no - * keypress is available, instead of waiting for a - * keypress.\n\n - * If "inkey_base" is TRUE, then all macro processing will be bypassed. - * If "inkey_base" and "inkey_scan" are both TRUE, then this function will - * not return immediately, but will wait for a keypress for as long as the - * normal macro matching code would, allowing the direct entry of macro - * triggers. The "inkey_base" flag is extremely - * dangerous!\n\n - * If "inkey_flag" is TRUE, then we will assume that we are waiting for a - * normal command, and we will only show the cursor if "hilite_player" is - * TRUE (or if the player is in a store), instead of always showing the - * cursor. The various "main-xxx.c" files should avoid saving the game - * in response to a "menu item" request unless "inkey_flag" is TRUE, to - * prevent savefile - * corruption.\n\n - * If we are waiting for a keypress, and no keypress is ready, then we will - * refresh (once) the window which was active when this function was - * called.\n\n - * Note that "back-quote" is automatically converted into "escape" for - * convenience on machines with no "escape" key. This is done after the - * macro matching, so the user can still make a macro for - * "backquote".\n\n - * Note the special handling of "ascii 30" (ctrl-caret, aka ctrl-shift-six) - * and "ascii 31" (ctrl-underscore, aka ctrl-shift-minus), which are used to - * provide support for simple keyboard "macros". These keys are so strange - * that their loss as normal keys will probably be noticed by nobody. The - * "ascii 30" key is used to indicate the "end" of a macro action, which - * allows recursive macros to be avoided. The "ascii 31" key is used by - * some of the "main-xxx.c" files to introduce macro trigger - * sequences.\n\n - * Hack -- we use "ascii 29" (ctrl-right-bracket) as a special "magic" key, - * which can be used to give a variety of "sub-commands" which can be used - * any time. These sub-commands could include commands to take a picture of - * the current screen, to start/stop recording a macro action, - * etc.\n\n - * If "angband_term[0]" is not active, we will make it active during this - * function, so that the various "main-xxx.c" files can assume that input - * is only requested (via "Term_inkey()") when "angband_term[0]" is - * active.\n\n - * Mega-Hack -- This function is used as the entry point for clearing the - * "signal_count" variable, and of the "character_saved" - * variable.\n\n - * Hack -- Note the use of "inkey_next" to allow "keymaps" to be - * processed.\n\n - * Mega-Hack -- Note the use of "inkey_hack" to allow the "Borg" to steal - * control of the keyboard from the user. - * @note (see file util.c) - */ -extern char inkey(void); - -/** @fn cmsg_print(byte color, cptr msg) - * @brief Output message "msg" in colour "color" to the top line of the - * screen.\n - * @param color Number \n the colour of the message (see TERM_ fields). - * @brief Colour - * @param msg String \n the message. - * @brief Message - * @note - * Break long messages into multiple pieces (40-72 chars).\n\n - * Allow multiple short messages to "share" the top line.\n\n - * Prompt the user to make sure he has a chance to read them.\n\n - * These messages are memorized for later reference (see above).\n\n - * We could do "Term_fresh()" to provide "flicker" if needed.\n\n - * The global "msg_flag" variable can be cleared to tell us to - * "erase" any "pending" messages still on the - * screen.\n\n - * XXX XXX XXX Note that we must be very careful about using the - * "msg_print()" functions without explicitly calling the special - * "msg_print(NULL)" function, since this may result in the loss - * of information if the screen is cleared, or if anything is - * displayed on the top - * line.\n\n - * XXX XXX XXX Note that "msg_print(NULL)" will clear the top line - * even if no messages are pending. This is probably a hack. - * @note (see file util.c) - */ -extern void cmsg_print(byte color, cptr msg); - -/** @fn msg_print(cptr msg) - * @brief Output message "msg" in white to the top line of the screen.\n - * @param msg String \n the message. - * @brief Message - * @note (see file util.c) - */ -extern void msg_print(cptr msg); - -/** @fn screen_save(void) - * @brief Save the screen. - * @note - * Increase the "icky" depth.\n\n - * This function must match exactly one call to "screen_load()". - * @note (see file util.c) - */ -extern void screen_save(void); - -/** @fn screen_load(void) - * @brief Load the screen. - * @note - * Decrease the "icky" depth.\n\n - * This function must match exactly one call to "screen_save()". - * @note (see file util.c) - */ -extern void screen_load(void); - -/** @fn Term_save(void) - * @brief Save the "requested" screen into the "memorized" screen. - * @return Number \n 0 (always). - * @note - * Every "Term_save()" should match exactly one "Term_load()" - * @note (see file z-term.c) - */ -extern errr Term_save(void); - -/** @fn Term_load(void) - * @brief Restore the "requested" contents from the "memorized" screen. - * @return Number \n 0 (always). - * @note - * Every "Term_save()" should match exactly one "Term_load()" - * @note (see file z-term.c) - */ -extern errr Term_load(void); - -/** @fn c_put_str(byte attr, cptr str, int row, int col) - * @brief Add string "str" with attributes "attr" to screen at row "row" - * and column "col".\n - * @param attr Number \n the attribute of the string - * @brief Attribute - * @param str String \n the string - * @brief String - * @param row Number \n the target row on the screen. - * @brief Row - * @param col Number \n the target column on the screen. - * @brief Column - * @note - * Display a string on the screen using an attribute.\n\n - * At the given location, using the given attribute, if allowed, - * add the given string. Do not clear the line. - * @note (see file util.c) - */ -extern void c_put_str(byte attr, cptr str, int row, int col); - -/** @fn c_prt(byte attr, cptr str, int row, int col) - * @brief Add string "str" with attributes "attr" to screen at row "row" - * and column "col", clearing to the end of the row.\n - * @param attr Number \n the attribute of the string - * @brief Attribute - * @param str String \n the string - * @brief String - * @param row Number \n the target row on the screen. - * @brief Row - * @param col Number \n the target column on the screen. - * @brief Column - * @note (see file util.c) - */ -extern void c_prt(byte attr, cptr str, int row, int col); - -/** @fn prt(cptr str, int row, int col) - * @brief Add white string "str" to screen at row "row" and column "col", - * clearing to the end of the row.\n - * @param str String \n the string - * @brief String - * @param row Number \n the target row on the screen. - * @brief Row - * @param col Number \n the target column on the screen. - * @brief Column - * @note (see file util.c) - */ -extern void prt(cptr str, int row, int col); - -/** @fn message_add(byte type, cptr msg, byte color) - * @brief Add a message "msg" of type "type" and colour "color" to the - * message array.\n - * @param type Number \n the type of message. MESSAGE_MSG for regular - * messages. - * @brief Type - * @param msg String \n the message. - * @brief Message - * @param color Number \n the colour of the message (see TERM_ fields). - * @brief Colour - * @note - * Use "msg_print() instead. If you insist on using this function, be - * careful. - * @note (see file util.c) - */ -extern void message_add(byte type, cptr msg, byte color); - -/** @fn display_message(int x, int y, int split, byte color, cptr t) - * @brief Display a message.\n - * @param x Number \n the x-coordinate of the screen where the message starts. - * @brief X-coordinate - * @param y Number \n the y-coordinate of the screen where the message starts. - * @brief Y-coordinate - * @param split Number \n the position in the message where it is split. The - * rest of the message will not appear. - * @brief Split position - * @param color Number \n the colour of the message (see TERM_ fields). - * @brief Colour - * @param t String \n the message. - * @brief Message - * @note - * @note (see file util.c) - */ -extern void display_message(int x, int y, int split, byte color, cptr t); - -/** @fn clear_from(int row) - * @brief Clear part of the screen.\n - * @param row Number \n the target row on the screen. - * @brief Row - * @note - * Clear all rows from the starting row to the end of the screen. - * @note (see file util.c) - */ -extern void clear_from(int row); - -/** @fn askfor_aux(char *buf, int len) - * @brief Get some input at the cursor location.\n - * @param *buf String \n Default string (optional). - * @brief String - * @param len Number \n the maximum length of the string. - * @brief Length of string - * @return Boolean \n TRUE if string was entered, otherwise FALSE. - * @return *buf \n The entered string. - * @note - * Assume the buffer is initialized to a default string.\n - * Note that this string is often "empty" (see below).\n - * The default buffer is displayed in yellow until cleared.\n - * Pressing RETURN right away accepts the default entry.\n - * Normal chars clear the default and append the char.\n - * Backspace clears the default or deletes the final char.\n - * ESCAPE clears the buffer and the window and returns FALSE.\n - * RETURN accepts the current buffer contents and returns TRUE. - * @note (see file util.c) - */ -extern bool askfor_aux(char *buf, int len); - -/** @fn get_string(cptr prompt, char *buf, int len) - * @brief Get a string from the user.\n - * @param prompt String \n the prompt, which should take the form "Prompt: " - * @brief Prompt - * @param *buf String - * @brief String - * @param len Number \n the maximum length of the string. - * @brief Length of string - * @return Boolean \n TRUE if string was entered, otherwise FALSE. - * @return *buf \n The entered string. - * @note - * Note that the initial contents of the string is used as - * the default response, so be sure to "clear" it if needed.\n\n - * We clear the input, and return FALSE, on "ESCAPE". - * @note (see file util.c) - */ -extern bool get_string(cptr prompt, char *buf, int len); - -/** @fn get_check(cptr prompt) - * @brief Verify something with the user.\n - * @param prompt String \n the prompt, which should take the form "Query? " - * @brief Prompt - * @return Boolean \n TRUE if "y" or "Y" is entered, otherwise FALSE. - * @note - * Note that "[y/n]" is appended to the prompt. - * @note (see file util.c) - */ -extern bool get_check(cptr prompt); - -/** @fn get_com(cptr promtp, int *com = 0); - * @brief Prompts for a keypress.\n - * @param promtp String \n the prompt, which should take the form "Command: " - * @brief Prompt - * @param *com Number - * @brief Command - * @return Boolean \n FALSE if "Escape" was pressed, otherwise TRUE. - * @return *com \n The entered command. - * @note (see file util.c) - */ -extern bool get_com_lua @ get_com(cptr promtp, int *com = 0); - -/** @fn get_quantity(cptr prompt, s32b max) - * @brief Request a "quantity" from the user.\n - * @param prompt String \n the prompt - * @brief Prompt - * @param max Number \n the maximum quantity - * @brief Maximum quantity - * @return Number \n the returned quantity. - * @note - * Hack -- allow "command_arg" to specify a quantity\n\n - * The quantity is in the range 0 to "max" inclusive. The default is 1. A - * letter means the maximum. - * @note (see file util.c) - */ -extern s32b get_quantity(cptr prompt, s32b max); - -/** @fn test_monster_name(cptr name) - * @brief Given monster name as string, return the index in r_info array.\n - * @param name String \n the monster name. - * @brief Monster name - * @return Number \n The index of the monster in r_info[], or 0 if the name - * does not match a monster. - * @note - * Name must exactly match (look out for commas and the like!), or else 0 is - * returned. Case doesn't matter. - * @note (see file util.c) - */ -extern int test_monster_name(cptr name); - -/** @fn test_item_name(cptr name) - * @brief Given item name as string, return the index in k_info array.\n - * @param name String \n the item name. - * @brief Item name - * @return Number \n The index of the item in k_info[], or 0 if the name - * does not match an item. - * @note - * Name must exactly match (look out for commas and the like!), or else 0 is - * returned. Case doesn't matter. - * @note (see file util.c) - */ -extern int test_item_name(cptr name); - -/** @fn luck(int min, int max) - * @brief Return a luck number between a certain range.\n - * @param min Number \n the minimum luck value returned. - * @brief Mimimum - * @param max Number \n the maximum luck value returned. - * @brief Maximum - * @return Number \n The scaled value of player's luck. - * @note - * Player lucked is cap at a minimum of -30 and maximum of +30 before it is - * scaled to the range defined by "min" and "max". - * @note (see file xtra1.c) - */ -extern int luck(int min, int max); - -/** @fn get_player_race_name(int pr, int ps) - * @brief Return the player's race (and sub-race) name.\n - * @param pr Number \n the player's race. It is an index to race_info[]. - * @brief Player race - * @param ps Number \n the player's subrace, if any. It is an index to - * race_mod_info[]. - * @brief Player subrace - * @return String \n The player's full race name. - * @note (see file util.c) - */ -extern cptr get_player_race_name(int pr, int ps); - -/** @fn quit(cptr str) - * @brief Quit the game. - * @param str String \n an error code or a message which is logged. - * @brief String - * @note - * Exit (ala "exit()"). If 'str' is NULL, do "exit(0)".\n - * If 'str' begins with "+" or "-", do "exit(atoi(str))".\n - * Otherwise, plog() 'str' and exit with an error code of -1.\n - * But always use 'quit_aux', if set, before anything else. - * @note (see file z-util.c) - */ -extern void quit(cptr str); - -/** @fn text_out_c(byte a, cptr str) - * @brief Output text to the screen (in color) or to a file depending on the - * selected hook.\n - * @param a Number \n the attribute of the string - * @brief Attribute - * @param str String \n the string - * @brief String - * @note (see file util.c) - */ -extern void text_out_c(byte a, cptr str); - -/** @fn text_out(cptr str) - * @brief Output text to the screen (in white) or to a file depending on the - * selected hook.\n - * @param str String \n the string - * @brief String - * @note (see file util.c) - */ -extern void text_out(cptr str); - -/** @fn change_option(cptr name, bool value) - * @brief Switch an option by only knowing its name.\n - * @param name String \n the name of the option. - * @brief Option name - * @param value Boolean \n the new value of the option. - * @brief Option value - * @return Boolean \n the old value of the option, or FALSE if "name" is not - * an option. - * @note (see file cmd4.c) - */ -extern bool change_option(cptr name, bool value); - -/** @var process_hooks_restart - * @brief Number - * @note - * Set this to TRUE after deleting a C-hook (from a quest) to clean up hook - * processing. This is not required for Lua hooks as they are not deleted. - */ -extern int process_hooks_restart; - -/** @fn dump_hooks(int h_idx) - * @brief Print the name and type (language) of all hooks in a hook chain.\n - * @param h_idx Number \n the index of the hook chain in the hook_chain array. - * If this is -1, then all hook chains will be printed. - * @brief Hook chain index - * @note (see file plots.c) - */ -extern void dump_hooks(int h_idx); - -/** @fn add_hook_script(int h_idx, char *script, cptr name) - * @brief Add Lua script "name" in file "script" to hook_chain.\n - * @param h_idx Number \n the index of the hook chain in the hook_chain array. - * @brief Hook chain index - * @param *script String \n the name of the Lua script file. - * @brief Script filename - * @param name String \n the name of the script. - * @brief Script name - * @note (see file plots.c) - */ -extern void add_hook_script(int h_idx, char *script, cptr name); - -/** @fn del_hook_name(int h_idx, cptr name) - * @brief Delete hook with name "name" from a hook chain.\n - * @param h_idx Number \n the index of the hook chain in the hook_chain array. - * @brief Hook chain index - * @param name String \n the name of the hook to delete - * @brief Hook name - * @note (see file plots.c) - */ -extern void del_hook_name(int h_idx, cptr name); - -/** @fn tome_dofile(char *file) - * @brief Load a Lua file from lib/scpts.\n - * @param *file String \n the name of a Lua file to load. - * @brief Filename - * @return Boolean \n TRUE if file was loaded, otherwise FALSE. - * @note (see file script.c) - */ -extern bool tome_dofile(char *file); - -/** @fn tome_dofile_anywhere(cptr dir, char *file, bool test_exist = TRUE) - * @brief Load a Lua file from any directory.\n - * @param dir String \n the name of a Lua file directory - * @brief Directory - * @param *file String \n the name of a Lua file to load. - * @brief Filename - * @param test_exist Boolean \n TRUE if a message is printed if the file does - * not exist, otherwise FALSE. - * @brief Message if file does not exist? - * @return Boolean \n TRUE if file was loaded, otherwise FALSE. - * @note (see file script.c) - */ -extern bool tome_dofile_anywhere(cptr dir, char *file, bool test_exist = TRUE); - -/** @fn exec_lua(char *file) - * @brief Execute Lua command "file" and return the integer result.\n - * @param *file String \n the Lua command to execute. - * @brief Command - * @return Number \n the result of the Lua command. - * @note (see file script.c) - */ -extern int exec_lua(char *file); - -/** @fn dump_lua_stack(int min, int max) - * @brief Display part of the Lua stack.\n - * @param min Number \n the starting item of the stack dump. - * @brief Start item - * @param max Number \n the ending item of the stack dump. - * @brief End item - * @note (see file script.c) - */ -extern void dump_lua_stack(int min, int max); - -/** @fn string_exec_lua(char *file) - * @brief Execute Lua command "file" and return the string result.\n - * @param *file String \n the Lua command to execute. - * @brief Command - * @return String \n the result of the Lua command. - * @note (see file script.c) - */ -extern cptr string_exec_lua(char *file); - -/** @fn print_hook(cptr str); - * @brief Print string "string" to the hook file.\n - * @param str String \ the string. - * @brief String - * @note (see file lua_bind.c) - */ -extern void lua_print_hook@print_hook(cptr str); - - -/* Tables */ -/** @var adj_mag_study[100] - * @brief Number - * @note Stat Table (INT/WIS) -- Number of half-spells per level - */ -extern byte adj_mag_study[100]; - -/** @var adj_mag_mana[100] - * @brief Number - * @note Stat Table (INT/WIS) -- extra half-mana-points per level - */ -extern byte adj_mag_mana[100]; - -/** @var adj_mag_fail[100] - * @brief Number - * @note Stat Table (INT/WIS) -- Minimum failure rate (percentage) - */ -extern byte adj_mag_fail[100]; - -/** @var adj_mag_stat[100] - * @brief Number - * @note Stat Table (INT/WIS) -- Various things - */ -extern byte adj_mag_stat[100]; - -/** @var adj_chr_gold[100] - * @brief Number - * @note Stat Table (CHR) -- payment percentages - */ -extern byte adj_chr_gold[100]; - -/** @var adj_int_dev[100] - * @brief Number - * @note Stat Table (INT) -- Magic devices - */ -extern byte adj_int_dev[100]; - -/** @var adj_wis_sav[100] - * @brief Number - * @note Stat Table (WIS) -- Saving throw - */ -extern byte adj_wis_sav[100]; - -/** @var adj_dex_dis[100] - * @brief Number - * @note Stat Table (DEX) -- disarming - */ -extern byte adj_dex_dis[100]; - -/** @var adj_int_dis[100] - * @brief Number - * @note Stat Table (INT) -- disarming - */ -extern byte adj_int_dis[100]; - -/** @var adj_dex_ta[100] - * @brief Number - * @note Stat Table (DEX) -- bonus to ac (plus 128) - */ -extern byte adj_dex_ta[100]; - -/** @var adj_str_td[100] - * @brief Number - * @note Stat Table (STR) -- bonus to dam (plus 128) - */ -extern byte adj_str_td[100]; - -/** @var adj_dex_th[100] - * @brief Number - * @note Stat Table (DEX) -- bonus to hit (plus 128) - */ -extern byte adj_dex_th[100]; - -/** @var adj_str_th[100] - * @brief Number - * @note Stat Table (STR) -- bonus to hit (plus 128) - */ -extern byte adj_str_th[100]; - -/** @var adj_str_wgt[100] - * @brief Number - * @note Stat Table (STR) -- weight limit in deca-pounds - */ -extern byte adj_str_wgt[100]; - -/** @var adj_str_hold[100] - * @brief Number - * @note Stat Table (STR) -- weapon weight limit in pounds - */ -extern byte adj_str_hold[100]; - -/** @var adj_str_dig[100] - * @brief Number - * @note Stat Table (STR) -- digging value - */ -extern byte adj_str_dig[100]; - -/** @var adj_str_blow[100] - * @brief Number - * @note Stat Table (STR) -- help index into the "blow" table - */ -extern byte adj_str_blow[100]; - -/** @var adj_dex_blow[100] - * @brief Number - * @note Stat Table (DEX) -- index into the "blow" table - */ -extern byte adj_dex_blow[100]; - -/** @var adj_dex_safe[100] - * @brief Number - * @note Stat Table (DEX) -- chance of avoiding "theft" and "falling" - */ -extern byte adj_dex_safe[100]; - -/** @var adj_con_fix[100] - * @brief Number - * @note Stat Table (CON) -- base regeneration rate - */ -extern byte adj_con_fix[100]; - -/** @var adj_con_mhp[100] - * @brief Number - * @note Stat Table (CON) -- extra half-hitpoints per level (plus 128) - */ -extern byte adj_con_mhp[100]; - -/* Repeat stuff */ -/** @fn repeat_push(int what) - * @brief Push key "what" onto the end of the repeat_key array.\n - * @param what Number \n the key to be repeated. - * @brief Key - * @note (see file util.c) - */ -extern void repeat_push(int what); - -/** @fn repeat_pull(int *what = 0) - * @brief Pull key from the repeat__key array.\n - * @param *what Number - * @brief Key - * @return Boolean \n TRUE if key was pulled, otherwise FALSE. - * @return *what Number \n the key pulled. - * @note - * This functions starts from an index, which may not be at the start of the - * array. - * @note (see file util.c) - */ -extern bool repeat_pull(int *what = 0); - -/** @fn repeat_check(void) - * @brief Check if the last command is repeated. - * @note - * Ignore certain commands: ESC, space, newline.\n - * 'n' repeats the last command (index is set to 0).\n - * Other commands reset the repeat array (index and count are set to 0). - * @note (see file util.c) - */ -extern void repeat_check(void); - -/** @fn get_count(int number, int max) - * @brief Allow the user to select multiple items without pressing '0'.\n - * @param number Number \n the default number. - * @brief Default - * @param max Number \n the maximum value allowed. - * @brief Maximum - * The user is prompted with "How many?" - * @note (see file util.c) - */ -extern void get_count(int number, int max); - -/** @name Feature Flags - * @{ - */ -/** @def FF1_NO_WALK */ -#define FF1_NO_WALK 0x00000001L - -/** @def FF1_NO_VISION */ -#define FF1_NO_VISION 0x00000002L - -/** @def FF1_CAN_LEVITATE */ -#define FF1_CAN_LEVITATE 0x00000004L - -/** @def FF1_CAN_PASS */ -#define FF1_CAN_PASS 0x00000008L - -/** @def FF1_FLOOR */ -#define FF1_FLOOR 0x00000010L - -/** @def FF1_WALL */ -#define FF1_WALL 0x00000020L - -/** @def FF1_PERMANENT */ -#define FF1_PERMANENT 0x00000040L - -/** @def FF1_CAN_FLY */ -#define FF1_CAN_FLY 0x00000080L - -/** @def FF1_REMEMBER */ -#define FF1_REMEMBER 0x00000100L - -/** @def FF1_NOTICE */ -#define FF1_NOTICE 0x00000200L - -/** @def FF1_DONT_NOTICE_RUNNING */ -#define FF1_DONT_NOTICE_RUNNING 0x00000400L - -/** @def FF1_CAN_RUN */ -#define FF1_CAN_RUN 0x00000800L - -/** @def FF1_DOOR */ -#define FF1_DOOR 0x00001000L - -/** @def FF1_SUPPORT_LIGHT */ -#define FF1_SUPPORT_LIGHT 0x00002000L - -/** @def FF1_CAN_CLIMB */ -#define FF1_CAN_CLIMB 0x00004000L - -/** @def FF1_TUNNELABLE */ -#define FF1_TUNNELABLE 0x00008000L - -/** @def FF1_WEB */ -#define FF1_WEB 0x00010000L - -/** @def FF1_ATTR_MULTI */ -#define FF1_ATTR_MULTI 0x00020000L - -/** @def FF1_SUPPORT_GROWTH */ -#define FF1_SUPPORT_GROWTH 0x00040000L -/** @} */ - - -/* Cave stuff */ -/** @struct cave_type - */ -struct cave_type -{ - /** @structvar info - * @brief Number - * @note Hack -- cave flags - */ - u16b info; - - /** @structvar feat - * @brief Number - * @note Hack -- feature type - */ - byte feat; - - /** @structvar o_idx - * @brief Number - * @note Object in this grid - */ - s16b o_idx; - - /** @structvar m_idx - * @brief Number - * @note Monster in this grid - */ - s16b m_idx; - - /** @structvar t_idx - * @brief Number - * @note trap index (in t_list) or zero - */ - s16b t_idx; - - /** @structvar special - * @brief Number - */ - s16b special; - /** @structvar special2 - * @brief Number - * @note Special cave info - */ - s16b special2; - - /** @structvar inscription - * @brief Number - * @note Inscription of the grid - */ - s16b inscription; - - /** @structvar mana - * @brief Number - * @note Magical energy of the grid - */ - byte mana; - - /** @structvar mimic - * @brief Number - * @note Feature to mimic - */ - byte mimic; - - /** @structvar effect - * @brief Number - * @note The lasting effects - */ - s16b effect; -}; - -/** @var ANGBAND_SYS - * @brief String - * @note - * Hack -- The special Angband "System Suffix"\n - * This variable is used to choose an appropriate "pref-xxx" file - */ -extern cptr ANGBAND_SYS; - -/** @var ANGBAND_KEYBOARD - * @brief String - * @note - * Hack -- The special Angband "Keyboard Suffix"\n - * This variable is used to choose an appropriate macro-trigger definition - */ -extern cptr ANGBAND_KEYBOARD; - -/** @var ANGBAND_GRAF - * @brief String - * @note - * Hack -- The special Angband "Graphics Suffix"\n - * This variable is used to choose an appropriate "graf-xxx" file - */ -extern cptr ANGBAND_GRAF; - -/** @var ANGBAND_DIR - * @brief String - * @note - * Path name: The main "lib" directory\n - * This variable is not actually used anywhere in the code - */ -extern cptr ANGBAND_DIR; - -/** @var ANGBAND_DIR_APEX - * @brief String - * @note - * High score files (binary)\n - * These files may be portable between platforms - */ -extern cptr ANGBAND_DIR_APEX; - -/** @var ANGBAND_DIR_CORE - * @brief String - * @note - * Core lua system\n - * These files are portable between platforms - */ -extern cptr ANGBAND_DIR_CORE; - -/** @var ANGBAND_DIR_DNGN - * @brief String - * @note - * Textual dungeon level definition files\n - * These files are portable between platforms - */ -extern cptr ANGBAND_DIR_DNGN; - -/** @var ANGBAND_DIR_DATA - * @brief String - * @note - * Binary image files for the "*_info" arrays (binary)\n - * These files are not portable between platforms - */ -extern cptr ANGBAND_DIR_DATA; - -/** @var ANGBAND_DIR_EDIT - * @brief String - * @note - * Textual template files for the "*_info" arrays (ascii)\n - * These files are portable between platforms - */ -extern cptr ANGBAND_DIR_EDIT; - -/** @var ANGBAND_DIR_FILE - * @brief String - * @note - * Various extra files (ascii)\n - * These files may be portable between platforms - */ -extern cptr ANGBAND_DIR_FILE; - -/** @var ANGBAND_DIR_HELP - * @brief String - * @note - * Help files (normal) for the online help (ascii)\n - * These files are portable between platforms - */ -extern cptr ANGBAND_DIR_HELP; - -/** @var ANGBAND_DIR_INFO - * @brief String - * @note - * Help files (spoilers) for the online help (ascii)\n - * These files are portable between platforms - */ -extern cptr ANGBAND_DIR_INFO; - -/** @var ANGBAND_DIR_MODULES - * @brief String - * @note - * Modules, those subdirectories are half-mirrors of lib/ - */ -extern cptr ANGBAND_DIR_MODULES; - -/** @var ANGBAND_DIR_NOTE - * @brief String - * @note - * Textual template files for the plot files (ascii)\n - * These files are portable between platforms - */ -extern cptr ANGBAND_DIR_NOTE; - -/** @var ANGBAND_DIR_SAVE - * @brief String - * @note - * Savefiles for current characters (binary)\n - * These files are portable between platforms - */ -extern cptr ANGBAND_DIR_SAVE; - -/** @var ANGBAND_DIR_SCPT - * @brief String - * @note - * Scripts.\n - * These files are portable between platforms - */ -extern cptr ANGBAND_DIR_SCPT; - -/** @var ANGBAND_DIR_PREF - * @brief String - * @note - * Default "preference" files (ascii)\n - * These files are rarely portable between platforms - */ -extern cptr ANGBAND_DIR_PREF; - -/** @var ANGBAND_DIR_PATCH - * @brief String - * @note - * Patches, contains one subdir per patch with a patch.lua file - * in it and a patch_init() function in it - */ -extern cptr ANGBAND_DIR_PATCH; - -/** @var ANGBAND_DIR_USER - * @brief String - * @note - * User "preference" files (ascii)\n - * These files are rarely portable between platforms - */ -extern cptr ANGBAND_DIR_USER; - -/** @var ANGBAND_DIR_XTRA - * @brief String - * @note - * Various extra files (binary)\n - * These files are rarely portable between platforms - */ -extern cptr ANGBAND_DIR_XTRA; - -/** @var ANGBAND_DIR_CMOV - * @brief String - * @note - * Cmovie files of entire games (ascii)\n - * Apart from possible newline things, likely portable btw platforms - */ -extern cptr ANGBAND_DIR_CMOV; - - -/** @fn los(int y1, int x1, int y2, int x2) - * @brief Determine if a line of sight can be traced from (x1,y1) to (x2,y2).\n - * @param y1 Number \n y-coordinate of the origin. - * @brief Origin y-coordinate - * @param x1 Number \n x-coordinate of the origin. - * @brief Origin x-coordinate - * @param y2 Number \n y-coordinate of the target. - * @brief Target y-coordinate - * @param x2 Number \n x-coordinate of the target. - * @brief Target x-coordinate - * @return Boolean \n TRUE if origin has line of sight to target, otherwise - * FALSE. - * @note - * A simple, fast, integer-based line-of-sight algorithm. By Joseph Hall, - * 4116 Brewster Drive, Raleigh NC 27606. Email to jnh@ecemwl.ncsu.edu.\n\n - * Returns TRUE if a line of sight can be traced from (x1,y1) to (x2,y2).\n\n - * The LOS begins at the center of the tile (x1,y1) and ends at the center of - * the tile (x2,y2). If los() is to return TRUE, all of the tiles this line - * passes through must be floor tiles, except for (x1,y1) and (x2,y2).\n\n - * We assume that the "mathematical corner" of a non-floor tile does not - * block line of sight.\n\n - * Because this function uses (short) ints for all calculations, overflow may - * occur if dx and dy exceed 90.\n\n - * Once all the degenerate cases are eliminated, the values "qx", "qy", and - * "m" are multiplied by a scale factor "f1 = abs(dx * dy * 2)", so that - * we can use integer arithmetic.\n\n - * We travel from start to finish along the longer axis, starting at the border - * between the first and second tiles, where the y offset = .5 * slope, taking - * into account the scale factor. See below.\n\n - * Also note that this function and the "move towards target" code do NOT - * share the same properties. Thus, you can see someone, target them, and - * then fire a bolt at them, but the bolt may hit a wall, not them. However, - * by clever choice of target locations, you can sometimes throw a "curve".\n\n - * Note that "line of sight" is not "reflexive" in all cases.\n\n - * Use the "projectable()" routine to test "spell/missile line of sight".\n\n* - * Use the "update_view()" function to determine player line-of-sight.\n\n - * @note (see file cave.c) - */ -extern bool los(int y1, int x1, int y2, int x2); -$static bool lua_cave_is(cave_type *c_ptr, s32b flag) { return (f_info[c_ptr->feat].flags1 & flag) ? TRUE : FALSE; } - -/** @fn cave_is(cave_type *c_ptr, s32b flag); - * @brief Determine if cave "c_ptr" has feature "flag".\n - * @param *c_ptr cave_type \n the cave. - * @brief Cave - * @param flag Number \n the required feature flag. - * @brief Feature - * @return Boolean \n TRUE if the cave features include "flag", otherwise - * FALSE. - * @note (see file w_util.c) - */ -static bool lua_cave_is @ cave_is(cave_type *c_ptr, s32b flag); - -/** @fn cave(int y, int x); - * @brief Return the type of cave at grid coordinate (x,y).\n - * @param y Number \n y-coordinate of grid. - * @brief Y-coordinate - * @param x Number \n x-coordinate of grid. - * @brief X-coordinate - * @return cave_type \n The type of cave at grid coordinate (x,y). - * @note (see file lua_bind.c) - */ -extern cave_type *lua_get_cave @ cave(int y, int x); - -/** @fn set_target(int y, int x) - * @brief Set grid coordinate (x,y) as the target grid.\n - * @param y Number \n y-coordinate of grid. - * @brief Y-coordinate - * @param x Number \n x-coordinate of grid. - * @brief X-coordinate - * @note (see file lua_bind.c) - */ -extern void set_target(int y, int x); - -/** @fn get_target(int dir, int *y = 0, int *x = 0) - * @brief Get a target based on direction "dir" from the player.\n - * @param dir Number \n dir must be a value from 0 to 9. - * @brief Direction - * @param *y Number - * @brief Target y-coordinate - * @param *x Number - * @brief Target x-coordinate - * @return *y Number \n The y-coordinate of the target. - * @return *x Number \n The x-coordinate of the target. - * @note - * The target is actually 100 grids away in direction "dir". If "dir" is 5, - * the actual target, if one is set, is returned. - * @note (see file lua_bind.c) - */ -extern void get_target(int dir, int *y = 0, int *x = 0); - -/** @var m_allow_special[max_r_idx] - * @brief Boolean - * @note "Special gene" flags for monsters - */ -extern bool m_allow_special[max_r_idx]; - -/** @var k_allow_special[max_k_idx] - * @brief Boolean - * @note "Special gene" flags for objects - */ -extern bool k_allow_special[max_k_idx]; - -/** @var a_allow_special[max_a_idx] - * @brief Boolean - * @note "Special gene" flags for artifacts - */ -extern bool a_allow_special[max_a_idx]; - -/** @fn cave_set_feat(int y, int x, int feat) - * @brief Change the "feat" flag for a grid, and notice/redraw the grid - * @param y Number \n y-coordinate of grid. - * @brief Y-coordinate - * @param x Number \n x-coordinate of grid. - * @brief X-coordinate - * @param feat Number \n new set of feature flags. - * @brief Features - * @note (see file cave.c) - */ -extern void cave_set_feat(int y, int x, int feat); - -/** @fn show_file(cptr name, cptr what, int line, int mode) - * @brief Show a help file.\n - * @param name String \n name of the help file. - * @brief Filename - * @param what String \n hyperlink caption. - * @brief Caption - * @param line Number \n the line number from where to start the display of - * the file. - * @brief Starting line - * @param mode Number \n *unused* - * @brief *Unused* - * @return Boolean \n TRUE if file was shown successfully, otherwise FALSE.\n - * @note - * If the file is not found, the function will search the help, info, and file - * directories for the file. If it is still not found, a message is displayed - * and the function returns FALSE.\n\n - * The file is parsed once to extract colour, tag, and hyperlink - * information.\n\n - * The file is parse again to show it on the screen. - * @note (see file files.c) - */ -extern bool show_file(cptr name, cptr what, int line, int mode); - -/** @var target_who - * @brief Number - * @note - * If this is -1, the target is the player.\n - * If this is 0, there is no target.\n - * If this is >0, the target is the monster m_idx[target_who]. - */ -extern s16b target_who; - -/** @var target_col - * @brief Number - * @note The column of the target grid - */ -extern s16b target_col; - -/** @var target_row - * @brief Number - * @note The row of the target grid - */ -extern s16b target_row; - -/** @var max_bact - * @brief Number - * @note Maximum building actions - */ -extern int max_bact; - -/** @var ddd[9] - * @brief Number - * @note Global array for looping through the "keypad directions" - */ -extern s16b ddd[9]; - -/** @var ddx[10] - * @brief Number - * @note Global array for converting "keypad direction" into x offsets - */ -extern s16b ddx[10]; - -/** @var ddy[10] - * @brief Number - * @note Global array for converting "keypad direction" into y offsets - */ -extern s16b ddy[10]; - -/** @var ddx_ddd[9] - * @brief Number - * @note Global array for optimizing "ddx[ddd[i]]" - */ -extern s16b ddx_ddd[9]; - -/** @var ddy_ddd[9] - * @brief Number - * @note Global array for optimizing "ddy[ddd[i]]" - */ -extern s16b ddy_ddd[9]; - - -/* Gen stuff */ - -/** @fn load_map(char *name, int *y = 2, int *x = 2) - * @brief Load the map in file "name".\n - * @param *name String \n the name of the map file. - * @brief Map - * @param *y Number - * @brief Maximum y-coordinate - * @param *x Number - * @brief Maximum x-coordinate - * @return *y Number \n The maximum y-coordinate of the map. - * @return *x Number \n The maximum x-coordinate of the map. - * @note - * The map is loaded and the player is placed at the starting position. - * @note (see file lua_bind.c) - */ -extern void load_map(char *name, int *y = 2, int *x = 2); - -/** @fn alloc_room(int by0, int bx0, int ysize, int xsize, int *y1 = 0, int *x1 = 0, int *y2 = 0, int *x2 = 0) - * @brief Allocate the space needed by a room in the room_map array.\n - * @param by0 Number \n the y-coordinate of the block to contain the room. - * @brief Block y-coordinate - * @param bx0 Number \n the x-coordinate of the block to contain the room. - * @brief Block x-coordinate - * @param ysize Number \n the vertical size (height) of the room. - * @brief Room height - * @param xsize Number \n the horizontal size (width) of the room. - * @brief Room width - * @param *y1 Number - * @brief Top-right y-coordinate - * @param *x1 Number - * @brief Top-right x-coordinate - * @param *y2 Number - * @brief Bottom-left y-coordinate - * @param *x2 Number - * @brief Bottom-right x-coordinate - * @return Boolean \n TRUE if the room was allocated successfully, otherwise - * FALSE. - * @return *y1 Number \n The y-coordinate of the top left corner. - * @return *x1 Number \n The x-coordinate of the top left corner. - * @return *y2 Number \n The y-coordinate of the bottom right corner. - * @return *x2 Number \n The x-coordinate of the bottom right corner. - * @note - * Dungeon generation is not something to be messed around with unless you - * really, really, really know what you are doing (or you are DarkGod). - * @note (see file lua_bind.c, generate.c) - */ -extern bool alloc_room(int by0, int bx0, int ysize, int xsize, int *y1 = 0, int *x1 = 0, int *y2 = 0, int *x2 = 0); - -/* Misc stuff */ -/** @fn input_box(cptr title, int max); - * @brief Create an input box and ask the user a question.\n - * @param title String \n the title of the box, which should take the form of - * a question. For example, "New name?". - * @brief Title - * @param max Number \n the maximum length of the response. - * @brief Maximum response length - * @return String \n The answer to the question. - * @note - * The input box is placed in the middle of the screen. The default reponse is - * blank, and can be up to 79 characters long. - * @note (see file lua_bind.c, util.c) - */ -extern char *lua_input_box@input_box(cptr title, int max); - -/** @fn msg_box(cptr title); - * @brief Create a msg box and ask a question.\n - * @param title String \n the question. - * @brief Question - * @return String \n The answer. - * @note - * The message box is placed in the middle of the screen. The answer is a - * single character / key press. - * @note (see file lua_bind.c, util.c) - */ -extern char lua_msg_box@msg_box(cptr title); - -/** @fn rescale(s32b x, s32b max, s32b new_max) - * @brief Rescale value "x".\n - * @param x Number \n the original value. - * @brief Value - * @param max Number \n the original maximum that value could have. - * @brief Original maximum - * @param new_max Number \n the new maximum that value can have. - * @brief New maximum - * @return Number \n The rescaled value of "x". - * @note - * There is no error checking here. Please don't set "max" to zero. - * @note (see file util.c) - */ -extern s32b rescale(s32b x, s32b max, s32b new_max); -$static const char *player_name_lua(void){return (const char *)player_name;} - -/** @fn player_name() - * @brief Return the player's name. - * @return String \n The player's name. - * @note (see file w_util.c) - */ -const char *player_name_lua@player_name(); - -/* Quarks */ -/** @fn quark_str(s16b num) - * @brief Return a quark (inscription) from the quark array.\n - * @param num Number \n the index to the quark string array. If this is less - * than zero or more than the maximum number of quarks, it is treated as zero. - * @brief Quark index - * @return String \n The quark. - * @note - * We use a global array for all inscriptions to reduce the memory - * spent maintaining inscriptions. Of course, it is still possible - * to run out of inscription memory, especially if too many different - * inscriptions are used, but hopefully this will be rare.\n\n - * We use dynamic string allocation because otherwise it is necessary - * to pre-guess the amount of quark activity. We limit the total - * number of quarks, but this is much easier to "expand" as needed.\n\n - * Any two items with the same inscription will have the same "quark" - * index, which should greatly reduce the need for inscription space.\n\n - * Note that "quark zero" is NULL and should not be "dereferenced". - * @note (see file util.c) - */ -extern cptr quark_str(s16b num); - -/** @fn quark_add(cptr str) - * @brief Add a quark (inscription) to the quark array.\n - * @param str String \n the quark to add to the array. - * @brief Quark - * @return Number \n The index to the quark array for this quark - * @note - * The array is searched to see if the quark already exists. If so, the index - * to the existing quark is returned.\n - * If there is no room, 0 (NULL reference) is returned. - * @note (see file util.c) - */ -extern s16b quark_add(cptr str); - -/* Modules */ -/** @fn module_reset_dir(cptr dir, cptr new_path) - * @brief Redirect one of the ToME directories.\n - * @param dir String \n the name of the directory (not the full path). - * @brief Directory - * @param new_path String \n the new path of "dir" under ANGBAND_DIR_MODULES.\n - * @brief New path - * @note (see file modules.c) - */ -extern void module_reset_dir(cptr dir, cptr new_path); - -/** @fn scansubdir(cptr dir) - * @brief Scan sub-directory "dir".\n - * @param dir String \n the sub-directory to scan. - * @brief Directory - * @note - * Nicer wrapper around TERM_XTRA_SCANSUBDIR\n\n - * This function sets scansubdir_dir and calls the SCANSUBDIR terminal hook. - * @note (see file util.c) - */ -extern void scansubdir(cptr dir); - -/** @fn file_exist(char *buf) - * @brief Check if file "buf" exists.\n - * @param *buf String \n the file to be tested. - * @brief Filename - * @return Boolean \n TRUE if the file exists, otherwise FALSE. - * @note (see file loadsave.c) - */ -extern bool file_exist(char *buf); - -/** @var game_module - * @brief String - * @note The name of the current game module - */ -extern cptr game_module; - -/* Input */ -/** @fn get_keymap_dir(char ch) - * @brief Get a direction from the keyboard according to the keymap.\n - * @param ch String \n the character representing a direction. - * @brief Direction - * @return Number \n The direction represented by "ch". It will be in the - * range 0 to 9. - * @note - * If "ch" is a number, the number is used. Otherwise the direction is - * chosen from the Original or Rogue keymaps.\n - * If the direction is 5, it is set to 0. - * @note (see file util.c) - */ -extern int get_keymap_dir(char ch); - -extern errr file_character(cptr name, bool full); -extern void calc_bonuses(bool silent); - -extern void note_spot(int y, int x); -extern void lite_spot(int y, int x); - -/** - * Mimicry - */ -extern s16b resolve_mimic_name(cptr name); - -/** - * Timers - */ -void timer_aggravate_evil_enable(); - -/** - * Initialize bookable spells. - */ -void initialize_bookable_spells(); diff --git a/src/wizard2.c b/src/wizard2.c index e2683435..f6ce41af 100644 --- a/src/wizard2.c +++ b/src/wizard2.c @@ -184,43 +184,6 @@ static void wiz_create_named_art() msg_print("Allocated."); } -/* - * Hack -- quick debugging hook - */ -void do_cmd_wiz_hack_ben(int num) -{ - s32b a; - - /* MAKE(r_ptr, monster_race); - COPY(r_ptr, &r_info[500], monster_race); - - r_ptr->level = 1; - r_ptr->flags6 |= RF6_BLINK; - r_ptr->freq_inate = r_ptr->freq_spell = 90; - - place_monster_one_race = r_ptr; - place_monster_one(p_ptr->py - 1, p_ptr->px, 500, 0, TRUE, MSTATUS_PET);*/ - - get_lua_var("a", 'd', &a); - msg_format("a: %d", a); - - /* Success */ - return; -} - -void do_cmd_lua_script() -{ - char script[80] = "tome_dofile_anywhere(ANGBAND_DIR_CORE, 'gen_idx.lua')"; - - if (!get_string("Script:", script, 80)) return; - - exec_lua(script); - - /* Success */ - return; -} - - #ifdef MONSTER_HORDES /* Summon a horde of monsters */ @@ -1909,11 +1872,6 @@ void do_cmd_debug(void) do_cmd_wiz_zap(); break; - /* Hack -- whatever I desire */ - case '_': - do_cmd_wiz_hack_ben(command_arg); - break; - /* Mimic shape changing */ case '*': p_ptr->tim_mimic = 100; @@ -1954,10 +1912,6 @@ void do_cmd_debug(void) summon_specific(p_ptr->py, p_ptr->px, max_dlv[dungeon_type], command_arg); break; - case '>': - do_cmd_lua_script(); - break; - /* Not a Wizard Command */ default: if (!process_hooks(HOOK_DEBUG_COMMAND, "(d)", cmd)) diff --git a/src/z_pack.pkg b/src/z_pack.pkg deleted file mode 100644 index 5a46b3b2..00000000 --- a/src/z_pack.pkg +++ /dev/null @@ -1,398 +0,0 @@ -/* File: z_pack.pkg */ - -/* - * Purpose: Lua interface defitions for z-*.c - * To be processed by tolua to generate C source code. - */ - -$#include "angband.h" - -/** @typedef cptr - * @note String - */ -typedef char* cptr; -/** @typedef errr - * @note Number - */ -typedef int errr; -/** @typedef bool - * @note Boolean - */ -typedef unsigned char bool; -/** @typedef byte - * @note Number - */ -typedef unsigned char byte; -/** @typedef s16b - * @note Number - */ -typedef signed short s16b; -/** @typedef u16b - * @note Number - */ -typedef unsigned short u16b; -/** @typedef s32b - * @note Number - */ -typedef signed int s32b; -/** @typedef u32b - * @note Number - */ -typedef unsigned int u32b; - -/** @name Terminal actions - * @{ */ -/** @def TERM_XTRA_EVENT - * @note Process some pending events - */ -#define TERM_XTRA_EVENT 1 -/** @def TERM_XTRA_FLUSH - * @note Flush all pending events - */ -#define TERM_XTRA_FLUSH 2 -/** @def TERM_XTRA_CLEAR - * @note Clear the entire window - */ -#define TERM_XTRA_CLEAR 3 -/** @def TERM_XTRA_SHAPE - * @note Set cursor shape (optional) - */ -#define TERM_XTRA_SHAPE 4 -/** @def TERM_XTRA_FROSH - * @note Flush one row (optional) - */ -#define TERM_XTRA_FROSH 5 -/** @def TERM_XTRA_FRESH - * @note Flush all rows (optional) - */ -#define TERM_XTRA_FRESH 6 -/** @def TERM_XTRA_NOISE - * @note Make a noise (optional) - */ -#define TERM_XTRA_NOISE 7 -/** @def TERM_XTRA_SOUND - * @note Make a sound (optional) - */ -#define TERM_XTRA_SOUND 8 -/** @def TERM_XTRA_BORED - * @note Handle stuff when bored (optional) - */ -#define TERM_XTRA_BORED 9 -/** @def TERM_XTRA_REACT - * @note React to global changes (optional) - */ -#define TERM_XTRA_REACT 10 -/** @def TERM_XTRA_ALIVE - * @note Change the "hard" level (optional) - */ -#define TERM_XTRA_ALIVE 11 -/** @def TERM_XTRA_LEVEL - * @note Change the "soft" level (optional) - */ -#define TERM_XTRA_LEVEL 12 -/** @def TERM_XTRA_DELAY - * @note Delay some milliseconds (optional) - */ -#define TERM_XTRA_DELAY 13 -/** @def TERM_XTRA_GET_DELAY - * @note Get the cuyrrent time in milliseconds (optional) - */ -#define TERM_XTRA_GET_DELAY 14 -/** @def TERM_XTRA_SCANSUBDIR - * @note Scan for subdir in a dir - */ -#define TERM_XTRA_SCANSUBDIR 15 -/** @} */ - -/** @var Term_xtra_long - * @brief Number - */ -extern long Term_xtra_long; - -/** @var scansubdir_dir[1024] - * @brief String - * @note The directory which is scanned for sub-directories. - */ -char scansubdir_dir[1024]; - -/** @var scansubdir_max - * @brief Number - * @note The number of entries in the scansubdir_result array. - */ -int scansubdir_max; - -/** @var scansubdir_result[scansubdir_max] - * @brief String - * @note The sub-directories of scansubdir_dir directory. - */ -cptr scansubdir_result[scansubdir_max]; - -/** @fn Term_xtra(int n, int v) - * @brief Generic function to perform system dependant terminal actions.\n - * @param n Number \n a terminal action (see TERM_XTRA fields). - * @brief Terminal action - * @param v Number \n variable depending on the terminal action. - * @brief Variable - * @return Number \n Result of the terminal action. - * @note - * The "Term->xtra_hook" hook provides a variety of different functions, - * based on the first parameter (which should be taken from the various - * TERM_XTRA_* defines) and the second parameter (which may make sense - * only for some first parameters). It is available to the program via - * the "Term_xtra()" function, though some first parameters are only - * "legal" when called from inside this package. - * @note (see file z-term.c) - */ -extern errr Term_xtra(int n, int v); - -/** @fn Term_set_cursor(int v) - * @brief Set the cursor visibility.\n - * @param v Number \n v is the visibility. - * @brief Visibility - * @return Number \n 1 if visibility was unchanged, otherwise 0. - * @note - * Cursor visibility (field "cv") is defined as a boolean, so take care what - * value is assigned to "v". - * @note (see file z-term.c) - */ -extern errr Term_set_cursor(int v); - -/** @fn Term_gotoxy(int x, int y) - * @brief Place the cursor at a given location.\n - * @param x Number \n x-coordinate of target location. - * @brief X-coordinate - * @param y Number \n y-coordinate of target location. - * @brief Y-coordinate - * @return Number \n -1 if cursor could not be placed at given location, - * otherwise 0. - * @note - * Note -- "illegal" requests do not move the cursor.\n\n - * The cursor is flagged as useful if it placed okay. - * @note (see file z-term.c) - */ -extern errr Term_gotoxy(int x, int y); - -/** @fn Term_putch(int x, int y, byte a, char c) - * @brief Move to a location and, using an attr, add a char.\n - * @param x Number \n x-coordinate of target location. - * @brief X-coordinate - * @param y Number \n y-coordinate of target location. - * @brief Y-coordinate - * @param a Number \n attribute of character. - * @brief Attribute - * @param c String \n the character. - * @brief Character - * @return Number \n <0 if error, 0 if success, 1 if success but cursor is - * useless. - * @note - * We return "-2" if the character is "illegal". XXX XXX\n\n - * We return "-1" if the cursor is currently unusable.\n\n - * We queue the given attr/char for display at the current - * cursor location, and advance the cursor to the right, - * marking it as unuable and returning "1" if it leaves - * the screen, and otherwise returning "0".\n\n - * So when this function returns a positive value, future calls to this - * function will return negative ones. - * @note (see file z-term.c) - */ -extern errr Term_putch(int x, int y, byte a, char c); - -/** @fn Term_putstr(int x, int y, int n, byte a, cptr s) - * @brief Move to a location and, using an attr, add a string.\n - * @param x Number \n x-coordinate of target location. - * @brief X-coordinate - * @param y Number \n y-coordinate of target location. - * @brief Y-coordinate - * @param n Number \n length of string. - * @brief Length - * @param a Number \n attribute of string. - * @brief Attribute - * @param s String \n the string. - * @brief String - * @return Number \n <0 if error, 0 if success, 1 if success but cursor is - * useless. - * @note - * For length "n", using negative values to imply the largest possible value, - * and then we use the minimum of this length and the "actual" length of the - * string as the actual number of characters to attempt to display, never - * displaying more characters than will actually fit, since we do NOT attempt - * to "wrap" the cursor at the screen edge.\n\n - * We return "-1" if the cursor is currently unusable.\n - * We return "N" if we were "only" able to write "N" chars, even if all of the - * given characters fit on the screen, and mark the cursor as unusable for - * future attempts.\n\n - * So when this function, returns a positive value, future calls to this - * function will return negative ones. - * @note (see file z-term.c) - */ -extern errr Term_putstr(int x, int y, int n, byte a, cptr s); - -/** @fn Term_clear(void) - * @brief Clear the entire window, and move to the top left corner. - * @return Number \n 0 (always). - * @note - * Note the use of the special "total_erase" code - * @note (see file z-term.c) - */ -extern errr Term_clear(void); - -/** @fn Term_redraw(void) - * @brief Redraw (and refresh) the whole window. - * @return Number \n 0 (always). - * @note (see file z-term.c) - */ -extern errr Term_redraw(void); - -/** @fn Term_redraw_section(int x1, int y1, int x2, int y2) - * @brief Redraw part of a window.\n - * @param x1 Number \n x-coordinate of top-left location. - * @brief X-coordinate (top left) - * @param y1 Number \n y-coordinate of top-left location. - * @brief Y-coordinate (top left) - * @param x2 Number \n x-coordinate of bottom-right location. - * @brief X-coordinate (bottom right) - * @param y2 Number \n y-coordinate of bottom-right location. - * @brief Y-coordinate (bottom right) - * @return Number \n 0 (always). - * @note (see file z-term.c) - */ -extern errr Term_redraw_section(int x1, int y1, int x2, int y2); - -/** @fn Term_get_size(int *w, int *h) - * @brief Extract the current window size.\n - * @param *w Number - * @brief Screen width - * @param *h Number - * @brief Screen height - * @return Number \n 0 (always). - * @return *w Number \n The width of the screen (in characters). - * @return *h Number \n The height of the screen (in characters). - * @note (see file z-term.c) - */ -extern errr Term_get_size(int *w, int *h); - -/* - * random numbers - */ -$static s32b lua_rand_int(s32b m) {return rand_int(m);} - -/** @fn rand_int(s32b m); - * @brief Generate a random integer between 0 and (m - 1).\n - * @param m Number \n maximum value of random integer. The random integer - * will be less than "m". - * @brief Maximum - * @return Number \n The random number. - * @note (see file w_z_pack.c) - */ -static s32b lua_rand_int @ rand_int(s32b m); - -/* - * Generates a random long integer X where A<=X<=B - * The integer X falls along a uniform distribution. - * Note: rand_range(0,N-1) == rand_int(N) - */ -$static s32b lua_rand_range(s32b A, s32b B) {return ((A) + (rand_int(1+(B)-(A))));} - -/** @fn rand_range(s32b A, s32b B); - * @brief Generate a random integer between A and B inclusive.\n - * @param A Number \n minimum number. - * @brief Minimum - * @param B Number \n maximum number. - * @brief Maximum - * @return Number \n The random number. - * @note (see file w_z_pack.c) - */ -static s32b lua_rand_range @ rand_range(s32b A, s32b B); - -/* - * Generate a random long integer X where A-D<=X<=A+D - * The integer X falls along a uniform distribution. - * Note: rand_spread(A,D) == rand_range(A-D,A+D) - */ -$static s32b lua_rand_spread(s32b A, s32b D) {return ((A) + (rand_int(1+(D)+(D))) - (D));} - -/** @fn rand_spread(s32b A, s32b D); - * @brief Generate a radom integer between A-D and A+D inclusive.\n - * @param A Number \n average number. - * @brief Average - * @param D Number \n deviation from average. - * @brief Deviation - * @return Number \n The random number. - * @note (see file w_z_pack.c) - */ -static s32b lua_rand_spread @ rand_spread(s32b A, s32b D); - - -/* - * Generate a random long integer X where 1<=X<=M - * Also, "correctly" handle the case of M<=1 - */ -$static s32b lua_randint(s32b m) {return rand_int(m) + 1;} - -/** @fn randint(s32b m); - * @brief Generate a random integer between 1 and M inclusive.\n - * @param m Number \n maximum value of random integer. - * @brief Maximum - * @return Number \n The random number. - * @note (see file w_z_pack.c) - */ -static s32b lua_randint @ randint(s32b m); - - -/* - * Evaluate to TRUE "P" percent of the time - */ -$static bool lua_magik(s32b P) {return (rand_int(100) < (P));} - -/** @fn magik(s32b P); - * @brief Return TRUE "P" % of the time. - * @param P Number \n percent chance the function returns TRUE. - * @brief Percent true - * @return Boolean \n TRUE if a random number from 0 to 99 is less than P, - * otherwise FALSE. - * @note (see file w_z_pack.c) - */ -static bool lua_magik @ magik(s32b P); - - -/**** Available Variables ****/ -/** @var Rand_quick - * @brief Boolean - * @note - * If this is TRUE, then use the "simple" Random Number Generator.\n - * If this is FALSE, then use the "complex" Random Number Generator. - */ -extern bool Rand_quick; - -/** @var Rand_value - * @brief Number - * @note - * The current value (seed) of the simple Random Number Generator. - */ -extern u32b Rand_value; - -/**** Available Functions ****/ -/** @fn damroll(int num, int sides) - * @brief Generates damage for "2d6" style dice rolls.\n - * @param num Number \n the number of "dice" used. - * @brief Number - * @param sides Number \n the number of sides on each "die". - * @brief Sides - * @return Number \n The random number. - * @note - * The function simulates the rolling of "num" "sides"-sided dice. Each die - * will result in a random number from 1 to "sides". - * @note (see file z-rand.c) - */ -extern s16b damroll(int num, int sides); - -/** @fn maxroll(int num, int sides) - * @brief Generate the maximum damage for "num" dice with "sides" sides each. - * @param num Number \n The number of "dice" used. - * @brief Number - * @param sides Number \n The number of sides on each "die". - * @brief Sides - * @return Number \n "num" * "sides". - * @note (see file z-rand.c) - */ -extern s16b maxroll(int num, int sides); -- cgit v1.2.3 From 4b66522b1f625592e691de4917ee5616ea4c0324 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 19 Jun 2012 18:32:22 +0200 Subject: Lua: Fix up installation to include Theme. --- lib/CMakeLists.txt | 9 ++------- lib/mods/CMakeLists.txt | 1 + lib/mods/theme/CMakeLists.txt | 14 ++++++++++++++ 3 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 lib/mods/CMakeLists.txt create mode 100644 lib/mods/theme/CMakeLists.txt diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index f6e7748c..15591830 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -1,7 +1,3 @@ -INSTALL(FILES - module.lua - DESTINATION ${DEFAULT_PATH} -) INSTALL(DIRECTORY apex cmov @@ -11,14 +7,13 @@ INSTALL(DIRECTORY file help info - mods note - plot pref save user xtra DESTINATION ${DEFAULT_PATH} - PATTERN "*.raw" EXCLUDE PATTERN "delete.me" EXCLUDE ) + +ADD_SUBDIRECTORY (mods) diff --git a/lib/mods/CMakeLists.txt b/lib/mods/CMakeLists.txt new file mode 100644 index 00000000..5cce23ea --- /dev/null +++ b/lib/mods/CMakeLists.txt @@ -0,0 +1 @@ +ADD_SUBDIRECTORY(theme) diff --git a/lib/mods/theme/CMakeLists.txt b/lib/mods/theme/CMakeLists.txt new file mode 100644 index 00000000..f1160786 --- /dev/null +++ b/lib/mods/theme/CMakeLists.txt @@ -0,0 +1,14 @@ +INSTALL(DIRECTORY + apex + data + dngn + edit + file + help + note + pref + save + user + DESTINATION ${DEFAULT_PATH}/mods/theme + PATTERN "delete.me" EXCLUDE + ) -- cgit v1.2.3 From 027c9b6900fff8174b0d8cbd30f998f2ac0d64c5 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 19 Jun 2012 22:05:53 +0200 Subject: Lua: Automatizer: Fix silly bug to do with module detection --- src/squeltch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/squeltch.c b/src/squeltch.c index 3b018834..5fb95d75 100644 --- a/src/squeltch.c +++ b/src/squeltch.c @@ -1289,7 +1289,7 @@ static bool_* automatizer_auto_pickup(object_type *o_ptr, int item_idx) static bool_ apply_rule(arule_type *rule, object_type *o_ptr, int item_idx) { /* Check module */ - if (rule->module_idx == game_module_idx) + if (rule->module_idx != game_module_idx) { return FALSE; } -- cgit v1.2.3 From 2b6c56c7520a7d4ddae74067b93e31f28b999357 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 23 Jun 2012 07:29:54 +0200 Subject: Fix 32-bit/64-bit inconsistencies. --- src/externs.h | 2 +- src/spells4.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/externs.h b/src/externs.h index f86014dd..19f43b50 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2379,7 +2379,7 @@ extern bool_ get_com_lua(cptr promtp, int *com); extern s32b lua_get_level(spell_type *spell, s32b lvl, s32b max, s32b min, s32b bonus); extern s32b get_level_device(s32b s, s32b max, s32b min); extern int get_mana(s32b s); -extern int get_power(s32b s); +extern s32b get_power(s32b s); extern s32b spell_chance(s32b s); extern s32b get_level(s32b s, s32b max, s32b min); extern void get_level_school(s32b s, s32b max, s32b min, s32b *level, bool_ *na); diff --git a/src/spells4.c b/src/spells4.c index e58ac4ea..f3809b7b 100644 --- a/src/spells4.c +++ b/src/spells4.c @@ -520,7 +520,7 @@ int print_spell(cptr label_, byte color, int y, s32b s) if (!na) { - sprintf(level_str, "%3d", level); + sprintf(level_str, "%3d", (int) level); } sprintf(buf, "%s%-20s%-16s %s %4d %3d%% %s", @@ -529,7 +529,7 @@ int print_spell(cptr label_, byte color, int y, s32b s) sch_str, level_str, get_mana(s), - spell_chance(s), + (int) spell_chance(s), spell_info); c_prt(color, buf, y, 0); -- cgit v1.2.3 From 721d727a76bfe2facfc9f893f913eaf43ab4ec64 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 25 Jun 2012 06:20:51 +0200 Subject: Remove Lua references from CMakeLists.txt --- src/CMakeLists.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 452ca3e2..b9d6874a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -40,9 +40,8 @@ endif(WIN32) # tome executable INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/lua) ADD_EXECUTABLE(tome ${EXECUTABLE_OPTIONS} ${SRCS}) -TARGET_LINK_LIBRARIES(tome lua ${LIBS}) +TARGET_LINK_LIBRARIES(tome ${LIBS}) # Installation INSTALL(TARGETS tome -- cgit v1.2.3 From 89116d61bd85e472a89062da4815a66b4b96e6b9 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 07:29:06 +0200 Subject: Remove unused variables. --- src/birth.c | 1 - src/dungeon.c | 14 -------------- src/externs.h | 4 ---- src/util.c | 3 --- src/variable.c | 5 ----- 5 files changed, 27 deletions(-) diff --git a/src/birth.c b/src/birth.c index 4734a189..c23e20b8 100644 --- a/src/birth.c +++ b/src/birth.c @@ -1911,7 +1911,6 @@ static bool_ player_birth_aux_ask() /* Extra info */ Term_putstr(5, 16, -1, TERM_WHITE, "Your 'race' determines various intrinsic factors and bonuses."); - hack_corruption = FALSE; /* Dump races */ sel = 0; diff --git a/src/dungeon.c b/src/dungeon.c index d13da812..9bcb6839 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -2271,11 +2271,6 @@ static void process_world(void) (void)set_tim_invis(p_ptr->tim_invis - 1); } - if (multi_rew) - { - multi_rew = FALSE; - } - /* Timed esp */ if (p_ptr->tim_esp) { @@ -4554,13 +4549,6 @@ void process_player(void) /*** Apply energy ***/ - if (hack_corruption) - { - msg_print("You feel different!"); - (void)gain_random_corruption(0); - hack_corruption = FALSE; - } - /* Obtain current speed */ speed_use = p_ptr->pspeed; @@ -5436,8 +5424,6 @@ void play_game(bool_ new_game) bool_ cheat_death = FALSE; - hack_corruption = FALSE; - /* Hack -- Character is "icky" */ character_icky = TRUE; diff --git a/src/externs.h b/src/externs.h index 19f43b50..0a6ebb35 100644 --- a/src/externs.h +++ b/src/externs.h @@ -161,7 +161,6 @@ extern byte graphics_mode; extern u16b total_winner; extern u16b has_won; extern u16b noscore; -extern s16b signal_count; extern bool_ inkey_base; extern bool_ inkey_xtra; extern bool_ inkey_scan; @@ -172,7 +171,6 @@ extern bool_ shimmer_monsters; extern bool_ shimmer_objects; extern bool_ repair_monsters; extern bool_ repair_objects; -extern s16b inven_nxt; extern s16b inven_cnt; extern s16b equip_cnt; extern s16b o_max; @@ -184,10 +182,8 @@ extern s16b hack_m_idx_ii; extern int total_friends; extern s32b total_friend_levels; extern int leaving_quest; -extern bool_ multi_rew; extern char summon_kin_type; extern bool_ hack_mind; -extern bool_ hack_corruption; extern bool_ is_autosave; extern int artifact_bias; extern FILE *text_out_file; diff --git a/src/util.c b/src/util.c index 019ec6da..e73dbce3 100644 --- a/src/util.c +++ b/src/util.c @@ -1929,9 +1929,6 @@ char inkey(void) /* Mega-Hack -- reset saved flag */ character_saved = FALSE; - /* Mega-Hack -- reset signal counter */ - signal_count = 0; - /* Only once */ done = TRUE; } diff --git a/src/variable.c b/src/variable.c index 417fb975..11f0867b 100644 --- a/src/variable.c +++ b/src/variable.c @@ -132,8 +132,6 @@ u16b has_won; /* Semi-Hack -- Game has been won */ u16b noscore; /* Track various "cheating" conditions */ -s16b signal_count; /* Hack -- Count interupts */ - bool_ inkey_base; /* See the "inkey()" function */ bool_ inkey_xtra; /* See the "inkey()" function */ bool_ inkey_scan; /* See the "inkey()" function */ @@ -149,9 +147,7 @@ bool_ shimmer_objects; /* Hack -- optimize multi-hued objects */ bool_ repair_monsters; /* Hack -- optimize detect monsters */ bool_ repair_objects; /* Hack -- optimize detect objects */ -s16b inven_nxt; /* Hack -- unused */ bool_ hack_mind; -bool_ hack_corruption; int artifact_bias; bool_ is_autosave = FALSE; @@ -166,7 +162,6 @@ s16b m_cnt = 0; /* Number of live monsters */ s16b hack_m_idx = 0; /* Hack -- see "process_monsters()" */ s16b hack_m_idx_ii = 0; -bool_ multi_rew = FALSE; char summon_kin_type; /* Hack, by Julian Lighton: summon 'relatives' */ int total_friends = 0; -- cgit v1.2.3 From ae6bee5100bb9ec4e7a3d5fa8538ca3eae38dc58 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 09:04:06 +0200 Subject: messages: Move message_* functions to separate compilation unit --- src/CMakeLists.txt | 2 +- src/birth.c | 2 + src/cmd4.c | 1 + src/defines.h | 17 --- src/externs.h | 14 -- src/init2.c | 13 +- src/loadsave.c | 2 + src/melee2.c | 1 + src/messages.c | 394 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/messages.h | 16 +++ src/plots.c | 3 + src/util.c | 323 +------------------------------------------ src/variable.c | 46 ------- src/xtra1.c | 1 + 14 files changed, 426 insertions(+), 409 deletions(-) create mode 100644 src/messages.c create mode 100644 src/messages.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b9d6874a..22563cd4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,7 +2,7 @@ SET(SRCS main-gcu.c main-x11.c main-xaw.c main-sdl.c main-gtk2.c z-rand.c z-util.c z-form.c z-virt.c z-term.c variable.c tables.c plots.c util.c cave.c dungeon.c - melee1.c melee2.c modules.c + melee1.c melee2.c messages.c modules.c q_god.c object1.c object2.c randart.c squeltch.c traps.c monster1.c monster2.c monster3.c diff --git a/src/birth.c b/src/birth.c index c23e20b8..851e1877 100644 --- a/src/birth.c +++ b/src/birth.c @@ -12,6 +12,8 @@ #include "angband.h" +#include "messages.h" + /* * How often the autoroller will update the display and pause * to check for user interuptions. diff --git a/src/cmd4.c b/src/cmd4.c index 0c1d28a7..e9db67d5 100644 --- a/src/cmd4.c +++ b/src/cmd4.c @@ -12,6 +12,7 @@ #include "angband.h" +#include "messages.h" /* * Hack -- redraw the screen diff --git a/src/defines.h b/src/defines.h index 0b6c4c26..ac74b937 100644 --- a/src/defines.h +++ b/src/defines.h @@ -303,23 +303,6 @@ #define QUARK_MAX 768 /* Was 512... 256 quarks added for random artifacts */ -/* - * OPTION: Maximum number of messages to remember (see "io.c") - * Default: assume maximal memorization of 2048 total messages - */ -#define MESSAGE_MAX 2048 - -#define MESSAGE_NONE 0 -#define MESSAGE_MSG 1 - -/* - * OPTION: Maximum space for the message text buffer (see "io.c") - * Default: assume that each of the 2048 messages is repeated an - * average of three times, and has an average length of 48 - */ -#define MESSAGE_BUF 32768 - - /* * Maximum value storable in a "byte" (hard-coded) */ diff --git a/src/externs.h b/src/externs.h index 0a6ebb35..ea2c4831 100644 --- a/src/externs.h +++ b/src/externs.h @@ -323,15 +323,6 @@ extern bool_ *macro__cmd; extern char *macro__buf; extern s16b quark__num; extern cptr *quark__str; -extern u16b message__next; -extern u16b message__last; -extern u16b message__head; -extern u16b message__tail; -extern u16b *message__ptr; -extern byte *message__color; -extern byte *message__type; -extern u16b *message__count; -extern char *message__buf; extern u32b option_flag[8]; extern u32b option_mask[8]; extern u32b window_flag[ANGBAND_TERM_MAX]; @@ -2054,11 +2045,6 @@ extern sint macro_find_exact(cptr pat); extern char inkey(void); extern cptr quark_str(s16b num); extern s16b quark_add(cptr str); -extern s16b message_num(void); -extern cptr message_str(int age); -extern byte message_color(int age); -extern byte message_type(int age); -extern void message_add(byte type, cptr msg, byte color); extern void display_message(int x, int y, int split, byte color, cptr t); extern void cmsg_print(byte color, cptr msg); extern void msg_print(cptr msg); diff --git a/src/init2.c b/src/init2.c index 8f20ecfc..dfb8a5dc 100644 --- a/src/init2.c +++ b/src/init2.c @@ -6,6 +6,8 @@ #include +#include "messages.h" + /* * This file is used to initialise various variables and arrays for the * Angband game. Note the use of "fd_read()" and "fd_write()" to bypass @@ -1949,15 +1951,8 @@ static errr init_misc(void) /* Quark variables */ C_MAKE(quark__str, QUARK_MAX, cptr); - /* Message variables */ - C_MAKE(message__ptr, MESSAGE_MAX, u16b); - C_MAKE(message__color, MESSAGE_MAX, byte); - C_MAKE(message__type, MESSAGE_MAX, byte); - C_MAKE(message__count, MESSAGE_MAX, u16b); - C_MAKE(message__buf, MESSAGE_BUF, char); - - /* Hack -- No messages yet */ - message__tail = MESSAGE_BUF; + /* Initialize messages subsystem */ + message_init(); /* Initialize game */ process_hooks(HOOK_INIT_GAME, "(s)", "begin"); diff --git a/src/loadsave.c b/src/loadsave.c index 049801de..598858db 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -6,6 +6,8 @@ #include "angband.h" +#include "messages.h" + static void do_byte(byte *, int); static void do_bool(bool_ *, int); static void do_u16b(u16b *, int); diff --git a/src/melee2.c b/src/melee2.c index 6ada6bd0..96f34bcb 100644 --- a/src/melee2.c +++ b/src/melee2.c @@ -16,6 +16,7 @@ */ #include "angband.h" +#include "messages.h" #define SPEAK_CHANCE 8 #define GRINDNOISE 20 diff --git a/src/messages.c b/src/messages.c new file mode 100644 index 00000000..d39ad84b --- /dev/null +++ b/src/messages.c @@ -0,0 +1,394 @@ +#include "messages.h" + +#include "angband.h" + +/* + * OPTION: Maximum number of messages to remember (see "io.c") + * Default: assume maximal memorization of 2048 total messages + */ +#define MESSAGE_MAX 2048 + +/* + * OPTION: Maximum space for the message text buffer (see "io.c") + * Default: assume that each of the 2048 messages is repeated an + * average of three times, and has an average length of 48 + */ +#define MESSAGE_BUF 32768 + + + + +/* + * The next "free" index to use + */ +static u16b message__next; + +/* + * The index of the oldest message (none yet) + */ +static u16b message__last; + +/* + * The next "free" offset + */ +static u16b message__head; + +/* + * The offset to the oldest used char (none yet) + */ +static u16b message__tail; + +/* + * The array of offsets, by index [MESSAGE_MAX] + */ +static u16b *message__ptr; + +/* + * The array of colors, by index [MESSAGE_MAX] + */ +static byte *message__color; + +/* + * The array of type, by index [MESSAGE_MAX] + */ +static byte *message__type; + +/* + * The array of message counts, by index [MESSAGE_MAX] + */ +static u16b *message__count; + +/* + * The array of chars, by offset [MESSAGE_BUF] + */ +static char *message__buf; + + +/* +* Second try for the "message" handling routines. +* +* Each call to "message_add(s)" will add a new "most recent" message +* to the "message recall list", using the contents of the string "s". +* +* The messages will be stored in such a way as to maximize "efficiency", +* that is, we attempt to maximize the number of sequential messages that +* can be retrieved, given a limited amount of storage space. +* +* We keep a buffer of chars to hold the "text" of the messages, not +* necessarily in "order", and an array of offsets into that buffer, +* representing the actual messages. This is made more complicated +* by the fact that both the array of indexes, and the buffer itself, +* are both treated as "circular arrays" for efficiency purposes, but +* the strings may not be "broken" across the ends of the array. +* +* The "message_add()" function is rather "complex", because it must be +* extremely efficient, both in space and time, for use with the Borg. +*/ + +void message_init() +{ + /* Message variables */ + C_MAKE(message__ptr, MESSAGE_MAX, u16b); + C_MAKE(message__color, MESSAGE_MAX, byte); + C_MAKE(message__type, MESSAGE_MAX, byte); + C_MAKE(message__count, MESSAGE_MAX, u16b); + C_MAKE(message__buf, MESSAGE_BUF, char); + + /* Hack -- No messages yet */ + message__tail = MESSAGE_BUF; +} + +/* +* How many messages are "available"? +*/ +s16b message_num(void) +{ + int last, next, n; + + /* Extract the indexes */ + last = message__last; + next = message__next; + + /* Handle "wrap" */ + if (next < last) next += MESSAGE_MAX; + + /* Extract the space */ + n = (next - last); + + /* Return the result */ + return (n); +} + + + +/* +* Recall the "text" of a saved message +*/ +cptr message_str(int age) +{ + static char buf[1024]; + s16b x; + s16b o; + cptr s; + + /* Forgotten messages have no text */ + if ((age < 0) || (age >= message_num())) return (""); + + /* Acquire the "logical" index */ + x = (message__next + MESSAGE_MAX - (age + 1)) % MESSAGE_MAX; + + /* Get the "offset" for the message */ + o = message__ptr[x]; + + /* Access the message text */ + s = &message__buf[o]; + + /* Hack -- Handle repeated messages */ + if (message__count[x] > 1) + { + strnfmt(buf, 1024, "%s <%dx>", s, message__count[x]); + s = buf; + } + + /* Return the message text */ + return (s); +} + +/* +* Recall the color of a saved message +*/ +byte message_color(int age) +{ + s16b x; + byte color = TERM_WHITE; + + /* Forgotten messages have no text */ + if ((age < 0) || (age >= message_num())) return (TERM_WHITE); + + /* Acquire the "logical" index */ + x = (message__next + MESSAGE_MAX - (age + 1)) % MESSAGE_MAX; + + /* Get the "offset" for the message */ + color = message__color[x]; + + /* Return the message text */ + return (color); +} + +/* + * Recall the type of a saved message + */ +byte message_type(int age) +{ + s16b x; + byte type; + + /* Forgotten messages have no text */ + if ((age < 0) || (age >= message_num())) return (MESSAGE_NONE); + + /* Acquire the "logical" index */ + x = (message__next + MESSAGE_MAX - (age + 1)) % MESSAGE_MAX; + + /* Get the "offset" for the message */ + type = message__type[x]; + + /* Return the message text */ + return (type); +} + + + +/* +* Add a new message, with great efficiency +*/ +void message_add(byte type, cptr str, byte color) +{ + int i, k, x, n; + cptr s; + + + /*** Step 1 -- Analyze the message ***/ + + /* Hack -- Ignore "non-messages" */ + if (!str) return; + + /* Message length */ + n = strlen(str); + + /* Important Hack -- Ignore "long" messages */ + if (n >= MESSAGE_BUF / 4) return; + + + /*** Step 2 -- Handle repeated messages ***/ + + /* Acquire the "logical" last index */ + x = (message__next + MESSAGE_MAX - 1) % MESSAGE_MAX; + + /* Get the last message text */ + s = &message__buf[message__ptr[x]]; + + /* Last message repeated? */ + if (streq(str, s)) + { + /* Increase the message count */ + message__count[x]++; + + /* Success */ + return; + } + + + /*** Step 3 -- Attempt to optimize ***/ + + /* Limit number of messages to check */ + k = message_num() / 4; + + /* Limit number of messages to check */ + if (k > MESSAGE_MAX / 32) k = MESSAGE_MAX / 32; + + /* Check the last few messages (if any to count) */ + for (i = message__next; k; k--) + { + u16b q; + + cptr old; + + /* Back up and wrap if needed */ + if (i-- == 0) i = MESSAGE_MAX - 1; + + /* Stop before oldest message */ + if (i == message__last) break; + + /* Extract "distance" from "head" */ + q = (message__head + MESSAGE_BUF - message__ptr[i]) % MESSAGE_BUF; + + /* Do not optimize over large distance */ + if (q > MESSAGE_BUF / 2) continue; + + /* Access the old string */ + old = &message__buf[message__ptr[i]]; + + /* Compare */ + if (!streq(old, str)) continue; + + /* Get the next message index, advance */ + x = message__next++; + + /* Handle wrap */ + if (message__next == MESSAGE_MAX) message__next = 0; + + /* Kill last message if needed */ + if (message__next == message__last) message__last++; + + /* Handle wrap */ + if (message__last == MESSAGE_MAX) message__last = 0; + + /* Assign the starting address */ + message__ptr[x] = message__ptr[i]; + message__color[x] = color; + message__type[x] = type; + message__count[x] = 1; + + /* Success */ + return; + } + + + /*** Step 4 -- Ensure space before end of buffer ***/ + + /* Kill messages and Wrap if needed */ + if (message__head + n + 1 >= MESSAGE_BUF) + { + /* Kill all "dead" messages */ + for (i = message__last; TRUE; i++) + { + /* Wrap if needed */ + if (i == MESSAGE_MAX) i = 0; + + /* Stop before the new message */ + if (i == message__next) break; + + /* Kill "dead" messages */ + if (message__ptr[i] >= message__head) + { + /* Track oldest message */ + message__last = i + 1; + } + } + + /* Wrap "tail" if needed */ + if (message__tail >= message__head) message__tail = 0; + + /* Start over */ + message__head = 0; + } + + + /*** Step 5 -- Ensure space before next message ***/ + + /* Kill messages if needed */ + if (message__head + n + 1 > message__tail) + { + /* Grab new "tail" */ + message__tail = message__head + n + 1; + + /* Advance tail while possible past first "nul" */ + while (message__buf[message__tail - 1]) message__tail++; + + /* Kill all "dead" messages */ + for (i = message__last; TRUE; i++) + { + /* Wrap if needed */ + if (i == MESSAGE_MAX) i = 0; + + /* Stop before the new message */ + if (i == message__next) break; + + /* Kill "dead" messages */ + if ((message__ptr[i] >= message__head) && + (message__ptr[i] < message__tail)) + { + /* Track oldest message */ + message__last = i + 1; + } + } + } + + + /*** Step 6 -- Grab a new message index ***/ + + /* Get the next message index, advance */ + x = message__next++; + + /* Handle wrap */ + if (message__next == MESSAGE_MAX) message__next = 0; + + /* Kill last message if needed */ + if (message__next == message__last) message__last++; + + /* Handle wrap */ + if (message__last == MESSAGE_MAX) message__last = 0; + + + + /*** Step 7 -- Insert the message text ***/ + + /* Assign the starting address */ + message__ptr[x] = message__head; + message__color[x] = color; + message__type[x] = type; + message__count[x] = 1; + + /* Append the new part of the message */ + for (i = 0; i < n; i++) + { + /* Copy the message */ + message__buf[message__head + i] = str[i]; + } + + /* Terminate */ + message__buf[message__head + i] = '\0'; + + /* Advance the "head" pointer */ + message__head += n + 1; +} diff --git a/src/messages.h b/src/messages.h new file mode 100644 index 00000000..2b02f0c3 --- /dev/null +++ b/src/messages.h @@ -0,0 +1,16 @@ +#ifndef H_f6dac2dc_0449_4764_9942_1c1fe7a70bc4 +#define H_f6dac2dc_0449_4764_9942_1c1fe7a70bc4 + +#include "h-type.h" + +#define MESSAGE_NONE 0 +#define MESSAGE_MSG 1 + +void message_init(); +s16b message_num(); +cptr message_str(int age); +byte message_color(int age); +byte message_type(int age); +void message_add(byte type, cptr msg, byte color); + +#endif diff --git a/src/plots.c b/src/plots.c index f5801ec3..754ab401 100644 --- a/src/plots.c +++ b/src/plots.c @@ -11,8 +11,11 @@ */ #include "angband.h" + #include +#include "messages.h" + /* #define DEBUG_HOOK */ /******** Hooks stuff *********/ diff --git a/src/util.c b/src/util.c index e73dbce3..e65e4455 100644 --- a/src/util.c +++ b/src/util.c @@ -4,6 +4,7 @@ #include "angband.h" +#include "messages.h" @@ -2128,328 +2129,6 @@ cptr quark_str(s16b i) } - - -/* -* Second try for the "message" handling routines. -* -* Each call to "message_add(s)" will add a new "most recent" message -* to the "message recall list", using the contents of the string "s". -* -* The messages will be stored in such a way as to maximize "efficiency", -* that is, we attempt to maximize the number of sequential messages that -* can be retrieved, given a limited amount of storage space. -* -* We keep a buffer of chars to hold the "text" of the messages, not -* necessarily in "order", and an array of offsets into that buffer, -* representing the actual messages. This is made more complicated -* by the fact that both the array of indexes, and the buffer itself, -* are both treated as "circular arrays" for efficiency purposes, but -* the strings may not be "broken" across the ends of the array. -* -* The "message_add()" function is rather "complex", because it must be -* extremely efficient, both in space and time, for use with the Borg. -*/ - - - -/* -* How many messages are "available"? -*/ -s16b message_num(void) -{ - int last, next, n; - - /* Extract the indexes */ - last = message__last; - next = message__next; - - /* Handle "wrap" */ - if (next < last) next += MESSAGE_MAX; - - /* Extract the space */ - n = (next - last); - - /* Return the result */ - return (n); -} - - - -/* -* Recall the "text" of a saved message -*/ -cptr message_str(int age) -{ - static char buf[1024]; - s16b x; - s16b o; - cptr s; - - /* Forgotten messages have no text */ - if ((age < 0) || (age >= message_num())) return (""); - - /* Acquire the "logical" index */ - x = (message__next + MESSAGE_MAX - (age + 1)) % MESSAGE_MAX; - - /* Get the "offset" for the message */ - o = message__ptr[x]; - - /* Access the message text */ - s = &message__buf[o]; - - /* Hack -- Handle repeated messages */ - if (message__count[x] > 1) - { - strnfmt(buf, 1024, "%s <%dx>", s, message__count[x]); - s = buf; - } - - /* Return the message text */ - return (s); -} - -/* -* Recall the color of a saved message -*/ -byte message_color(int age) -{ - s16b x; - byte color = TERM_WHITE; - - /* Forgotten messages have no text */ - if ((age < 0) || (age >= message_num())) return (TERM_WHITE); - - /* Acquire the "logical" index */ - x = (message__next + MESSAGE_MAX - (age + 1)) % MESSAGE_MAX; - - /* Get the "offset" for the message */ - color = message__color[x]; - - /* Return the message text */ - return (color); -} - -/* - * Recall the type of a saved message - */ -byte message_type(int age) -{ - s16b x; - byte type; - - /* Forgotten messages have no text */ - if ((age < 0) || (age >= message_num())) return (MESSAGE_NONE); - - /* Acquire the "logical" index */ - x = (message__next + MESSAGE_MAX - (age + 1)) % MESSAGE_MAX; - - /* Get the "offset" for the message */ - type = message__type[x]; - - /* Return the message text */ - return (type); -} - - - -/* -* Add a new message, with great efficiency -*/ -void message_add(byte type, cptr str, byte color) -{ - int i, k, x, n; - cptr s; - - - /*** Step 1 -- Analyze the message ***/ - - /* Hack -- Ignore "non-messages" */ - if (!str) return; - - /* Message length */ - n = strlen(str); - - /* Important Hack -- Ignore "long" messages */ - if (n >= MESSAGE_BUF / 4) return; - - - /*** Step 2 -- Handle repeated messages ***/ - - /* Acquire the "logical" last index */ - x = (message__next + MESSAGE_MAX - 1) % MESSAGE_MAX; - - /* Get the last message text */ - s = &message__buf[message__ptr[x]]; - - /* Last message repeated? */ - if (streq(str, s)) - { - /* Increase the message count */ - message__count[x]++; - - /* Success */ - return; - } - - - /*** Step 3 -- Attempt to optimize ***/ - - /* Limit number of messages to check */ - k = message_num() / 4; - - /* Limit number of messages to check */ - if (k > MESSAGE_MAX / 32) k = MESSAGE_MAX / 32; - - /* Check the last few messages (if any to count) */ - for (i = message__next; k; k--) - { - u16b q; - - cptr old; - - /* Back up and wrap if needed */ - if (i-- == 0) i = MESSAGE_MAX - 1; - - /* Stop before oldest message */ - if (i == message__last) break; - - /* Extract "distance" from "head" */ - q = (message__head + MESSAGE_BUF - message__ptr[i]) % MESSAGE_BUF; - - /* Do not optimize over large distance */ - if (q > MESSAGE_BUF / 2) continue; - - /* Access the old string */ - old = &message__buf[message__ptr[i]]; - - /* Compare */ - if (!streq(old, str)) continue; - - /* Get the next message index, advance */ - x = message__next++; - - /* Handle wrap */ - if (message__next == MESSAGE_MAX) message__next = 0; - - /* Kill last message if needed */ - if (message__next == message__last) message__last++; - - /* Handle wrap */ - if (message__last == MESSAGE_MAX) message__last = 0; - - /* Assign the starting address */ - message__ptr[x] = message__ptr[i]; - message__color[x] = color; - message__type[x] = type; - message__count[x] = 1; - - /* Success */ - return; - } - - - /*** Step 4 -- Ensure space before end of buffer ***/ - - /* Kill messages and Wrap if needed */ - if (message__head + n + 1 >= MESSAGE_BUF) - { - /* Kill all "dead" messages */ - for (i = message__last; TRUE; i++) - { - /* Wrap if needed */ - if (i == MESSAGE_MAX) i = 0; - - /* Stop before the new message */ - if (i == message__next) break; - - /* Kill "dead" messages */ - if (message__ptr[i] >= message__head) - { - /* Track oldest message */ - message__last = i + 1; - } - } - - /* Wrap "tail" if needed */ - if (message__tail >= message__head) message__tail = 0; - - /* Start over */ - message__head = 0; - } - - - /*** Step 5 -- Ensure space before next message ***/ - - /* Kill messages if needed */ - if (message__head + n + 1 > message__tail) - { - /* Grab new "tail" */ - message__tail = message__head + n + 1; - - /* Advance tail while possible past first "nul" */ - while (message__buf[message__tail - 1]) message__tail++; - - /* Kill all "dead" messages */ - for (i = message__last; TRUE; i++) - { - /* Wrap if needed */ - if (i == MESSAGE_MAX) i = 0; - - /* Stop before the new message */ - if (i == message__next) break; - - /* Kill "dead" messages */ - if ((message__ptr[i] >= message__head) && - (message__ptr[i] < message__tail)) - { - /* Track oldest message */ - message__last = i + 1; - } - } - } - - - /*** Step 6 -- Grab a new message index ***/ - - /* Get the next message index, advance */ - x = message__next++; - - /* Handle wrap */ - if (message__next == MESSAGE_MAX) message__next = 0; - - /* Kill last message if needed */ - if (message__next == message__last) message__last++; - - /* Handle wrap */ - if (message__last == MESSAGE_MAX) message__last = 0; - - - - /*** Step 7 -- Insert the message text ***/ - - /* Assign the starting address */ - message__ptr[x] = message__head; - message__color[x] = color; - message__type[x] = type; - message__count[x] = 1; - - /* Append the new part of the message */ - for (i = 0; i < n; i++) - { - /* Copy the message */ - message__buf[message__head + i] = str[i]; - } - - /* Terminate */ - message__buf[message__head + i] = '\0'; - - /* Advance the "head" pointer */ - message__head += n + 1; -} - - - /* * Hack -- flush */ diff --git a/src/variable.c b/src/variable.c index 11f0867b..ab9bf699 100644 --- a/src/variable.c +++ b/src/variable.c @@ -493,52 +493,6 @@ s16b quark__num; cptr *quark__str; -/* - * The next "free" index to use - */ -u16b message__next; - -/* - * The index of the oldest message (none yet) - */ -u16b message__last; - -/* - * The next "free" offset - */ -u16b message__head; - -/* - * The offset to the oldest used char (none yet) - */ -u16b message__tail; - -/* - * The array of offsets, by index [MESSAGE_MAX] - */ -u16b *message__ptr; - -/* - * The array of colors, by index [MESSAGE_MAX] - */ -byte *message__color; - -/* - * The array of type, by index [MESSAGE_MAX] - */ -byte *message__type; - -/* - * The array of message counts, by index [MESSAGE_MAX] - */ -u16b *message__count; - -/* - * The array of chars, by offset [MESSAGE_BUF] - */ -char *message__buf; - - /* * The array of normal options */ diff --git a/src/xtra1.c b/src/xtra1.c index 4ccdf08e..0cc3ccac 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -12,6 +12,7 @@ #include "angband.h" +#include "messages.h" /* * Converts stat num into a six-char (right justified) string -- cgit v1.2.3 From 30ba18d4fd9901f7d7fdbde83b41de5e0ef7e8c1 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 09:14:06 +0200 Subject: messages: Remove message__type; it's not really used. --- src/birth.c | 28 ++++++++++++++++++---------- src/loadsave.c | 9 +++++---- src/melee2.c | 4 ++-- src/messages.c | 32 +------------------------------- src/messages.h | 5 +---- src/q_hobbit.c | 5 ++++- src/q_poison.c | 2 +- src/q_shroom.c | 5 ++++- src/q_thrain.c | 5 ++++- src/util.c | 7 +++++-- 10 files changed, 45 insertions(+), 57 deletions(-) diff --git a/src/birth.c b/src/birth.c index 851e1877..d8c4ef3f 100644 --- a/src/birth.c +++ b/src/birth.c @@ -1427,7 +1427,10 @@ static void gen_random_quests(int n) /* Arg could not find anything ??? */ if (!tries) { - if (wizard) message_add(MESSAGE_MSG, format("Could not find quest monster on lvl %d", rl), TERM_RED); + if (wizard) + { + message_add(format("Could not find quest monster on lvl %d", rl), TERM_RED); + } q_ptr->type = 0; } else @@ -1439,9 +1442,11 @@ static void gen_random_quests(int n) q_ptr->done = FALSE; - if (wizard) message_add(MESSAGE_MSG, - format("Quest for %d on lvl %d", - q_ptr->r_idx, rl), TERM_RED); + if (wizard) + { + message_add(format("Quest for %d on lvl %d", + q_ptr->r_idx, rl), TERM_RED); + } } lvl += step; @@ -3508,11 +3513,11 @@ void player_birth(void) } /* Note player birth in the message recall */ - message_add(MESSAGE_MSG, " ", TERM_L_BLUE); - message_add(MESSAGE_MSG, " ", TERM_L_BLUE); - message_add(MESSAGE_MSG, "====================", TERM_L_BLUE); - message_add(MESSAGE_MSG, " ", TERM_L_BLUE); - message_add(MESSAGE_MSG, " ", TERM_L_BLUE); + message_add(" ", TERM_L_BLUE); + message_add(" ", TERM_L_BLUE); + message_add("====================", TERM_L_BLUE); + message_add(" ", TERM_L_BLUE); + message_add(" ", TERM_L_BLUE); /* Hack -- outfit the player */ player_outfit(); @@ -3557,7 +3562,10 @@ void player_birth(void) } d_ptr->t_level[num] = lev; - if (wizard) message_add(MESSAGE_MSG, format("Random dungeon town: d_idx:%d, lev:%d", i, lev), TERM_WHITE); + if (wizard) + { + message_add(format("Random dungeon town: d_idx:%d, lev:%d", i, lev), TERM_WHITE); + } /* Create the town */ init_town(d_ptr->t_idx[num], d_ptr->t_level[num]); diff --git a/src/loadsave.c b/src/loadsave.c index 598858db..de3bcd60 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -2123,27 +2123,28 @@ static void do_messages(int flag) /* FIXME! We should be able to unify this be /* Read the messages */ if (flag == LS_LOAD) { + byte tmp8u = 0; for (i = 0; i < num; i++) { /* Read the message */ do_string(buf, 128, LS_LOAD); do_byte(&color, flag); - do_byte(&type, flag); + do_byte(&tmp8u, flag); /* Save the message */ - message_add(type, buf, color); + message_add(buf, color); } } if (flag == LS_SAVE) { byte holder; + byte zero = 0; for (i = num - 1; i >= 0; i--) { do_string((char *)message_str((s16b)i), 0, LS_SAVE); holder = message_color((s16b)i); do_byte(&holder, flag); - holder = message_type((s16b)i); - do_byte(&holder, flag); + do_byte(&zero, flag); } } } diff --git a/src/melee2.c b/src/melee2.c index 96f34bcb..2880c99c 100644 --- a/src/melee2.c +++ b/src/melee2.c @@ -958,7 +958,7 @@ void monster_msg(cptr fmt, ...) msg_print(buf); else { - message_add(MESSAGE_MSG, buf, TERM_WHITE); + message_add(buf, TERM_WHITE); p_ptr->window |= PW_MESSAGE; } } @@ -983,7 +983,7 @@ void cmonster_msg(char a, cptr fmt, ...) cmsg_print(a, buf); else { - message_add(MESSAGE_MSG, buf, a); + message_add(buf, a); p_ptr->window |= PW_MESSAGE; } } diff --git a/src/messages.c b/src/messages.c index d39ad84b..e88cf58e 100644 --- a/src/messages.c +++ b/src/messages.c @@ -48,11 +48,6 @@ static u16b *message__ptr; */ static byte *message__color; -/* - * The array of type, by index [MESSAGE_MAX] - */ -static byte *message__type; - /* * The array of message counts, by index [MESSAGE_MAX] */ @@ -90,7 +85,6 @@ void message_init() /* Message variables */ C_MAKE(message__ptr, MESSAGE_MAX, u16b); C_MAKE(message__color, MESSAGE_MAX, byte); - C_MAKE(message__type, MESSAGE_MAX, byte); C_MAKE(message__count, MESSAGE_MAX, u16b); C_MAKE(message__buf, MESSAGE_BUF, char); @@ -175,33 +169,11 @@ byte message_color(int age) return (color); } -/* - * Recall the type of a saved message - */ -byte message_type(int age) -{ - s16b x; - byte type; - - /* Forgotten messages have no text */ - if ((age < 0) || (age >= message_num())) return (MESSAGE_NONE); - - /* Acquire the "logical" index */ - x = (message__next + MESSAGE_MAX - (age + 1)) % MESSAGE_MAX; - - /* Get the "offset" for the message */ - type = message__type[x]; - - /* Return the message text */ - return (type); -} - - /* * Add a new message, with great efficiency */ -void message_add(byte type, cptr str, byte color) +void message_add(cptr str, byte color) { int i, k, x, n; cptr s; @@ -286,7 +258,6 @@ void message_add(byte type, cptr str, byte color) /* Assign the starting address */ message__ptr[x] = message__ptr[i]; message__color[x] = color; - message__type[x] = type; message__count[x] = 1; /* Success */ @@ -376,7 +347,6 @@ void message_add(byte type, cptr str, byte color) /* Assign the starting address */ message__ptr[x] = message__head; message__color[x] = color; - message__type[x] = type; message__count[x] = 1; /* Append the new part of the message */ diff --git a/src/messages.h b/src/messages.h index 2b02f0c3..401c5727 100644 --- a/src/messages.h +++ b/src/messages.h @@ -3,14 +3,11 @@ #include "h-type.h" -#define MESSAGE_NONE 0 -#define MESSAGE_MSG 1 - void message_init(); s16b message_num(); cptr message_str(int age); byte message_color(int age); byte message_type(int age); -void message_add(byte type, cptr msg, byte color); +void message_add(cptr msg, byte color); #endif diff --git a/src/q_hobbit.c b/src/q_hobbit.c index f3b7d856..b80638ad 100644 --- a/src/q_hobbit.c +++ b/src/q_hobbit.c @@ -173,7 +173,10 @@ bool_ quest_hobbit_init_hook(int q_idx) { cquest.data[0] = rand_range(26, 34); cquest.data[1] = turn; - if (wizard) message_add(MESSAGE_MSG, format("Hobbit level %d", cquest.data[0]), TERM_BLUE); + if (wizard) + { + message_add(format("Hobbit level %d", cquest.data[0]), TERM_BLUE); + } } if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED)) diff --git a/src/q_poison.c b/src/q_poison.c index e6fed3a1..0c3987df 100644 --- a/src/q_poison.c +++ b/src/q_poison.c @@ -220,7 +220,7 @@ bool_ quest_poison_init_hook(int q_idx) { cquest.data[1] = TRUE; cquest.data[0] = rand_int(4); - if (wizard) message_add(MESSAGE_MSG, format("Wilderness poison %d, %d", wild_locs[cquest.data[0]][0], wild_locs[cquest.data[0]][1]), TERM_BLUE); + if (wizard) message_add(format("Wilderness poison %d, %d", wild_locs[cquest.data[0]][0], wild_locs[cquest.data[0]][1]), TERM_BLUE); } if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED)) diff --git a/src/q_shroom.c b/src/q_shroom.c index 4d4d7494..c0133e74 100644 --- a/src/q_shroom.c +++ b/src/q_shroom.c @@ -272,7 +272,10 @@ bool_ quest_shroom_init_hook(int q_idx) { cquest.data[0] = 0; cquest.data[1] = rand_range(7, 14); - if (wizard) message_add(MESSAGE_MSG, format("Shrooms number %d", cquest.data[1]), TERM_BLUE); + if (wizard) + { + message_add(format("Shrooms number %d", cquest.data[1]), TERM_BLUE); + } } if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED)) diff --git a/src/q_thrain.c b/src/q_thrain.c index b2b1be9f..6180706c 100644 --- a/src/q_thrain.c +++ b/src/q_thrain.c @@ -212,7 +212,10 @@ bool_ quest_thrain_init_hook(int q) if (!cquest.data[0]) { cquest.data[0] = rand_range(d_info[DUNGEON_DOL_GULDUR].mindepth + 1, d_info[DUNGEON_DOL_GULDUR].maxdepth - 1); - if (wizard) message_add(MESSAGE_MSG, format("Thrain lvl %d", cquest.data[0]), TERM_BLUE); + if (wizard) + { + message_add(format("Thrain lvl %d", cquest.data[0]), TERM_BLUE); + } } if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED)) { diff --git a/src/util.c b/src/util.c index e65e4455..a9a9d10a 100644 --- a/src/util.c +++ b/src/util.c @@ -2249,7 +2249,7 @@ void cmsg_print(byte color, cptr msg) /* Memorize the message */ - if (character_generated) message_add(MESSAGE_MSG, msg, color); + if (character_generated) message_add(msg, color); /* Handle "auto_more" */ if (auto_more) @@ -3978,7 +3978,10 @@ bool_ prefix(cptr s, cptr t) /* Paranoia */ if (!s || !t) { - if (alert_failure) message_add(MESSAGE_MSG, "prefix() called with null argument!", TERM_RED); + if (alert_failure) + { + message_add("prefix() called with null argument!", TERM_RED); + } return FALSE; } -- cgit v1.2.3 From 0eab7f1626d7950dbf38451b33768ba4d209686a Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 09:31:43 +0200 Subject: Show skills immediately on "m" menu --- src/skills.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/skills.c b/src/skills.c index 4de0b047..c343dcce 100644 --- a/src/skills.c +++ b/src/skills.c @@ -754,12 +754,12 @@ void select_default_melee() /* * Print a batch of skills. */ -static void print_skill_batch(int *p, cptr *p_desc, int start, int max, bool_ mode) +static void print_skill_batch(int *p, cptr *p_desc, int start, int max) { char buff[80]; int i = start, j = 0; - if (mode) prt(format(" %-31s", "Name"), 1, 20); + prt(format(" %-31s", "Name"), 1, 20); for (i = start; i < (start + 20); i++) { @@ -770,10 +770,10 @@ static void print_skill_batch(int *p, cptr *p_desc, int start, int max, bool_ mo else sprintf(buff, " %c - %d) %-30s", I2A(j), p[i], "Change melee style"); - if (mode) prt(buff, 2 + j, 20); + prt(buff, 2 + j, 20); j++; } - if (mode) prt("", 2 + j, 20); + prt("", 2 + j, 20); prt(format("Select a skill (a-%c), @ to select by name, +/- to scroll:", I2A(j - 1)), 0, 0); } @@ -782,7 +782,6 @@ int do_cmd_activate_skill_aux() char which; int max = 0, i, start = 0; int ret; - bool_ mode = FALSE; int *p; cptr *p_desc; @@ -855,7 +854,7 @@ int do_cmd_activate_skill_aux() while (1) { - print_skill_batch(p, p_desc, start, max, mode); + print_skill_batch(p, p_desc, start, max); which = inkey(); if (which == ESCAPE) @@ -863,12 +862,6 @@ int do_cmd_activate_skill_aux() ret = -1; break; } - else if (which == '*' || which == '?' || which == ' ') - { - mode = (mode) ? FALSE : TRUE; - Term_load(); - character_icky = FALSE; - } else if (which == '+') { start += 20; -- cgit v1.2.3 From d15295cab3c0eaebb772f608664d8138cd72e976 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 09:47:50 +0200 Subject: Show symbiote powers immediately when using --- src/cmd5.c | 114 +++++++++++++++++++++++++------------------------------------ 1 file changed, 46 insertions(+), 68 deletions(-) diff --git a/src/cmd5.c b/src/cmd5.c index 7a69f396..8c191183 100644 --- a/src/cmd5.c +++ b/src/cmd5.c @@ -852,7 +852,7 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost int powers[96]; - bool_ flag, redraw; + bool_ flag; int ask, plev = p_ptr->lev; @@ -915,99 +915,80 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost /* Nothing chosen yet */ flag = FALSE; - /* No redraw yet */ - redraw = FALSE; - /* Get the last label */ label = (num <= 26) ? I2A(num - 1) : I2D(num - 1 - 26); /* Build a prompt (accept all spells) */ /* Mega Hack -- if no_cost is false, we're actually a Possessor -dsb */ strnfmt(out_val, 78, - "(Powers a-%c, *=List, ESC=exit) Use which power of your %s? ", + "(Powers a-%c, ESC=exit) Use which power of your %s? ", label, (no_cost ? "symbiote" : "body")); + /* Save the screen */ + character_icky = TRUE; + Term_save(); + /* Get a spell from the user */ - while (!flag && get_com(out_val, &choice)) + while (!flag) { - /* Request redraw */ - if ((choice == ' ') || (choice == '*') || (choice == '?')) + /* Show the list */ { - /* Show the list */ - if (!redraw) - { - byte y = 1, x = 0; - int ctr = 0; - char dummy[80]; + byte y = 1, x = 0; + int ctr = 0; + char dummy[80]; + + strcpy(dummy, ""); - strcpy(dummy, ""); + prt ("", y++, x); + + while (ctr < num) + { + monster_power *mp_ptr = &monster_powers[powers[ctr]]; + int mana = mp_ptr->mana / 10; - /* Show list */ - redraw = TRUE; + if (mana > p_ptr->msp) mana = p_ptr->msp; - /* Save the screen */ - character_icky = TRUE; - Term_save(); + if (!mana) mana = 1; - prt ("", y++, x); + label = (ctr < 26) ? I2A(ctr) : I2D(ctr - 26); - while (ctr < num) + if (!no_cost) + { + strnfmt(dummy, 80, " %c) %2d %s", + label, mana, mp_ptr->name); + } + else { - monster_power *mp_ptr = &monster_powers[powers[ctr]]; - int mana = mp_ptr->mana / 10; - - if (mana > p_ptr->msp) mana = p_ptr->msp; - - if (!mana) mana = 1; - - label = (ctr < 26) ? I2A(ctr) : I2D(ctr - 26); - - if (!no_cost) - { - strnfmt(dummy, 80, " %c) %2d %s", - label, mana, mp_ptr->name); - } - else - { - strnfmt(dummy, 80, " %c) %s", - label, mp_ptr->name); - } - - if (ctr < 17) - { - prt(dummy, y + ctr, x); - } - else - { - prt(dummy, y + ctr - 17, x + 40); - } - - ctr++; + strnfmt(dummy, 80, " %c) %s", + label, mp_ptr->name); } if (ctr < 17) { - prt ("", y + ctr, x); + prt(dummy, y + ctr, x); } else { - prt ("", y + 17, x); + prt(dummy, y + ctr - 17, x + 40); } + + ctr++; } - /* Hide the list */ + if (ctr < 17) + { + prt ("", y + ctr, x); + } else { - /* Hide list */ - redraw = FALSE; - - /* Restore the screen */ - Term_load(); - character_icky = FALSE; + prt ("", y + 17, x); } + } - /* Redo asking */ - continue; + if (!get_com(out_val, &choice)) + { + flag = FALSE; + break; } if (choice == '\r' && num == 1) @@ -1061,11 +1042,8 @@ int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost } /* Restore the screen */ - if (redraw) - { - Term_load(); - character_icky = FALSE; - } + Term_load(); + character_icky = FALSE; /* Abort if needed */ if (!flag) -- cgit v1.2.3 From 3224281f94c23f0fecc66e478da2d647b8c0c588 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 10:01:40 +0200 Subject: Show spells imeddiately when casting --- src/cmd5.c | 83 +++++++++++++++++--------------------------------------------- 1 file changed, 23 insertions(+), 60 deletions(-) diff --git a/src/cmd5.c b/src/cmd5.c index 8c191183..7b7d334d 100644 --- a/src/cmd5.c +++ b/src/cmd5.c @@ -2152,8 +2152,7 @@ s32b get_school_spell(cptr do_what, s16b force_book) int num = 0; s32b where = 1; int ask; - bool_ flag, redraw; - char choice; + bool_ flag; char out_val[160]; char buf2[40]; char buf3[40]; @@ -2202,9 +2201,6 @@ s32b get_school_spell(cptr do_what, s16b force_book) /* Nothing chosen yet */ flag = FALSE; - /* No redraw yet */ - redraw = FALSE; - /* Show choices */ if (show_choices) { @@ -2227,51 +2223,40 @@ s32b get_school_spell(cptr do_what, s16b force_book) pval = o_ptr->pval2; } + /* Save the screen */ + character_icky = TRUE; + Term_save(); + + /* Go */ if (hack_force_spell == -1) { num = school_book_length(sval); /* Build a prompt (accept all spells) */ - strnfmt(out_val, 78, "(Spells %c-%c, Descs %c-%c, *=List, ESC=exit) %^s which spell? ", + strnfmt(out_val, 78, "(Spells %c-%c, Descs %c-%c, ESC=exit) %^s which spell? ", I2A(0), I2A(num - 1), I2A(0) - 'a' + 'A', I2A(num - 1) - 'a' + 'A', do_what); /* Get a spell from the user */ - while (!flag && get_com(out_val, &choice)) + while (!flag) { - /* Request redraw */ - if (((choice == ' ') || (choice == '*') || (choice == '?'))) - { - /* Show the list */ - if (!redraw) - { - /* Show list */ - redraw = TRUE; - - /* Save the screen */ - character_icky = TRUE; - Term_save(); - - /* Display a list of spells */ - where = print_book(sval, pval, o_ptr); - } + char choice; - /* Hide the list */ - else - { - /* Hide list */ - redraw = FALSE; - where = 1; + /* Restore and save screen; this prevents + subprompt from leaving garbage when going + around the loop multiple times. */ + Term_load(); + Term_save(); - /* Restore the screen */ - Term_load(); - character_icky = FALSE; - } + /* Display a list of spells */ + where = print_book(sval, pval, o_ptr); - /* Redo asking */ - continue; + /* Input */ + if (!get_com(out_val, &choice)) + { + flag = FALSE; + break; } - /* Note verify */ ask = (isupper(choice)); @@ -2291,25 +2276,6 @@ s32b get_school_spell(cptr do_what, s16b force_book) /* Verify it */ if (ask) { - /* Show the list */ - if (!redraw) - { - /* Show list */ - redraw = TRUE; - - /* Save the screen */ - character_icky = TRUE; - Term_load(); - Term_save(); - - } - /* Rstore the screen */ - else - { - /* Restore the screen */ - Term_load(); - } - /* Display a list of spells */ where = print_book(sval, pval, o_ptr); print_spell_desc(spell_x(sval, pval, i), where); @@ -2359,11 +2325,8 @@ s32b get_school_spell(cptr do_what, s16b force_book) /* Restore the screen */ - if (redraw) - { - Term_load(); - character_icky = FALSE; - } + Term_load(); + character_icky = FALSE; /* Show choices */ -- cgit v1.2.3 From 7d75770faa5ce498a9351951281de3c5d7019e9a Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 10:20:34 +0200 Subject: Show character powers immediately when (U)sing --- src/powers.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/powers.c b/src/powers.c index 613968df..a12d55f6 100644 --- a/src/powers.c +++ b/src/powers.c @@ -1262,13 +1262,13 @@ static void power_activate(int power) /* * Print a batch of power. */ -static void print_power_batch(int *p, int start, int max, bool_ mode) +static void print_power_batch(int *p, int start, int max) { char buff[80]; power_type* spell; int i = start, j = 0; - if (mode) prt(format(" %-31s Level Mana Fail", "Name"), 1, 20); + prt(format(" %-31s Level Mana Fail", "Name"), 1, 20); for (i = start; i < (start + 20); i++) { @@ -1279,10 +1279,10 @@ static void print_power_batch(int *p, int start, int max, bool_ mode) sprintf(buff, " %c-%3d) %-30s %5d %4d %s@%d", I2A(j), p[i] + 1, spell->name, spell->level, spell->cost, stat_names[spell->stat], spell->diff); - if (mode) prt(buff, 2 + j, 20); + prt(buff, 2 + j, 20); j++; } - if (mode) prt("", 2 + j, 20); + prt("", 2 + j, 20); prt(format("Select a power (a-%c), +/- to scroll:", I2A(j - 1)), 0, 0); } @@ -1296,7 +1296,6 @@ static power_type* select_power(int *x_idx) char which; int max = 0, i, start = 0; power_type* ret; - bool_ mode = FALSE; int p[POWER_MAX]; /* Count the max */ @@ -1322,7 +1321,7 @@ static power_type* select_power(int *x_idx) while (1) { - print_power_batch(p, start, max, mode); + print_power_batch(p, start, max); which = inkey(); if (which == ESCAPE) @@ -1331,12 +1330,6 @@ static power_type* select_power(int *x_idx) ret = NULL; break; } - else if (which == '*' || which == '?' || which == ' ') - { - mode = (mode) ? FALSE : TRUE; - Term_load(); - character_icky = FALSE; - } else if (which == '+') { start += 20; -- cgit v1.2.3 From 5ca481fa01ec592fa67181135605180cb22b56c3 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 14:25:59 +0200 Subject: Show Thaumaturgy spells immediately when casting Fixes a few display bugs too. --- src/cmd7.c | 37 ++++++++++++++----------------------- src/externs.h | 1 - 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/src/cmd7.c b/src/cmd7.c index f174e96a..d148dc07 100644 --- a/src/cmd7.c +++ b/src/cmd7.c @@ -4390,7 +4390,7 @@ static void print_spell_batch(int batch, int max) /* * List ten random spells and ask to pick one. */ -static random_spell* select_spell_from_batch(int batch, bool_ quick) +static random_spell* select_spell_from_batch(int batch) { char tmp[160]; @@ -4414,18 +4414,16 @@ static random_spell* select_spell_from_batch(int batch, bool_ quick) mut_max = spell_num - batch * 10; } - strnfmt(tmp, 160, "(a-%c, * to list, A-%cto browse, / to rename, - to comment) Select a power: ", + strnfmt(tmp, 160, "(a-%c, A-%cto browse, / to rename, - to comment) Select a power: ", I2A(mut_max - 1), I2A(mut_max - 1) - 'a' + 'A'); prt(tmp, 0, 0); - if (quick) + while (1) { + /* Print power list */ print_spell_batch(batch, mut_max); - } - while (1) - { /* Get a command */ which = inkey(); @@ -4440,16 +4438,6 @@ static random_spell* select_spell_from_batch(int batch, bool_ quick) } - /* List */ - if (which == '*' || which == '?' || which == ' ') - { - /* Print power list */ - print_spell_batch(batch, mut_max); - - /* Wait for next command */ - continue; - } - /* Accept default */ if (which == '\r') { @@ -4552,7 +4540,7 @@ static random_spell* select_spell_from_batch(int batch, bool_ quick) /* * Pick a random spell from a menu */ -random_spell* select_spell(bool_ quick) +static random_spell* select_spell() { char tmp[160]; @@ -4593,6 +4581,8 @@ random_spell* select_spell(bool_ quick) if (which == ESCAPE) { + Term_load(); + ret = NULL; break; @@ -4602,7 +4592,9 @@ random_spell* select_spell(bool_ quick) { if (batch_max == 0) { - ret = select_spell_from_batch(0, quick); + Term_load(); + + ret = select_spell_from_batch(0); break; } @@ -4613,7 +4605,9 @@ random_spell* select_spell(bool_ quick) which = tolower(which); if (isalpha(which) && (A2I(which) <= batch_max)) { - ret = select_spell_from_batch(A2I(which), quick); + Term_load(); + + ret = select_spell_from_batch(A2I(which)); break; } @@ -4623,9 +4617,6 @@ random_spell* select_spell(bool_ quick) } } - /* Restore the screen */ - Term_load(); - /* Leave "icky" mode */ character_icky = FALSE; @@ -4659,7 +4650,7 @@ void do_cmd_powermage(void) } - s_ptr = select_spell(FALSE); + s_ptr = select_spell(); if (s_ptr == NULL) return; diff --git a/src/externs.h b/src/externs.h index ea2c4831..3a4c50b5 100644 --- a/src/externs.h +++ b/src/externs.h @@ -828,7 +828,6 @@ extern void necro_info(char *p, int power); extern void mindcraft_info(char *p, int power); extern void symbiotic_info(char *p, int power); extern void mimic_info(char *p, int power); -extern random_spell* select_spell(bool_ quick); extern void cast_magic_spell(int spell, byte level); extern void do_cmd_summoner(void); extern void do_cmd_mindcraft(void); -- cgit v1.2.3 From 72bde5e602786fd349f6cc6642fff6f9c5658e1c Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 14:40:48 +0200 Subject: Show rune spells immediately when using --- src/cmd7.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/cmd7.c b/src/cmd7.c index d148dc07..cb655526 100644 --- a/src/cmd7.c +++ b/src/cmd7.c @@ -6058,8 +6058,7 @@ static void print_runespell_batch(int batch, int max) * List ten random spells and ask to pick one. */ -static rune_spell* select_runespell_from_batch(int batch, bool_ quick, - int *s_idx) +static rune_spell* select_runespell_from_batch(int batch, int *s_idx) { char tmp[160]; @@ -6073,7 +6072,6 @@ static rune_spell* select_runespell_from_batch(int batch, bool_ quick, character_icky = TRUE; - Term_save(); if (rune_num < (batch + 1) * 10) { @@ -6085,15 +6083,16 @@ static rune_spell* select_runespell_from_batch(int batch, bool_ quick, prt(tmp, 0, 0); - if (quick) + while (1) { + Term_save(); + print_runespell_batch(batch, mut_max); - } - while (1) - { which = inkey(); + Term_load(); + if (which == ESCAPE) { *s_idx = -1; @@ -6146,7 +6145,6 @@ static rune_spell* select_runespell_from_batch(int batch, bool_ quick, } } - Term_load(); character_icky = FALSE; return (ret); @@ -6157,7 +6155,7 @@ static rune_spell* select_runespell_from_batch(int batch, bool_ quick, * Pick a random spell from a menu */ -rune_spell* select_runespell(bool_ quick, int *s_idx) +rune_spell* select_runespell(int *s_idx) { char tmp[160]; @@ -6192,7 +6190,7 @@ rune_spell* select_runespell(bool_ quick, int *s_idx) { Term_load(); character_icky = FALSE; - return (select_runespell_from_batch(0, quick, s_idx)); + return (select_runespell_from_batch(0, s_idx)); } else @@ -6202,7 +6200,7 @@ rune_spell* select_runespell(bool_ quick, int *s_idx) { Term_load(); character_icky = FALSE; - return (select_runespell_from_batch(A2I(which), quick, s_idx)); + return (select_runespell_from_batch(A2I(which), s_idx)); } else { @@ -6252,7 +6250,7 @@ void do_cmd_rune_cast() return; } - s_ptr = select_runespell(FALSE, &s_idx); + s_ptr = select_runespell(&s_idx); if (s_ptr == NULL) return; @@ -6524,7 +6522,7 @@ void do_cmd_rune_del() return; } - s_ptr = select_runespell(FALSE, &s_idx); + s_ptr = select_runespell(&s_idx); if (s_ptr == NULL) return; -- cgit v1.2.3 From 6c3d9cd354cc69bbbc719e0be91169946e3212a0 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 17:09:57 +0200 Subject: Quarks: Move subsystem to separate compilation unit --- src/CMakeLists.txt | 1 + src/cmd1.c | 3 ++ src/cmd3.c | 1 + src/cmd5.c | 2 ++ src/cmd7.c | 1 + src/dungeon.c | 3 ++ src/externs.h | 4 --- src/init2.c | 5 ++-- src/loadsave.c | 1 + src/melee2.c | 2 ++ src/object1.c | 1 + src/plots.c | 1 + src/powers.c | 2 ++ src/q_god.c | 3 ++ src/quark.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/quark.h | 10 +++++++ src/randart.c | 2 ++ src/squeltch.c | 3 ++ src/store.c | 2 ++ src/util.c | 68 ++--------------------------------------- src/variable.c | 11 ------- src/xtra2.c | 3 ++ 22 files changed, 134 insertions(+), 83 deletions(-) create mode 100644 src/quark.c create mode 100644 src/quark.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 22563cd4..0e71e07b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,6 +15,7 @@ SET(SRCS generate.c gen_maze.c gen_evol.c wild.c levels.c store.c bldg.c cmovie.c wizard2.c init2.c birth.c wizard1.c init1.c main.c + quark.c # Lua bits: lua_bind.c script.c ) diff --git a/src/cmd1.c b/src/cmd1.c index ce43c008..98fa264b 100644 --- a/src/cmd1.c +++ b/src/cmd1.c @@ -11,6 +11,9 @@ */ #include "angband.h" + +#include "quark.h" + #define MAX_VAMPIRIC_DRAIN 100 diff --git a/src/cmd3.c b/src/cmd3.c index 02dbc1c4..d648a0dc 100644 --- a/src/cmd3.c +++ b/src/cmd3.c @@ -12,6 +12,7 @@ #include "angband.h" +#include "quark.h" /* * Display p_ptr->inventory diff --git a/src/cmd5.c b/src/cmd5.c index 7b7d334d..51fd6f17 100644 --- a/src/cmd5.c +++ b/src/cmd5.c @@ -15,6 +15,8 @@ #include +#include "quark.h" + /* Maximum number of tries for teleporting */ #define MAX_TRIES 300 diff --git a/src/cmd7.c b/src/cmd7.c index cb655526..0276a6b6 100644 --- a/src/cmd7.c +++ b/src/cmd7.c @@ -13,6 +13,7 @@ #include "angband.h" +#include "quark.h" /* * Describe class powers of Mindcrafters diff --git a/src/dungeon.c b/src/dungeon.c index 9bcb6839..3bf40690 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -11,8 +11,11 @@ */ #include "angband.h" + #include +#include "quark.h" + #define TY_CURSE_CHANCE 100 #define DG_CURSE_CHANCE 50 #define AUTO_CURSE_CHANCE 15 diff --git a/src/externs.h b/src/externs.h index 3a4c50b5..2bd48d10 100644 --- a/src/externs.h +++ b/src/externs.h @@ -321,8 +321,6 @@ extern cptr *macro__pat; extern cptr *macro__act; extern bool_ *macro__cmd; extern char *macro__buf; -extern s16b quark__num; -extern cptr *quark__str; extern u32b option_flag[8]; extern u32b option_mask[8]; extern u32b window_flag[ANGBAND_TERM_MAX]; @@ -2042,8 +2040,6 @@ extern void keymap_init(void); extern errr macro_add(cptr pat, cptr act); extern sint macro_find_exact(cptr pat); extern char inkey(void); -extern cptr quark_str(s16b num); -extern s16b quark_add(cptr str); extern void display_message(int x, int y, int split, byte color, cptr t); extern void cmsg_print(byte color, cptr msg); extern void msg_print(cptr msg); diff --git a/src/init2.c b/src/init2.c index dfb8a5dc..1e5ff17f 100644 --- a/src/init2.c +++ b/src/init2.c @@ -7,6 +7,7 @@ #include #include "messages.h" +#include "quark.h" /* * This file is used to initialise various variables and arrays for the @@ -1948,8 +1949,8 @@ static errr init_misc(void) /*** Prepare the various "bizarre" arrays ***/ - /* Quark variables */ - C_MAKE(quark__str, QUARK_MAX, cptr); + /* Initialize quark subsystem */ + quark_init(); /* Initialize messages subsystem */ message_init(); diff --git a/src/loadsave.c b/src/loadsave.c index de3bcd60..4ec7a02a 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -7,6 +7,7 @@ #include "angband.h" #include "messages.h" +#include "quark.h" static void do_byte(byte *, int); static void do_bool(bool_ *, int); diff --git a/src/melee2.c b/src/melee2.c index 2880c99c..5443a214 100644 --- a/src/melee2.c +++ b/src/melee2.c @@ -16,7 +16,9 @@ */ #include "angband.h" + #include "messages.h" +#include "quark.h" #define SPEAK_CHANCE 8 #define GRINDNOISE 20 diff --git a/src/object1.c b/src/object1.c index 7d40a8c3..21161dea 100644 --- a/src/object1.c +++ b/src/object1.c @@ -12,6 +12,7 @@ #include "angband.h" +#include "quark.h" /* * Hack -- note that "TERM_MULTI" is now just "TERM_VIOLET". diff --git a/src/plots.c b/src/plots.c index 754ab401..ce60b446 100644 --- a/src/plots.c +++ b/src/plots.c @@ -15,6 +15,7 @@ #include #include "messages.h" +#include "quark.h" /* #define DEBUG_HOOK */ diff --git a/src/powers.c b/src/powers.c index a12d55f6..afc4a13a 100644 --- a/src/powers.c +++ b/src/powers.c @@ -12,6 +12,8 @@ #include "angband.h" +#include "quark.h" + /* * Note: return value indicates the amount of mana to use */ diff --git a/src/q_god.c b/src/q_god.c index a01a60a9..82f90a25 100644 --- a/src/q_god.c +++ b/src/q_god.c @@ -1,6 +1,9 @@ #include "angband.h" + #include +#include "quark.h" + #define cquest (quest[QUEST_GOD]) #define cquest_quests_given (cquest.data[0]) #define cquest_relics_found (cquest.data[1]) diff --git a/src/quark.c b/src/quark.c new file mode 100644 index 00000000..32efaaa0 --- /dev/null +++ b/src/quark.c @@ -0,0 +1,88 @@ +#include "quark.h" + +#include "angband.h" + +/* + * The number of quarks + */ +static s16b quark__num = 0; + + +/* + * The pointers to the quarks [QUARK_MAX] + */ +static cptr *quark__str = NULL; + + +/* + * Initialize the quark subsystem + */ +void quark_init() +{ + quark__num = 0; + C_MAKE(quark__str, QUARK_MAX, cptr); +} + + +/* +* We use a global array for all inscriptions to reduce the memory +* spent maintaining inscriptions. Of course, it is still possible +* to run out of inscription memory, especially if too many different +* inscriptions are used, but hopefully this will be rare. +* +* We use dynamic string allocation because otherwise it is necessary +* to pre-guess the amount of quark activity. We limit the total +* number of quarks, but this is much easier to "expand" as needed. +* +* Any two items with the same inscription will have the same "quark" +* index, which should greatly reduce the need for inscription space. +* +* Note that "quark zero" is NULL and should not be "dereferenced". +*/ + +/* +* Add a new "quark" to the set of quarks. +*/ +s16b quark_add(cptr str) +{ + int i; + + /* Look for an existing quark */ + for (i = 1; i < quark__num; i++) + { + /* Check for equality */ + if (streq(quark__str[i], str)) return (i); + } + + /* Paranoia -- Require room */ + if (quark__num == QUARK_MAX) return (0); + + /* New maximal quark */ + quark__num = i + 1; + + /* Add a new quark */ + quark__str[i] = string_make(str); + + /* Return the index */ + return (i); +} + + +/* +* This function looks up a quark +*/ +cptr quark_str(s16b i) +{ + cptr q; + + /* Verify */ + if ((i < 0) || (i >= quark__num)) i = 0; + + /* Access the quark */ + q = quark__str[i]; + + /* Return the quark */ + return (q); +} + + diff --git a/src/quark.h b/src/quark.h new file mode 100644 index 00000000..93cb938f --- /dev/null +++ b/src/quark.h @@ -0,0 +1,10 @@ +#ifndef H_eeb941c7_1a44_405a_8db3_ba14732c5b94 +#define H_eeb941c7_1a44_405a_8db3_ba14732c5b94 + +#include "h-type.h" + +void quark_init(); +cptr quark_str(s16b num); +s16b quark_add(cptr str); + +#endif diff --git a/src/randart.c b/src/randart.c index 580fa144..10fd51b0 100644 --- a/src/randart.c +++ b/src/randart.c @@ -12,6 +12,8 @@ #include "angband.h" +#include "quark.h" + /* Chance of using syllables to form the name instead of the "template" files */ #define TABLE_NAME 45 #define A_CURSED 13 diff --git a/src/squeltch.c b/src/squeltch.c index 5fb95d75..d79e1989 100644 --- a/src/squeltch.c +++ b/src/squeltch.c @@ -11,8 +11,11 @@ */ #include "angband.h" + #include +#include "quark.h" + #define RULES_MAX 4096 #define STACK_MAX 1024 diff --git a/src/store.c b/src/store.c index e62701d9..cca3be85 100644 --- a/src/store.c +++ b/src/store.c @@ -12,6 +12,8 @@ #include "angband.h" +#include "quark.h" + #define STORE_GENERAL_STORE "General Store" #define STORE_ARMOURY "Armoury" #define STORE_WEAPONSMITH "Weaponsmith" diff --git a/src/util.c b/src/util.c index a9a9d10a..cf72eb1f 100644 --- a/src/util.c +++ b/src/util.c @@ -4,8 +4,9 @@ #include "angband.h" -#include "messages.h" +#include "messages.h" +#include "quark.h" @@ -2064,71 +2065,6 @@ char inkey(void) return (ch); } - - - -/* -* We use a global array for all inscriptions to reduce the memory -* spent maintaining inscriptions. Of course, it is still possible -* to run out of inscription memory, especially if too many different -* inscriptions are used, but hopefully this will be rare. -* -* We use dynamic string allocation because otherwise it is necessary -* to pre-guess the amount of quark activity. We limit the total -* number of quarks, but this is much easier to "expand" as needed. -* -* Any two items with the same inscription will have the same "quark" -* index, which should greatly reduce the need for inscription space. -* -* Note that "quark zero" is NULL and should not be "dereferenced". -*/ - -/* -* Add a new "quark" to the set of quarks. -*/ -s16b quark_add(cptr str) -{ - int i; - - /* Look for an existing quark */ - for (i = 1; i < quark__num; i++) - { - /* Check for equality */ - if (streq(quark__str[i], str)) return (i); - } - - /* Paranoia -- Require room */ - if (quark__num == QUARK_MAX) return (0); - - /* New maximal quark */ - quark__num = i + 1; - - /* Add a new quark */ - quark__str[i] = string_make(str); - - /* Return the index */ - return (i); -} - - -/* -* This function looks up a quark -*/ -cptr quark_str(s16b i) -{ - cptr q; - - /* Verify */ - if ((i < 0) || (i >= quark__num)) i = 0; - - /* Access the quark */ - q = quark__str[i]; - - /* Return the quark */ - return (q); -} - - /* * Hack -- flush */ diff --git a/src/variable.c b/src/variable.c index ab9bf699..af89fdcf 100644 --- a/src/variable.c +++ b/src/variable.c @@ -482,17 +482,6 @@ bool_ *macro__cmd; char *macro__buf; -/* - * The number of quarks - */ -s16b quark__num; - -/* - * The pointers to the quarks [QUARK_MAX] - */ -cptr *quark__str; - - /* * The array of normal options */ diff --git a/src/xtra2.c b/src/xtra2.c index 1569f442..6594e482 100644 --- a/src/xtra2.c +++ b/src/xtra2.c @@ -12,8 +12,11 @@ */ #include "angband.h" + #include +#include "quark.h" + /* * Invoke The Rush */ -- cgit v1.2.3 From 67485c9c36e244861c6226a3854781d1dd16f3ca Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 17:22:37 +0200 Subject: Remove ANGBAND_DIR_APEX since it's not used any more --- src/config.h | 2 -- src/externs.h | 1 - src/files.c | 8 ++++---- src/init2.c | 10 +--------- src/main-crb.c | 13 +------------ src/main-win.c | 3 +-- src/main.c | 7 ------- src/modules.c | 5 ----- src/variable.c | 6 ------ 9 files changed, 7 insertions(+), 48 deletions(-) diff --git a/src/config.h b/src/config.h index 7c1cf1d7..20463a62 100644 --- a/src/config.h +++ b/src/config.h @@ -236,11 +236,9 @@ #if defined(MACH_O_CARBON) #define PRIVATE_USER_PATH "~/Library/Application Support/ToME" #define PRIVATE_USER_PATH_DATA -#define PRIVATE_USER_PATH_APEX #define PRIVATE_USER_PATH_MODULES #else #define PRIVATE_USER_PATH "~/.tome" -#define PRIVATE_USER_PATH_APEX #endif /* diff --git a/src/externs.h b/src/externs.h index 2bd48d10..1e5b71f4 100644 --- a/src/externs.h +++ b/src/externs.h @@ -445,7 +445,6 @@ extern cptr ANGBAND_SYS; extern cptr ANGBAND_KEYBOARD; extern cptr ANGBAND_GRAF; extern cptr ANGBAND_DIR; -extern cptr ANGBAND_DIR_APEX; extern cptr ANGBAND_DIR_CORE; extern cptr ANGBAND_DIR_DNGN; extern cptr ANGBAND_DIR_DATA; diff --git a/src/files.c b/src/files.c index ee3bc86c..01f55d7e 100644 --- a/src/files.c +++ b/src/files.c @@ -5036,7 +5036,7 @@ void display_scores(int from, int to) char buf[1024]; /* Build the filename */ - path_build(buf, 1024, ANGBAND_DIR_APEX, "scores.raw"); + path_build(buf, 1024, ANGBAND_DIR_USER, "scores.raw"); /* Open the binary high score file, for reading */ highscore_fd = fd_open(buf, O_RDONLY); @@ -5108,7 +5108,7 @@ void show_highclass(int building) } /* Build the filename */ - path_build(buf, 1024, ANGBAND_DIR_APEX, "scores.raw"); + path_build(buf, 1024, ANGBAND_DIR_USER, "scores.raw"); /* Open file */ highscore_fd = fd_open(buf, O_RDONLY); @@ -5199,7 +5199,7 @@ void race_score(int race_num) prt(tmp_str, 5, 3); /* Build the filename */ - path_build(buf, 1024, ANGBAND_DIR_APEX, "scores.raw"); + path_build(buf, 1024, ANGBAND_DIR_USER, "scores.raw"); /* Open the highscore file */ highscore_fd = fd_open(buf, O_RDONLY); @@ -5636,7 +5636,7 @@ void close_game(void) /* Build the filename */ - path_build(buf, 1024, ANGBAND_DIR_APEX, "scores.raw"); + path_build(buf, 1024, ANGBAND_DIR_USER, "scores.raw"); /* Open the high score file, for reading/writing */ highscore_fd = fd_open(buf, O_RDWR); diff --git a/src/init2.c b/src/init2.c index 1e5ff17f..977e6d1a 100644 --- a/src/init2.c +++ b/src/init2.c @@ -74,7 +74,6 @@ void init_file_paths(char *path) string_free(ANGBAND_DIR); /* Free the sub-paths */ - string_free(ANGBAND_DIR_APEX); string_free(ANGBAND_DIR_CORE); string_free(ANGBAND_DIR_DNGN); string_free(ANGBAND_DIR_DATA); @@ -125,10 +124,6 @@ void init_file_paths(char *path) /*** Build the sub-directory names ***/ - /* Build a path name */ - strcpy(tail, "apex"); - ANGBAND_DIR_APEX = string_make(path); - /* Build a path name */ strcpy(tail, "core"); ANGBAND_DIR_CORE = string_make(path); @@ -186,9 +181,6 @@ void init_file_paths(char *path) #ifdef PRIVATE_USER_PATH_MODULES ANGBAND_DIR_MODULES = string_make(user_path); #endif -#ifdef PRIVATE_USER_PATH_APEX - ANGBAND_DIR_APEX = string_make(user_path); -#endif #ifdef PRIVATE_USER_PATH_DATA { char user_path_data[1024]; @@ -2608,7 +2600,7 @@ void init_angband(void) /*** Verify (or create) the "high score" file ***/ /* Build the filename */ - path_build(buf, 1024, ANGBAND_DIR_APEX, "scores.raw"); + path_build(buf, 1024, ANGBAND_DIR_USER, "scores.raw"); /* Attempt to open the high score file */ fd = fd_open(buf, O_RDONLY); diff --git a/src/main-crb.c b/src/main-crb.c index a4a1a742..0877bec6 100644 --- a/src/main-crb.c +++ b/src/main-crb.c @@ -531,9 +531,6 @@ static bool_ check_create_user_dir(void) #ifdef PRIVATE_USER_PATH_DATA char datapath[1024]; #endif -#ifdef PRIVATE_USER_PATH_APEX - char apexpath[1024]; -#endif /* Get an absolute path from the filename */ path_parse(dirpath, 1024, PRIVATE_USER_PATH); @@ -545,19 +542,12 @@ static bool_ check_create_user_dir(void) strcpy(datapath, versionpath); strcat(datapath, "/data"); #endif -#ifdef PRIVATE_USER_PATH_APEX - strcpy(apexpath, versionpath); - strcat(apexpath, "/apex"); -#endif return /* don't forget, the dirpath muts come first */ private_check_user_directory(dirpath) && private_check_user_directory(versionpath) && #ifdef PRIVATE_USER_PATH_DATA private_check_user_directory(datapath) && -#endif -#ifdef PRIVATE_USER_PATH_APEX - private_check_user_directory(apexpath) && #endif private_check_user_directory(savepath); } @@ -4825,8 +4815,7 @@ static void menu(long mc) } /* Build the pathname of the score file */ - path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, - "scores.raw"); + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "scores.raw"); /* Hack - open the score file for reading */ highscore_fd = fd_open(buf, O_RDONLY); diff --git a/src/main-win.c b/src/main-win.c index 92a2a775..1498672d 100644 --- a/src/main-win.c +++ b/src/main-win.c @@ -2952,7 +2952,7 @@ ofn.lStructSize = sizeof(OPENFILENAME); } /* Build the pathname of the score file */ - path_build(buf, sizeof(buf), ANGBAND_DIR_APEX, "scores.raw"); + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "scores.raw"); /* Hack - open the score file for reading */ highscore_fd = fd_open(buf, O_RDONLY); @@ -4136,7 +4136,6 @@ static void init_stuff(void) /*** Validate the paths to ensure we have a working install ***/ - validate_dir(ANGBAND_DIR_APEX); validate_dir(ANGBAND_DIR_DATA); validate_dir(ANGBAND_DIR_EDIT); validate_dir(ANGBAND_DIR_FILE); diff --git a/src/main.c b/src/main.c index 8dc87a2a..6bd2b154 100644 --- a/src/main.c +++ b/src/main.c @@ -163,13 +163,6 @@ static void change_path(cptr info) /* Analyze */ switch (tolower(info[0])) { - case 'a': - { - string_free(ANGBAND_DIR_APEX); - ANGBAND_DIR_APEX = string_make(s + 1); - break; - } - case 'f': { string_free(ANGBAND_DIR_FILE); diff --git a/src/modules.c b/src/modules.c index 60128f79..0c9250eb 100644 --- a/src/modules.c +++ b/src/modules.c @@ -32,7 +32,6 @@ void module_reset_dir(cptr dir, cptr new_path) cptr *d = 0; char buf[1025]; - if (!strcmp(dir, "apex")) d = &ANGBAND_DIR_APEX; if (!strcmp(dir, "core")) d = &ANGBAND_DIR_CORE; if (!strcmp(dir, "dngn")) d = &ANGBAND_DIR_DNGN; if (!strcmp(dir, "data")) d = &ANGBAND_DIR_DATA; @@ -48,9 +47,6 @@ void module_reset_dir(cptr dir, cptr new_path) if (!strcmp(dir, "note")) d = &ANGBAND_DIR_NOTE; if (!strcmp(dir, "cmov")) d = &ANGBAND_DIR_CMOV; if ( -#ifdef PRIVATE_USER_PATH_APEX - !strcmp(dir, "apex") || -#endif !strcmp(dir, "user") || !strcmp(dir, "note") || !strcmp(dir, "cmov")) @@ -158,7 +154,6 @@ static void init_module(module_type *module_ptr) /* Set up module directories? */ cptr dir = module_ptr->meta.module_dir; if (dir) { - module_reset_dir("apex", dir); module_reset_dir("core", dir); module_reset_dir("data", dir); module_reset_dir("dngn", dir); diff --git a/src/variable.c b/src/variable.c index af89fdcf..c7874c50 100644 --- a/src/variable.c +++ b/src/variable.c @@ -942,12 +942,6 @@ cptr ANGBAND_GRAF = "old"; */ cptr ANGBAND_DIR; -/* - * High score files (binary) - * These files may be portable between platforms - */ -cptr ANGBAND_DIR_APEX; - /* * Core lua system * These files are portable between platforms -- cgit v1.2.3 From 758e1f85d64024dce419cfe8a1cd3315b4b58b53 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 19:29:01 +0200 Subject: Remove "highscore_fd" global. --- src/externs.h | 2 +- src/files.c | 219 +++++++++++++++++++++++++++++++++++++-------------------- src/main-crb.c | 66 +---------------- src/main-win.c | 66 +---------------- src/variable.c | 6 -- 5 files changed, 145 insertions(+), 214 deletions(-) diff --git a/src/externs.h b/src/externs.h index 1e5b71f4..bf742c29 100644 --- a/src/externs.h +++ b/src/externs.h @@ -190,7 +190,6 @@ extern FILE *text_out_file; extern void (*text_out_hook)(byte a, cptr str); extern int text_out_wrap; extern int text_out_indent; -extern int highscore_fd; extern bool_ show_inven_graph; extern bool_ show_store_graph; extern bool_ show_equip_graph; @@ -895,6 +894,7 @@ extern void autosave_checkpoint(); extern long total_points(void); extern void display_scores(int from, int to); extern errr predict_score(void); +extern void predict_score_gui(bool_ *initialized, bool_ *game_in_progress); extern void close_game(void); extern void signals_ignore_tstp(void); extern void signals_handle_tstp(void); diff --git a/src/files.c b/src/files.c index 01f55d7e..ba60ae29 100644 --- a/src/files.c +++ b/src/files.c @@ -4753,7 +4753,7 @@ struct high_score /* * Seek score 'i' in the highscore file */ -static int highscore_seek(int i) +static int highscore_seek(int highscore_fd, int i) { /* Seek for the requested record */ return (fd_seek(highscore_fd, (huge)(i) * sizeof(high_score))); @@ -4763,7 +4763,7 @@ static int highscore_seek(int i) /* * Read one score from the highscore file */ -static errr highscore_read(high_score *score) +static errr highscore_read(int highscore_fd, high_score *score) { /* Read the record, note failure */ return (fd_read(highscore_fd, (char*)(score), sizeof(high_score))); @@ -4773,7 +4773,7 @@ static errr highscore_read(high_score *score) /* * Write one score to the highscore file */ -static int highscore_write(high_score *score) +static int highscore_write(int highscore_fd, high_score *score) { /* Write the record, note failure */ return (fd_write(highscore_fd, (char*)(score), sizeof(high_score))); @@ -4786,7 +4786,7 @@ static int highscore_write(high_score *score) * Just determine where a new score *would* be placed * Return the location (0 is best) or -1 on failure */ -static int highscore_where(high_score *score) +static int highscore_where(int highscore_fd, high_score *score) { int i; @@ -4796,12 +4796,12 @@ static int highscore_where(high_score *score) if (highscore_fd < 0) return ( -1); /* Go to the start of the highscore file */ - if (highscore_seek(0)) return ( -1); + if (highscore_seek(highscore_fd, 0)) return ( -1); /* Read until we get to a higher score */ for (i = 0; i < MAX_HISCORES; i++) { - if (highscore_read(&the_score)) return (i); + if (highscore_read(highscore_fd, &the_score)) return (i); if (strcmp(the_score.pts, score->pts) < 0) return (i); } @@ -4814,7 +4814,7 @@ static int highscore_where(high_score *score) * Actually place an entry into the high score file * Return the location (0 is best) or -1 on "failure" */ -static int highscore_add(high_score *score) +static int highscore_add(int highscore_fd, high_score *score) { int i, slot; bool_ done = FALSE; @@ -4826,7 +4826,7 @@ static int highscore_add(high_score *score) if (highscore_fd < 0) return ( -1); /* Determine where the score should go */ - slot = highscore_where(score); + slot = highscore_where(highscore_fd, score); /* Hack -- Not on the list */ if (slot < 0) return ( -1); @@ -4838,12 +4838,12 @@ static int highscore_add(high_score *score) for (i = slot; !done && (i < MAX_HISCORES); i++) { /* Read the old guy, note errors */ - if (highscore_seek(i)) return ( -1); - if (highscore_read(&tmpscore)) done = TRUE; + if (highscore_seek(highscore_fd, i)) return ( -1); + if (highscore_read(highscore_fd, &tmpscore)) done = TRUE; /* Back up and dump the score we were holding */ - if (highscore_seek(i)) return ( -1); - if (highscore_write(&the_score)) return ( -1); + if (highscore_seek(highscore_fd, i)) return ( -1); + if (highscore_write(highscore_fd, &the_score)) return ( -1); /* Hack -- Save the old score, for the next pass */ the_score = tmpscore; @@ -4862,7 +4862,7 @@ static int highscore_add(high_score *score) * * Mega-Hack -- allow "fake" entry at the given position. */ -static void display_scores_aux(int from, int to, int note, high_score *score) +static void display_scores_aux(int highscore_fd, int from, int to, int note, high_score *score) { int i, j, k, n, place; byte attr; @@ -4882,12 +4882,12 @@ static void display_scores_aux(int from, int to, int note, high_score *score) /* Seek to the beginning */ - if (highscore_seek(0)) return; + if (highscore_seek(highscore_fd, 0)) return; /* Hack -- Count the high scores */ for (i = 0; i < MAX_HISCORES; i++) { - if (highscore_read(&the_score)) break; + if (highscore_read(highscore_fd, &the_score)) break; } /* Hack -- allow "fake" entry to be last */ @@ -4940,8 +4940,8 @@ static void display_scores_aux(int from, int to, int note, high_score *score) else { /* Read the proper record */ - if (highscore_seek(j)) break; - if (highscore_read(&the_score)) break; + if (highscore_seek(highscore_fd, j)) break; + if (highscore_read(highscore_fd, &the_score)) break; } /* Extract the race/class */ @@ -5034,6 +5034,7 @@ static void display_scores_aux(int from, int to, int note, high_score *score) void display_scores(int from, int to) { char buf[1024]; + int highscore_fd; /* Build the filename */ path_build(buf, 1024, ANGBAND_DIR_USER, "scores.raw"); @@ -5048,13 +5049,10 @@ void display_scores(int from, int to) Term_clear(); /* Display the scores */ - display_scores_aux(from, to, -1, NULL); + display_scores_aux(highscore_fd, from, to, -1, NULL); /* Shut the high score file */ - (void)fd_close(highscore_fd); - - /* Forget the high score fd */ - highscore_fd = -1; + fd_close(highscore_fd); /* Quit */ quit(NULL); @@ -5072,6 +5070,7 @@ void show_highclass(int building) int pr, pc, clev, al; high_score the_score; char buf[1024], out_val[256]; + int highscore_fd; switch (building) { @@ -5120,10 +5119,10 @@ void show_highclass(int building) return; } - if (highscore_seek(0)) return; + if (highscore_seek(highscore_fd, 0)) return; for (i = 0; i < MAX_HISCORES; i++) - if (highscore_read(&the_score)) break; + if (highscore_read(highscore_fd, &the_score)) break; m = 0; j = 0; @@ -5131,8 +5130,8 @@ void show_highclass(int building) while ((m < 9) || (j < MAX_HISCORES)) { - if (highscore_seek(j)) break; - if (highscore_read(&the_score)) break; + if (highscore_seek(highscore_fd, j)) break; + if (highscore_read(highscore_fd, &the_score)) break; pr = atoi(the_score.p_r); pc = atoi(the_score.p_c); clev = atoi(the_score.cur_lev); @@ -5172,8 +5171,8 @@ void show_highclass(int building) } } - (void)fd_close(highscore_fd); - highscore_fd = -1; + fd_close(highscore_fd); + msg_print("Hit any key to continue"); msg_print(NULL); for (j = 5; j < 18; j++) @@ -5191,6 +5190,7 @@ void race_score(int race_num) int pr, clev, lastlev; high_score the_score; char buf[1024], out_val[256], tmp_str[80]; + int highscore_fd; lastlev = 0; @@ -5211,11 +5211,11 @@ void race_score(int race_num) return; } - if (highscore_seek(0)) return; + if (highscore_seek(highscore_fd, 0)) return; for (i = 0; i < MAX_HISCORES; i++) { - if (highscore_read(&the_score)) break; + if (highscore_read(highscore_fd, &the_score)) break; } m = 0; @@ -5223,8 +5223,8 @@ void race_score(int race_num) while ((m < 10) && (j < i)) { - if (highscore_seek(j)) break; - if (highscore_read(&the_score)) break; + if (highscore_seek(highscore_fd, j)) break; + if (highscore_read(highscore_fd, &the_score)) break; pr = atoi(the_score.p_r); clev = atoi(the_score.cur_lev); if (pr == race_num) @@ -5247,8 +5247,7 @@ void race_score(int race_num) prt(out_val, (m + 8), 0); } - (void)fd_close(highscore_fd); - highscore_fd = -1; + fd_close(highscore_fd); } @@ -5287,26 +5286,34 @@ static errr top_twenty(void) time_t ct = time((time_t*)0); + char buf[1024]; - /* Clear screen */ - Term_clear(); + int highscore_fd = 0; + + /* Build the filename */ + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "scores.raw"); + + /* Open the highscore file, for reading/writing */ + highscore_fd = fd_open(buf, O_RDWR); - /* No score file */ if (highscore_fd < 0) { msg_print("Score file unavailable."); msg_print(NULL); - return (0); + goto out; } + /* Clear screen */ + Term_clear(); + #ifndef SCORE_WIZARDS /* Wizard-mode pre-empts scoring */ if (noscore & 0x000F) { msg_print("Score not registered for wizards."); msg_print(NULL); - display_scores_aux(0, 10, -1, NULL); - return (0); + display_scores_aux(highscore_fd, 0, 10, -1, NULL); + goto out; } #endif @@ -5316,8 +5323,8 @@ static errr top_twenty(void) { msg_print("Score not registered for borgs."); msg_print(NULL); - display_scores_aux(0, 10, -1, NULL); - return (0); + display_scores_aux(highscore_fd, 0, 10, -1, NULL); + goto out; } #endif @@ -5327,8 +5334,8 @@ static errr top_twenty(void) { msg_print("Score not registered for cheaters."); msg_print(NULL); - display_scores_aux(0, 10, -1, NULL); - return (0); + display_scores_aux(highscore_fd, 0, 10, -1, NULL); + goto out; } #endif @@ -5337,8 +5344,8 @@ static errr top_twenty(void) { msg_print("Score not registered due to interruption."); msg_print(NULL); - display_scores_aux(0, 10, -1, NULL); - return (0); + display_scores_aux(highscore_fd, 0, 10, -1, NULL); + goto out; } /* Quitter */ @@ -5346,8 +5353,8 @@ static errr top_twenty(void) { msg_print("Score not registered due to quitting."); msg_print(NULL); - display_scores_aux(0, 10, -1, NULL); - return (0); + display_scores_aux(highscore_fd, 0, 10, -1, NULL); + goto out; } @@ -5404,30 +5411,30 @@ static errr top_twenty(void) sprintf(the_score.how, "%-.31s", died_from); - /* Lock (for writing) the highscore file, or fail */ - if (fd_lock(highscore_fd, F_WRLCK)) return (1); - /* Add a new entry to the score list, see where it went */ - j = highscore_add(&the_score); - - /* Unlock the highscore file, or fail */ - if (fd_lock(highscore_fd, F_UNLCK)) return (1); + j = highscore_add(highscore_fd, &the_score); /* Hack -- Display the top fifteen scores */ if (j < 10) { - display_scores_aux(0, 15, j, NULL); + display_scores_aux(highscore_fd, 0, 15, j, NULL); } /* Display the scores surrounding the player */ else { - display_scores_aux(0, 5, j, NULL); - display_scores_aux(j - 2, j + 7, j, NULL); + display_scores_aux(highscore_fd, 0, 5, j, NULL); + display_scores_aux(highscore_fd, j - 2, j + 7, j, NULL); } +out: + if (highscore_fd >= 0) + { + fd_close(highscore_fd); + } + /* Success */ return (0); } @@ -5442,16 +5449,23 @@ errr predict_score(void) high_score the_score; + char buf[1024]; + + int highscore_fd = 0; + + /* Build the filename */ + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "scores.raw"); + + /* Open the highscore file */ + highscore_fd = fd_open(buf, O_RDONLY); - /* No score file */ if (highscore_fd < 0) { msg_print("Score file unavailable."); msg_print(NULL); - return (0); + goto out; } - /* Save the version */ sprintf(the_score.what, "%ld.%ld.%ld", (long int) VERSION_MAJOR, (long int) VERSION_MINOR, (long int) VERSION_PATCH); @@ -5498,28 +5512,91 @@ errr predict_score(void) /* See where the entry would be placed */ - j = highscore_where(&the_score); + j = highscore_where(highscore_fd, &the_score); /* Hack -- Display the top fifteen scores */ if (j < 10) { - display_scores_aux(0, 15, j, &the_score); + display_scores_aux(highscore_fd, 0, 15, j, &the_score); } /* Display some "useful" scores */ else { - display_scores_aux(0, 5, -1, NULL); - display_scores_aux(j - 2, j + 7, j, &the_score); + display_scores_aux(highscore_fd, 0, 5, -1, NULL); + display_scores_aux(highscore_fd, j - 2, j + 7, j, &the_score); } +out: + if (highscore_fd >= 0) + { + fd_close(highscore_fd); + } /* Success */ return (0); } +void predict_score_gui(bool_ *initialized_p, bool_ *game_in_progress_p) +{ + char buf[1024]; + int highscore_fd; + + /* Paranoia */ + if (!(*initialized_p) || character_icky || + !(*game_in_progress_p) || !character_generated) + { + /* Can't happen but just in case */ + plog("You may not do that right now."); + return; + } + + /* Build the pathname of the score file */ + path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "scores.raw"); + + /* Hack - open the score file for reading */ + highscore_fd = fd_open(buf, O_RDONLY); + + /* Paranoia - No score file */ + if (highscore_fd < 0) + { + msg_print("Score file is not available."); + return; + } + + /* Mega-Hack - prevent various functions XXX XXX XXX */ + *initialized_p = FALSE; + + /* Save screen */ + screen_save(); + + /* Clear screen */ + Term_clear(); + + /* Prepare scores */ + if ((*game_in_progress_p) && character_generated) + { + predict_score(); + } + + /* Close the high score file */ + (void)fd_close(highscore_fd); + + /* Forget the fd */ + highscore_fd = -1; + + /* Restore screen */ + screen_load(); + + /* Hack - Flush it */ + Term_fresh(); + + /* Mega-Hack - We are ready again */ + *initialized_p = TRUE; +} + /* * Change the player into a King! -RAK- @@ -5635,12 +5712,6 @@ void close_game(void) character_icky = TRUE; - /* Build the filename */ - path_build(buf, 1024, ANGBAND_DIR_USER, "scores.raw"); - - /* Open the high score file, for reading/writing */ - highscore_fd = fd_open(buf, O_RDWR); - /* Handle death */ if (death) { @@ -5713,12 +5784,6 @@ void close_game(void) } - /* Shut the high score file */ - (void)fd_close(highscore_fd); - - /* Forget the high score fd */ - highscore_fd = -1; - /* Allow suspending now */ signals_handle_tstp(); } diff --git a/src/main-crb.c b/src/main-crb.c index 0877bec6..86604471 100644 --- a/src/main-crb.c +++ b/src/main-crb.c @@ -4802,71 +4802,7 @@ static void menu(long mc) /* Show score */ case ITEM_SCORE: { - char buf[1024]; - - /* Paranoia */ - if (!initialized || character_icky || - !game_in_progress || !character_generated) - { - /* Can't happen but just in case */ - plog("You may not do that right now."); - - break; - } - - /* Build the pathname of the score file */ - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "scores.raw"); - - /* Hack - open the score file for reading */ - highscore_fd = fd_open(buf, O_RDONLY); - - /* Paranoia - No score file */ - if (highscore_fd < 0) - { - msg_print("Score file is not available."); - - break; - } - - /* Mega-Hack - prevent various functions XXX XXX XXX */ - initialized = FALSE; - - /* Save screen */ - screen_save(); - - /* Clear screen */ - Term_clear(); - - /* Prepare scores */ - if (game_in_progress && character_generated) - { - predict_score(); - } - -#if 0 /* I don't like this - pelpel */ - - /* Mega-Hack - No current player XXX XXX XXX XXX */ - else - { - display_scores_aux(0, MAX_HISCORES, -1, NULL); - } - -#endif - - /* Close the high score file */ - (void)fd_close(highscore_fd); - - /* Forget the fd */ - highscore_fd = -1; - - /* Restore screen */ - screen_load(); - - /* Hack - Flush it */ - Term_fresh(); - - /* Mega-Hack - We are ready again */ - initialized = TRUE; + predict_score_gui(&initialized, &game_in_progress); /* Done */ break; diff --git a/src/main-win.c b/src/main-win.c index 1498672d..3674c88d 100644 --- a/src/main-win.c +++ b/src/main-win.c @@ -2939,71 +2939,7 @@ ofn.lStructSize = sizeof(OPENFILENAME); /* Score */ case IDM_FILE_SCORE: { - char buf[1024]; - - /* Paranoia */ - if (!initialized || character_icky || - !game_in_progress || !character_generated) - { - /* Can't happen but just in case */ - plog("You may not do that right now."); - - break; - } - - /* Build the pathname of the score file */ - path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "scores.raw"); - - /* Hack - open the score file for reading */ - highscore_fd = fd_open(buf, O_RDONLY); - - /* Paranoia - No score file */ - if (highscore_fd < 0) - { - msg_print("Score file is not available."); - - break; - } - - /* Mega-Hack - prevent various functions XXX XXX XXX */ - initialized = FALSE; - - /* Save screen */ - screen_save(); - - /* Clear screen */ - Term_clear(); - - /* Prepare scores */ - if (game_in_progress && character_generated) - { - predict_score(); - } - -#if 0 /* I don't like this - pelpel */ - - /* Mega-Hack - No current player XXX XXX XXX XXX */ - else - { - display_scores_aux(0, MAX_HISCORES, -1, NULL); - } - -#endif - - /* Close the high score file */ - (void)fd_close(highscore_fd); - - /* Forget the fd */ - highscore_fd = -1; - - /* Restore screen */ - screen_load(); - - /* Hack - Flush it */ - Term_fresh(); - - /* Mega-Hack - We are ready again */ - initialized = TRUE; + predict_score_gui(&initialized, &game_in_progress); /* Done */ break; diff --git a/src/variable.c b/src/variable.c index c7874c50..88728216 100644 --- a/src/variable.c +++ b/src/variable.c @@ -197,12 +197,6 @@ int text_out_wrap = 0; int text_out_indent = 0; -/* - * The "highscore" file descriptor, if available. - */ -int highscore_fd = -1; - - /* * Software options (set via the '=' command). See "tables.c" */ -- cgit v1.2.3 From 06b20f4b9d18f0a8730707d63f9714719157a9a3 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 19:49:18 +0200 Subject: Remove HIGHSCORE_DATE_HACK --- src/files.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/files.c b/src/files.c index ba60ae29..4e2ff70a 100644 --- a/src/files.c +++ b/src/files.c @@ -5377,13 +5377,8 @@ static errr top_twenty(void) sprintf(the_score.turns, "%9lu", (long)turn - (START_DAY * 10L)); the_score.turns[9] = '\0'; -#ifdef HIGHSCORE_DATE_HACK - /* Save the date in a hacked up form (9 chars) */ - sprintf(the_score.day, "%-.6s %-.2s", ctime(&ct) + 4, ctime(&ct) + 22); -#else /* Save the date in standard form (8 chars) */ strftime(the_score.day, 9, "%m/%d/%y", localtime(&ct)); -#endif /* Save the player name (15 chars) */ sprintf(the_score.who, "%-.15s", player_name); -- cgit v1.2.3 From 2b9664ae8b76dadaace0bd55f6d7b6dbe1367255 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 20:07:56 +0200 Subject: Remove SCORE_{BORGS,WIZARDS,CHEATERS} preprocessor defines --- src/config.h | 15 --------------- src/files.c | 6 ------ 2 files changed, 21 deletions(-) diff --git a/src/config.h b/src/config.h index 20463a62..99b6b9f0 100644 --- a/src/config.h +++ b/src/config.h @@ -135,21 +135,6 @@ #define HANDLE_SIGNALS -/* - * Allow "Wizards" to yield "high scores" - */ -/* #define SCORE_WIZARDS */ - -/* - * Allow "Borgs" to yield "high scores" - */ -/*#define SCORE_BORGS*/ - -/* - * Allow "Cheaters" to yield "high scores" - */ -/* #define SCORE_CHEATERS */ - /* diff --git a/src/files.c b/src/files.c index 4e2ff70a..cd3a5bf4 100644 --- a/src/files.c +++ b/src/files.c @@ -5306,7 +5306,6 @@ static errr top_twenty(void) /* Clear screen */ Term_clear(); -#ifndef SCORE_WIZARDS /* Wizard-mode pre-empts scoring */ if (noscore & 0x000F) { @@ -5315,9 +5314,7 @@ static errr top_twenty(void) display_scores_aux(highscore_fd, 0, 10, -1, NULL); goto out; } -#endif -#ifndef SCORE_BORGS /* Borg-mode pre-empts scoring */ if (noscore & 0x00F0) { @@ -5326,9 +5323,7 @@ static errr top_twenty(void) display_scores_aux(highscore_fd, 0, 10, -1, NULL); goto out; } -#endif -#ifndef SCORE_CHEATERS /* Cheaters are not scored */ if (noscore & 0xFF00) { @@ -5337,7 +5332,6 @@ static errr top_twenty(void) display_scores_aux(highscore_fd, 0, 10, -1, NULL); goto out; } -#endif /* Interupted */ if (!total_winner && streq(died_from, "Interrupting")) -- cgit v1.2.3 From 6e7e34189889e6fc371b7231411824ed34577807 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 20:17:24 +0200 Subject: Remove "text_out_wrap" global --- src/externs.h | 1 - src/util.c | 12 ++++-------- src/variable.c | 7 ------- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/src/externs.h b/src/externs.h index bf742c29..74cc34bd 100644 --- a/src/externs.h +++ b/src/externs.h @@ -188,7 +188,6 @@ extern bool_ is_autosave; extern int artifact_bias; extern FILE *text_out_file; extern void (*text_out_hook)(byte a, cptr str); -extern int text_out_wrap; extern int text_out_indent; extern bool_ show_inven_graph; extern bool_ show_store_graph; diff --git a/src/util.c b/src/util.c index cf72eb1f..bc8478e2 100644 --- a/src/util.c +++ b/src/util.c @@ -2440,11 +2440,8 @@ void text_out_to_screen(byte a, cptr str) /* Obtain the cursor */ (void)Term_locate(&x, &y); - /* Use special wrapping boundary? */ - if ((text_out_wrap > 0) && (text_out_wrap < wid)) - wrap = text_out_wrap; - else - wrap = wid; + /* Wrapping boundary */ + wrap = wid; /* Process the string */ for (s = str; *s; s++) @@ -2531,8 +2528,7 @@ void text_out_to_screen(byte a, cptr str) * Hook function for text_out(). Make sure that text_out_file points * to an open text-file. * - * Long lines will be wrapped at text_out_wrap, or at column 75 if that - * is not set; or at a newline character. + * Long lines will be wrapped at column 75 ; or at a newline character. * * You must be careful to end all file output with a newline character * to "flush" the stored line position. @@ -2543,7 +2539,7 @@ void text_out_to_file(byte a, cptr str) static int pos = 0; /* Wrap width */ - int wrap = (text_out_wrap ? text_out_wrap : 75); + int wrap = 75; /* Current location within "str" */ cptr s = str; diff --git a/src/variable.c b/src/variable.c index 88728216..e4adb21d 100644 --- a/src/variable.c +++ b/src/variable.c @@ -184,13 +184,6 @@ FILE *text_out_file = NULL; void (*text_out_hook)(byte a, cptr str) = text_out_to_screen; -/* - * Hack -- Where to wrap the text when using text_out(). Use the default - * value (for example the screen width) when 'text_out_wrap' is 0. - */ -int text_out_wrap = 0; - - /* * Hack -- Indentation for the text when using text_out(). */ -- cgit v1.2.3 From 799070362567a091cee65a0a1c1b616675e13a1d Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 20:32:32 +0200 Subject: Remove "show_weights" option --- lib/help/option.txt | 5 ----- lib/mods/theme/help/option.txt | 5 ----- src/cmd2.c | 9 ++++----- src/object1.c | 33 +++++++++++++++------------------ src/store.c | 25 +++++++------------------ src/tables.c | 3 --- src/variable.c | 1 - 7 files changed, 26 insertions(+), 55 deletions(-) diff --git a/lib/help/option.txt b/lib/help/option.txt index 6fd3b413..abee7b51 100644 --- a/lib/help/option.txt +++ b/lib/help/option.txt @@ -150,11 +150,6 @@ off at will during the course of the game. flavoured object descriptions": a separate option for them has been added under "ToME Options". -#####GShow weights in object lists [show_weights] - Display the weight of objects in the inventory and equipment lists, - and in stores, and in any special window which is displaying any of - these lists. - #####GShow graphics in inventory list [show_inven_graph] Display the graphics of objects in the inventory list, and in any special window which is displaying the inventory list. diff --git a/lib/mods/theme/help/option.txt b/lib/mods/theme/help/option.txt index 34a2fe6b..3ae9cacc 100644 --- a/lib/mods/theme/help/option.txt +++ b/lib/mods/theme/help/option.txt @@ -150,11 +150,6 @@ off at will during the course of the game. flavoured object descriptions": a separate option for them has been added under "ToME Options". -#####GShow weights in object lists [show_weights] - Display the weight of objects in the inventory and equipment lists, - and in stores, and in any special window which is displaying any of - these lists. - #####GShow graphics in inventory list [show_inven_graph] Display the graphics of objects in the inventory list, and in any special window which is displaying the inventory list. diff --git a/src/cmd2.c b/src/cmd2.c index 9149e76b..9b1a8ed7 100644 --- a/src/cmd2.c +++ b/src/cmd2.c @@ -4817,8 +4817,8 @@ byte show_monster_inven(int m_idx, int *monst_list) /* Maximum space allowed for descriptions */ lim = 79 - 3; - /* Require space for weight (if needed) */ - if (show_weights) lim -= 9; + /* Require space for weight */ + lim -= 9; /* Scan for objects on the monster */ (void)scan_monst(monst_list, &monst_num, m_idx); @@ -4846,8 +4846,8 @@ byte show_monster_inven(int m_idx, int *monst_list) /* Find the predicted "line length" */ l = strlen(out_desc[k]) + 5; - /* Be sure to account for the weight */ - if (show_weights) l += 9; + /* Account for the weight */ + l += 9; /* Maintain the maximum length */ if (l > len) len = l; @@ -4881,7 +4881,6 @@ byte show_monster_inven(int m_idx, int *monst_list) c_put_str(out_color[j], out_desc[j], j + 1, col + 3); /* Display the weight if needed */ - if (show_weights) { int wgt = o_ptr->weight * o_ptr->number; strnfmt(tmp_val, 80, "%3d.%1d lb", wgt / 10, wgt % 10); diff --git a/src/object1.c b/src/object1.c index 21161dea..fd9ead08 100644 --- a/src/object1.c +++ b/src/object1.c @@ -4528,8 +4528,8 @@ void show_inven_aux(bool_ mirror, bool_ everything) /* Maximum space allowed for descriptions */ lim = 79 - 3; - /* Require space for weight (if needed) */ - if (show_weights) lim -= 9; + /* Space for weight */ + lim -= 9; /* Require space for icon */ if (show_inven_graph) lim -= 2; @@ -4578,7 +4578,7 @@ void show_inven_aux(bool_ mirror, bool_ everything) l = strlen(out_desc[k]) + 5; /* Be sure to account for the weight */ - if (show_weights) l += 9; + l += 9; /* Account for icon if displayed */ if (show_inven_graph) l += 2; @@ -4632,11 +4632,10 @@ void show_inven_aux(bool_ mirror, bool_ everything) c_put_str(out_color[j], out_desc[j], row + j, show_inven_graph ? (col + 5) : (col + 3)); - /* Display the weight if needed */ - if (show_weights) + /* Display the weight */ { int wgt = o_ptr->weight * o_ptr->number; - (void)sprintf(tmp_val, "%3d.%1d lb", wgt / 10, wgt % 10); + sprintf(tmp_val, "%3d.%1d lb", wgt / 10, wgt % 10); put_str(tmp_val, row + j, wid - 9); } } @@ -4706,8 +4705,8 @@ void show_equip_aux(bool_ mirror, bool_ everything) /* Require space for labels (if needed) */ if (show_labels) lim -= (14 + 2); - /* Require space for weight (if needed) */ - if (show_weights) lim -= 9; + /* Require space for weight */ + lim -= 9; if (show_equip_graph) lim -= 2; @@ -4807,8 +4806,8 @@ void show_equip_aux(bool_ mirror, bool_ everything) /* Increase length for labels (if needed) */ if (show_labels) l += (14 + 2); - /* Increase length for weight (if needed) */ - if (show_weights) l += 9; + /* Increase length for weight */ + l += 9; if (show_equip_graph) l += 2; @@ -4874,11 +4873,10 @@ void show_equip_aux(bool_ mirror, bool_ everything) c_put_str(out_color[j], out_desc[j], row + j, show_equip_graph ? col + 5 : col + 3); } - /* Display the weight if needed */ - if (show_weights) + /* Display the weight */ { int wgt = o_ptr->weight * o_ptr->number; - (void)sprintf(tmp_val, "%3d.%d lb", wgt / 10, wgt % 10); + sprintf(tmp_val, "%3d.%d lb", wgt / 10, wgt % 10); put_str(tmp_val, row + j, wid - 9); } } @@ -5171,8 +5169,8 @@ void show_floor(int y, int x) /* Maximum space allowed for descriptions */ lim = 79 - 3; - /* Require space for weight (if needed) */ - if (show_weights) lim -= 9; + /* Require space for weight */ + lim -= 9; /* Scan for objects in the grid, using item_tester_okay() */ (void) scan_floor(floor_list, &floor_num, y, x, 0x01); @@ -5200,8 +5198,8 @@ void show_floor(int y, int x) /* Find the predicted "line length" */ l = strlen(out_desc[k]) + 5; - /* Be sure to account for the weight */ - if (show_weights) l += 9; + /* Account for the weight */ + l += 9; /* Maintain the maximum length */ if (l > len) len = l; @@ -5235,7 +5233,6 @@ void show_floor(int y, int x) c_put_str(out_color[j], out_desc[j], j + 1, col + 3); /* Display the weight if needed */ - if (show_weights) { int wgt = o_ptr->weight * o_ptr->number; sprintf(tmp_val, "%3d.%1d lb", wgt / 10, wgt % 10); diff --git a/src/store.c b/src/store.c index cca3be85..3114380c 100644 --- a/src/store.c +++ b/src/store.c @@ -1669,8 +1669,8 @@ static void display_entry(int pos) { maxwid = 75; - /* Leave room for weights, if necessary -DRS- */ - if (show_weights) maxwid -= 10; + /* Leave room for weights */ + maxwid -= 10; /* Describe the object */ object_desc(o_name, o_ptr, TRUE, 3); @@ -1678,7 +1678,6 @@ static void display_entry(int pos) c_put_str(tval_to_attr[o_ptr->tval], o_name, i + 6, cur_col); /* Show weights */ - if (show_weights) { /* Only show the weight of an individual item */ int wgt = o_ptr->weight; @@ -1695,8 +1694,8 @@ static void display_entry(int pos) /* Must leave room for the "price" */ maxwid = 65; - /* Leave room for weights, if necessary -DRS- */ - if (show_weights) maxwid -= 7; + /* Leave room for weights */ + maxwid -= 7; /* Describe the object (fully) */ object_desc_store(o_name, o_ptr, TRUE, 3); @@ -1704,7 +1703,6 @@ static void display_entry(int pos) c_put_str(tval_to_attr[o_ptr->tval], o_name, i + 6, cur_col); /* Show weights */ - if (show_weights) { /* Only show the weight of an individual item */ int wgt = o_ptr->weight; @@ -1830,10 +1828,7 @@ void display_store(void) put_str("Item Description", 5, 3); /* If showing weights, show label */ - if (show_weights) - { - put_str("Weight", 5, 70); - } + put_str("Weight", 5, 70); } else if (st_info[st_ptr->st_idx].flags1 & SF1_MUSEUM) @@ -1848,10 +1843,7 @@ void display_store(void) put_str("Item Description", 5, 3); /* If showing weights, show label */ - if (show_weights) - { - put_str("Weight", 5, 70); - } + put_str("Weight", 5, 70); } /* Normal stores */ @@ -1872,10 +1864,7 @@ void display_store(void) put_str("Item Description", 5, 3); /* If showing weights, show label */ - if (show_weights) - { - put_str("Weight", 5, 60); - } + put_str("Weight", 5, 60); /* Label the asking price (in stores) */ put_str("Price", 5, 72); diff --git a/src/tables.c b/src/tables.c index 7d87d5d8..74bd66f2 100644 --- a/src/tables.c +++ b/src/tables.c @@ -1385,9 +1385,6 @@ option_type option_info[] = { &show_labels, TRUE, 1, 11, "show_labels", "Show labels in object listings" }, - { &show_weights, TRUE, 1, 12, - "show_weights", "Show weights in object listings" }, - { &show_inven_graph, TRUE, 1, 13, "show_inven_graph", "Show graphics in inventory list" }, diff --git a/src/variable.c b/src/variable.c index e4adb21d..135edb1c 100644 --- a/src/variable.c +++ b/src/variable.c @@ -211,7 +211,6 @@ bool_ stack_force_notes; /* Merge inscriptions when stacking */ bool_ stack_force_costs; /* Merge discounts when stacking */ bool_ show_labels; /* Show labels in object listings */ -bool_ show_weights; /* Show weights in object listings */ bool_ show_choices; /* Show choices in certain sub-windows */ bool_ show_details; /* Show details in certain sub-windows */ -- cgit v1.2.3 From 07339db486c538b44b7c9488943dfb34c2ae24e4 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 20:44:17 +0200 Subject: Remove "show_choices" option --- lib/help/option.txt | 3 --- lib/mods/theme/help/option.txt | 3 --- src/cmd5.c | 24 ++++-------------------- src/object1.c | 2 -- src/tables.c | 3 --- src/variable.c | 1 - 6 files changed, 4 insertions(+), 32 deletions(-) diff --git a/lib/help/option.txt b/lib/help/option.txt index abee7b51..84ef4d42 100644 --- a/lib/help/option.txt +++ b/lib/help/option.txt @@ -161,9 +161,6 @@ off at will during the course of the game. #####GShow graphics in stores [show_store_graph] Display the graphics of objects in the store list. -#####GShow choices in certain sub-windows [show_choices] - Indicate legal choices in special windows which display lists. - #####GShow details in certain sub-windows [show_details] Indicate extra details in special windows, currently used to activate the display of death counts and monster descriptions when recalling diff --git a/lib/mods/theme/help/option.txt b/lib/mods/theme/help/option.txt index 3ae9cacc..696bb56d 100644 --- a/lib/mods/theme/help/option.txt +++ b/lib/mods/theme/help/option.txt @@ -161,9 +161,6 @@ off at will during the course of the game. #####GShow graphics in stores [show_store_graph] Display the graphics of objects in the store list. -#####GShow choices in certain sub-windows [show_choices] - Indicate legal choices in special windows which display lists. - #####GShow details in certain sub-windows [show_details] Indicate extra details in special windows, currently used to activate the display of death counts and monster descriptions when recalling diff --git a/src/cmd5.c b/src/cmd5.c index 51fd6f17..c32d5690 100644 --- a/src/cmd5.c +++ b/src/cmd5.c @@ -2204,11 +2204,7 @@ s32b get_school_spell(cptr do_what, s16b force_book) flag = FALSE; /* Show choices */ - if (show_choices) - { - /* Window stuff */ - window_stuff(); - } + window_stuff(); /* No spell to cast by default */ spell = -1; @@ -2332,11 +2328,7 @@ s32b get_school_spell(cptr do_what, s16b force_book) /* Show choices */ - if (show_choices) - { - /* Window stuff */ - window_stuff(); - } + window_stuff(); /* Abort if needed */ @@ -2383,11 +2375,7 @@ void browse_school_spell(int book, int pval, object_type *o_ptr) char out_val[160]; /* Show choices */ - if (show_choices) - { - /* Window stuff */ - window_stuff(); - } + window_stuff(); num = school_book_length(book); @@ -2438,11 +2426,7 @@ void browse_school_spell(int book, int pval, object_type *o_ptr) character_icky = FALSE; /* Show choices */ - if (show_choices) - { - /* Window stuff */ - window_stuff(); - } + window_stuff(); } /* Can it contains a schooled spell ? */ diff --git a/src/object1.c b/src/object1.c index fd9ead08..8cec49d8 100644 --- a/src/object1.c +++ b/src/object1.c @@ -5428,7 +5428,6 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode) while (!done) { /* Show choices */ - if (show_choices) { int ni = 0; int ne = 0; @@ -5911,7 +5910,6 @@ bool_ get_item_floor(int *cp, cptr pmt, cptr str, int mode) } /* Clean up */ - if (show_choices) { /* Toggle again if needed */ if (toggle) toggle_inven_equip(); diff --git a/src/tables.c b/src/tables.c index 74bd66f2..ac6f36d7 100644 --- a/src/tables.c +++ b/src/tables.c @@ -1394,9 +1394,6 @@ option_type option_info[] = { &show_store_graph, TRUE, 1, 15, "show_store_graph", "Show graphics in stores" }, - { &show_choices, TRUE, 1, 16, - "show_choices", "Show choices in certain sub-windows" }, - { &show_details, TRUE, 1, 17, "show_details", "Show details in certain sub-windows" }, diff --git a/src/variable.c b/src/variable.c index 135edb1c..174a2654 100644 --- a/src/variable.c +++ b/src/variable.c @@ -211,7 +211,6 @@ bool_ stack_force_notes; /* Merge inscriptions when stacking */ bool_ stack_force_costs; /* Merge discounts when stacking */ bool_ show_labels; /* Show labels in object listings */ -bool_ show_choices; /* Show choices in certain sub-windows */ bool_ show_details; /* Show details in certain sub-windows */ bool_ ring_bell; /* Ring the bell (on errors, etc) */ -- cgit v1.2.3 From 5241fee18e1a85b3b8e1492fa4d430e8af375035 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 20:47:26 +0200 Subject: Remove "show_details" option --- lib/help/option.txt | 5 ----- lib/mods/theme/help/option.txt | 5 ----- src/monster1.c | 9 +-------- src/tables.c | 3 --- src/variable.c | 2 -- 5 files changed, 1 insertion(+), 23 deletions(-) diff --git a/lib/help/option.txt b/lib/help/option.txt index 84ef4d42..0fd71d66 100644 --- a/lib/help/option.txt +++ b/lib/help/option.txt @@ -161,11 +161,6 @@ off at will during the course of the game. #####GShow graphics in stores [show_store_graph] Display the graphics of objects in the store list. -#####GShow details in certain sub-windows [show_details] - Indicate extra details in special windows, currently used to activate - the display of death counts and monster descriptions when recalling - details about a monster. - #####GAudible bell (on errors, etc) [ring_bell] Attempt to make a "bell" noise when various errors occur. diff --git a/lib/mods/theme/help/option.txt b/lib/mods/theme/help/option.txt index 696bb56d..55062b6b 100644 --- a/lib/mods/theme/help/option.txt +++ b/lib/mods/theme/help/option.txt @@ -161,11 +161,6 @@ off at will during the course of the game. #####GShow graphics in stores [show_store_graph] Display the graphics of objects in the store list. -#####GShow details in certain sub-windows [show_details] - Indicate extra details in special windows, currently used to activate - the display of death counts and monster descriptions when recalling - details about a monster. - #####GAudible bell (on errors, etc) [ring_bell] Attempt to make a "bell" noise when various errors occur. diff --git a/src/monster1.c b/src/monster1.c index 196272ce..68882d27 100644 --- a/src/monster1.c +++ b/src/monster1.c @@ -242,14 +242,8 @@ static void roff_aux(int r_idx, int ego, int remem) } - /* Require a flag to show kills */ - if (!(show_details)) - { - /* nothing */ - } - /* Treat uniques differently */ - else if (flags1 & (RF1_UNIQUE)) + if (flags1 & (RF1_UNIQUE)) { /* Hack -- Determine if the unique is "dead" */ bool_ dead = (r_ptr->max_num == 0) ? TRUE : FALSE; @@ -339,7 +333,6 @@ static void roff_aux(int r_idx, int ego, int remem) /* Descriptions */ - if (show_details) { char buf[2048]; diff --git a/src/tables.c b/src/tables.c index ac6f36d7..b1fc54e5 100644 --- a/src/tables.c +++ b/src/tables.c @@ -1394,9 +1394,6 @@ option_type option_info[] = { &show_store_graph, TRUE, 1, 15, "show_store_graph", "Show graphics in stores" }, - { &show_details, TRUE, 1, 17, - "show_details", "Show details in certain sub-windows" }, - { &ring_bell, FALSE, 1, 18, "ring_bell", "Audible bell (on errors, etc)" }, /* Changed to default to FALSE -- it's so extremely annoying!!! -TY */ diff --git a/src/variable.c b/src/variable.c index 174a2654..7c378a24 100644 --- a/src/variable.c +++ b/src/variable.c @@ -211,8 +211,6 @@ bool_ stack_force_notes; /* Merge inscriptions when stacking */ bool_ stack_force_costs; /* Merge discounts when stacking */ bool_ show_labels; /* Show labels in object listings */ -bool_ show_details; /* Show details in certain sub-windows */ - bool_ ring_bell; /* Ring the bell (on errors, etc) */ bool_ show_inven_graph; /* Show graphics in inventory */ -- cgit v1.2.3 From 4ac43f667228f37723071895b654422bbaad4835 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 20:51:34 +0200 Subject: Remove "show_labels" option --- lib/help/option.txt | 10 ---------- lib/mods/theme/help/option.txt | 10 ---------- src/object1.c | 14 +++----------- src/tables.c | 3 --- src/variable.c | 1 - 5 files changed, 3 insertions(+), 35 deletions(-) diff --git a/lib/help/option.txt b/lib/help/option.txt index 0fd71d66..7505f46b 100644 --- a/lib/help/option.txt +++ b/lib/help/option.txt @@ -140,16 +140,6 @@ off at will during the course of the game. discounts. The resulting stack keeps the largest discount. This option may cause you to lose "value", but will give you optimal pack usage. -#####GShow labels in object lists [show_labels] - Display the "labels" for objects in the equipment list, and in any - special window which is displaying the equipment. These labels - indicate what the player is using the object for, such as "wielding" - or "wearing" (in a given location). After you have played for a while, - this information is no longer useful, and can be annoying. - Note that in ToME this option no longer controls the "plain - flavoured object descriptions": a separate option for them has been added - under "ToME Options". - #####GShow graphics in inventory list [show_inven_graph] Display the graphics of objects in the inventory list, and in any special window which is displaying the inventory list. diff --git a/lib/mods/theme/help/option.txt b/lib/mods/theme/help/option.txt index 55062b6b..93b34cd8 100644 --- a/lib/mods/theme/help/option.txt +++ b/lib/mods/theme/help/option.txt @@ -140,16 +140,6 @@ off at will during the course of the game. discounts. The resulting stack keeps the largest discount. This option may cause you to lose "value", but will give you optimal pack usage. -#####GShow labels in object lists [show_labels] - Display the "labels" for objects in the equipment list, and in any - special window which is displaying the equipment. These labels - indicate what the player is using the object for, such as "wielding" - or "wearing" (in a given location). After you have played for a while, - this information is no longer useful, and can be annoying. - Note that in ToME this option no longer controls the "plain - flavoured object descriptions": a separate option for them has been added - under "ToME Options". - #####GShow graphics in inventory list [show_inven_graph] Display the graphics of objects in the inventory list, and in any special window which is displaying the inventory list. diff --git a/src/object1.c b/src/object1.c index 8cec49d8..655e4e2c 100644 --- a/src/object1.c +++ b/src/object1.c @@ -4702,8 +4702,8 @@ void show_equip_aux(bool_ mirror, bool_ everything) /* Maximum space allowed for descriptions */ lim = 79 - 3; - /* Require space for labels (if needed) */ - if (show_labels) lim -= (14 + 2); + /* Require space for labels */ + lim -= (14 + 2); /* Require space for weight */ lim -= 9; @@ -4804,7 +4804,7 @@ void show_equip_aux(bool_ mirror, bool_ everything) l = strlen(out_desc[k]) + (2 + 3); /* Increase length for labels (if needed) */ - if (show_labels) l += (14 + 2); + l += (14 + 2); /* Increase length for weight */ l += 9; @@ -4856,7 +4856,6 @@ void show_equip_aux(bool_ mirror, bool_ everything) } /* Use labels */ - if (show_labels) { /* Mention the use */ (void)sprintf(tmp_val, "%-14s: ", mention_use(out_rindex[j])); @@ -4866,13 +4865,6 @@ void show_equip_aux(bool_ mirror, bool_ everything) c_put_str(out_color[j], out_desc[j], row + j, show_equip_graph ? col + 21 : col + 19); } - /* No labels */ - else - { - /* Display the entry itself */ - c_put_str(out_color[j], out_desc[j], row + j, show_equip_graph ? col + 5 : col + 3); - } - /* Display the weight */ { int wgt = o_ptr->weight * o_ptr->number; diff --git a/src/tables.c b/src/tables.c index b1fc54e5..e3d3e664 100644 --- a/src/tables.c +++ b/src/tables.c @@ -1382,9 +1382,6 @@ option_type option_info[] = { &stack_force_costs, FALSE, 1, 10, "stack_force_costs", "Merge discounts when stacking" }, - { &show_labels, TRUE, 1, 11, - "show_labels", "Show labels in object listings" }, - { &show_inven_graph, TRUE, 1, 13, "show_inven_graph", "Show graphics in inventory list" }, diff --git a/src/variable.c b/src/variable.c index 7c378a24..13209ead 100644 --- a/src/variable.c +++ b/src/variable.c @@ -210,7 +210,6 @@ bool_ depth_in_feet; /* Show dungeon level in feet */ bool_ stack_force_notes; /* Merge inscriptions when stacking */ bool_ stack_force_costs; /* Merge discounts when stacking */ -bool_ show_labels; /* Show labels in object listings */ bool_ ring_bell; /* Ring the bell (on errors, etc) */ bool_ show_inven_graph; /* Show graphics in inventory */ -- cgit v1.2.3 From 9f4251ec8809d716eeb7930928517b9e2bcdea86 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 21:00:55 +0200 Subject: Remove "player_uid" global --- src/externs.h | 1 - src/files.c | 14 +++++++------- src/main.c | 2 ++ src/variable.c | 5 ----- 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/externs.h b/src/externs.h index 74cc34bd..300bc73d 100644 --- a/src/externs.h +++ b/src/externs.h @@ -299,7 +299,6 @@ extern s16b health_who; extern s16b monster_race_idx; extern s16b monster_ego_idx; extern object_type *tracked_object; -extern int player_uid; extern char player_name[32]; extern char player_base[32]; extern char died_from[80]; diff --git a/src/files.c b/src/files.c index cd3a5bf4..c1ff6d36 100644 --- a/src/files.c +++ b/src/files.c @@ -4727,7 +4727,7 @@ struct high_score char who[16]; /* Player Name (string) */ - char uid[8]; /* Player UID (number) */ + char unused_1[8]; /* Kept for compatibility only */ char sex[2]; /* Player Sex (string) */ char p_r[3]; /* Player Race (number) */ @@ -4918,7 +4918,7 @@ static void display_scores_aux(int highscore_fd, int from, int to, int note, hig { int pcs, pr, ps, pc, clev, mlev, cdun, mdun; - cptr user, gold, when, aged; + cptr gold, when, aged; int in_arena, in_quest; @@ -4960,7 +4960,6 @@ static void display_scores_aux(int highscore_fd, int from, int to, int note, hig in_quest = atoi(the_score.inside_quest); /* Hack -- extract the gold and such */ - for (user = the_score.uid; isspace(*user); user++) /* loop */; for (when = the_score.day; isspace(*when); when++) /* loop */; for (gold = the_score.gold; isspace(*gold); gold++) /* loop */; for (aged = the_score.turns; isspace(*aged); aged++) /* loop */; @@ -5008,8 +5007,8 @@ static void display_scores_aux(int highscore_fd, int from, int to, int note, hig /* And still another line of info */ sprintf(out_val, - " (User %s, Date %s, Gold %s, Turn %s).", - user, when, gold, aged); + " (Date %s, Gold %s, Turn %s).", + when, gold, aged); c_put_str(attr, out_val, n*4 + 4, 0); } @@ -5378,7 +5377,6 @@ static errr top_twenty(void) sprintf(the_score.who, "%-.15s", player_name); /* Save the player info XXX XXX XXX */ - sprintf(the_score.uid, "%7u", player_uid); sprintf(the_score.sex, "%c", (p_ptr->psex ? 'm' : 'f')); sprintf(the_score.p_r, "%2d", p_ptr->prace); sprintf(the_score.p_s, "%2d", p_ptr->pracem); @@ -5455,6 +5453,9 @@ errr predict_score(void) goto out; } + /* Clear the record */ + WIPE(&the_score, high_score); + /* Save the version */ sprintf(the_score.what, "%ld.%ld.%ld", (long int) VERSION_MAJOR, (long int) VERSION_MINOR, (long int) VERSION_PATCH); @@ -5478,7 +5479,6 @@ errr predict_score(void) sprintf(the_score.who, "%-.15s", player_name); /* Save the player info XXX XXX XXX */ - sprintf(the_score.uid, "%7u", player_uid); sprintf(the_score.sex, "%c", (p_ptr->psex ? 'm' : 'f')); sprintf(the_score.p_r, "%2d", p_ptr->prace); sprintf(the_score.p_s, "%2d", p_ptr->pracem); diff --git a/src/main.c b/src/main.c index 6bd2b154..af719a20 100644 --- a/src/main.c +++ b/src/main.c @@ -248,6 +248,8 @@ int main(int argc, char *argv[]) bool_ args = TRUE; + int player_uid; + #ifdef CHECK_MEMORY_LEAKS GC_find_leak = 1; #endif /* CHECK_MEMORY_LEAKS */ diff --git a/src/variable.c b/src/variable.c index 13209ead..e5a4e92c 100644 --- a/src/variable.c +++ b/src/variable.c @@ -385,11 +385,6 @@ object_type *tracked_object; -/* - * User info - */ -int player_uid; - /* * Current player's character name */ -- cgit v1.2.3 From d861617f0fa266d9ca86088ba0b8fc9561043ea1 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 21:14:16 +0200 Subject: Remove "monk_*" globals --- src/externs.h | 2 -- src/variable.c | 4 ---- src/xtra1.c | 2 ++ 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/externs.h b/src/externs.h index 300bc73d..3c9d6d74 100644 --- a/src/externs.h +++ b/src/externs.h @@ -467,8 +467,6 @@ extern void (*ang_sort_swap)(vptr u, vptr v, int a, int b); extern bool_ (*get_mon_num_hook)(int r_idx); extern bool_ (*get_mon_num2_hook)(int r_idx); extern bool_ (*get_obj_num_hook)(int k_idx); -extern bool_ monk_armour_aux; -extern bool_ monk_notify_aux; extern u16b max_wild_x; extern u16b max_wild_y; extern wilderness_map **wild_map; diff --git a/src/variable.c b/src/variable.c index e5a4e92c..4972e647 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1071,10 +1071,6 @@ bool_ (*get_mon_num2_hook)(int r_idx); bool_ (*get_obj_num_hook)(int k_idx); -/* Hack, monk armour */ -bool_ monk_armour_aux; -bool_ monk_notify_aux; - bool_ easy_open = TRUE; bool_ easy_disarm = TRUE; bool_ easy_tunnel = FALSE; diff --git a/src/xtra1.c b/src/xtra1.c index 0cc3ccac..d24eaa5c 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -2821,6 +2821,7 @@ void apply_flags(u32b f1, u32b f2, u32b f3, u32b f4, u32b f5, u32b esp, s16b pva */ void calc_bonuses(bool_ silent) { + static bool_ monk_notify_aux = FALSE; int i, j, hold; int old_speed; u32b old_telepathy; @@ -2829,6 +2830,7 @@ void calc_bonuses(bool_ silent) int old_dis_to_a; object_type *o_ptr; u32b f1, f2, f3, f4, f5, esp; + bool_ monk_armour_aux; /* Save the old speed */ -- cgit v1.2.3 From 0a70d3b23bd63bc55fff874be505317ebcb58154 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 21:16:53 +0200 Subject: Remove "permanent_levels" global --- src/variable.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/variable.c b/src/variable.c index 4972e647..64cd49c7 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1279,9 +1279,6 @@ s16b doppleganger; /* To allow wilderness encounters */ bool_ generate_encounter; -/* Permanent dungeons ? */ -bool_ permanent_levels; - /* Autoroler */ bool_ autoroll; -- cgit v1.2.3 From c6c713350f8331a439acc5672bb1789d3c9add5c Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 21:24:23 +0200 Subject: Remove "munchkin_multipliers" global --- src/externs.h | 1 - src/object1.c | 20 +++----------------- src/variable.c | 5 ----- src/xtra1.c | 18 ++++-------------- 4 files changed, 7 insertions(+), 37 deletions(-) diff --git a/src/externs.h b/src/externs.h index 3c9d6d74..da47af0f 100644 --- a/src/externs.h +++ b/src/externs.h @@ -526,7 +526,6 @@ extern bool_ *a_allow_special; extern bool_ rand_birth; extern bool_ fast_autoroller; extern bool_ joke_monsters; -extern bool_ munchkin_multipliers; extern bool_ center_player; extern s16b plots[MAX_PLOTS]; extern random_quest random_quests[MAX_RANDOM_QUEST]; diff --git a/src/object1.c b/src/object1.c index 655e4e2c..86f98ae5 100644 --- a/src/object1.c +++ b/src/object1.c @@ -2246,28 +2246,14 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode) if ((f1 & TR1_MANA) && (known) && (o_ptr->pval > 0)) { t = object_desc_chr(t, '('); - if (munchkin_multipliers) - { - t = object_desc_num(t, 100 * o_ptr->pval / 5); - } - else - { - t = object_desc_num(t, 100 * o_ptr->pval / 10); - } + t = object_desc_num(t, 100 * o_ptr->pval / 5); t = object_desc_str(t, "%)"); } if ((known) && (f2 & TR2_LIFE) ) /* Can disp neg now -- Improv */ { t = object_desc_chr(t, '('); - if (munchkin_multipliers) - { - t = object_desc_num(t, 100 * o_ptr->pval / 5); - } - else - { - t = object_desc_num(t, 100 * o_ptr->pval / 10); - } + t = object_desc_num(t, 100 * o_ptr->pval / 5); t = object_desc_str(t, "%)"); } @@ -3157,7 +3143,7 @@ bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait } text_out(" by "); - percent = 100 * o_ptr->pval / ( munchkin_multipliers ? 5 : 10 ); + percent = 100 * o_ptr->pval / 5; if (o_ptr->pval > 0) diff --git a/src/variable.c b/src/variable.c index 64cd49c7..6302d57a 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1318,11 +1318,6 @@ bool_ fast_autoroller; */ bool_ joke_monsters; -/* - * How will mana staf & weapons of life act - */ -bool_ munchkin_multipliers = TRUE; - /* * Center view */ diff --git a/src/xtra1.c b/src/xtra1.c index d24eaa5c..d4df67af 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -1747,13 +1747,9 @@ static void calc_mana(void) } /* Augment mana */ - if (munchkin_multipliers) + if (p_ptr->to_m) { - if (p_ptr->to_m) msp += msp * p_ptr->to_m / 5; - } - else - { - if (p_ptr->to_m) msp += msp * p_ptr->to_m / 10; + msp += msp * p_ptr->to_m / 5; } /* Assume player not encumbered by armor */ @@ -1903,14 +1899,8 @@ void calc_hitpoints(void) if (p_ptr->shero) mhp += 30; /* Augment Hitpoint */ - if (munchkin_multipliers) - { - mhp += mhp * p_ptr->to_l / 5; - } - else - { - mhp += mhp * p_ptr->to_l / 10; - } + mhp += mhp * p_ptr->to_l / 5; + if (mhp < 1) mhp = 1; if (p_ptr->body_monster) -- cgit v1.2.3 From 7596aa392513c741848afee229153f82c6b8d3ee Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 21:45:21 +0200 Subject: Remove "copyright" global --- src/variable.c | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/variable.c b/src/variable.c index 6302d57a..feed0c37 100644 --- a/src/variable.c +++ b/src/variable.c @@ -13,18 +13,6 @@ #include "angband.h" -/* - * Hack -- Link a copyright message into the executable - */ -cptr copyright[5] = -{ - "Copyright (c) 1989 James E. Wilson, Robert A. Keoneke", - "", - "This software may be copied and distributed for educational, research,", - "and not for profit purposes provided that this copyright and statement", - "are included in all such copies." -}; - int max_macrotrigger = 0; char *macro_template = NULL; char *macro_modifier_chr; -- cgit v1.2.3 From b533f5e8eb893edc447c47cd43c0e681e9d58825 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 21:56:00 +0200 Subject: Remove "arg_fiddle" global --- src/externs.h | 1 - src/loadsave.c | 11 ----------- src/main-crb.c | 12 ------------ src/main.c | 8 -------- src/variable.c | 3 +-- 5 files changed, 1 insertion(+), 34 deletions(-) diff --git a/src/externs.h b/src/externs.h index da47af0f..33a74266 100644 --- a/src/externs.h +++ b/src/externs.h @@ -113,7 +113,6 @@ extern u32b sf_when; extern u16b sf_lives; extern u16b sf_saves; extern u32b vernum; /* Version flag */ -extern bool_ arg_fiddle; extern bool_ arg_wizard; extern bool_ arg_sound; extern bool_ arg_graphics; diff --git a/src/loadsave.c b/src/loadsave.c index 4ec7a02a..858ea377 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -2609,18 +2609,15 @@ static bool_ do_savefile_aux(int flag) /* Read RNG state */ do_randomizer(flag); - if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Randomizer Info"); /* Automatizer state */ do_byte((byte*)&automatizer_enabled, flag); /* Then the options */ do_options(flag); - if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Option Flags"); /* Then the "messages" */ do_messages(flag); - if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Messages"); /* Monster Memory */ if (flag == LS_SAVE) tmp16u = max_r_idx; @@ -2640,7 +2637,6 @@ static bool_ do_savefile_aux(int flag) do_lore(i, flag); } - if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Monster Memory"); /* Object Memory */ if (flag == LS_SAVE) tmp16u = max_k_idx; do_u16b(&tmp16u, flag); @@ -2654,7 +2650,6 @@ static bool_ do_savefile_aux(int flag) /* Read the object memory */ for (i = 0; i < tmp16u; i++) do_xtra(i, flag); - if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Object Memory"); if (flag == LS_LOAD) junkinit(); { @@ -2790,7 +2785,6 @@ static bool_ do_savefile_aux(int flag) } } } - if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Quests"); /* Load the random artifacts. */ if (flag == LS_SAVE) tmp16u = MAX_RANDARTS; @@ -2828,7 +2822,6 @@ static bool_ do_savefile_aux(int flag) { do_byte(&(&a_info[i])->cur_num, flag); } - if ((flag == LS_LOAD) && arg_fiddle) note("Loaded Artifacts"); /* Fates */ if (flag == LS_SAVE) tmp16u = MAX_FATES; @@ -2846,7 +2839,6 @@ static bool_ do_savefile_aux(int flag) { do_fate(i, flag); } - if ((flag == LS_LOAD) && arg_fiddle) note("Loaded Fates"); /* Load the Traps */ if (flag == LS_SAVE) tmp16u = max_t_idx; @@ -2864,7 +2856,6 @@ static bool_ do_savefile_aux(int flag) { do_byte((byte*)&t_info[i].ident, flag); } - if ((flag == LS_LOAD) && (arg_fiddle)) note("Loaded Traps"); /* inscription knowledge */ if (flag == LS_SAVE) tmp16u = MAX_INSCRIPTIONS; @@ -2880,13 +2871,11 @@ static bool_ do_savefile_aux(int flag) /* Read the inscription flag */ for (i = 0; i < tmp16u; i++) do_byte((byte*)&inscription_info[i].know, flag); - if ((flag == LS_LOAD) && arg_fiddle) note("Loaded Inscriptions"); /* Read the extra stuff */ if (!do_extra(flag)) return FALSE; - if ((flag == LS_LOAD) && arg_fiddle) note("Loaded extra information"); /* player_hp array */ diff --git a/src/main-crb.c b/src/main-crb.c index 86604471..d8af65de 100644 --- a/src/main-crb.c +++ b/src/main-crb.c @@ -3992,7 +3992,6 @@ static void handle_open_when_ready(void) # define SUBMENU_TILEWIDTH 145 #define ITEM_TILEHEIGHT 4 # define SUBMENU_TILEHEIGHT 146 -#define ITEM_FIDDLE 6 #define ITEM_WIZARD 7 @@ -4630,10 +4629,6 @@ static void setup_menus(void) } } - /* Item "arg_fiddle" */ - EnableMenuItem(m, ITEM_FIDDLE); - CheckMenuItem(m, ITEM_FIDDLE, arg_fiddle); - /* Item "arg_wizard" */ EnableMenuItem(m, ITEM_WIZARD); CheckMenuItem(m, ITEM_WIZARD, arg_wizard); @@ -5039,13 +5034,6 @@ static void menu(long mc) break; } - case ITEM_FIDDLE: - { - arg_fiddle = !arg_fiddle; - - break; - } - case ITEM_WIZARD: { arg_wizard = !arg_wizard; diff --git a/src/main.c b/src/main.c index af719a20..9bde57a1 100644 --- a/src/main.c +++ b/src/main.c @@ -307,13 +307,6 @@ int main(int argc, char *argv[]) break; } - case 'F': - case 'f': - { - arg_fiddle = TRUE; - break; - } - case 'W': case 'w': { @@ -439,7 +432,6 @@ usage: puts("Usage: tome [options] [-- subopts]"); puts(" -h This help"); puts(" -n Start a new character"); - puts(" -f Request fiddle mode"); puts(" -w Request wizard mode"); puts(" -v Request sound mode"); puts(" -g Request graphics mode"); diff --git a/src/variable.c b/src/variable.c index feed0c37..2ec4f7bc 100644 --- a/src/variable.c +++ b/src/variable.c @@ -46,9 +46,8 @@ u16b sf_lives; /* Number of past "lives" with this file */ u16b sf_saves; /* Number of "saves" during this life */ /* - * Run-time arguments + * Run-time aruments */ -bool_ arg_fiddle; /* Command arg -- Request fiddle mode */ bool_ arg_wizard; /* Command arg -- Request wizard mode */ bool_ arg_sound; /* Command arg -- Request special sounds */ bool_ arg_graphics; /* Command arg -- Request graphics mode */ -- cgit v1.2.3 From ae546bfca75294edebbc562640cc90f534e8e6b5 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 22:07:10 +0200 Subject: Remove bogus #if 1 / #endif pragmas --- src/cave.c | 12 +----- src/dungeon.c | 4 -- src/generate.c | 17 -------- src/main-gtk2.c | 118 -------------------------------------------------------- src/main-win.c | 83 --------------------------------------- 5 files changed, 1 insertion(+), 233 deletions(-) diff --git a/src/cave.c b/src/cave.c index d23fc44c..ee45d167 100644 --- a/src/cave.c +++ b/src/cave.c @@ -501,21 +501,11 @@ static void image_random(byte *ap, char *cp) /* * The 16x16 tile of the terrain supports lighting */ -#if 1 - -#define feat_supports_lighting(F) \ -((f_info[F].flags1 & FF1_SUPPORT_LIGHT) != 0) - -#else - static bool_ feat_supports_lighting(byte feat) { - if (f_info[feat].flags1 & FF1_SUPPORT_LIGHT) return TRUE; - else return FALSE; + return (f_info[feat].flags1 & FF1_SUPPORT_LIGHT) != 0; } -#endif - char get_shimmer_color() { diff --git a/src/dungeon.c b/src/dungeon.c index 3bf40690..43db5b29 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -5486,8 +5486,6 @@ void play_game(bool_ new_game) } } -#if 1 - /* Process old character */ if (!new_game) { @@ -5495,8 +5493,6 @@ void play_game(bool_ new_game) process_player_name(FALSE); } -#endif - /* Init the RNG */ if (Rand_quick) { diff --git a/src/generate.c b/src/generate.c index bedd169d..313d9498 100644 --- a/src/generate.c +++ b/src/generate.c @@ -586,8 +586,6 @@ void place_new_way(int *y, int *x) /* Check if it connects to current dungeon */ while (in_bounds(yy, xx)) { -#if 1 - /* Check grids ahead */ if (is_safe_floor(yy + y0, xx + x0)) ok = TRUE; @@ -595,21 +593,6 @@ void place_new_way(int *y, int *x) if (is_safe_floor(yy + y1, xx + x1)) ok = TRUE; if (is_safe_floor(yy + y2, xx + x2)) ok = TRUE; -#else - - /* - * This can create unconnected sections if it bumps into a - * non-penetrating streamer - */ - /* Check grids ahead */ - if (cave_floor_bold(yy + y0, xx + x0)) ok = TRUE; - - /* Check side grids */ - if (cave_floor_bold(yy + y1, xx + x1)) ok = TRUE; - if (cave_floor_bold(yy + y2, xx + x2)) ok = TRUE; - -#endif - /* Connected */ if (ok) break; diff --git a/src/main-gtk2.c b/src/main-gtk2.c index 4830638a..e55b038e 100644 --- a/src/main-gtk2.c +++ b/src/main-gtk2.c @@ -3586,7 +3586,6 @@ static gboolean keypress_event_handler( GdkEventKey *event, gpointer user_data) { -#if 1 int i, mc, ms, mo, mx; char msg[128]; @@ -3703,123 +3702,6 @@ static gboolean keypress_event_handler( } return (TRUE); - -#else - int i, mc, ms, mo, mx; - - char msg[128]; - - - /* Extract four "modifier flags" */ - mc = (event->state & GDK_CONTROL_MASK) ? TRUE : FALSE; - ms = (event->state & GDK_SHIFT_MASK) ? TRUE : FALSE; - mo = (event->state & GDK_MOD1_MASK) ? TRUE : FALSE; - mx = (event->state & GDK_MOD3_MASK) ? TRUE : FALSE; - printf("0=%d 9=%d;; keyval=%d; mc=%d, ms=%d ::=:: ", GDK_KP_0, GDK_KP_9, event->keyval, mc, ms); - /* Enqueue the normal key(s) */ - for (i = 0; i < event->length; i++) printf("%d;", event->string[i]); - printf("\n"); - - /* - * Hack XXX - * Parse shifted numeric (keypad) keys specially. - */ - if ((event->state & GDK_SHIFT_MASK) - && (event->keyval >= GDK_KP_Left) && (event->keyval <= GDK_KP_Delete)) - { - /* Build the macro trigger string */ - strnfmt(msg, 128, "%cS_%X%c", 31, event->keyval, 13); - printf("%cS_%X%c", 31, event->keyval, 13); - - /* Enqueue the "macro trigger" string */ - for (i = 0; msg[i]; i++) Term_keypress(msg[i]); - - /* Hack -- auto-define macros as needed */ - if (event->length && (macro_find_exact(msg) < 0)) - { - /* Create a macro */ - macro_add(msg, event->string); - } - - return (TRUE); - } - - /* Normal keys with no modifiers */ - if (event->length && !mo && !mx) - { - /* Enqueue the normal key(s) */ - for (i = 0; i < event->length; i++) Term_keypress(event->string[i]); - - /* All done */ - return (TRUE); - } - - /* Handle a few standard keys (bypass modifiers) XXX XXX XXX */ - switch ((uint) event->keyval) - { - case GDK_Escape: - { - Term_keypress(ESCAPE); - return (TRUE); - } - - case GDK_Return: - { - Term_keypress('\r'); - return (TRUE); - } - - case GDK_Tab: - { - Term_keypress('\t'); - return (TRUE); - } - - case GDK_Delete: - case GDK_BackSpace: - { - Term_keypress('\010'); - return (TRUE); - } - - case GDK_Shift_L: - case GDK_Shift_R: - case GDK_Control_L: - case GDK_Control_R: - case GDK_Caps_Lock: - case GDK_Shift_Lock: - case GDK_Meta_L: - case GDK_Meta_R: - case GDK_Alt_L: - case GDK_Alt_R: - case GDK_Super_L: - case GDK_Super_R: - case GDK_Hyper_L: - case GDK_Hyper_R: - { - /* Hack - do nothing to control characters */ - return (TRUE); - } - } - - /* Build the macro trigger string */ - strnfmt(msg, 128, "%c%s%s%s%s_%X%c", 31, - mc ? "N" : "", ms ? "S" : "", - mo ? "O" : "", mx ? "M" : "", - event->keyval, 13); - - /* Enqueue the "macro trigger" string */ - for (i = 0; msg[i]; i++) Term_keypress(msg[i]); - - /* Hack -- auto-define macros as needed */ - if (event->length && (macro_find_exact(msg) < 0)) - { - /* Create a macro */ - macro_add(msg, event->string); - } - - return (TRUE); -#endif } diff --git a/src/main-win.c b/src/main-win.c index 3674c88d..fdde5e87 100644 --- a/src/main-win.c +++ b/src/main-win.c @@ -548,7 +548,6 @@ static BYTE win_pal[256] = static bool_ special_key[256]; static bool_ ignore_key[256]; -#if 1 /* * Hack -- initialization list for "special_key" */ @@ -574,88 +573,6 @@ static byte ignore_key_list[] = { VK_LSHIFT, VK_RSHIFT, VK_LCONTROL, VK_RCONTROL, VK_LMENU, VK_RMENU, 0 }; -#else -/* -* Hack -- initialization list for "special_key" -* -* We ignore the modifier keys (shift, control, alt, num lock, scroll lock), -* and the normal keys (escape, tab, return, letters, numbers, etc), but we -* catch the keypad keys (with and without numlock set, including keypad 5), -* the function keys (including the "menu" key which maps to F10), and the -* "pause" key (between scroll lock and numlock). We also catch a few odd -* keys which I do not recognize, but which are listed among keys which we -* do catch, so they should be harmless to catch. -*/ -static byte special_key_list[] = -{ - VK_CLEAR, /* 0x0C (KP<5>) */ - - VK_PAUSE, /* 0x13 (pause) */ - - VK_PRIOR, /* 0x21 (KP<9>) */ - VK_NEXT, /* 0x22 (KP<3>) */ - VK_END, /* 0x23 (KP<1>) */ - VK_HOME, /* 0x24 (KP<7>) */ - VK_LEFT, /* 0x25 (KP<4>) */ - VK_UP, /* 0x26 (KP<8>) */ - VK_RIGHT, /* 0x27 (KP<6>) */ - VK_DOWN, /* 0x28 (KP<2>) */ - VK_SELECT, /* 0x29 (?????) */ - VK_PRINT, /* 0x2A (?????) */ - VK_EXECUTE, /* 0x2B (?????) */ - VK_SNAPSHOT, /* 0x2C (?????) */ - VK_INSERT, /* 0x2D (KP<0>) */ - VK_DELETE, /* 0x2E (KP<.>) */ - VK_HELP, /* 0x2F (?????) */ - -#if 0 - VK_NUMPAD0, /* 0x60 (KP<0>) */ - VK_NUMPAD1, /* 0x61 (KP<1>) */ - VK_NUMPAD2, /* 0x62 (KP<2>) */ - VK_NUMPAD3, /* 0x63 (KP<3>) */ - VK_NUMPAD4, /* 0x64 (KP<4>) */ - VK_NUMPAD5, /* 0x65 (KP<5>) */ - VK_NUMPAD6, /* 0x66 (KP<6>) */ - VK_NUMPAD7, /* 0x67 (KP<7>) */ - VK_NUMPAD8, /* 0x68 (KP<8>) */ - VK_NUMPAD9, /* 0x69 (KP<9>) */ - VK_MULTIPLY, /* 0x6A (KP<*>) */ - VK_ADD, /* 0x6B (KP<+>) */ - VK_SEPARATOR, /* 0x6C (?????) */ - VK_SUBTRACT, /* 0x6D (KP<->) */ - VK_DECIMAL, /* 0x6E (KP<.>) */ - VK_DIVIDE, /* 0x6F (KP) */ -#endif - - VK_F1, /* 0x70 */ - VK_F2, /* 0x71 */ - VK_F3, /* 0x72 */ - VK_F4, /* 0x73 */ - VK_F5, /* 0x74 */ - VK_F6, /* 0x75 */ - VK_F7, /* 0x76 */ - VK_F8, /* 0x77 */ - VK_F9, /* 0x78 */ - VK_F10, /* 0x79 */ - VK_F11, /* 0x7A */ - VK_F12, /* 0x7B */ - VK_F13, /* 0x7C */ - VK_F14, /* 0x7D */ - VK_F15, /* 0x7E */ - VK_F16, /* 0x7F */ - VK_F17, /* 0x80 */ - VK_F18, /* 0x81 */ - VK_F19, /* 0x82 */ - VK_F20, /* 0x83 */ - VK_F21, /* 0x84 */ - VK_F22, /* 0x85 */ - VK_F23, /* 0x86 */ - VK_F24, /* 0x87 */ - - 0 -}; -#endif - /* * Hack -- given a pathname, point at the filename -- cgit v1.2.3 From d49211e82c52a62920f78b7faec77c275467bd24 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Jun 2012 23:42:19 +0200 Subject: Remove #ifdef BEN_HACK --- src/util.c | 32 -------------------------------- 1 file changed, 32 deletions(-) diff --git a/src/util.c b/src/util.c index bc8478e2..e8a0bad7 100644 --- a/src/util.c +++ b/src/util.c @@ -481,18 +481,6 @@ errr my_fputs(FILE *fff, cptr buf, huge n) } -/* -* Code Warrior is a little weird about some functions -*/ -#ifdef BEN_HACK -extern int open(const char *, int, ...); -extern int close(int); -extern int read(int, void *, unsigned int); -extern int write(int, const void *, unsigned int); -extern long lseek(int, long, int); -#endif /* BEN_HACK */ - - /* * The Macintosh is a little bit brain-dead sometimes */ @@ -581,11 +569,6 @@ errr fd_copy(cptr file, cptr what) * * Note that we assume that the file should be "binary" * -* XXX XXX XXX The horrible "BEN_HACK" code is for compiling under -* the CodeWarrior compiler, in which case, for some reason, none -* of the "O_*" flags are defined, and we must fake the definition -* of "O_RDONLY", "O_WRONLY", and "O_RDWR" in "A-win-h", and then -* we must simulate the effect of the proper "open()" call below. */ int fd_make(cptr file, int mode) { @@ -594,19 +577,6 @@ int fd_make(cptr file, int mode) /* Hack -- Try to parse the path */ if (path_parse(buf, 1024, file)) return ( -1); -#ifdef BEN_HACK - - /* Check for existance */ - /* if (fd_close(fd_open(file, O_RDONLY | O_BINARY))) return (1); */ - - /* Mega-Hack -- Create the file */ - (void)my_fclose(my_fopen(file, "wb")); - - /* Re-open the file for writing */ - return (open(buf, O_WRONLY | O_BINARY, mode)); - -#else /* BEN_HACK */ - #ifdef MACH_O_CARBON { @@ -629,8 +599,6 @@ return (open(buf, O_CREAT | O_EXCL | O_WRONLY | O_BINARY, mode)); #endif /* MACH_O_CARBON */ -#endif /* BEN_HACK */ - } -- cgit v1.2.3 From 6bf06677908ff25c98980b24a46057dbf3124cce Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 20:04:05 +0200 Subject: Auto-create "user" directory if necessary This fixes a bug where creation of the "scores" file would fail when selecting the Theme module with no pre-existing ~/.tome/2.3/theme directory. --- src/modules.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/modules.c b/src/modules.c index 0c9250eb..088dfbd7 100644 --- a/src/modules.c +++ b/src/modules.c @@ -58,6 +58,11 @@ void module_reset_dir(cptr dir, cptr new_path) strnfmt(buf, 1024, "%s%s%s", user_path, PATH_SEP, new_path); string_free(*d); *d = string_make(buf); + // Make it if needed */ + if (!private_check_user_directory(*d)) + { + quit(format("Unable to create module dir %s\n", *d)); + } } #ifdef PRIVATE_USER_PATH_DATA else if (!strcmp(dir, "data")) -- cgit v1.2.3 From 29b86f5998e5b74afcfba6e1bfae3cacb8799f5c Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 20:19:22 +0200 Subject: Remove DEBUG_HOOK preprocessor define --- src/plots.c | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/src/plots.c b/src/plots.c index ce60b446..afc59350 100644 --- a/src/plots.c +++ b/src/plots.c @@ -17,8 +17,6 @@ #include "messages.h" #include "quark.h" -/* #define DEBUG_HOOK */ - /******** Hooks stuff *********/ FILE *hook_file; @@ -98,10 +96,6 @@ hooks_chain* add_hook(int h_idx, hook_type hook, cptr name) MAKE(new_, hooks_chain); new_->hook = hook; sprintf(new_->name, "%s", name); -#ifdef DEBUG_HOOK - if (wizard) cmsg_format(TERM_VIOLET, "HOOK ADD: %s", name); - if (take_notes) add_note(format("HOOK ADD: %s", name), 'D'); -#endif new_->next = hooks_heads[h_idx]; hooks_heads[h_idx] = new_; return (new_); @@ -134,19 +128,11 @@ void del_hook(int h_idx, hook_type hook) { if (p == NULL) { -#ifdef DEBUG_HOOK - if (wizard) cmsg_format(TERM_VIOLET, "HOOK DEL: %s", c->name); - if (take_notes) add_note(format("HOOK DEL: %s", c->name), 'D'); -#endif hooks_heads[h_idx] = c->next; FREE(c, hooks_chain); } else { -#ifdef DEBUG_HOOK - if (wizard) cmsg_format(TERM_VIOLET, "HOOK DEL: %s", c->name); - if (take_notes) add_note(format("HOOK DEL: %s", c->name), 'D'); -#endif p->next = c->next; FREE(c, hooks_chain); } @@ -169,19 +155,11 @@ void del_hook_name(int h_idx, cptr name) { if (p == NULL) { -#ifdef DEBUG_HOOK - if (wizard) cmsg_format(TERM_VIOLET, "HOOK DEL: %s", c->name); - if (take_notes) add_note(format("HOOK DEL: %s", c->name), 'D'); -#endif hooks_heads[h_idx] = c->next; FREE(c, hooks_chain); } else { -#ifdef DEBUG_HOOK - if (wizard) cmsg_format(TERM_VIOLET, "HOOK DEL: %s", c->name); - if (take_notes) add_note(format("HOOK DEL: %s", c->name), 'D'); -#endif p->next = c->next; FREE(c, hooks_chain); } @@ -238,10 +216,6 @@ static bool_ vprocess_hooks_return (int h_idx, char *ret, char *fmt, va_list *ap while (c != NULL) { -#ifdef DEBUG_HOOK - if (wizard) cmsg_format(TERM_VIOLET, "HOOK: %s", c->name); - if (take_notes) add_note(format("HOOK PROCESS: %s", c->name), 'D'); -#endif if (c->type == HOOK_TYPE_C) { int i = 0, nb = 0; -- cgit v1.2.3 From f0fd793a1005cb82ea6613345050a307585ac837 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 20:24:10 +0200 Subject: Remove "SLang" front-end --- src/main-sla.c | 455 --------------------------------------------------------- src/main.c | 19 --- 2 files changed, 474 deletions(-) delete mode 100644 src/main-sla.c diff --git a/src/main-sla.c b/src/main-sla.c deleted file mode 100644 index 3c02d61f..00000000 --- a/src/main-sla.c +++ /dev/null @@ -1,455 +0,0 @@ -/* File: main-sla.c */ - -/* Purpose: Actual Unix "slang" support for Angband */ - -/* - * Author: hans@grumbeer.pfalz.de (Hans-Joachim Baader) - * - * Most of this code is adapted directly from "main-gcu.c" - */ - -#include "angband.h" - - -#ifdef USE_SLA - - - -#include - - -/* - * Are we "active"? - */ -static int slang_on = FALSE; - - -/* - * Can we use "color"? - */ -static bool_ can_use_color = FALSE; - - -/* - * Angband to SLang color conversion table - */ -static int colortable[16]; - - -/* - * Currently, only a single "term" is supported here - */ -static term term_screen_body; - - - - - -/* - * Hack -- see below - */ -void init_pair (int index, char *foreground, char *background) -{ - SLtt_set_color (index, "", foreground, background); -} - - - - - -#define A_NORMAL 0 -#define A_BOLD 8 -#define A_REVERSE 0 -#define REVERSE 8 - -#define COLOR_BLACK "black" -#define COLOR_BLUE "blue" -#define COLOR_GREEN "green" -#define COLOR_CYAN "cyan" -#define COLOR_RED "red" -#define COLOR_MAGENTA "magenta" -#define COLOR_YELLOW "brown" -#define COLOR_WHITE "lightgray" -#define COLOR_BBLACK "gray" -#define COLOR_BBLUE "brightblue" -#define COLOR_BGREEN "brightgreen" -#define COLOR_BCYAN "brightcyan" -#define COLOR_BRED "brightred" -#define COLOR_BMAGENTA "brightmagenta" -#define COLOR_BYELLOW "yellow" -#define COLOR_BWHITE "white" - - - - - -static char *color_terminals [] = -{ -#ifdef linux - "console", -#endif - "linux", - "xterm-color", - "color-xterm", - "xtermc", - "ansi", - 0 -}; - - - - - -/* - * Stolen from the Midnight Commander - */ -int has_colors(void) -{ - int i; - - char *terminal; - - - /* Access the terminal type */ - terminal = getenv("TERM"); - - /* Check for colors */ - SLtt_Use_Ansi_Colors = 0; - if (NULL != getenv ("COLORTERM")) - { - SLtt_Use_Ansi_Colors = 1; - } - - /* We want to allow overriding */ - for (i = 0; color_terminals [i]; i++) - { - if (strcmp (color_terminals [i], terminal) == 0) - { - SLtt_Use_Ansi_Colors = 1; - } - } - - /* Setup emulated colors */ - if (SLtt_Use_Ansi_Colors) - { - /*init_pair (REVERSE, "black", "white");*/ - } - - /* Setup bizarre colors */ - else - { - SLtt_set_mono (A_BOLD, NULL, SLTT_BOLD_MASK); - SLtt_set_mono (A_REVERSE, NULL, SLTT_REV_MASK); - SLtt_set_mono (A_BOLD | A_REVERSE, NULL, SLTT_BOLD_MASK | SLTT_REV_MASK); - } - - return SLtt_Use_Ansi_Colors; -} - - - - - -/* - * Nuke SLang - */ -static void Term_nuke_sla(term *t) -{ - if (!slang_on) return; - - /* Show the cursor */ - /* curs_set(1); */ - - /* Clear the screen */ - (void)SLsmg_cls(); - - /* Refresh */ - SLsmg_refresh(); - - /* We are now off */ - slang_on = FALSE; - - /* Shut down */ - SLsmg_reset_smg(); - SLang_reset_tty(); -} - - -/* - * Init SLang - */ -static void Term_init_sla(term *t) -{ - /* Note that we are on */ - slang_on = TRUE; -} - - -/* - * Process an event, wait if requested - */ -static errr Term_xtra_sla_event(int v) -{ - /* Do not wait unless requested */ - if (!v && (SLang_input_pending (0) == 0)) return (1); - - /* Get and enqueue the key */ - Term_keypress(SLang_getkey ()); - - /* Success */ - return 0; -} - - - -/* - * Suspend / Resume - */ -static errr Term_xtra_sla_alive(int v) -{ - /* Suspend */ - if (!v) - { - /* Oops */ - if (!slang_on) return (1); - - /* We are now off */ - slang_on = FALSE; - - /* Shut down (temporarily) */ - SLsmg_reset_smg(); - SLang_reset_tty(); - } - - /* Resume */ - else - { - /* Oops */ - if (slang_on) return (1); - - /* Fix the screen */ - SLsmg_refresh(); - - /* Note that we are on */ - slang_on = TRUE; - } - - /* Success */ - return (0); -} - - -/* - * Handle a "special request" - */ -static errr Term_xtra_sla(int n, int v) -{ - /* Analyze the request */ - switch (n) - { - /* Make a noise */ - case TERM_XTRA_NOISE: - (void)SLsmg_write_char('\007'); - return (0); - - /* Flush the ncurses buffer */ - case TERM_XTRA_FRESH: - (void)SLsmg_refresh(); - return (0); - - /* Make the cursor invisible or visible */ - case TERM_XTRA_SHAPE: - /* curs_set(v); */ - return (0); - - /* Handle events */ - case TERM_XTRA_EVENT: - return (Term_xtra_sla_event(v)); - - /* Handle events */ - case TERM_XTRA_FLUSH: - while (!Term_xtra_sla_event(FALSE)); - return (0); - - /* Suspend/Resume */ - case TERM_XTRA_ALIVE: - return (Term_xtra_sla_alive(v)); - - /* Clear the screen */ - case TERM_XTRA_CLEAR: - (void)SLsmg_cls(); - SLsmg_gotorc(0, 0); - return (0); - - /* Delay */ - case TERM_XTRA_DELAY: - usleep(1000 * v); - return (0); - } - - /* Oops */ - return (1); -} - - - - -/* - * Actually MOVE the hardware cursor - */ -static errr Term_curs_sla(int x, int y, int z) -{ - /* Literally move the cursor */ - SLsmg_gotorc (y, x); - - /* Success */ - return 0; -} - - -/* - * Erase some characters - */ -static errr Term_wipe_sla(int x, int y, int n) -{ - int i; - - /* Place the cursor */ - SLsmg_gotorc(y, x); - - /* Dump spaces */ - for (i = 0; i < n; i++) SLsmg_write_char(' '); - - /* Success */ - return 0; -} - - -/* - * Place some text on the screen using an attribute - */ -static errr Term_text_sla(int x, int y, int n, byte a, cptr s) -{ - /* Move the cursor */ - SLsmg_gotorc(y, x); - - /* Set the color */ - if (can_use_color) SLsmg_set_color(colortable[a&0x0F]); - - /* Dump the string */ - SLsmg_write_nchars(s, n); - - /* Success */ - return 0; -} - - -/* - * Prepare "SLang" for use by the file "term.c" - * Installs the "hook" functions defined above - */ -errr init_sla(void) -{ - int i, err; - - term *t = &term_screen_body; - - - /* Initialize, check for errors */ - err = (SLang_init_tty( -1, TRUE, 0) == -1); - - /* Quit on error */ - if (err) quit("SLang initialization failed"); - - /* Get terminal info */ - SLtt_get_terminfo (); - - /* Initialize some more */ - if (SLsmg_init_smg() == 0) - { - quit("Could not get virtual display memory"); - } - - /* Check we have enough screen. */ - err = ((SLtt_Screen_Rows < 24) || (SLtt_Screen_Cols < 80)); - - /* Quit with message */ - if (err) quit("SLang screen must be at least 80x24"); - - /* Now let's go for a little bit of color! */ - err = !has_colors(); - - /* Do we have color available? */ - can_use_color = !err; - - /* Init the Color-pairs and set up a translation table */ - /* If the terminal has enough colors */ - /* Color-pair 0 is *always* WHITE on BLACK */ - - /* XXX XXX XXX See "main-gcu.c" for proper method */ - - /* Only do this on color machines */ - if (can_use_color) - { - /* Prepare the color pairs */ - init_pair(1, COLOR_RED, COLOR_BLACK); - init_pair(2, COLOR_GREEN, COLOR_BLACK); - init_pair(3, COLOR_YELLOW, COLOR_BLACK); - init_pair(4, COLOR_BLUE, COLOR_BLACK); - init_pair(5, COLOR_MAGENTA, COLOR_BLACK); - init_pair(6, COLOR_CYAN, COLOR_BLACK); - init_pair(7, COLOR_BLACK, COLOR_BLACK); - init_pair(9, COLOR_BRED, COLOR_BLACK); - init_pair(10, COLOR_BGREEN, COLOR_BLACK); - init_pair(11, COLOR_BYELLOW, COLOR_BLACK); - init_pair(12, COLOR_BBLUE, COLOR_BLACK); - init_pair(13, COLOR_BMAGENTA, COLOR_BLACK); - init_pair(14, COLOR_BCYAN, COLOR_BLACK); - init_pair(15, COLOR_BBLACK, COLOR_BLACK); - - /* Prepare the color table */ - colortable[0] = 7; /* Black */ - colortable[1] = 0; /* White */ - colortable[2] = 6; /* Grey XXX */ - colortable[3] = 11; /* Orange XXX */ - colortable[4] = 1; /* Red */ - colortable[5] = 2; /* Green */ - colortable[6] = 4; /* Blue */ - colortable[7] = 3; /* Brown */ - colortable[8] = 15; /* Dark-grey XXX */ - colortable[9] = 14; /* Light-grey XXX */ - colortable[10] = 5; /* Purple */ - colortable[11] = 11; /* Yellow */ - colortable[12] = 9; /* Light Red */ - colortable[13] = 10; /* Light Green */ - colortable[14] = 12; /* Light Blue */ - colortable[15] = 3; /* Light Brown XXX */ - } - - - /* Initialize the term */ - term_init(t, 80, 24, 64); - - /* Stick in some hooks */ - t->nuke_hook = Term_nuke_sla; - t->init_hook = Term_init_sla; - - /* Stick in some more hooks */ - t->xtra_hook = Term_xtra_sla; - t->curs_hook = Term_curs_sla; - t->wipe_hook = Term_wipe_sla; - t->text_hook = Term_text_sla; - - /* Save the term */ - term_screen = t; - - /* Activate it */ - Term_activate(t); - - - /* Success */ - return 0; -} - -#endif /* USE_SLA */ - diff --git a/src/main.c b/src/main.c index 9bde57a1..6e2ab52a 100644 --- a/src/main.c +++ b/src/main.c @@ -486,10 +486,6 @@ usage: puts(" -- -b Requests big screen"); #endif /* USE_GCU */ -#ifdef USE_SLA - puts(" -msla To use SLang"); -#endif /* USE_SLA */ - #ifdef USE_SDL puts(" -msdl To use SDL"); puts(" -- Sub options"); @@ -618,21 +614,6 @@ usage: } #endif - -#ifdef USE_SLA - /* Attempt to use the "main-sla.c" support */ - if (!done && (!mstr || (streq(mstr, "sla")))) - { - extern errr init_sla(void); - if (0 == init_sla()) - { - ANGBAND_SYS = "sla"; - done = TRUE; - } - } -#endif - - #ifdef USE_SDL /* Attempt to use the "main-sdl.c" support */ if (!done && (!mstr || (streq(mstr, "sdl")))) -- cgit v1.2.3 From fef4e37676e3890d65277f378e29f3f01a1a66ff Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 20:24:49 +0200 Subject: Remove USE_GLU conditional code --- src/main.c | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/src/main.c b/src/main.c index 6e2ab52a..8a56cd17 100644 --- a/src/main.c +++ b/src/main.c @@ -523,19 +523,6 @@ usage: quit_aux = quit_hook; -#ifdef USE_GLU - /* Attempt to use the "main-glu.c" support */ - if (!done && (!mstr || (streq(mstr, "glu")))) - { - extern errr init_glu(int, char**); - if (0 == init_glu(argc, argv)) - { - ANGBAND_SYS = "glu"; - done = TRUE; - } - } -#endif - #ifdef USE_GTK2 /* Attempt to use the "main-gtk2.c" support */ if (!done && (!mstr || (streq(mstr, "gtk2")))) @@ -601,19 +588,6 @@ usage: } #endif -#ifdef USE_GLU - /* Attempt to use the "main-glu.c" support */ - if (!done && (!mstr || (streq(mstr, "glu")))) - { - extern errr init_glu(int, char**); - if (0 == init_glu(argc, argv)) - { - ANGBAND_SYS = "glu"; - done = TRUE; - } - } -#endif - #ifdef USE_SDL /* Attempt to use the "main-sdl.c" support */ if (!done && (!mstr || (streq(mstr, "sdl")))) -- cgit v1.2.3 From 5a4f719a406a09b14d10758f44f5037634fbdfef Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 20:32:44 +0200 Subject: Remove ANGBAND300 conditional code --- src/main-gtk2.c | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/src/main-gtk2.c b/src/main-gtk2.c index e55b038e..a3ab64fc 100644 --- a/src/main-gtk2.c +++ b/src/main-gtk2.c @@ -66,11 +66,6 @@ /* * Some examples */ -#ifdef ANGBAND300 -# define can_save TRUE /* Mimick the short-lived flag */ -# define C_FREE(P, N, T) FREE(P) /* Emulate the long-lived macro */ -#endif /* ANGBAND300 */ - #ifdef GUMBAND # define ANG293_COMPAT /* Requires V2.9.3 compatibility code */ # define ANG291_COMPAT /* Requires V2.9.1 compatibility code */ @@ -350,11 +345,7 @@ static bool_ use_transparency = TRUE; /* * Hook to "release" memory */ -#ifdef ANGBAND300 -static vptr hook_rnfree(vptr v) -#else static vptr hook_rnfree(vptr v, huge size) -#endif /* ANGBAND300 */ { /* Dispose */ g_free(v); @@ -4702,26 +4693,6 @@ static void hook_quit(cptr str) } -#ifdef ANGBAND300 - -/* - * Help message for this port - */ -const char help_gtk[] = - "GTK for X11, subopts -n\n" - " -b(acking store off)\n" -#ifdef USE_GRAPHICS - " -g(raphics) -o(ld graphics) -s(moothscaling off) \n" - " -t(ransparency on)\n" -# ifdef USE_DOUBLE_TILES - " -w(ide tiles)\n" -# endif /* USE_DOUBLE_TILES */ -#endif /* USE_GRAPHICS */ - " and standard GTK options"; - -#endif /* ANGBAND300 */ - - /* * Initialization function */ -- cgit v1.2.3 From f24219b49d6d501c668e1e9ec7d579d47d14ca6c Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 20:33:46 +0200 Subject: Remove GUMBAND conditional code --- src/main-gtk2.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/main-gtk2.c b/src/main-gtk2.c index a3ab64fc..f7e15333 100644 --- a/src/main-gtk2.c +++ b/src/main-gtk2.c @@ -66,14 +66,6 @@ /* * Some examples */ -#ifdef GUMBAND -# define ANG293_COMPAT /* Requires V2.9.3 compatibility code */ -# define ANG291_COMPAT /* Requires V2.9.1 compatibility code */ -# define ANG281_RESET_VISUALS /* The old style reset_visuals() */ -# define OLD_SAVEFILE_CODE /* See also SAVEFILE_MUTABLE in files.c */ -# define NO_REDRAW_SECTION /* Doesn't have Term_redraw_section() */ -#endif /* GUMBAND */ - #ifdef OANGBAND # define ANG293_COMPAT /* Requires V2.9.3 compatibility code */ # define ZANG_SAVE_GAME /* do_cmd_save_game with auto_save parameter */ -- cgit v1.2.3 From 695b969c31ece1ee87fff6b88cbe1f54fc40ac49 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 20:34:14 +0200 Subject: Remove OANGBAND conditional code --- src/main-gtk2.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/main-gtk2.c b/src/main-gtk2.c index f7e15333..c39d8fff 100644 --- a/src/main-gtk2.c +++ b/src/main-gtk2.c @@ -63,14 +63,6 @@ # define USE_DOUBLE_TILES /* Mogami's bigtile patch */ #endif /* TOME */ -/* - * Some examples - */ -#ifdef OANGBAND -# define ANG293_COMPAT /* Requires V2.9.3 compatibility code */ -# define ZANG_SAVE_GAME /* do_cmd_save_game with auto_save parameter */ -#endif /* OANGBAND */ - #ifdef USE_GTK2 -- cgit v1.2.3 From 803e532c456db05e3b26ee0fc2a119b63f2df4f6 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 20:35:13 +0200 Subject: Remove USE_GTK conditional code --- src/main.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/main.c b/src/main.c index 8a56cd17..65ec6c3b 100644 --- a/src/main.c +++ b/src/main.c @@ -536,19 +536,6 @@ usage: } #endif -#ifdef USE_GTK - /* Attempt to use the "main-gtk.c" support */ - if (!done && (!mstr || (streq(mstr, "gtk")))) - { - extern errr init_gtk(int, char**); - if (0 == init_gtk(argc, argv)) - { - ANGBAND_SYS = "gtk"; - done = TRUE; - } - } -#endif - #ifdef USE_XAW /* Attempt to use the "main-xaw.c" support */ if (!done && (!mstr || (streq(mstr, "xaw")))) -- cgit v1.2.3 From 0055cc0ff65aa85b00d7d57da5ce0ecd6309257e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 20:37:29 +0200 Subject: Remove CHECK_MEMORY_LEAKS conditional code --- src/main.c | 7 ------- src/z-virt.h | 4 ---- 2 files changed, 11 deletions(-) diff --git a/src/main.c b/src/main.c index 65ec6c3b..2950506f 100644 --- a/src/main.c +++ b/src/main.c @@ -250,9 +250,6 @@ int main(int argc, char *argv[]) int player_uid; -#ifdef CHECK_MEMORY_LEAKS - GC_find_leak = 1; -#endif /* CHECK_MEMORY_LEAKS */ /* Save the "program name" XXX XXX XXX */ @@ -607,10 +604,6 @@ usage: /* Play the game */ play_game(new_game); -#ifdef CHECK_MEMORY_LEAKS - CHECK_LEAKS(); -#endif - /* Quit */ quit(NULL); diff --git a/src/z-virt.h b/src/z-virt.h index a7880f2f..58aed382 100644 --- a/src/z-virt.h +++ b/src/z-virt.h @@ -17,10 +17,6 @@ extern "C" { #include "h-basic.h" -#ifdef CHECK_MEMORY_LEAKS -#include -#endif - /* * Memory management routines. * -- cgit v1.2.3 From 5cf2eebbe631c01f541a1d5ad9221b6942fe5715 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 20:39:05 +0200 Subject: Remove OLD_SAVEFILE_CODE conditional code --- src/main-gtk2.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main-gtk2.c b/src/main-gtk2.c index c39d8fff..b34c6f11 100644 --- a/src/main-gtk2.c +++ b/src/main-gtk2.c @@ -4821,13 +4821,9 @@ errr init_gtk2(int argc, char **argv) /* Initialize */ init_angband(); -#ifndef OLD_SAVEFILE_CODE - /* Hack - because this port has New/Open menus XXX */ savefile[0] = '\0'; -#endif /* !OLD_SAVEFILE_CODE */ - /* Prompt the user */ prt("[Choose 'New' or 'Open' from the 'File' menu]", 23, 17); Term_fresh(); -- cgit v1.2.3 From bcbdb77ad85255f788b2fb37a13d100428f883b1 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 20:42:04 +0200 Subject: Remove DRS_SHOW_* preprocessor defines --- src/config.h | 11 ----------- src/xtra1.c | 6 ------ 2 files changed, 17 deletions(-) diff --git a/src/config.h b/src/config.h index 99b6b9f0..889b3574 100644 --- a/src/config.h +++ b/src/config.h @@ -144,17 +144,6 @@ -/* - * OPTION: Allow use of extended spell info -DRS- - */ -#define DRS_SHOW_SPELL_INFO - -/* - * OPTION: Allow use of the monster health bar -DRS- - */ -#define DRS_SHOW_HEALTH_BAR - - /* * OPTION: Allow the use of "sound" in various places. diff --git a/src/xtra1.c b/src/xtra1.c index d4df67af..6e9b15fd 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -933,9 +933,6 @@ static void prt_stun(void) */ static void health_redraw(void) { - -#ifdef DRS_SHOW_HEALTH_BAR - /* Not tracking */ if (!health_who) { @@ -1010,9 +1007,6 @@ static void health_redraw(void) /* Dump the current "health" (use '*' symbols) */ Term_putstr(COL_INFO + 1, ROW_INFO, len, attr, "**********"); } - -#endif - } -- cgit v1.2.3 From 2384dff0de2858e8c97fa7b18634aca0ec4f5a8e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 20:56:05 +0200 Subject: Remove ALLOW_FEAR preprocessor define Remove duplicate fear-handling code while we're at it --- src/config.h | 5 ----- src/externs.h | 1 + src/melee2.c | 30 ++++++++++++++++++------------ src/xtra2.c | 55 ++----------------------------------------------------- 4 files changed, 21 insertions(+), 70 deletions(-) diff --git a/src/config.h b/src/config.h index 889b3574..3e0076de 100644 --- a/src/config.h +++ b/src/config.h @@ -118,11 +118,6 @@ #define ALLOW_AUTOROLLER -/* - * OPTION: Allow monsters to "flee" when hit hard - */ -#define ALLOW_FEAR - /* * OPTION: Allow monsters to "flee" from strong players */ diff --git a/src/externs.h b/src/externs.h index 33a74266..86127f25 100644 --- a/src/externs.h +++ b/src/externs.h @@ -985,6 +985,7 @@ extern errr rd_savefile_new(void); /* melee2.c */ extern int monst_spell_monst_spell; extern bool_ mon_take_hit_mon(int s_idx, int m_idx, int dam, bool_ *fear, cptr note); +extern void mon_handle_fear(monster_type *m_ptr, int dam, bool_ *fear); extern int check_hit2(int power, int level, int ac); extern int get_attack_power(int effect); extern bool_ carried_make_attack_normal(int r_idx); diff --git a/src/melee2.c b/src/melee2.c index 5443a214..91be521d 100644 --- a/src/melee2.c +++ b/src/melee2.c @@ -166,7 +166,21 @@ bool_ mon_take_hit_mon(int s_idx, int m_idx, int dam, bool_ *fear, cptr note) } -#ifdef ALLOW_FEAR + /* Apply fear */ + mon_handle_fear(m_ptr, dam, fear); + + /* Not dead yet */ + return (FALSE); +} + + +void mon_handle_fear(monster_type *m_ptr, int dam, bool_ *fear) +{ + monster_race *r_ptr = NULL; + + assert(m_ptr != NULL); + + r_ptr = race_inf(m_ptr); /* Mega-Hack -- Pain cancels fear */ if (m_ptr->monfear && (dam > 0)) @@ -200,9 +214,9 @@ bool_ mon_take_hit_mon(int s_idx, int m_idx, int dam, bool_ *fear, cptr note) percentage = (100L * m_ptr->hp) / m_ptr->maxhp; /* - * Run (sometimes) if at 10% or less of max hit points, - * or (usually) when hit for half its current hit points - */ + * Run (sometimes) if at 10% or less of max hit points, + * or (usually) when hit for half its current hit points + */ if (((percentage <= 10) && (rand_int(10) < percentage)) || ((dam >= m_ptr->hp) && (rand_int(100) < 80))) { @@ -215,17 +229,9 @@ bool_ mon_take_hit_mon(int s_idx, int m_idx, int dam, bool_ *fear, cptr note) 20 : ((11 - percentage) * 5))); } } - -#endif /* ALLOW_FEAR */ - - /* Not dead yet */ - return (FALSE); } - - - /* * And now for Intelligent monster attacks (including spells). * diff --git a/src/xtra2.c b/src/xtra2.c index 6594e482..ef753b3a 100644 --- a/src/xtra2.c +++ b/src/xtra2.c @@ -3452,59 +3452,8 @@ bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note) return (TRUE); } - -#ifdef ALLOW_FEAR - - /* Mega-Hack -- Pain cancels fear */ - if (m_ptr->monfear && (dam > 0)) - { - int tmp = randint(dam); - - /* Cure a little fear */ - if (tmp < m_ptr->monfear) - { - /* Reduce fear */ - m_ptr->monfear -= tmp; - } - - /* Cure all the fear */ - else - { - /* Cure fear */ - m_ptr->monfear = 0; - - /* No more fear */ - (*fear) = FALSE; - } - } - - /* Sometimes a monster gets scared by damage */ - if (!m_ptr->monfear && !(r_ptr->flags3 & (RF3_NO_FEAR))) - { - int percentage; - - /* Percentage of fully healthy */ - percentage = (100L * m_ptr->hp) / m_ptr->maxhp; - - /* - * Run (sometimes) if at 10% or less of max hit points, - * or (usually) when hit for half its current hit points - */ - if (((percentage <= 10) && (rand_int(10) < percentage)) || - ((dam >= m_ptr->hp) && (rand_int(100) < 80))) - { - /* Hack -- note fear */ - (*fear) = TRUE; - - /* XXX XXX XXX Hack -- Add some timed fear */ - m_ptr->monfear = (randint(10) + - (((dam >= m_ptr->hp) && (percentage > 7)) ? - 20 : ((11 - percentage) * 5))); - } - } - -#endif - + /* Apply fear */ + mon_handle_fear(m_ptr, dam, fear); /* Not dead yet */ return (FALSE); -- cgit v1.2.3 From 047922a4dd4f74c2a475935368bb15edea516e6f Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 20:57:45 +0200 Subject: Remove ALLOW_TERROR preprocessor define --- src/config.h | 6 ------ src/melee2.c | 9 --------- 2 files changed, 15 deletions(-) diff --git a/src/config.h b/src/config.h index 3e0076de..86e4f17f 100644 --- a/src/config.h +++ b/src/config.h @@ -118,12 +118,6 @@ #define ALLOW_AUTOROLLER -/* - * OPTION: Allow monsters to "flee" from strong players - */ -#define ALLOW_TERROR - - /* * OPTION: Handle signals */ diff --git a/src/melee2.c b/src/melee2.c index 91be521d..04575dd2 100644 --- a/src/melee2.c +++ b/src/melee2.c @@ -4680,16 +4680,11 @@ bool_ make_attack_spell(int m_idx) static int mon_will_run(int m_idx) { monster_type *m_ptr = &m_list[m_idx]; - -#ifdef ALLOW_TERROR - u16b p_lev, m_lev; u16b p_chp, p_mhp; u16b m_chp, m_mhp; u32b p_val, m_val; -#endif - /* Keep monsters from running too far away */ if (m_ptr->cdis > MAX_SIGHT + 5) return (FALSE); @@ -4699,8 +4694,6 @@ static int mon_will_run(int m_idx) /* All "afraid" monsters will run away */ if (m_ptr->monfear) return (TRUE); -#ifdef ALLOW_TERROR - /* Nearby monsters will not become terrified */ if (m_ptr->cdis <= 5) return (FALSE); @@ -4729,8 +4722,6 @@ static int mon_will_run(int m_idx) /* Strong players scare strong monsters */ if (p_val * m_mhp > m_val * p_mhp) return (TRUE); -#endif - /* Assume no terror */ return (FALSE); } -- cgit v1.2.3 From 146edd7571c86de7c580af6ac4db6bb9b85e5ba0 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 21:42:38 +0200 Subject: Remove SHOW_LIFE_RATE preprocessor define --- src/birth.c | 16 ---------------- src/config.h | 3 --- 2 files changed, 19 deletions(-) diff --git a/src/birth.c b/src/birth.c index d8c4ef3f..09c6f08d 100644 --- a/src/birth.c +++ b/src/birth.c @@ -465,12 +465,6 @@ static void get_extra(void) { int i, j, min_value, max_value; -#ifdef SHOW_LIFE_RATE - - int percent; - -#endif - /* Level one */ p_ptr->max_plv = p_ptr->lev = 1; @@ -523,16 +517,6 @@ static void get_extra(void) p_ptr->tactic = 4; p_ptr->movement = 4; - -#ifdef SHOW_LIFE_RATE - - percent = (int)(((long)player_hp[PY_MAX_LEVEL - 1] * 200L) / - (p_ptr->hitdie + ((PY_MAX_LEVEL - 1) * p_ptr->hitdie))); - - msg_format("Current Life Rating is %d/100.", percent); - msg_print(NULL); - -#endif /* SHOW_LIFE_RATE */ } diff --git a/src/config.h b/src/config.h index 86e4f17f..f0be62da 100644 --- a/src/config.h +++ b/src/config.h @@ -242,9 +242,6 @@ /* ToME options: */ -/* Should the player know his / her starting life rate? */ -/* #define SHOW_LIFE_RATE */ - /* Allow hordes of 'similar' monsters */ #define MONSTER_HORDES -- cgit v1.2.3 From fe3f2d47aa2a4da812597a2c78a8a5f10e044cdf Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 21:45:09 +0200 Subject: Remove TRACK_FRIENDS preprocessor define --- src/config.h | 3 --- src/dungeon.c | 22 ---------------------- 2 files changed, 25 deletions(-) diff --git a/src/config.h b/src/config.h index f0be62da..438832b4 100644 --- a/src/config.h +++ b/src/config.h @@ -250,9 +250,6 @@ /* For testing the vaults */ /* # define FORCE_V_IDX 20 */ -/* Testing upkeep */ -/* # define TRACK_FRIENDS */ - /* * Using the fast autoroller can be considered as cheating */ diff --git a/src/dungeon.c b/src/dungeon.c index 43db5b29..3a725720 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -1836,25 +1836,12 @@ static void process_world(void) if (has_ability(AB_PERFECT_CASTING)) upkeep_divider = 15; -#ifdef TRACK_FRIENDS - - if (wizard) msg_format("Total friends: %d.", total_friends); - -#endif /* TRACK_FRIENDS */ - if (total_friends > 1 + (p_ptr->lev / (upkeep_divider))) { upkeep_factor = (total_friend_levels); if (upkeep_factor > 100) upkeep_factor = 100; else if (upkeep_factor < 10) upkeep_factor = 10; - -#ifdef TRACK_FRIENDS - - if (wizard) msg_format("Levels %d, upkeep %d", total_friend_levels, - upkeep_factor); - -#endif /* TRACK_FRIENDS */ } } @@ -1865,15 +1852,6 @@ static void process_world(void) { s16b upkeep_regen = (((100 - upkeep_factor) * regen_amount) / 100); regenmana(upkeep_regen); - -#ifdef TRACK_FRIENDS - - if (wizard) - { - msg_format("Regen: %d/%d", upkeep_regen, regen_amount); - } - -#endif /* TRACK_FRIENDS */ } else { -- cgit v1.2.3 From a65a6d5f557d4e6846c1ef959a68fa556d86fd1e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 21:47:49 +0200 Subject: Remove USE_FAST_AUTOROLLER preprocessor define --- src/birth.c | 6 ------ src/config.h | 5 ----- 2 files changed, 11 deletions(-) diff --git a/src/birth.c b/src/birth.c index 09c6f08d..31be2db2 100644 --- a/src/birth.c +++ b/src/birth.c @@ -3027,12 +3027,6 @@ static bool_ player_birth_aux_auto() /* Make sure they see everything */ Term_fresh(); -#ifndef USE_FAST_AUTOROLLER - - /* Delay 1/10 second */ - if (fast_autoroller && flag) Term_xtra(TERM_XTRA_DELAY, 100); - -#endif /* Do not wait for a key */ inkey_scan = TRUE; diff --git a/src/config.h b/src/config.h index 438832b4..73e016e2 100644 --- a/src/config.h +++ b/src/config.h @@ -250,11 +250,6 @@ /* For testing the vaults */ /* # define FORCE_V_IDX 20 */ -/* - * Using the fast autoroller can be considered as cheating - */ -#define USE_FAST_AUTOROLLER - /* * Enable the CTRL + L command to quit without saving * Only use for debugging purpose, otherwise you are a CHEATER -- cgit v1.2.3 From 6db6117ed91de0e002dbcd7731b32f6e409b2043 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 21:51:12 +0200 Subject: Remove ALLOW_QUITTING preprocessor define --- src/angband.rc | 6 ------ src/config.h | 6 ------ src/dungeon.c | 9 --------- src/main-win.c | 44 +------------------------------------------- 4 files changed, 1 insertion(+), 64 deletions(-) diff --git a/src/angband.rc b/src/angband.rc index 00e16516..547d43a1 100644 --- a/src/angband.rc +++ b/src/angband.rc @@ -1,10 +1,5 @@ /* File: angband.rc */ -/* - * If the windows command to compile this file understands #ifdef's, please - * say #ifdef ALLOW_QUITTING to select from "A&bort" and "Sh&ow scores" - */ - ANGBAND MENU { POPUP "&File" @@ -12,7 +7,6 @@ ANGBAND MENU MENUITEM "&Save", 110 MENUITEM SEPARATOR MENUITEM "S&how score", 120 - /*MENUITEM "A&bort", 120*/ MENUITEM "E&xit", 121 } diff --git a/src/config.h b/src/config.h index 73e016e2..2215f075 100644 --- a/src/config.h +++ b/src/config.h @@ -250,12 +250,6 @@ /* For testing the vaults */ /* # define FORCE_V_IDX 20 */ -/* - * Enable the CTRL + L command to quit without saving - * Only use for debugging purpose, otherwise you are a CHEATER - */ -/* #define ALLOW_QUITTING */ - /* * Allow makefiles to override the default file mode */ diff --git a/src/dungeon.c b/src/dungeon.c index 3a725720..ae8d6912 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -3473,15 +3473,6 @@ static void process_command(void) break; } -#ifdef ALLOW_QUITTING - - case KTRL('L'): - { - quit("CHEATER"); - break; - } - -#endif /*** Wizard Commands ***/ diff --git a/src/main-win.c b/src/main-win.c index fdde5e87..a618de96 100644 --- a/src/main-win.c +++ b/src/main-win.c @@ -101,11 +101,7 @@ #define IDM_FILE_NEW 100 #define IDM_FILE_OPEN 101 #define IDM_FILE_SAVE 110 -#ifdef ALLOW_QUITTING -# define IDM_FILE_ABORT 120 -#else -# define IDM_FILE_SCORE 120 -#endif +#define IDM_FILE_SCORE 120 #define IDM_FILE_EXIT 121 #define IDM_WINDOW_VIS_0 200 @@ -2465,13 +2461,8 @@ static void setup_menus(void) MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); EnableMenuItem(hm, IDM_FILE_SAVE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); -#ifdef ALLOW_QUITTING - EnableMenuItem(hm, IDM_FILE_ABORT, - MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); -#else EnableMenuItem(hm, IDM_FILE_SCORE, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); -#endif /* ALLOW_QUITTING */ EnableMenuItem(hm, IDM_FILE_EXIT, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED); @@ -2495,14 +2486,6 @@ static void setup_menus(void) MF_BYCOMMAND | MF_ENABLED); } -#ifdef ALLOW_QUITTING - - /* Menu "File", Item "Abort" */ - EnableMenuItem(hm, IDM_FILE_ABORT, - MF_BYCOMMAND | MF_ENABLED); - -#else - /* Menu "File", Item "Score" */ if (initialized && character_generated && !character_icky) { @@ -2510,8 +2493,6 @@ static void setup_menus(void) MF_BYCOMMAND | MF_ENABLED); } -#endif - /* Menu "File", Item "Exit" */ EnableMenuItem(hm, IDM_FILE_EXIT, MF_BYCOMMAND | MF_ENABLED); @@ -2832,27 +2813,6 @@ ofn.lStructSize = sizeof(OPENFILENAME); break; } -#ifdef ALLOW_QUITTING - - /* Abort */ - case IDM_FILE_ABORT: - { - if (game_in_progress && character_generated) - { - /* XXX XXX XXX */ - if (MessageBox(data[0].w, - "Your character will be not saved!", "Warning", - MB_ICONEXCLAMATION | MB_OKCANCEL) == IDCANCEL) - { - break; - } - } - quit(NULL); - break; - } - -#else - /* Score */ case IDM_FILE_SCORE: { @@ -2862,8 +2822,6 @@ ofn.lStructSize = sizeof(OPENFILENAME); break; } -#endif - case IDM_WINDOW_VIS_0: { plog("You are not allowed to do that!"); -- cgit v1.2.3 From a76f713c5a5e164a1c78af296fc4b9afa74fb22b Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 21:54:38 +0200 Subject: Remove SAVEFILE_MUTABLE preprocessor define --- src/config.h | 14 -------------- src/files.c | 7 ------- 2 files changed, 21 deletions(-) diff --git a/src/config.h b/src/config.h index 2215f075..87e7e89a 100644 --- a/src/config.h +++ b/src/config.h @@ -204,20 +204,6 @@ #define PRIVATE_USER_PATH "~/.tome" #endif -/* - * OPTION: For some brain-dead computers with no command line interface, - * namely Macintosh, there has to be some way of "naming" your savefiles. - * The current "Macintosh" hack is to make it so whenever the character - * name changes, the savefile is renamed accordingly. But on normal - * machines, once you manage to "load" a savefile, it stays that way. - * Macintosh is particularly weird because you can load savefiles that - * are not contained in the "lib:save:" folder, and if you change the - * player's name, it will then save the savefile elsewhere. - */ -#if defined(MACINTOSH) || defined(WINDOWS) -/* #define SAVEFILE_MUTABLE */ -#endif - /* * OPTION: Person to bother if something goes wrong. diff --git a/src/files.c b/src/files.c index c1ff6d36..ea1922a5 100644 --- a/src/files.c +++ b/src/files.c @@ -4066,13 +4066,6 @@ void process_player_name(bool_ sf) if (!player_base[0]) strcpy(player_base, "PLAYER"); -#ifdef SAVEFILE_MUTABLE - - /* Accept */ - sf = TRUE; - -#endif - /* Change the savefile name */ if (sf) { -- cgit v1.2.3 From def21e40a42a6e7dc949e9748de61f6bc0561216 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 21:57:37 +0200 Subject: Remove MONSTER_HORDES preprocessor define --- lib/help/debug.txt | 3 +-- lib/mods/theme/help/debug.txt | 3 +-- src/config.h | 5 ----- src/monster2.c | 8 -------- src/wizard2.c | 6 ------ 5 files changed, 2 insertions(+), 23 deletions(-) diff --git a/lib/help/debug.txt b/lib/help/debug.txt index 4d5e75da..0420a42c 100644 --- a/lib/help/debug.txt +++ b/lib/help/debug.txt @@ -138,8 +138,7 @@ maximal legal value. Change your life rating. ~~~~~16 [[[[[GHostile monster creation (H)] - Summons a Pack of Creatures of the same kind. Will only work - if MONSTER_HORDES has been defined at compile time. + Summons a Pack of Creatures of the same kind. ~~~~~17 [[[[[GIdentify (i)] Like a Scroll of Identify. diff --git a/lib/mods/theme/help/debug.txt b/lib/mods/theme/help/debug.txt index 56d57098..780b2f4d 100644 --- a/lib/mods/theme/help/debug.txt +++ b/lib/mods/theme/help/debug.txt @@ -138,8 +138,7 @@ maximal legal value. Change your life rating. ~~~~~16 [[[[[GHostile monster creation (H)] - Summons a Pack of Creatures of the same kind. Will only work - if MONSTER_HORDES has been defined at compile time. + Summons a Pack of Creatures of the same kind. ~~~~~17 [[[[[GIdentify (i)] Like a Scroll of Identify. diff --git a/src/config.h b/src/config.h index 87e7e89a..1a7218d7 100644 --- a/src/config.h +++ b/src/config.h @@ -226,11 +226,6 @@ -/* ToME options: */ - -/* Allow hordes of 'similar' monsters */ -#define MONSTER_HORDES - /* Wizard mode testing options: */ /* For testing the vaults */ diff --git a/src/monster2.c b/src/monster2.c index e9ae164e..b87df278 100644 --- a/src/monster2.c +++ b/src/monster2.c @@ -2940,8 +2940,6 @@ bool_ place_monster(int y, int x, bool_ slp, bool_ grp) } -#ifdef MONSTER_HORDES - bool_ alloc_horde(int y, int x) { int r_idx = 0; @@ -2999,8 +2997,6 @@ bool_ alloc_horde(int y, int x) return TRUE; } -#endif /* MONSTER_HORDES */ - /* * Attempt to allocate a random monster in the dungeon. * @@ -3040,7 +3036,6 @@ bool_ alloc_monster(int dis, bool_ slp) } -#ifdef MONSTER_HORDES if (randint(5000) <= dun_level) { if (alloc_horde(y, x)) @@ -3051,14 +3046,11 @@ bool_ alloc_monster(int dis, bool_ slp) } else { -#endif /* MONSTER_HORDES */ /* Attempt to place the monster, allow groups */ if (place_monster(y, x, slp, TRUE)) return (TRUE); -#ifdef MONSTER_HORDES } -#endif /* MONSTER_HORDES */ /* Nope */ return (FALSE); diff --git a/src/wizard2.c b/src/wizard2.c index f6ce41af..2a372bcd 100644 --- a/src/wizard2.c +++ b/src/wizard2.c @@ -184,8 +184,6 @@ static void wiz_create_named_art() msg_print("Allocated."); } -#ifdef MONSTER_HORDES - /* Summon a horde of monsters */ static void do_cmd_summon_horde() { @@ -201,8 +199,6 @@ static void do_cmd_summon_horde() (void)alloc_horde(wy, wx); } -#endif /* MONSTER_HORDES */ - /* * Output a long int in binary format. @@ -1706,10 +1702,8 @@ void do_cmd_debug(void) case 'h': do_cmd_rerate(); break; -#ifdef MONSTER_HORDES case 'H': do_cmd_summon_horde(); break; -#endif /* MONSTER_HORDES */ /* Identify */ case 'i': -- cgit v1.2.3 From 3cbdeb036de1adec0d9292909f7d9561554809e1 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 22:01:54 +0200 Subject: Remove ALLOW_AUTOROLLER preprocessor define --- src/birth.c | 4 ---- src/config.h | 6 ------ 2 files changed, 10 deletions(-) diff --git a/src/birth.c b/src/birth.c index 31be2db2..1751a14c 100644 --- a/src/birth.c +++ b/src/birth.c @@ -2831,8 +2831,6 @@ static bool_ player_birth_aux_auto() char inp[80]; -#ifdef ALLOW_AUTOROLLER - /* Initialize */ if (autoroll) { @@ -2933,8 +2931,6 @@ static bool_ player_birth_aux_auto() } } -#endif /* ALLOW_AUTOROLLER */ - /* Roll */ while (TRUE) { diff --git a/src/config.h b/src/config.h index 1a7218d7..d8046ffb 100644 --- a/src/config.h +++ b/src/config.h @@ -112,12 +112,6 @@ #endif -/* - * OPTION: Allow characteres to be "auto-rolled" - */ -#define ALLOW_AUTOROLLER - - /* * OPTION: Handle signals */ -- cgit v1.2.3 From c0d4c414589ab6d43df5bbaa364564cb9c288e4a Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Jun 2012 22:14:41 +0200 Subject: Remove ZANG_* preprocessor defines --- src/main-crb.c | 13 ------------- src/main-gtk2.c | 6 ------ 2 files changed, 19 deletions(-) diff --git a/src/main-crb.c b/src/main-crb.c index d8af65de..3bcbecfc 100644 --- a/src/main-crb.c +++ b/src/main-crb.c @@ -560,7 +560,6 @@ static bool_ check_create_user_dir(void) * more work. New S one is too idiosyncratic...) * #define ANG281_RESET_VISUALS (Cth, Gum, T.o.M.E., Z) * #define SAVEFILE_SCREEN (T.o.M.E.) - * #define ZANG_AUTO_SAVE (O and Z) * #define HAS_SCORE_MENU (V and T.o.M.E.) * #define ANGBAND_CREATOR four letter code for your variant, if any. * or use the default one. @@ -4783,11 +4782,7 @@ static void menu(long mc) msg_flag = FALSE; /* Hack -- Save the game */ -#ifndef ZANG_AUTO_SAVE do_cmd_save_game(); -#else - do_cmd_save_game(FALSE); -#endif /* !ZANG_AUTO_SAVE */ break; } @@ -4815,11 +4810,7 @@ static void menu(long mc) msg_flag = FALSE; /* Save the game */ -#ifndef ZANG_AUTO_SAVE do_cmd_save_game(); -#else - do_cmd_save_game(FALSE); -#endif /* !ZANG_AUTO_SAVE */ } /* Quit */ @@ -5322,11 +5313,7 @@ static void quit_calmly(void) msg_flag = FALSE; /* Save the game */ -#ifndef ZANG_AUTO_SAVE do_cmd_save_game(); -#else - do_cmd_save_game(FALSE); -#endif /* !ZANG_AUTO_SAVE */ /* Quit */ quit(NULL); diff --git a/src/main-gtk2.c b/src/main-gtk2.c index b34c6f11..fc02f164 100644 --- a/src/main-gtk2.c +++ b/src/main-gtk2.c @@ -3070,13 +3070,7 @@ static void save_game_gtk(void) msg_flag = FALSE; /* Save the game */ -#ifdef ZANG_SAVE_GAME - /* Also for OAngband - the parameter tells if it's autosave */ - do_cmd_save_game(FALSE); -#else -/* Everything else */ do_cmd_save_game(); -#endif /* ZANG_SAVE_GAME */ } -- cgit v1.2.3 From 3b0a9bcf376ab893751991199aea5888932accc5 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 28 Jun 2012 06:28:19 +0200 Subject: Remove VERBOSE_RALLOC preprocessor define --- src/z-virt.c | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/src/z-virt.c b/src/z-virt.c index c9277166..92632080 100644 --- a/src/z-virt.c +++ b/src/z-virt.c @@ -15,16 +15,6 @@ #include "z-util.h" -/* - * Allow debugging messages to track memory usage. - */ -#ifdef VERBOSE_RALLOC -static long virt_make = 0; -static long virt_kill = 0; -static long virt_size = 0; -#endif - - /* * Optional auxiliary "rnfree" function */ @@ -38,22 +28,6 @@ vptr rnfree(vptr p, huge len) /* Easy to free zero bytes */ if (len == 0) return (NULL); -#ifdef VERBOSE_RALLOC - - /* Decrease memory count */ - virt_kill += len; - - /* Message */ - if (len > virt_size) - { - char buf[80]; - sprintf(buf, "Kill (%ld): %ld - %ld = %ld.", - len, virt_make, virt_kill, virt_make - virt_kill); - plog(buf); - } - -#endif - /* Use the "aux" function */ if (rnfree_aux) return ((*rnfree_aux)(p, len)); @@ -105,22 +79,6 @@ vptr ralloc(huge len) /* Allow allocation of "zero bytes" */ if (len == 0) return ((vptr)(NULL)); -#ifdef VERBOSE_RALLOC - - /* Count allocated memory */ - virt_make += len; - - /* Log important allocations */ - if (len > virt_size) - { - char buf[80]; - sprintf(buf, "Make (%ld): %ld - %ld = %ld.", - len, virt_make, virt_kill, virt_make - virt_kill); - plog(buf); - } - -#endif - /* Use the aux function if set */ if (ralloc_aux) mem = (*ralloc_aux)(len); -- cgit v1.2.3 From 046525fb26733df2e87928a48d2e23914174f5ac Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 28 Jun 2012 08:18:38 +0200 Subject: Remove NeXT conditional code --- src/h-system.h | 10 +++------- src/init2.c | 38 -------------------------------------- 2 files changed, 3 insertions(+), 45 deletions(-) diff --git a/src/h-system.h b/src/h-system.h index 50cc0af8..c1b17e1f 100644 --- a/src/h-system.h +++ b/src/h-system.h @@ -18,18 +18,14 @@ #include #include -#if defined(NeXT) -# include -#else -# include -#endif +#include #ifdef SET_UID # include -# if defined(Pyramid) || defined(NeXT) || defined(SUNOS) || \ +# if defined(Pyramid) || defined(SUNOS) || \ defined(NCR3K) || defined(SUNOS) || defined(ibm032) || \ defined(__osf__) || defined(ISC) || defined(SGI) || \ defined(linux) @@ -65,7 +61,7 @@ #endif -#if !defined(NeXT) && !defined(__MWERKS__) +#if !defined(__MWERKS__) # include #endif diff --git a/src/init2.c b/src/init2.c index 977e6d1a..9c1c2afa 100644 --- a/src/init2.c +++ b/src/init2.c @@ -198,44 +198,6 @@ void init_file_paths(char *path) /* Build a path name */ strcpy(tail, "xtra"); ANGBAND_DIR_XTRA = string_make(path); - -#ifdef NeXT - - /* Allow "fat binary" usage with NeXT */ - if (TRUE) - { - cptr next = NULL; - -# if defined(m68k) - next = "m68k"; -# endif - -# if defined(i386) - next = "i386"; -# endif - -# if defined(sparc) - next = "sparc"; -# endif - -# if defined(hppa) - next = "hppa"; -# endif - - /* Use special directory */ - if (next) - { - /* Forget the old path name */ - string_free(ANGBAND_DIR_DATA); - - /* Build a new path name */ - sprintf(tail, "data-%s", next); - ANGBAND_DIR_DATA = string_make(path); - } - } - -#endif /* NeXT */ - } -- cgit v1.2.3 From d5da4694480008c083896a43dc21f7c4434096eb Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 28 Jun 2012 08:26:47 +0200 Subject: Remove ANGBAND30X conditional code --- src/main-crb.c | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/src/main-crb.c b/src/main-crb.c index 3bcbecfc..ad027c72 100644 --- a/src/main-crb.c +++ b/src/main-crb.c @@ -232,9 +232,6 @@ * DEFINES = -DMACH_O_CARBON -DANGBAND30X * LIBS = -framework CoreFoundation -framework QuickTime -framework Carbon * - * -DANGBAND30X only affects main-crb.c. This is because I'm also compiling - * a couple of variants, and this arrangement makes my life easier. - * * Never, ever #define MACINTOSH. It'll wreck havoc in system interface * (mostly because of totally different pathname convention). * @@ -569,20 +566,12 @@ static bool_ check_create_user_dir(void) * that has some interesting features. */ -/* Some porting examples */ -#ifdef ANGBAND30X -# define USE_DOUBLE_TILES -# define ALLOW_BIG_SCREEN -# define HAS_SCORE_MENU -# define NEW_ZVIRT_HOOKS -#endif /* ANGBAND30X */ - -# define USE_DOUBLE_TILES -# define SAVEFILE_SCREEN -# define ANG281_RESET_VISUALS -# define ALLOW_BIG_SCREEN -# define HAS_SCORE_MENU -# define ANGBAND_CREATOR 'PrnA' +#define USE_DOUBLE_TILES +#define SAVEFILE_SCREEN +#define ANG281_RESET_VISUALS +#define ALLOW_BIG_SCREEN +#define HAS_SCORE_MENU +#define ANGBAND_CREATOR 'PrnA' /* Default creator signature */ #ifndef ANGBAND_CREATOR @@ -5800,11 +5789,7 @@ static void *lifeboat = NULL; /* * Hook to "release" memory */ -#ifdef NEW_ZVIRT_HOOKS /* [V] removed the unused 'size' argument. */ -static void *hook_rnfree(void *v) -#else static void *hook_rnfree(void *v, size_t size) -#endif /* NEW_ZVIRT_HOOKS */ { #ifdef USE_MALLOC -- cgit v1.2.3 From f3413482e842d5f2b0b492807caa60660888d02e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 28 Jun 2012 08:53:18 +0200 Subject: Remove SPOIL_* conditional code --- src/object1.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/object1.c b/src/object1.c index 86f98ae5..3b17e8c2 100644 --- a/src/object1.c +++ b/src/object1.c @@ -1028,8 +1028,6 @@ int object_power(object_type *o_ptr) */ void object_flags_known(object_type *o_ptr, u32b *f1, u32b *f2, u32b *f3, u32b *f4, u32b *f5, u32b *esp) { - bool_ spoil = FALSE; - object_kind *k_ptr = &k_info[o_ptr->k_idx]; /* Clear */ @@ -1053,23 +1051,13 @@ void object_flags_known(object_type *o_ptr, u32b *f1, u32b *f2, u32b *f3, u32b * (*f5) |= k_ptr->oflags5; (*esp) |= k_ptr->oesp; -#ifdef SPOIL_ARTIFACTS - /* Full knowledge for some artifacts */ - if (artifact_p(o_ptr) || o_ptr->art_name) spoil = TRUE; -#endif /* SPOIL_ARTIFACTS */ - -#ifdef SPOIL_EGO_ITEMS - /* Full knowledge for some ego-items */ - if (ego_item_p(o_ptr)) spoil = TRUE; -#endif /* SPOIL_EGO_ITEMS */ - /* Artifact */ if (o_ptr->name1) { artifact_type *a_ptr = &a_info[o_ptr->name1]; /* Need full knowledge or spoilers */ - if (spoil || (o_ptr->ident & IDENT_MENTAL)) + if ((o_ptr->ident & IDENT_MENTAL)) { (*f1) = a_ptr->flags1; (*f2) = a_ptr->flags2; @@ -1098,7 +1086,7 @@ void object_flags_known(object_type *o_ptr, u32b *f1, u32b *f2, u32b *f3, u32b * if (o_ptr->art_flags1 || o_ptr->art_flags2 || o_ptr->art_flags3 || o_ptr->art_flags4 || o_ptr->art_flags5 || o_ptr->art_esp) { /* Need full knowledge or spoilers */ - if (spoil || (o_ptr->ident & IDENT_MENTAL)) + if ((o_ptr->ident & IDENT_MENTAL)) { (*f1) |= o_ptr->art_flags1; (*f2) |= o_ptr->art_flags2; -- cgit v1.2.3 From dfe25f4b76e82167fd6a92fa2316164e12004f79 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 28 Jun 2012 08:58:19 +0200 Subject: Remove ANG281_RESET_VISUALS preprocessor define --- src/main-crb.c | 6 ------ src/main-gtk2.c | 7 +------ 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/main-crb.c b/src/main-crb.c index ad027c72..53761e1a 100644 --- a/src/main-crb.c +++ b/src/main-crb.c @@ -555,7 +555,6 @@ static bool_ check_create_user_dir(void) * * #define ALLOW_BIG_SCREEN (V, Ey, O, T.o.M.E., and Z. Dr's big screen needs * more work. New S one is too idiosyncratic...) - * #define ANG281_RESET_VISUALS (Cth, Gum, T.o.M.E., Z) * #define SAVEFILE_SCREEN (T.o.M.E.) * #define HAS_SCORE_MENU (V and T.o.M.E.) * #define ANGBAND_CREATOR four letter code for your variant, if any. @@ -568,7 +567,6 @@ static bool_ check_create_user_dir(void) #define USE_DOUBLE_TILES #define SAVEFILE_SCREEN -#define ANG281_RESET_VISUALS #define ALLOW_BIG_SCREEN #define HAS_SCORE_MENU #define ANGBAND_CREATOR 'PrnA' @@ -2460,11 +2458,7 @@ static errr Term_xtra_mac_react(void) term_data_resize(td); /* Reset visuals */ -#ifndef ANG281_RESET_VISUALS - reset_visuals(TRUE); -#else reset_visuals(); -#endif /* !ANG281_RESET_VISUALS */ } /* Success */ diff --git a/src/main-gtk2.c b/src/main-gtk2.c index fc02f164..d129f866 100644 --- a/src/main-gtk2.c +++ b/src/main-gtk2.c @@ -45,7 +45,7 @@ * with FREE/KILL, which takes one pointer parameter. * * [Z]-based variants (Gum and Cth, for example) usually need - * ANG293_COMPAT, ANG291_COMPAT and ANG281_RESET_VISUALS. + * ANG293_COMPAT, ANG291_COMPAT. * * [O] needs ANG293_COMPAT and ZANG_SAVE_GAME. * @@ -58,7 +58,6 @@ #ifdef TOME # define ANG293_COMPAT /* Requires V2.9.3 compatibility code */ # define ANG291_COMPAT /* Requires V2.9.1 compatibility code */ -# define ANG281_RESET_VISUALS /* The old style reset_visuals() */ # define SAVEFILE_SCREEN /* New/Open integrated into the game */ # define USE_DOUBLE_TILES /* Mogami's bigtile patch */ #endif /* TOME */ @@ -2254,11 +2253,7 @@ static void init_graphics(void) smooth_rescaling = smooth_rescaling_request; /* Reset visuals */ -#ifndef ANG281_RESET_VISUALS - reset_visuals(TRUE); -#else reset_visuals(); -#endif /* !ANG281_RESET_VISUALS */ } #endif /* USE_GRAPHICS */ -- cgit v1.2.3 From 7f2b71704a15777bef37c27ef9b3796b0725179d Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 28 Jun 2012 09:00:03 +0200 Subject: Remove UPDATE_VIEW_COMPLEX_WALL_ILLUMINATION conditional code --- src/cave.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/cave.c b/src/cave.c index ee45d167..ab1ce56e 100644 --- a/src/cave.c +++ b/src/cave.c @@ -3798,31 +3798,12 @@ void update_view(void) int yy = (y < p_ptr->py) ? (y + 1) : (y > p_ptr->py) ? (y - 1) : y; int xx = (x < p_ptr->px) ? (x + 1) : (x > p_ptr->px) ? (x - 1) : x; -#ifdef UPDATE_VIEW_COMPLEX_WALL_ILLUMINATION - - /* Check for "complex" illumination */ - if ((!(cave[yy][xx].info & (CAVE_WALL)) && - (cave[yy][xx].info & (CAVE_GLOW))) || - (!(cave[y][xx].info & (CAVE_WALL)) && - (cave[y][xx].info & (CAVE_GLOW))) || - (!(cave[yy][x].info & (CAVE_WALL)) && - (cave[yy][x].info & (CAVE_GLOW)))) - { - /* Mark as seen */ - info |= (CAVE_SEEN); - } - -#else /* UPDATE_VIEW_COMPLEX_WALL_ILLUMINATION */ - /* Check for "simple" illumination */ if (cave[yy][xx].info & (CAVE_GLOW)) { /* Mark as seen */ info |= (CAVE_SEEN); } - -#endif /* UPDATE_VIEW_COMPLEX_WALL_ILLUMINATION */ - } /* Save cave info */ -- cgit v1.2.3 From b4318e8c469eb10f596e13d128fefbe50680b9cf Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 28 Jun 2012 09:03:49 +0200 Subject: Remove ANG293_COMPAT preprocessor define --- src/main-gtk2.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/main-gtk2.c b/src/main-gtk2.c index d129f866..b0965966 100644 --- a/src/main-gtk2.c +++ b/src/main-gtk2.c @@ -44,11 +44,6 @@ * z-virt macro names. Find C_FREE/C_KILL and replace them * with FREE/KILL, which takes one pointer parameter. * - * [Z]-based variants (Gum and Cth, for example) usually need - * ANG293_COMPAT, ANG291_COMPAT. - * - * [O] needs ANG293_COMPAT and ZANG_SAVE_GAME. - * * ZAngband has its own enhanced main-gtk.c as mentioned above, and * you *should* use it :-) * @@ -56,7 +51,6 @@ #define TOME #ifdef TOME -# define ANG293_COMPAT /* Requires V2.9.3 compatibility code */ # define ANG291_COMPAT /* Requires V2.9.1 compatibility code */ # define SAVEFILE_SCREEN /* New/Open integrated into the game */ # define USE_DOUBLE_TILES /* Mogami's bigtile patch */ @@ -84,14 +78,6 @@ #endif -/* - * Include some helpful X11 code. - */ -#ifndef ANG293_COMPAT -# include "maid-x11.h" -#endif /* !ANG293_COMPAT */ - - /* * Number of pixels inserted between the menu bar and the main screen */ @@ -255,8 +241,6 @@ static bool_ use_backing_store = TRUE; /**** Vanilla compatibility functions ****/ -#ifdef ANG293_COMPAT - /* * Look up some environment variables to find font name for each window. */ @@ -304,8 +288,6 @@ static void cleanup_angband(void) */ #define can_save TRUE -#endif /* ANG293_COMPAT */ - #ifdef ANG291_COMPAT -- cgit v1.2.3 From 93fcd75161c4de0cb52076f0273944a158fe4345 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 28 Jun 2012 09:04:57 +0200 Subject: Remove ANG291_COMPAT preprocessor define --- src/main-gtk2.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/main-gtk2.c b/src/main-gtk2.c index b0965966..8567a7a3 100644 --- a/src/main-gtk2.c +++ b/src/main-gtk2.c @@ -51,7 +51,6 @@ #define TOME #ifdef TOME -# define ANG291_COMPAT /* Requires V2.9.1 compatibility code */ # define SAVEFILE_SCREEN /* New/Open integrated into the game */ # define USE_DOUBLE_TILES /* Mogami's bigtile patch */ #endif /* TOME */ @@ -289,8 +288,6 @@ static void cleanup_angband(void) #define can_save TRUE -#ifdef ANG291_COMPAT - /* * The standard game uses this to implement lighting effects * for 16x16 tiles in cave.c... @@ -300,8 +297,6 @@ static void cleanup_angband(void) */ static bool_ use_transparency = TRUE; -#endif /* ANG291_COMPAT */ - -- cgit v1.2.3 From d5139a07fd76c3cac1637ca887d670c07164a784 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 28 Jun 2012 09:14:28 +0200 Subject: Remove SAVEFILE_SCREEN preprocessor define --- src/main-crb.c | 279 ++------------------------------------------------------ src/main-gtk2.c | 192 -------------------------------------- 2 files changed, 8 insertions(+), 463 deletions(-) diff --git a/src/main-crb.c b/src/main-crb.c index 53761e1a..6defe9f2 100644 --- a/src/main-crb.c +++ b/src/main-crb.c @@ -139,8 +139,6 @@ * * MBAR 128 = array of MENU id's (128, 129, 130, 131, 132, 133, 134) * MENU 128 = apple (about, -, ...) - * MENU 129 = File (new, open, close, save, -, score, quit) - * (If SAVEFILE_SCREEN is defined) * MENU 129 = File (close, save, -, score, quit) * MENU 130 = Edit (undo, -, cut, copy, paste, clear) * MENU 131 = Font (bold, wide, -) @@ -555,7 +553,6 @@ static bool_ check_create_user_dir(void) * * #define ALLOW_BIG_SCREEN (V, Ey, O, T.o.M.E., and Z. Dr's big screen needs * more work. New S one is too idiosyncratic...) - * #define SAVEFILE_SCREEN (T.o.M.E.) * #define HAS_SCORE_MENU (V and T.o.M.E.) * #define ANGBAND_CREATOR four letter code for your variant, if any. * or use the default one. @@ -566,7 +563,6 @@ static bool_ check_create_user_dir(void) */ #define USE_DOUBLE_TILES -#define SAVEFILE_SCREEN #define ALLOW_BIG_SCREEN #define HAS_SCORE_MENU #define ANGBAND_CREATOR 'PrnA' @@ -3667,195 +3663,6 @@ static void save_pref_file(void) } - - -#ifndef SAVEFILE_SCREEN - -/* - * Prepare savefile dialogue and set the variable - * savefile accordingly. Returns true if it succeeds, false (or - * aborts) otherwise. If all is false, only allow files whose type - * is 'SAVE'. - * Originally written by Peter Ammon - */ -static bool_ select_savefile(bool_ all) -{ - OSErr err; - FSSpec theFolderSpec; - FSSpec savedGameSpec; - NavDialogOptions dialogOptions; - NavReplyRecord reply; - /* Used only when 'all' is true */ - NavTypeList types = {ANGBAND_CREATOR, 1, 1, {'SAVE'}}; - NavTypeListHandle myTypeList; - AEDesc defaultLocation; - -#ifdef MACH_O_CARBON - - /* Find the save folder */ - err = path_to_spec(ANGBAND_DIR_SAVE, &theFolderSpec); - -#else - - /* Find :lib:save: folder */ - err = FSMakeFSSpec( - app_vol, - app_dir, - "\p:lib:save:", - &theFolderSpec); - -#endif - - /* Oops */ - if (err != noErr) quit("Unable to find the folder :lib:save:"); - - /* Get default Navigator dialog options */ - err = NavGetDefaultDialogOptions(&dialogOptions); - - /* Clear preview option */ - dialogOptions.dialogOptionFlags &= ~kNavAllowPreviews; - - /* Disable multiple file selection */ - dialogOptions.dialogOptionFlags &= ~kNavAllowMultipleFiles; - - /* Make descriptor for default location */ - err = AECreateDesc( - typeFSS, - &theFolderSpec, - sizeof(FSSpec), - &defaultLocation); - - /* Oops */ - if (err != noErr) quit("Unable to allocate descriptor"); - - /* We are indifferent to signature and file types */ - if (all) - { - myTypeList = (NavTypeListHandle)nil; - } - - /* Set up type handle */ - else - { - err = PtrToHand(&types, (Handle *) & myTypeList, sizeof(NavTypeList)); - - /* Oops */ - if (err != noErr) quit("Error in PtrToHand. Try enlarging heap"); - - } - - /* Call NavGetFile() with the types list */ - err = NavChooseFile( - &defaultLocation, - &reply, - &dialogOptions, - nil, - nil, - nil, - myTypeList, - nil); - - /* Free type list */ - DisposeHandle((Handle)myTypeList); - - /* Invalid response -- allow the user to cancel */ - if (!reply.validRecord) return (FALSE); - - /* Retrieve FSSpec from the reply */ - if (err == noErr) - { - AEKeyword theKeyword; - DescType actualType; - Size actualSize; - - /* Get a pointer to selected file */ - (void)AEGetNthPtr( - &reply.selection, - 1, - typeFSS, - &theKeyword, - &actualType, - &savedGameSpec, - sizeof(FSSpec), - &actualSize); - - /* Dispose NavReplyRecord, resources and descriptors */ - (void)NavDisposeReply(&reply); - } - - /* Dispose location info */ - AEDisposeDesc(&defaultLocation); - -#ifdef MACH_O_CARBON - - /* Convert FSSpec to pathname and store it in variable savefile */ - (void)spec_to_path(&savedGameSpec, savefile, sizeof(savefile)); - -#else - - /* Convert FSSpec to pathname and store it in variable savefile */ - refnum_to_name( - savefile, - savedGameSpec.parID, - savedGameSpec.vRefNum, - (char *)savedGameSpec.name); - -#endif - - /* Success */ - return (TRUE); -} - - -/* - * Handle menu: "File" + "New" - */ -static void do_menu_file_new(void) -{ - /* Hack */ - HiliteMenu(0); - - /* Game is in progress */ - game_in_progress = 1; - - /* Flush input */ - Term_flush(); - - /* Play a game */ - play_game(TRUE); - - /* Hack -- quit */ - quit(NULL); -} - - -/* - * Handle menu: "File" + "Open" / "Import" - */ -static void do_menu_file_open(bool_ all) -{ - /* Let the player to choose savefile */ - if (!select_savefile(all)) return; - - /* Hack */ - HiliteMenu(0); - - /* Game is in progress */ - game_in_progress = 1; - - /* Flush input */ - flush(); - - /* Play a game */ - play_game(FALSE); - - /* Hack -- quit */ - quit(NULL); -} - -#endif /* !SAVEFILE_SCREEN */ - - /* * Handle the "open_when_ready" flag */ @@ -3876,13 +3683,9 @@ static void handle_open_when_ready(void) /* Flush input */ flush(); -#ifdef SAVEFILE_SCREEN - /* User double-clicked savefile; no savefile screen */ no_begin_screen = TRUE; -#endif /* SAVEFILE_SCREEN */ - /* Play a game */ play_game(FALSE); @@ -3900,8 +3703,6 @@ static void handle_open_when_ready(void) * The standard menus are: * * Apple (128) = { About, -, ... } - * File (129) = { New,Open,Import,Close,Save,-,Score,Quit } - * (If SAVEFILE_SCREEN is defined, this becomes) * File (129) = { Close,Save,-,Score,Quit } * Edit (130) = { Cut, Copy, Paste, Clear } (?) * Font (131) = { Bold, Extend, -, Monaco, ..., -, ... } @@ -3918,28 +3719,14 @@ static void handle_open_when_ready(void) /* File menu */ #define MENU_FILE 129 -#ifndef SAVEFILE_SCREEN -# define ITEM_NEW 1 -# define ITEM_OPEN 2 -# define ITEM_IMPORT 3 -# define ITEM_CLOSE 4 -# define ITEM_SAVE 5 -# ifdef HAS_SCORE_MENU -# define ITEM_SCORE 7 -# define ITEM_QUIT 8 -# else -# define ITEM_QUIT 7 -# endif /* HAS_SCORE_MENU */ -#else /* !SAVEFILE_SCREEN - in-game savefile menu */ -# define ITEM_CLOSE 1 -# define ITEM_SAVE 2 -# ifdef HAS_SCORE_MENU -# define ITEM_SCORE 4 -# define ITEM_QUIT 5 -# else -# define ITEM_QUIT 4 -# endif /* HAS_SCORE_MENU */ -#endif /* !SAVEFILE_SCREEN */ +#define ITEM_CLOSE 1 +#define ITEM_SAVE 2 +#ifdef HAS_SCORE_MENU +#define ITEM_SCORE 4 +#define ITEM_QUIT 5 +#else +#define ITEM_QUIT 4 +#endif /* HAS_SCORE_MENU */ /* Edit menu */ #define MENU_EDIT 130 @@ -4308,18 +4095,6 @@ static void setup_menus(void) CheckMenuItem(m, i, FALSE); } -#ifndef SAVEFILE_SCREEN - - /* Enable "new"/"open..."/"import..." */ - if (initialized && !game_in_progress) - { - EnableMenuItem(m, ITEM_NEW); - EnableMenuItem(m, ITEM_OPEN); - EnableMenuItem(m, ITEM_IMPORT); - } - -#endif /* !SAVEFILE_SCREEN */ - /* Enable "close" */ if (initialized) { @@ -4712,30 +4487,6 @@ static void menu(long mc) { switch (selection) { -#ifndef SAVEFILE_SCREEN - - /* New */ - case ITEM_NEW: - { - do_menu_file_new(); - break; - } - - /* Open... */ - case ITEM_OPEN: - { - do_menu_file_open(FALSE); - break; - } - - /* Import... */ - case ITEM_IMPORT: - { - do_menu_file_open(TRUE); - break; - } - -#endif /* !SAVEFILE_SCREEN */ /* Close */ case ITEM_CLOSE: @@ -6244,19 +5995,6 @@ int main(void) /* Handle "open_when_ready" */ handle_open_when_ready(); -#ifndef SAVEFILE_SCREEN - - /* Prompt the user - You may have to change this for some variants */ - prt("[Choose 'New' or 'Open' from the 'File' menu]", 23, 15); - - /* Flush the prompt */ - Term_fresh(); - - /* Hack -- Process Events Forever */ - while (TRUE) CheckEvents(TRUE); - -#else - /* Game is in progress */ game_in_progress = 1; @@ -6274,7 +6012,6 @@ int main(void) /* Since it's a int function */ return (0); -#endif /* !SAVEFILE_SCREEN */ } #endif /* MACINTOSH || MACH_O_CARBON */ diff --git a/src/main-gtk2.c b/src/main-gtk2.c index 8567a7a3..678d79eb 100644 --- a/src/main-gtk2.c +++ b/src/main-gtk2.c @@ -51,7 +51,6 @@ #define TOME #ifdef TOME -# define SAVEFILE_SCREEN /* New/Open integrated into the game */ # define USE_DOUBLE_TILES /* Mogami's bigtile patch */ #endif /* TOME */ @@ -270,18 +269,6 @@ static cptr get_default_font(int term) } -# ifndef SAVEFILE_SCREEN - -/* - * In [V]2.9.3, this frees all dynamically allocated memory - */ -static void cleanup_angband(void) -{ - /* XXX XXX XXX */ -} - -# endif /* !SAVEFILE_SCREEN */ - /* * New global flag to indicate if it's safe to save now */ @@ -3149,41 +3136,6 @@ static void destroy_sub_event_handler( } -#ifndef SAVEFILE_SCREEN - -/* - * Process File-New menu command - */ -static void new_event_handler( - gpointer user_data, - guint user_action, - GtkWidget *was_clicked) -{ - if (game_in_progress) - { - plog("You can't start a new game while you're still playing!"); - return; - } - - /* The game is in progress */ - game_in_progress = TRUE; - - /* Flush input */ - Term_flush(); - - /* Play game */ - play_game(TRUE); - - /* Houseclearing */ - cleanup_angband(); - - /* Done */ - quit(NULL); -} - -#endif /* !SAVEFILE_SCREEN */ - - /* * Load fond specified by an XLFD fontname and * set up related term_data members @@ -3416,92 +3368,6 @@ static void change_trans_mode_event_handler( #endif /* USE_GRAPHICS */ -#ifndef SAVEFILE_SCREEN - -/* - * Caution: Modal or not, callbacks are called by gtk_main(), - * so this is the right place to start a game. - */ -static void file_ok_callback( - GtkWidget *widget, - GtkWidget *file_selector) -{ - strcpy(savefile, - gtk_file_selection_get_filename(GTK_FILE_SELECTION(file_selector))); - - gtk_widget_destroy(file_selector); - - /* game is in progress */ - game_in_progress = TRUE; - - /* Flush input */ - Term_flush(); - - /* Play game */ - play_game(FALSE); - - /* Free memory allocated by game */ - cleanup_angband(); - - /* Done */ - quit(NULL); -} - - -/* - * Process File-Open menu command - */ -static void open_event_handler( - gpointer user_data, - guint user_action, - GtkWidget *was_clicked) -{ - GtkWidget *file_selector; - char buf[1024]; - - - if (game_in_progress) - { - plog("You can't open a new game while you're still playing!"); - return; - } - - /* Prepare the savefile path */ - path_build(buf, 1024, ANGBAND_DIR_SAVE, "*"); - - file_selector = gtk_file_selection_new("Select a savefile"); - gtk_file_selection_set_filename( - GTK_FILE_SELECTION(file_selector), - buf); - gtk_signal_connect( - GTK_OBJECT(GTK_FILE_SELECTION(file_selector)->ok_button), - "clicked", - file_ok_callback, - (gpointer)file_selector); - - /* - * Ensure that the dialog box is destroyed when the user - * clicks a button. - */ - gtk_signal_connect_object( - GTK_OBJECT(GTK_FILE_SELECTION(file_selector)->ok_button), - "clicked", - GTK_SIGNAL_FUNC(gtk_widget_destroy), - (gpointer)file_selector); - - gtk_signal_connect_object( - GTK_OBJECT(GTK_FILE_SELECTION(file_selector)->cancel_button), - "clicked", - GTK_SIGNAL_FUNC(gtk_widget_destroy), - (gpointer)file_selector); - - gtk_window_set_modal(GTK_WINDOW(file_selector), TRUE); - gtk_widget_show(GTK_WIDGET(file_selector)); -} - -#endif /* !SAVEFILE_SCREEN */ - - /* * React to "delete" signal sent to Window widgets */ @@ -3935,14 +3801,6 @@ static GtkItemFactoryEntry main_menu_items[] = { "/File", NULL, NULL, 0, "", NULL }, -#ifndef SAVEFILE_SCREEN - { "/File/New", "N", - new_event_handler, 0, NULL, NULL }, - { "/File/Open", "O", - open_event_handler, 0, NULL, NULL }, - { "/File/sep1", NULL, - NULL, 0, "", NULL }, -#endif /* !SAVEFILE_SCREEN */ { "/File/Save", "S", save_event_handler, 0, NULL, NULL }, { "/File/Quit", "Q", @@ -4222,18 +4080,8 @@ static void file_menu_update_handler( GtkWidget *widget, gpointer user_data) { -#ifndef SAVEFILE_SCREEN - bool_ game_start_ok; -#endif /* !SAVEFILE_SCREEN */ bool_ save_ok, quit_ok; -#ifndef SAVEFILE_SCREEN - - /* Can we start a game now? */ - game_start_ok = !game_in_progress; - -#endif /* !SAVEFILE_SCREEN */ - /* Cave we save/quit now? */ if (!character_generated || !game_in_progress) { @@ -4247,10 +4095,6 @@ static void file_menu_update_handler( } /* Enable / disable menu items according to those conditions */ -#ifndef SAVEFILE_SCREEN - enable_menu_item("/File/New", game_start_ok); - enable_menu_item("/File/Open", game_start_ok); -#endif /* !SAVEFILE_SCREEN */ enable_menu_item("/File/Save", save_ok); enable_menu_item("/File/Quit", quit_ok); } @@ -4776,48 +4620,12 @@ errr init_gtk2(int argc, char **argv) /* Activate the "Angband" window screen */ Term_activate(&data[0].t); -#ifndef SAVEFILE_SCREEN - - /* Set the system suffix */ - ANGBAND_SYS = "gtk"; - - /* Catch nasty signals */ - signals_init(); - - /* Initialize */ - init_angband(); - - /* Hack - because this port has New/Open menus XXX */ - savefile[0] = '\0'; - - /* Prompt the user */ - prt("[Choose 'New' or 'Open' from the 'File' menu]", 23, 17); - Term_fresh(); - - /* Activate more hook */ - plog_aux = hook_plog; - - - /* Processing loop */ - gtk_main(); - - - /* Free allocated memory */ - cleanup_angband(); - - /* Stop now */ - quit(NULL); - -#else /* !SAVEFILE_SCREEN */ - /* Activate more hook */ plog_aux = hook_plog; /* It's too early to set this, but cannot do so elsewhere XXX XXX */ game_in_progress = TRUE; -#endif /* !SAVEFILE_SCREEN */ - /* Success */ return (0); } -- cgit v1.2.3 From d7a4953cd5fa431336ba5c863f58efdfe58ed510 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 28 Jun 2012 09:31:26 +0200 Subject: Remove OBSOLETE_SIZING_METHOD conditional code --- src/main-x11.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main-x11.c b/src/main-x11.c index e32e2617..9d7370b4 100644 --- a/src/main-x11.c +++ b/src/main-x11.c @@ -1317,13 +1317,6 @@ static errr Infofnt_prepare(XFontStruct *info) ifnt->twid = ifnt->wid; -#ifdef OBSOLETE_SIZING_METHOD - /* Extract default sizing info */ - ifnt->asc = cs->ascent; - ifnt->hgt = (cs->ascent + cs->descent); - ifnt->wid = cs->width; -#endif - /* Success */ return (0); } -- cgit v1.2.3 From 9d65e7c4ab6856dea66eb20e1a47474652f1c71a Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 28 Jun 2012 09:39:06 +0200 Subject: Remove IGNORE_UNUSED_FUNCTIONS conditional code --- src/main-x11.c | 322 --------------------------------------------------------- 1 file changed, 322 deletions(-) diff --git a/src/main-x11.c b/src/main-x11.c index 9d7370b4..9a106bd6 100644 --- a/src/main-x11.c +++ b/src/main-x11.c @@ -122,11 +122,6 @@ */ #include "maid-x11.c" -/* - * Hack -- avoid some compiler warnings - */ -#define IGNORE_UNUSED_FUNCTIONS - /* * Notes on Colors: @@ -406,15 +401,9 @@ Infowin_init_dad(D,X,Y,W,H,B,Metadpy->fg,Metadpy->bg) #define Infoclr_init_ppo(F,B,O,M) \ Infoclr_init_data(F,B,O,M) -#define Infoclr_init_cco(F,B,O,M) \ -Infoclr_init_ppo(Infoclr_Pixell(F),Infoclr_Pixell(B),O,M) - #define Infoclr_init_ppn(F,B,O,M) \ Infoclr_init_ppo(F,B,Infoclr_Opcode(O),M) -#define Infoclr_init_ccn(F,B,O,M) \ -Infoclr_init_cco(F,B,Infoclr_Opcode(O),M) - /* Set the current infofnt */ #define Infofnt_set(I) \ @@ -615,36 +604,6 @@ static errr Metadpy_init_2(Display *dpy, cptr name) } -#ifndef IGNORE_UNUSED_FUNCTIONS - -/* - * Nuke the current metadpy - */ -static errr Metadpy_nuke(void) -{ - metadpy *m = Metadpy; - - - /* If required, Free the Display */ - if (m->nuke) - { - /* Close the Display */ - XCloseDisplay(m->dpy); - - /* Forget the Display */ - m->dpy = (Display*)(NULL); - - /* Do not nuke it again */ - m->nuke = 0; - } - - /* Return Success */ - return (0); -} - -#endif /* IGNORE_UNUSED_FUNCTIONS */ - - /* * General Flush/ Sync/ Discard routine */ @@ -690,45 +649,6 @@ static errr Infowin_set_name(cptr name) } -#ifndef IGNORE_UNUSED_FUNCTIONS - -/* - * Set the icon name of Infowin - */ -static errr Infowin_set_icon_name(cptr name) -{ - Status st; - XTextProperty tp; - char buf[128]; - char *bp = buf; - strcpy(buf, name); - st = XStringListToTextProperty(&bp, 1, &tp); - if (st) XSetWMIconName(Metadpy->dpy, Infowin->win, &tp); - return (0); -} - - -/* - * Nuke Infowin - */ -static errr Infowin_nuke(void) -{ - infowin *iwin = Infowin; - - /* Nuke if requested */ - if (iwin->nuke) - { - /* Destory the old window */ - XDestroyWindow(Metadpy->dpy, iwin->win); - } - - /* Success */ - return (0); -} - -#endif /* IGNORE_UNUSED_FUNCTIONS */ - - /* * Prepare a new 'infowin'. */ @@ -769,26 +689,6 @@ static errr Infowin_prepare(Window xid) } -#ifndef IGNORE_UNUSED_FUNCTIONS - -/* - * Initialize a new 'infowin'. - */ -static errr Infowin_init_real(Window xid) -{ - /* Wipe it clean */ - (void)WIPE(Infowin, infowin); - - /* Start out non-nukable */ - Infowin->nuke = 0; - - /* Attempt to Prepare ourself */ - return (Infowin_prepare(xid)); -} - -#endif /* IGNORE_UNUSED_FUNCTIONS */ - - /* * Init an infowin by giving some data. * @@ -880,23 +780,6 @@ static errr Infowin_map(void) } -#ifndef IGNORE_UNUSED_FUNCTIONS - -/* - * Request that Infowin be unmapped - */ -static errr Infowin_unmap(void) -{ - /* Execute the Un-Mapping */ - XUnmapWindow(Metadpy->dpy, Infowin->win); - - /* Success */ - return (0); -} - -#endif /* IGNORE_UNUSED_FUNCTIONS */ - - /* * Request that Infowin be raised */ @@ -910,23 +793,6 @@ static errr Infowin_raise(void) } -#ifndef IGNORE_UNUSED_FUNCTIONS - -/* - * Request that Infowin be lowered - */ -static errr Infowin_lower(void) -{ - /* Lower towards invisibility */ - XLowerWindow(Metadpy->dpy, Infowin->win); - - /* Success */ - return (0); -} - -#endif /* IGNORE_UNUSED_FUNCTIONS */ - - /* * Request that Infowin be moved to a new location */ @@ -940,23 +806,6 @@ static errr Infowin_impell(int x, int y) } -#ifndef IGNORE_UNUSED_FUNCTIONS - -/* - * Move and Resize an infowin - */ -static errr Infowin_locate(int x, int y, int w, int h) -{ - /* Execute the request */ - XMoveResizeWindow(Metadpy->dpy, Infowin->win, x, y, w, h); - - /* Success */ - return (0); -} - -#endif /* IGNORE_UNUSED_FUNCTIONS */ - - /* * Visually clear Infowin */ @@ -970,24 +819,6 @@ static errr Infowin_wipe(void) } -#ifndef IGNORE_UNUSED_FUNCTIONS - -/* - * Visually Paint Infowin with the current color - */ -static errr Infowin_fill(void) -{ - /* Execute the request */ - XFillRectangle(Metadpy->dpy, Infowin->win, Infoclr->gc, - 0, 0, Infowin->w, Infowin->h); - - /* Success */ - return (0); -} - -#endif /* IGNORE_UNUSED_FUNCTIONS */ - - /* * A NULL terminated pair list of legal "operation names" * @@ -1050,109 +881,6 @@ static int Infoclr_Opcode(cptr str) } -#ifndef IGNORE_UNUSED_FUNCTIONS - -/* - * Request a Pixell by name. Note: uses 'Metadpy'. - * - * Inputs: - * name: The name of the color to try to load (see below) - * - * Output: - * The Pixell value that metched the given name - * 'Metadpy->fg' if the name was unparseable - * - * Valid forms for 'name': - * 'fg', 'bg', 'zg', '' and '#' - */ -static Pixell Infoclr_Pixell(cptr name) -{ - XColor scrn; - - /* Attempt to Parse the name */ - if (name && name[0]) - { - /* The 'bg' color is available */ - if (streq(name, "bg")) return (Metadpy->bg); - - /* The 'fg' color is available */ - if (streq(name, "fg")) return (Metadpy->fg); - - /* The 'zg' color is available */ - if (streq(name, "zg")) return (Metadpy->zg); - - /* The 'white' color is available */ - if (streq(name, "white")) return (Metadpy->white); - - /* The 'black' color is available */ - if (streq(name, "black")) return (Metadpy->black); - - /* Attempt to parse 'name' into 'scrn' */ - if (!(XParseColor(Metadpy->dpy, Metadpy->cmap, name, &scrn))) - { - plog_fmt("Warning: Couldn't parse color '%s'\n", name); - } - - /* Attempt to Allocate the Parsed color */ - if (!(XAllocColor(Metadpy->dpy, Metadpy->cmap, &scrn))) - { - plog_fmt("Warning: Couldn't allocate color '%s'\n", name); - } - - /* The Pixel was Allocated correctly */ - else return (scrn.pixel); - } - - /* Warn about the Default being Used */ - plog_fmt("Warning: Using 'fg' for unknown color '%s'\n", name); - - /* Default to the 'Foreground' color */ - return (Metadpy->fg); -} - - -/* - * Initialize a new 'infoclr' with a real GC. - */ -static errr Infoclr_init_1(GC gc) -{ - infoclr *iclr = Infoclr; - - /* Wipe the iclr clean */ - (void)WIPE(iclr, infoclr); - - /* Assign the GC */ - iclr->gc = gc; - - /* Success */ - return (0); -} - - -/* - * Nuke an old 'infoclr'. - */ -static errr Infoclr_nuke(void) -{ - infoclr *iclr = Infoclr; - - /* Deal with 'GC' */ - if (iclr->nuke) - { - /* Free the GC */ - XFreeGC(Metadpy->dpy, iclr->gc); - } - - /* Forget the current */ - Infoclr = (infoclr*)(NULL); - - /* Success */ - return (0); -} - -#endif /* IGNORE_UNUSED_FUNCTIONS */ - - /* * Initialize an infoclr with some data * @@ -1262,36 +990,6 @@ static errr Infoclr_change_fg(Pixell fg) -#ifndef IGNORE_UNUSED_FUNCTIONS - -/* - * Nuke an old 'infofnt'. - */ -static errr Infofnt_nuke(void) -{ - infofnt *ifnt = Infofnt; - - /* Deal with 'name' */ - if (ifnt->name) - { - /* Free the name */ - string_free(ifnt->name); - } - - /* Nuke info if needed */ - if (ifnt->nuke) - { - /* Free the font */ - XFreeFont(Metadpy->dpy, ifnt->info); - } - - /* Success */ - return (0); -} - -#endif /* IGNORE_UNUSED_FUNCTIONS */ - - /* * Prepare a new 'infofnt' */ @@ -1322,26 +1020,6 @@ static errr Infofnt_prepare(XFontStruct *info) } -#ifndef IGNORE_UNUSED_FUNCTIONS - -/* - * Initialize a new 'infofnt'. - */ -static errr Infofnt_init_real(XFontStruct *info) -{ - /* Wipe the thing */ - (void)WIPE(Infofnt, infofnt); - - /* No nuking */ - Infofnt->nuke = 0; - - /* Attempt to prepare it */ - return (Infofnt_prepare(info)); -} - -#endif /* IGNORE_UNUSED_FUNCTIONS */ - - /* * Init an infofnt by its Name * -- cgit v1.2.3 From f9ff5f7b2be06310695c08d9ee16650b5d54f414 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 28 Jun 2012 11:14:39 +0200 Subject: Remove TOME preprocessor define --- src/main-gtk2.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/main-gtk2.c b/src/main-gtk2.c index 678d79eb..0a14787c 100644 --- a/src/main-gtk2.c +++ b/src/main-gtk2.c @@ -48,11 +48,8 @@ * you *should* use it :-) * */ -#define TOME -#ifdef TOME -# define USE_DOUBLE_TILES /* Mogami's bigtile patch */ -#endif /* TOME */ +#define USE_DOUBLE_TILES /* Mogami's bigtile patch */ #ifdef USE_GTK2 @@ -3314,10 +3311,8 @@ static void change_wide_tile_mode_event_handler( /* Toggle "use_bigtile" */ use_bigtile = !use_bigtile; -#ifdef TOME /* T.o.M.E. requires this as well */ arg_bigtile = use_bigtile; -#endif /* TOME */ /* Double the width of tiles (only for the main window) */ if (use_bigtile) @@ -4545,10 +4540,7 @@ errr init_gtk2(int argc, char **argv) if (streq(argv[i], "-w")) { use_bigtile = TRUE; -# ifdef TOME - /* T.o.M.E. uses older version of the patch */ arg_bigtile = TRUE; -# endif /* TOME */ continue; } -- cgit v1.2.3 From d37a1238a94362ebfdebfdc3daf662cd3ba714af Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 28 Jun 2012 11:16:30 +0200 Subject: Remove #if 0'd code --- src/carbon/Carbon.r | 10 ------ src/main-crb.c | 55 ------------------------------- src/main-gtk2.c | 95 ----------------------------------------------------- src/main-win.c | 37 --------------------- src/main-xaw.c | 8 ----- 5 files changed, 205 deletions(-) diff --git a/src/carbon/Carbon.r b/src/carbon/Carbon.r index e3194dd2..9c1d412d 100644 --- a/src/carbon/Carbon.r +++ b/src/carbon/Carbon.r @@ -258,16 +258,6 @@ resource 'MENU' (129, preload) /* its contents */ { -#if 0 - /* item #1 */ - "New", noicon, "N", nomark, plain; - - /* item #2 */ - "Open", noicon, "O", nomark, plain; - - /* item #3 */ - "Import", noicon, "I", nomark, plain; -#endif /* item #1 (was #4) */ "Close", noicon, "W", nomark, plain; diff --git a/src/main-crb.c b/src/main-crb.c index 6defe9f2..c6a3a412 100644 --- a/src/main-crb.c +++ b/src/main-crb.c @@ -3119,13 +3119,6 @@ static void term_data_link(int i) td->t->text_hook = Term_text_mac; td->t->pict_hook = Term_pict_mac; -#if 0 - - /* Doesn't make big difference? */ - td->t->never_bored = TRUE; - -#endif - /* Link the local structure */ td->t->data = (void *)(td); @@ -3445,25 +3438,6 @@ static void cf_load_prefs() return; } -#if 0 - - /* Check version */ - if ((pref_major != PREF_VER_MAJOR) || - (pref_minor != PREF_VER_MINOR) || - (pref_patch != PREF_VER_PATCH) || - (pref_extra != PREF_VER_EXTRA)) - { - /* Message */ - mac_warning( - format("Ignoring %d.%d.%d.%d preferences.", - pref_major, pref_minor, pref_patch, pref_extra)); - - /* Ignore */ - return; - } - -#endif - /* Gfx settings */ { short pref_tmp; @@ -5161,19 +5135,6 @@ static bool_ CheckEvents(bool_ wait) switch (event.what) { -#if 0 - - case activateEvt: - { - w = (WindowPtr)event.message; - - activate(w); - - break; - } - -#endif - case updateEvt: { /* Extract the window */ @@ -5494,13 +5455,6 @@ static bool_ CheckEvents(bool_ wait) /* Handle "quit_when_ready" */ if (quit_when_ready) { -#if 0 /* Doesn't work with Aqua well */ - /* Forget */ - quit_when_ready = FALSE; - - /* Do the menu key */ - menu(MenuKey('q')); -#endif /* Turn off the menus */ HiliteMenu(0); } @@ -5766,19 +5720,10 @@ static void init_stuff(void) /* Display location */ dialogOptions.location = topleft; -#if 0 - - /* Load the message for the missing folder from the resource fork */ - /* GetIndString(dialogOptions.message, 128, 1); */ - -#else - /* Set the message for the missing folder XXX XXX */ strcpy(dialogOptions.message + 1, "Please select the \"lib\" folder"); dialogOptions.message[0] = strlen(dialogOptions.message + 1); -#endif - /* Wait for the user to choose a folder */ err = NavChooseFolder( nil, &theReply, &dialogOptions, nil, nil, nil); diff --git a/src/main-gtk2.c b/src/main-gtk2.c index 0a14787c..102a8b7b 100644 --- a/src/main-gtk2.c +++ b/src/main-gtk2.c @@ -169,36 +169,6 @@ if ((td)->backing_store) gdk_draw_pixmap( \ (hgt) * (td)->font_hgt) -#if 0 - -/* Compile time option version */ - -# ifdef USE_BACKING_STORE - -# define TERM_DATA_DRAWABLE(td) (td)->backing_store - -# define TERM_DATA_REFRESH(td, x, y, wid, hgt) \ -gdk_draw_pixmap( \ -(td)->drawing_area->window, \ -(td)->gc, \ -(td)->backing_store, \ -(x) * (td)->font_wid, \ -(y) * (td)->font_hgt, \ -(x) * (td)->font_wid, \ -(y) * (td)->font_hgt, \ -(wid) * (td)->font_wid, \ -(hgt) * (td)->font_hgt) - -# else /* USE_BACKING_STORE */ - -# define TERM_DATA_DRAWABLE(td) (td)->drawing_area->window -# define TERM_DATA_REFRESH(td, x, y, wid, hgt) - -# endif /* USE_BACKING_STORE */ - -#endif /* 0 */ - - /* * An array of "term_data" structures, one for each "sub-window" */ @@ -498,41 +468,6 @@ static void gdk_rgb_image_destroy( } -#if 0 - -/* - * Unref a GdkRGBImage - */ -static void gdk_rgb_image_unref( - GdkRGBImage *im) -{ - /* Paranoia */ - g_return_if_fail(im != NULL); - - /* Decrease reference count by 1 */ - im->ref_count--; - - /* Free if nobody's using it */ - if (im->ref_count <= 0) gdk_rgb_image_destroy(im); -} - - -/* - * Reference a GdkRGBImage - */ -static void gdk_rgb_image_ref( - GdkRGBImage *im) -{ - /* Paranoia */ - g_return_if_fail(im != NULL); - - /* Increase reference count by 1 */ - im->ref_count++; -} - -#endif /* 0 */ - - /* * Write RGB pixel of the format 0xRRGGBB to (x, y) in GdkRGBImage */ @@ -1107,36 +1042,6 @@ static void copy_pixels( } -#if 0 - -/* 32-bit version: it might be useful in the future */ -static void copy_pixels( - int wid, - int y, - int offset, - int *xoffsets, - GdkRGBImage *old_image, - GdkRGBImage *new_image) -{ - int i; - - /* Get source and destination */ - byte *src = &old_image->image[offset * old_image->width * 4]; - byte *dst = &new_image->image[y * new_image->width * 4]; - - /* Copy to the image */ - for (i = 0; i < wid; i++) - { - *dst++ = src[4 * xoffsets[i]]; - *dst++ = src[4 * xoffsets[i] + 1]; - *dst++ = src[4 * xoffsets[i] + 2]; - *dst++ = src[4 * xoffsets[i] + 3]; - } -} - -#endif - - /* * Resize ix * iy pixel tiles in old to ox * oy pixels * and return a new GdkRGBImage containing the resized tiles diff --git a/src/main-win.c b/src/main-win.c index a618de96..2d740034 100644 --- a/src/main-win.c +++ b/src/main-win.c @@ -1444,28 +1444,6 @@ static void term_data_redraw(term_data *td) /*** Function hooks needed by "Term" ***/ -#if 0 - -/* - * Initialize a new Term - */ -static void Term_init_win(term *t) -{ - /* XXX Unused */ -} - - -/* - * Nuke an old Term - */ -static void Term_nuke_win(term *t) -{ - /* XXX Unused */ -} - -#endif - - /* * Interact with the User */ @@ -2247,12 +2225,6 @@ static void term_data_link(term_data *td) t->attr_blank = TERM_WHITE; t->char_blank = ' '; -#if 0 - /* Prepare the init/nuke hooks */ - t->init_hook = Term_init_win; - t->nuke_hook = Term_nuke_win; -#endif - /* Prepare the template hooks */ t->user_hook = Term_user_win; t->xtra_hook = Term_xtra_win; @@ -3726,15 +3698,6 @@ WPARAM wParam, LPARAM lParam) return 0; } -#if 0 - case WM_ACTIVATE: - { - if (LOWORD(wParam) == WA_INACTIVE) break; - - /* else fall through */ - } -#endif - case WM_LBUTTONDOWN: case WM_MBUTTONDOWN: case WM_RBUTTONDOWN: diff --git a/src/main-xaw.c b/src/main-xaw.c index 8795e00d..8de36a95 100644 --- a/src/main-xaw.c +++ b/src/main-xaw.c @@ -852,14 +852,6 @@ static void Redisplay(AngbandWidget wnew, XEvent *xev, Region region) /* Activate the old term */ Term_activate(&old_td->t); - - -#if 0 - if (XtHasCallbacks((Widget)widget, XtNredrawCallback) == XtCallbackHasSome) - { - XtCallCallbacks((Widget)widget, XtNredrawCallback, NULL); - } -#endif /* 0 */ } -- cgit v1.2.3 From be5ec8c7d9945b268202483609ff43a66b59ef0d Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 28 Jun 2012 11:23:15 +0200 Subject: Remove R_IDX_TESTING_HACK conditional code --- src/monster2.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/monster2.c b/src/monster2.c index b87df278..65d1c368 100644 --- a/src/monster2.c +++ b/src/monster2.c @@ -3434,10 +3434,6 @@ bool_ summon_specific(int y1, int x1, int lev, int type) r_idx = get_mon_num((dun_level + lev) / 2 + 5); summon_hack = FALSE; -#ifdef R_IDX_TESTING_HACK - r_idx = 356; -#endif - /* Reset restriction */ get_mon_num_hook = old_get_mon_num_hook; @@ -3518,10 +3514,6 @@ bool_ summon_specific_friendly(int y1, int x1, int lev, int type, bool_ Group_ok /* Pick a monster, using the level calculation */ r_idx = get_mon_num((dun_level + lev) / 2 + 5); -#ifdef R_IDX_TESTING_HACK - r_idx = 356; -#endif - /* Reset restriction */ get_mon_num_hook = old_get_mon_num_hook; -- cgit v1.2.3 From 37a488bff1aa553bff9116f1bf56d5402a7732fa Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 28 Jun 2012 11:36:38 +0200 Subject: Add "extern C" declarations for C++ --- src/h-type.h | 9 +++++++++ src/quark.h | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/src/h-type.h b/src/h-type.h index 27551b7f..145d4729 100644 --- a/src/h-type.h +++ b/src/h-type.h @@ -3,6 +3,11 @@ #ifndef INCLUDED_H_TYPE_H #define INCLUDED_H_TYPE_H +#ifdef __cplusplus +extern "C" { +#endif + + /* * Basic "types". * @@ -180,5 +185,9 @@ typedef vptr (*func_key)(vptr); +#ifdef __cplusplus +} // extern "C" +#endif + #endif diff --git a/src/quark.h b/src/quark.h index 93cb938f..9488b105 100644 --- a/src/quark.h +++ b/src/quark.h @@ -3,8 +3,16 @@ #include "h-type.h" +#ifdef __cplusplus +extern "C" { +#endif + void quark_init(); cptr quark_str(s16b num); s16b quark_add(cptr str); +#ifdef __cplusplus +} // extern "C" +#endif + #endif -- cgit v1.2.3 From a61dd3da6e8e21f4bc0e47e3f42814e8977a1b28 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 28 Jun 2012 16:45:57 +0200 Subject: Simplify do_s16b/do_32b load/save code --- src/loadsave.c | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/src/loadsave.c b/src/loadsave.c index 858ea377..aac4e8a1 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -1105,19 +1105,7 @@ static void do_u16b(u16b *v, int flag) static void do_s16b(s16b *ip, int flag) { - if (flag == LS_LOAD) - { - do_u16b((u16b *)ip, flag); - return; - } - if (flag == LS_SAVE) - { - do_u16b((u16b *)ip, flag); - return; - } - /* Blah blah, never should reach here, die */ - printf("FATAL: do_s16b passed %d\n", flag); - exit(0); + do_u16b((u16b *)ip, flag); } static void do_u32b(u32b *ip, int flag) @@ -1146,19 +1134,7 @@ static void do_u32b(u32b *ip, int flag) static void do_s32b(s32b *ip, int flag) { - if (flag == LS_LOAD) - { - do_u32b((u32b *)ip, flag); - return; - } - if (flag == LS_SAVE) - { - do_u32b((u32b *)ip, flag); - return; - } - /* Raus! Schnell! */ - printf("FATAL: do_s32b passed %d\n", flag); - exit(0); + do_u32b((u32b *)ip, flag); } static void do_string(char *str, int max, int flag) -- cgit v1.2.3 From ca71337c773e730fbb02a8d1464678659ac07e7e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 28 Jun 2012 22:04:21 +0200 Subject: Remove dead lua_bind.c code --- src/externs.h | 18 ------------- src/lua_bind.c | 82 ---------------------------------------------------------- src/types.h | 9 ------- 3 files changed, 109 deletions(-) diff --git a/src/externs.h b/src/externs.h index 86127f25..4a1b64d4 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2331,22 +2331,12 @@ extern int find_module(cptr name); /* lua_bind.c */ extern s16b can_spell_random(s16b spell_idx); -extern magic_power *grab_magic_power(magic_power *m_ptr, int num); extern bool_ get_magic_power(int *sn, magic_power *powers, int max_powers, void (*power_info)(char *p, int power), int plev, int cast_stat); -extern object_type *new_object(void); -extern void end_object(object_type *o_ptr); -extern void lua_set_item_tester(int tval, char *fct); -extern char *lua_object_desc(object_type *o_ptr, int pref, int mode); - extern s16b add_new_power(cptr name, cptr desc, cptr gain, cptr lose, byte level, byte cost, byte stat, byte diff); extern void find_position(int y, int x, int *yy, int *xx); -extern s16b add_new_gods(char *name); - -extern bool_ get_com_lua(cptr promtp, int *com); - extern s32b lua_get_level(spell_type *spell, s32b lvl, s32b max, s32b min, s32b bonus); extern s32b get_level_device(s32b s, s32b max, s32b min); extern int get_mana(s32b s); @@ -2360,25 +2350,17 @@ extern s32b lua_spell_device_chance(s32b chance, int level, int base_level); extern s32b get_level_max_stick; extern s32b get_level_use_stick; -extern cave_type *lua_get_cave(int y, int x); extern void set_target(int y, int x); extern void get_target(int dir, int *y, int *x); extern void get_map_size(char *name, int *ysize, int *xsize); extern void load_map(char *name, int *y, int *x); -extern bool_ alloc_room(int by0, int bx0, int ysize, int xsize, int *y1, int *x1, int *y2, int *x2); - -extern void lua_print_hook(cptr str); extern int lua_get_new_bounty_monster(int lev); extern char *lua_input_box(cptr title, int max); extern char lua_msg_box(cptr title); -extern list_type *lua_create_list(int size); -extern void lua_delete_list(list_type *, int size); -extern void lua_add_to_list(list_type *, int idx, cptr str); - extern void increase_mana(int delta); extern timer_type *TIMER_AGGRAVATE_EVIL; diff --git a/src/lua_bind.c b/src/lua_bind.c index 076404cf..dd7acede 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -18,34 +18,6 @@ s16b can_spell_random(s16b spell_idx) return spell_at(spell_idx)->random_type; } -magic_power *grab_magic_power(magic_power *m_ptr, int num) -{ - return (&m_ptr[num]); -} - -/* - * Create objects - */ -object_type *new_object() -{ - object_type *o_ptr; - MAKE(o_ptr, object_type); - return (o_ptr); -} - -void end_object(object_type *o_ptr) -{ - FREE(o_ptr, object_type); -} - -char *lua_object_desc(object_type *o_ptr, int pref, int mode) -{ - static char buf[150]; - - object_desc(buf, o_ptr, pref, mode); - return (buf); -} - /* * Monsters */ @@ -64,19 +36,6 @@ void find_position(int y, int x, int *yy, int *xx) /* * Misc */ -bool_ get_com_lua(cptr prompt, int *com) -{ - char c; - - if (!get_com(prompt, &c)) return (FALSE); - *com = c; - return (TRUE); -} - -school_type *grab_school_type(s16b num) -{ - return (&schools[num]); -} /* Change this fct if I want to switch to learnable spells */ s32b lua_get_level(spell_type *spell, s32b lvl, s32b max, s32b min, s32b bonus) @@ -217,12 +176,6 @@ s32b lua_spell_device_chance(s32b chance, int level, int base_level) return clamp_failure_chance(chance, minfail); } -/* Cave */ -cave_type *lua_get_cave(int y, int x) -{ - return (&(cave[y][x])); -} - void set_target(int y, int x) { target_who = -1; @@ -269,41 +222,6 @@ void load_map(char *name, int *y, int *x) process_dungeon_file(name, y, x, cur_hgt, cur_wid, TRUE, TRUE); } -bool_ alloc_room(int by0, int bx0, int ysize, int xsize, int *y1, int *x1, int *y2, int *x2) -{ - int xval, yval, x, y; - - /* Try to allocate space for room. If fails, exit */ - if (!room_alloc(xsize + 2, ysize + 2, FALSE, by0, bx0, &xval, &yval)) return FALSE; - - /* Get corner values */ - *y1 = yval - ysize / 2; - *x1 = xval - xsize / 2; - *y2 = yval + (ysize) / 2; - *x2 = xval + (xsize) / 2; - - /* Place a full floor under the room */ - for (y = *y1 - 1; y <= *y2 + 1; y++) - { - for (x = *x1 - 1; x <= *x2 + 1; x++) - { - cave_type *c_ptr = &cave[y][x]; - cave_set_feat(y, x, floor_type[rand_int(100)]); - c_ptr->info |= (CAVE_ROOM); - c_ptr->info |= (CAVE_GLOW); - } - } - return TRUE; -} - - -/* Files */ -void lua_print_hook(cptr str) -{ - fprintf(hook_file, "%s", str); -} - - /* * Finds a good random bounty monster * Im too lazy to write it in lua since the lua API for monsters is not very well yet diff --git a/src/types.h b/src/types.h index cb6d8e73..825e25ab 100644 --- a/src/types.h +++ b/src/types.h @@ -2710,15 +2710,6 @@ struct timer_type void (*callback)(); /* The C function to call upon firing */ }; -/* - * This is for lua functions that need to pass table to c functions - */ -typedef struct list_type list_type; -struct list_type -{ - cptr *list; -}; - /* * Abilities */ -- cgit v1.2.3 From 3926a7dee3cd9ab7aaf4b5345c6ee23f08219cb4 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 29 Jun 2012 07:29:08 +0200 Subject: lua_bind: Inline lua_spell_{device_,}chance() --- src/externs.h | 2 -- src/lua_bind.c | 103 ++++++++++++++++++++++++++++----------------------------- 2 files changed, 50 insertions(+), 55 deletions(-) diff --git a/src/externs.h b/src/externs.h index 4a1b64d4..cab134d7 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2344,8 +2344,6 @@ extern s32b get_power(s32b s); extern s32b spell_chance(s32b s); extern s32b get_level(s32b s, s32b max, s32b min); extern void get_level_school(s32b s, s32b max, s32b min, s32b *level, bool_ *na); -extern s32b lua_spell_chance(s32b chance, int level, int skill_level, int mana, int cur_mana, int stat); -extern s32b lua_spell_device_chance(s32b chance, int level, int base_level); extern s32b get_level_max_stick; extern s32b get_level_use_stick; diff --git a/src/lua_bind.c b/src/lua_bind.c index dd7acede..d6657bff 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -107,10 +107,56 @@ s32b spell_chance(s32b s) int level = get_level(s, 50, 1); /* Extract the base spell failure rate */ - if (get_level_use_stick > -1) { - return lua_spell_device_chance(s_ptr->failure_rate, level, s_ptr->skill_level); - } else { - return lua_spell_chance(s_ptr->failure_rate, level, s_ptr->skill_level, get_mana(s), get_power(s), s_ptr->casting_stat); + if (get_level_use_stick > -1) + { + int minfail; + s32b chance = s_ptr->failure_rate; + + /* Reduce failure rate by "effective" level adjustment */ + chance -= (level - 1); + + /* Extract the minimum failure rate */ + minfail = 15 - get_skill_scale(SKILL_DEVICE, 25); + + /* Return the chance */ + return clamp_failure_chance(chance, minfail); + } + else + { + s32b chance = s_ptr->failure_rate; + int mana = get_mana(s); + int cur_mana = get_power(s); + int stat = s_ptr->casting_stat; + int stat_ind = p_ptr->stat_ind[stat]; + int minfail; + + /* Reduce failure rate by "effective" level adjustment */ + chance -= 3 * (level - 1); + + /* Reduce failure rate by INT/WIS adjustment */ + chance -= 3 * (adj_mag_stat[stat_ind] - 1); + + /* Not enough mana to cast */ + if (chance < 0) chance = 0; + if (mana > cur_mana) + { + chance += 15 * (mana - cur_mana); + } + + /* Extract the minimum failure rate */ + minfail = adj_mag_fail[stat_ind]; + + /* Must have Perfect Casting to get below 5% */ + if (!(has_ability(AB_PERFECT_CASTING))) + { + if (minfail < 5) minfail = 5; + } + + /* Hack -- Priest prayer penalty for "edged" weapons -DGK */ + if ((forbid_non_blessed()) && (p_ptr->icky_wield)) chance += 25; + + /* Return the chance */ + return clamp_failure_chance(chance, minfail); } } @@ -127,55 +173,6 @@ s32b get_level(s32b s, s32b max, s32b min) } } - -s32b lua_spell_chance(s32b chance, int level, int skill_level, int mana, int cur_mana, int stat) -{ - int minfail; - /* Reduce failure rate by "effective" level adjustment */ - chance -= 3 * (level - 1); - - /* Reduce failure rate by INT/WIS adjustment */ - chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[stat]] - 1); - - /* Not enough mana to cast */ - if (chance < 0) chance = 0; - if (mana > cur_mana) - { - chance += 15 * (mana - cur_mana); - } - - /* Extract the minimum failure rate */ - minfail = adj_mag_fail[p_ptr->stat_ind[stat]]; - - /* - * Non mage characters never get too good - */ - if (!(has_ability(AB_PERFECT_CASTING))) - { - if (minfail < 5) minfail = 5; - } - - /* Hack -- Priest prayer penalty for "edged" weapons -DGK */ - if ((forbid_non_blessed()) && (p_ptr->icky_wield)) chance += 25; - - /* Return the chance */ - return clamp_failure_chance(chance, minfail); -} - -s32b lua_spell_device_chance(s32b chance, int level, int base_level) -{ - int minfail; - - /* Reduce failure rate by "effective" level adjustment */ - chance -= (level - 1); - - /* Extract the minimum failure rate */ - minfail = 15 - get_skill_scale(SKILL_DEVICE, 25); - - /* Return the chance */ - return clamp_failure_chance(chance, minfail); -} - void set_target(int y, int x) { target_who = -1; -- cgit v1.2.3 From c6cd8211eb4655520a607d7d1a854927de7a1803 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 29 Jun 2012 20:33:13 +0200 Subject: Remove FORCE_V_IDX preprocessor define --- src/config.h | 5 ----- src/generate.c | 14 +------------- 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/src/config.h b/src/config.h index d8046ffb..8ee46cf7 100644 --- a/src/config.h +++ b/src/config.h @@ -220,11 +220,6 @@ -/* Wizard mode testing options: */ - -/* For testing the vaults */ -/* # define FORCE_V_IDX 20 */ - /* * Allow makefiles to override the default file mode */ diff --git a/src/generate.c b/src/generate.c index 313d9498..44e331a6 100644 --- a/src/generate.c +++ b/src/generate.c @@ -3813,10 +3813,6 @@ static void build_type7(int by0, int bx0) } -#ifdef FORCE_V_IDX - v_ptr = &v_info[FORCE_V_IDX]; -#endif - /* Message */ if (cheat_room || p_ptr->precognition) msg_print("Lesser Vault"); @@ -3873,10 +3869,6 @@ static void build_type8(int by0, int bx0) } -#ifdef FORCE_V_IDX - v_ptr = &v_info[FORCE_V_IDX]; -#endif - /* Message */ if (cheat_room || p_ptr->precognition) msg_print("Greater Vault"); @@ -6859,10 +6851,7 @@ bool_ level_generate_dungeon() /* Attempt a very unusual room */ /* test hack */ if (ironman_rooms || (rand_int(DUN_UNUSUAL) < dun_level)) { -#ifdef FORCE_V_IDX - if (room_build(y, x, 8)) continue; -#else -/* Type 8 -- Greater vault (10%) */ + /* Type 8 -- Greater vault (10%) */ if (k < 10) { if (max_vault_ok > 1) @@ -6897,7 +6886,6 @@ bool_ level_generate_dungeon() /* Type 11 -- Random vault (5%) */ if ((k < 60) && room_build(y, x, 11)) continue; -#endif } /* Type 4 -- Large room (25%) */ -- cgit v1.2.3 From f7e87bc98111f97ca489e1f13999058a7df8171e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Fri, 29 Jun 2012 20:49:49 +0200 Subject: Split high score reading/writing into separate compilation unit --- src/CMakeLists.txt | 2 +- src/files.c | 157 +---------------------------------------------------- src/hiscore.c | 85 +++++++++++++++++++++++++++++ src/hiscore.h | 89 ++++++++++++++++++++++++++++++ 4 files changed, 177 insertions(+), 156 deletions(-) create mode 100644 src/hiscore.c create mode 100644 src/hiscore.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0e71e07b..50bb33de 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,7 +11,7 @@ SET(SRCS corrupt.c joke.c mimic.c status.c files.c notes.c loadsave.c string_list.c cmd1.c cmd2.c cmd3.c cmd4.c cmd5.c cmd6.c cmd7.c - help.c range.c + help.c hiscore.c range.c generate.c gen_maze.c gen_evol.c wild.c levels.c store.c bldg.c cmovie.c wizard2.c init2.c birth.c wizard1.c init1.c main.c diff --git a/src/files.c b/src/files.c index ea1922a5..f8125148 100644 --- a/src/files.c +++ b/src/files.c @@ -12,6 +12,8 @@ #include "angband.h" +#include "hiscore.h" + /* * Extract the first few "tokens" from a buffer @@ -4693,161 +4695,6 @@ static void show_info(void) -/* - * Semi-Portable High Score List Entry (128 bytes) -- BEN - * - * All fields listed below are null terminated ascii strings. - * - * In addition, the "number" fields are right justified, and - * space padded, to the full available length (minus the "null"). - * - * Note that "string comparisons" are thus valid on "pts". - */ - -typedef struct high_score high_score; - -struct high_score -{ - char what[8]; /* Version info (string) */ - - char pts[10]; /* Total Score (number) */ - - char gold[10]; /* Total Gold (number) */ - - char turns[10]; /* Turns Taken (number) */ - - char day[10]; /* Time stamp (string) */ - - char who[16]; /* Player Name (string) */ - - char unused_1[8]; /* Kept for compatibility only */ - - char sex[2]; /* Player Sex (string) */ - char p_r[3]; /* Player Race (number) */ - char p_s[3]; /* Player Subrace (number) */ - char p_c[3]; /* Player Class (number) */ - char p_cs[3]; /* Player Class spec (number) */ - - char cur_lev[4]; /* Current Player Level (number) */ - char cur_dun[4]; /* Current Dungeon Level (number) */ - char max_lev[4]; /* Max Player Level (number) */ - char max_dun[4]; /* Max Dungeon Level (number) */ - - char arena_number[4]; /* Arena level attained -KMW- */ - char inside_arena[4]; /* Did the player die in the arena? */ - char inside_quest[4]; /* Did the player die in a quest? */ - char exit_bldg[4]; /* Can the player exit arena? Goal obtained? -KMW- */ - - char how[32]; /* Method of death (string) */ -}; - - - -/* - * Seek score 'i' in the highscore file - */ -static int highscore_seek(int highscore_fd, int i) -{ - /* Seek for the requested record */ - return (fd_seek(highscore_fd, (huge)(i) * sizeof(high_score))); -} - - -/* - * Read one score from the highscore file - */ -static errr highscore_read(int highscore_fd, high_score *score) -{ - /* Read the record, note failure */ - return (fd_read(highscore_fd, (char*)(score), sizeof(high_score))); -} - - -/* - * Write one score to the highscore file - */ -static int highscore_write(int highscore_fd, high_score *score) -{ - /* Write the record, note failure */ - return (fd_write(highscore_fd, (char*)(score), sizeof(high_score))); -} - - - - -/* - * Just determine where a new score *would* be placed - * Return the location (0 is best) or -1 on failure - */ -static int highscore_where(int highscore_fd, high_score *score) -{ - int i; - - high_score the_score; - - /* Paranoia -- it may not have opened */ - if (highscore_fd < 0) return ( -1); - - /* Go to the start of the highscore file */ - if (highscore_seek(highscore_fd, 0)) return ( -1); - - /* Read until we get to a higher score */ - for (i = 0; i < MAX_HISCORES; i++) - { - if (highscore_read(highscore_fd, &the_score)) return (i); - if (strcmp(the_score.pts, score->pts) < 0) return (i); - } - - /* The "last" entry is always usable */ - return (MAX_HISCORES - 1); -} - - -/* - * Actually place an entry into the high score file - * Return the location (0 is best) or -1 on "failure" - */ -static int highscore_add(int highscore_fd, high_score *score) -{ - int i, slot; - bool_ done = FALSE; - - high_score the_score, tmpscore; - - - /* Paranoia -- it may not have opened */ - if (highscore_fd < 0) return ( -1); - - /* Determine where the score should go */ - slot = highscore_where(highscore_fd, score); - - /* Hack -- Not on the list */ - if (slot < 0) return ( -1); - - /* Hack -- prepare to dump the new score */ - the_score = (*score); - - /* Slide all the scores down one */ - for (i = slot; !done && (i < MAX_HISCORES); i++) - { - /* Read the old guy, note errors */ - if (highscore_seek(highscore_fd, i)) return ( -1); - if (highscore_read(highscore_fd, &tmpscore)) done = TRUE; - - /* Back up and dump the score we were holding */ - if (highscore_seek(highscore_fd, i)) return ( -1); - if (highscore_write(highscore_fd, &the_score)) return ( -1); - - /* Hack -- Save the old score, for the next pass */ - the_score = tmpscore; - } - - /* Return location used */ - return (slot); -} - - - /* * Display the scores in a given range. * Assumes the high score list is already open. diff --git a/src/hiscore.c b/src/hiscore.c new file mode 100644 index 00000000..357026da --- /dev/null +++ b/src/hiscore.c @@ -0,0 +1,85 @@ +#include "hiscore.h" + +#include + +#include "angband.h" + +int highscore_seek(int highscore_fd, int i) +{ + /* Seek for the requested record */ + return (fd_seek(highscore_fd, (huge)(i) * sizeof(high_score))); +} + +errr highscore_read(int highscore_fd, high_score *score) +{ + /* Read the record, note failure */ + return (fd_read(highscore_fd, (char*)(score), sizeof(high_score))); +} + +int highscore_write(int highscore_fd, high_score *score) +{ + /* Write the record, note failure */ + return (fd_write(highscore_fd, (char*)(score), sizeof(high_score))); +} + +int highscore_where(int highscore_fd, high_score *score) +{ + int i; + + high_score the_score; + + /* Paranoia -- it may not have opened */ + if (highscore_fd < 0) return ( -1); + + /* Go to the start of the highscore file */ + if (highscore_seek(highscore_fd, 0)) return ( -1); + + /* Read until we get to a higher score */ + for (i = 0; i < MAX_HISCORES; i++) + { + if (highscore_read(highscore_fd, &the_score)) return (i); + if (strcmp(the_score.pts, score->pts) < 0) return (i); + } + + /* The "last" entry is always usable */ + return (MAX_HISCORES - 1); +} + +int highscore_add(int highscore_fd, high_score *score) +{ + int i, slot; + bool_ done = FALSE; + + high_score the_score, tmpscore; + + + /* Paranoia -- it may not have opened */ + if (highscore_fd < 0) return ( -1); + + /* Determine where the score should go */ + slot = highscore_where(highscore_fd, score); + + /* Hack -- Not on the list */ + if (slot < 0) return ( -1); + + /* Hack -- prepare to dump the new score */ + the_score = (*score); + + /* Slide all the scores down one */ + for (i = slot; !done && (i < MAX_HISCORES); i++) + { + /* Read the old guy, note errors */ + if (highscore_seek(highscore_fd, i)) return ( -1); + if (highscore_read(highscore_fd, &tmpscore)) done = TRUE; + + /* Back up and dump the score we were holding */ + if (highscore_seek(highscore_fd, i)) return ( -1); + if (highscore_write(highscore_fd, &the_score)) return ( -1); + + /* Hack -- Save the old score, for the next pass */ + the_score = tmpscore; + } + + /* Return location used */ + return (slot); +} diff --git a/src/hiscore.h b/src/hiscore.h new file mode 100644 index 00000000..0eed91b4 --- /dev/null +++ b/src/hiscore.h @@ -0,0 +1,89 @@ +#ifndef H_267bf1c1_eada_4b18_9558_d96330fa7258 +#define H_267bf1c1_eada_4b18_9558_d96330fa7258 + +#include "h-type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Semi-Portable High Score List Entry (128 bytes) -- BEN + * + * All fields listed below are null terminated ascii strings. + * + * In addition, the "number" fields are right justified, and + * space padded, to the full available length (minus the "null"). + * + * Note that "string comparisons" are thus valid on "pts". + */ + +typedef struct high_score high_score; + +struct high_score +{ + char what[8]; /* Version info (string) */ + + char pts[10]; /* Total Score (number) */ + + char gold[10]; /* Total Gold (number) */ + + char turns[10]; /* Turns Taken (number) */ + + char day[10]; /* Time stamp (string) */ + + char who[16]; /* Player Name (string) */ + + char unused_1[8]; /* Kept for compatibility only */ + + char sex[2]; /* Player Sex (string) */ + char p_r[3]; /* Player Race (number) */ + char p_s[3]; /* Player Subrace (number) */ + char p_c[3]; /* Player Class (number) */ + char p_cs[3]; /* Player Class spec (number) */ + + char cur_lev[4]; /* Current Player Level (number) */ + char cur_dun[4]; /* Current Dungeon Level (number) */ + char max_lev[4]; /* Max Player Level (number) */ + char max_dun[4]; /* Max Dungeon Level (number) */ + + char arena_number[4]; /* Arena level attained -KMW- */ + char inside_arena[4]; /* Did the player die in the arena? */ + char inside_quest[4]; /* Did the player die in a quest? */ + char exit_bldg[4]; /* Can the player exit arena? Goal obtained? -KMW- */ + + char how[32]; /* Method of death (string) */ +}; + +/* + * Seek score 'i' in the highscore file + */ +int highscore_seek(int highscore_fd, int i); + +/* + * Read one score from the highscore file + */ +errr highscore_read(int highscore_fd, high_score *score); + +/* + * Write one score to the highscore file + */ +int highscore_write(int highscore_fd, high_score *score); + +/* + * Determine where a new score *would* be placed + * Return the location (0 is best) or -1 on failure + */ +int highscore_where(int highscore_fd, high_score *score); + +/* + * Place an entry into the high score file. Return the location (0 is + * best) or -1 on "failure" + */ +int highscore_add(int highscore_fd, high_score *score); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif -- cgit v1.2.3 From 763a1c383895f5f04d025ba6ebf79aee9425df70 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 30 Jun 2012 08:51:51 +0200 Subject: Change spell_type to a semi-ADT --- src/CMakeLists.txt | 1 + src/angband.h | 1 + src/cmd5.c | 5 +- src/cmd6.c | 40 +- src/dungeon.c | 5 +- src/externs.h | 12 +- src/lua_bind.c | 32 +- src/object1.c | 36 +- src/object2.c | 44 +- src/spell_type.c | 465 ++++++++ src/spell_type.h | 103 ++ src/spell_type_fwd.h | 27 + src/spells1.c | 4 +- src/spells3.c | 52 +- src/spells4.c | 143 +-- src/spells5.c | 3020 ++++++++++++++++++++++++-------------------------- src/spells6.c | 178 +-- src/store.c | 5 +- src/types.h | 66 -- src/variable.c | 2 +- 20 files changed, 2262 insertions(+), 1979 deletions(-) create mode 100644 src/spell_type.c create mode 100644 src/spell_type.h create mode 100644 src/spell_type_fwd.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 50bb33de..03c1771b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,6 +8,7 @@ SET(SRCS monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c spells1.c spells2.c spells3.c spells4.c spells5.c spells6.c + spell_type.c corrupt.c joke.c mimic.c status.c files.c notes.c loadsave.c string_list.c cmd1.c cmd2.c cmd3.c cmd4.c cmd5.c cmd6.c cmd7.c diff --git a/src/angband.h b/src/angband.h index 93e3b76e..6bfbb984 100644 --- a/src/angband.h +++ b/src/angband.h @@ -55,6 +55,7 @@ extern "C" { */ #include "defines.h" #include "types.h" +#include "spell_type_fwd.h" #include "externs.h" #include "plots.h" diff --git a/src/cmd5.c b/src/cmd5.c index c32d5690..9571ce99 100644 --- a/src/cmd5.c +++ b/src/cmd5.c @@ -15,6 +15,7 @@ #include +#include "spell_type.h" #include "quark.h" /* Maximum number of tries for teleporting */ @@ -2135,7 +2136,7 @@ bool_ is_ok_spell(s32b spell_idx, object_type *o_ptr) return FALSE; } - if (o_ptr->pval < spell->minimum_pval) + if (o_ptr->pval < spell_type_minimum_pval(spell)) { return FALSE; } @@ -2454,7 +2455,7 @@ void do_cmd_copy_spell() if (spell == -1) return; /* Spells that cannot be randomly created cannot be copied */ - if (can_spell_random(spell) <= 0) + if (spell_type_random_type(spell_at(spell)) <= 0) { msg_print("This spell cannot be copied."); return; diff --git a/src/cmd6.c b/src/cmd6.c index 5377ef38..f15860b9 100644 --- a/src/cmd6.c +++ b/src/cmd6.c @@ -12,6 +12,7 @@ #include "angband.h" +#include "spell_type.h" /* * Forward declare @@ -3666,9 +3667,8 @@ static void activate_stick(s16b s, bool_ *obvious, bool_ *use_charge) assert(obvious != NULL); assert(use_charge != NULL); - assert(spell->effect_func != NULL); - ret = spell->effect_func(-1); + ret = spell_type_produce_effect(spell, -1); switch (ret) { @@ -5029,35 +5029,6 @@ void do_cmd_activate(void) msg_print("Oops. That object cannot be activated."); } - -static void get_activation_desc(char *buf, int spl) -{ - spell_type *spell = spell_at(spl); - char turns[32]; - - dice_print(&spell->activation_duration, turns); - - assert(spell->description != NULL); - assert(spell->description->s != NULL); - - sprintf(buf, "%s every %s turns", - spell->description->s, - turns); -} - -static int get_activation_timeout(int spl) -{ - spell_type *spell = spell_at(spl); - return dice_roll(&spell->activation_duration); -} - -static void activate_activation(long s, int item) -{ - spell_type *spell = spell_at(s); - assert(spell->effect_func != NULL); - spell->effect_func(item); -} - const char *activation_aux(object_type * o_ptr, bool_ doit, int item) { static char buf[256]; @@ -5100,14 +5071,15 @@ const char *activation_aux(object_type * o_ptr, bool_ doit, int item) /* Negative means a unified spell index */ if (spell < 0) { + struct spell_type *spell_ptr = spell_at(-spell); if (doit) { - activate_activation(-spell, item); - o_ptr->timeout = get_activation_timeout(-spell); + spell_type_produce_effect(spell_ptr, item); + o_ptr->timeout = spell_type_activation_roll_timeout(spell_ptr); } else { - get_activation_desc(buf, -spell); + spell_type_activation_description(spell_ptr, buf); return buf; } } diff --git a/src/dungeon.c b/src/dungeon.c index ae8d6912..a74fed2c 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -15,6 +15,7 @@ #include #include "quark.h" +#include "spell_type.h" #define TY_CURSE_CHANCE 100 #define DG_CURSE_CHANCE 50 @@ -801,9 +802,7 @@ bool_ decays(object_type *o_ptr) static int process_lasting_spell(s16b music) { spell_type *spell = spell_at(-music); - - assert(spell->lasting_func != NULL); - return spell->lasting_func(); + return spell_type_produce_effect_lasting(spell); } static void gere_class_special() diff --git a/src/externs.h b/src/externs.h index cab134d7..290a3152 100644 --- a/src/externs.h +++ b/src/externs.h @@ -542,7 +542,7 @@ extern int max_bg_idx; extern s32b extra_savefile_parts; extern bool_ player_char_health; extern s16b school_spells_count; -extern spell_type school_spells[SCHOOL_SPELLS_MAX]; +extern spell_type *school_spells[SCHOOL_SPELLS_MAX]; extern s16b schools_count; extern school_type schools[SCHOOLS_MAX]; extern int project_time; @@ -1894,7 +1894,6 @@ char *varda_star_kindler_info(); /* spells4.c */ SGLIB_DEFINE_LIST_PROTOTYPES(spell_idx_list, compare_spell_idx, next); -SGLIB_DEFINE_LIST_PROTOTYPES(school_idx, compare_school_idx, next); extern s32b SCHOOL_AIR; extern s32b SCHOOL_AULE; @@ -1922,10 +1921,6 @@ extern s32b SCHOOL_VARDA; extern s32b SCHOOL_WATER; extern s32b SCHOOL_YAVANNA; -void school_idx_init(school_idx *e, s32b i); -school_idx *school_idx_new(s32b i); -void school_idx_add_new(school_idx **list, s32b i); - void print_spell_desc(int s, int y); void init_school_books(); school_book_type *school_books_at(int sval); @@ -1938,7 +1933,6 @@ int spell_x(int sval, int pval, int i); bool_ school_book_contains_spell(int sval, s32b spell_idx); void lua_cast_school_spell(s32b spell_idx, bool_ no_cost); -void spell_description_add_line(s32b spell_idx, cptr line); void device_allocation_init(device_allocation *device_allocation, byte tval); device_allocation *device_allocation_new(byte tval); @@ -1952,7 +1946,6 @@ void dice_print(dice_type *dice, char *buf); void school_spells_init(); spell_type *spell_at(s32b index); s16b get_random_spell(s16b random_type, int lev); -bool_ check_spell_depends(spell_type *spell); /* spells6.c */ @@ -2330,7 +2323,6 @@ extern int find_module(cptr name); /* lua_bind.c */ -extern s16b can_spell_random(s16b spell_idx); extern bool_ get_magic_power(int *sn, magic_power *powers, int max_powers, void (*power_info)(char *p, int power), int plev, int cast_stat); extern s16b add_new_power(cptr name, cptr desc, cptr gain, cptr lose, byte level, byte cost, byte stat, byte diff); @@ -2366,8 +2358,6 @@ extern timer_type *TIMER_AGGRAVATE_EVIL; void timer_aggravate_evil_enable(); void timer_aggravate_evil_callback(); -cptr get_spell_info(s32b s); - /* skills.c */ extern void dump_skills(FILE *fff); extern s16b find_skill(cptr name); diff --git a/src/lua_bind.c b/src/lua_bind.c index d6657bff..a15e9eb8 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -11,12 +11,10 @@ */ #include "angband.h" + #include -s16b can_spell_random(s16b spell_idx) -{ - return spell_at(spell_idx)->random_type; -} +#include "spell_type.h" /* * Monsters @@ -42,7 +40,7 @@ s32b lua_get_level(spell_type *spell, s32b lvl, s32b max, s32b min, s32b bonus) { s32b tmp; - tmp = lvl - ((spell->skill_level - 1) * (SKILL_STEP / 10)); + tmp = lvl - ((spell_type_skill_level(spell) - 1) * (SKILL_STEP / 10)); if (tmp >= (SKILL_STEP / 10)) /* We require at least one spell level */ tmp += bonus; @@ -80,9 +78,9 @@ s32b get_level_device(s32b s, s32b max, s32b min) lvl = lvl + (get_level_use_stick * SKILL_STEP); /* Sticks are limited */ - if (lvl - ((spell->skill_level + 1) * SKILL_STEP) >= get_level_max_stick * SKILL_STEP) + if (lvl - ((spell_type_skill_level(spell) + 1) * SKILL_STEP) >= get_level_max_stick * SKILL_STEP) { - lvl = (get_level_max_stick + spell->skill_level - 1) * SKILL_STEP; + lvl = (get_level_max_stick + spell_type_skill_level(spell) - 1) * SKILL_STEP; } /* / 10 because otherwise we can overflow a s32b and we can use a u32b because the value can be negative @@ -97,20 +95,22 @@ s32b get_level_device(s32b s, s32b max, s32b min) int get_mana(s32b s) { spell_type *spell = spell_at(s); - return get_level(s, spell->mana_range.max, spell->mana_range.min); + range_type mana_range; + spell_type_mana_range(spell, &mana_range); + return get_level(s, mana_range.max, mana_range.min); } /** Returns spell chance of failure for spell */ s32b spell_chance(s32b s) { - spell_type *s_ptr = &school_spells[s]; + spell_type *s_ptr = spell_at(s); int level = get_level(s, 50, 1); /* Extract the base spell failure rate */ if (get_level_use_stick > -1) { int minfail; - s32b chance = s_ptr->failure_rate; + s32b chance = spell_type_failure_rate(s_ptr); /* Reduce failure rate by "effective" level adjustment */ chance -= (level - 1); @@ -123,10 +123,10 @@ s32b spell_chance(s32b s) } else { - s32b chance = s_ptr->failure_rate; + s32b chance = spell_type_failure_rate(s_ptr); int mana = get_mana(s); int cur_mana = get_power(s); - int stat = s_ptr->casting_stat; + int stat = spell_type_casting_stat(s_ptr); int stat_ind = p_ptr->stat_ind[stat]; int minfail; @@ -340,11 +340,3 @@ void timer_aggravate_evil_callback() dispel_evil(0); } } - -cptr get_spell_info(s32b s) -{ - spell_type *spell = spell_at(s); - - assert(spell->info_func != NULL); - return spell->info_func(); -} diff --git a/src/object1.c b/src/object1.c index 3b17e8c2..504bc9c9 100644 --- a/src/object1.c +++ b/src/object1.c @@ -13,6 +13,7 @@ #include "angband.h" #include "quark.h" +#include "spell_type.h" /* * Hack -- note that "TERM_MULTI" is now just "TERM_VIOLET". @@ -1662,7 +1663,10 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode) case TV_BOOK: { basenm = k_name + k_ptr->name; - if (o_ptr->sval == 255) modstr = school_spells[o_ptr->pval].name; + if (o_ptr->sval == 255) + { + modstr = spell_type_name(spell_at(o_ptr->pval)); + } break; } @@ -1941,7 +1945,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode) if (((o_ptr->tval == TV_WAND) || (o_ptr->tval == TV_STAFF))) { - t = object_desc_str(t, school_spells[o_ptr->pval2].name); + t = object_desc_str(t, spell_type_name(spell_at(o_ptr->pval2))); if (mode >= 1) { s32b bonus = o_ptr->pval3 & 0xFFFF; @@ -2021,7 +2025,7 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode) /* It contains a spell */ if ((known) && (f5 & TR5_SPELL_CONTAIN) && (o_ptr->pval2 != -1)) { - t = object_desc_str(t, format(" [%s]", school_spells[o_ptr->pval2].name)); + t = object_desc_str(t, format(" [%s]", spell_type_name(spell_at(o_ptr->pval2)))); } /* Add symbiote hp here, after the "fake-artifact" name. --dsb */ @@ -2799,20 +2803,12 @@ void display_ammo_damage(object_type *o_ptr) } /* - * Describe the device spell + * Output spell description */ -static void print_device_desc(int s) +static void print_device_desc_callback(void *data, cptr text) { - string_list *sl; - struct sglib_string_list_iterator it; - - for (sl = sglib_string_list_it_init(&it, school_spells[s].description); - sl != NULL; - sl = sglib_string_list_it_next(&it)) - { - text_out("\n"); - text_out(sl->s); - } + text_out("\n"); + text_out(text); } /* @@ -2828,22 +2824,24 @@ void describe_device(object_type *o_ptr) /* Enter device mode */ set_stick_mode(o_ptr); - text_out("\nSpell description:"); - print_device_desc(o_ptr->pval2); + text_out("\nSpell description:\n"); + spell_type_description_foreach(spell_at(o_ptr->pval2), + print_device_desc_callback, + NULL); text_out("\nSpell level: "); sprintf(buf, FMTs32b, get_level(o_ptr->pval2, 50, 0)); text_out_c(TERM_L_BLUE, buf); text_out("\nMinimum Magic Device level to increase spell level: "); - text_out_c(TERM_L_BLUE, format("%d", school_spells[o_ptr->pval2].skill_level)); + text_out_c(TERM_L_BLUE, format("%d", spell_type_skill_level(spell_at(o_ptr->pval2)))); text_out("\nSpell fail: "); sprintf(buf, FMTs32b, spell_chance(o_ptr->pval2)); text_out_c(TERM_GREEN, buf); text_out("\nSpell info: "); - text_out_c(TERM_YELLOW, get_spell_info(o_ptr->pval2)); + text_out_c(TERM_YELLOW, spell_type_info(spell_at(o_ptr->pval2))); /* Leave device mode */ unset_stick_mode(); diff --git a/src/object2.c b/src/object2.c index cf413c4c..b82691ea 100644 --- a/src/object2.c +++ b/src/object2.c @@ -12,6 +12,8 @@ #include "angband.h" +#include "spell_type.h" + /* * Calculate the player's total inventory weight. */ @@ -1200,7 +1202,7 @@ s32b object_value_real(object_type *o_ptr) if (f5 & TR5_SPELL_CONTAIN) { if (o_ptr->pval2 != -1) - value += 5000 + 500 * school_spells[o_ptr->pval2].skill_level; + value += 5000 + 500 * spell_type_skill_level(spell_at(o_ptr->pval2)); else value += 5000; } @@ -1282,7 +1284,7 @@ s32b object_value_real(object_type *o_ptr) case TV_WAND: { /* Par for the spell */ - value *= school_spells[o_ptr->pval2].skill_level; + value *= spell_type_skill_level(spell_at(o_ptr->pval2)); /* Take the average of the base and max spell levels */ value *= (((o_ptr->pval3 >> 16) & 0xFFFF) + (o_ptr->pval3 & 0xFFFF)) / 2; /* Hack */ @@ -1297,7 +1299,7 @@ s32b object_value_real(object_type *o_ptr) case TV_STAFF: { /* Par for the spell */ - value *= school_spells[o_ptr->pval2].skill_level; + value *= spell_type_skill_level(spell_at(o_ptr->pval2)); /* Take the average of the base and max spell levels */ value *= (((o_ptr->pval3 >> 16) & 0xFFFF) + (o_ptr->pval3 & 0xFFFF)) / 2; /* Hack */ @@ -1314,7 +1316,7 @@ s32b object_value_real(object_type *o_ptr) if (o_ptr->sval == 255) { /* Pay extra for the spell */ - value = value * school_spells[o_ptr->pval].skill_level; + value = value * spell_type_skill_level(spell_at(o_ptr->pval)); } /* Done */ break; @@ -2536,7 +2538,7 @@ static bool_ make_ego_item(object_type *o_ptr, bool_ good) void charge_stick(object_type *o_ptr) { spell_type *spell = spell_at(o_ptr->pval2); - o_ptr->pval = dice_roll(&spell->device_charges); + o_ptr->pval = spell_type_roll_charges(spell); } /* @@ -3225,28 +3227,6 @@ static void a_m_aux_3(object_type *o_ptr, int level, int power) } } - -/* - * Get device allocation for a given spell and tval - */ -static device_allocation *get_device_allocation(spell_type *spell, byte tval) -{ - struct sglib_device_allocation_iterator it; - device_allocation *device_allocation; - - for (device_allocation = sglib_device_allocation_it_init(&it, spell->device_allocation); - device_allocation != NULL; - device_allocation = sglib_device_allocation_it_next(&it)) - { - if (device_allocation->tval == tval) - { - return device_allocation; - } - } - - return NULL; -} - /* * Get a spell for a given stick(wand, staff, rod) */ @@ -3258,10 +3238,10 @@ long get_random_stick(byte tval, int level) { long spell_idx = rand_int(school_spells_count); spell_type *spell = spell_at(spell_idx); - device_allocation *device_allocation = get_device_allocation(spell, tval); + device_allocation *device_allocation = spell_type_device_allocation(spell, tval); if ((device_allocation != NULL) && - (rand_int(spell->skill_level * 3) < level) && + (rand_int(spell_type_skill_level(spell) * 3) < level) && (magik(100 - device_allocation->rarity))) { return spell_idx; @@ -3299,7 +3279,8 @@ static int randomized_level_in_range(range_type *range, int level) static int get_stick_base_level(byte tval, int level, int spl) { spell_type *spell = spell_at(spl); - device_allocation *device_allocation = get_device_allocation(spell, tval); + device_allocation *device_allocation = spell_type_device_allocation(spell, tval); + assert(device_allocation != NULL); return randomized_level_in_range(&device_allocation->base_level, level); } @@ -3309,7 +3290,8 @@ static int get_stick_base_level(byte tval, int level, int spl) static int get_stick_max_level(byte tval, int level, int spl) { spell_type *spell = spell_at(spl); - device_allocation *device_allocation = get_device_allocation(spell, tval); + device_allocation *device_allocation = spell_type_device_allocation(spell, tval); + assert(device_allocation != NULL); return randomized_level_in_range(&device_allocation->max_level, level); } diff --git a/src/spell_type.c b/src/spell_type.c new file mode 100644 index 00000000..b8bec0cd --- /dev/null +++ b/src/spell_type.c @@ -0,0 +1,465 @@ +#include "spell_type.h" + +#include "angband.h" + +#define SCHOOL_IDXS_MAX 3 + +/** + * Spell type definition. + */ +struct spell_type +{ + cptr name; /* Name */ + byte skill_level; /* Required level (to learn) */ + string_list *description; /* List of strings */ + + casting_result (*effect_func)(int o_idx); /* Spell effect function */ + char* (*info_func)(); /* Information function */ + int (*lasting_func)(); /* Lasting effect function */ + bool_ (*depend_func)(); /* Check dependencies */ + + s16b minimum_pval; /* Minimum required pval for item-based spells */ + + casting_type casting_type; /* Type of casting required */ + s16b casting_stat; /* Stat used for casting */ + + bool_ castable_while_blind; + bool_ castable_while_confused; + + dice_type device_charges; /* Number of charges for devices */ + device_allocation *device_allocation; /* Allocation table for devices */ + + s16b random_type; /* Type of random items in which skill may appear */ + + s32b failure_rate; /* Failure rate */ + + s32b inertia_difficulty; /* Mana cost when used in Inertia Control */ + s32b inertia_delay; /* Delay between castings */ + + range_type mana_range; + + dice_type activation_timeout; /* Timeout for activation (if any) */ + + int school_idxs_count; + s32b school_idxs[3]; +}; + +static void school_idx_add_new(spell_type *spell, s32b i) +{ + assert(spell != NULL); + assert(spell->school_idxs_count < SCHOOL_IDXS_MAX); + + spell->school_idxs[spell->school_idxs_count] = i; + spell->school_idxs_count++; +} + +void spell_type_init(spell_type *spell, cptr name) +{ + assert(spell != NULL); + + memset(spell, 0, sizeof(spell_type)); + + spell->name = name; + spell->description = NULL; + spell->effect_func = NULL; + spell->info_func = NULL; + spell->lasting_func = NULL; + spell->depend_func = NULL; + + spell->device_allocation = NULL; + + spell->school_idxs_count = 0; + + spell->random_type = -1; + + spell->castable_while_blind = FALSE; + spell->castable_while_confused = FALSE; + + spell_type_set_inertia(spell, -1, -1); +} + +void spell_type_set_inertia(spell_type *spell, s32b difficulty, s32b delay) +{ + assert(spell != NULL); + spell->inertia_difficulty = difficulty; + spell->inertia_delay = delay; +} + +void spell_type_init_music(spell_type *spell, + s16b minimum_pval, + char* (*info_func)(), + casting_result (*effect_func)(int o_idx)) +{ + assert(spell != NULL); + + /* Set up callbacks */ + spell->info_func = info_func; + spell->effect_func = effect_func; + + /* Use spell points, but CHR for success/failure calculations */ + spell->casting_type = USE_SPELL_POINTS; + spell->casting_stat = A_CHR; + spell->random_type = SKILL_MUSIC; + spell->minimum_pval = minimum_pval; + /* Add school */ + school_idx_add_new(spell, SCHOOL_MUSIC); +} + +void spell_type_init_music_lasting(spell_type *spell, + s16b minimum_pval, + char* (*info_func)(), + casting_result (*effect_func)(int o_idx), + int (*lasting_func)()) +{ + spell_type_init_music( + spell, + minimum_pval, + info_func, + effect_func); + + spell->lasting_func = lasting_func; +} + +void spell_type_init_mage(spell_type *spell, + random_type random_type, + s32b school_idx, + char* (*info_func)(), + casting_result (*effect_func)(int o_idx)) +{ + assert(spell != NULL); + + spell->info_func = info_func; + spell->effect_func = effect_func; + + spell->casting_type = USE_SPELL_POINTS; + spell->casting_stat = A_INT; + + switch (random_type) + { + case RANDOM: + spell->random_type = SKILL_MAGIC; + break; + case NO_RANDOM: + spell->random_type = -1; + break; + default: + /* Cannot happen */ + assert(FALSE); + } + + /* Add first school */ + spell_type_add_school(spell, school_idx); +} + +void spell_type_init_priest(spell_type *spell, + s32b school_idx, + char* (*info_func)(), + casting_result (*effect_func)(int o_idx)) +{ + assert(spell != NULL); + + spell->info_func = info_func; + spell->effect_func = effect_func; + + spell->random_type = SKILL_SPIRITUALITY; + spell->casting_type = USE_PIETY; + spell->casting_stat = A_WIS; + + school_idx_add_new(spell, school_idx); +} + +void spell_type_init_device(spell_type *spell, + char* (*info_func)(), + casting_result (*effect_func)(int o_idx)) +{ + assert(spell != NULL); + + spell_type_init_mage(spell, + NO_RANDOM, + SCHOOL_DEVICE, + info_func, + effect_func); +} + +void spell_type_init_demonology(spell_type *spell, + char* (*info_func)(), + casting_result (*effect_func)(int o_idx)) +{ + spell_type_init_mage(spell, + NO_RANDOM, + SCHOOL_DEMON, + info_func, + effect_func); +} + +void spell_type_init_geomancy(spell_type *spell, + char* (*info_func)(), + casting_result (*effect_func)(int o_idx), + bool_ (*depend_func)()) +{ + spell_type_init_mage(spell, + NO_RANDOM, + SCHOOL_GEOMANCY, + info_func, + effect_func); + + spell->depend_func = depend_func; +} + +void spell_type_set_activation_timeout(spell_type *spell, cptr timeout_s) +{ + assert(spell != NULL); + + dice_parse_checked(&spell->activation_timeout, timeout_s); +} + +void spell_type_set_difficulty(spell_type *spell, byte skill_level, s32b failure_rate) +{ + assert(spell != NULL); + + spell->skill_level = skill_level; + spell->failure_rate = failure_rate; +} + +void spell_type_set_mana(spell_type *spell, s32b min, s32b max) +{ + assert(spell != NULL); + + range_init(&spell->mana_range, min, max); +} + +void spell_type_set_castable_while_blind(spell_type *spell, bool_ value) +{ + assert(spell != NULL); + + spell->castable_while_blind = value; +} + +void spell_type_set_castable_while_confused(spell_type *spell, bool_ value) +{ + assert(spell != NULL); + + spell->castable_while_confused = value; +} + +void spell_type_describe(spell_type *spell, cptr line) +{ + assert(spell != NULL); + + string_list_append(&spell->description, line); +} + +void spell_type_add_school(spell_type *spell, s32b school_idx) +{ + school_idx_add_new(spell, school_idx); +} + +void spell_type_set_device_charges(spell_type *spell, cptr charges_s) +{ + assert(spell != NULL); + + dice_parse_checked(&spell->device_charges, charges_s); +} + +void spell_type_add_device_allocation(spell_type *spell, struct device_allocation *a) +{ + assert(spell != NULL); + assert(a != NULL); + + sglib_device_allocation_add(&spell->device_allocation, a); +} + +spell_type *spell_type_new(cptr name) +{ + spell_type *spell = malloc(sizeof(spell_type)); + assert(spell != NULL); + spell_type_init(spell, name); + return spell; +} + +int spell_type_produce_effect_lasting(spell_type *spell) +{ + assert(spell->lasting_func != NULL); + return spell->lasting_func(); +} + +casting_result spell_type_produce_effect(spell_type *spell, int o_idx) +{ + assert(spell->effect_func != NULL); + return spell->effect_func(o_idx); +} + +cptr spell_type_name(spell_type *spell) +{ + assert(spell != NULL); + + return spell->name; +} + +int spell_type_skill_level(spell_type *spell) +{ + assert(spell != NULL); + + return spell->skill_level; +} + +void spell_type_description_foreach(spell_type *spell, void (*callback)(void *data, cptr text), void *data) +{ + string_list *sl; + struct sglib_string_list_iterator it; + + assert(callback != NULL); + + for (sl = sglib_string_list_it_init(&it, spell->description); + sl != NULL; + sl = sglib_string_list_it_next(&it)) + { + callback(data, sl->s); + } +} + +long spell_type_roll_charges(spell_type *spell) +{ + return dice_roll(&spell->device_charges); +} + +void spell_type_activation_description(spell_type *spell, char *buf) +{ + char turns[32]; + + dice_print(&spell->activation_timeout, turns); + + assert(spell->description != NULL); + assert(spell->description->s != NULL); + + sprintf(buf, "%s every %s turns", spell->description->s, turns); +} + +int spell_type_activation_roll_timeout(spell_type *spell) +{ + return dice_roll(&spell->activation_timeout); +} + +device_allocation *spell_type_device_allocation(spell_type *spell, byte tval) +{ + struct sglib_device_allocation_iterator it; + device_allocation *device_allocation; + + for (device_allocation = sglib_device_allocation_it_init(&it, spell->device_allocation); + device_allocation != NULL; + device_allocation = sglib_device_allocation_it_next(&it)) + { + if (device_allocation->tval == tval) + { + return device_allocation; + } + } + + return NULL; +} + +bool_ spell_type_uses_piety_to_cast(spell_type *spell) +{ + assert(spell != NULL); + return spell->casting_type == USE_PIETY; +} + +bool_ spell_type_castable_while_blind(spell_type *spell) +{ + assert(spell != NULL); + return spell->castable_while_blind; +} + +bool_ spell_type_castable_while_confused(spell_type *spell) +{ + assert(spell != NULL); + return spell->castable_while_confused; +} + +s16b spell_type_minimum_pval(spell_type *spell) +{ + return spell->minimum_pval; +} + +s16b spell_type_random_type(spell_type *spell) +{ + return spell->random_type; +} + +bool_ spell_type_school_foreach(spell_type *spell, bool_ (*callback)(void *data, s32b school_idx), void *data) +{ + int i; + + for (i = 0; i < spell->school_idxs_count; i++) + { + if (!callback(data, spell->school_idxs[i])) + { + return FALSE; + } + } + + return TRUE; +} + +bool_ spell_type_inertia(spell_type *spell, s32b *difficulty, s32b *delay) +{ + if ((spell->inertia_difficulty < 0) || + (spell->inertia_delay < 0)) + { + return FALSE; + } + + if (difficulty != NULL) + { + *difficulty = spell->inertia_difficulty; + } + + if (delay != NULL) + { + *delay = spell->inertia_delay; + } + + return TRUE; +} + +cptr spell_type_info(spell_type *spell) +{ + assert(spell != NULL); + + return spell->info_func(); +} + +s32b spell_type_failure_rate(spell_type *spell) +{ + assert(spell != NULL); + + return spell->failure_rate; +} + +s16b spell_type_casting_stat(spell_type *spell) +{ + assert(spell != NULL); + + return spell->casting_stat; +} + +void spell_type_mana_range(spell_type *spell, range_type *range) +{ + assert(spell != NULL); + + if (range != NULL) + { + *range = spell->mana_range; + } +} + +bool_ spell_type_dependencies_satisfied(spell_type *spell) +{ + assert(spell != NULL); + + if (spell->depend_func != NULL) { + return spell->depend_func(); + } else { + return TRUE; + } +} diff --git a/src/spell_type.h b/src/spell_type.h new file mode 100644 index 00000000..32d6c7b6 --- /dev/null +++ b/src/spell_type.h @@ -0,0 +1,103 @@ +#ifndef H_e7e01ebf_e19f_439d_b88d_cad51446a7a0 +#define H_e7e01ebf_e19f_439d_b88d_cad51446a7a0 + +#include "spell_type_fwd.h" + +#include "h-type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Forward declarations + */ +struct device_allocation; +struct range_type; + +/* + * Casting type + */ +typedef enum { USE_SPELL_POINTS, USE_PIETY } casting_type; + +/* + * Does the spell appear on spell random books? + */ +typedef enum { RANDOM, NO_RANDOM } random_type; + +/* + * Spell functions + */ + +void spell_type_init(spell_type *spell, cptr name); +void spell_type_init_music(spell_type *spell, + s16b minimum_pval, + char* (*info_func)(), + casting_result (*effect_func)(int o_idx)); +void spell_type_init_music_lasting(spell_type *spell, + s16b minimum_pval, + char* (*info_func)(), + casting_result (*effect_func)(int o_idx), + int (*lasting_func)()); +void spell_type_init_mage(spell_type *spell, + random_type random_type, + s32b school_idx, + char* (*info_func)(), + casting_result (*effect_func)(int o_idx)); +void spell_type_init_priest(spell_type *spell, + s32b school_idx, + char* (*info_func)(), + casting_result (*effect_func)(int o_idx)); +void spell_type_init_device(spell_type *spell, + char* (*info_func)(), + casting_result (*effect_func)(int o_idx)); +void spell_type_init_demonology(spell_type *spell, + char* (*info_func)(), + casting_result (*effect_func)(int o_idx)); +void spell_type_init_geomancy(spell_type *spell, + char* (*info_func)(), + casting_result (*effect_func)(int o_idx), + bool_ (*depend_func)()); + +void spell_type_set_activation_timeout(spell_type *spell, cptr timeout_s); +void spell_type_set_inertia(spell_type *spell, s32b difficulty, s32b delay); +void spell_type_set_difficulty(spell_type *spell, byte skill_level, s32b failure_rate); +void spell_type_set_mana(spell_type *spell, s32b min, s32b max); +void spell_type_set_castable_while_blind(spell_type *spell, bool_ value); +void spell_type_set_castable_while_confused(spell_type *spell, bool_ value); +void spell_type_describe(spell_type *spell, cptr line); + +void spell_type_add_school(spell_type *spell, s32b school_idx); + +void spell_type_set_device_charges(spell_type *spell, cptr charges_s); +void spell_type_add_device_allocation(spell_type *spell, struct device_allocation *a); + +spell_type *spell_type_new(cptr name); + +int spell_type_produce_effect_lasting(spell_type *spell); +casting_result spell_type_produce_effect(spell_type *spell, int o_idx); +cptr spell_type_name(spell_type *spell); +int spell_type_skill_level(spell_type *spell); +void spell_type_description_foreach(spell_type *spell, void (*callback)(void *data, cptr text), void *data); +long spell_type_roll_charges(spell_type *spell); +void spell_type_activation_description(spell_type *spell, char *buf); +int spell_type_activation_roll_timeout(spell_type *spell); +struct device_allocation *spell_type_device_allocation(spell_type *spell, byte tval); +bool_ spell_type_uses_piety_to_cast(spell_type *spell); +bool_ spell_type_castable_while_blind(spell_type *spell); +bool_ spell_type_castable_while_confused(spell_type *spell); +s16b spell_type_minimum_pval(spell_type *spell); +s16b spell_type_random_type(spell_type *spell); +bool_ spell_type_school_foreach(spell_type *spell, bool_ (*callback)(void *data, s32b school_idx), void *data); +bool_ spell_type_inertia(spell_type *spell, s32b *difficulty, s32b *delay); +s32b spell_type_failure_rate(spell_type *spell); +s16b spell_type_casting_stat(spell_type *spell); +cptr spell_type_info(spell_type *spell); +void spell_type_mana_range(spell_type *spell, struct range_type *range); +bool_ spell_type_dependencies_satisfied(spell_type *spell); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/src/spell_type_fwd.h b/src/spell_type_fwd.h new file mode 100644 index 00000000..4664592c --- /dev/null +++ b/src/spell_type_fwd.h @@ -0,0 +1,27 @@ +#ifndef H_ce003b12_cf58_444f_a927_5451f6dd8af1 +#define H_ce003b12_cf58_444f_a927_5451f6dd8af1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Spell effect function result + */ +typedef enum { + NO_CAST, /* Spell not cast; user aborted */ + CAST_OBVIOUS, /* Cast; caster discovers effect (devices) */ + CAST_HIDDEN /* Cast; caster does NOT discover effect (devices) */ +} casting_result; + +/* + * Forward declaration of the spell_type + */ +typedef struct spell_type spell_type; +struct spell_type; + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/src/spells1.c b/src/spells1.c index e82d708a..9981f2be 100644 --- a/src/spells1.c +++ b/src/spells1.c @@ -12,6 +12,8 @@ #include "angband.h" +#include "spell_type.h" + /* 1/x chance of reducing stats (for elemental attacks) */ #define HURT_CHANCE 32 @@ -1258,7 +1260,7 @@ void spellbinder_trigger() cmsg_print(TERM_L_GREEN, "The spellbinder is triggered!"); for (i = 0; i < p_ptr->spellbinder_num; i++) { - msg_format("Triggering spell %s.", school_spells[p_ptr->spellbinder[i]].name); + msg_format("Triggering spell %s.", spell_type_name(spell_at(p_ptr->spellbinder[i]))); lua_cast_school_spell(p_ptr->spellbinder[i], TRUE); } p_ptr->spellbinder_num = 0; diff --git a/src/spells3.c b/src/spells3.c index bb67ac61..269e861a 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -2,6 +2,8 @@ #include +#include "spell_type.h" + s32b NOXIOUSCLOUD = -1; /* Identifier */ s32b AIRWINGS = -1; /* Identifier */ s32b INVISIBILITY; @@ -2357,7 +2359,7 @@ casting_result meta_spellbinder(int item) msg_print("With the spells: "); for (i = 0; i < p_ptr->spellbinder_num; i++) { - msg_print(school_spells[p_ptr->spellbinder[i]].name); + msg_print(spell_type_name(spell_at(p_ptr->spellbinder[i]))); } /* Doesn't cost anything */ @@ -2400,7 +2402,7 @@ casting_result meta_spellbinder(int item) p_ptr->spellbinder_num = 0; return CAST_OBVIOUS; } else { - if (school_spells[s].skill_level > 7 + get_level_s(SPELLBINDER, 35)) + if (spell_type_skill_level(spell_at(s)) > 7 + get_level_s(SPELLBINDER, 35)) { msg_format("You are only allowed spells with a base level of " FMTs32b ".", (7 + get_level_s(SPELLBINDER, 35))); return CAST_OBVIOUS; @@ -2503,7 +2505,7 @@ void meta_inertia_control_hook_birth_objects() casting_result meta_inertia_control(int item) { - s32b s; + s32b s, difficulty, delay; spell_type *spell; if (p_ptr->inertia_controlled_spell != -1) @@ -2522,27 +2524,26 @@ casting_result meta_inertia_control(int item) spell = spell_at(s); - if ((spell->inertia_difficulty < 0) || - (spell->inertia_delay < 0)) + if (!spell_type_inertia(spell, &difficulty, &delay)) { msg_print("This spell inertia flow can not be controlled."); stop_inertia_controlled_spell(); return NO_CAST; } - if (spell->inertia_difficulty > get_level_s(INERTIA_CONTROL, 10)) + if (difficulty > get_level_s(INERTIA_CONTROL, 10)) { - msg_format("This spell inertia flow(%d) is too strong to be controlled by your current spell.", spell->inertia_difficulty); + msg_format("This spell inertia flow(" FMTs32b ") is too strong to be controlled by your current spell.", difficulty); stop_inertia_controlled_spell(); return NO_CAST; } p_ptr->inertia_controlled_spell = s; TIMER_INERTIA_CONTROL->enabled = TRUE; - TIMER_INERTIA_CONTROL->delay = spell->inertia_delay; - TIMER_INERTIA_CONTROL->countdown = TIMER_INERTIA_CONTROL->delay; + TIMER_INERTIA_CONTROL->delay = delay; + TIMER_INERTIA_CONTROL->countdown = delay; p_ptr->update |= PU_MANA; - msg_format("Inertia flow controlling spell %s.", school_spells[s].name); + msg_format("Inertia flow controlling spell %s.", spell_type_name(spell_at(s))); return CAST_OBVIOUS; } @@ -2938,6 +2939,20 @@ char *tulkas_whirlwind_info() return ""; } +static bool_ check_school_is_udun(void *data, s32b school_idx) +{ + int *count = (int *) data; + + if ((school_idx == SCHOOL_UDUN) || + (school_idx == SCHOOL_MELKOR)) + { + (*count)++; + } + + /* Keep going */ + return TRUE; +} + /* Return the number of Udun/Melkor spells in a given book */ int udun_in_book(s32b sval, s32b pval) { @@ -2957,20 +2972,7 @@ int udun_in_book(s32b sval, s32b pval) spell_idx = sglib_spell_idx_list_it_next(&it)) { spell_type *spell = spell_at(spell_idx->i); - school_idx *school_idx = NULL; - struct sglib_school_idx_iterator sit; - - for (school_idx = sglib_school_idx_it_init(&sit, spell->schools); - school_idx != NULL; - school_idx = sglib_school_idx_it_next(&sit)) - { - int sch = school_idx->i; - if ((sch == SCHOOL_UDUN) || - (sch == SCHOOL_MELKOR)) - { - count++; - } - } + spell_type_school_foreach(spell, check_school_is_udun, &count); } return count; @@ -2996,7 +2998,7 @@ int levels_in_book(s32b sval, s32b pval) s32b s = spell_idx->i; spell_type *spell = spell_at(s); - levels += spell->skill_level; + levels += spell_type_skill_level(spell); } return levels; diff --git a/src/spells4.c b/src/spells4.c index f3809b7b..c977742d 100644 --- a/src/spells4.c +++ b/src/spells4.c @@ -2,6 +2,8 @@ #include +#include "spell_type.h" + school_book_type school_books[SCHOOL_BOOKS_SIZE]; s32b SCHOOL_AIR; @@ -37,52 +39,9 @@ static int compare_spell_idx(spell_idx_list *a, spell_idx_list *b) SGLIB_DEFINE_LIST_FUNCTIONS(spell_idx_list, compare_spell_idx, next); -static int compare_school_idx(school_idx *a, school_idx *b) -{ - return SGLIB_NUMERIC_COMPARATOR(a->i, b->i); -} - -SGLIB_DEFINE_LIST_FUNCTIONS(school_idx, compare_school_idx, next); - -void school_idx_init(school_idx *e, s32b i) -{ - assert(e != NULL); - - e->i = i; - e->next = NULL; -} - -school_idx *school_idx_new(s32b i) -{ - school_idx *e = malloc(sizeof(school_idx)); - assert(e != NULL); - - school_idx_init(e, i); - - return e; -} - -void school_idx_add_new(school_idx **list, s32b i) -{ - school_idx *e = school_idx_new(i); - assert(e != NULL); - - sglib_school_idx_add(list, e); -} - static bool_ uses_piety_to_cast(int s) { - return spell_at(s)->casting_type == USE_PIETY; -} - -static bool_ castable_while_blind(int s) -{ - return spell_at(s)->castable_while_blind; -} - -static bool_ castable_while_confused(int s) -{ - return spell_at(s)->castable_while_confused; + return spell_type_uses_piety_to_cast(spell_at(s)); } /** Describe what type of energy the spell uses for casting */ @@ -110,31 +69,36 @@ s32b get_power(s32b s) return uses_piety_to_cast(s) ? p_ptr->grace : p_ptr->csp; } +static void print_spell_desc_callback(void *data, cptr text) +{ + int *y = (int *) data; + + c_prt(TERM_L_BLUE, text, *y, 0); + (*y) += 1; +} + /* Output the describtion when it is used as a spell */ void print_spell_desc(int s, int y) { - string_list *sl; - struct sglib_string_list_iterator it; + spell_type *spell = spell_at(s); - for (sl = sglib_string_list_it_init(&it, school_spells[s].description); - sl != NULL; - sl = sglib_string_list_it_next(&it)) - { - c_prt(TERM_L_BLUE, sl->s, y, 0); - y++; - } + spell_type_description_foreach(spell, + print_spell_desc_callback, + &y); - if (uses_piety_to_cast(s)) + if (spell_type_uses_piety_to_cast(spell)) { c_prt(TERM_L_WHITE, "It uses piety to cast.", y, 0); y++; } - if (castable_while_blind(s)) + + if (spell_type_castable_while_blind(spell)) { c_prt(TERM_ORANGE, "It is castable even while blinded.", y, 0); y++; } - if (castable_while_confused(s)) + + if (spell_type_castable_while_confused(spell)) { c_prt(TERM_ORANGE, "It is castable even while confused.", y, 0); y++; @@ -478,30 +442,30 @@ void random_book_setup(s16b sval, s32b spell_idx) } } -static void spell_school_name(char *buf, spell_type *spell) +static bool_ spell_school_name_callback(void *data, s32b sch) { - school_idx *school_idx = NULL; - struct sglib_school_idx_iterator sit; - bool_ first = TRUE; - - buf[0] = '\0'; + school_type *school = school_at(sch); + char *buf = (char *) data; - for (school_idx = sglib_school_idx_it_init(&sit, spell->schools); - school_idx != NULL; - school_idx = sglib_school_idx_it_next(&sit)) + /* Add separator? */ + if (buf[0] != '\0') { - int sch = school_idx->i; - school_type *school = school_at(sch); - /* Add separator? */ - if (!first) - { - strcat(buf, "/"); - } - first = FALSE; - - /* Add school name */ - strcat(buf, school->name); + strcat(buf, "/"); } + + /* Add school name */ + strcat(buf, school->name); + + /* Keep going */ + return TRUE; +} + +static void spell_school_name(char *buf, spell_type *spell) +{ + buf[0] = '\0'; + spell_type_school_foreach(spell, + spell_school_name_callback, + buf); } int print_spell(cptr label_, byte color, int y, s32b s) @@ -510,7 +474,7 @@ int print_spell(cptr label_, byte color, int y, s32b s) bool_ na; spell_type *spell = spell_at(s); char sch_str[128]; - cptr spell_info = get_spell_info(s); + cptr spell_info = spell_type_info(spell); cptr label = (label_ == NULL) ? "" : label_; char level_str[8] = "n/a"; char buf[128]; @@ -525,7 +489,7 @@ int print_spell(cptr label_, byte color, int y, s32b s) sprintf(buf, "%s%-20s%-16s %s %4d %3d%% %s", label, - school_spells[s].name, + spell_type_name(spell_at(s)), sch_str, level_str, get_mana(s), @@ -575,16 +539,10 @@ int print_book(s16b sval, s32b pval, object_type *obj) return y; } -static bool_ call_spell_function(s32b s) -{ - spell_type *spell = spell_at(s); - assert(spell->effect_func != NULL); - return (spell->effect_func(-1) != NO_CAST); -} - void lua_cast_school_spell(s32b s, bool_ no_cost) { bool_ use = FALSE; + spell_type *spell = spell_at(s); /* No magic? */ if (p_ptr->antimagic > 0) @@ -604,14 +562,16 @@ void lua_cast_school_spell(s32b s, bool_ no_cost) if (!no_cost) { /* Require lite */ - if (!castable_while_blind(s) && ((p_ptr->blind > 0) || no_lite())) + if (!spell_type_castable_while_blind(spell) && + ((p_ptr->blind > 0) || no_lite())) { msg_print("You cannot see!"); return; } /* Not when confused */ - if (!castable_while_confused(s) && (p_ptr->confused > 0)) + if (!spell_type_castable_while_confused(spell) && + (p_ptr->confused > 0)) { msg_print("You are too confused!"); return; @@ -634,7 +594,7 @@ void lua_cast_school_spell(s32b s, bool_ no_cost) /* Invoke the spell effect */ if (!magik(spell_chance(s))) { - use = call_spell_function(s); + use = (spell_type_produce_effect(spell, -1) != NO_CAST); } else { @@ -652,7 +612,7 @@ void lua_cast_school_spell(s32b s, bool_ no_cost) } else { - call_spell_function(s); + spell_type_produce_effect(spell, -1); } /* Use the mana/piety */ @@ -670,11 +630,6 @@ void lua_cast_school_spell(s32b s, bool_ no_cost) p_ptr->window |= PW_PLAYER; } -void spell_description_add_line(s32b spell_idx, cptr line) -{ - string_list_append(&school_spells[spell_idx].description, line); -} - void device_allocation_init(device_allocation *device_allocation, byte tval) { assert(device_allocation != NULL); diff --git a/src/spells5.c b/src/spells5.c index d2d9eda2..7ad0d3b9 100644 --- a/src/spells5.c +++ b/src/spells5.c @@ -1,45 +1,15 @@ #include -#include - -typedef enum { RANDOM, NO_RANDOM } random_type; - -static void spell_inertia_init(spell_type *spell, s32b diff, s32b delay) -{ - spell->inertia_difficulty = diff; - spell->inertia_delay = delay; -} - -static void spell_init(spell_type *spell) -{ - memset(spell, 0, sizeof(spell_type)); - - spell->name = NULL; - spell->description = NULL; - spell->effect_func = NULL; - spell->info_func = NULL; - spell->lasting_func = NULL; - spell->depend_func = NULL; - - spell->device_allocation = NULL; - spell->schools = NULL; - spell->random_type = -1; - - spell_inertia_init(spell, -1, -1); +#include - spell->castable_while_blind = FALSE; - spell->castable_while_confused = FALSE; -} +#include "spell_type.h" static spell_type *spell_new(s32b *index, cptr id, cptr name) { assert(school_spells_count < SCHOOL_SPELLS_MAX); - spell_type *spell = &school_spells[school_spells_count]; - - spell_init(spell); - spell->name = name; - + spell_type *spell = spell_type_new(name); + school_spells[school_spells_count] = spell; *index = school_spells_count; school_spells_count++; @@ -51,7 +21,7 @@ spell_type *spell_at(s32b index) assert(index >= 0); assert(index < school_spells_count); - return &school_spells[index]; + return school_spells[index]; } int find_spell(cptr name) @@ -60,8 +30,7 @@ int find_spell(cptr name) for (i = 0; i < school_spells_count; i++) { - spell_type *spell = spell_at(i); - if (streq(spell->name, name)) + if (streq(spell_type_name(spell_at(i)), name)) { return i; } @@ -80,8 +49,8 @@ s16b get_random_spell(s16b random_type, int level) s16b spl = rand_int(school_spells_count); spell_type *spell = spell_at(spl); - if ((can_spell_random(spl) == random_type) && - (rand_int(spell->skill_level * 3) < level)) + if ((spell_type_random_type(spell) == random_type) && + (rand_int(spell_type_skill_level(spell) * 3) < level)) { return spl; } @@ -90,106 +59,47 @@ s16b get_random_spell(s16b random_type, int level) return -1; } -bool_ check_spell_depends(spell_type *spell) -{ - assert(spell != NULL); - - if (spell->depend_func != NULL) { - return spell->depend_func(); - } else { - return TRUE; - } -} - -static void spell_init_music(spell_type *spell, s16b minimum_pval) -{ - assert(spell != NULL); - /* Use spell points, but CHR for success/failure calculations */ - spell->casting_type = USE_SPELL_POINTS; - spell->casting_stat = A_CHR; - spell->random_type = SKILL_MUSIC; - spell->minimum_pval = minimum_pval; - /* Add school */ - school_idx_add_new(&spell->schools, SCHOOL_MUSIC); -} - -static void spell_init_mage(spell_type *spell, random_type random_type) -{ - assert(spell != NULL); - - spell->casting_type = USE_SPELL_POINTS; - spell->casting_stat = A_INT; - - switch (random_type) - { - case RANDOM: - spell->random_type = SKILL_MAGIC; - break; - case NO_RANDOM: - spell->random_type = -1; - break; - default: - /* Cannot happen */ - assert(FALSE); - } -} - -static void spell_init_priest(spell_type *spell) -{ - assert(spell != NULL); - - spell->random_type = SKILL_SPIRITUALITY; - spell->casting_type = USE_PIETY; - spell->casting_stat = A_WIS; -} - static void spells_init_tome() { { spell_type *spell = spell_new(&DEVICE_LEBOHAUM, "DEVICE_LEBOHAUM", "Artifact Lebauhaum"); - dice_parse_checked(&spell->activation_duration, "3"); - string_list_append(&spell->description, "sing a cheerful song"); - school_idx_add_new(&spell->schools, SCHOOL_DEVICE); - range_init(&spell->mana_range, 0, 0); - spell->info_func = device_lebohaum_info; - spell->effect_func = device_lebohaum; - spell->failure_rate = 0; - spell->skill_level = 1; - spell_init_mage(spell, NO_RANDOM); + spell_type_set_activation_timeout(spell, "3"); + spell_type_describe(spell, "sing a cheerful song"); + spell_type_set_mana(spell, 0, 0); + spell_type_set_difficulty(spell, 1, 0); + spell_type_init_device(spell, + device_lebohaum_info, + device_lebohaum); } { spell_type *spell = spell_new(&DEVICE_DURANDIL, "DEVICE_DURANDIL", "Artifact Durandil"); - dice_parse_checked(&spell->activation_duration, "3"); - string_list_append(&spell->description, "sing a cheerful song"); - school_idx_add_new(&spell->schools, SCHOOL_DEVICE); - range_init(&spell->mana_range, 0, 0); - spell->info_func = device_durandil_info; - spell->effect_func = device_durandil; - spell->failure_rate = 0; - spell->skill_level = 1; - spell_init_mage(spell, NO_RANDOM); + spell_type_set_activation_timeout(spell, "3"); + spell_type_describe(spell, "sing a cheerful song"); + spell_type_set_mana(spell, 0, 0); + spell_type_set_difficulty(spell, 1, 0); + spell_type_init_device(spell, + device_durandil_info, + device_durandil); } { spell_type *spell = spell_new(&DEVICE_THUNDERLORDS, "DEVICE_THUNDERLORDS", "Artifact Thunderlords"); - string_list_append(&spell->description, "A thunderlord will appear to transport you quickly to the surface."); - school_idx_add_new(&spell->schools, SCHOOL_DEVICE); - range_init(&spell->mana_range, 1, 1); - spell->info_func = device_thunderlords_info; - spell->effect_func = device_thunderlords; - spell->failure_rate = 20; - spell->skill_level = 1; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "A thunderlord will appear to transport you quickly to the surface."); + spell_type_set_mana(spell, 1, 1); + spell_type_set_difficulty(spell, 1, 20); + spell_type_init_device(spell, + device_thunderlords_info, + device_thunderlords); - dice_parse_checked(&spell->device_charges, "3+d3"); + spell_type_set_device_charges(spell, "3+d3"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 999; range_init(&device_allocation->base_level, 1, 1); range_init(&device_allocation->max_level, 1, 1); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } } @@ -198,2139 +108,2073 @@ static void spells_init_theme() { { spell_type *spell = spell_new(&GROW_ATHELAS, "GROW_ATHELAS", "Grow Athelas"); - string_list_append(&spell->description, "Cures the Black Breath"); - school_idx_add_new(&spell->schools, SCHOOL_NATURE); - range_init(&spell->mana_range, 60, 100); - spell->info_func = nature_grow_athelas_info; - spell->effect_func = nature_grow_athelas; - spell->failure_rate = 95; - spell->skill_level = 30; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Cures the Black Breath"); + spell_type_set_mana(spell, 60, 100); + spell_type_set_difficulty(spell, 30, 95); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_NATURE, + nature_grow_athelas_info, + nature_grow_athelas); - dice_parse_checked(&spell->device_charges, "1+d3"); + spell_type_set_device_charges(spell, "1+d3"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 85; range_init(&device_allocation->base_level, 1, 5); range_init(&device_allocation->max_level, 15, 45); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&AULE_FIREBRAND, "AULE_FIREBRAND", "Firebrand"); - string_list_append(&spell->description, "Imbues your melee weapon with fire to deal more damage"); - string_list_append(&spell->description, "At level 15 it spreads over a 1 radius zone around your target"); - string_list_append(&spell->description, "At level 30 it deals holy fire damage"); - school_idx_add_new(&spell->schools, SCHOOL_AULE); - range_init(&spell->mana_range, 10, 100); - spell->info_func = aule_firebrand_info; - spell->effect_func = aule_firebrand_spell; - spell->failure_rate = 20; - spell->skill_level = 1; - spell_init_priest(spell); + spell_type_describe(spell, "Imbues your melee weapon with fire to deal more damage"); + spell_type_describe(spell, "At level 15 it spreads over a 1 radius zone around your target"); + spell_type_describe(spell, "At level 30 it deals holy fire damage"); + spell_type_set_mana(spell, 10, 100); + spell_type_set_difficulty(spell, 1, 20); + spell_type_init_priest(spell, + SCHOOL_AULE, + aule_firebrand_info, + aule_firebrand_spell); } { spell_type *spell = spell_new(&AULE_ENCHANT_WEAPON, "AULE_ENCHANT_WEAPON", "Enchant Weapon"); - string_list_append(&spell->description, "Tries to enchant a weapon to-hit"); - string_list_append(&spell->description, "At level 5 it also enchants to-dam"); - string_list_append(&spell->description, "At level 45 it enhances the special powers of magical weapons"); - string_list_append(&spell->description, "The might of the enchantment increases with the level"); - school_idx_add_new(&spell->schools, SCHOOL_AULE); - range_init(&spell->mana_range, 100, 200); - spell->info_func = aule_enchant_weapon_info; - spell->effect_func = aule_enchant_weapon_spell; - spell->failure_rate = 20; - spell->skill_level = 10; - spell_init_priest(spell); + spell_type_describe(spell, "Tries to enchant a weapon to-hit"); + spell_type_describe(spell, "At level 5 it also enchants to-dam"); + spell_type_describe(spell, "At level 45 it enhances the special powers of magical weapons"); + spell_type_describe(spell, "The might of the enchantment increases with the level"); + spell_type_set_mana(spell, 100, 200); + spell_type_set_difficulty(spell, 10, 20); + spell_type_init_priest(spell, + SCHOOL_AULE, + aule_enchant_weapon_info, + aule_enchant_weapon_spell); } { spell_type *spell = spell_new(&AULE_ENCHANT_ARMOUR, "AULE_ENCHANT_ARMOUR", "Enchant Armour"); - string_list_append(&spell->description, "Tries to enchant a piece of armour"); - string_list_append(&spell->description, "At level 20 it also enchants to-hit and to-dam"); - string_list_append(&spell->description, "At level 40 it enhances the special powers of magical armour"); - string_list_append(&spell->description, "The might of the enchantment increases with the level"); - school_idx_add_new(&spell->schools, SCHOOL_AULE); - range_init(&spell->mana_range, 100, 200); - spell->info_func = aule_enchant_armour_info; - spell->effect_func = aule_enchant_armour_spell; - spell->failure_rate = 20; - spell->skill_level = 15; - spell_init_priest(spell); + spell_type_describe(spell, "Tries to enchant a piece of armour"); + spell_type_describe(spell, "At level 20 it also enchants to-hit and to-dam"); + spell_type_describe(spell, "At level 40 it enhances the special powers of magical armour"); + spell_type_describe(spell, "The might of the enchantment increases with the level"); + spell_type_set_mana(spell, 100, 200); + spell_type_set_difficulty(spell, 15, 20); + spell_type_init_priest(spell, + SCHOOL_AULE, + aule_enchant_armour_info, + aule_enchant_armour_spell); } { spell_type *spell = spell_new(&AULE_CHILD, "AULE_CHILD", "Child of Aule"); - string_list_append(&spell->description, "Summons a levelled Dwarven warrior to help you battle the forces"); - string_list_append(&spell->description, "of Morgoth"); - school_idx_add_new(&spell->schools, SCHOOL_AULE); - range_init(&spell->mana_range, 200, 500); - spell->info_func = aule_child_info; - spell->effect_func = aule_child_spell; - spell->failure_rate = 40; - spell->skill_level = 20; - spell_init_priest(spell); + spell_type_describe(spell, "Summons a levelled Dwarven warrior to help you battle the forces"); + spell_type_describe(spell, "of Morgoth"); + spell_type_set_mana(spell, 200, 500); + spell_type_set_difficulty(spell, 20, 40); + spell_type_init_priest(spell, + SCHOOL_AULE, + aule_child_info, + aule_child_spell); } { spell_type *spell = spell_new(&VARDA_LIGHT_VALINOR, "VARDA_LIGHT_VALINOR", "Light of Valinor"); - string_list_append(&spell->description, "Lights a room"); - string_list_append(&spell->description, "At level 3 it starts damaging monsters"); - string_list_append(&spell->description, "At level 15 it starts creating a more powerful kind of light"); - school_idx_add_new(&spell->schools, SCHOOL_VARDA); - range_init(&spell->mana_range, 1, 100); - spell->info_func = varda_light_of_valinor_info; - spell->effect_func = varda_light_of_valinor_spell; - spell->failure_rate = 20; - spell->skill_level = 1; - spell_init_priest(spell); + spell_type_describe(spell, "Lights a room"); + spell_type_describe(spell, "At level 3 it starts damaging monsters"); + spell_type_describe(spell, "At level 15 it starts creating a more powerful kind of light"); + spell_type_set_mana(spell, 1, 100); + spell_type_set_difficulty(spell, 1, 20); + spell_type_init_priest(spell, + SCHOOL_VARDA, + varda_light_of_valinor_info, + varda_light_of_valinor_spell); } { spell_type *spell = spell_new(&VARDA_CALL_ALMAREN, "VARDA_CALL_ALMAREN", "Call of Almaren"); - string_list_append(&spell->description, "Banishes evil beings"); - string_list_append(&spell->description, "At level 20 it dispels evil beings"); - school_idx_add_new(&spell->schools, SCHOOL_VARDA); - range_init(&spell->mana_range, 5, 150); - spell->info_func = varda_call_of_almaren_info; - spell->effect_func = varda_call_of_almaren_spell; - spell->failure_rate = 20; - spell->skill_level = 10; - spell_init_priest(spell); + spell_type_describe(spell, "Banishes evil beings"); + spell_type_describe(spell, "At level 20 it dispels evil beings"); + spell_type_set_mana(spell, 5, 150); + spell_type_set_difficulty(spell, 10, 20); + spell_type_init_priest(spell, + SCHOOL_VARDA, + varda_call_of_almaren_info, + varda_call_of_almaren_spell); } { spell_type *spell = spell_new(&VARDA_EVENSTAR, "VARDA_EVENSTAR", "Evenstar"); - string_list_append(&spell->description, "Maps and lights the whole level."); - string_list_append(&spell->description, "At level 40 it maps and lights the whole level,"); - string_list_append(&spell->description, "in addition to letting you know yourself better"); - string_list_append(&spell->description, "and identifying your whole pack."); - school_idx_add_new(&spell->schools, SCHOOL_VARDA); - range_init(&spell->mana_range, 20, 200); - spell->info_func = varda_evenstar_info; - spell->effect_func = varda_evenstar_spell; - spell->failure_rate = 20; - spell->skill_level = 20; - spell_init_priest(spell); + spell_type_describe(spell, "Maps and lights the whole level."); + spell_type_describe(spell, "At level 40 it maps and lights the whole level,"); + spell_type_describe(spell, "in addition to letting you know yourself better"); + spell_type_describe(spell, "and identifying your whole pack."); + spell_type_set_mana(spell, 20, 200); + spell_type_set_difficulty(spell, 20, 20); + spell_type_init_priest(spell, + SCHOOL_VARDA, + varda_evenstar_info, + varda_evenstar_spell); } { spell_type *spell = spell_new(&VARDA_STARKINDLER, "VARDA_STARKINDLER", "Star Kindler"); - string_list_append(&spell->description, "Does multiple bursts of light damage."); - string_list_append(&spell->description, "The damage increases with level."); - school_idx_add_new(&spell->schools, SCHOOL_VARDA); - range_init(&spell->mana_range, 50, 250); - spell->info_func = varda_star_kindler_info; - spell->effect_func = varda_star_kindler_spell; - spell->failure_rate = 20; - spell->skill_level = 30; - spell_init_priest(spell); + spell_type_describe(spell, "Does multiple bursts of light damage."); + spell_type_describe(spell, "The damage increases with level."); + spell_type_set_mana(spell, 50, 250); + spell_type_set_difficulty(spell, 30, 20); + spell_type_init_priest(spell, + SCHOOL_VARDA, + varda_star_kindler_info, + varda_star_kindler_spell); } { spell_type *spell = spell_new(&ULMO_BELEGAER, "ULMO_BELEGAER", "Song of Belegaer"); - string_list_append(&spell->description, "Channels the power of the Great Sea into your fingertips."); - string_list_append(&spell->description, "Sometimes it can blast through its first target."); - school_idx_add_new(&spell->schools, SCHOOL_ULMO); - range_init(&spell->mana_range, 1, 100); - spell->info_func = ulmo_song_of_belegaer_info; - spell->effect_func = ulmo_song_of_belegaer_spell; - spell->failure_rate = 25; - spell->skill_level = 1; - spell_init_priest(spell); + spell_type_describe(spell, "Channels the power of the Great Sea into your fingertips."); + spell_type_describe(spell, "Sometimes it can blast through its first target."); + spell_type_set_mana(spell, 1, 100); + spell_type_set_difficulty(spell, 1, 25); + spell_type_init_priest(spell, + SCHOOL_ULMO, + ulmo_song_of_belegaer_info, + ulmo_song_of_belegaer_spell); } { spell_type *spell = spell_new(&ULMO_DRAUGHT_ULMONAN, "ULMO_DRAUGHT_ULMONAN", "Draught of Ulmonan"); - string_list_append(&spell->description, "Fills you with a draught with powerful curing effects,"); - string_list_append(&spell->description, "prepared by Ulmo himself."); - string_list_append(&spell->description, "Level 1: blindness, poison, cuts and stunning"); - string_list_append(&spell->description, "Level 10: drained STR, DEX and CON"); - string_list_append(&spell->description, "Level 20: parasites and mimicry"); - school_idx_add_new(&spell->schools, SCHOOL_ULMO); - range_init(&spell->mana_range, 25, 200); - spell->info_func = ulmo_draught_of_ulmonan_info; - spell->effect_func = ulmo_draught_of_ulmonan_spell; - spell->failure_rate = 50; - spell->skill_level = 15; - spell_init_priest(spell); + spell_type_describe(spell, "Fills you with a draught with powerful curing effects,"); + spell_type_describe(spell, "prepared by Ulmo himself."); + spell_type_describe(spell, "Level 1: blindness, poison, cuts and stunning"); + spell_type_describe(spell, "Level 10: drained STR, DEX and CON"); + spell_type_describe(spell, "Level 20: parasites and mimicry"); + spell_type_set_mana(spell, 25, 200); + spell_type_set_difficulty(spell, 15, 50); + spell_type_init_priest(spell, + SCHOOL_ULMO, + ulmo_draught_of_ulmonan_info, + ulmo_draught_of_ulmonan_spell); } { spell_type *spell = spell_new(&ULMO_CALL_ULUMURI, "ULMO_CALL_ULUMURI", "Call of the Ulumuri"); - string_list_append(&spell->description, "Summons a leveled water spirit or elemental"); - string_list_append(&spell->description, "to fight for you"); - school_idx_add_new(&spell->schools, SCHOOL_ULMO); - range_init(&spell->mana_range, 50, 300); - spell->info_func = ulmo_call_of_the_ulumuri_info; - spell->effect_func = ulmo_call_of_the_ulumuri_spell; - spell->failure_rate = 75; - spell->skill_level = 20; - spell_init_priest(spell); + spell_type_describe(spell, "Summons a leveled water spirit or elemental"); + spell_type_describe(spell, "to fight for you"); + spell_type_set_mana(spell, 50, 300); + spell_type_set_difficulty(spell, 20, 75); + spell_type_init_priest(spell, + SCHOOL_ULMO, + ulmo_call_of_the_ulumuri_info, + ulmo_call_of_the_ulumuri_spell); } { spell_type *spell = spell_new(&ULMO_WRATH, "ULMO_WRATH", "Wrath of Ulmo"); - string_list_append(&spell->description, "Conjures up a sea storm."); - string_list_append(&spell->description, "At level 30 it turns into a more forceful storm."); - school_idx_add_new(&spell->schools, SCHOOL_ULMO); - range_init(&spell->mana_range, 100, 400); - spell->info_func = ulmo_wrath_of_ulmo_info; - spell->effect_func = ulmo_wrath_of_ulmo_spell; - spell->failure_rate = 95; - spell->skill_level = 30; - spell_init_priest(spell); + spell_type_describe(spell, "Conjures up a sea storm."); + spell_type_describe(spell, "At level 30 it turns into a more forceful storm."); + spell_type_set_mana(spell, 100, 400); + spell_type_set_difficulty(spell, 30, 95); + spell_type_init_priest(spell, + SCHOOL_ULMO, + ulmo_wrath_of_ulmo_info, + ulmo_wrath_of_ulmo_spell); } { spell_type *spell = spell_new(&MANDOS_TEARS_LUTHIEN, "MANDOS_TEARS_LUTHIEN", "Tears of Luthien"); - string_list_append(&spell->description, "Calls upon the spirit of Luthien to ask Mandos for healing and succour."); - school_idx_add_new(&spell->schools, SCHOOL_MANDOS); - range_init(&spell->mana_range, 10, 100); - spell->info_func = mandos_tears_of_luthien_info; - spell->effect_func = mandos_tears_of_luthien_spell; - spell->failure_rate = 25; - spell->skill_level = 5; - spell_init_priest(spell); + spell_type_describe(spell, "Calls upon the spirit of Luthien to ask Mandos for healing and succour."); + spell_type_set_mana(spell, 10, 100); + spell_type_set_difficulty(spell, 5, 25); + spell_type_init_priest(spell, + SCHOOL_MANDOS, + mandos_tears_of_luthien_info, + mandos_tears_of_luthien_spell); } { spell_type *spell = spell_new(&MANDOS_SPIRIT_FEANTURI, "MANDOS_SPIRIT_FEANTURI", "Feanturi"); - string_list_append(&spell->description, "Channels the power of Mandos to cure fear and confusion."); - string_list_append(&spell->description, "At level 20 it restores lost INT and WIS"); - string_list_append(&spell->description, "At level 30 it cures hallucinations and restores a percentage of lost sanity"); - school_idx_add_new(&spell->schools, SCHOOL_MANDOS); - range_init(&spell->mana_range, 40, 200); - spell->info_func = mandos_spirit_of_the_feanturi_info; - spell->effect_func = mandos_spirit_of_the_feanturi_spell; - spell->failure_rate = 50; - spell->skill_level = 10; - spell_init_priest(spell); + spell_type_describe(spell, "Channels the power of Mandos to cure fear and confusion."); + spell_type_describe(spell, "At level 20 it restores lost INT and WIS"); + spell_type_describe(spell, "At level 30 it cures hallucinations and restores a percentage of lost sanity"); + spell_type_set_mana(spell, 40, 200); + spell_type_set_difficulty(spell, 10, 50); + spell_type_init_priest(spell, + SCHOOL_MANDOS, + mandos_spirit_of_the_feanturi_info, + mandos_spirit_of_the_feanturi_spell); } { spell_type *spell = spell_new(&MANDOS_TALE_DOOM, "MANDOS_TALE_DOOM", "Tale of Doom"); - string_list_append(&spell->description, "Allows you to predict the future for a short time."); - school_idx_add_new(&spell->schools, SCHOOL_MANDOS); - range_init(&spell->mana_range, 60, 300); - spell->info_func = mandos_tale_of_doom_info; - spell->effect_func = mandos_tale_of_doom_spell; - spell->failure_rate = 75; - spell->skill_level = 25; - spell_init_priest(spell); + spell_type_describe(spell, "Allows you to predict the future for a short time."); + spell_type_set_mana(spell, 60, 300); + spell_type_set_difficulty(spell, 25, 75); + spell_type_init_priest(spell, + SCHOOL_MANDOS, + mandos_tale_of_doom_info, + mandos_tale_of_doom_spell); } { spell_type *spell = spell_new(&MANDOS_CALL_HALLS, "MANDOS_CALL_HALLS", "Call to the Halls"); - string_list_append(&spell->description, "Summons a leveled spirit from the Halls of Mandos"); - string_list_append(&spell->description, "to fight for you."); - school_idx_add_new(&spell->schools, SCHOOL_MANDOS); - range_init(&spell->mana_range, 80, 400); - spell->info_func = mandos_call_to_the_halls_info; - spell->effect_func = mandos_call_to_the_halls_spell; - spell->failure_rate = 95; - spell->skill_level = 30; - spell_init_priest(spell); + spell_type_describe(spell, "Summons a leveled spirit from the Halls of Mandos"); + spell_type_describe(spell, "to fight for you."); + spell_type_set_mana(spell, 80, 400); + spell_type_set_difficulty(spell, 30, 95); + spell_type_init_priest(spell, + SCHOOL_MANDOS, + mandos_call_to_the_halls_info, + mandos_call_to_the_halls_spell); } { spell_type *spell = spell_new(&DEVICE_THUNDERLORDS, "DEVICE_THUNDERLORDS", "Artifact Thunderlords"); - string_list_append(&spell->description, "An Eagle of Manwe will appear to transport you quickly to the town."); - school_idx_add_new(&spell->schools, SCHOOL_DEVICE); - range_init(&spell->mana_range, 1, 1); - spell->info_func = device_thunderlords_info; - spell->effect_func = device_thunderlords; - spell->failure_rate = 20; - spell->skill_level = 1; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "An Eagle of Manwe will appear to transport you quickly to the town."); + spell_type_set_mana(spell, 1, 1); + spell_type_set_difficulty(spell, 1, 20); + spell_type_init_device(spell, + device_thunderlords_info, + device_thunderlords); - dice_parse_checked(&spell->device_charges, "5+d5"); + spell_type_set_device_charges(spell, "5+d5"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 999; range_init(&device_allocation->base_level, 1, 1); range_init(&device_allocation->max_level, 1, 1); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&DEVICE_RADAGAST, "DEVICE_RADAGAST", "Artifact Radagast"); - dice_parse_checked(&spell->activation_duration, "15000"); - string_list_append(&spell->description, "purity and health"); - school_idx_add_new(&spell->schools, SCHOOL_DEVICE); - range_init(&spell->mana_range, 0, 0); - spell->info_func = device_radagast_info; - spell->effect_func = device_radagast; - spell->failure_rate = 10; - spell->skill_level = 1; - spell_init_mage(spell, NO_RANDOM); + spell_type_set_activation_timeout(spell, "15000"); + spell_type_describe(spell, "purity and health"); + spell_type_set_mana(spell, 0, 0); + spell_type_set_difficulty(spell, 1, 10); + spell_type_init_device(spell, + device_radagast_info, + device_radagast); } { spell_type *spell = spell_new(&DEVICE_VALAROMA, "DEVICE_VALAROMA", "Artifact Valaroma"); - dice_parse_checked(&spell->activation_duration, "250"); - string_list_append(&spell->description, "banish evil (level x5)"); - school_idx_add_new(&spell->schools, SCHOOL_DEVICE); - range_init(&spell->mana_range, 0, 0); - spell->info_func = device_valaroma_info; - spell->effect_func = device_valaroma; - spell->failure_rate = 25; - spell->skill_level = 1; - spell_init_mage(spell, NO_RANDOM); + spell_type_set_activation_timeout(spell, "250"); + spell_type_describe(spell, "banish evil (level x5)"); + spell_type_set_mana(spell, 0, 0); + spell_type_set_difficulty(spell, 1, 25); + spell_type_init_device(spell, + device_valaroma_info, + device_valaroma); } } void school_spells_init() { + /* Zero out spell array */ + { + int i = 0; + for (i = 0; i < SCHOOL_SPELLS_MAX; i++) + { + school_spells[i] = NULL; + } + } + + /* Spells */ { spell_type *spell = spell_new(&GLOBELIGHT, "GLOBELIGHT", "Globe of Light"); - string_list_append(&spell->description, "Creates a globe of pure light"); - string_list_append(&spell->description, "At level 3 it starts damaging monsters"); - string_list_append(&spell->description, "At level 15 it starts creating a more powerful kind of light"); - school_idx_add_new(&spell->schools, SCHOOL_FIRE); - range_init(&spell->mana_range, 2, 15); - spell_inertia_init(spell, 1, 40); - spell->info_func = fire_globe_of_light_info; - spell->effect_func = fire_globe_of_light; - spell->failure_rate = 10; - spell->skill_level = 1; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "10+d5"); + spell_type_describe(spell, "Creates a globe of pure light"); + spell_type_describe(spell, "At level 3 it starts damaging monsters"); + spell_type_describe(spell, "At level 15 it starts creating a more powerful kind of light"); + spell_type_set_mana(spell, 2, 15); + spell_type_set_inertia(spell, 1, 40); + spell_type_set_difficulty(spell, 1, 10); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_FIRE, + fire_globe_of_light_info, + fire_globe_of_light); + + spell_type_set_device_charges(spell, "10+d5"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 7; range_init(&device_allocation->base_level, 1, 15); range_init(&device_allocation->max_level, 10, 45); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&FIREFLASH, "FIREFLASH", "Fireflash"); - string_list_append(&spell->description, "Conjures a ball of fire to burn your foes to ashes"); - string_list_append(&spell->description, "At level 20 it turns into a ball of holy fire"); - school_idx_add_new(&spell->schools, SCHOOL_FIRE); - range_init(&spell->mana_range, 5, 70); - spell->info_func = fire_fireflash_info; - spell->effect_func = fire_fireflash; - spell->failure_rate = 35; - spell->skill_level = 10; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "5+d5"); + spell_type_describe(spell, "Conjures a ball of fire to burn your foes to ashes"); + spell_type_describe(spell, "At level 20 it turns into a ball of holy fire"); + spell_type_set_mana(spell, 5, 70); + spell_type_set_difficulty(spell, 10, 35); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_FIRE, + fire_fireflash_info, + fire_fireflash); + + spell_type_set_device_charges(spell, "5+d5"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 35; range_init(&device_allocation->base_level, 1, 15); range_init(&device_allocation->max_level, 15, 35); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&FIERYAURA, "FIERYAURA", "Fiery Shield"); - string_list_append(&spell->description, "Creates a shield of fierce flames around you"); - string_list_append(&spell->description, "At level 8 it turns into a greater kind of flame that can not be resisted"); - school_idx_add_new(&spell->schools, SCHOOL_FIRE); - range_init(&spell->mana_range, 20, 60); - spell_inertia_init(spell, 2, 15); - spell->info_func = fire_fiery_shield_info; - spell->effect_func = fire_fiery_shield; - spell->failure_rate = 50; - spell->skill_level = 20; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "3+d5"); + spell_type_describe(spell, "Creates a shield of fierce flames around you"); + spell_type_describe(spell, "At level 8 it turns into a greater kind of flame that can not be resisted"); + spell_type_set_mana(spell, 20, 60); + spell_type_set_inertia(spell, 2, 15); + spell_type_set_difficulty(spell, 20, 50); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_FIRE, + fire_fiery_shield_info, + fire_fiery_shield); + + spell_type_set_device_charges(spell, "3+d5"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 50; range_init(&device_allocation->base_level, 1, 10); range_init(&device_allocation->max_level, 5, 40); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&FIREWALL, "FIREWALL", "Firewall"); - string_list_append(&spell->description, "Creates a fiery wall to incinerate monsters stupid enough to attack you"); - string_list_append(&spell->description, "At level 6 it turns into a wall of hell fire"); - school_idx_add_new(&spell->schools, SCHOOL_FIRE); - range_init(&spell->mana_range, 25, 100); - spell->info_func = fire_firewall_info; - spell->effect_func = fire_firewall; - spell->failure_rate = 40; - spell->skill_level = 15; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "4+d5"); + spell_type_describe(spell, "Creates a fiery wall to incinerate monsters stupid enough to attack you"); + spell_type_describe(spell, "At level 6 it turns into a wall of hell fire"); + spell_type_set_mana(spell, 25, 100); + spell_type_set_difficulty(spell, 15, 40); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_FIRE, + fire_firewall_info, + fire_firewall); + + spell_type_set_device_charges(spell, "4+d5"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 55; range_init(&device_allocation->base_level, 1, 10); range_init(&device_allocation->max_level, 5, 40); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&FIREGOLEM, "FIREGOLEM", "Fire Golem"); - string_list_append(&spell->description, "Creates a fiery golem and controls it"); - string_list_append(&spell->description, "During the control the available keylist is:"); - string_list_append(&spell->description, "Movement keys: movement of the golem(depending on its speed"); - string_list_append(&spell->description, " it can move more than one square)"); - string_list_append(&spell->description, ", : pickup all items on the floor"); - string_list_append(&spell->description, "d : drop all carried items"); - string_list_append(&spell->description, "i : list all carried items"); - string_list_append(&spell->description, "m : end the possession/use golem powers"); - string_list_append(&spell->description, "Most of the other keys are disabled, you cannot interact with your"); - string_list_append(&spell->description, "real body while controlling the golem"); - string_list_append(&spell->description, "But to cast the spell you will need a lantern or a wooden torch to"); - string_list_append(&spell->description, "Create the golem from"); - school_idx_add_new(&spell->schools, SCHOOL_FIRE); - school_idx_add_new(&spell->schools, SCHOOL_MIND); - range_init(&spell->mana_range, 16, 70); - spell->info_func = fire_golem_info; - spell->effect_func = fire_golem; - spell->failure_rate = 40; - spell->skill_level = 7; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Creates a fiery golem and controls it"); + spell_type_describe(spell, "During the control the available keylist is:"); + spell_type_describe(spell, "Movement keys: movement of the golem(depending on its speed"); + spell_type_describe(spell, " it can move more than one square)"); + spell_type_describe(spell, ", : pickup all items on the floor"); + spell_type_describe(spell, "d : drop all carried items"); + spell_type_describe(spell, "i : list all carried items"); + spell_type_describe(spell, "m : end the possession/use golem powers"); + spell_type_describe(spell, "Most of the other keys are disabled, you cannot interact with your"); + spell_type_describe(spell, "real body while controlling the golem"); + spell_type_describe(spell, "But to cast the spell you will need a lantern or a wooden torch to"); + spell_type_describe(spell, "Create the golem from"); + spell_type_add_school(spell, SCHOOL_MIND); + spell_type_set_mana(spell, 16, 70); + spell_type_set_difficulty(spell, 7, 40); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_FIRE, + fire_golem_info, + fire_golem); } { spell_type *spell = spell_new(&MANATHRUST, "MANATHRUST", "Manathrust"); - string_list_append(&spell->description, "Conjures up mana into a powerful bolt"); - string_list_append(&spell->description, "The damage is irresistible and will increase with level"); - school_idx_add_new(&spell->schools, SCHOOL_MANA); - range_init(&spell->mana_range, 1, 25); - spell->info_func = mana_manathrust_info; - spell->effect_func = mana_manathrust; - spell->failure_rate = 10; - spell->skill_level = 1; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "7+d10"); + spell_type_describe(spell, "Conjures up mana into a powerful bolt"); + spell_type_describe(spell, "The damage is irresistible and will increase with level"); + spell_type_set_mana(spell, 1, 25); + spell_type_set_difficulty(spell, 1, 10); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_MANA, + mana_manathrust_info, + mana_manathrust); + + spell_type_set_device_charges(spell, "7+d10"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 5; range_init(&device_allocation->base_level, 1, 20); range_init(&device_allocation->max_level, 15, 33); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&DELCURSES, "DELCURSES", "Remove Curses"); - string_list_append(&spell->description, "Remove curses of worn objects"); - string_list_append(&spell->description, "At level 20 switches to *remove curses*"); - school_idx_add_new(&spell->schools, SCHOOL_MANA); - range_init(&spell->mana_range, 20, 40); - spell_inertia_init(spell, 1, 10); - spell->info_func = mana_remove_curses_info; - spell->effect_func = mana_remove_curses; - spell->failure_rate = 30; - spell->skill_level = 10; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "3+d8"); + spell_type_describe(spell, "Remove curses of worn objects"); + spell_type_describe(spell, "At level 20 switches to *remove curses*"); + spell_type_set_mana(spell, 20, 40); + spell_type_set_inertia(spell, 1, 10); + spell_type_set_difficulty(spell, 10, 30); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_MANA, + mana_remove_curses_info, + mana_remove_curses); + + spell_type_set_device_charges(spell, "3+d8"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 70; range_init(&device_allocation->base_level, 1, 5); range_init(&device_allocation->max_level, 15, 50); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&RESISTS, "RESISTS", "Elemental Shield"); - string_list_append(&spell->description, "Provide resistances to the four basic elements"); - school_idx_add_new(&spell->schools, SCHOOL_MANA); - range_init(&spell->mana_range, 17, 20); - spell_inertia_init(spell, 2, 25); - spell->info_func = mana_elemental_shield_info; - spell->effect_func = mana_elemental_shield; - spell->failure_rate = 40; - spell->skill_level = 20; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Provide resistances to the four basic elements"); + spell_type_set_mana(spell, 17, 20); + spell_type_set_inertia(spell, 2, 25); + spell_type_set_difficulty(spell, 20, 40); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_MANA, + mana_elemental_shield_info, + mana_elemental_shield); } { spell_type *spell = spell_new(&MANASHIELD, "MANASHIELD", "Disruption Shield"); - string_list_append(&spell->description, "Uses mana instead of hp to take damage"); - string_list_append(&spell->description, "At level 5 switches to Globe of Invulnerability."); - string_list_append(&spell->description, "The spell breaks as soon as a melee, shooting, throwing or magical"); - string_list_append(&spell->description, "skill action is attempted, and lasts only a short time."); - school_idx_add_new(&spell->schools, SCHOOL_MANA); - range_init(&spell->mana_range, 50, 50); - spell_inertia_init(spell, 9, 10); - spell->info_func = mana_disruption_shield_info; - spell->effect_func = mana_disruption_shield; - spell->failure_rate = 90; - spell->skill_level = 45; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Uses mana instead of hp to take damage"); + spell_type_describe(spell, "At level 5 switches to Globe of Invulnerability."); + spell_type_describe(spell, "The spell breaks as soon as a melee, shooting, throwing or magical"); + spell_type_describe(spell, "skill action is attempted, and lasts only a short time."); + spell_type_set_mana(spell, 50, 50); + spell_type_set_inertia(spell, 9, 10); + spell_type_set_difficulty(spell, 45, 90); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_MANA, + mana_disruption_shield_info, + mana_disruption_shield); } { spell_type *spell = spell_new(&TIDALWAVE, "TIDALWAVE", "Tidal Wave"); - string_list_append(&spell->description, "Summons a monstrous tidal wave that will expand and crush the"); - string_list_append(&spell->description, "monsters under its mighty waves."); - school_idx_add_new(&spell->schools, SCHOOL_WATER); - range_init(&spell->mana_range, 16, 40); - spell_inertia_init(spell, 4, 100); - spell->info_func = water_tidal_wave_info; - spell->effect_func = water_tidal_wave; - spell->failure_rate = 65; - spell->skill_level = 16; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "6+d5"); + spell_type_describe(spell, "Summons a monstrous tidal wave that will expand and crush the"); + spell_type_describe(spell, "monsters under its mighty waves."); + spell_type_set_mana(spell, 16, 40); + spell_type_set_inertia(spell, 4, 100); + spell_type_set_difficulty(spell, 16, 65); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_WATER, + water_tidal_wave_info, + water_tidal_wave); + + spell_type_set_device_charges(spell, "6+d5"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 54; range_init(&device_allocation->base_level, 1, 10); range_init(&device_allocation->max_level, 20, 50); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&ICESTORM, "ICESTORM", "Ice Storm"); - string_list_append(&spell->description, "Engulfs you in a storm of roaring cold that strikes your foes."); - string_list_append(&spell->description, "At level 10 it turns into shards of ice."); - school_idx_add_new(&spell->schools, SCHOOL_WATER); - range_init(&spell->mana_range, 30, 60); - spell_inertia_init(spell, 3, 40); - spell->info_func = water_ice_storm_info; - spell->effect_func = water_ice_storm; - spell->failure_rate = 80; - spell->skill_level = 22; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "3+d7"); + spell_type_describe(spell, "Engulfs you in a storm of roaring cold that strikes your foes."); + spell_type_describe(spell, "At level 10 it turns into shards of ice."); + spell_type_set_mana(spell, 30, 60); + spell_type_set_inertia(spell, 3, 40); + spell_type_set_difficulty(spell, 22, 80); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_WATER, + water_ice_storm_info, + water_ice_storm); + + spell_type_set_device_charges(spell, "3+d7"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 65; range_init(&device_allocation->base_level, 1, 5); range_init(&device_allocation->max_level, 25, 45); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&ENTPOTION, "ENTPOTION", "Ent's Potion"); - string_list_append(&spell->description, "Fills up your stomach."); - string_list_append(&spell->description, "At level 5 it boldens your heart."); - string_list_append(&spell->description, "At level 12 it makes you heroic."); - school_idx_add_new(&spell->schools, SCHOOL_WATER); - range_init(&spell->mana_range, 7, 15); - spell_inertia_init(spell, 1, 30); - spell->info_func = water_ent_potion_info; - spell->effect_func = water_ent_potion; - spell->failure_rate = 35; - spell->skill_level = 6; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Fills up your stomach."); + spell_type_describe(spell, "At level 5 it boldens your heart."); + spell_type_describe(spell, "At level 12 it makes you heroic."); + spell_type_set_mana(spell, 7, 15); + spell_type_set_inertia(spell, 1, 30); + spell_type_set_difficulty(spell, 6, 35); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_WATER, + water_ent_potion_info, + water_ent_potion); } { spell_type *spell = spell_new(&VAPOR, "VAPOR", "Vapor"); - string_list_append(&spell->description, "Fills the air with toxic moisture to eradicate annoying critters."); - school_idx_add_new(&spell->schools, SCHOOL_WATER); - range_init(&spell->mana_range, 2, 12); - spell_inertia_init(spell, 1, 30); - spell->info_func = water_vapor_info; - spell->effect_func = water_vapor; - spell->failure_rate = 20; - spell->skill_level = 2; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Fills the air with toxic moisture to eradicate annoying critters."); + spell_type_set_mana(spell, 2, 12); + spell_type_set_inertia(spell, 1, 30); + spell_type_set_difficulty(spell, 2, 20); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_WATER, + water_vapor_info, + water_vapor); } { spell_type *spell = spell_new(&GEYSER, "GEYSER", "Geyser"); - string_list_append(&spell->description, "Shoots a geyser of water from your fingertips."); - string_list_append(&spell->description, "Sometimes it can blast through its first target."); - school_idx_add_new(&spell->schools, SCHOOL_WATER); - range_init(&spell->mana_range, 1, 35); - spell->info_func = water_geyser_info; - spell->effect_func = water_geyser; - spell->failure_rate = 5; - spell->skill_level = 1; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Shoots a geyser of water from your fingertips."); + spell_type_describe(spell, "Sometimes it can blast through its first target."); + spell_type_set_mana(spell, 1, 35); + spell_type_set_difficulty(spell, 1, 5); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_WATER, + water_geyser_info, + water_geyser); } { spell_type *spell = spell_new(&NOXIOUSCLOUD, "NOXIOUSCLOUD", "Noxious Cloud"); - string_list_append(&spell->description, "Creates a cloud of poison"); - string_list_append(&spell->description, "The cloud will persist for some turns, damaging all monsters passing by"); - string_list_append(&spell->description, "At spell level 30 it turns into a thick gas attacking all living beings"); - school_idx_add_new(&spell->schools, SCHOOL_AIR); - range_init(&spell->mana_range, 3, 30); - spell->info_func = air_noxious_cloud_info; - spell->effect_func = air_noxious_cloud; - spell->failure_rate = 20; - spell->skill_level = 3; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "5+d7"); + spell_type_describe(spell, "Creates a cloud of poison"); + spell_type_describe(spell, "The cloud will persist for some turns, damaging all monsters passing by"); + spell_type_describe(spell, "At spell level 30 it turns into a thick gas attacking all living beings"); + spell_type_set_mana(spell, 3, 30); + spell_type_set_difficulty(spell, 3, 20); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_AIR, + air_noxious_cloud_info, + air_noxious_cloud); + + spell_type_set_device_charges(spell, "5+d7"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 15; range_init(&device_allocation->base_level, 1, 15); range_init(&device_allocation->max_level, 25, 50); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&AIRWINGS, "AIRWINGS", "Wings of Winds"); - string_list_append(&spell->description, "Grants the power of levitation"); - string_list_append(&spell->description, "At level 16 it grants the power of controlled flight"); - school_idx_add_new(&spell->schools, SCHOOL_AIR); - school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); - range_init(&spell->mana_range, 30, 40); - spell_inertia_init(spell, 1, 10); - spell->info_func = air_wings_of_winds_info; - spell->effect_func = air_wings_of_winds; - spell->failure_rate = 60; - spell->skill_level = 22; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "7+d5"); + spell_type_describe(spell, "Grants the power of levitation"); + spell_type_describe(spell, "At level 16 it grants the power of controlled flight"); + spell_type_add_school(spell, SCHOOL_CONVEYANCE); + spell_type_set_mana(spell, 30, 40); + spell_type_set_inertia(spell, 1, 10); + spell_type_set_difficulty(spell, 22, 60); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_AIR, + air_wings_of_winds_info, + air_wings_of_winds); + + spell_type_set_device_charges(spell, "7+d5"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 27; range_init(&device_allocation->base_level, 1, 10); range_init(&device_allocation->max_level, 20, 50); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&INVISIBILITY, "INVISIBILITY", "Invisibility"); - string_list_append(&spell->description, "Grants invisibility"); - school_idx_add_new(&spell->schools, SCHOOL_AIR); - range_init(&spell->mana_range, 10, 20); - spell_inertia_init(spell, 1, 30); - spell->info_func = air_invisibility_info; - spell->effect_func = air_invisibility; - spell->failure_rate = 50; - spell->skill_level = 16; - spell_init_mage(spell, RANDOM); - + spell_type_describe(spell, "Grants invisibility"); + spell_type_set_mana(spell, 10, 20); + spell_type_set_inertia(spell, 1, 30); + spell_type_set_difficulty(spell, 16, 50); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_AIR, + air_invisibility_info, + air_invisibility); } { spell_type *spell = spell_new(&POISONBLOOD, "POISONBLOOD", "Poison Blood"); - string_list_append(&spell->description, "Grants resist poison"); - string_list_append(&spell->description, "At level 15 it provides poison branding to wielded weapon"); - school_idx_add_new(&spell->schools, SCHOOL_AIR); - range_init(&spell->mana_range, 10, 20); - spell_inertia_init(spell, 1, 35); - spell->info_func = air_poison_blood_info; - spell->effect_func = air_poison_blood; - spell->failure_rate = 30; - spell->skill_level = 12; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "10+d15"); + spell_type_describe(spell, "Grants resist poison"); + spell_type_describe(spell, "At level 15 it provides poison branding to wielded weapon"); + spell_type_set_mana(spell, 10, 20); + spell_type_set_inertia(spell, 1, 35); + spell_type_set_difficulty(spell, 12, 30); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_AIR, + air_poison_blood_info, + air_poison_blood); + + spell_type_set_device_charges(spell, "10+d15"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 45; range_init(&device_allocation->base_level, 1, 25); range_init(&device_allocation->max_level, 35, 50); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&THUNDERSTORM, "THUNDERSTORM", "Thunderstorm"); - string_list_append(&spell->description, "Charges up the air around you with electricity"); - string_list_append(&spell->description, "Each turn it will throw a thunder bolt at a random monster in sight"); - string_list_append(&spell->description, "The thunder does 3 types of damage, one third of lightning"); - string_list_append(&spell->description, "one third of sound and one third of light"); - school_idx_add_new(&spell->schools, SCHOOL_AIR); - school_idx_add_new(&spell->schools, SCHOOL_NATURE); - range_init(&spell->mana_range, 40, 60); - spell_inertia_init(spell, 2, 15); - spell->info_func = air_thunderstorm_info; - spell->effect_func = air_thunderstorm; - spell->failure_rate = 60; - spell->skill_level = 25; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "5+d5"); + spell_type_describe(spell, "Charges up the air around you with electricity"); + spell_type_describe(spell, "Each turn it will throw a thunder bolt at a random monster in sight"); + spell_type_describe(spell, "The thunder does 3 types of damage, one third of lightning"); + spell_type_describe(spell, "one third of sound and one third of light"); + spell_type_add_school(spell, SCHOOL_NATURE); + spell_type_set_mana(spell, 40, 60); + spell_type_set_inertia(spell, 2, 15); + spell_type_set_difficulty(spell, 25, 60); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_AIR, + air_thunderstorm_info, + air_thunderstorm); + + spell_type_set_device_charges(spell, "5+d5"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 85; range_init(&device_allocation->base_level, 1, 5); range_init(&device_allocation->max_level, 25, 50); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&STERILIZE, "STERILIZE", "Sterilize"); - string_list_append(&spell->description, "Prevents explosive breeding for a while."); - school_idx_add_new(&spell->schools, SCHOOL_AIR); - range_init(&spell->mana_range, 10, 100); - spell->info_func = air_sterilize_info; - spell->effect_func = air_sterilize; - spell->failure_rate = 50; - spell->skill_level = 20; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Prevents explosive breeding for a while."); + spell_type_set_mana(spell, 10, 100); + spell_type_set_difficulty(spell, 20, 50); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_AIR, + air_sterilize_info, + air_sterilize); - dice_parse_checked(&spell->device_charges, "7+d5"); + spell_type_set_device_charges(spell, "7+d5"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 20; range_init(&device_allocation->base_level, 1, 10); range_init(&device_allocation->max_level, 20, 50); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&STONESKIN, "STONESKIN", "Stone Skin"); - string_list_append(&spell->description, "Creates a shield of earth around you to protect you"); - string_list_append(&spell->description, "At level 25 it starts dealing damage to attackers"); - school_idx_add_new(&spell->schools, SCHOOL_EARTH); - range_init(&spell->mana_range, 1, 50); - spell_inertia_init(spell, 2, 50); - spell->info_func = earth_stone_skin_info; - spell->effect_func = earth_stone_skin; - spell->failure_rate = 10; - spell->skill_level = 1; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Creates a shield of earth around you to protect you"); + spell_type_describe(spell, "At level 25 it starts dealing damage to attackers"); + spell_type_set_mana(spell, 1, 50); + spell_type_set_inertia(spell, 2, 50); + spell_type_set_difficulty(spell, 1, 10); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_EARTH, + earth_stone_skin_info, + earth_stone_skin); } { spell_type *spell = spell_new(&DIG, "DIG", "Dig"); - string_list_append(&spell->description, "Digs a hole in a wall much faster than any shovels"); - school_idx_add_new(&spell->schools, SCHOOL_EARTH); - range_init(&spell->mana_range, 14, 14); - spell->info_func = earth_dig_info; - spell->effect_func = earth_dig; - spell->failure_rate = 20; - spell->skill_level = 12; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Digs a hole in a wall much faster than any shovels"); + spell_type_set_mana(spell, 14, 14); + spell_type_set_difficulty(spell, 12, 20); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_EARTH, + earth_dig_info, + earth_dig); - dice_parse_checked(&spell->device_charges, "15+d5"); + spell_type_set_device_charges(spell, "15+d5"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 25; range_init(&device_allocation->base_level, 1, 1); range_init(&device_allocation->max_level, 1, 1); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&STONEPRISON, "STONEPRISON", "Stone Prison"); - string_list_append(&spell->description, "Creates a prison of walls around you"); - string_list_append(&spell->description, "At level 10 it allows you to target a monster"); - school_idx_add_new(&spell->schools, SCHOOL_EARTH); - range_init(&spell->mana_range, 30, 50); - spell->info_func = earth_stone_prison_info; - spell->effect_func = earth_stone_prison; - spell->failure_rate = 65; - spell->skill_level = 25; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "5+d3"); + spell_type_describe(spell, "Creates a prison of walls around you"); + spell_type_describe(spell, "At level 10 it allows you to target a monster"); + spell_type_set_mana(spell, 30, 50); + spell_type_set_difficulty(spell, 25, 65); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_EARTH, + earth_stone_prison_info, + earth_stone_prison); + + spell_type_set_device_charges(spell, "5+d3"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 57; range_init(&device_allocation->base_level, 1, 3); range_init(&device_allocation->max_level, 5, 20); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&STRIKE, "STRIKE", "Strike"); - string_list_append(&spell->description, "Creates a micro-ball of force that will push monsters backwards"); - string_list_append(&spell->description, "If the monster is caught near a wall, it'll be crushed against it"); - string_list_append(&spell->description, "At level 12 it turns into a ball of radius 1"); - school_idx_add_new(&spell->schools, SCHOOL_EARTH); - range_init(&spell->mana_range, 30, 50); - spell->info_func = earth_strike_info; - spell->effect_func = earth_strike; - spell->failure_rate = 60; - spell->skill_level = 30; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "2+d6"); + spell_type_describe(spell, "Creates a micro-ball of force that will push monsters backwards"); + spell_type_describe(spell, "If the monster is caught near a wall, it'll be crushed against it"); + spell_type_describe(spell, "At level 12 it turns into a ball of radius 1"); + spell_type_set_mana(spell, 30, 50); + spell_type_set_difficulty(spell, 30, 60); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_EARTH, + earth_strike_info, + earth_strike); + + spell_type_set_device_charges(spell, "2+d6"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 635; range_init(&device_allocation->base_level, 1, 5); range_init(&device_allocation->max_level, 10, 50); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&SHAKE, "SHAKE", "Shake"); - string_list_append(&spell->description, "Creates a localised earthquake"); - string_list_append(&spell->description, "At level 10 it can be targeted at any location"); - school_idx_add_new(&spell->schools, SCHOOL_EARTH); - range_init(&spell->mana_range, 25, 30); - spell_inertia_init(spell, 2, 50); - spell->info_func = earth_shake_info; - spell->effect_func = earth_shake; - spell->failure_rate = 60; - spell->skill_level = 27; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "5+d10"); + spell_type_describe(spell, "Creates a localised earthquake"); + spell_type_describe(spell, "At level 10 it can be targeted at any location"); + spell_type_set_mana(spell, 25, 30); + spell_type_set_inertia(spell, 2, 50); + spell_type_set_difficulty(spell, 27, 60); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_EARTH, + earth_shake_info, + earth_shake); + + spell_type_set_device_charges(spell, "5+d10"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 75; range_init(&device_allocation->base_level, 1, 3); range_init(&device_allocation->max_level, 9, 20); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&BLINK, "BLINK", "Phase Door"); - string_list_append(&spell->description, "Teleports you on a small scale range"); - string_list_append(&spell->description, "At level 30 it creates void jumpgates"); - school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); - range_init(&spell->mana_range, 1, 3); - spell_inertia_init(spell, 1, 5); - spell->info_func = convey_blink_info; - spell->effect_func = convey_blink; - spell->failure_rate = 10; - spell->skill_level = 1; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Teleports you on a small scale range"); + spell_type_describe(spell, "At level 30 it creates void jumpgates"); + spell_type_set_mana(spell, 1, 3); + spell_type_set_inertia(spell, 1, 5); + spell_type_set_difficulty(spell, 1, 10); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_CONVEYANCE, + convey_blink_info, + convey_blink); } { spell_type *spell = spell_new(&DISARM, "DISARM", "Disarm"); - string_list_append(&spell->description, "Destroys doors and traps"); - string_list_append(&spell->description, "At level 10 it destroys doors and traps, then reveals and unlocks any secret"); - string_list_append(&spell->description, "doors"); - school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); - range_init(&spell->mana_range, 2, 4); - spell->info_func = convey_disarm_info; - spell->effect_func = convey_disarm; - spell->failure_rate = 15; - spell->skill_level = 3; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "10+d15"); + spell_type_describe(spell, "Destroys doors and traps"); + spell_type_describe(spell, "At level 10 it destroys doors and traps, then reveals and unlocks any secret"); + spell_type_describe(spell, "doors"); + spell_type_set_mana(spell, 2, 4); + spell_type_set_difficulty(spell, 3, 15); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_CONVEYANCE, + convey_disarm_info, + convey_disarm); + + spell_type_set_device_charges(spell, "10+d15"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 4; range_init(&device_allocation->base_level, 1, 10); range_init(&device_allocation->max_level, 10, 50); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&TELEPORT, "TELEPORT", "Teleportation"); - string_list_append(&spell->description, "Teleports you around the level. The casting time decreases with level"); - school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); - range_init(&spell->mana_range, 8, 14); - spell_inertia_init(spell, 1, 10); - spell->info_func = convey_teleport_info; - spell->effect_func = convey_teleport; - spell->failure_rate = 30; - spell->skill_level = 10; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "7+d7"); + spell_type_describe(spell, "Teleports you around the level. The casting time decreases with level"); + spell_type_set_mana(spell, 8, 14); + spell_type_set_inertia(spell, 1, 10); + spell_type_set_difficulty(spell, 10, 30); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_CONVEYANCE, + convey_teleport_info, + convey_teleport); + + spell_type_set_device_charges(spell, "7+d7"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 50; range_init(&device_allocation->base_level, 1, 20); range_init(&device_allocation->max_level, 20, 50); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&TELEAWAY, "TELEAWAY", "Teleport Away"); - string_list_append(&spell->description, "Teleports a line of monsters away"); - string_list_append(&spell->description, "At level 10 it turns into a ball"); - string_list_append(&spell->description, "At level 20 it teleports all monsters in sight"); - school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); - range_init(&spell->mana_range, 15, 40); - spell->info_func = convey_teleport_away_info; - spell->effect_func = convey_teleport_away; - spell->failure_rate = 60; - spell->skill_level = 23; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "3+d5"); + spell_type_describe(spell, "Teleports a line of monsters away"); + spell_type_describe(spell, "At level 10 it turns into a ball"); + spell_type_describe(spell, "At level 20 it teleports all monsters in sight"); + spell_type_set_mana(spell, 15, 40); + spell_type_set_difficulty(spell, 23, 60); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_CONVEYANCE, + convey_teleport_away_info, + convey_teleport_away); + + spell_type_set_device_charges(spell, "3+d5"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 75; range_init(&device_allocation->base_level, 1, 20); range_init(&device_allocation->max_level, 20, 50); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&RECALL, "RECALL", "Recall"); - string_list_append(&spell->description, "Cast on yourself it will recall you to the surface/dungeon."); - string_list_append(&spell->description, "Cast at a monster you will swap positions with the monster."); - string_list_append(&spell->description, "Cast at an object it will fetch the object to you."); - school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); - range_init(&spell->mana_range, 25, 25); - spell->info_func = convey_recall_info; - spell->effect_func = convey_recall; - spell->failure_rate = 60; - spell->skill_level = 30; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Cast on yourself it will recall you to the surface/dungeon."); + spell_type_describe(spell, "Cast at a monster you will swap positions with the monster."); + spell_type_describe(spell, "Cast at an object it will fetch the object to you."); + spell_type_set_mana(spell, 25, 25); + spell_type_set_difficulty(spell, 30, 60); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_CONVEYANCE, + convey_recall_info, + convey_recall); } { spell_type *spell = spell_new(&PROBABILITY_TRAVEL, "PROBABILITY_TRAVEL", "Probability Travel"); - string_list_append(&spell->description, "Renders you immaterial, when you hit a wall you travel through it and"); - string_list_append(&spell->description, "instantly appear on the other side of it. You can also float up and down"); - string_list_append(&spell->description, "at will"); - school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); - range_init(&spell->mana_range, 30, 50); - spell_inertia_init(spell, 6, 40); - spell->info_func = convey_probability_travel_info; - spell->effect_func = convey_probability_travel; - spell->failure_rate = 90; - spell->skill_level = 35; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "1+d2"); + spell_type_describe(spell, "Renders you immaterial, when you hit a wall you travel through it and"); + spell_type_describe(spell, "instantly appear on the other side of it. You can also float up and down"); + spell_type_describe(spell, "at will"); + spell_type_set_mana(spell, 30, 50); + spell_type_set_inertia(spell, 6, 40); + spell_type_set_difficulty(spell, 35, 90); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_CONVEYANCE, + convey_probability_travel_info, + convey_probability_travel); + + spell_type_set_device_charges(spell, "1+d2"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 97; range_init(&device_allocation->base_level, 1, 5); range_init(&device_allocation->max_level, 8, 25); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&GROWTREE, "GROWTREE", "Grow Trees"); - string_list_append(&spell->description, "Makes trees grow extremely quickly around you"); - school_idx_add_new(&spell->schools, SCHOOL_NATURE); - school_idx_add_new(&spell->schools, SCHOOL_TEMPORAL); - range_init(&spell->mana_range, 6, 30); - spell_inertia_init(spell, 5, 50); - spell->info_func = nature_grow_trees_info; - spell->effect_func = nature_grow_trees; - spell->failure_rate = 35; - spell->skill_level = 6; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Makes trees grow extremely quickly around you"); + spell_type_add_school(spell, SCHOOL_TEMPORAL); + spell_type_set_mana(spell, 6, 30); + spell_type_set_inertia(spell, 5, 50); + spell_type_set_difficulty(spell, 6, 35); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_NATURE, + nature_grow_trees_info, + nature_grow_trees); } { spell_type *spell = spell_new(&HEALING, "HEALING", "Healing"); - string_list_append(&spell->description, "Heals a percent of hitpoints"); - school_idx_add_new(&spell->schools, SCHOOL_NATURE); - range_init(&spell->mana_range, 15, 50); - spell->info_func = nature_healing_info; - spell->effect_func = nature_healing; - spell->failure_rate = 45; - spell->skill_level = 10; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Heals a percent of hitpoints"); + spell_type_set_mana(spell, 15, 50); + spell_type_set_difficulty(spell, 10, 45); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_NATURE, + nature_healing_info, + nature_healing); - dice_parse_checked(&spell->device_charges, "2+d3"); + spell_type_set_device_charges(spell, "2+d3"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 90; range_init(&device_allocation->base_level, 1, 5); range_init(&device_allocation->max_level, 20, 40); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&RECOVERY, "RECOVERY", "Recovery"); - string_list_append(&spell->description, "Reduces the length of time that you are poisoned"); - string_list_append(&spell->description, "At level 5 it cures poison and cuts"); - string_list_append(&spell->description, "At level 10 it restores drained stats"); - string_list_append(&spell->description, "At level 15 it restores lost experience"); - school_idx_add_new(&spell->schools, SCHOOL_NATURE); - range_init(&spell->mana_range, 10, 25); - spell_inertia_init(spell, 2, 100); - spell->info_func = nature_recovery_info; - spell->effect_func = nature_recovery; - spell->failure_rate = 60; - spell->skill_level = 15; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "5+d10"); + spell_type_describe(spell, "Reduces the length of time that you are poisoned"); + spell_type_describe(spell, "At level 5 it cures poison and cuts"); + spell_type_describe(spell, "At level 10 it restores drained stats"); + spell_type_describe(spell, "At level 15 it restores lost experience"); + spell_type_set_mana(spell, 10, 25); + spell_type_set_inertia(spell, 2, 100); + spell_type_set_difficulty(spell, 15, 60); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_NATURE, + nature_recovery_info, + nature_recovery); + + spell_type_set_device_charges(spell, "5+d10"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 50; range_init(&device_allocation->base_level, 1, 5); range_init(&device_allocation->max_level, 10, 30); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(®ENERATION, "REGENERATION", "Regeneration"); - string_list_append(&spell->description, "Increases your body's regeneration rate"); - school_idx_add_new(&spell->schools, SCHOOL_NATURE); - range_init(&spell->mana_range, 30, 55); - spell_inertia_init(spell, 4, 40); - spell->info_func = nature_regeneration_info; - spell->effect_func = nature_regeneration; - spell->failure_rate = 70; - spell->skill_level = 20; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Increases your body's regeneration rate"); + spell_type_set_mana(spell, 30, 55); + spell_type_set_inertia(spell, 4, 40); + spell_type_set_difficulty(spell, 20, 70); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_NATURE, + nature_regeneration_info, + nature_regeneration); } { spell_type *spell = spell_new(&SUMMONANNIMAL, "SUMMONANNIMAL", "Summon Animal"); - string_list_append(&spell->description, "Summons a leveled animal to your aid"); - school_idx_add_new(&spell->schools, SCHOOL_NATURE); - range_init(&spell->mana_range, 25, 50); - spell->info_func = nature_summon_animal_info; - spell->effect_func = nature_summon_animal; - spell->failure_rate = 90; - spell->skill_level = 25; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Summons a leveled animal to your aid"); + spell_type_set_mana(spell, 25, 50); + spell_type_set_difficulty(spell, 25, 90); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_NATURE, + nature_summon_animal_info, + nature_summon_animal); - dice_parse_checked(&spell->device_charges, "1+d3"); + spell_type_set_device_charges(spell, "1+d3"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 85; range_init(&device_allocation->base_level, 1, 5); range_init(&device_allocation->max_level, 15, 45); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&STARIDENTIFY, "STARIDENTIFY", "Greater Identify"); - string_list_append(&spell->description, "Asks for an object and fully identify it, providing the full list of powers"); - string_list_append(&spell->description, "Cast at yourself it will reveal your powers"); - school_idx_add_new(&spell->schools, SCHOOL_DIVINATION); - range_init(&spell->mana_range, 30, 30); - spell->info_func = divination_greater_identify_info; - spell->effect_func = divination_greater_identify; - spell->failure_rate = 80; - spell->skill_level = 35; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Asks for an object and fully identify it, providing the full list of powers"); + spell_type_describe(spell, "Cast at yourself it will reveal your powers"); + spell_type_set_mana(spell, 30, 30); + spell_type_set_difficulty(spell, 35, 80); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_DIVINATION, + divination_greater_identify_info, + divination_greater_identify); } { spell_type *spell = spell_new(&IDENTIFY, "IDENTIFY", "Identify"); - string_list_append(&spell->description, "Asks for an object and identifies it"); - string_list_append(&spell->description, "At level 17 it identifies all objects in the inventory"); - string_list_append(&spell->description, "At level 27 it identifies all objects in the inventory and in a"); - string_list_append(&spell->description, "radius on the floor, as well as probing monsters in that radius"); - school_idx_add_new(&spell->schools, SCHOOL_DIVINATION); - range_init(&spell->mana_range, 10, 50); - spell->info_func = divination_identify_info; - spell->effect_func = divination_identify; - spell->failure_rate = 40; - spell->skill_level = 8; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "7+d10"); + spell_type_describe(spell, "Asks for an object and identifies it"); + spell_type_describe(spell, "At level 17 it identifies all objects in the inventory"); + spell_type_describe(spell, "At level 27 it identifies all objects in the inventory and in a"); + spell_type_describe(spell, "radius on the floor, as well as probing monsters in that radius"); + spell_type_set_mana(spell, 10, 50); + spell_type_set_difficulty(spell, 8, 40); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_DIVINATION, + divination_identify_info, + divination_identify); + + spell_type_set_device_charges(spell, "7+d10"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 45; range_init(&device_allocation->base_level, 1, 15); range_init(&device_allocation->max_level, 15, 40); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&VISION, "VISION", "Vision"); - string_list_append(&spell->description, "Detects the layout of the surrounding area"); - string_list_append(&spell->description, "At level 25 it maps and lights the whole level"); - school_idx_add_new(&spell->schools, SCHOOL_DIVINATION); - range_init(&spell->mana_range, 7, 55); - spell_inertia_init(spell, 2, 200); - spell->info_func = divination_vision_info; - spell->effect_func = divination_vision; - spell->failure_rate = 45; - spell->skill_level = 15; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "4+d6"); + spell_type_describe(spell, "Detects the layout of the surrounding area"); + spell_type_describe(spell, "At level 25 it maps and lights the whole level"); + spell_type_set_mana(spell, 7, 55); + spell_type_set_inertia(spell, 2, 200); + spell_type_set_difficulty(spell, 15, 45); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_DIVINATION, + divination_vision_info, + divination_vision); + + spell_type_set_device_charges(spell, "4+d6"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 60; range_init(&device_allocation->base_level, 1, 5); range_init(&device_allocation->max_level, 10, 30); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&SENSEHIDDEN, "SENSEHIDDEN", "Sense Hidden"); - string_list_append(&spell->description, "Detects the traps in a certain radius around you"); - string_list_append(&spell->description, "At level 15 it allows you to sense invisible for a while"); - school_idx_add_new(&spell->schools, SCHOOL_DIVINATION); - range_init(&spell->mana_range, 2, 10); - spell_inertia_init(spell, 1, 10); - spell->info_func = divination_sense_hidden_info; - spell->effect_func = divination_sense_hidden; - spell->failure_rate = 25; - spell->skill_level = 5; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "1+d15"); + spell_type_describe(spell, "Detects the traps in a certain radius around you"); + spell_type_describe(spell, "At level 15 it allows you to sense invisible for a while"); + spell_type_set_mana(spell, 2, 10); + spell_type_set_inertia(spell, 1, 10); + spell_type_set_difficulty(spell, 5, 25); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_DIVINATION, + divination_sense_hidden_info, + divination_sense_hidden); + + spell_type_set_device_charges(spell, "1+d15"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 20; range_init(&device_allocation->base_level, 1, 15); range_init(&device_allocation->max_level, 10, 50); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&REVEALWAYS, "REVEALWAYS", "Reveal Ways"); - string_list_append(&spell->description, "Detects the doors/stairs/ways in a certain radius around you"); - school_idx_add_new(&spell->schools, SCHOOL_DIVINATION); - range_init(&spell->mana_range, 3, 15); - spell_inertia_init(spell, 1, 10); - spell->info_func = divination_reveal_ways_info; - spell->effect_func = divination_reveal_ways; - spell->failure_rate = 20; - spell->skill_level = 9; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "6+d6"); + spell_type_describe(spell, "Detects the doors/stairs/ways in a certain radius around you"); + spell_type_set_mana(spell, 3, 15); + spell_type_set_inertia(spell, 1, 10); + spell_type_set_difficulty(spell, 9, 20); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_DIVINATION, + divination_reveal_ways_info, + divination_reveal_ways); + + spell_type_set_device_charges(spell, "6+d6"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 35; range_init(&device_allocation->base_level, 1, 15); range_init(&device_allocation->max_level, 25, 50); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&SENSEMONSTERS, "SENSEMONSTERS", "Sense Monsters"); - string_list_append(&spell->description, "Detects all monsters near you"); - string_list_append(&spell->description, "At level 30 it allows you to sense monster minds for a while"); - school_idx_add_new(&spell->schools, SCHOOL_DIVINATION); - range_init(&spell->mana_range, 1, 20); - spell_inertia_init(spell, 1, 10); - spell->info_func = divination_sense_monsters_info; - spell->effect_func = divination_sense_monsters; - spell->failure_rate = 10; - spell->skill_level = 1; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "5+d10"); + spell_type_describe(spell, "Detects all monsters near you"); + spell_type_describe(spell, "At level 30 it allows you to sense monster minds for a while"); + spell_type_set_mana(spell, 1, 20); + spell_type_set_inertia(spell, 1, 10); + spell_type_set_difficulty(spell, 1, 10); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_DIVINATION, + divination_sense_monsters_info, + divination_sense_monsters); + + spell_type_set_device_charges(spell, "5+d10"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 37; range_init(&device_allocation->base_level, 1, 10); range_init(&device_allocation->max_level, 15, 40); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&MAGELOCK, "MAGELOCK", "Magelock"); - string_list_append(&spell->description, "Magically locks a door"); - string_list_append(&spell->description, "At level 30 it creates a glyph of warding"); - string_list_append(&spell->description, "At level 40 the glyph can be placed anywhere in the field of vision"); - school_idx_add_new(&spell->schools, SCHOOL_TEMPORAL); - range_init(&spell->mana_range, 1, 35); - spell->info_func = tempo_magelock_info; - spell->effect_func = tempo_magelock; - spell->failure_rate = 10; - spell->skill_level = 1; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "7+d5"); + spell_type_describe(spell, "Magically locks a door"); + spell_type_describe(spell, "At level 30 it creates a glyph of warding"); + spell_type_describe(spell, "At level 40 the glyph can be placed anywhere in the field of vision"); + spell_type_set_mana(spell, 1, 35); + spell_type_set_difficulty(spell, 1, 10); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_TEMPORAL, + tempo_magelock_info, + tempo_magelock); + + spell_type_set_device_charges(spell, "7+d5"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 30; range_init(&device_allocation->base_level, 1, 5); range_init(&device_allocation->max_level, 15, 45); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&SLOWMONSTER, "SLOWMONSTER", "Slow Monster"); - string_list_append(&spell->description, "Magically slows down the passing of time around a monster"); - string_list_append(&spell->description, "At level 20 it affects a zone"); - school_idx_add_new(&spell->schools, SCHOOL_TEMPORAL); - range_init(&spell->mana_range, 10, 15); - spell->info_func = tempo_slow_monster_info; - spell->effect_func = tempo_slow_monster; - spell->failure_rate = 35; - spell->skill_level = 10; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "5+d5"); + spell_type_describe(spell, "Magically slows down the passing of time around a monster"); + spell_type_describe(spell, "At level 20 it affects a zone"); + spell_type_set_mana(spell, 10, 15); + spell_type_set_difficulty(spell, 10, 35); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_TEMPORAL, + tempo_slow_monster_info, + tempo_slow_monster); + + spell_type_set_device_charges(spell, "5+d5"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 23; range_init(&device_allocation->base_level, 1, 15); range_init(&device_allocation->max_level, 20, 50); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&ESSENCESPEED, "ESSENCESPEED", "Essence of Speed"); - string_list_append(&spell->description, "Magically decreases the passing of time around you, making you move faster with"); - string_list_append(&spell->description, "respect to the rest of the universe."); - school_idx_add_new(&spell->schools, SCHOOL_TEMPORAL); - range_init(&spell->mana_range, 20, 40); - spell_inertia_init(spell, 5, 20); - spell->info_func = tempo_essence_of_speed_info; - spell->effect_func = tempo_essence_of_speed; - spell->failure_rate = 50; - spell->skill_level = 15; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "3+d3"); + spell_type_describe(spell, "Magically decreases the passing of time around you, making you move faster with"); + spell_type_describe(spell, "respect to the rest of the universe."); + spell_type_set_mana(spell, 20, 40); + spell_type_set_inertia(spell, 5, 20); + spell_type_set_difficulty(spell, 15, 50); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_TEMPORAL, + tempo_essence_of_speed_info, + tempo_essence_of_speed); + + spell_type_set_device_charges(spell, "3+d3"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 80; range_init(&device_allocation->base_level, 1, 1); range_init(&device_allocation->max_level, 10, 39); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&BANISHMENT, "BANISHMENT", "Banishment"); - string_list_append(&spell->description, "Disrupts the space/time continuum in your area and teleports all monsters away."); - string_list_append(&spell->description, "At level 15 it may also lock them in a time bubble for a while."); - school_idx_add_new(&spell->schools, SCHOOL_TEMPORAL); - school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); - range_init(&spell->mana_range, 30, 40); - spell_inertia_init(spell, 5, 50); - spell->info_func = tempo_banishment_info; - spell->effect_func = tempo_banishment; - spell->failure_rate = 95; - spell->skill_level = 30; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "1+d3"); + spell_type_describe(spell, "Disrupts the space/time continuum in your area and teleports all monsters away."); + spell_type_describe(spell, "At level 15 it may also lock them in a time bubble for a while."); + spell_type_add_school(spell, SCHOOL_CONVEYANCE); + spell_type_set_mana(spell, 30, 40); + spell_type_set_inertia(spell, 5, 50); + spell_type_set_difficulty(spell, 30, 95); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_TEMPORAL, + tempo_banishment_info, + tempo_banishment); + + spell_type_set_device_charges(spell, "1+d3"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 98; range_init(&device_allocation->base_level, 1, 15); range_init(&device_allocation->max_level, 10, 36); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&RECHARGE, "RECHARGE", "Recharge"); - string_list_append(&spell->description, "Taps on the ambient mana to recharge an object's power (charges or mana)"); - school_idx_add_new(&spell->schools, SCHOOL_META); - range_init(&spell->mana_range, 10, 100); - spell->info_func = meta_recharge_info; - spell->effect_func = meta_recharge; - spell->failure_rate = 20; - spell->skill_level = 5; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Taps on the ambient mana to recharge an object's power (charges or mana)"); + spell_type_set_mana(spell, 10, 100); + spell_type_set_difficulty(spell, 5, 20); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_META, + meta_recharge_info, + meta_recharge); } { spell_type *spell = spell_new(&SPELLBINDER, "SPELLBINDER", "Spellbinder"); - string_list_append(&spell->description, "Stores spells in a trigger."); - string_list_append(&spell->description, "When the condition is met all spells fire off at the same time"); - string_list_append(&spell->description, "This spell takes a long time to cast so you are advised to prepare it"); - string_list_append(&spell->description, "in a safe area."); - string_list_append(&spell->description, "Also it will use the mana for the Spellbinder and the mana for the"); - string_list_append(&spell->description, "selected spells"); - school_idx_add_new(&spell->schools, SCHOOL_META); - range_init(&spell->mana_range, 100, 300); - spell->info_func = meta_spellbinder_info; - spell->effect_func = meta_spellbinder; - spell->failure_rate = 85; - spell->skill_level = 20; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Stores spells in a trigger."); + spell_type_describe(spell, "When the condition is met all spells fire off at the same time"); + spell_type_describe(spell, "This spell takes a long time to cast so you are advised to prepare it"); + spell_type_describe(spell, "in a safe area."); + spell_type_describe(spell, "Also it will use the mana for the Spellbinder and the mana for the"); + spell_type_describe(spell, "selected spells"); + spell_type_set_mana(spell, 100, 300); + spell_type_set_difficulty(spell, 20, 85); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_META, + meta_spellbinder_info, + meta_spellbinder); } { spell_type *spell = spell_new(&DISPERSEMAGIC, "DISPERSEMAGIC", "Disperse Magic"); - string_list_append(&spell->description, "Dispels a lot of magic that can affect you, be it good or bad"); - string_list_append(&spell->description, "Level 1: blindness and light"); - string_list_append(&spell->description, "Level 5: confusion and hallucination"); - string_list_append(&spell->description, "Level 10: speed (both bad or good) and light speed"); - string_list_append(&spell->description, "Level 15: stunning, meditation, cuts"); - string_list_append(&spell->description, "Level 20: hero, super hero, bless, shields, afraid, parasites, mimicry"); - school_idx_add_new(&spell->schools, SCHOOL_META); - range_init(&spell->mana_range, 30, 60); - spell_inertia_init(spell, 1, 5); - spell->info_func = meta_disperse_magic_info; - spell->effect_func = meta_disperse_magic; - spell->failure_rate = 40; - spell->skill_level = 15; - spell->castable_while_blind = TRUE; - spell->castable_while_confused = TRUE; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "5+d5"); + spell_type_describe(spell, "Dispels a lot of magic that can affect you, be it good or bad"); + spell_type_describe(spell, "Level 1: blindness and light"); + spell_type_describe(spell, "Level 5: confusion and hallucination"); + spell_type_describe(spell, "Level 10: speed (both bad or good) and light speed"); + spell_type_describe(spell, "Level 15: stunning, meditation, cuts"); + spell_type_describe(spell, "Level 20: hero, super hero, bless, shields, afraid, parasites, mimicry"); + spell_type_set_mana(spell, 30, 60); + spell_type_set_inertia(spell, 1, 5); + spell_type_set_difficulty(spell, 15, 40); + spell_type_set_castable_while_blind(spell, TRUE); + spell_type_set_castable_while_confused(spell, TRUE); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_META, + meta_disperse_magic_info, + meta_disperse_magic); + + spell_type_set_device_charges(spell, "5+d5"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 25; range_init(&device_allocation->base_level, 1, 15); range_init(&device_allocation->max_level, 5, 40); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&TRACKER, "TRACKER", "Tracker"); - string_list_append(&spell->description, "Tracks down the last teleportation that happened on the level and teleports"); - string_list_append(&spell->description, "you to it"); - school_idx_add_new(&spell->schools, SCHOOL_META); - school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); - range_init(&spell->mana_range, 50, 50); - spell->info_func = meta_tracker_info; - spell->effect_func = meta_tracker; - spell->failure_rate = 95; - spell->skill_level = 30; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Tracks down the last teleportation that happened on the level and teleports"); + spell_type_describe(spell, "you to it"); + spell_type_add_school(spell, SCHOOL_CONVEYANCE); + spell_type_set_mana(spell, 50, 50); + spell_type_set_difficulty(spell, 30, 95); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_META, + meta_tracker_info, + meta_tracker); } { spell_type *spell = spell_new(&INERTIA_CONTROL, "INERTIA_CONTROL", "Inertia Control"); - string_list_append(&spell->description, "Changes the energy flow of a spell to be continuously recasted"); - string_list_append(&spell->description, "at a given interval. The inertia controlled spell reduces your"); - string_list_append(&spell->description, "maximum mana by four times its cost."); - school_idx_add_new(&spell->schools, SCHOOL_META); - range_init(&spell->mana_range, 300, 700); - spell->info_func = meta_inertia_control_info; - spell->effect_func = meta_inertia_control; - spell->failure_rate = 95; - spell->skill_level = 37; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Changes the energy flow of a spell to be continuously recasted"); + spell_type_describe(spell, "at a given interval. The inertia controlled spell reduces your"); + spell_type_describe(spell, "maximum mana by four times its cost."); + spell_type_set_mana(spell, 300, 700); + spell_type_set_difficulty(spell, 37, 95); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_META, + meta_inertia_control_info, + meta_inertia_control); } { spell_type *spell = spell_new(&CHARM, "CHARM", "Charm"); - string_list_append(&spell->description, "Tries to manipulate the mind of a monster to make it friendly"); - string_list_append(&spell->description, "At level 15 it turns into a ball"); - string_list_append(&spell->description, "At level 35 it affects all monsters in sight"); - school_idx_add_new(&spell->schools, SCHOOL_MIND); - range_init(&spell->mana_range, 1, 20); - spell->info_func = mind_charm_info; - spell->effect_func = mind_charm; - spell->failure_rate = 10; - spell->skill_level = 1; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "7+d5"); + spell_type_describe(spell, "Tries to manipulate the mind of a monster to make it friendly"); + spell_type_describe(spell, "At level 15 it turns into a ball"); + spell_type_describe(spell, "At level 35 it affects all monsters in sight"); + spell_type_set_mana(spell, 1, 20); + spell_type_set_difficulty(spell, 1, 10); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_MIND, + mind_charm_info, + mind_charm); + + spell_type_set_device_charges(spell, "7+d5"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 35; range_init(&device_allocation->base_level, 1, 15); range_init(&device_allocation->max_level, 20, 40); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&CONFUSE, "CONFUSE", "Confuse"); - string_list_append(&spell->description, "Tries to manipulate the mind of a monster to confuse it"); - string_list_append(&spell->description, "At level 15 it turns into a ball"); - string_list_append(&spell->description, "At level 35 it affects all monsters in sight"); - school_idx_add_new(&spell->schools, SCHOOL_MIND); - range_init(&spell->mana_range, 5, 30); - spell->info_func = mind_confuse_info; - spell->effect_func = mind_confuse; - spell->failure_rate = 20; - spell->skill_level = 5; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "3+d4"); + spell_type_describe(spell, "Tries to manipulate the mind of a monster to confuse it"); + spell_type_describe(spell, "At level 15 it turns into a ball"); + spell_type_describe(spell, "At level 35 it affects all monsters in sight"); + spell_type_set_mana(spell, 5, 30); + spell_type_set_difficulty(spell, 5, 20); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_MIND, + mind_confuse_info, + mind_confuse); + + spell_type_set_device_charges(spell, "3+d4"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 45; range_init(&device_allocation->base_level, 1, 5); range_init(&device_allocation->max_level, 20, 40); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&ARMOROFFEAR, "ARMOROFFEAR", "Armor of Fear"); - string_list_append(&spell->description, "Creates a shield of pure fear around you. Any monster attempting to hit you"); - string_list_append(&spell->description, "must save or flee"); - school_idx_add_new(&spell->schools, SCHOOL_MIND); - range_init(&spell->mana_range, 10, 50); - spell_inertia_init(spell, 2, 20); - spell->info_func = mind_armor_of_fear_info; - spell->effect_func = mind_armor_of_fear; - spell->failure_rate = 35; - spell->skill_level = 10; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Creates a shield of pure fear around you. Any monster attempting to hit you"); + spell_type_describe(spell, "must save or flee"); + spell_type_set_mana(spell, 10, 50); + spell_type_set_inertia(spell, 2, 20); + spell_type_set_difficulty(spell, 10, 35); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_MIND, + mind_armor_of_fear_info, + mind_armor_of_fear); } { spell_type *spell = spell_new(&STUN, "STUN", "Stun"); - string_list_append(&spell->description, "Tries to manipulate the mind of a monster to stun it"); - string_list_append(&spell->description, "At level 20 it turns into a ball"); - school_idx_add_new(&spell->schools, SCHOOL_MIND); - range_init(&spell->mana_range, 10, 90); - spell->info_func = mind_stun_info; - spell->effect_func = mind_stun; - spell->failure_rate = 45; - spell->skill_level = 15; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Tries to manipulate the mind of a monster to stun it"); + spell_type_describe(spell, "At level 20 it turns into a ball"); + spell_type_set_mana(spell, 10, 90); + spell_type_set_difficulty(spell, 15, 45); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_MIND, + mind_stun_info, + mind_stun); } { spell_type *spell = spell_new(&DRAIN, "DRAIN", "Drain"); - string_list_append(&spell->description, "Drains the mana contained in wands, staves and rods to increase yours"); - school_idx_add_new(&spell->schools, SCHOOL_UDUN); - school_idx_add_new(&spell->schools, SCHOOL_MANA); - range_init(&spell->mana_range, 0, 0); - spell->info_func = udun_drain_info; - spell->effect_func = udun_drain; - spell->failure_rate = 20; - spell->skill_level = 1; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Drains the mana contained in wands, staves and rods to increase yours"); + spell_type_add_school(spell, SCHOOL_MANA); + spell_type_set_mana(spell, 0, 0); + spell_type_set_difficulty(spell, 1, 20); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_UDUN, + udun_drain_info, + udun_drain); } { spell_type *spell = spell_new(&GENOCIDE, "GENOCIDE", "Genocide"); - string_list_append(&spell->description, "Genocides all monsters of a race on the level"); - string_list_append(&spell->description, "At level 10 it can genocide all monsters near you"); - school_idx_add_new(&spell->schools, SCHOOL_UDUN); - school_idx_add_new(&spell->schools, SCHOOL_NATURE); - range_init(&spell->mana_range, 50, 50); - spell->info_func = udun_genocide_info; - spell->effect_func = udun_genocide; - spell->failure_rate = 90; - spell->skill_level = 25; - spell_init_mage(spell, RANDOM); - - dice_parse_checked(&spell->device_charges, "2+d2"); + spell_type_describe(spell, "Genocides all monsters of a race on the level"); + spell_type_describe(spell, "At level 10 it can genocide all monsters near you"); + spell_type_add_school(spell, SCHOOL_NATURE); + spell_type_set_mana(spell, 50, 50); + spell_type_set_difficulty(spell, 25, 90); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_UDUN, + udun_genocide_info, + udun_genocide); + + spell_type_set_device_charges(spell, "2+d2"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 85; range_init(&device_allocation->base_level, 1, 1); range_init(&device_allocation->max_level, 5, 15); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&WRAITHFORM, "WRAITHFORM", "Wraithform"); - string_list_append(&spell->description, "Turns you into an immaterial being"); - school_idx_add_new(&spell->schools, SCHOOL_UDUN); - school_idx_add_new(&spell->schools, SCHOOL_CONVEYANCE); - range_init(&spell->mana_range, 20, 40); - spell_inertia_init(spell, 4, 30); - spell->info_func = udun_wraithform_info; - spell->effect_func = udun_wraithform; - spell->failure_rate = 95; - spell->skill_level = 30; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Turns you into an immaterial being"); + spell_type_add_school(spell, SCHOOL_CONVEYANCE); + spell_type_set_mana(spell, 20, 40); + spell_type_set_inertia(spell, 4, 30); + spell_type_set_difficulty(spell, 30, 95); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_UDUN, + udun_wraithform_info, + udun_wraithform); } { spell_type *spell = spell_new(&FLAMEOFUDUN, "FLAMEOFUDUN", "Flame of Udun"); - string_list_append(&spell->description, "Turns you into a powerful Balrog"); - school_idx_add_new(&spell->schools, SCHOOL_UDUN); - school_idx_add_new(&spell->schools, SCHOOL_FIRE); - range_init(&spell->mana_range, 70, 100); - spell_inertia_init(spell, 7, 15); - spell->info_func = udun_flame_of_udun_info; - spell->effect_func = udun_flame_of_udun; - spell->failure_rate = 95; - spell->skill_level = 35; - spell_init_mage(spell, RANDOM); + spell_type_describe(spell, "Turns you into a powerful Balrog"); + spell_type_add_school(spell, SCHOOL_FIRE); + spell_type_set_mana(spell, 70, 100); + spell_type_set_inertia(spell, 7, 15); + spell_type_set_difficulty(spell, 35, 95); + spell_type_init_mage(spell, + RANDOM, + SCHOOL_UDUN, + udun_flame_of_udun_info, + udun_flame_of_udun); } { spell_type *spell = spell_new(&CALL_THE_ELEMENTS, "CALL_THE_ELEMENTS", "Call the Elements"); - string_list_append(&spell->description, "Randomly creates various elements around you"); - string_list_append(&spell->description, "Each type of element chance is controlled by your level"); - string_list_append(&spell->description, "in the corresponding skill"); - string_list_append(&spell->description, "At level 17 it can be targeted"); - school_idx_add_new(&spell->schools, SCHOOL_GEOMANCY); - range_init(&spell->mana_range, 2, 20); - spell->info_func = geomancy_call_the_elements_info; - spell->effect_func = geomancy_call_the_elements; - spell->failure_rate = 10; - spell->skill_level = 1; - spell->castable_while_blind = TRUE; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "Randomly creates various elements around you"); + spell_type_describe(spell, "Each type of element chance is controlled by your level"); + spell_type_describe(spell, "in the corresponding skill"); + spell_type_describe(spell, "At level 17 it can be targeted"); + spell_type_set_mana(spell, 2, 20); + spell_type_set_difficulty(spell, 1, 10); + spell_type_set_castable_while_blind(spell, TRUE); + spell_type_init_mage(spell, + NO_RANDOM, + SCHOOL_GEOMANCY, + geomancy_call_the_elements_info, + geomancy_call_the_elements); } { spell_type *spell = spell_new(&CHANNEL_ELEMENTS, "CHANNEL_ELEMENTS", "Channel Elements"); - string_list_append(&spell->description, "Draws on the caster's immediate environs to form an attack or other effect."); - string_list_append(&spell->description, "Grass/Flower heals."); - string_list_append(&spell->description, "Water creates water bolt attacks."); - string_list_append(&spell->description, "Ice creates ice bolt attacks."); - string_list_append(&spell->description, "Sand creates a wall of thick, blinding, burning sand around you."); - string_list_append(&spell->description, "Lava creates fire bolt attacks."); - string_list_append(&spell->description, "Deep lava creates fire ball attacks."); - string_list_append(&spell->description, "Chasm creates darkness bolt attacks."); - string_list_append(&spell->description, "At Earth level 18, darkness becomes nether."); - string_list_append(&spell->description, "At Water level 8, water attacks become beams with a striking effect."); - string_list_append(&spell->description, "At Water level 12, ice attacks become balls of ice shards."); - string_list_append(&spell->description, "At Water level 18, water attacks push monsters back."); - string_list_append(&spell->description, "At Fire level 15, fire become hellfire."); - school_idx_add_new(&spell->schools, SCHOOL_GEOMANCY); - range_init(&spell->mana_range, 3, 30); - spell->info_func = geomancy_channel_elements_info; - spell->effect_func = geomancy_channel_elements; - spell->failure_rate = 20; - spell->skill_level = 3; - spell->castable_while_blind = TRUE; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "Draws on the caster's immediate environs to form an attack or other effect."); + spell_type_describe(spell, "Grass/Flower heals."); + spell_type_describe(spell, "Water creates water bolt attacks."); + spell_type_describe(spell, "Ice creates ice bolt attacks."); + spell_type_describe(spell, "Sand creates a wall of thick, blinding, burning sand around you."); + spell_type_describe(spell, "Lava creates fire bolt attacks."); + spell_type_describe(spell, "Deep lava creates fire ball attacks."); + spell_type_describe(spell, "Chasm creates darkness bolt attacks."); + spell_type_describe(spell, "At Earth level 18, darkness becomes nether."); + spell_type_describe(spell, "At Water level 8, water attacks become beams with a striking effect."); + spell_type_describe(spell, "At Water level 12, ice attacks become balls of ice shards."); + spell_type_describe(spell, "At Water level 18, water attacks push monsters back."); + spell_type_describe(spell, "At Fire level 15, fire become hellfire."); + spell_type_set_mana(spell, 3, 30); + spell_type_set_difficulty(spell, 3, 20); + spell_type_set_castable_while_blind(spell, TRUE); + spell_type_init_mage(spell, + NO_RANDOM, + SCHOOL_GEOMANCY, + geomancy_channel_elements_info, + geomancy_channel_elements); } { spell_type *spell = spell_new(&ELEMENTAL_WAVE, "ELEMENTAL_WAVE", "Elemental Wave"); - string_list_append(&spell->description, "Draws on an adjacent special square to project a slow-moving"); - string_list_append(&spell->description, "wave of that element in that direction"); - string_list_append(&spell->description, "Abyss squares cannot be channeled into a wave."); - school_idx_add_new(&spell->schools, SCHOOL_GEOMANCY); - range_init(&spell->mana_range, 15, 50); - spell->info_func = geomancy_elemental_wave_info; - spell->effect_func = geomancy_elemental_wave; - spell->failure_rate = 20; - spell->skill_level = 15; - spell->castable_while_blind = TRUE; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "Draws on an adjacent special square to project a slow-moving"); + spell_type_describe(spell, "wave of that element in that direction"); + spell_type_describe(spell, "Abyss squares cannot be channeled into a wave."); + spell_type_set_mana(spell, 15, 50); + spell_type_set_difficulty(spell, 15, 20); + spell_type_set_castable_while_blind(spell, TRUE); + spell_type_init_mage(spell, + NO_RANDOM, + SCHOOL_GEOMANCY, + geomancy_elemental_wave_info, + geomancy_elemental_wave); } { spell_type *spell = spell_new(&VAPORIZE, "VAPORIZE", "Vaporize"); - string_list_append(&spell->description, "Draws upon your immediate environs to form a cloud of damaging vapors"); - school_idx_add_new(&spell->schools, SCHOOL_GEOMANCY); - range_init(&spell->mana_range, 3, 30); - spell->info_func = geomancy_vaporize_info; - spell->effect_func = geomancy_vaporize; - spell->depend_func = geomancy_vaporize_depends; - spell->failure_rate = 15; - spell->skill_level = 4; - spell->castable_while_blind = TRUE; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "Draws upon your immediate environs to form a cloud of damaging vapors"); + spell_type_set_mana(spell, 3, 30); + spell_type_set_difficulty(spell, 4, 15); + spell_type_set_castable_while_blind(spell, TRUE); + spell_type_init_geomancy( + spell, + geomancy_vaporize_info, + geomancy_vaporize, + geomancy_vaporize_depends); } { spell_type *spell = spell_new(&GEOLYSIS, "GEOLYSIS", "Geolysis"); - string_list_append(&spell->description, "Burrows deeply and slightly at random into a wall,"); - string_list_append(&spell->description, "leaving behind tailings of various different sorts of walls in the passage."); - school_idx_add_new(&spell->schools, SCHOOL_GEOMANCY); - range_init(&spell->mana_range, 15, 40); - spell->info_func = geomancy_geolysis_info; - spell->effect_func = geomancy_geolysis; - spell->depend_func = geomancy_geolysis_depends; - spell->failure_rate = 15; - spell->skill_level = 7; - spell->castable_while_blind = TRUE; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "Burrows deeply and slightly at random into a wall,"); + spell_type_describe(spell, "leaving behind tailings of various different sorts of walls in the passage."); + spell_type_set_mana(spell, 15, 40); + spell_type_set_difficulty(spell, 7, 15); + spell_type_set_castable_while_blind(spell, TRUE); + spell_type_init_geomancy( + spell, + geomancy_geolysis_info, + geomancy_geolysis, + geomancy_geolysis_depends); } { spell_type *spell = spell_new(&DRIPPING_TREAD, "DRIPPING_TREAD", "Dripping Tread"); - string_list_append(&spell->description, "Causes you to leave random elemental forms behind as you walk"); - school_idx_add_new(&spell->schools, SCHOOL_GEOMANCY); - range_init(&spell->mana_range, 15, 25); - spell->info_func = geomancy_dripping_tread_info; - spell->effect_func = geomancy_dripping_tread; - spell->depend_func = geomancy_dripping_tread_depends; - spell->failure_rate = 15; - spell->skill_level = 10; - spell->castable_while_blind = TRUE; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "Causes you to leave random elemental forms behind as you walk"); + spell_type_set_mana(spell, 15, 25); + spell_type_set_difficulty(spell, 10, 15); + spell_type_set_castable_while_blind(spell, TRUE); + spell_type_init_geomancy( + spell, + geomancy_dripping_tread_info, + geomancy_dripping_tread, + geomancy_dripping_tread_depends); } { spell_type *spell = spell_new(&GROW_BARRIER, "GROW_BARRIER", "Grow Barrier"); - string_list_append(&spell->description, "Creates impassable terrain (walls, trees, etc.) around you."); - string_list_append(&spell->description, "At level 20 it can be projected around another area."); - school_idx_add_new(&spell->schools, SCHOOL_GEOMANCY); - range_init(&spell->mana_range, 30, 40); - spell->info_func = geomancy_grow_barrier_info; - spell->effect_func = geomancy_grow_barrier; - spell->depend_func = geomancy_grow_barrier_depends; - spell->failure_rate = 15; - spell->skill_level = 12; - spell->castable_while_blind = TRUE; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "Creates impassable terrain (walls, trees, etc.) around you."); + spell_type_describe(spell, "At level 20 it can be projected around another area."); + spell_type_set_mana(spell, 30, 40); + spell_type_set_difficulty(spell, 12, 15); + spell_type_set_castable_while_blind(spell, TRUE); + spell_type_init_geomancy( + spell, + geomancy_grow_barrier_info, + geomancy_grow_barrier, + geomancy_grow_barrier_depends); } { spell_type *spell = spell_new(&ELEMENTAL_MINION, "ELEMENTAL_MINION", "Elemental Minion"); - string_list_append(&spell->description, "Summons a minion from a nearby element."); - string_list_append(&spell->description, "Walls can summon Earth elmentals, Xorns and Xarens"); - string_list_append(&spell->description, "Dark Pits can summon Air elementals, Ancient blue dragons, Great Storm Wyrms"); - string_list_append(&spell->description, "and Sky Drakes"); - string_list_append(&spell->description, "Sandwalls and lava can summon Fire elementals and Ancient red dragons"); - string_list_append(&spell->description, "Icewall, and water can summon Water elementals, Water trolls and Water demons"); - school_idx_add_new(&spell->schools, SCHOOL_GEOMANCY); - range_init(&spell->mana_range, 40, 80); - spell->info_func = geomancy_elemental_minion_info; - spell->effect_func = geomancy_elemental_minion; - spell->failure_rate = 25; - spell->skill_level = 20; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "Summons a minion from a nearby element."); + spell_type_describe(spell, "Walls can summon Earth elmentals, Xorns and Xarens"); + spell_type_describe(spell, "Dark Pits can summon Air elementals, Ancient blue dragons, Great Storm Wyrms"); + spell_type_describe(spell, "and Sky Drakes"); + spell_type_describe(spell, "Sandwalls and lava can summon Fire elementals and Ancient red dragons"); + spell_type_describe(spell, "Icewall, and water can summon Water elementals, Water trolls and Water demons"); + spell_type_set_mana(spell, 40, 80); + spell_type_set_difficulty(spell, 20, 25); + spell_type_init_geomancy( + spell, + geomancy_elemental_minion_info, + geomancy_elemental_minion, + NULL); } { spell_type *spell = spell_new(&ERU_SEE, "ERU_SEE", "See the Music"); - string_list_append(&spell->description, "Allows you to 'see' the Great Music from which the world"); - string_list_append(&spell->description, "originates, allowing you to see unseen things"); - string_list_append(&spell->description, "At level 10 it allows you to see your surroundings"); - string_list_append(&spell->description, "At level 20 it allows you to cure blindness"); - string_list_append(&spell->description, "At level 30 it allows you to fully see all the level"); - school_idx_add_new(&spell->schools, SCHOOL_ERU); - range_init(&spell->mana_range, 1, 50); - spell->info_func = eru_see_the_music_info; - spell->effect_func = eru_see_the_music; - spell->failure_rate = 20; - spell->skill_level = 1; - spell_init_priest(spell); - spell->castable_while_blind = TRUE; + spell_type_describe(spell, "Allows you to 'see' the Great Music from which the world"); + spell_type_describe(spell, "originates, allowing you to see unseen things"); + spell_type_describe(spell, "At level 10 it allows you to see your surroundings"); + spell_type_describe(spell, "At level 20 it allows you to cure blindness"); + spell_type_describe(spell, "At level 30 it allows you to fully see all the level"); + spell_type_set_mana(spell, 1, 50); + spell_type_set_difficulty(spell, 1, 20); + spell_type_init_priest(spell, + SCHOOL_ERU, + eru_see_the_music_info, + eru_see_the_music); + spell_type_set_castable_while_blind(spell, TRUE); } { spell_type *spell = spell_new(&ERU_LISTEN, "ERU_LISTEN", "Listen to the Music"); - string_list_append(&spell->description, "Allows you to listen to the Great Music from which the world"); - string_list_append(&spell->description, "originates, allowing you to understand the meaning of things"); - string_list_append(&spell->description, "At level 14 it allows you to identify all your pack"); - string_list_append(&spell->description, "At level 30 it allows you to identify all items on the level"); - school_idx_add_new(&spell->schools, SCHOOL_ERU); - range_init(&spell->mana_range, 15, 200); - spell->info_func = eru_listen_to_the_music_info; - spell->effect_func = eru_listen_to_the_music; - spell->failure_rate = 25; - spell->skill_level = 7; - spell_init_priest(spell); + spell_type_describe(spell, "Allows you to listen to the Great Music from which the world"); + spell_type_describe(spell, "originates, allowing you to understand the meaning of things"); + spell_type_describe(spell, "At level 14 it allows you to identify all your pack"); + spell_type_describe(spell, "At level 30 it allows you to identify all items on the level"); + spell_type_set_mana(spell, 15, 200); + spell_type_set_difficulty(spell, 7, 25); + spell_type_init_priest(spell, + SCHOOL_ERU, + eru_listen_to_the_music_info, + eru_listen_to_the_music); } { spell_type *spell = spell_new(&ERU_UNDERSTAND, "ERU_UNDERSTAND", "Know the Music"); - string_list_append(&spell->description, "Allows you to understand the Great Music from which the world"); - string_list_append(&spell->description, "originates, allowing you to know the full abilities of things"); - string_list_append(&spell->description, "At level 10 it allows you to *identify* all your pack"); - school_idx_add_new(&spell->schools, SCHOOL_ERU); - range_init(&spell->mana_range, 200, 600); - spell->info_func = eru_know_the_music_info; - spell->effect_func = eru_know_the_music; - spell->failure_rate = 50; - spell->skill_level = 30; - spell_init_priest(spell); + spell_type_describe(spell, "Allows you to understand the Great Music from which the world"); + spell_type_describe(spell, "originates, allowing you to know the full abilities of things"); + spell_type_describe(spell, "At level 10 it allows you to *identify* all your pack"); + spell_type_set_mana(spell, 200, 600); + spell_type_set_difficulty(spell, 30, 50); + spell_type_init_priest(spell, + SCHOOL_ERU, + eru_know_the_music_info, + eru_know_the_music); } { spell_type *spell = spell_new(&ERU_PROT, "ERU_PROT", "Lay of Protection"); - string_list_append(&spell->description, "Creates a circle of safety around you"); - school_idx_add_new(&spell->schools, SCHOOL_ERU); - range_init(&spell->mana_range, 400, 400); - spell->info_func = eru_lay_of_protection_info; - spell->effect_func = eru_lay_of_protection; - spell->failure_rate = 80; - spell->skill_level = 35; - spell_init_priest(spell); + spell_type_describe(spell, "Creates a circle of safety around you"); + spell_type_set_mana(spell, 400, 400); + spell_type_set_difficulty(spell, 35, 80); + spell_type_init_priest(spell, + SCHOOL_ERU, + eru_lay_of_protection_info, + eru_lay_of_protection); } { spell_type *spell = spell_new(&MANWE_SHIELD, "MANWE_SHIELD", "Wind Shield"); - string_list_append(&spell->description, "It surrounds you with a shield of wind that deflects blows from evil monsters"); - string_list_append(&spell->description, "At level 10 it increases your armour rating"); - string_list_append(&spell->description, "At level 20 it retaliates against monsters that melee you"); - school_idx_add_new(&spell->schools, SCHOOL_MANWE); - range_init(&spell->mana_range, 100, 500); - spell->info_func = manwe_wind_shield_info; - spell->effect_func = manwe_wind_shield; - spell->failure_rate = 30; - spell->skill_level = 10; - spell_init_priest(spell); + spell_type_describe(spell, "It surrounds you with a shield of wind that deflects blows from evil monsters"); + spell_type_describe(spell, "At level 10 it increases your armour rating"); + spell_type_describe(spell, "At level 20 it retaliates against monsters that melee you"); + spell_type_set_mana(spell, 100, 500); + spell_type_set_difficulty(spell, 10, 30); + spell_type_init_priest(spell, + SCHOOL_MANWE, + manwe_wind_shield_info, + manwe_wind_shield); } { spell_type *spell = spell_new(&MANWE_AVATAR, "MANWE_AVATAR", "Avatar"); - string_list_append(&spell->description, "It turns you into a full grown Maia"); - school_idx_add_new(&spell->schools, SCHOOL_MANWE); - range_init(&spell->mana_range, 1000, 1000); - spell->info_func = manwe_avatar_info; - spell->effect_func = manwe_avatar; - spell->failure_rate = 80; - spell->skill_level = 35; - spell_init_priest(spell); + spell_type_describe(spell, "It turns you into a full grown Maia"); + spell_type_set_mana(spell, 1000, 1000); + spell_type_set_difficulty(spell, 35, 80); + spell_type_init_priest(spell, + SCHOOL_MANWE, + manwe_avatar_info, + manwe_avatar); } { spell_type *spell = spell_new(&MANWE_BLESS, "MANWE_BLESS", "Manwe's Blessing"); - string_list_append(&spell->description, "Manwe's Blessing removes your fears, blesses you and surrounds you with"); - string_list_append(&spell->description, "holy light"); - string_list_append(&spell->description, "At level 10 it also grants heroism"); - string_list_append(&spell->description, "At level 20 it also grants super heroism"); - string_list_append(&spell->description, "At level 30 it also grants holy luck and life protection"); - school_idx_add_new(&spell->schools, SCHOOL_MANWE); - range_init(&spell->mana_range, 10, 100); - spell->info_func = manwe_blessing_info; - spell->effect_func = manwe_blessing; - spell->failure_rate = 20; - spell->skill_level = 1; - spell_init_priest(spell); + spell_type_describe(spell, "Manwe's Blessing removes your fears, blesses you and surrounds you with"); + spell_type_describe(spell, "holy light"); + spell_type_describe(spell, "At level 10 it also grants heroism"); + spell_type_describe(spell, "At level 20 it also grants super heroism"); + spell_type_describe(spell, "At level 30 it also grants holy luck and life protection"); + spell_type_set_mana(spell, 10, 100); + spell_type_set_difficulty(spell, 1, 20); + spell_type_init_priest(spell, + SCHOOL_MANWE, + manwe_blessing_info, + manwe_blessing); } { spell_type *spell = spell_new(&MANWE_CALL, "MANWE_CALL", "Manwe's Call"); - string_list_append(&spell->description, "Manwe's Call summons a Great Eagle to help you battle the forces"); - string_list_append(&spell->description, "of Morgoth"); - school_idx_add_new(&spell->schools, SCHOOL_MANWE); - range_init(&spell->mana_range, 200, 500); - spell->info_func = manwe_call_info; - spell->effect_func = manwe_call; - spell->failure_rate = 40; - spell->skill_level = 20; - spell_init_priest(spell); + spell_type_describe(spell, "Manwe's Call summons a Great Eagle to help you battle the forces"); + spell_type_describe(spell, "of Morgoth"); + spell_type_set_mana(spell, 200, 500); + spell_type_set_difficulty(spell, 20, 40); + spell_type_init_priest(spell, + SCHOOL_MANWE, + manwe_call_info, + manwe_call); } { spell_type *spell = spell_new(&TULKAS_AIM, "TULKAS_AIM", "Divine Aim"); - string_list_append(&spell->description, "It makes you more accurate in combat"); - string_list_append(&spell->description, "At level 20 all your blows are critical hits"); - school_idx_add_new(&spell->schools, SCHOOL_TULKAS); - range_init(&spell->mana_range, 30, 500); - spell->info_func = tulkas_divine_aim_info; - spell->effect_func = tulkas_divine_aim; - spell->failure_rate = 20; - spell->skill_level = 1; - spell_init_priest(spell); + spell_type_describe(spell, "It makes you more accurate in combat"); + spell_type_describe(spell, "At level 20 all your blows are critical hits"); + spell_type_set_mana(spell, 30, 500); + spell_type_set_difficulty(spell, 1, 20); + spell_type_init_priest(spell, + SCHOOL_TULKAS, + tulkas_divine_aim_info, + tulkas_divine_aim); } { spell_type *spell = spell_new(&TULKAS_WAVE, "TULKAS_WAVE", "Wave of Power"); - string_list_append(&spell->description, "It allows you to project a number of melee blows across a distance"); - school_idx_add_new(&spell->schools, SCHOOL_TULKAS); - range_init(&spell->mana_range, 200, 200); - spell->info_func = tulkas_wave_of_power_info; - spell->effect_func = tulkas_wave_of_power; - spell->failure_rate = 75; - spell->skill_level = 20; - spell_init_priest(spell); + spell_type_describe(spell, "It allows you to project a number of melee blows across a distance"); + spell_type_set_mana(spell, 200, 200); + spell_type_set_difficulty(spell, 20, 75); + spell_type_init_priest(spell, + SCHOOL_TULKAS, + tulkas_wave_of_power_info, + tulkas_wave_of_power); } { spell_type *spell = spell_new(&TULKAS_SPIN, "TULKAS_SPIN", "Whirlwind"); - string_list_append(&spell->description, "It allows you to spin around and hit all monsters nearby"); - school_idx_add_new(&spell->schools, SCHOOL_TULKAS); - range_init(&spell->mana_range, 100, 100); - spell->info_func = tulkas_whirlwind_info; - spell->effect_func = tulkas_whirlwind; - spell->failure_rate = 45; - spell->skill_level = 10; - spell_init_priest(spell); + spell_type_describe(spell, "It allows you to spin around and hit all monsters nearby"); + spell_type_set_mana(spell, 100, 100); + spell_type_set_difficulty(spell, 10, 45); + spell_type_init_priest(spell, + SCHOOL_TULKAS, + tulkas_whirlwind_info, + tulkas_whirlwind); } { spell_type *spell = spell_new(&MELKOR_CURSE, "MELKOR_CURSE", "Curse"); - string_list_append(&spell->description, "It curses a monster, reducing its melee power"); - string_list_append(&spell->description, "At level 5 it can be auto-casted (with no piety cost) while fighting"); - string_list_append(&spell->description, "At level 15 it also reduces armor"); - string_list_append(&spell->description, "At level 25 it also reduces speed"); - string_list_append(&spell->description, "At level 35 it also reduces max life (but it is never fatal)"); - school_idx_add_new(&spell->schools, SCHOOL_MELKOR); - range_init(&spell->mana_range, 50, 300); - spell->info_func = melkor_curse_info; - spell->effect_func = melkor_curse; - spell->failure_rate = 20; - spell->skill_level = 1; - spell_init_priest(spell); + spell_type_describe(spell, "It curses a monster, reducing its melee power"); + spell_type_describe(spell, "At level 5 it can be auto-casted (with no piety cost) while fighting"); + spell_type_describe(spell, "At level 15 it also reduces armor"); + spell_type_describe(spell, "At level 25 it also reduces speed"); + spell_type_describe(spell, "At level 35 it also reduces max life (but it is never fatal)"); + spell_type_set_mana(spell, 50, 300); + spell_type_set_difficulty(spell, 1, 20); + spell_type_init_priest(spell, + SCHOOL_MELKOR, + melkor_curse_info, + melkor_curse); } { spell_type *spell = spell_new(&MELKOR_CORPSE_EXPLOSION, "MELKOR_CORPSE_EXPLOSION", "Corpse Explosion"); - string_list_append(&spell->description, "It makes corpses in an area around you explode for a percent of their"); - string_list_append(&spell->description, "hit points as damage"); - school_idx_add_new(&spell->schools, SCHOOL_MELKOR); - range_init(&spell->mana_range, 100, 500); - spell->info_func = melkor_corpse_explosion_info; - spell->effect_func = melkor_corpse_explosion; - spell->failure_rate = 45; - spell->skill_level = 10; - spell_init_priest(spell); + spell_type_describe(spell, "It makes corpses in an area around you explode for a percent of their"); + spell_type_describe(spell, "hit points as damage"); + spell_type_set_mana(spell, 100, 500); + spell_type_set_difficulty(spell, 10, 45); + spell_type_init_priest(spell, + SCHOOL_MELKOR, + melkor_corpse_explosion_info, + melkor_corpse_explosion); } { spell_type *spell = spell_new(&MELKOR_MIND_STEAL, "MELKOR_MIND_STEAL", "Mind Steal"); - string_list_append(&spell->description, "It allows your spirit to temporarily leave your own body, which will"); - string_list_append(&spell->description, "be vulnerable, to control one of your enemies body."); - school_idx_add_new(&spell->schools, SCHOOL_MELKOR); - range_init(&spell->mana_range, 1000, 3000); - spell->info_func = melkor_mind_steal_info; - spell->effect_func = melkor_mind_steal; - spell->failure_rate = 90; - spell->skill_level = 20; - spell_init_priest(spell); + spell_type_describe(spell, "It allows your spirit to temporarily leave your own body, which will"); + spell_type_describe(spell, "be vulnerable, to control one of your enemies body."); + spell_type_set_mana(spell, 1000, 3000); + spell_type_set_difficulty(spell, 20, 90); + spell_type_init_priest(spell, + SCHOOL_MELKOR, + melkor_mind_steal_info, + melkor_mind_steal); } { spell_type *spell = spell_new(&YAVANNA_CHARM_ANIMAL, "YAVANNA_CHARM_ANIMAL", "Charm Animal"); - string_list_append(&spell->description, "It tries to tame an animal"); - school_idx_add_new(&spell->schools, SCHOOL_YAVANNA); - range_init(&spell->mana_range, 10, 100); - spell->info_func = yavanna_charm_animal_info; - spell->effect_func = yavanna_charm_animal; - spell->failure_rate = 30; - spell->skill_level = 1; - spell_init_priest(spell); + spell_type_describe(spell, "It tries to tame an animal"); + spell_type_set_mana(spell, 10, 100); + spell_type_set_difficulty(spell, 1, 30); + spell_type_init_priest(spell, + SCHOOL_YAVANNA, + yavanna_charm_animal_info, + yavanna_charm_animal); } { spell_type *spell = spell_new(&YAVANNA_GROW_GRASS, "YAVANNA_GROW_GRASS", "Grow Grass"); - string_list_append(&spell->description, "Create a floor of grass around you. While on grass and praying"); - string_list_append(&spell->description, "a worshipper of Yavanna will know a greater regeneration rate"); - school_idx_add_new(&spell->schools, SCHOOL_YAVANNA); - range_init(&spell->mana_range, 70, 150); - spell->info_func = yavanna_grow_grass_info; - spell->effect_func = yavanna_grow_grass; - spell->failure_rate = 65; - spell->skill_level = 10; - spell_init_priest(spell); + spell_type_describe(spell, "Create a floor of grass around you. While on grass and praying"); + spell_type_describe(spell, "a worshipper of Yavanna will know a greater regeneration rate"); + spell_type_set_mana(spell, 70, 150); + spell_type_set_difficulty(spell, 10, 65); + spell_type_init_priest(spell, + SCHOOL_YAVANNA, + yavanna_grow_grass_info, + yavanna_grow_grass); } { spell_type *spell = spell_new(&YAVANNA_TREE_ROOTS, "YAVANNA_TREE_ROOTS", "Tree Roots"); - string_list_append(&spell->description, "Creates roots deep in the floor from your feet, making you more stable and able"); - string_list_append(&spell->description, "to make stronger attacks, but prevents any movement (even teleportation)."); - string_list_append(&spell->description, "It also makes you recover from stunning almost immediately."); - school_idx_add_new(&spell->schools, SCHOOL_YAVANNA); - range_init(&spell->mana_range, 50, 1000); - spell->info_func = yavanna_tree_roots_info; - spell->effect_func = yavanna_tree_roots; - spell->failure_rate = 70; - spell->skill_level = 15; - spell_init_priest(spell); + spell_type_describe(spell, "Creates roots deep in the floor from your feet, making you more stable and able"); + spell_type_describe(spell, "to make stronger attacks, but prevents any movement (even teleportation)."); + spell_type_describe(spell, "It also makes you recover from stunning almost immediately."); + spell_type_set_mana(spell, 50, 1000); + spell_type_set_difficulty(spell, 15, 70); + spell_type_init_priest(spell, + SCHOOL_YAVANNA, + yavanna_tree_roots_info, + yavanna_tree_roots); } { spell_type *spell = spell_new(&YAVANNA_WATER_BITE, "YAVANNA_WATER_BITE", "Water Bite"); - string_list_append(&spell->description, "Imbues your melee weapon with a natural stream of water"); - string_list_append(&spell->description, "At level 25, it spreads over a 1 radius zone around your target"); - school_idx_add_new(&spell->schools, SCHOOL_YAVANNA); - range_init(&spell->mana_range, 150, 300); - spell->info_func = yavanna_water_bite_info; - spell->effect_func = yavanna_water_bite; - spell->failure_rate = 90; - spell->skill_level = 20; - spell_init_priest(spell); + spell_type_describe(spell, "Imbues your melee weapon with a natural stream of water"); + spell_type_describe(spell, "At level 25, it spreads over a 1 radius zone around your target"); + spell_type_set_mana(spell, 150, 300); + spell_type_set_difficulty(spell, 20, 90); + spell_type_init_priest(spell, + SCHOOL_YAVANNA, + yavanna_water_bite_info, + yavanna_water_bite); } { spell_type *spell = spell_new(&YAVANNA_UPROOT, "YAVANNA_UPROOT", "Uproot"); - string_list_append(&spell->description, "Awakes a tree to help you battle the forces of Morgoth"); - school_idx_add_new(&spell->schools, SCHOOL_YAVANNA); - range_init(&spell->mana_range, 250, 350); - spell->info_func = yavanna_uproot_info; - spell->effect_func = yavanna_uproot; - spell->failure_rate = 95; - spell->skill_level = 35; - spell_init_priest(spell); + spell_type_describe(spell, "Awakes a tree to help you battle the forces of Morgoth"); + spell_type_set_mana(spell, 250, 350); + spell_type_set_difficulty(spell, 35, 95); + spell_type_init_priest(spell, + SCHOOL_YAVANNA, + yavanna_uproot_info, + yavanna_uproot); } { spell_type *spell = spell_new(&DEMON_BLADE, "DEMON_BLADE", "Demon Blade"); - string_list_append(&spell->description, "Imbues your blade with fire to deal more damage"); - string_list_append(&spell->description, "At level 30 it deals hellfire damage"); - string_list_append(&spell->description, "At level 45 it spreads over a 1 radius zone around your target"); - school_idx_add_new(&spell->schools, SCHOOL_DEMON); - range_init(&spell->mana_range, 4, 44); - spell->info_func = demonology_demon_blade_info; - spell->effect_func = demonology_demon_blade; - spell->failure_rate = 10; - spell->skill_level = 1; - spell_init_mage(spell, NO_RANDOM); - - dice_parse_checked(&spell->device_charges, "3+d7"); + spell_type_describe(spell, "Imbues your blade with fire to deal more damage"); + spell_type_describe(spell, "At level 30 it deals hellfire damage"); + spell_type_describe(spell, "At level 45 it spreads over a 1 radius zone around your target"); + spell_type_set_mana(spell, 4, 44); + spell_type_set_difficulty(spell, 1, 10); + spell_type_init_demonology(spell, + demonology_demon_blade_info, + demonology_demon_blade); + + spell_type_set_device_charges(spell, "3+d7"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 75; range_init(&device_allocation->base_level, 1, 17); range_init(&device_allocation->max_level, 20, 40); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&DEMON_MADNESS, "DEMON_MADNESS", "Demon Madness"); - string_list_append(&spell->description, "Fire 2 balls in opposite directions of randomly chaos, confusion or charm"); - school_idx_add_new(&spell->schools, SCHOOL_DEMON); - range_init(&spell->mana_range, 5, 20); - spell->info_func = demonology_demon_madness_info; - spell->effect_func = demonology_demon_madness; - spell->failure_rate = 25; - spell->skill_level = 10; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "Fire 2 balls in opposite directions of randomly chaos, confusion or charm"); + spell_type_set_mana(spell, 5, 20); + spell_type_set_difficulty(spell, 10, 25); + spell_type_init_demonology(spell, + demonology_demon_madness_info, + demonology_demon_madness); } { spell_type *spell = spell_new(&DEMON_FIELD, "DEMON_FIELD", "Demon Field"); - string_list_append(&spell->description, "Fires a cloud of deadly nexus over a radius of 7"); - school_idx_add_new(&spell->schools, SCHOOL_DEMON); - range_init(&spell->mana_range, 20, 60); - spell->info_func = demonology_demon_field_info; - spell->effect_func = demonology_demon_field; - spell->failure_rate = 60; - spell->skill_level = 20; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "Fires a cloud of deadly nexus over a radius of 7"); + spell_type_set_mana(spell, 20, 60); + spell_type_set_difficulty(spell, 20, 60); + spell_type_init_demonology(spell, + demonology_demon_field_info, + demonology_demon_field); } { spell_type *spell = spell_new(&DOOM_SHIELD, "DOOM_SHIELD", "Doom Shield"); - string_list_append(&spell->description, "Raises a mirror of pain around you, doing very high damage to your foes"); - string_list_append(&spell->description, "that dare hit you, but greatly reduces your armour class"); - school_idx_add_new(&spell->schools, SCHOOL_DEMON); - range_init(&spell->mana_range, 2, 30); - spell->info_func = demonology_doom_shield_info; - spell->effect_func = demonology_doom_shield; - spell->failure_rate = 10; - spell->skill_level = 1; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "Raises a mirror of pain around you, doing very high damage to your foes"); + spell_type_describe(spell, "that dare hit you, but greatly reduces your armour class"); + spell_type_set_mana(spell, 2, 30); + spell_type_set_difficulty(spell, 1, 10); + spell_type_init_demonology(spell, + demonology_doom_shield_info, + demonology_doom_shield); } { spell_type *spell = spell_new(&UNHOLY_WORD, "UNHOLY_WORD", "Unholy Word"); - string_list_append(&spell->description, "Kills a pet to heal you"); - string_list_append(&spell->description, "There is a chance that the pet won't die but will turn against you"); - string_list_append(&spell->description, "it will decrease with higher level"); - school_idx_add_new(&spell->schools, SCHOOL_DEMON); - range_init(&spell->mana_range, 15, 45); - spell->info_func = demonology_unholy_word_info; - spell->effect_func = demonology_unholy_word; - spell->failure_rate = 55; - spell->skill_level = 25; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "Kills a pet to heal you"); + spell_type_describe(spell, "There is a chance that the pet won't die but will turn against you"); + spell_type_describe(spell, "it will decrease with higher level"); + spell_type_set_mana(spell, 15, 45); + spell_type_set_difficulty(spell, 25, 55); + spell_type_init_demonology(spell, + demonology_unholy_word_info, + demonology_unholy_word); } { spell_type *spell = spell_new(&DEMON_CLOAK, "DEMON_CLOAK", "Demon Cloak"); - string_list_append(&spell->description, "Raises a mirror that can reflect bolts and arrows for a time"); - school_idx_add_new(&spell->schools, SCHOOL_DEMON); - range_init(&spell->mana_range, 10, 40); - spell->info_func = demonology_demon_cloak_info; - spell->effect_func = demonology_demon_cloak; - spell->failure_rate = 70; - spell->skill_level = 20; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "Raises a mirror that can reflect bolts and arrows for a time"); + spell_type_set_mana(spell, 10, 40); + spell_type_set_difficulty(spell, 20, 70); + spell_type_init_demonology(spell, + demonology_demon_cloak_info, + demonology_demon_cloak); } { spell_type *spell = spell_new(&DEMON_SUMMON, "DEMON_SUMMON", "Summon Demon"); - string_list_append(&spell->description, "Summons a leveled demon to your side"); - string_list_append(&spell->description, "At level 35 it summons a high demon"); - school_idx_add_new(&spell->schools, SCHOOL_DEMON); - range_init(&spell->mana_range, 10, 50); - spell->info_func = demonology_summon_demon_info; - spell->effect_func = demonology_summon_demon; - spell->failure_rate = 30; - spell->skill_level = 5; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "Summons a leveled demon to your side"); + spell_type_describe(spell, "At level 35 it summons a high demon"); + spell_type_set_mana(spell, 10, 50); + spell_type_set_difficulty(spell, 5, 30); + spell_type_init_demonology(spell, + demonology_summon_demon_info, + demonology_summon_demon); } { spell_type *spell = spell_new(&DISCHARGE_MINION, "DISCHARGE_MINION", "Discharge Minion"); - string_list_append(&spell->description, "The targeted pet will explode in a burst of gravity"); - school_idx_add_new(&spell->schools, SCHOOL_DEMON); - range_init(&spell->mana_range, 20, 50); - spell->info_func = demonology_discharge_minion_info; - spell->effect_func = demonology_discharge_minion; - spell->failure_rate = 30; - spell->skill_level = 10; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "The targeted pet will explode in a burst of gravity"); + spell_type_set_mana(spell, 20, 50); + spell_type_set_difficulty(spell, 10, 30); + spell_type_init_demonology(spell, + demonology_discharge_minion_info, + demonology_discharge_minion); } { spell_type *spell = spell_new(&CONTROL_DEMON, "CONTROL_DEMON", "Control Demon"); - string_list_append(&spell->description, "Attempts to control a demon"); - school_idx_add_new(&spell->schools, SCHOOL_DEMON); - range_init(&spell->mana_range, 30, 70); - spell->info_func = demonology_control_demon_info; - spell->effect_func = demonology_control_demon; - spell->failure_rate = 55; - spell->skill_level = 25; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "Attempts to control a demon"); + spell_type_set_mana(spell, 30, 70); + spell_type_set_difficulty(spell, 25, 55); + spell_type_init_demonology(spell, + demonology_control_demon_info, + demonology_control_demon); } { spell_type *spell = spell_new(&DEVICE_HEAL_MONSTER, "DEVICE_HEAL_MONSTER", "Heal Monster"); - string_list_append(&spell->description, "Heals a monster"); - school_idx_add_new(&spell->schools, SCHOOL_DEVICE); - range_init(&spell->mana_range, 5, 20); - spell->info_func = device_heal_monster_info; - spell->effect_func = device_heal_monster; - spell->failure_rate = 15; - spell->skill_level = 3; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "Heals a monster"); + spell_type_set_mana(spell, 5, 20); + spell_type_set_difficulty(spell, 3, 15); + spell_type_init_device(spell, + device_heal_monster_info, + device_heal_monster); - dice_parse_checked(&spell->device_charges, "10+d10"); + spell_type_set_device_charges(spell, "10+d10"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 17; range_init(&device_allocation->base_level, 1, 15); range_init(&device_allocation->max_level, 20, 50); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&DEVICE_SPEED_MONSTER, "DEVICE_SPEED_MONSTER", "Haste Monster"); - string_list_append(&spell->description, "Haste a monster"); - school_idx_add_new(&spell->schools, SCHOOL_DEVICE); - range_init(&spell->mana_range, 10, 10); - spell->info_func = device_haste_monster_info; - spell->effect_func = device_haste_monster; - spell->failure_rate = 30; - spell->skill_level = 10; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "Haste a monster"); + spell_type_set_mana(spell, 10, 10); + spell_type_set_difficulty(spell, 10, 30); + spell_type_init_device(spell, + device_haste_monster_info, + device_haste_monster); - dice_parse_checked(&spell->device_charges, "10+d5"); + spell_type_set_device_charges(spell, "10+d5"); { device_allocation *device_allocation = device_allocation_new(TV_WAND); device_allocation->rarity = 7; range_init(&device_allocation->base_level, 1, 1); range_init(&device_allocation->max_level, 20, 50); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&DEVICE_WISH, "DEVICE_WISH", "Wish"); - string_list_append(&spell->description, "This grants you a wish, beware of what you ask for!"); - school_idx_add_new(&spell->schools, SCHOOL_DEVICE); - range_init(&spell->mana_range, 400, 400); - spell->info_func = device_wish_info; - spell->effect_func = device_wish; - spell->failure_rate = 99; - spell->skill_level = 50; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "This grants you a wish, beware of what you ask for!"); + spell_type_set_mana(spell, 400, 400); + spell_type_set_difficulty(spell, 50, 99); + spell_type_init_device(spell, + device_wish_info, + device_wish); - dice_parse_checked(&spell->device_charges, "1+d2"); + spell_type_set_device_charges(spell, "1+d2"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 98; range_init(&device_allocation->base_level, 1, 1); range_init(&device_allocation->max_level, 1, 1); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&DEVICE_SUMMON, "DEVICE_SUMMON", "Summon"); - string_list_append(&spell->description, "Summons hostile monsters near you"); - school_idx_add_new(&spell->schools, SCHOOL_DEVICE); - range_init(&spell->mana_range, 5, 25); - spell->info_func = device_summon_monster_info; - spell->effect_func = device_summon_monster; - spell->failure_rate = 20; - spell->skill_level = 5; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "Summons hostile monsters near you"); + spell_type_set_mana(spell, 5, 25); + spell_type_set_difficulty(spell, 5, 20); + spell_type_init_device(spell, + device_summon_monster_info, + device_summon_monster); - dice_parse_checked(&spell->device_charges, "1+d20"); + spell_type_set_device_charges(spell, "1+d20"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 13; range_init(&device_allocation->base_level, 1, 40); range_init(&device_allocation->max_level, 25, 50); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&DEVICE_MANA, "DEVICE_MANA", "Mana"); - string_list_append(&spell->description, "Restores a part(or all) of your mana"); - school_idx_add_new(&spell->schools, SCHOOL_DEVICE); - range_init(&spell->mana_range, 1, 1); - spell->info_func = device_mana_info; - spell->effect_func = device_mana; - spell->failure_rate = 80; - spell->skill_level = 30; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "Restores a part(or all) of your mana"); + spell_type_set_mana(spell, 1, 1); + spell_type_set_difficulty(spell, 30, 80); + spell_type_init_device(spell, + device_mana_info, + device_mana); - dice_parse_checked(&spell->device_charges, "2+d3"); + spell_type_set_device_charges(spell, "2+d3"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 78; range_init(&device_allocation->base_level, 1, 5); range_init(&device_allocation->max_level, 20, 35); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&DEVICE_NOTHING, "DEVICE_NOTHING", "Nothing"); - string_list_append(&spell->description, "It does nothing."); - school_idx_add_new(&spell->schools, SCHOOL_DEVICE); - range_init(&spell->mana_range, 0, 0); - spell->info_func = device_nothing_info; - spell->effect_func = device_nothing; - spell->failure_rate = 0; - spell->skill_level = 1; - spell_init_mage(spell, NO_RANDOM); + spell_type_describe(spell, "It does nothing."); + spell_type_set_mana(spell, 0, 0); + spell_type_set_difficulty(spell, 1, 0); + spell_type_init_device(spell, + device_nothing_info, + device_nothing); - dice_parse_checked(&spell->device_charges, "0+d0"); + spell_type_set_device_charges(spell, "0+d0"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 3; range_init(&device_allocation->base_level, 1, 1); range_init(&device_allocation->max_level, 1, 1); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } { @@ -2338,228 +2182,230 @@ void school_spells_init() device_allocation->rarity = 3; range_init(&device_allocation->base_level, 1, 1); range_init(&device_allocation->max_level, 1, 1); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&DEVICE_MAGGOT, "DEVICE_MAGGOT", "Artifact Maggot"); - dice_parse_checked(&spell->activation_duration, "10+d50"); - string_list_append(&spell->description, "terrify"); - school_idx_add_new(&spell->schools, SCHOOL_DEVICE); - range_init(&spell->mana_range, 7, 7); - spell->info_func = device_maggot_info; - spell->effect_func = device_maggot; - spell->failure_rate = 20; - spell->skill_level = 1; - spell_init_mage(spell, NO_RANDOM); + spell_type_set_activation_timeout(spell, "10+d50"); + spell_type_describe(spell, "terrify"); + spell_type_set_mana(spell, 7, 7); + spell_type_set_difficulty(spell, 1, 20); + spell_type_init_device(spell, + device_maggot_info, + device_maggot); } { spell_type *spell = spell_new(&DEVICE_HOLY_FIRE, "DEVICE_HOLY_FIRE", "Holy Fire of Mithrandir"); - string_list_append(&spell->description, "The Holy Fire created by this staff will deeply(double damage) burn"); - string_list_append(&spell->description, "all that is evil."); - school_idx_add_new(&spell->schools, SCHOOL_DEVICE); - range_init(&spell->mana_range, 50, 150); - spell->info_func = device_holy_fire_info; - spell->effect_func = device_holy_fire; - spell->failure_rate = 75; - spell->skill_level = 30; - spell_init_mage(spell, NO_RANDOM); - - dice_parse_checked(&spell->device_charges, "2+d5"); + spell_type_describe(spell, "The Holy Fire created by this staff will deeply(double damage) burn"); + spell_type_describe(spell, "all that is evil."); + spell_type_set_mana(spell, 50, 150); + spell_type_set_difficulty(spell, 30, 75); + spell_type_init_device(spell, + device_holy_fire_info, + device_holy_fire); + + spell_type_set_device_charges(spell, "2+d5"); { device_allocation *device_allocation = device_allocation_new(TV_STAFF); device_allocation->rarity = 999; range_init(&device_allocation->base_level, 1, 1); range_init(&device_allocation->max_level, 35, 35); - sglib_device_allocation_add(&spell->device_allocation, device_allocation); + spell_type_add_device_allocation(spell, device_allocation); } } { spell_type *spell = spell_new(&DEVICE_ETERNAL_FLAME, "DEVICE_ETERNAL_FLAME", "Artifact Eternal Flame"); - dice_parse_checked(&spell->activation_duration, "0"); - string_list_append(&spell->description, "Imbuing an object with the eternal fire"); - school_idx_add_new(&spell->schools, SCHOOL_DEVICE); - range_init(&spell->mana_range, 0, 0); - spell->info_func = device_eternal_flame_info; - spell->effect_func = device_eternal_flame; - spell->failure_rate = 0; - spell->skill_level = 1; - spell_init_mage(spell, NO_RANDOM); + spell_type_set_activation_timeout(spell, "0"); + spell_type_describe(spell, "Imbuing an object with the eternal fire"); + spell_type_set_mana(spell, 0, 0); + spell_type_set_difficulty(spell, 1, 0); + spell_type_init_device(spell, + device_eternal_flame_info, + device_eternal_flame); } { spell_type *spell = spell_new(&MUSIC_STOP, "MUSIC_STOP", "Stop singing(I)"); - string_list_append(&spell->description, "Stops the current song, if any."); - range_init(&spell->mana_range, 0, 0); - spell->info_func = music_stop_singing_info; - spell->effect_func = music_stop_singing_spell; - spell->failure_rate = -400; - spell->skill_level = 1; - spell->castable_while_blind = TRUE; - spell_init_music(spell, 1); + spell_type_describe(spell, "Stops the current song, if any."); + spell_type_set_mana(spell, 0, 0); + spell_type_set_difficulty(spell, 1, -400); + spell_type_set_castable_while_blind(spell, TRUE); + spell_type_init_music(spell, + 1, + music_stop_singing_info, + music_stop_singing_spell); } { spell_type *spell = spell_new(&MUSIC_HOLD, "MUSIC_HOLD", "Holding Pattern(I)"); - string_list_append(&spell->description, "Slows down all monsters listening the song."); - string_list_append(&spell->description, "Consumes the amount of mana each turn."); - range_init(&spell->mana_range, 1, 10); - spell->info_func = music_holding_pattern_info; - spell->effect_func = music_holding_pattern_spell; - spell->lasting_func = music_holding_pattern_lasting; - spell->failure_rate = 20; - spell->skill_level = 1; - spell->castable_while_blind = TRUE; - spell_init_music(spell, 1); + spell_type_describe(spell, "Slows down all monsters listening the song."); + spell_type_describe(spell, "Consumes the amount of mana each turn."); + spell_type_set_mana(spell, 1, 10); + spell_type_set_difficulty(spell, 1, 20); + spell_type_set_castable_while_blind(spell, TRUE); + spell_type_init_music_lasting( + spell, + 1, + music_holding_pattern_info, + music_holding_pattern_spell, + music_holding_pattern_lasting); } { spell_type *spell = spell_new(&MUSIC_CONF, "MUSIC_CONF", "Illusion Pattern(II)"); - string_list_append(&spell->description, "Tries to confuse all monsters listening the song."); - string_list_append(&spell->description, "Consumes the amount of mana each turn."); - range_init(&spell->mana_range, 2, 15); - spell->info_func = music_illusion_pattern_info; - spell->effect_func = music_illusion_pattern_spell; - spell->lasting_func = music_illusion_pattern_lasting; - spell->failure_rate = 30; - spell->skill_level = 5; - spell->castable_while_blind = TRUE; - spell_init_music(spell, 2); + spell_type_describe(spell, "Tries to confuse all monsters listening the song."); + spell_type_describe(spell, "Consumes the amount of mana each turn."); + spell_type_set_mana(spell, 2, 15); + spell_type_set_difficulty(spell, 5, 30); + spell_type_set_castable_while_blind(spell, TRUE); + spell_type_init_music_lasting( + spell, + 2, + music_illusion_pattern_info, + music_illusion_pattern_spell, + music_illusion_pattern_lasting); } { spell_type *spell = spell_new(&MUSIC_STUN, "MUSIC_STUN", "Stun Pattern(IV)"); - string_list_append(&spell->description, "Stuns all monsters listening the song."); - string_list_append(&spell->description, "Consumes the amount of mana each turn."); - range_init(&spell->mana_range, 3, 25); - spell->info_func = music_stun_pattern_info; - spell->effect_func = music_stun_pattern_spell; - spell->lasting_func = music_stun_pattern_lasting; - spell->failure_rate = 45; - spell->skill_level = 10; - spell->castable_while_blind = TRUE; - spell_init_music(spell, 4); + spell_type_describe(spell, "Stuns all monsters listening the song."); + spell_type_describe(spell, "Consumes the amount of mana each turn."); + spell_type_set_mana(spell, 3, 25); + spell_type_set_difficulty(spell, 10, 45); + spell_type_set_castable_while_blind(spell, TRUE); + spell_type_init_music_lasting( + spell, + 4, + music_stun_pattern_info, + music_stun_pattern_spell, + music_stun_pattern_lasting); } { spell_type *spell = spell_new(&MUSIC_LITE, "MUSIC_LITE", "Song of the Sun(I)"); - string_list_append(&spell->description, "Provides light as long as you sing."); - string_list_append(&spell->description, "Consumes the amount of mana each turn."); - range_init(&spell->mana_range, 1, 1); - spell->info_func = music_song_of_the_sun_info; - spell->effect_func = music_song_of_the_sun_spell; - spell->lasting_func = music_song_of_the_sun_lasting; - spell->failure_rate = 20; - spell->skill_level = 1; - spell->castable_while_blind = TRUE; - spell_init_music(spell, 1); + spell_type_describe(spell, "Provides light as long as you sing."); + spell_type_describe(spell, "Consumes the amount of mana each turn."); + spell_type_set_mana(spell, 1, 1); + spell_type_set_difficulty(spell, 1, 20); + spell_type_set_castable_while_blind(spell, TRUE); + spell_type_init_music_lasting( + spell, + 1, + music_song_of_the_sun_info, + music_song_of_the_sun_spell, + music_song_of_the_sun_lasting); } { spell_type *spell = spell_new(&MUSIC_HEAL, "MUSIC_HEAL", "Flow of Life(II)"); - string_list_append(&spell->description, "Heals you as long as you sing."); - string_list_append(&spell->description, "Consumes the amount of mana each turn."); - range_init(&spell->mana_range, 5, 30); - spell->info_func = music_flow_of_life_info; - spell->effect_func = music_flow_of_life_spell; - spell->lasting_func = music_flow_of_life_lasting; - spell->failure_rate = 35; - spell->skill_level = 7; - spell_init_music(spell, 2); + spell_type_describe(spell, "Heals you as long as you sing."); + spell_type_describe(spell, "Consumes the amount of mana each turn."); + spell_type_set_mana(spell, 5, 30); + spell_type_set_difficulty(spell, 7, 35); + spell_type_init_music_lasting( + spell, + 2, + music_flow_of_life_info, + music_flow_of_life_spell, + music_flow_of_life_lasting); } { spell_type *spell = spell_new(&MUSIC_HERO, "MUSIC_HERO", "Heroic Ballad(II)"); - string_list_append(&spell->description, "Increases melee accuracy"); - string_list_append(&spell->description, "At level 10 it increases it even more and reduces armour a bit"); - string_list_append(&spell->description, "At level 20 it increases it again"); - string_list_append(&spell->description, "At level 25 it grants protection against chaos and confusion"); - string_list_append(&spell->description, "Consumes the amount of mana each turn."); - range_init(&spell->mana_range, 4, 14); - spell->info_func = music_heroic_ballad_info; - spell->effect_func = music_heroic_ballad_spell; - spell->lasting_func = music_heroic_ballad_lasting; - spell->failure_rate = 45; - spell->skill_level = 10; - spell_init_music(spell, 2); + spell_type_describe(spell, "Increases melee accuracy"); + spell_type_describe(spell, "At level 10 it increases it even more and reduces armour a bit"); + spell_type_describe(spell, "At level 20 it increases it again"); + spell_type_describe(spell, "At level 25 it grants protection against chaos and confusion"); + spell_type_describe(spell, "Consumes the amount of mana each turn."); + spell_type_set_mana(spell, 4, 14); + spell_type_set_difficulty(spell, 10, 45); + spell_type_init_music_lasting( + spell, + 2, + music_heroic_ballad_info, + music_heroic_ballad_spell, + music_heroic_ballad_lasting); } { spell_type *spell = spell_new(&MUSIC_TIME, "MUSIC_TIME", "Hobbit Melodies(III)"); - string_list_append(&spell->description, "Greatly increases your reflexes allowing you to block more melee blows."); - string_list_append(&spell->description, "At level 15 it also makes you faster."); - string_list_append(&spell->description, "Consumes the amount of mana each turn."); - range_init(&spell->mana_range, 10, 30); - spell->info_func = music_hobbit_melodies_info; - spell->effect_func = music_hobbit_melodies_spell; - spell->lasting_func = music_hobbit_melodies_lasting; - spell->failure_rate = 70; - spell->skill_level = 20; - spell_init_music(spell, 3); + spell_type_describe(spell, "Greatly increases your reflexes allowing you to block more melee blows."); + spell_type_describe(spell, "At level 15 it also makes you faster."); + spell_type_describe(spell, "Consumes the amount of mana each turn."); + spell_type_set_mana(spell, 10, 30); + spell_type_set_difficulty(spell, 20, 70); + spell_type_init_music_lasting( + spell, + 3, + music_hobbit_melodies_info, + music_hobbit_melodies_spell, + music_hobbit_melodies_lasting); } { spell_type *spell = spell_new(&MUSIC_MIND, "MUSIC_MIND", "Clairaudience(IV)"); - string_list_append(&spell->description, "Allows you to sense monster minds as long as you sing."); - string_list_append(&spell->description, "At level 10 it identifies all objects in a radius on the floor,"); - string_list_append(&spell->description, "as well as probing monsters in that radius."); - string_list_append(&spell->description, "Consumes the amount of mana each turn."); - range_init(&spell->mana_range, 15, 30); - spell->info_func = music_clairaudience_info; - spell->effect_func = music_clairaudience_spell; - spell->lasting_func = music_clairaudience_lasting; - spell->failure_rate = 75; - spell->skill_level = 25; - spell_init_music(spell, 4); + spell_type_describe(spell, "Allows you to sense monster minds as long as you sing."); + spell_type_describe(spell, "At level 10 it identifies all objects in a radius on the floor,"); + spell_type_describe(spell, "as well as probing monsters in that radius."); + spell_type_describe(spell, "Consumes the amount of mana each turn."); + spell_type_set_mana(spell, 15, 30); + spell_type_set_difficulty(spell, 25, 75); + spell_type_init_music_lasting( + spell, + 4, + music_clairaudience_info, + music_clairaudience_spell, + music_clairaudience_lasting); } { spell_type *spell = spell_new(&MUSIC_BLOW, "MUSIC_BLOW", "Blow(I)"); - string_list_append(&spell->description, "Produces a powerful, blowing, sound all around you."); - range_init(&spell->mana_range, 3, 30); - spell->info_func = music_blow_info; - spell->effect_func = music_blow_spell; - spell->failure_rate = 20; - spell->skill_level = 4; - spell_init_music(spell, 1); + spell_type_describe(spell, "Produces a powerful, blowing, sound all around you."); + spell_type_set_mana(spell, 3, 30); + spell_type_set_difficulty(spell, 4, 20); + spell_type_init_music(spell, + 1, + music_blow_info, + music_blow_spell); } { spell_type *spell = spell_new(&MUSIC_WIND, "MUSIC_WIND", "Gush of Wind(II)"); - string_list_append(&spell->description, "Produces a outgoing gush of wind that sends monsters away."); - range_init(&spell->mana_range, 15, 45); - spell->info_func = music_gush_of_wind_info; - spell->effect_func = music_gush_of_wind_spell; - spell->failure_rate = 30; - spell->skill_level = 14; - spell_init_music(spell, 2); + spell_type_describe(spell, "Produces a outgoing gush of wind that sends monsters away."); + spell_type_set_mana(spell, 15, 45); + spell_type_set_difficulty(spell, 14, 30); + spell_type_init_music(spell, + 2, + music_gush_of_wind_info, + music_gush_of_wind_spell); } { spell_type *spell = spell_new(&MUSIC_YLMIR, "MUSIC_YLMIR", "Horns of Ylmir(III)"); - string_list_append(&spell->description, "Produces an earth shaking sound."); - range_init(&spell->mana_range, 25, 30); - spell->info_func = music_horns_of_ylmir_info; - spell->effect_func = music_horns_of_ylmir_spell; - spell->failure_rate = 20; - spell->skill_level = 20; - spell_init_music(spell, 3); + spell_type_describe(spell, "Produces an earth shaking sound."); + spell_type_set_mana(spell, 25, 30); + spell_type_set_difficulty(spell, 20, 20); + spell_type_init_music(spell, + 3, + music_horns_of_ylmir_info, + music_horns_of_ylmir_spell); } { spell_type *spell = spell_new(&MUSIC_AMBARKANTA, "MUSIC_AMBARKANTA", "Ambarkanta(IV)"); - string_list_append(&spell->description, "Produces a reality shaking sound that transports you to a nearly"); - string_list_append(&spell->description, "identical reality."); - range_init(&spell->mana_range, 70, 70); - spell->info_func = music_ambarkanta_info; - spell->effect_func = music_ambarkanta_spell; - spell->failure_rate = 60; - spell->skill_level = 25; - spell_init_music(spell, 4); + spell_type_describe(spell, "Produces a reality shaking sound that transports you to a nearly"); + spell_type_describe(spell, "identical reality."); + spell_type_set_mana(spell, 70, 70); + spell_type_set_difficulty(spell, 25, 60); + spell_type_init_music(spell, + 4, + music_ambarkanta_info, + music_ambarkanta_spell); } /* Module-specific spells */ diff --git a/src/spells6.c b/src/spells6.c index 37e4c42c..5db4e18e 100644 --- a/src/spells6.c +++ b/src/spells6.c @@ -2,6 +2,8 @@ #include +#include "spell_type.h" + static int compare_school_provider(school_provider *a, school_provider *b) { return SGLIB_NUMERIC_COMPARATOR(a->deity_idx, b->deity_idx); @@ -150,122 +152,132 @@ long get_provided_levels(school_type *school) return 0; } -void get_level_school(s32b spell_idx, s32b max, s32b min, s32b *level, bool_ *na) +typedef struct get_level_school_callback_data get_level_school_callback_data; +struct get_level_school_callback_data { + bool_ allow_spell_power; + long bonus; + long lvl; + long num; +}; + +static bool_ get_level_school_callback(void *data_, int school_idx) { - spell_type *spell = spell_at(spell_idx); - school_idx *school_idx = NULL; - struct sglib_school_idx_iterator sit; - bool_ allow_spell_power = TRUE; - long lvl, num, bonus; + get_level_school_callback_data *data = data_; + school_type *school = school_at(school_idx); + long r = 0, s = 0, p = 0, ok = 0; - assert(level != NULL); - assert(na != NULL); + /* Does it require we worship a specific god? */ + if ((school->deity_idx > 0) && + (school->deity_idx != p_ptr->pgod)) + { + return FALSE; + } - lvl = 0; - num = 0; - bonus = 0; + /* Take the basic skill value */ + r = s_info[school->skill].value; /* Do we pass tests? */ - if (!check_spell_depends(spell)) + if ((school->depends_satisfied != NULL) && + (!school->depends_satisfied())) { - *level = min; - *na = TRUE; - return; + return FALSE; } - /* Go through all the spell's schools. */ - for (school_idx = sglib_school_idx_it_init(&sit, spell->schools); - school_idx != NULL; - school_idx = sglib_school_idx_it_next(&sit)) + /* Include effects of Sorcery (if applicable) */ + if (school->sorcery) { - school_type *school = school_at(school_idx->i); - long r = 0, s = 0, p = 0, ok = 0; + s = s_info[SKILL_SORCERY].value; + } - /* Does it require we worship a specific god? */ - if ((school->deity_idx > 0) && - (school->deity_idx != p_ptr->pgod)) - { - *level = min; - *na = TRUE; - return; - } + /* Include effects of Spell Power? Every school must + * allow use of Spell Power for it to apply. */ + if (!school->spell_power) + { + data->allow_spell_power = FALSE; + } - /* Take the basic skill value */ - r = s_info[school->skill].value; + /* Calculate effects of provided levels */ + p = get_provided_levels(school); - /* Do we pass tests? */ - if ((school->depends_satisfied != NULL) && - (!school->depends_satisfied())) - { - *level = min; - *na = TRUE; - return; - } + /* Find the highest of Skill, Sorcery and Provided levels. */ + ok = r; + if (ok < s) + { + ok = s; + } + if (ok < p) + { + ok = p; + } - /* Include effects of Sorcery (if applicable) */ - if (school->sorcery) - { - s = s_info[SKILL_SORCERY].value; - } + /* Do we need to add a special bonus? */ + if (school->bonus_levels != NULL) + { + data->bonus += (school->bonus_levels() * (SKILL_STEP / 10)); + } - /* Include effects of Spell Power? Every school must - * allow use of Spell Power for it to apply. */ - if (!school->spell_power) - { - allow_spell_power = FALSE; - } + /* All schools must be non-zero to be able to use it. */ + if (ok <= 0) + { + return FALSE; + } - /* Calculate effects of provided levels */ - p = get_provided_levels(school); + /* Apply it */ + data->lvl += ok; + data->num += 1; - /* Find the highest of Skill, Sorcery and Provided levels. */ - ok = r; - if (ok < s) - { - ok = s; - } - if (ok < p) - { - ok = p; - } + /* Keep going */ + return TRUE; +} - /* Do we need to add a special bonus? */ - if (school->bonus_levels != NULL) - { - bonus += (school->bonus_levels() * (SKILL_STEP / 10)); - } +void get_level_school(s32b spell_idx, s32b max, s32b min, s32b *level, bool_ *na) +{ + spell_type *spell = spell_at(spell_idx); - /* All schools must be non-zero to be able to use it. */ - if (ok <= 0) - { - *level = min; - *na = TRUE; - return; - } + assert(level != NULL); + assert(na != NULL); - /* Apply it */ - lvl = lvl + ok; - num = num + 1; + /* Do we pass tests? */ + if (!spell_type_dependencies_satisfied(spell)) + { + *level = min; + *na = TRUE; + return; + } + + /* Set up initial state */ + get_level_school_callback_data data; + data.allow_spell_power = TRUE; + data.bonus = 0; + data.lvl = 0; + data.num = 0; + + /* Go through all the spell's schools. */ + if (!spell_type_school_foreach(spell, get_level_school_callback, &data)) + { + *level = min; + *na = TRUE; + return; } /* Add the Spellpower skill as a bonus on top */ - if (allow_spell_power) + if (data.allow_spell_power) { - bonus += (get_skill_scale(SKILL_SPELL, 20) * (SKILL_STEP / 10)); + data.bonus += (get_skill_scale(SKILL_SPELL, 20) * (SKILL_STEP / 10)); } /* Add bonus from objects */ - bonus += (p_ptr->to_s * (SKILL_STEP / 10)); + data.bonus += (p_ptr->to_s * (SKILL_STEP / 10)); /* We divide by 10 because otherwise we can overflow a s32b * and we can use a u32b because the value can be negative. * The loss of information should be negligible since 1 skill * point is 1000 internally. */ - lvl = (lvl / num) / 10; - lvl = lua_get_level(spell, lvl, max, min, bonus); + data.lvl = (data.lvl / data.num) / 10; + data.lvl = lua_get_level(spell, data.lvl, max, min, data.bonus); /* Result */ - *level = lvl; + *level = data.lvl; *na = FALSE; } diff --git a/src/store.c b/src/store.c index 3114380c..6cdaad4a 100644 --- a/src/store.c +++ b/src/store.c @@ -12,6 +12,7 @@ #include "angband.h" +#include "spell_type.h" #include "quark.h" #define STORE_GENERAL_STORE "General Store" @@ -834,7 +835,7 @@ static bool_ store_will_buy(object_type *o_ptr) if ((o_ptr->tval == TV_BOOK) && (o_ptr->sval == BOOK_RANDOM) && - (can_spell_random(o_ptr->pval) == SKILL_SPIRITUALITY)) + (spell_type_random_type(spell_at(o_ptr->pval)) == SKILL_SPIRITUALITY)) { return TRUE; } @@ -892,7 +893,7 @@ static bool_ store_will_buy(object_type *o_ptr) if ((o_ptr->tval == TV_BOOK) && (o_ptr->sval == BOOK_RANDOM) && - (can_spell_random(o_ptr->pval) == SKILL_MAGIC)) + (spell_type_random_type(spell_at(o_ptr->pval)) == SKILL_MAGIC)) { return TRUE; } diff --git a/src/types.h b/src/types.h index 825e25ab..c921d028 100644 --- a/src/types.h +++ b/src/types.h @@ -2569,72 +2569,6 @@ struct skill_type u32b flags1; /* Skill flags */ }; - -/* - * School index list. - */ -typedef struct school_idx school_idx; -struct school_idx { - s32b i; /* School index */ - school_idx *next; /* for list */ -}; - - -/* - * Casting type - */ -typedef enum { USE_SPELL_POINTS, USE_PIETY } casting_type; - - -/* - * Spell effect function result - */ -typedef enum { - NO_CAST, /* Spell not cast; user aborted */ - CAST_OBVIOUS, /* Cast; caster discovers effect (devices) */ - CAST_HIDDEN /* Cast; caster does NOT discover effect (devices) */ -} casting_result; - -/* - * The spell function must provide the desc - */ -typedef struct spell_type spell_type; -struct spell_type -{ - cptr name; /* Name */ - byte skill_level; /* Required level (to learn) */ - string_list *description; /* List of strings */ - - casting_result (*effect_func)(int o_idx); /* Spell effect function */ - char* (*info_func)(); /* Information function */ - int (*lasting_func)(); /* Lasting effect function */ - bool_ (*depend_func)(); /* Check dependencies */ - - s16b minimum_pval; /* Minimum required pval for item-based spells */ - - casting_type casting_type; /* Type of casting required */ - s16b casting_stat; /* Stat used for casting */ - - bool_ castable_while_blind; - bool_ castable_while_confused; - - dice_type device_charges; /* Number of charges for devices */ - device_allocation *device_allocation; /* Allocation table for devices */ - - s16b random_type; /* Type of random items in which skill may appear */ - - s32b failure_rate; /* Failure rate */ - - s32b inertia_difficulty; /* Mana cost when used in Inertia Control */ - s32b inertia_delay; /* Delay between castings */ - - range_type mana_range; - - dice_type activation_duration; /* Duration for activation (if any) */ - - school_idx *schools; -}; - typedef struct school_provider school_provider; struct school_provider { diff --git a/src/variable.c b/src/variable.c index 2ec4f7bc..84ca93ee 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1383,7 +1383,7 @@ bool_ player_char_health; * The spell list of schools */ s16b school_spells_count = 0; -spell_type school_spells[SCHOOL_SPELLS_MAX]; +spell_type *school_spells[SCHOOL_SPELLS_MAX]; s16b schools_count = 0; school_type schools[SCHOOLS_MAX]; -- cgit v1.2.3 From 2653d949a0008b44d4a41fb52d516a7766f55928 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 30 Jun 2012 20:20:58 +0200 Subject: Remove unused variables --- src/files.c | 3 --- src/loadsave.c | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/files.c b/src/files.c index f8125148..8e19922f 100644 --- a/src/files.c +++ b/src/files.c @@ -5521,9 +5521,6 @@ void wipe_saved() */ void close_game(void) { - char buf[1024]; - - /* Handle stuff */ handle_stuff(); diff --git a/src/loadsave.c b/src/loadsave.c index aac4e8a1..0f01e8ec 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -2088,7 +2088,7 @@ static void do_messages(int flag) /* FIXME! We should be able to unify this be { int i; char buf[128]; - byte color, type; + byte color; s16b num; -- cgit v1.2.3 From 3cb6bbdb5733d7ebf601558067e81f3e0e79e59a Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 30 Jun 2012 20:49:07 +0200 Subject: Add Clang support and C++ support --- CMakeLists.txt | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index da5486b2..225b3af9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ # Project definition. PROJECT (tome2) -CMAKE_MINIMUM_REQUIRED (VERSION 2.6) +CMAKE_MINIMUM_REQUIRED (VERSION 2.8) # We want a readable feature summary. INCLUDE(FeatureSummary) @@ -8,12 +8,31 @@ INCLUDE(FeatureSummary) # pkg-config support INCLUDE(FindPkgConfig) -# Default flags. +# +# GCC/G++ flags +# IF(CMAKE_COMPILER_IS_GNUCC) # Let's set sensible options. - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pipe -Wall -Wno-unused-value -Wno-unused-variable") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pipe -Wall -Wno-unused-value") SET(CMAKE_C_FLAGS_RELEASE "-O2") SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe -Wall -Wno-unused-value --std=c++11 -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC") + SET(CMAKE_CXX_FLAGS_RELEASE "-O2") + SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") +ENDIF() + +# +# Clang flags +# +IF("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pipe -Wall -Wno-unused-value") + SET(CMAKE_C_FLAGS_RELEASE "-O2") + SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") +ENDIF() +IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe -Wall -Wno-unused-value --std=c++11 -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC") + SET(CMAKE_CXX_FLAGS_RELEASE "-O2") + SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") ENDIF() # Add definitions. -- cgit v1.2.3 From 7d8712ba5bcf8ba7837ca0c198f364fd208db354 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 29 Nov 2012 17:52:48 +0100 Subject: Fix a linking issue on some distributions/toolchains. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 225b3af9..56713c7b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,7 +86,7 @@ IF(SDL_FOUND) # Add SDL flags/options ADD_DEFINITIONS(-DUSE_SDL) INCLUDE_DIRECTORIES(${SDL_INCLUDE_DIR} ${SDLIMAGE_INCLUDE_DIR} ${SDLTTF_INCLUDE_DIR}) - SET(LIBS ${LIBS} ${SDLIMAGE_LIBRARY} ${SDLTTF_LIBRARY} ${SDL_LIBRARY}) + SET(LIBS ${LIBS} ${SDLIMAGE_LIBRARY} ${SDLTTF_LIBRARY} ${SDL_LIBRARY} m) ELSE() # Let user know that (and why) we haven't enabled SDL. IF(SDLIMAGE_FOUND) -- cgit v1.2.3 From c23c15a18d3de893db0cc0143f2a0924a0488b73 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 29 Nov 2012 18:55:41 +0100 Subject: Fix for Orc Cave exit in Theme module. Thanks to 'trudge' for the fix. --- lib/mods/theme/edit/d_info.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/mods/theme/edit/d_info.txt b/lib/mods/theme/edit/d_info.txt index c54c9f8f..91cf3d20 100644 --- a/lib/mods/theme/edit/d_info.txt +++ b/lib/mods/theme/edit/d_info.txt @@ -296,7 +296,7 @@ F:RANDOM_TOWNS | F:FINAL_OBJECT_810 | FINAL_GUARDIAN_373 | CAVE | F:FILL_METHOD_0 F:FORCE_DOWN -F:WILD_21_49__51_19 +F:WILD_49_21__51_19 R:30:3 M:TROLL R:20:0 -- cgit v1.2.3 From 2ebf28b8a8bc486913ba21b4b852a407988f67cb Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 6 Mar 2013 16:53:03 +0100 Subject: Fix a long-standing bug in power calculation for wielded symbiotes. Thanks to Improv, the Mighty MoLD(!) for the fix. --- src/cmd1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd1.c b/src/cmd1.c index 98fa264b..a349ac12 100644 --- a/src/cmd1.c +++ b/src/cmd1.c @@ -1327,7 +1327,7 @@ static void incarnate_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath, visible = TRUE; /* Extract the attack "power" */ - effect = get_attack_power(effect); + power = get_attack_power(effect); /* Monster hits */ if (!effect || check_hit2(power, rlev, ac)) -- cgit v1.2.3 From d39105ff82a42cbedbb1b68683aefce050228551 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 17:29:07 +0100 Subject: Clang warning fix --- src/q_fireprof.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/q_fireprof.c b/src/q_fireprof.c index 4405d43b..3afa348f 100644 --- a/src/q_fireprof.c +++ b/src/q_fireprof.c @@ -119,17 +119,19 @@ static bool_ fireproof_enough_points(object_type *o_ptr, int *stack) /* check for item type and multiply number in the stack by the * amount of points per item of that type */ - if (o_ptr->tval == TV_BOOK) + switch (o_ptr->tval) { + case TV_BOOK: item_value = FIREPROOF_BOOK_POINTS * (*stack); - } - else if (o_ptr->tval == TV_STAFF) - { + break; + case TV_STAFF: item_value = FIREPROOF_STAFF_POINTS * (*stack); - } - else if (o_ptr->tval == TV_SCROLL) - { + break; + case TV_SCROLL: item_value = FIREPROOF_SCROLL_POINTS * (*stack); + break; + default: + assert(FALSE); } /* do we have enough points? */ -- cgit v1.2.3 From 45c2cb4e51f3683cf527598bff0554e0b1723402 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 24 Jun 2013 07:41:12 +0200 Subject: Remove HANDLE_SIGNALS and SPECIAL_BSD --- src/config.h | 33 --------------- src/externs.h | 3 -- src/files.c | 126 ---------------------------------------------------------- src/main.c | 3 -- 4 files changed, 165 deletions(-) diff --git a/src/config.h b/src/config.h index 8ee46cf7..cb258925 100644 --- a/src/config.h +++ b/src/config.h @@ -43,13 +43,6 @@ */ -/* - * OPTION: define "SPECIAL_BSD" for using certain versions of UNIX - * that use the 4.4BSD Lite version of Curses in "main-gcu.c" - */ -/* #define SPECIAL_BSD */ - - /* * OPTION: Use the POSIX "termios" methods in "main-gcu.c" */ @@ -112,11 +105,6 @@ #endif -/* - * OPTION: Handle signals - */ -#define HANDLE_SIGNALS - @@ -139,27 +127,6 @@ #define USE_GRAPHICS -/* - * OPTION: Hack -- Macintosh stuff - */ -#ifdef MACINTOSH - -/* Do not handle signals */ -# undef HANDLE_SIGNALS - -#endif - - -/* - * OPTION: Hack -- Windows stuff - */ -#ifdef WINDOWS - -/* Do not handle signals */ -# undef HANDLE_SIGNALS - -#endif - /* * OPTION: Set the "default" path to the angband "lib" directory. diff --git a/src/externs.h b/src/externs.h index 290a3152..deb93010 100644 --- a/src/externs.h +++ b/src/externs.h @@ -890,9 +890,6 @@ extern void display_scores(int from, int to); extern errr predict_score(void); extern void predict_score_gui(bool_ *initialized, bool_ *game_in_progress); extern void close_game(void); -extern void signals_ignore_tstp(void); -extern void signals_handle_tstp(void); -extern void signals_init(void); extern errr get_rnd_line(char * file_name, char * output); extern char *get_line(char* fname, cptr fdir, char *linbuf, int line); extern void do_cmd_knowledge_corruptions(void); diff --git a/src/files.c b/src/files.c index 8e19922f..7b1d10ce 100644 --- a/src/files.c +++ b/src/files.c @@ -4236,9 +4236,6 @@ void do_cmd_save_game(void) /* The player is not dead */ (void)strcpy(died_from, "(saved)"); - /* Forbid suspend */ - signals_ignore_tstp(); - /* Save the player */ if (save_player()) { @@ -4253,9 +4250,6 @@ void do_cmd_save_game(void) remove_cave_view(FALSE); - /* Allow suspend again */ - signals_handle_tstp(); - /* Refresh */ Term_fresh(); @@ -5114,8 +5108,6 @@ void race_legends(void) /* * Enters a players name on a hi-score table, if "legal", and in any * case, displays some relevant portion of the high score list. - * - * Assumes "signals_ignore_tstp()" has been called. */ static errr top_twenty(void) { @@ -5531,9 +5523,6 @@ void close_game(void) flush(); - /* No suspending now */ - signals_ignore_tstp(); - /* Hack -- Character is now "icky" */ character_icky = TRUE; @@ -5608,10 +5597,6 @@ void close_game(void) /* Predict score (or ESCAPE) */ if (inkey() != ESCAPE) predict_score(); } - - - /* Allow suspending now */ - signals_handle_tstp(); } @@ -5865,114 +5850,3 @@ errr get_xtra_line(char *file_name, monster_type *m_ptr, char *output) /* Success */ return (0); } - - -#ifdef HANDLE_SIGNALS - - -#include - - -/* - * Handle signals -- suspend - * - * Actually suspend the game, and then resume cleanly - */ -static void handle_signal_suspend(int sig) -{ - /* Disable handler */ - (void)signal(sig, SIG_IGN); - -#ifdef SIGSTOP - - /* Flush output */ - Term_fresh(); - - /* Suspend the "Term" */ - Term_xtra(TERM_XTRA_ALIVE, 0); - - /* Suspend ourself */ - (void)kill(0, SIGSTOP); - - /* Resume the "Term" */ - Term_xtra(TERM_XTRA_ALIVE, 1); - - /* Redraw the term */ - Term_redraw(); - - /* Flush the term */ - Term_fresh(); - -#endif - - /* Restore handler */ - (void)signal(sig, handle_signal_suspend); -} - - -/* - * Ignore SIGTSTP signals (keyboard suspend) - */ -void signals_ignore_tstp(void) -{ - -#ifdef SIGTSTP - (void)signal(SIGTSTP, SIG_IGN); -#endif - -} - -/* - * Handle SIGTSTP signals (keyboard suspend) - */ -void signals_handle_tstp(void) -{ - -#ifdef SIGTSTP - (void)signal(SIGTSTP, handle_signal_suspend); -#endif - -} - - -/* - * Prepare to handle the relevant signals - */ -void signals_init(void) -{ - -#ifdef SIGHUP - (void)signal(SIGHUP, SIG_IGN); -#endif - - -#ifdef SIGTSTP - (void)signal(SIGTSTP, handle_signal_suspend); -#endif - -} - - -#else /* HANDLE_SIGNALS */ - - -/* -* Do nothing -*/ -void signals_ignore_tstp(void) -{} - -/* -* Do nothing -*/ -void signals_handle_tstp(void) -{} - -/* -* Do nothing -*/ -void signals_init(void) -{} - - -#endif /* HANDLE_SIGNALS */ diff --git a/src/main.c b/src/main.c index 2950506f..10500ab6 100644 --- a/src/main.c +++ b/src/main.c @@ -589,9 +589,6 @@ usage: if (!done) quit("Unable to prepare any 'display module'!"); - /* Catch nasty signals */ - signals_init(); - /* Initialize */ init_angband(); -- cgit v1.2.3 From f544f4a026ebd3205b73724047157547fa7bbaa5 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 24 Jun 2013 08:14:32 +0200 Subject: Remove unused variable --- src/cmd6.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/cmd6.c b/src/cmd6.c index f15860b9..ce49b155 100644 --- a/src/cmd6.c +++ b/src/cmd6.c @@ -3893,7 +3893,7 @@ void do_cmd_aim_wand(void) { bool_ obvious, use_charge; - int item, ident, chance, sval; + int item, ident, chance; object_type *o_ptr; @@ -3982,9 +3982,6 @@ void do_cmd_aim_wand(void) sound(SOUND_ZAP); - /* XXX Hack -- Extract the "sval" effect */ - sval = o_ptr->sval; - /* Analyze the wand */ activate_stick(o_ptr->pval2, &obvious, &use_charge); -- cgit v1.2.3 From 6d3f6acd7498db5b9958d51002986ee957dbe11b Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 24 Jun 2013 08:47:21 +0200 Subject: Remove old_colors option --- lib/pref/422color.prf | 909 -------------------------------------------------- src/dungeon.c | 7 - src/externs.h | 1 - src/tables.c | 3 - src/variable.c | 5 - 5 files changed, 925 deletions(-) delete mode 100644 lib/pref/422color.prf diff --git a/lib/pref/422color.prf b/lib/pref/422color.prf deleted file mode 100644 index 309c36b0..00000000 --- a/lib/pref/422color.prf +++ /dev/null @@ -1,909 +0,0 @@ -# Agent of the black market -R:14:0x08:0x74 - -# Mean-looking mercenary -R:17:0x0c:0x74 - -# Battle-scarred veteran -R:18:0x04:0x74 - -# Small kobold -R:29:0x0d:0x6b - -# Kobold -R:30:0x05:0x6b - -# Floating eye -R:32:0x06:0x65 - -# Fruit bat -R:37:0x0a:0x62 - -# Blubbering icky thing -R:41:0x05:0x69 - -# Metallic green centipede -R:42:0x0d:0x63 - -# Novice warrior -R:43:0x0f:0x70 - -# Novice rogue -R:44:0x08:0x70 - -# Novice priest -R:45:0x0e:0x70 - -# Novice mage -R:46:0x0c:0x70 - -# Smeagol -R:63:0x07:0x68 - -# Metallic blue centipede -R:67:0x0e:0x63 - -# Metallic red centipede -R:77:0x0c:0x63 - -# Novice ranger -R:83:0x05:0x70 - -# Snotling -R:87:0x0d:0x6f - -# Skeleton kobold -R:91:0x01:0x73 - -# Novice mage -R:93:0x0c:0x70 - -# Giant leech -R:95:0x0a:0x77 - -# Large kobold -R:102:0x01:0x6b - -# Novice priest -R:109:0x0e:0x70 - -# Novice warrior -R:110:0x0f:0x70 - -# Novice rogue -R:116:0x08:0x70 - -# Snaga -R:118:0x0d:0x6f - -# Giant pink frog -R:121:0x0c:0x52 - -# Cave orc -R:126:0x0f:0x6f - -# Manes -R:128:0x0c:0x75 - -# Red naga -R:130:0x0c:0x6e - -# Red jelly -R:131:0x0c:0x6a - -# Green icky thing -R:132:0x0d:0x69 - -# Lost soul -R:133:0x07:0x47 - -# Mughash, the Kobold Lord -R:135:0x06:0x6b - -# Skeleton orc -R:136:0x01:0x73 - -# Wormtongue, Agent of Saruman -R:137:0x08:0x70 - -# Nurgling -R:139:0x0f:0x75 - -# Lagduf, the Snaga -R:140:0x07:0x6f - -# Novice ranger -R:142:0x05:0x70 - -# Giant salamander -R:143:0x04:0x52 - -# Lemure -R:148:0x03:0x75 - -# Hill orc -R:149:0x02:0x6f - -# Bandit -R:150:0x08:0x70 - -# Orc shaman -R:162:0x06:0x6f - -# Baby blue dragon -R:163:0x0e:0x64 - -# Baby white dragon -R:164:0x09:0x64 - -# Baby green dragon -R:165:0x0d:0x64 - -# Baby red dragon -R:167:0x0c:0x64 - -# Giant red ant -R:168:0x0c:0x61 - -# Brodda, the Easterling -R:169:0x03:0x70 - -# Giant spider -R:175:0x02:0x53 - -# Dark elven mage -R:178:0x0a:0x68 - -# Kamikaze yeek -R:179:0x07:0x79 - -# Dark elven warrior -R:182:0x08:0x68 - -# Sand-dweller -R:183:0x0f:0x75 - -# Clear mushroom patch -R:184:0x01:0x2c - -# Grishnakh, the Hill Orc -R:186:0x07:0x6f - -# Hairy mold -R:190:0x0f:0x6d - -# Grizzly bear -R:191:0x07:0x71 - -# Pseudo dragon -R:193:0x0a:0x64 - -# Giant fruit fly -R:197:0x0f:0x49 - -# Golfimbul, the Hill Orc Chief -R:215:0x07:0x6f - -# Swordsman -R:216:0x0f:0x70 - -# Priest -R:225:0x0e:0x70 - -# Dark elven priest -R:226:0x06:0x68 - -# Skeleton human -R:228:0x01:0x73 - -# Moaning spirit -R:231:0x0f:0x47 - -# Stegocentipede -R:232:0x06:0x63 - -# Spotted jelly -R:233:0x02:0x6a - -# Illusionist -R:240:0x0a:0x70 - -# Druid -R:241:0x05:0x70 - -# Ochre jelly -R:245:0x0b:0x6a - -# Vlasta -R:249:0x06:0x52 - -# Snaga sapper -R:251:0x0d:0x6f - -# Flesh golem -R:256:0x03:0x67 - -# Dark naga -R:265:0x08:0x6e - -# Giant tarantula -R:275:0x0d:0x53 - -# Giant clear centipede -R:276:0x01:0x63 - -# Mirkwood spider -R:277:0x07:0x53 - -# Umber hulk -R:283:0x07:0x58 - -# Orc captain -R:285:0x05:0x6f - -# Gelatinous cube -R:286:0x0e:0x6a - -# Lizard man -R:290:0x0c:0x68 - -# Ulfast, Son of Ulfang -R:291:0x03:0x70 - -# Quasit -R:294:0x09:0x75 - -# Imp -R:296:0x04:0x75 - -# Forest troll -R:297:0x0d:0x54 - -# Giant red scorpion -R:304:0x0c:0x53 - -# Earth spirit -R:305:0x0f:0x45 - -# Fire spirit -R:306:0x0c:0x45 - -# Cold hound -R:308:0x09:0x5a - -# Energy hound -R:309:0x0b:0x5a - -# Uruk -R:313:0x01:0x6f - -# Shagrat, the Orc Captain -R:314:0x07:0x6f - -# Gorbag, the Orc Captain -R:315:0x07:0x6f - -# Stone giant -R:321:0x02:0x50 - -# Giant black dragon fly -R:322:0x08:0x46 - -# Stone golem -R:323:0x02:0x67 - -# Ghast -R:327:0x0f:0x7a - -# Bolg, Son of Azog -R:330:0x0c:0x6f - -# Lizard king -R:332:0x0c:0x68 - -# Wyvern -R:334:0x0d:0x64 - -# Air hound -R:338:0x0e:0x5a - -# Quylthulg -R:342:0x09:0x51 - -# Dark elven lord -R:348:0x08:0x68 - -# Cloud giant -R:349:0x0e:0x50 - -# Ugluk, the Uruk -R:350:0x07:0x6f - -# Blue dragon bat -R:351:0x0e:0x62 - -# Water vortex -R:355:0x06:0x76 - -# Cold vortex -R:358:0x09:0x76 - -# Energy vortex -R:359:0x0b:0x76 - -# Mummified orc -R:362:0x07:0x7a - -# Serpent man -R:364:0x05:0x4a - -# Killer stag beetle -R:366:0x02:0x4b - -# Iron golem -R:367:0x09:0x67 - -# Azog, King of the Uruk-Hai -R:373:0x04:0x6f - -# Master rogue -R:376:0x08:0x70 - -# Angamaite of Umbar -R:380:0x07:0x70 - -# Forest wight -R:381:0x0d:0x57 - -# 4-headed hydra -R:387:0x0f:0x4d - -# Mummified human -R:390:0x0f:0x7a - -# Sangahyando of Umbar -R:392:0x03:0x70 - -# Banshee -R:394:0x09:0x47 - -# Pukelman -R:398:0x07:0x67 - -# Disenchanter beast -R:399:0x01:0x71 - -# Stone troll -R:401:0x08:0x54 - -# Troll priest -R:403:0x06:0x54 - -# Khufu, the Mummified King -R:409:0x07:0x7a - -# Beast of Nurgle -R:422:0x03:0x71 - -# Creeping adamantite coins -R:423:0x0a:0x24 - -# Algroth -R:424:0x02:0x54 - -# Flamer of Tzeentch -R:425:0x0c:0x2c - -# Vibration hound -R:428:0x0f:0x5a - -# Ogre mage -R:430:0x03:0x4f - -# Lokkak, the Ogre Chieftain -R:431:0x05:0x4f - -# Colbran -R:435:0x06:0x67 - -# Spirit naga -R:436:0x0e:0x6e - -# Corpser -R:437:0x05:0x2c - -# Black knight -R:442:0x08:0x70 - -# Clairvoyant -R:445:0x0e:0x70 - -# Basilisk -R:453:0x08:0x52 - -# Aklash -R:463:0x09:0x54 - -# Skeleton troll -R:465:0x01:0x73 - -# Shadow drake -R:471:0x08:0x64 - -# Manticore -R:472:0x03:0x48 - -# Killer slicer beetle -R:474:0x03:0x4b - -# Gug -R:476:0x08:0x50 - -# Death watch beetle -R:478:0x0e:0x4b - -# Doombat -R:484:0x06:0x62 - -# Ninja -R:485:0x08:0x70 - -# Storm giant -R:487:0x06:0x50 - -# Bokrug -R:489:0x05:0x52 - -# Half-troll -R:491:0x03:0x54 - -# Bert the Stone Troll -R:493:0x09:0x54 - -# Bill the Stone Troll -R:494:0x09:0x54 - -# Tom the Stone Troll -R:495:0x09:0x54 - -# Barrow wight -R:499:0x09:0x57 - -# Law drake -R:502:0x09:0x64 - -# Balance drake -R:503:0x02:0x64 - -# Groo, the Wanderer -R:505:0x03:0x70 - -# Spectre -R:508:0x0d:0x47 - -# Cherub -R:511:0x09:0x41 - -# Master thief -R:516:0x08:0x70 - -# Lich -R:518:0x01:0x4c - -# Master vampire -R:520:0x02:0x56 - -# Oriental vampire -R:521:0x05:0x56 - -# Greater mummy -R:522:0x09:0x7a - -# Eog golem -R:530:0x08:0x67 - -# Dagashi -R:532:0x0b:0x70 - -# Smoke elemental -R:537:0x08:0x45 - -# Olog -R:538:0x05:0x54 - -# Gravity hound -R:540:0x02:0x5a - -# Acidic cytoplasm -R:541:0x0d:0x6a - -# Ooze elemental -R:545:0x0f:0x45 - -# Young black dragon -R:546:0x08:0x64 - -# Xorn -R:550:0x03:0x58 - -# Colossus -R:558:0x0b:0x67 - -# Bodak -R:566:0x08:0x75 - -# Lorgan, Chief of the Easterlings -R:573:0x0c:0x70 - -# Chaos spawn -R:574:0x07:0x65 - -# Crypt thing -R:577:0x0e:0x4c - -# Will o' the wisp -R:582:0x0b:0x45 - -# Crystal drake -R:591:0x0e:0x64 - -# Mature black dragon -R:592:0x08:0x64 - -# Draebor, the Imp -R:595:0x05:0x75 - -# Mother Hydra -R:596:0x05:0x75 - -# Death knight -R:597:0x02:0x70 - -# Time vortex -R:599:0x0d:0x76 - -# Shimmering vortex -R:600:0x0a:0x76 - -# Beholder -R:603:0x05:0x65 - -# Emperor wight -R:604:0x0b:0x57 - -# Vargo, Tyrant of Fire -R:606:0x0c:0x45 - -# Nether wraith -R:612:0x0c:0x57 - -# Waldern, King of Water -R:615:0x02:0x45 - -# Ettin -R:621:0x0b:0x54 - -# Night mare -R:622:0x0a:0x71 - -# Ancient black dragon -R:624:0x08:0x44 - -# Shadowfax, steed of Gandalf -R:629:0x09:0x71 - -# Spirit troll -R:630:0x0a:0x47 - -# War troll -R:631:0x05:0x54 - -# Rotting quylthulg -R:633:0x0f:0x51 - -# 9-headed hydra -R:635:0x03:0x4d - -# Enchantress -R:636:0x0b:0x70 - -# Sorcerer -R:638:0x03:0x70 - -# Xaren -R:639:0x0b:0x58 - -# Medusa, the Gorgon -R:642:0x03:0x6e - -# Death drake -R:643:0x07:0x44 - -# Great crystal drake -R:646:0x0e:0x44 - -# Wyrd sister -R:647:0x0b:0x70 - -# Death quasit -R:649:0x01:0x75 - -# Fallen angel -R:652:0x08:0x41 - -# Judge Fire -R:654:0x04:0x73 - -# Master lich -R:658:0x09:0x4c - -# Eol, the Dark Elf -R:660:0x02:0x68 - -# Undead beholder -R:664:0x02:0x65 - -# Dark young of Shub-Niggurath -R:677:0x08:0x55 - -# Dreadmaster -R:690:0x03:0x47 - -# Scatha the Worm -R:692:0x01:0x44 - -# Zoth-Ommog -R:695:0x07:0x52 - -# Grand master thief -R:696:0x0e:0x70 - -# Leprechaun fanatic -R:700:0x08:0x68 - -# Dracolich -R:701:0x0e:0x44 - -# Greater titan -R:702:0x0a:0x50 - -# Dracolisk -R:703:0x04:0x44 - -# Itangast the Fire Drake -R:710:0x04:0x44 - -# Glaurung, Father of the Dragons -R:715:0x04:0x44 - -# Behemoth -R:716:0x05:0x48 - -# Garm, Guardian of Hel -R:717:0x07:0x43 - -# Maulotaur -R:723:0x07:0x48 - -# Nether hound -R:724:0x08:0x5a - -# Time hound -R:725:0x0d:0x5a - -# Demonic quylthulg -R:727:0x0c:0x51 - -# Ulik the Troll -R:729:0x03:0x54 - -# Baphomet the Minotaur Lord -R:730:0x08:0x48 - -# Hell knight -R:731:0x02:0x70 - -# Old Sorcerer -R:738:0x0a:0x70 - -# Keeper of Secrets -R:746:0x0a:0x48 - -# Hand druj -R:748:0x08:0x73 - -# Eye druj -R:749:0x08:0x73 - -# Skull druj -R:750:0x08:0x73 - -# Aether vortex -R:752:0x0e:0x76 - -# Draconic quylthulg -R:759:0x0d:0x51 - -# Fundin Bluecloak -R:762:0x0d:0x68 - -# Gabriel, the Messenger -R:769:0x0a:0x41 - -# Artsi, the Champion of Chaos -R:770:0x0d:0x68 - -# The Cat Lord -R:777:0x04:0x66 - -# Vlad Dracula, Prince of Darkness -R:780:0x06:0x56 - -# Great Wyrm of Law -R:784:0x09:0x44 - -# Great Wyrm of Balance -R:785:0x02:0x44 - -# Glaaki -R:788:0x05:0x7e - -# Greater draconic quylthulg -R:801:0x05:0x51 - -# Greater rotting quylthulg -R:802:0x07:0x51 - -# Omarax the Eye Tyrant -R:805:0x0b:0x65 - -# Greater Balrog -R:807:0x0c:0x55 - -# Aether hound -R:811:0x0e:0x5a - -# Yig, Father of Serpents -R:814:0x05:0x4a - -# Hela, Queen of the Dead -R:817:0x05:0x70 - -# Master quylthulg -R:821:0x06:0x51 - -# Qlzqqlzuup, the Lord of Flesh -R:822:0x0e:0x51 - -# F'lar, rider of the Bronze Mnementh -R:824:0x08:0x44 - -# Cyaegha -R:826:0x08:0x65 - -# Pazuzu, Lord of Air -R:827:0x01:0x55 - -# Cantoras, the Skeletal Lord -R:830:0x0e:0x73 - -# Godzilla -R:832:0x05:0x52 - -# Loki, the Trickster -R:835:0x05:0x50 - -# Lungorthin, the Balrog of White Fire -R:839:0x01:0x55 - -# Draugluin, Sire of All Werewolves -R:840:0x07:0x43 - -# Vecna, the Emperor Lich -R:844:0x0b:0x4c - -# Great Wyrm of Power -R:847:0x0b:0x44 - -# Nodens, Lord of the Great Abyss -R:849:0x01:0x50 - -# Jormungand the Midgard Serpent -R:854:0x05:0x4a - -# The Destroyer -R:855:0x09:0x67 - -# Gothmog, the High Captain of Balrogs -R:856:0x0c:0x55 - -# Sauron, the Sorcerer -R:860:0x03:0x70 - -# Human Warrior -R:863:0x01:0x70 - -# Elven archer -R:864:0x0d:0x68 - -# Death -R:875:0x02:0x47 - -# Famine -R:876:0x02:0x47 - -# Pestilence -R:877:0x02:0x47 - -# War -R:878:0x02:0x47 - -# Giant piranha -R:884:0x0d:0x7e - -# Octopus -R:891:0x02:0x7e - -# Giant octopus -R:892:0x0a:0x7e - -# Drowned soul -R:895:0x02:0x47 - -# Devilfish -R:920:0x0a:0x7e - -# Undead devilfish -R:921:0x0a:0x7e - -# Gandalf the Grey -R:935:0x0a:0x70 - -# Brown Firelizard -R:942:0x0f:0x64 - -# Bronze Firelizard -R:943:0x01:0x64 - -# Elder aranea -R:964:0x04:0x53 - -# Bullroarer the Hobbit -R:985:0x06:0x68 - -# Hezrou -R:992:0x0a:0x55 - -# Glabrezu -R:993:0x03:0x55 - -# Lesser Balrog -R:996:0x0c:0x55 - -# The Rat King -R:1006:0x07:0x72 - -# Vort the Kobold Queen -R:1007:0x06:0x6b - -# Fire Phantom -R:1009:0x0c:0x47 - -# Bone golem -R:1013:0x08:0x67 - -# Snake of Yig -R:1014:0x04:0x4a - -# Cultist -R:1017:0x0e:0x70 - -# Cult leader -R:1018:0x06:0x70 - -# Green dragon worm -R:1025:0x05:0x77 - -# Red dragon worm -R:1027:0x04:0x77 - diff --git a/src/dungeon.c b/src/dungeon.c index a74fed2c..fdf11b3b 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -5623,13 +5623,6 @@ void play_game(bool_ new_game) /* Hack -- Enforce "delayed death" */ if (p_ptr->chp < 0) death = TRUE; - /* Should we use old colors */ - if (autoload_old_colors) - { - process_pref_file("422color.prf"); - } - - /* Process */ while (TRUE) { diff --git a/src/externs.h b/src/externs.h index deb93010..fbdbf916 100644 --- a/src/externs.h +++ b/src/externs.h @@ -529,7 +529,6 @@ extern bool_ center_player; extern s16b plots[MAX_PLOTS]; extern random_quest random_quests[MAX_RANDOM_QUEST]; extern bool_ exp_need; -extern bool_ autoload_old_colors; extern bool_ fate_option; extern bool_ *special_lvl[MAX_DUNGEON_DEPTH]; extern bool_ generate_special_feeling; diff --git a/src/tables.c b/src/tables.c index e3d3e664..f2478eef 100644 --- a/src/tables.c +++ b/src/tables.c @@ -1583,9 +1583,6 @@ option_type option_info[] = { &exp_need, FALSE, 5, 2, "exp_need", "Show the experience needed for next level" }, - { &autoload_old_colors, FALSE, 5, 3, - "old_colors", "Use the old(Z) coloring scheme(reload the game)" }, - { &auto_more, FALSE, 5, 4, "auto_more", "Automatically clear '-more-' prompts" }, diff --git a/src/variable.c b/src/variable.c index 84ca93ee..41d6a9a9 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1325,11 +1325,6 @@ random_quest random_quests[MAX_RANDOM_QUEST]; */ bool_ exp_need; -/* - * Auto load old colors; - */ -bool_ autoload_old_colors; - /* * Fated ? */ -- cgit v1.2.3 From 7d05ca4fd4562421f16d07dc6f13a23355953f11 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 24 Jun 2013 08:50:34 +0200 Subject: Remove fast_autoroller option It wasn't implemented anyway. --- lib/help/option.txt | 6 ------ lib/mods/theme/help/option.txt | 6 ------ src/externs.h | 1 - src/tables.c | 3 --- src/variable.c | 5 ----- 5 files changed, 21 deletions(-) diff --git a/lib/help/option.txt b/lib/help/option.txt index 7505f46b..ccb2896f 100644 --- a/lib/help/option.txt +++ b/lib/help/option.txt @@ -64,12 +64,6 @@ can also be viewed from the option menu while playing, but not changed then. Used in conjunction with the take_notes option, this option makes a note each time you gain a level, kill a unique, find an artifact, etc. -#####GFast autoroller (NOT on multiuser systems) [fast_autoroller] - The normal autoroller has a built-in delay that helps prevent it from - overloading a system. This option reduces that delay, allowing characters - to be rolled in a much shorter time, but should not be used on multiuser - systems. - #####GAllow use of some 'joke' monsters [joke_monsters] Allows monsters flagged as being some of DarkGod's jokes to be generated. diff --git a/lib/mods/theme/help/option.txt b/lib/mods/theme/help/option.txt index 93b34cd8..e4ee32f9 100644 --- a/lib/mods/theme/help/option.txt +++ b/lib/mods/theme/help/option.txt @@ -64,12 +64,6 @@ can also be viewed from the option menu while playing, but not changed then. Used in conjunction with the take_notes option, this option makes a note each time you gain a level, kill a unique, find an artifact, etc. -#####GFast autoroller (NOT on multiuser systems) [fast_autoroller] - The normal autoroller has a built-in delay that helps prevent it from - overloading a system. This option reduces that delay, allowing characters - to be rolled in a much shorter time, but should not be used on multiuser - systems. - #####GAllow use of some 'joke' monsters [joke_monsters] Allows monsters flagged as being some of DarkGod's jokes to be generated. diff --git a/src/externs.h b/src/externs.h index fbdbf916..fc930559 100644 --- a/src/externs.h +++ b/src/externs.h @@ -523,7 +523,6 @@ extern bool_ *m_allow_special; extern bool_ *k_allow_special; extern bool_ *a_allow_special; extern bool_ rand_birth; -extern bool_ fast_autoroller; extern bool_ joke_monsters; extern bool_ center_player; extern s16b plots[MAX_PLOTS]; diff --git a/src/tables.c b/src/tables.c index f2478eef..a66557cc 100644 --- a/src/tables.c +++ b/src/tables.c @@ -1619,9 +1619,6 @@ option_type option_info[] = { &auto_notes, TRUE, 6, 8, "auto_notes", "Automatically note important events" }, - { &fast_autoroller, FALSE, 6, 10, - "fast_autoroller", "Fast autoroller(NOT on multiuser systems)" }, - { &joke_monsters, FALSE, 6, 14, "joke_monsters", "Allow use of some 'joke' monsters" }, diff --git a/src/variable.c b/src/variable.c index 41d6a9a9..2510f6dd 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1295,11 +1295,6 @@ bool_ *a_allow_special; */ bool_ rand_birth; -/* - * Fast autoroller - */ -bool_ fast_autoroller; - /* * Which monsters are allowed ? */ -- cgit v1.2.3 From b09c46dab88eb95a130ffedf4fbd411d720d8a35 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 24 Jun 2013 10:27:59 +0200 Subject: Remove show_*_graph options --- lib/help/option.txt | 11 ----------- lib/mods/theme/help/option.txt | 11 ----------- lib/mods/theme/user/all.prf | 9 --------- src/externs.h | 3 --- src/object1.c | 26 +++++++++++++------------- src/store.c | 1 - src/tables.c | 9 --------- src/variable.c | 5 ----- 8 files changed, 13 insertions(+), 62 deletions(-) diff --git a/lib/help/option.txt b/lib/help/option.txt index ccb2896f..4c779254 100644 --- a/lib/help/option.txt +++ b/lib/help/option.txt @@ -134,17 +134,6 @@ off at will during the course of the game. discounts. The resulting stack keeps the largest discount. This option may cause you to lose "value", but will give you optimal pack usage. -#####GShow graphics in inventory list [show_inven_graph] - Display the graphics of objects in the inventory list, and in any special - window which is displaying the inventory list. - -#####GShow graphics in equipment list [show_equip_graph] - Display the graphics of objects in the equipment list, and in any special - window which is displaying the equipment list. - -#####GShow graphics in stores [show_store_graph] - Display the graphics of objects in the store list. - #####GAudible bell (on errors, etc) [ring_bell] Attempt to make a "bell" noise when various errors occur. diff --git a/lib/mods/theme/help/option.txt b/lib/mods/theme/help/option.txt index e4ee32f9..10edb403 100644 --- a/lib/mods/theme/help/option.txt +++ b/lib/mods/theme/help/option.txt @@ -134,17 +134,6 @@ off at will during the course of the game. discounts. The resulting stack keeps the largest discount. This option may cause you to lose "value", but will give you optimal pack usage. -#####GShow graphics in inventory list [show_inven_graph] - Display the graphics of objects in the inventory list, and in any special - window which is displaying the inventory list. - -#####GShow graphics in equipment list [show_equip_graph] - Display the graphics of objects in the equipment list, and in any special - window which is displaying the equipment list. - -#####GShow graphics in stores [show_store_graph] - Display the graphics of objects in the store list. - #####GAudible bell (on errors, etc) [ring_bell] Attempt to make a "bell" noise when various errors occur. diff --git a/lib/mods/theme/user/all.prf b/lib/mods/theme/user/all.prf index 4e9dead3..700c4637 100644 --- a/lib/mods/theme/user/all.prf +++ b/lib/mods/theme/user/all.prf @@ -41,15 +41,6 @@ Y:show_labels # Option 'Show weights in object listings' Y:show_weights -# Option 'Show graphics in inventory list' -Y:show_inven_graph - -# Option 'Show graphics in equipment list' -Y:show_equip_graph - -# Option 'Show graphics in stores' -Y:show_store_graph - # Option 'Show choices in certain sub-windows' Y:show_choices diff --git a/src/externs.h b/src/externs.h index fc930559..f86be687 100644 --- a/src/externs.h +++ b/src/externs.h @@ -188,9 +188,6 @@ extern int artifact_bias; extern FILE *text_out_file; extern void (*text_out_hook)(byte a, cptr str); extern int text_out_indent; -extern bool_ show_inven_graph; -extern bool_ show_store_graph; -extern bool_ show_equip_graph; extern bool_ rogue_like_commands; extern bool_ quick_messages; extern bool_ other_query_flag; diff --git a/src/object1.c b/src/object1.c index 504bc9c9..dd27c27e 100644 --- a/src/object1.c +++ b/src/object1.c @@ -4503,8 +4503,8 @@ void show_inven_aux(bool_ mirror, bool_ everything) /* Space for weight */ lim -= 9; - /* Require space for icon */ - if (show_inven_graph) lim -= 2; + /* Space for icon */ + lim -= 2; /* Find the "final" slot */ for (i = 0; i < INVEN_PACK; i++) @@ -4552,8 +4552,8 @@ void show_inven_aux(bool_ mirror, bool_ everything) /* Be sure to account for the weight */ l += 9; - /* Account for icon if displayed */ - if (show_inven_graph) l += 2; + /* Account for icon */ + l += 2; /* Maintain the maximum length */ if (l > len) len = l; @@ -4588,8 +4588,7 @@ void show_inven_aux(bool_ mirror, bool_ everything) /* Clear the line with the (possibly indented) index */ c_put_str(get_item_letter_color(o_ptr), tmp_val, row + j, col); - /* Display graphics for object, if desired */ - if (show_inven_graph) + /* Display graphics for object */ { byte a = object_attr(o_ptr); char c = object_char(o_ptr); @@ -4599,10 +4598,9 @@ void show_inven_aux(bool_ mirror, bool_ everything) Term_draw(col + 3, row + j, a, c); } - /* Display the entry itself */ c_put_str(out_color[j], out_desc[j], row + j, - show_inven_graph ? (col + 5) : (col + 3)); + col + 5); /* Display the weight */ { @@ -4680,7 +4678,8 @@ void show_equip_aux(bool_ mirror, bool_ everything) /* Require space for weight */ lim -= 9; - if (show_equip_graph) lim -= 2; + /* Require space for icon */ + lim -= 2; /* Scan the equipment list */ idx = 0; @@ -4781,7 +4780,8 @@ void show_equip_aux(bool_ mirror, bool_ everything) /* Increase length for weight */ l += 9; - if (show_equip_graph) l += 2; + /* Icon */ + l += 2; /* Maintain the max-length */ if (l > len) len = l; @@ -4817,7 +4817,7 @@ void show_equip_aux(bool_ mirror, bool_ everything) /* Clear the line with the (possibly indented) index */ c_put_str(get_item_letter_color(o_ptr), tmp_val, row + j, col); - if (show_equip_graph) + /* Show icon */ { byte a = object_attr(o_ptr); char c = object_char(o_ptr); @@ -4831,10 +4831,10 @@ void show_equip_aux(bool_ mirror, bool_ everything) { /* Mention the use */ (void)sprintf(tmp_val, "%-14s: ", mention_use(out_rindex[j])); - put_str(tmp_val, row + j, show_equip_graph ? col + 5 : col + 3); + put_str(tmp_val, row + j, col + 5); /* Display the entry itself */ - c_put_str(out_color[j], out_desc[j], row + j, show_equip_graph ? col + 21 : col + 19); + c_put_str(out_color[j], out_desc[j], row + j, col + 21); } /* Display the weight */ diff --git a/src/store.c b/src/store.c index 6cdaad4a..e1977920 100644 --- a/src/store.c +++ b/src/store.c @@ -1647,7 +1647,6 @@ static void display_entry(int pos) cur_col = 3; - if (show_store_graph) { byte a = object_attr(o_ptr); char c = object_char(o_ptr); diff --git a/src/tables.c b/src/tables.c index a66557cc..60550de7 100644 --- a/src/tables.c +++ b/src/tables.c @@ -1382,15 +1382,6 @@ option_type option_info[] = { &stack_force_costs, FALSE, 1, 10, "stack_force_costs", "Merge discounts when stacking" }, - { &show_inven_graph, TRUE, 1, 13, - "show_inven_graph", "Show graphics in inventory list" }, - - { &show_equip_graph, TRUE, 1, 14, - "show_equip_graph", "Show graphics in equipment list" }, - - { &show_store_graph, TRUE, 1, 15, - "show_store_graph", "Show graphics in stores" }, - { &ring_bell, FALSE, 1, 18, "ring_bell", "Audible bell (on errors, etc)" }, /* Changed to default to FALSE -- it's so extremely annoying!!! -TY */ diff --git a/src/variable.c b/src/variable.c index 2510f6dd..9f828da9 100644 --- a/src/variable.c +++ b/src/variable.c @@ -199,11 +199,6 @@ bool_ stack_force_costs; /* Merge discounts when stacking */ bool_ ring_bell; /* Ring the bell (on errors, etc) */ -bool_ show_inven_graph; /* Show graphics in inventory */ -bool_ show_equip_graph; /* Show graphics in equip list */ -bool_ show_store_graph; /* Show graphics in store */ - - /* Option Set 2 -- Disturbance */ -- cgit v1.2.3 From 10c35c2542895ff7064208614c0a67e14d146df9 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 29 Jun 2013 05:49:37 +0200 Subject: Use "2.4" as save directory and bump SAVEFILE_VERSION --- src/defines.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/defines.h b/src/defines.h index ac74b937..d06746d3 100644 --- a/src/defines.h +++ b/src/defines.h @@ -41,11 +41,9 @@ #define IS_CVS " (ah, git)" #endif -#define USER_PATH_VERSION "/2.3" +#define USER_PATH_VERSION "/2.4" -#define ANGBAND_2_8_1 - -#define SAVEFILE_VERSION 104 +#define SAVEFILE_VERSION 105 /* * This value is not currently used -- cgit v1.2.3 From 966ae460fcde74c5e33782c829b732c9bd4c2821 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 29 Jun 2013 06:18:05 +0200 Subject: Remove unused chaos patron code --- lib/help/debug.txt | 2 +- lib/mods/theme/help/debug.txt | 2 +- src/birth.c | 15 -- src/defines.h | 41 ---- src/externs.h | 5 - src/loadsave.c | 2 +- src/tables.c | 180 ----------------- src/types.h | 2 - src/wizard2.c | 5 - src/xtra2.c | 439 ------------------------------------------ 10 files changed, 3 insertions(+), 690 deletions(-) diff --git a/lib/help/debug.txt b/lib/help/debug.txt index 0420a42c..65e7ff91 100644 --- a/lib/help/debug.txt +++ b/lib/help/debug.txt @@ -29,7 +29,7 @@ will not be scored if you use debug commands. *****debug.txt*29[o Edit object attributes] O (unused) *****debug.txt*31[p Phase door] P (unused) *****debug.txt*33[q Get a quest] Q (unused) - *****debug.txt*35[r Gain reward] *****debug.txt*36[R Create a trap] + r (unused) *****debug.txt*36[R Create a trap] *****debug.txt*37[s Summon monster] *****debug.txt*38[S Change the feature of the map] *****debug.txt*39[t Teleport] *****debug.txt*40[T Teleport to a town] *****debug.txt*41[u Complete map] *****debug.txt*42[U Become undead] diff --git a/lib/mods/theme/help/debug.txt b/lib/mods/theme/help/debug.txt index 780b2f4d..1fa0efd5 100644 --- a/lib/mods/theme/help/debug.txt +++ b/lib/mods/theme/help/debug.txt @@ -29,7 +29,7 @@ will not be scored if you use debug commands. *****debug.txt*29[o Edit object attributes] O (unused) *****debug.txt*31[p Phase door] *****debug.txt*32[P Panic save] *****debug.txt*33[q Get a quest] Q (unused) - *****debug.txt*35[r Gain reward] *****debug.txt*36[R Create a trap] + r (unused) *****debug.txt*36[R Create a trap] *****debug.txt*37[s Summon monster] *****debug.txt*38[S Change the feature of the map] *****debug.txt*39[t Teleport] *****debug.txt*40[T Teleport to a town] *****debug.txt*41[u Complete map] *****debug.txt*42[U Become undead] diff --git a/src/birth.c b/src/birth.c index 1751a14c..b219a1a0 100644 --- a/src/birth.c +++ b/src/birth.c @@ -185,9 +185,6 @@ static void save_prev_data(void) } previous_char.luck = p_ptr->luck_base; - /* Save the chaos patron */ - previous_char.chaos_patron = p_ptr->chaos_patron; - /* Save the weapon specialty */ previous_char.weapon = 0; @@ -225,9 +222,6 @@ static void load_prev_data(bool_ save) } temp.luck = p_ptr->luck_base; - /* Save the chaos patron */ - temp.chaos_patron = p_ptr->chaos_patron; - /* Save the weapon specialty */ temp.weapon = 0; @@ -256,9 +250,6 @@ static void load_prev_data(bool_ save) p_ptr->luck_base = previous_char.luck; p_ptr->luck_max = previous_char.luck; - /* Load the chaos patron */ - p_ptr->chaos_patron = previous_char.chaos_patron; - /* Load the history */ for (i = 0; i < 4; i++) { @@ -2673,9 +2664,6 @@ static bool_ player_birth_aux_point(void) /*** Generate ***/ process_hooks(HOOK_BIRTH, "()"); - /* Hack -- get a chaos patron even if you are not a chaos warrior */ - p_ptr->chaos_patron = (randint(MAX_PATRON)) - 1; - /* Get luck */ p_ptr->luck_base = rp_ptr->luck + rmp_ptr->luck + rand_range( -5, 5); p_ptr->luck_max = p_ptr->luck_base; @@ -3055,9 +3043,6 @@ static bool_ player_birth_aux_auto() /*** Generate ***/ process_hooks(HOOK_BIRTH, "()"); - /* Hack -- get a chaos patron even if you are not a chaos warrior */ - p_ptr->chaos_patron = (randint(MAX_PATRON)) - 1; - /* Input loop */ while (TRUE) { diff --git a/src/defines.h b/src/defines.h index d06746d3..37f0a8e9 100644 --- a/src/defines.h +++ b/src/defines.h @@ -147,51 +147,10 @@ */ #define MAX_SEXES 3 -/* The number of "patrons" available (for Chaos Warriors) */ -#define MAX_PATRON 16 - /* Number of Random Artifacts */ #define MAX_RANDARTS 84 #define MAX_T_ACT 51 -/* Chaos Warrior: Reward types: */ -#define REW_POLY_SLF 0 -#define REW_GAIN_EXP 1 -#define REW_LOSE_EXP 2 -#define REW_GOOD_OBJ 3 -#define REW_GREA_OBJ 4 -#define REW_CHAOS_WP 5 -#define REW_GOOD_OBS 6 -#define REW_GREA_OBS 7 -#define REW_TY_CURSE 8 -#define REW_SUMMON_M 9 -#define REW_H_SUMMON 10 -#define REW_DO_HAVOC 11 -#define REW_GAIN_ABL 12 -#define REW_LOSE_ABL 13 -#define REW_RUIN_ABL 14 -#define REW_AUGM_ABL 15 -#define REW_POLY_WND 16 -#define REW_HEAL_FUL 17 -#define REW_HURT_LOT 18 -#define REW_CURSE_WP 19 -#define REW_CURSE_AR 20 -#define REW_PISS_OFF 21 -#define REW_WRATH 22 -#define REW_DESTRUCT 23 -#define REW_GENOCIDE 24 -#define REW_MASS_GEN 25 -#define REW_DISPEL_C 26 -#define REW_UNUSED_1 27 -#define REW_UNUSED_2 28 -#define REW_UNUSED_3 29 -#define REW_UNUSED_4 30 -#define REW_UNUSED_5 31 -#define REW_IGNORE 32 -#define REW_SER_UNDE 33 -#define REW_SER_DEMO 34 -#define REW_SER_MONS 35 - /* bear barehanded attacks ... */ #define MAX_BEAR 8 diff --git a/src/externs.h b/src/externs.h index f86be687..fdf82f5e 100644 --- a/src/externs.h +++ b/src/externs.h @@ -65,9 +65,6 @@ extern cptr stat_names[6]; extern cptr stat_names_reduced[6]; extern cptr window_flag_desc[32]; extern option_type option_info[]; -extern cptr chaos_patrons[MAX_PATRON]; -extern int chaos_stats[MAX_PATRON]; -extern int chaos_rewards[MAX_PATRON][20]; extern martial_arts bear_blows[MAX_BEAR]; extern martial_arts ma_blows[MAX_MA]; extern magic_power mindcraft_powers[MAX_MINDCRAFT_POWERS]; @@ -2181,8 +2178,6 @@ extern bool_ target_set(int mode); extern bool_ get_aim_dir(int *dp); extern bool_ get_hack_dir(int *dp); extern bool_ get_rep_dir(int *dp); -extern int get_chaos_patron(void); -extern void gain_level_reward(int chosen_reward); extern bool_ set_shadow(int v); extern bool_ set_tim_esp(int v); extern bool_ tgp_pt(int *x, int * y); diff --git a/src/loadsave.c b/src/loadsave.c index 0f01e8ec..48a982c6 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -585,7 +585,7 @@ static bool_ do_extra(int flag) do_s32b(&p_ptr->inertia_controlled_spell, flag); do_s16b(&p_ptr->last_rewarded_level, flag); - do_s16b(&p_ptr->chaos_patron, flag); + do_s16b(&tmp16s, flag); /* compat */ if (flag == LS_SAVE) { tmp16s = CORRUPTIONS_MAX; } do_s16b(&tmp16s, flag); diff --git a/src/tables.c b/src/tables.c index 60550de7..6430e69a 100644 --- a/src/tables.c +++ b/src/tables.c @@ -1639,186 +1639,6 @@ option_type option_info[] = }; -cptr chaos_patrons[MAX_PATRON] = -{ - "Slortar", - "Mabelode", - "Chardros", - "Hionhurn", - "Xiombarg", - - "Pyaray", - "Balaan", - "Arioch", - "Eequor", - "Narjhan", - - "Balo", - "Khorne", - "Slaanesh", - "Nurgle", - "Tzeentch", - - "Khaine" -}; - -int chaos_stats[MAX_PATRON] = -{ - A_CON, /* Slortar */ - A_CON, /* Mabelode */ - A_STR, /* Chardros */ - A_STR, /* Hionhurn */ - A_STR, /* Xiombarg */ - - A_INT, /* Pyaray */ - A_STR, /* Balaan */ - A_INT, /* Arioch */ - A_CON, /* Eequor */ - A_CHR, /* Narjhan */ - - -1, /* Balo */ - A_STR, /* Khorne */ - A_CHR, /* Slaanesh */ - A_CON, /* Nurgle */ - A_INT, /* Tzeentch */ - - A_STR, /* Khaine */ -}; - - - - -int chaos_rewards[MAX_PATRON][20] = -{ - /* Slortar the Old: */ - { - REW_WRATH, REW_CURSE_WP, REW_CURSE_AR, REW_RUIN_ABL, REW_LOSE_ABL, - REW_IGNORE, REW_IGNORE, REW_IGNORE, REW_POLY_WND, REW_POLY_SLF, - REW_POLY_SLF, REW_POLY_SLF, REW_GAIN_ABL, REW_GAIN_ABL, REW_GAIN_EXP, - REW_GOOD_OBJ, REW_CHAOS_WP, REW_GREA_OBJ, REW_AUGM_ABL, REW_AUGM_ABL - }, - - /* Mabelode the Faceless: */ - { - REW_WRATH, REW_CURSE_WP, REW_CURSE_AR, REW_H_SUMMON, REW_SUMMON_M, - REW_SUMMON_M, REW_IGNORE, REW_IGNORE, REW_POLY_WND, REW_POLY_WND, - REW_POLY_SLF, REW_HEAL_FUL, REW_HEAL_FUL, REW_GAIN_ABL, REW_SER_UNDE, - REW_CHAOS_WP, REW_GOOD_OBJ, REW_GOOD_OBJ, REW_GOOD_OBS, REW_GOOD_OBS - }, - - /* Chardros the Reaper: */ - { - REW_WRATH, REW_WRATH, REW_HURT_LOT, REW_PISS_OFF, REW_H_SUMMON, - REW_SUMMON_M, REW_IGNORE, REW_IGNORE, REW_DESTRUCT, REW_SER_UNDE, - REW_GENOCIDE, REW_MASS_GEN, REW_MASS_GEN, REW_DISPEL_C, REW_GOOD_OBJ, - REW_CHAOS_WP, REW_GOOD_OBS, REW_GOOD_OBS, REW_AUGM_ABL, REW_AUGM_ABL - }, - - /* Hionhurn the Executioner: */ - { - REW_WRATH, REW_WRATH, REW_CURSE_WP, REW_CURSE_AR, REW_RUIN_ABL, - REW_IGNORE, REW_IGNORE, REW_SER_UNDE, REW_DESTRUCT, REW_GENOCIDE, - REW_MASS_GEN, REW_MASS_GEN, REW_HEAL_FUL, REW_GAIN_ABL, REW_GAIN_ABL, - REW_CHAOS_WP, REW_GOOD_OBS, REW_GOOD_OBS, REW_AUGM_ABL, REW_AUGM_ABL - }, - - /* Xiombarg the Sword-Queen: */ - { - REW_TY_CURSE, REW_TY_CURSE, REW_PISS_OFF, REW_RUIN_ABL, REW_LOSE_ABL, - REW_IGNORE, REW_POLY_SLF, REW_POLY_SLF, REW_POLY_WND, REW_POLY_WND, - REW_GENOCIDE, REW_DISPEL_C, REW_GOOD_OBJ, REW_GOOD_OBJ, REW_SER_MONS, - REW_GAIN_ABL, REW_CHAOS_WP, REW_GAIN_EXP, REW_AUGM_ABL, REW_GOOD_OBS - }, - - - /* Pyaray the Tentacled Whisperer of Impossible Secretes: */ - { - REW_WRATH, REW_TY_CURSE, REW_PISS_OFF, REW_H_SUMMON, REW_H_SUMMON, - REW_IGNORE, REW_IGNORE, REW_IGNORE, REW_POLY_WND, REW_POLY_SLF, - REW_POLY_SLF, REW_SER_DEMO, REW_HEAL_FUL, REW_GAIN_ABL, REW_GAIN_ABL, - REW_CHAOS_WP, REW_DO_HAVOC, REW_GOOD_OBJ, REW_GREA_OBJ, REW_GREA_OBS - }, - - /* Balaan the Grim: */ - { - REW_TY_CURSE, REW_HURT_LOT, REW_CURSE_WP, REW_CURSE_AR, REW_RUIN_ABL, - REW_SUMMON_M, REW_LOSE_EXP, REW_POLY_SLF, REW_POLY_SLF, REW_POLY_WND, - REW_SER_UNDE, REW_HEAL_FUL, REW_HEAL_FUL, REW_GAIN_EXP, REW_GAIN_EXP, - REW_CHAOS_WP, REW_GOOD_OBJ, REW_GOOD_OBS, REW_GREA_OBS, REW_AUGM_ABL - }, - - /* Arioch, Duke of Hell: */ - { - REW_WRATH, REW_PISS_OFF, REW_RUIN_ABL, REW_LOSE_EXP, REW_H_SUMMON, - REW_IGNORE, REW_IGNORE, REW_IGNORE, REW_IGNORE, REW_POLY_SLF, - REW_POLY_SLF, REW_MASS_GEN, REW_SER_DEMO, REW_HEAL_FUL, REW_CHAOS_WP, - REW_CHAOS_WP, REW_GOOD_OBJ, REW_GAIN_EXP, REW_GREA_OBJ, REW_AUGM_ABL - }, - - /* Eequor, Blue Lady of Dismay: */ - { - REW_WRATH, REW_TY_CURSE, REW_PISS_OFF, REW_CURSE_WP, REW_RUIN_ABL, - REW_IGNORE, REW_IGNORE, REW_POLY_SLF, REW_POLY_SLF, REW_POLY_WND, - REW_GOOD_OBJ, REW_GOOD_OBJ, REW_SER_MONS, REW_HEAL_FUL, REW_GAIN_EXP, - REW_GAIN_ABL, REW_CHAOS_WP, REW_GOOD_OBS, REW_GREA_OBJ, REW_AUGM_ABL - }, - - /* Narjhan, Lord of Beggars: */ - { - REW_WRATH, REW_CURSE_AR, REW_CURSE_WP, REW_CURSE_WP, REW_CURSE_AR, - REW_IGNORE, REW_IGNORE, REW_IGNORE, REW_POLY_SLF, REW_POLY_SLF, - REW_POLY_WND, REW_HEAL_FUL, REW_HEAL_FUL, REW_GAIN_EXP, REW_AUGM_ABL, - REW_GOOD_OBJ, REW_GOOD_OBJ, REW_CHAOS_WP, REW_GREA_OBJ, REW_GREA_OBS - }, - - /* Balo the Jester: */ - { - REW_WRATH, REW_SER_DEMO, REW_CURSE_WP, REW_CURSE_AR, REW_LOSE_EXP, - REW_GAIN_ABL, REW_LOSE_ABL, REW_POLY_WND, REW_POLY_SLF, REW_IGNORE, - REW_DESTRUCT, REW_MASS_GEN, REW_CHAOS_WP, REW_GREA_OBJ, REW_HURT_LOT, - REW_AUGM_ABL, REW_RUIN_ABL, REW_H_SUMMON, REW_GREA_OBS, REW_AUGM_ABL - }, - - /* Khorne the Bloodgod: */ - { - REW_WRATH, REW_HURT_LOT, REW_HURT_LOT, REW_H_SUMMON, REW_H_SUMMON, - REW_IGNORE, REW_IGNORE, REW_IGNORE, REW_SER_MONS, REW_SER_DEMO, - REW_POLY_SLF, REW_POLY_WND, REW_HEAL_FUL, REW_GOOD_OBJ, REW_GOOD_OBJ, - REW_CHAOS_WP, REW_GOOD_OBS, REW_GOOD_OBS, REW_GREA_OBJ, REW_GREA_OBS - }, - - /* Slaanesh: */ - { - REW_WRATH, REW_PISS_OFF, REW_PISS_OFF, REW_RUIN_ABL, REW_LOSE_ABL, - REW_LOSE_EXP, REW_IGNORE, REW_IGNORE, REW_POLY_WND, REW_SER_DEMO, - REW_POLY_SLF, REW_HEAL_FUL, REW_HEAL_FUL, REW_GOOD_OBJ, REW_GAIN_EXP, - REW_GAIN_EXP, REW_CHAOS_WP, REW_GAIN_ABL, REW_GREA_OBJ, REW_AUGM_ABL - }, - - /* Nurgle: */ - { - REW_WRATH, REW_PISS_OFF, REW_HURT_LOT, REW_RUIN_ABL, REW_LOSE_ABL, - REW_LOSE_EXP, REW_IGNORE, REW_IGNORE, REW_IGNORE, REW_POLY_SLF, - REW_POLY_SLF, REW_POLY_WND, REW_HEAL_FUL, REW_GOOD_OBJ, REW_GAIN_ABL, - REW_GAIN_ABL, REW_SER_UNDE, REW_CHAOS_WP, REW_GREA_OBJ, REW_AUGM_ABL - }, - - /* Tzeentch: */ - { - REW_WRATH, REW_CURSE_WP, REW_CURSE_AR, REW_RUIN_ABL, REW_LOSE_ABL, - REW_LOSE_EXP, REW_IGNORE, REW_POLY_SLF, REW_POLY_SLF, REW_POLY_SLF, - REW_POLY_SLF, REW_POLY_WND, REW_HEAL_FUL, REW_CHAOS_WP, REW_GREA_OBJ, - REW_GAIN_ABL, REW_GAIN_ABL, REW_GAIN_EXP, REW_GAIN_EXP, REW_AUGM_ABL - }, - - /* Khaine: */ - { - REW_WRATH, REW_HURT_LOT, REW_PISS_OFF, REW_LOSE_ABL, REW_LOSE_EXP, - REW_IGNORE, REW_IGNORE, REW_DISPEL_C, REW_DO_HAVOC, REW_DO_HAVOC, - REW_POLY_SLF, REW_POLY_SLF, REW_GAIN_EXP, REW_GAIN_ABL, REW_GAIN_ABL, - REW_SER_MONS, REW_GOOD_OBJ, REW_CHAOS_WP, REW_GREA_OBJ, REW_GOOD_OBS - } -}; /* Names used for random artifact name generation */ cptr artifact_names_list = diff --git a/src/types.h b/src/types.h index c921d028..538df721 100644 --- a/src/types.h +++ b/src/types.h @@ -1607,8 +1607,6 @@ struct player_type s16b immov_cntr; /* Timed -- Last ``immovable'' command. */ - s16b chaos_patron; - s16b recall_dungeon; /* Recall in which dungeon */ s16b word_recall; /* Word of recall counter */ diff --git a/src/wizard2.c b/src/wizard2.c index 2a372bcd..66ddaa38 100644 --- a/src/wizard2.c +++ b/src/wizard2.c @@ -1735,11 +1735,6 @@ void do_cmd_debug(void) gain_random_corruption(); break; - /* Specific reward */ - case 'r': - (void) gain_level_reward(command_arg); - break; - /* Create a trap */ case 'R': wiz_place_trap(p_ptr->py, p_ptr->px, command_arg); diff --git a/src/xtra2.c b/src/xtra2.c index ef753b3a..6f86b5f7 100644 --- a/src/xtra2.c +++ b/src/xtra2.c @@ -1975,7 +1975,6 @@ bool_ set_food(int v) void check_experience(void) { int gained = 0; - bool_ level_reward = FALSE; bool_ level_corruption = FALSE; @@ -2086,12 +2085,6 @@ void check_experience(void) /* Handle stuff */ handle_stuff(); - if (level_reward) - { - gain_level_reward(0); - level_reward = FALSE; - } - if (level_corruption) { msg_print("You feel different..."); @@ -5284,438 +5277,6 @@ bool_ get_rep_dir(int *dp) } -int get_chaos_patron(void) -{ - return (((p_ptr->age) + (p_ptr->sc)) % MAX_PATRON); -} - - -void gain_level_reward(int chosen_reward) -{ - object_type *q_ptr; - object_type forge; - char wrath_reason[32] = ""; - int nasty_chance = 6; - int dummy = 0, dummy2 = 0; - int type, effect; - - - if (p_ptr->lev == 13) nasty_chance = 2; - else if (!(p_ptr->lev % 13)) nasty_chance = 3; - else if (!(p_ptr->lev % 14)) nasty_chance = 12; - - if (randint(nasty_chance) == 1) - type = randint(20); /* Allow the 'nasty' effects */ - else - type = randint(15) + 5; /* Or disallow them */ - - if (type < 1) type = 1; - if (type > 20) type = 20; - type--; - - - sprintf(wrath_reason, "the Wrath of %s", - chaos_patrons[p_ptr->chaos_patron]); - - effect = chaos_rewards[p_ptr->chaos_patron][type]; - - if ((randint(6) == 1) && !chosen_reward) - { - msg_format("%^s rewards you with a corruption!", - chaos_patrons[p_ptr->chaos_patron]); - gain_random_corruption(); - return; - } - - switch (chosen_reward ? chosen_reward : effect) - { - case REW_POLY_SLF : - msg_format("The voice of %s booms out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Thou needst a new form, mortal!'"); - do_poly_self(); - break; - - case REW_GAIN_EXP: - msg_format("The voice of %s booms out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Well done, mortal! Lead on!'"); - if (p_ptr->exp < PY_MAX_EXP) - { - s32b ee = (p_ptr->exp / 2) + 10; - if (ee > 100000L) ee = 100000L; - msg_print("You feel more experienced."); - gain_exp(ee); - } - break; - - case REW_LOSE_EXP: - msg_format("The voice of %s booms out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Thou didst not deserve that, slave.'"); - lose_exp(p_ptr->exp / 6); - break; - - case REW_GOOD_OBJ: - msg_format("The voice of %s whispers:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Use my gift wisely.'"); - acquirement(p_ptr->py, p_ptr->px, 1, FALSE, FALSE); - break; - - case REW_GREA_OBJ: - msg_format("The voice of %s booms out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Use my gift wisely.'"); - acquirement(p_ptr->py, p_ptr->px, 1, TRUE, FALSE); - break; - - case REW_CHAOS_WP: - msg_format("The voice of %s booms out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Thy deed hath earned thee a worthy blade.'"); - /* Get local object */ - q_ptr = &forge; - dummy = TV_SWORD; - switch (randint(p_ptr->lev)) - { - case 0: - case 1: - dummy2 = SV_DAGGER; - break; - case 2: - case 3: - dummy2 = SV_MAIN_GAUCHE; - break; - case 4: - case 5: - case 6: - dummy2 = SV_RAPIER; - break; - case 7: - case 8: - dummy2 = SV_SMALL_SWORD; - break; - case 9: - case 10: - dummy2 = SV_BASILLARD; - break; - case 11: - case 12: - case 13: - dummy2 = SV_SHORT_SWORD; - break; - case 14: - case 15: - dummy2 = SV_SABRE; - break; - case 16: - case 17: - dummy2 = SV_CUTLASS; - break; - case 18: - case 19: - dummy2 = SV_KHOPESH; - break; - case 20: - dummy2 = SV_TULWAR; - break; - case 21: - dummy2 = SV_BROAD_SWORD; - break; - case 22: - case 23: - dummy2 = SV_LONG_SWORD; - break; - case 24: - case 25: - dummy2 = SV_SCIMITAR; - break; - case 26: - case 27: - dummy2 = SV_KATANA; - break; - case 28: - case 29: - dummy2 = SV_BASTARD_SWORD; - break; - case 30: - dummy2 = SV_GREAT_SCIMITAR; - break; - case 31: - dummy2 = SV_CLAYMORE; - break; - case 32: - dummy2 = SV_ESPADON; - break; - case 33: - dummy2 = SV_TWO_HANDED_SWORD; - break; - case 34: - dummy2 = SV_FLAMBERGE; - break; - case 35: - case 36: - dummy2 = SV_EXECUTIONERS_SWORD; - break; - case 37: - dummy2 = SV_ZWEIHANDER; - break; - default: - dummy2 = SV_BLADE_OF_CHAOS; - } - - object_prep(q_ptr, lookup_kind(dummy, dummy2)); - q_ptr->to_h = 3 + (randint(dun_level)) % 10; - q_ptr->to_d = 3 + (randint(dun_level)) % 10; - random_resistance(q_ptr, FALSE, (randint(34) + 4)); - q_ptr->name2 = EGO_CHAOTIC; - - /* Apply the ego */ - apply_magic(q_ptr, dun_level, FALSE, FALSE, FALSE); - - /* Drop it in the dungeon */ - drop_near(q_ptr, -1, p_ptr->py, p_ptr->px); - break; - - case REW_GOOD_OBS: - msg_format("The voice of %s booms out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Thy deed hath earned thee a worthy reward.'"); - acquirement(p_ptr->py, p_ptr->px, randint(2) + 1, FALSE, FALSE); - break; - - case REW_GREA_OBS: - msg_format("The voice of %s booms out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Behold, mortal, how generously I reward thy loyalty.'"); - acquirement(p_ptr->py, p_ptr->px, randint(2) + 1, TRUE, FALSE); - break; - - case REW_TY_CURSE: - msg_format("The voice of %s thunders:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Thou art growing arrogant, mortal.'"); - activate_ty_curse(); - break; - - case REW_SUMMON_M: - msg_format("The voice of %s booms out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'My pets, destroy the arrogant mortal!'"); - for (dummy = 0; dummy < randint(5) + 1; dummy++) - { - (void)summon_specific(p_ptr->py, p_ptr->px, dun_level, 0); - } - break; - - case REW_H_SUMMON: - msg_format("The voice of %s booms out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Thou needst worthier opponents!'"); - activate_hi_summon(); - break; - - case REW_DO_HAVOC: - msg_format("The voice of %s booms out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Death and destruction! This pleaseth me!'"); - call_chaos(); - break; - - case REW_GAIN_ABL: - msg_format("The voice of %s rings out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Stay, mortal, and let me mold thee.'"); - if ((randint(3) == 1) && - !(chaos_stats[p_ptr->chaos_patron] < 0)) - do_inc_stat(chaos_stats[p_ptr->chaos_patron]); - else - do_inc_stat(randint(6) - 1); - break; - - case REW_LOSE_ABL: - msg_format("The voice of %s booms out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'I grow tired of thee, mortal.'"); - if ((randint(3) == 1) && - !(chaos_stats[p_ptr->chaos_patron] < 0)) - do_dec_stat(chaos_stats[p_ptr->chaos_patron], STAT_DEC_NORMAL); - else - (void)do_dec_stat(randint(6) - 1, STAT_DEC_NORMAL); - break; - - case REW_RUIN_ABL: - msg_format("The voice of %s thunders:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Thou needst a lesson in humility, mortal!'"); - msg_print("You feel less powerful!"); - for (dummy = 0; dummy < 6; dummy++) - { - (void)dec_stat(dummy, 10 + randint(15), TRUE); - } - break; - - case REW_POLY_WND: - msg_format("You feel the power of %s touch you.", - chaos_patrons[p_ptr->chaos_patron]); - do_poly_wounds(); - break; - - case REW_AUGM_ABL: - msg_format("The voice of %s booms out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Receive this modest gift from me!'"); - for (dummy = 0; dummy < 6; dummy++) - { - (void) do_inc_stat(dummy); - } - break; - - case REW_HURT_LOT: - msg_format("The voice of %s booms out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Suffer, pathetic fool!'"); - fire_ball(GF_DISINTEGRATE, 0, (p_ptr->lev * 4), 4); - take_hit(p_ptr->lev * 4, wrath_reason); - break; - - case REW_HEAL_FUL: - msg_format("The voice of %s booms out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Rise, my servant!'"); - restore_level(); - (void)set_poisoned(0); - (void)set_blind(0); - (void)set_confused(0); - (void)set_image(0); - (void)set_stun(0); - (void)set_cut(0); - hp_player(5000); - for (dummy = 0; dummy < 6; dummy++) - { - (void) do_res_stat(dummy, TRUE); - } - break; - - case REW_CURSE_WP: - msg_format("The voice of %s booms out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Thou reliest too much on thy weapon.'"); - (void)curse_weapon(); - break; - - case REW_CURSE_AR: - msg_format("The voice of %s booms out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Thou reliest too much on thine equipment.'"); - (void)curse_armor(); - break; - - case REW_PISS_OFF: - msg_format("The voice of %s whispers:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Now thou shalt pay for annoying me.'"); - switch (randint(4)) - { - case 1: - activate_ty_curse(); - break; - case 2: - activate_hi_summon(); - break; - case 3: - if (randint(2) == 1) (void)curse_weapon(); - else (void)curse_armor(); - break; - default: - for (dummy = 0; dummy < 6; dummy++) - { - (void) dec_stat(dummy, 10 + randint(15), TRUE); - } - break; - } - break; - - case REW_WRATH: - msg_format("The voice of %s thunders:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Die, mortal!'"); - take_hit(p_ptr->lev * 4, wrath_reason); - for (dummy = 0; dummy < 6; dummy++) - { - (void) dec_stat(dummy, 10 + randint(15), FALSE); - } - activate_hi_summon(); - activate_ty_curse(); - if (randint(2) == 1) (void)curse_weapon(); - if (randint(2) == 1) (void)curse_armor(); - break; - - case REW_DESTRUCT: - /* Prevent destruction of quest levels and town */ - if (!is_quest(dun_level) && dun_level) - { - msg_format("The voice of %s booms out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Death and destruction! This pleaseth me!'"); - destroy_area(p_ptr->py, p_ptr->px, 25, TRUE, FALSE); - } - break; - - case REW_GENOCIDE: - msg_format("The voice of %s booms out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Let me relieve thee of thine oppressors!'"); - (void) genocide(FALSE); - break; - - case REW_MASS_GEN: - msg_format("The voice of %s booms out:", - chaos_patrons[p_ptr->chaos_patron]); - msg_print("'Let me relieve thee of thine oppressors!'"); - (void) mass_genocide(FALSE); - break; - - case REW_DISPEL_C: - msg_format("You can feel the power of %s assault your enemies!", - chaos_patrons[p_ptr->chaos_patron]); - (void) dispel_monsters(p_ptr->lev * 4); - break; - - case REW_IGNORE: - msg_format("%s ignores you.", - chaos_patrons[p_ptr->chaos_patron]); - break; - - case REW_SER_DEMO: - msg_format("%s rewards you with a demonic servant!", chaos_patrons[p_ptr->chaos_patron]); - if (!(summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_DEMON, FALSE))) - msg_print("Nobody ever turns up..."); - break; - - case REW_SER_MONS: - msg_format("%s rewards you with a servant!", chaos_patrons[p_ptr->chaos_patron]); - if (!(summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_NO_UNIQUES, FALSE))) - msg_print("Nobody ever turns up..."); - break; - - case REW_SER_UNDE: - msg_format("%s rewards you with an undead servant!", chaos_patrons[p_ptr->chaos_patron]); - if (!(summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_UNDEAD, FALSE))) - msg_print("Nobody ever turns up..."); - break; - - default: - msg_format("The voice of %s stammers:", - chaos_patrons[p_ptr->chaos_patron]); - msg_format("'Uh... uh... the answer's %d/%d, what's the question?'", type, - effect ); - break; - } -} - - /* * old -- from PsiAngband. */ -- cgit v1.2.3 From 820480f8e22a0f881446542c173e9bd97c0665d6 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 29 Jun 2013 13:43:40 +0200 Subject: Remove unused other_query_flag option --- lib/help/option.txt | 3 --- lib/mods/theme/help/option.txt | 3 --- lib/mods/theme/user/all.prf | 3 --- src/externs.h | 1 - src/tables.c | 3 --- src/variable.c | 1 - 6 files changed, 14 deletions(-) diff --git a/lib/help/option.txt b/lib/help/option.txt index 4c779254..53121769 100644 --- a/lib/help/option.txt +++ b/lib/help/option.txt @@ -92,9 +92,6 @@ off at will during the course of the game. (useful for monster farming). Allows most keys to mean "no" to any "[y/n]" prompt. -#####GPrompt for various information [other_query_flag] - No longer used. - #####GPrompt before picking things up [carry_query_flag] Forces the game to ask you for confirmation when you do something that would normally cause an item to be picked up. diff --git a/lib/mods/theme/help/option.txt b/lib/mods/theme/help/option.txt index 10edb403..46db5b0d 100644 --- a/lib/mods/theme/help/option.txt +++ b/lib/mods/theme/help/option.txt @@ -92,9 +92,6 @@ off at will during the course of the game. (useful for monster farming). Allows most keys to mean "no" to any "[y/n]" prompt. -#####GPrompt for various information [other_query_flag] - No longer used. - #####GPrompt before picking things up [carry_query_flag] Forces the game to ask you for confirmation when you do something that would normally cause an item to be picked up. diff --git a/lib/mods/theme/user/all.prf b/lib/mods/theme/user/all.prf index 700c4637..e3da030f 100644 --- a/lib/mods/theme/user/all.prf +++ b/lib/mods/theme/user/all.prf @@ -8,9 +8,6 @@ X:rogue_like_commands # Option 'Activate quick messages' Y:quick_messages -# Option 'Prompt for various information' -X:other_query_flag - # Option 'Prompt before picking things up' X:carry_query_flag diff --git a/src/externs.h b/src/externs.h index fdf82f5e..6ac56f79 100644 --- a/src/externs.h +++ b/src/externs.h @@ -187,7 +187,6 @@ extern void (*text_out_hook)(byte a, cptr str); extern int text_out_indent; extern bool_ rogue_like_commands; extern bool_ quick_messages; -extern bool_ other_query_flag; extern bool_ carry_query_flag; extern bool_ always_pickup; extern bool_ prompt_pickup_heavy; diff --git a/src/tables.c b/src/tables.c index 6430e69a..1ebc52fd 100644 --- a/src/tables.c +++ b/src/tables.c @@ -1355,9 +1355,6 @@ option_type option_info[] = { &quick_messages, TRUE, 1, 1, "quick_messages", "Activate quick messages" }, - { &other_query_flag, FALSE, 1, 2, - "other_query_flag", "Prompt for various information" }, - { &carry_query_flag, FALSE, 1, 3, "carry_query_flag", "Prompt before picking things up" }, diff --git a/src/variable.c b/src/variable.c index 9f828da9..0cea5814 100644 --- a/src/variable.c +++ b/src/variable.c @@ -186,7 +186,6 @@ int text_out_indent = 0; bool_ rogue_like_commands; /* Rogue-like commands */ bool_ quick_messages; /* Activate quick messages */ -bool_ other_query_flag; /* Prompt for various information */ bool_ carry_query_flag; /* Prompt before picking things up */ bool_ use_old_target; /* Use old target by default */ bool_ always_pickup; /* Pick things up by default */ -- cgit v1.2.3 From bcfbd5d7c3d6a1485fd7f8ecab4f55235c0a3382 Mon Sep 17 00:00:00 2001 From: Elmo Todurov Date: Tue, 6 Aug 2013 11:17:02 +0300 Subject: Changed cbreak mode to raw mode in main-gcu. Fixes ctrl-c, ctl-s, ctrl-q in ncurses mode. --- src/main-gcu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main-gcu.c b/src/main-gcu.c index 57c41703..4e259a65 100644 --- a/src/main-gcu.c +++ b/src/main-gcu.c @@ -451,7 +451,7 @@ static errr Term_xtra_gcu_alive(int v) keymap_norm(); /* Restore modes */ - nocbreak(); + noraw(); echo(); nl(); @@ -482,7 +482,7 @@ static errr Term_xtra_gcu_alive(int v) /* (void)wrefresh(curscr); */ /* Restore the settings */ - cbreak(); + raw(); noecho(); nonl(); @@ -1114,7 +1114,7 @@ errr init_gcu(int argc, char **argv) #endif /* Prepare */ - cbreak(); + raw(); noecho(); nonl(); -- cgit v1.2.3 From 4e0b087706432e72753829db68265ef369428fe7 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 15 Jul 2013 17:30:16 +0200 Subject: !oExperience always grants 100K XP If you're lucky enough to find it early, you should be able to take full advantage of it. --- src/cmd6.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/cmd6.c b/src/cmd6.c index ce49b155..ab82bc17 100644 --- a/src/cmd6.c +++ b/src/cmd6.c @@ -2280,10 +2280,8 @@ static bool_ quaff_potion(int tval, int sval, int pval, int pval2) { if (p_ptr->exp < PY_MAX_EXP) { - s32b ee = (p_ptr->exp / 2) + 10; - if (ee > 100000L) ee = 100000L; msg_print("You feel more experienced."); - gain_exp(ee); + gain_exp(100000L); ident = TRUE; } -- cgit v1.2.3 From 62786de50b3a1a4ff6b945b31c54185b409bc85a Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 15 Jul 2013 17:30:16 +0200 Subject: Show list of Mindcrafter powers automatically on Mindcrafting menu User is no longer required to press '*' or SPC to show the drop-down list of Mindcrafter powers on the Mindcrafting menu. --- src/cmd7.c | 165 +++++++++++++++++++++++++++------------------------------- src/externs.h | 1 - 2 files changed, 77 insertions(+), 89 deletions(-) diff --git a/src/cmd7.c b/src/cmd7.c index 0276a6b6..555e7e17 100644 --- a/src/cmd7.c +++ b/src/cmd7.c @@ -110,6 +110,73 @@ void mimic_info(char *p, int power) } } +/** + * Show magic powers that user can choose from + */ +static void display_magic_powers( + magic_power *powers, + int max_powers, + void (*power_info)(char *p, int power), + int plev, + int cast_stat, + int y, + int x) +{ + char psi_desc[80]; + magic_power spell; + int i; + int chance = 0; + int minfail = 0; + char comment[80]; + + /* Display a list of spells */ + prt("", 1, x); + prt("", y, x); + put_str("Name", y, x + 5); + put_str("Lv Mana Fail Info", y, x + 35); + + /* Dump the spells */ + for (i = 0; i < max_powers; i++) + { + /* Access the spell */ + spell = powers[i]; + if (spell.min_lev > plev) + { + break; + } + + chance = spell.fail; + /* Reduce failure rate by "effective" level adjustment */ + chance -= 3 * (plev - spell.min_lev); + + /* Reduce failure rate by INT/WIS adjustment */ + chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[cast_stat]] - 1); + + /* Not enough mana to cast */ + if (spell.mana_cost > p_ptr->csp) + { + chance += 5 * (spell.mana_cost - p_ptr->csp); + } + + /* Extract the minimum failure rate */ + minfail = adj_mag_fail[p_ptr->stat_ind[cast_stat]]; + + /* Failure rate */ + chance = clamp_failure_chance(chance, minfail); + + /* Get info */ + power_info(comment, i); + + /* Dump the spell --(-- */ + strnfmt(psi_desc, 80, " %c) %-30s%2d %4d %3d%%%s", + I2A(i), spell.name, + spell.min_lev, spell.mana_cost, chance, comment); + prt(psi_desc, y + i + 1, x); + } + + /* Clear the bottom line */ + prt("", y + i + 1, x); +} /* * Allow user to choose a magic power. @@ -125,7 +192,7 @@ void mimic_info(char *p, int power) * when you run it. It's probably easy to fix but I haven't tried, * sorry. */ -bool_ get_magic_power(int *sn, magic_power *powers, int max_powers, +static bool_ get_magic_power(int *sn, magic_power *powers, int max_powers, void (*power_info)(char *p, int power), int plev, int cast_stat) { int i; @@ -136,23 +203,17 @@ bool_ get_magic_power(int *sn, magic_power *powers, int max_powers, int x = 18; - int minfail = 0; - - int chance = 0; - int info; char choice; char out_val[160]; - char comment[80]; - cptr p = "power"; magic_power spell; - bool_ flag, redraw; + bool_ flag; /* Assume cancelled */ @@ -172,9 +233,6 @@ bool_ get_magic_power(int *sn, magic_power *powers, int max_powers, /* Nothing chosen yet */ flag = FALSE; - /* No redraw yet */ - redraw = FALSE; - /* Count number of powers that satisfies minimum plev requirement */ for (i = 0; i < max_powers; i++) { @@ -185,88 +243,19 @@ bool_ get_magic_power(int *sn, magic_power *powers, int max_powers, } /* Build a prompt (accept all spells) */ - strnfmt(out_val, 78, "(%^ss %c-%c, *=List, ESC=exit, %c-%c=Info) Use which %s? ", + strnfmt(out_val, 78, "(%^ss %c-%c, ESC=exit, %c-%c=Info) Use which %s? ", p, I2A(0), I2A(num - 1), toupper(I2A(0)), toupper(I2A(num - 1)), p); /* Save the screen */ character_icky = TRUE; Term_save(); + /* Show the list */ + display_magic_powers(powers, max_powers, power_info, plev, cast_stat, y, x); + /* Get a spell from the user */ while (!flag && get_com(out_val, &choice)) { - /* Request redraw */ - if ((choice == ' ') || (choice == '*') || (choice == '?')) - { - /* Show the list */ - if (!redraw) - { - char psi_desc[80]; - - /* Show list */ - redraw = TRUE; - - /* Display a list of spells */ - prt("", 1, x); - prt("", y, x); - put_str("Name", y, x + 5); - put_str("Lv Mana Fail Info", y, x + 35); - - /* Dump the spells */ - for (i = 0; i < max_powers; i++) - { - /* Access the spell */ - spell = powers[i]; - if (spell.min_lev > plev) break; - - chance = spell.fail; - /* Reduce failure rate by "effective" level adjustment */ - chance -= 3 * (plev - spell.min_lev); - - /* Reduce failure rate by INT/WIS adjustment */ - chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[cast_stat]] - 1); - - /* Not enough mana to cast */ - if (spell.mana_cost > p_ptr->csp) - { - chance += 5 * (spell.mana_cost - p_ptr->csp); - } - - /* Extract the minimum failure rate */ - minfail = adj_mag_fail[p_ptr->stat_ind[cast_stat]]; - - /* Failure rate */ - chance = clamp_failure_chance(chance, minfail); - - /* Get info */ - power_info(comment, i); - - /* Dump the spell --(-- */ - strnfmt(psi_desc, 80, " %c) %-30s%2d %4d %3d%%%s", - I2A(i), spell.name, - spell.min_lev, spell.mana_cost, chance, comment); - prt(psi_desc, y + i + 1, x); - } - - /* Clear the bottom line */ - prt("", y + i + 1, x); - } - - /* Hide the list */ - else - { - /* Hide list */ - redraw = FALSE; - - /* Restore the screen */ - Term_load(); - character_icky = FALSE; - } - - /* Redo asking */ - continue; - } - /* Note verify */ info = (isupper(choice)); @@ -295,6 +284,9 @@ bool_ get_magic_power(int *sn, magic_power *powers, int max_powers, inkey(); Term_load(); character_icky = FALSE; + + /* Redisplay choices */ + display_magic_powers(powers, max_powers, power_info, plev, cast_stat, y, x); continue; } @@ -303,10 +295,7 @@ bool_ get_magic_power(int *sn, magic_power *powers, int max_powers, } /* Restore the screen */ - if (redraw) - { - Term_load(); - } + Term_load(); character_icky = FALSE; /* Abort if needed */ diff --git a/src/externs.h b/src/externs.h index 6ac56f79..a7a0748a 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2309,7 +2309,6 @@ extern int find_module(cptr name); /* lua_bind.c */ -extern bool_ get_magic_power(int *sn, magic_power *powers, int max_powers, void (*power_info)(char *p, int power), int plev, int cast_stat); extern s16b add_new_power(cptr name, cptr desc, cptr gain, cptr lose, byte level, byte cost, byte stat, byte diff); -- cgit v1.2.3 From 13503952c8aef44cebd3289a15b9ad2767a3937c Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 15 Jul 2013 17:30:16 +0200 Subject: Fix assert in case of subrace choices with no help The assert would trigger when trying to access the help from the Ent -> Classic menu item which has no associated help entry. --- src/help.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/help.c b/src/help.c index 6d196060..7aae360e 100644 --- a/src/help.c +++ b/src/help.c @@ -674,7 +674,10 @@ void init_hooks_help() */ static void show_context_help(context_help_type *context_help) { - assert(context_help != NULL); + if (context_help == NULL) + { + return; + } screen_save(); -- cgit v1.2.3 From 3dfea8f553013c251a60e2f99d5fa3f0ef65fec8 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 15 Jul 2013 17:30:16 +0200 Subject: Rework paralysis to avoid insta-death Paralysis would mean instant death (even when hit by a lowly floating eye), but this is not really an interesting mechanic. It has been reworked to not be cumulative, such that it isn't a death sentence, but is still very dangerous if the paralyzer is faster than the player. --- src/cmd2.c | 2 +- src/cmd6.c | 13 ++++++------- src/cmd7.c | 8 ++++---- src/dungeon.c | 4 ++-- src/externs.h | 1 + src/melee1.c | 4 ++-- src/melee2.c | 4 ++-- src/monster2.c | 2 +- src/spells1.c | 6 +++--- src/spells2.c | 8 ++++---- src/traps.c | 4 ++-- src/xtra2.c | 35 ++++++++++++++++++++++++++++++++--- 12 files changed, 60 insertions(+), 31 deletions(-) diff --git a/src/cmd2.c b/src/cmd2.c index 9b1a8ed7..20ef50af 100644 --- a/src/cmd2.c +++ b/src/cmd2.c @@ -2339,7 +2339,7 @@ static bool_ do_cmd_bash_aux(int y, int x, int dir) msg_print("You are off-balance."); /* Hack -- Lose balance ala paralysis */ - (void)set_paralyzed(p_ptr->paralyzed + 2 + rand_int(2)); + (void)set_paralyzed(2 + rand_int(2)); } /* Result */ diff --git a/src/cmd6.c b/src/cmd6.c index ab82bc17..bfe364e5 100644 --- a/src/cmd6.c +++ b/src/cmd6.c @@ -285,7 +285,7 @@ static void corpse_effect(object_type *o_ptr, bool_ cutting) { if (!p_ptr->free_act) { - set_paralyzed(p_ptr->paralyzed + dam + idam + 10); + set_paralyzed(dam + idam + 10); } break; @@ -1060,7 +1060,7 @@ void do_cmd_eat_food(void) { if (!p_ptr->free_act) { - if (set_paralyzed(p_ptr->paralyzed + rand_int(10) + 10)) + if (set_paralyzed(rand_int(10) + 10)) { ident = TRUE; } @@ -1779,7 +1779,7 @@ static bool_ quaff_potion(int tval, int sval, int pval, int pval2) msg_print("The potion makes you vomit!"); (void)set_food(PY_FOOD_STARVE - 1); (void)set_poisoned(0); - (void)set_paralyzed(p_ptr->paralyzed + 4); + (void)set_paralyzed(4); ident = TRUE; break; @@ -1846,7 +1846,7 @@ static bool_ quaff_potion(int tval, int sval, int pval, int pval2) { if (!p_ptr->free_act) { - if (set_paralyzed(p_ptr->paralyzed + rand_int(4) + 4)) + if (set_paralyzed(rand_int(4) + 4)) { ident = TRUE; } @@ -5383,8 +5383,7 @@ const char *activation_aux(object_type * o_ptr, bool_ doit, int item) msg_print("You are too weak to control the stone!"); /* Hack -- Bypass free action */ - (void)set_paralyzed(p_ptr->paralyzed + - randint(5 * oops + 1)); + (void)set_paralyzed(randint(5 * oops + 1)); /* Confusing. */ (void)set_confused(p_ptr->confused + @@ -6999,7 +6998,7 @@ const char *activation_aux(object_type * o_ptr, bool_ doit, int item) case ACT_PARALYZE: { if (!doit) return "paralyze"; - set_paralyzed(p_ptr->paralyzed + 20 + randint(10)); + set_paralyzed(20 + randint(10)); /* Timeout is set before return */ diff --git a/src/cmd7.c b/src/cmd7.c index 555e7e17..3d3b1bb2 100644 --- a/src/cmd7.c +++ b/src/cmd7.c @@ -698,7 +698,7 @@ void do_cmd_mindcraft(void) msg_print("You faint from the effort!"); /* Hack -- Bypass free action */ - (void)set_paralyzed(p_ptr->paralyzed + randint(5 * oops + 1)); + (void)set_paralyzed(randint(5 * oops + 1)); /* Damage WIS (possibly permanently) */ if (rand_int(100) < 50) @@ -1107,7 +1107,7 @@ void do_cmd_mimic(void) msg_print("You faint from the effort!"); /* Hack -- Bypass free action */ - (void)set_paralyzed(p_ptr->paralyzed + randint(5 * oops + 1)); + (void)set_paralyzed(randint(5 * oops + 1)); /* Damage WIS (possibly permanently) */ if (rand_int(100) < 50) @@ -5513,7 +5513,7 @@ void do_cmd_necromancer(void) msg_print("You faint from the effort!"); /* Hack -- Bypass free action */ - (void)set_paralyzed(p_ptr->paralyzed + randint(5 * oops + 1)); + (void)set_paralyzed(randint(5 * oops + 1)); /* Damage CON (possibly permanently) */ if (rand_int(100) < 50) @@ -7540,7 +7540,7 @@ void do_cmd_symbiotic(void) msg_print("You faint from the effort!"); /* Hack -- Bypass free action */ - (void)set_paralyzed(p_ptr->paralyzed + randint(5 * oops + 1)); + (void)set_paralyzed(randint(5 * oops + 1)); /* Damage CON (possibly permanently) */ if (rand_int(100) < 50) diff --git a/src/dungeon.c b/src/dungeon.c index fdf11b3b..de1a51fe 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -1802,7 +1802,7 @@ static void process_world(void) disturb(1, 0); /* Hack -- faint (bypass free action) */ - (void)set_paralyzed(p_ptr->paralyzed + 1 + rand_int(5)); + (void)set_paralyzed(1 + rand_int(5)); } } } @@ -2266,7 +2266,7 @@ static void process_world(void) /* Paralysis */ if (p_ptr->paralyzed) { - (void)set_paralyzed(p_ptr->paralyzed - 1); + dec_paralyzed(); } /* Confusion */ diff --git a/src/externs.h b/src/externs.h index a7a0748a..46675de7 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2130,6 +2130,7 @@ extern bool_ set_confused(int v); extern bool_ set_poisoned(int v); extern bool_ set_afraid(int v); extern bool_ set_paralyzed(int v); +extern void dec_paralyzed(); extern bool_ set_image(int v); extern bool_ set_fast(int v, int p); extern bool_ set_light_speed(int v); diff --git a/src/melee1.c b/src/melee1.c index 0940f7b4..157656a9 100644 --- a/src/melee1.c +++ b/src/melee1.c @@ -783,7 +783,7 @@ bool_ carried_make_attack_normal(int r_idx) } else { - if (set_paralyzed(p_ptr->paralyzed + 3 + randint(rlev))) + if (set_paralyzed(3 + randint(rlev))) { obvious = TRUE; } @@ -2418,7 +2418,7 @@ bool_ make_attack_normal(int m_idx, byte divis) } else { - if (set_paralyzed(p_ptr->paralyzed + 3 + randint(rlev))) + if (set_paralyzed(3 + randint(rlev))) { obvious = TRUE; } diff --git a/src/melee2.c b/src/melee2.c index 04575dd2..9dbdda86 100644 --- a/src/melee2.c +++ b/src/melee2.c @@ -3771,7 +3771,7 @@ bool_ make_attack_spell(int m_idx) } if (!p_ptr->free_act) { - (void)set_paralyzed(p_ptr->paralyzed + rand_int(4) + 4); + (void)set_paralyzed(rand_int(4) + 4); } (void)set_slow(p_ptr->slow + rand_int(4) + 4); @@ -4095,7 +4095,7 @@ bool_ make_attack_spell(int m_idx) } else { - (void)set_paralyzed(p_ptr->paralyzed + rand_int(4) + 4); + (void)set_paralyzed(rand_int(4) + 4); } update_smart_learn(m_idx, DRS_FREE); break; diff --git a/src/monster2.c b/src/monster2.c index 65d1c368..5ed4758a 100644 --- a/src/monster2.c +++ b/src/monster2.c @@ -1633,7 +1633,7 @@ void sanity_blast(monster_type * m_ptr, bool_ necro) } if (!p_ptr->free_act) { - (void)set_paralyzed(p_ptr->paralyzed + rand_int(4) + 4); + (void)set_paralyzed(rand_int(4) + 4); } while (rand_int(100) > p_ptr->skill_sav) (void)do_dec_stat(A_INT, STAT_DEC_NORMAL); diff --git a/src/spells1.c b/src/spells1.c index 9981f2be..5aec03bf 100644 --- a/src/spells1.c +++ b/src/spells1.c @@ -5348,7 +5348,7 @@ bool_ project_m(int who, int r, int y, int x, int dam, int typ) } default: if (!p_ptr->free_act) - (void)set_paralyzed(p_ptr->paralyzed + randint(dam)); + (void)set_paralyzed(randint(dam)); break; } } @@ -7954,7 +7954,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad { if (p_ptr->free_act) break; if (fuzzy) msg_print("You fall asleep!"); - set_paralyzed(p_ptr->paralyzed + dam); + set_paralyzed(dam); dam = 0; break; } @@ -8023,7 +8023,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad case GF_STASIS: { if (fuzzy) msg_print("You are hit by something paralyzing!"); - set_paralyzed(p_ptr->paralyzed + dam); + set_paralyzed(dam); break; } diff --git a/src/spells2.c b/src/spells2.c index cdd3af66..19fb9f8f 100644 --- a/src/spells2.c +++ b/src/spells2.c @@ -7083,9 +7083,9 @@ case 13: case 14: case 15: case 19: case 20: { msg_print("You feel like a statue!"); if (p_ptr->free_act) - set_paralyzed (p_ptr->paralyzed + randint(3)); + set_paralyzed(randint(3)); else - set_paralyzed (p_ptr->paralyzed + randint(13)); + set_paralyzed(randint(13)); stop_ty = TRUE; } if (randint(6) != 1) break; @@ -7175,9 +7175,9 @@ void activate_dg_curse(void) { msg_print("You feel like a statue!"); if (p_ptr->free_act) - set_paralyzed (p_ptr->paralyzed + randint(3)); + set_paralyzed(randint(3)); else - set_paralyzed (p_ptr->paralyzed + randint(13)); + set_paralyzed(randint(13)); stop_dg = TRUE; } if (randint(7) != 1) break; diff --git a/src/traps.c b/src/traps.c index 0006edc7..999f9acc 100644 --- a/src/traps.c +++ b/src/traps.c @@ -617,7 +617,7 @@ bool_ player_activate_trap_type(s16b y, s16b x, object_type *i_ptr, s16b item) if (!p_ptr->free_act) { msg_print("You touch a poisoned part and can't move."); - (void)set_paralyzed(p_ptr->paralyzed + rand_int(10) + 10); + (void)set_paralyzed(rand_int(10) + 10); ident = TRUE; } else @@ -706,7 +706,7 @@ bool_ player_activate_trap_type(s16b y, s16b x, object_type *i_ptr, s16b item) if (!p_ptr->free_act) { - (void)set_paralyzed(p_ptr->paralyzed + rand_int(dun_level) + 6); + (void)set_paralyzed(rand_int(dun_level) + 6); } ident = TRUE; break; diff --git a/src/xtra2.c b/src/xtra2.c index 6f86b5f7..a0d500f2 100644 --- a/src/xtra2.c +++ b/src/xtra2.c @@ -676,11 +676,14 @@ bool_ set_afraid(int v) /* - * Set "p_ptr->paralyzed", notice observable changes + * Mechanics for setting the "paralyzed" field. */ -bool_ set_paralyzed(int v) +static bool_ set_paralyzed_aux(int v) { - bool_ notice = set_simple_field( + bool_ notice; + + /* Normal processing */ + notice = set_simple_field( &p_ptr->paralyzed, v, TERM_WHITE, "You are paralyzed!", TERM_WHITE, "You can move again."); @@ -698,6 +701,32 @@ bool_ set_paralyzed(int v) return notice; } +/* + * Set "p_ptr->paralyzed", notice observable changes + */ +bool_ set_paralyzed(int v) +{ + /* Paralysis effects do not accumulate -- this is to + prevent the uninteresting insta-death effect, but + still leave paralyzers highly dangerous if they're + faster than the player. */ + + if (p_ptr->paralyzed > 0) { + return FALSE; + } + + /* Normal processing */ + return set_paralyzed_aux(v); +} + +/* + * Decrement "p_ptr->paralyzed", notice observable changes + */ +void dec_paralyzed() +{ + set_paralyzed_aux(p_ptr->paralyzed - 1); +} + /* * Set "p_ptr->image", notice observable changes -- cgit v1.2.3 From 1d700624578364d23cd1667490d773cab1e84ed1 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 15 Jul 2013 17:30:16 +0200 Subject: Use proper random sampling for Lost Sword skill reward --- src/skills.c | 171 +++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 126 insertions(+), 45 deletions(-) diff --git a/src/skills.c b/src/skills.c index c343dcce..4df3c1b3 100644 --- a/src/skills.c +++ b/src/skills.c @@ -12,6 +12,7 @@ #include "angband.h" +#include /* * Advance the skill point of the skill specified by i and @@ -1238,84 +1239,164 @@ void init_skill(s32b value, s32b mod, int i) s_info[i].hidden = FALSE; } +/* + * Perform weighted random selection without replacement according to + * the algorithm given in "Weighted Random Sampling" (2005, Eframidis, + * Spirakis) + * + * @param n is the total number of items to choose from. + * @param k is the total number of items to choose. + * @param weights is the array of weights. + * @param indexes is the output array containing the chosen permutation. + * The first k values will be set to a value in [0, n[ according to + * which item was chosen. + */ +static void wrs_without_replacement(size_t n, size_t k, s32b unscaled_weights[], size_t indexes[]) +{ + size_t i; + s32b scale; + double *weights = NULL; + double *keys = NULL; + size_t *permutation = NULL; + + assert(k <= n); + + /* Allocate working memory */ + keys = C_RNEW(n, double); + weights = C_RNEW(n, double); + permutation = C_RNEW(n, double); + + /* Calculate the scale of the weights. */ + scale = 0; + for (i = 0; i < n; i++) + { + scale += unscaled_weights[i]; + } + + /* Rescale weights into unit interval for numerical stability */ + for (i = 0; i < n; i++) { + weights[i] = + ((double) unscaled_weights[i]) / + ((double) scale); + } + + /* Generate the keys to use for selection. This is where the + magic happens. */ + for (i = 0; i < n; i++) { + double u = ((double) rand_int(100000)) / ((double) 100000); + keys[i] = pow(u, 1/weights[i]); + } + + /* Generate the initial permutation */ + for (i = 0; i < n; i++) { + permutation[i] = i; + } + + /* Select the k indexes with the largest keys */ + for (i = 0; i < k; i++) { + /* Find maximal value and its index */ + int max_idx = i; + double max_value = keys[max_idx]; + size_t j; + for (j = i+1; j < n; j++) { + if (keys[j] > max_value) { + max_idx = j; + max_value = keys[j]; + } + } + + /* Swap into k'th position */ + if (max_idx != i) { + double tmp_key; + size_t tmp_idx; + /* Swap keys */ + tmp_key = keys[i]; + keys[i] = keys[max_idx]; + keys[max_idx] = tmp_key; + /* Swap indexes in permutation */ + tmp_idx = permutation[i]; + permutation[i] = permutation[max_idx]; + permutation[max_idx] = tmp_idx; + } + + /* Output the k'th choice. */ + indexes[i] = permutation[i]; + } + + /* Clean up */ + C_FREE(keys, n, double); + C_FREE(weights, n, double); + C_FREE(permutation, n, size_t); +} + void do_get_new_skill() { char *items[LOST_SWORD_NSKILLS]; int skl[LOST_SWORD_NSKILLS]; s32b val[LOST_SWORD_NSKILLS], mod[LOST_SWORD_NSKILLS]; - bool_ used[MAX_SKILLS]; int available_skills[MAX_SKILLS]; - int max = 0, max_a = 0, res, i; + int max_a = 0, res, i; + size_t indexes[LOST_SWORD_NSKILLS]; + s32b weights[MAX_SKILLS]; /* Check if some skills didn't influence other stuff */ recalc_skills(TRUE); /* Grab the ones we can gain */ - max = 0; + max_a = 0; for (i = 0; i < max_s_idx; i++) { - if (s_info[i].flags1 & SKF1_RANDOM_GAIN) - available_skills[max++] = i; + if (s_info[i].flags1 & SKF1_RANDOM_GAIN) { + available_skills[max_a] = i; + max_a++; + } } - available_skills[max++] = -1; - /* Init */ - for (max = 0; max < MAX_SKILLS; max++) - { - used[max] = FALSE; + /* Perform the selection */ + for (i = 0; i < max_a; i++) { + weights[i] = s_info[available_skills[i]].random_gain_chance; } - /* Count the number of available skills */ - while (available_skills[max_a] != -1) max_a++; + wrs_without_replacement(max_a, LOST_SWORD_NSKILLS, weights, indexes); - /* Get LOST_SWORD_NSKILLS skills */ - for (max = 0; max < LOST_SWORD_NSKILLS; max++) + /* Extract the information needed from the skills */ + for (i = 0; i < LOST_SWORD_NSKILLS; i++) { - int i; - skill_type *s_ptr; - - /* Get an non used skill */ - do - { - i = rand_int(max_a); - - /* Does it pass the check? */ - if (!magik(s_info[available_skills[i]].random_gain_chance)) - continue; - } - while (used[available_skills[i]]); - - s_ptr = &s_info[available_skills[i]]; - used[available_skills[i]] = TRUE; + s32b s_idx = available_skills[indexes[i]]; + skill_type *s_ptr = &s_info[s_idx]; if (s_ptr->mod) { if (s_ptr->mod < 300) { - val[max] = 1000; - mod[max] = 300 - s_ptr->mod; + val[i] = 1000; + mod[i] = 300 - s_ptr->mod; } else if (s_ptr->mod < 500) { - val[max] = s_ptr->mod * 1; - mod[max] = 100; - if (mod[max] + s_ptr->mod > 500) - mod[max] = 500 - s_ptr->mod; + val[i] = s_ptr->mod * 1; + mod[i] = 100; + if (mod[i] + s_ptr->mod > 500) + mod[i] = 500 - s_ptr->mod; } else { - val[max] = s_ptr->mod * 3; - mod[max] = 0; + val[i] = s_ptr->mod * 3; + mod[i] = 0; } } else { - mod[max] = 300; - val[max] = 1000; + mod[i] = 300; + val[i] = 1000; + } + + if (s_ptr->value + val[i] > SKILL_MAX) { + val[i] = SKILL_MAX - s_ptr->value; } - if (s_ptr->value + val[max] > SKILL_MAX) val[max] = SKILL_MAX - s_ptr->value; - skl[max] = available_skills[i]; - items[max] = (char *)string_make(format("%-40s: +%02ld.%03ld value, +%01d.%03d modifier", s_ptr->name + s_name, val[max] / SKILL_STEP, val[max] % SKILL_STEP, mod[max] / SKILL_STEP, mod[max] % SKILL_STEP)); + + skl[i] = s_idx; + items[i] = (char *)string_make(format("%-40s: +%02ld.%03ld value, +%01d.%03d modifier", s_ptr->name + s_name, val[i] / SKILL_STEP, val[i] % SKILL_STEP, mod[i] / SKILL_STEP, mod[i] % SKILL_STEP)); } while (TRUE) @@ -1382,9 +1463,9 @@ void do_get_new_skill() } /* Free them ! */ - for (max = 0; max < LOST_SWORD_NSKILLS; max++) + for (i = 0; i < LOST_SWORD_NSKILLS; i++) { - string_free(items[max]); + string_free(items[i]); } /* Check if some skills didn't influence other stuff */ -- cgit v1.2.3 From 7a56383dbe952c9c8f7a979a6bab469f2b451a29 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 15 Jul 2013 17:30:16 +0200 Subject: Remove unnecessary override of quick_messages --- src/q_invas.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/q_invas.c b/src/q_invas.c index 59c71d62..985062af 100644 --- a/src/q_invas.c +++ b/src/q_invas.c @@ -84,8 +84,6 @@ bool_ quest_invasion_ai_hook(char *fmt) } bool_ quest_invasion_turn_hook(char *fmt) { - bool_ old_quick_messages = quick_messages; - if (cquest.status != QUEST_STATUS_UNTAKEN) return (FALSE); if (p_ptr->lev < 45) return (FALSE); @@ -96,7 +94,6 @@ bool_ quest_invasion_turn_hook(char *fmt) if (p_ptr->astral) return ( FALSE); /* Ok give the quest */ - quick_messages = FALSE; cmsg_print(TERM_YELLOW, "A Thunderlord appears in front of you and says:"); cmsg_print(TERM_YELLOW, "'Hello, noble hero. I am Liron, rider of Tolan. Turgon, King of Gondolin sent me.'"); cmsg_print(TERM_YELLOW, "'Gondolin is being invaded; he needs your help now or everything will be lost.'"); @@ -104,8 +101,6 @@ bool_ quest_invasion_turn_hook(char *fmt) cquest.status = QUEST_STATUS_TAKEN; - quick_messages = old_quick_messages; - quest_invasion_init_hook(QUEST_INVASION); del_hook(HOOK_END_TURN, quest_invasion_turn_hook); process_hooks_restart = TRUE; -- cgit v1.2.3 From 209b9c3b6afd06e098384b77bde4905a69be58ae Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 15 Jul 2013 17:30:17 +0200 Subject: Use 'c'/'s' in monster health bar if monster is confused/stunned --- src/xtra1.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/xtra1.c b/src/xtra1.c index 6e9b15fd..638a2102 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -1005,7 +1005,13 @@ static void health_redraw(void) Term_putstr(COL_INFO, ROW_INFO, 12, TERM_WHITE, "[----------]"); /* Dump the current "health" (use '*' symbols) */ - Term_putstr(COL_INFO + 1, ROW_INFO, len, attr, "**********"); + if (m_ptr->stunned) { + Term_putstr(COL_INFO + 1, ROW_INFO, len, attr, "ssssssssss"); + } else if (m_ptr->confused) { + Term_putstr(COL_INFO + 1, ROW_INFO, len, attr, "cccccccccc"); + } else { + Term_putstr(COL_INFO + 1, ROW_INFO, len, attr, "**********"); + } } } -- cgit v1.2.3 From 7105f93feb1ea0387e72939ed1e35a5fcd3ee546 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 15 Jul 2013 17:30:17 +0200 Subject: Remove 'auto_haggle' option --- lib/edit/ow_info.txt | 140 +++--- lib/mods/theme/edit/ow_info.txt | 424 +++++++++--------- src/defines.h | 1 - src/externs.h | 1 - src/init1.c | 11 +- src/loadsave.c | 4 - src/store.c | 932 ++++------------------------------------ src/tables.c | 3 - src/types.h | 16 +- src/variable.c | 2 - 10 files changed, 381 insertions(+), 1153 deletions(-) diff --git a/lib/edit/ow_info.txt b/lib/edit/ow_info.txt index a1e3d0a3..4bd7c41a 100644 --- a/lib/edit/ow_info.txt +++ b/lib/edit/ow_info.txt @@ -18,430 +18,430 @@ V:2.0.0 N:0:Bilbo the Friendly(Hobbit) -I:20000:170:108:5:15 +I:20000:120 C:120:100:80 L:Elf | Half-Elf | High-Elf | Dunadan | Hobbit | Dwarf | RohanKnight H:Orc | Troll | DeathMold | Half-Ogre | Beorning | Kobold N:1:Uldrik(Human) -I:20000:170:108:1:1 +I:20000:120 C:120:100:80 L:Dunadan | Hobbit | Human | H:Orc | Troll | DeathMold | Half-Ogre | Beorning | Kobold | N:2:Otick(Human) -I:100:170:108:4:10 +I:100:120 C:120:100:80 L:Dunadan | Hobbit | Human | H:Orc | Troll | DeathMold | Half-Ogre | Beorning | Kobold | N:3:Merana(Human) -I:0:170:108:1:1 +I:0:120 C:200:100:95 L:Human H:Orc | Troll | DeathMold | Half-Ogre | Beorning | Kobold | N:4:Mirimbar(High-Elf) -I:0:170:108:1:1 +I:0:120 C:120:100:80 L:High-Elf | Half-Elf | Elf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:5:Raistlin the Chicken(Human) -I:20000:175:108:4:12 +I:20000:130 C:120:100:80 L:Human H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:6:Sultan the Midget(Gnome) -I:30000:170:107:5:15 +I:30000:120 C:120:100:80 L:Gnome | Dwarf | Petty-Dwarf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:7:Lyar-el the Comely(Elf) -I:30000:165:107:6:18 +I:30000:120 C:120:100:80 L:Elf | Half-Elf | Dark-Elf | High-Elf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:8:Kon-Dar the Ugly(Half-Orc) -I:5000:210:115:5:7 +I:5000:140 C:120:100:80 L:Orc | Troll | Half-Ogre | Beorning | Kobold H:Gnome | Dwarf | Human | RohanKnight | Elf | Half-Elf | High-Elf N:9:Darg-Low the Grim(Human) -I:10000:190:111:4:9 +I:10000:130 C:120:100:80 L:Human H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:10:Decado the Handsome(Dunadan) -I:25000:200:112:4:10 +I:25000:140 C:120:100:80 L:Human | Dunadan | RohanKnight H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:11:Wieland the Smith(Dwarf) -I:30000:200:112:4:5 +I:30000:140 C:120:100:80 L:Gnome | Dwarf | Petty-Dwarf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:12:Arnold the Beastly(Barbarian) -I:5000:210:115:6:6 +I:5000:140 C:120:100:80 N:13:Arndal Beast-Slayer(Half-Elf) -I:10000:185:110:5:9 +I:10000:130 C:120:100:80 L:Elf | Half-Elf | Dark-Elf | High-Elf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:14:Eddie Beast-Master(Half-Orc) -I:25000:190:115:5:7 +I:25000:140 C:120:100:80 L:Orc | Troll | Half-Ogre | Beorning | Kobold H:Gnome | Dwarf | Human | RohanKnight | Elf | Half-Elf | High-Elf N:15:Oglign Dragon-Slayer(Dwarf) -I:30000:195:112:4:8 +I:30000:130 C:120:100:80 L:Gnome | Dwarf | Petty-Dwarf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:16:Aragorn(Dunadan) -I:20000:200:112:4:10 +I:20000:140 C:120:100:80 L:Human | Dunadan | RohanKnight H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:17:Sondar(Human) -I:0:200:112:4:10 +I:0:140 C:120:100:80 N:18:Celebor(Half-Elf) -I:100:170:108:4:10 +I:100:120 C:120:100:80 L:Dunadan | Hobbit | Human | H:Orc | Troll | DeathMold | Half-Ogre | Beorning | Kobold | N:19:Sharra(Human) -I:25000:200:112:4:10 +I:25000:140 C:120:100:80 L:Human | Dunadan | RohanKnight H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:20:Hjolgar(Barbarian) -I:5000:210:115:6:6 +I:5000:140 C:120:100:80 #L:Warrior | N:21:Tanistil(Elf) -I:5000:210:115:6:6 +I:5000:140 C:120:100:80 #L:Mage | Sorceror | Thaumaturgist #H:Warrior | N:22:Eldore(Human) -I:5000:210:115:6:6 +I:5000:140 C:120:100:80 #L:Priest #H:Necromancer N:23:Vilios(Human) -I:5000:210:115:6:6 +I:5000:140 C:120:100:80 #L:Paladin #H:Necromancer N:24:Angros(Elf) -I:5000:210:115:6:6 +I:5000:140 C:120:100:80 #L:Ranger N:25:Palano(Thunderlord) -I:0:210:115:6:6 +I:0:140 C:120:100:80 L:Thunderlord N:26:Ludwig the Humble(Dwarf) -I:5000:175:109:6:15 +I:5000:130 C:120:100:80 L:Gnome | Dwarf | Petty-Dwarf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:27:Gunnar the Paladin(Half-Troll) -I:10000:185:110:5:23 +I:10000:130 C:120:100:80 L:Orc | Troll | Half-Ogre | Beorning | Kobold H:Gnome | Dwarf | Human | RohanKnight | Elf | Half-Elf | High-Elf N:28:Torin the Chosen(High-Elf) -I:25000:180:107:6:20 +I:25000:130 C:120:100:80 L:High-Elf | Half-Elf | Elf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:29:Sarastro the Wise(Human) -I:30000:185:109:5:15 +I:30000:130 C:120:100:80 L:Dunadan | Hobbit | Human | H:Orc | Troll | DeathMold | Half-Ogre | Beorning | Kobold | N:30:Mauser the Chemist(Half-Elf) -I:10000:190:111:5:8 +I:10000:130 C:120:100:80 L:Dunadan | Hobbit | Human | H:Orc | Troll | DeathMold | Half-Ogre | Beorning | Kobold | N:31:Wizzle the Chaotic(Hobbit) -I:10000:190:110:6:8 +I:10000:130 C:120:100:80 L:Elf | Half-Elf | High-Elf | Dunadan | Hobbit | Dwarf | RohanKnight H:Orc | Troll | DeathMold | Half-Ogre | Beorning | Kobold | N:32:Midas the Greedy(Gnome) -I:15000:200:116:6:9 +I:15000:140 C:120:100:80 L:Gnome | Dwarf | Petty-Dwarf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:33:Ja-Far the Alchemist(Elf) -I:15000:220:111:4:9 +I:15000:140 C:120:100:80 L:Elf | Half-Elf | Dark-Elf | High-Elf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:34:Ariel the Sorceress(Half-Elf) -I:20000:200:110:7:8 +I:20000:140 C:120:100:80 L:Dunadan | Hobbit | Human | H:Orc | Troll | DeathMold | Half-Ogre | Beorning | Kobold | N:35:Buggerby the Great(Gnome) -I:20000:215:113:6:10 +I:20000:140 C:120:100:80 L:Gnome | Dwarf | Petty-Dwarf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:36:Inglorian the Mage(Human) -I:30000:200:110:7:10 +I:30000:140 C:120:100:80 L:Dunadan | Hobbit | Human | H:Orc | Troll | DeathMold | Half-Ogre | Beorning | Kobold | N:37:Luthien Starshine(High-Elf) -I:30000:175:110:5:11 +I:30000:130 C:120:100:80 L:High-Elf | Half-Elf | Elf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:38:Gary Gygaz(Half-Troll) -I:20000:250:150:10:5 +I:20000:180 C:120:100:80 #L:Rogue H:Gnome | Dwarf | Human | RohanKnight | Elf | Half-Elf | High-Elf N:39:Histor the Goblin(Half-Orc) -I:20000:250:150:10:5 +I:20000:180 C:120:100:80 #L:Rogue H:Gnome | Dwarf | Human | RohanKnight | Elf | Half-Elf | High-Elf N:40:Zorak the Smart(Dwarf) -I:30000:250:150:10:5 +I:30000:180 C:120:100:80 #L:Rogue H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:41:Tipo the Fair(Human) -I:30000:250:150:10:5 +I:30000:180 C:120:100:80 #L:Rogue H:Orc | Troll | DeathMold | Half-Ogre | Beorning | Kobold | N:42:Dolaf the Greedy(Human) -I:10000:175:108:4:12 +I:10000:130 C:120:100:80 L:Dunadan | Hobbit | Human | H:Orc | Troll | DeathMold | Half-Ogre | Beorning | Kobold | N:43:Odnar the Sage(High-Elf) -I:15000:120:105:6:16 +I:15000:110 C:120:100:80 L:High-Elf | Half-Elf | Elf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:44:Gandar the Neutral(Dark-Elf) -I:25000:120:110:7:19 +I:25000:110 C:120:100:80 L:High-Elf | Half-Elf | Elf H:Orc | Troll | Half-Ogre | Beorning | Kobold N:45:Ro-sha the Patient(Elf) -I:30000:140:105:6:12 +I:30000:110 C:120:100:80 L:Elf | Half-Elf | Dark-Elf | High-Elf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:46:N'rak the Summoner(Human) -I:10000:175:108:4:12 +I:10000:130 C:120:100:80 L:Human | Dunadan | RohanKnight H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:47:Esperion the Beastlover(High-Elf) -I:15000:120:105:6:16 +I:15000:110 C:120:100:80 L:High-Elf | Half-Elf | Elf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:48:Flarim the Shopkeeper(Dunadan) -I:25000:120:110:7:19 +I:25000:110 C:120:100:80 L:Human | Dunadan | RohanKnight H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:49:Tril-akheb the Supreme(Elf) -I:30000:140:105:6:12 +I:30000:110 C:120:100:80 L:Elf | Half-Elf | Dark-Elf | High-Elf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:50:Dorchel(Elf) -I:30000:140:105:6:12 +I:30000:110 C:120:100:80 L:Elf | Half-Elf | Dark-Elf | High-Elf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:51:Galadriel(High-Elf) -I:15000:120:105:6:16 +I:15000:110 C:120:100:80 L:High-Elf | Half-Elf | Elf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:52:Celeborn(High-Elf) -I:15000:120:105:6:16 +I:15000:110 C:120:100:80 L:High-Elf | Half-Elf | Elf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:53:Aulendil(Elf) -I:30000:140:105:6:12 +I:30000:110 C:120:100:80 #L:Warrior | H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:54:Valceronwe(Elf) -I:30000:140:105:6:12 +I:30000:110 C:120:100:80 #L:Mage | Thaumaturgist | Sorceror H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:55:Voronwe(Elf) -I:30000:140:105:6:12 +I:30000:110 C:120:100:80 #L:Priest | Paladin H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:56:Celegail(Elf) -I:30000:140:105:6:12 +I:30000:110 C:120:100:80 #L:Ranger H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:57:Turgon(High-Elf) -I:30000:120:105:6:16 +I:30000:110 C:120:100:80 L:High-Elf | Half-Elf | Elf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:58:Pengolodh(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf | Elf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:59:Aerandir(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf | Elf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:60:Celebrimbor(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf | Elf #L:Warrior | H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:61:Lomelosse(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf | Elf | H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:62:Arlindel(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf | Elf #L:Harper | Ranger H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:63:Sulraen(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf | Elf #L:Mage | Sorceror H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:64:Firiel(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf | Elf | H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:65:Earendur(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf | Elf H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:66:Glorfindel(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf #L:Ranger H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:67:Ecthelion(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf #L:Paladin H:Orc | Troll | Half-Ogre | Beorning | Kobold | N:68:Kanris(Human) -I:5000:210:115:6:6 +I:5000:140 C:120:100:80 #L:Merchant #H:Rogue N:69:Barliman Butterbur(Human) -I:100:170:108:4:10 +I:100:120 C:120:100:80 L:Dunadan | Hobbit | Human | H:Orc | Troll | DeathMold | Half-Ogre | Beorning | Kobold | diff --git a/lib/mods/theme/edit/ow_info.txt b/lib/mods/theme/edit/ow_info.txt index bf1283fb..92f0076a 100644 --- a/lib/mods/theme/edit/ow_info.txt +++ b/lib/mods/theme/edit/ow_info.txt @@ -19,7 +19,7 @@ V:2.0.0 # The zero index owner. If she owns a shop, there is a problem. :P N:0:Bell Goodchild(Hobbit) -I:20000:170:108:5:15 +I:20000:120 C:120:100:80 L:Elf | Half-Elf | High-Elf | Dunadan | Hobbit | Dwarf | RohanKnight H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning | Druadan | Dark-Elf @@ -27,25 +27,25 @@ H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning | Druadan | Dark-Elf ### The General Store - 1 ### N:1:Balin(Dwarf) -I:25000:180:108:2:2 +I:25000:130 C:150:100:50 L:Dwarf | Petty-Dwarf H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Troll N:2:Berylla Boffin(Hobbit) -I:20000:190:109:3:4 +I:20000:130 C:125:100:70 L:Human | Hobbit H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll | Easterling N:3:Adrahil(Half-Elf) -I:30000:170:107:1:1 +I:30000:120 C:110:100:80 L:Half-Elf | High-Elf | Dunadan | Elf H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Petty-Dwarf | Dwarf | Troll N:4:Aegnor(Wood-Elf) -I:10000:200:110:4:8 +I:10000:140 C:110:100:80 L:High-Elf | Dunadan | Elf H:Dragon | Demon | Orc | Half-Ogre | Troll | Easterling @@ -53,25 +53,25 @@ H:Dragon | Demon | Orc | Half-Ogre | Troll | Easterling ### The Armoury - 2 ### N:5:Bifur(Dwarf) -I:20000:190:109:3:4 +I:20000:130 C:125:100:70 L:Hobbit | Petty-Dwarf | Dwarf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll N:6:Lalia Clayhanger(Hobbit) -I:25000:180:108:2:2 +I:25000:130 C:125:100:50 L:Human | Hobbit | Elf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll N:7:Alcarin(Human) -I:10000:200:110:4:8 +I:10000:140 C:110:100:80 L:Human | Half-Elf | RohanKnight | Dunadan H:Dragon | Demon | Beorning | Orc | Half-Ogre | Petty-Dwarf | Troll | Easterling N:8:Alatariel(High-Elf) -I:30000:170:107:1:1 +I:30000:120 C:110:100:80 L:High-Elf | Dunadan | Elf H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Petty-Dwarf | Troll | Easterling @@ -79,25 +79,25 @@ H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Petty-Dwarf | Troll | Easterling ### The Weaponsmith - 3 ### N:9:Bofur(Dwarf) -I:30000:170:107:1:1 +I:30000:120 C:125:100:70 L:Human | Dwarf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll N:10:Daisy Gamgee(Hobbit) -I:20000:190:109:3:4 +I:20000:130 C:110:100:80 L:Human | Hobbit H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll N:11:Beregond(Dunadan) -I:25000:180:108:2:2 +I:25000:130 C:110:100:80 L:Human | High-Elf | Dunadan | Elf H:Dragon | Demon | Orc | Half-Ogre | Troll N:12:Amarie(Dark-Elf) -I:10000:200:110:4:8 +I:10000:140 C:125:100:50 L:Dark-Elf | Elf H:Dragon | Demon | Orc | Half-Ogre | Petty-Dwarf | Dwarf | Troll | Easterling @@ -105,25 +105,25 @@ H:Dragon | Demon | Orc | Half-Ogre | Petty-Dwarf | Dwarf | Troll | Easterling ### The Temple - 4 ### N:13:Bombur(Dwarf) -I:20000:190:109:3:4 +I:20000:130 C:125:100:70 L:Half-Elf | Petty-Dwarf | Dwarf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll N:14:Dora Baggins(Hobbit) -I:30000:170:107:1:1 +I:30000:120 C:110:100:80 L:Human | High-Elf | Hobbit | Elf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll N:15:Bergil(Half-Elf) -I:10000:200:110:4:8 +I:10000:140 C:125:100:50 L:Human | Half-Elf | Dunadan | Elf H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Troll | Easterling N:16:Amdir(Wood-Elf) -I:25000:180:108:2:2 +I:25000:130 C:110:100:80 L:High-Elf | Dunadan | Hobbit | Elf H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Dwarf | Troll | Easterling @@ -131,25 +131,25 @@ H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Dwarf | Troll | Easterling ### The Alchemist - 5 ### N:17:Borin(Dwarf) -I:20000:190:109:3:4 +I:20000:130 C:110:100:80 L:Petty-Dwarf | Dwarf H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Elf | Troll N:18:Elfstan Fairbairn(Hobbit) -I:10000:200:110:4:8 +I:10000:140 C:125:100:50 L:Human | Half-Elf | High-Elf | Hobbit | Elf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Dwarf | Troll N:19:Cemendur(Human) -I:25000:180:108:2:2 +I:25000:130 C:110:100:80 L:Human | Half-Elf | RohanKnight | Dunadan | Elf H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Troll | Easterling N:20:Annael(High-Elf) -I:30000:170:107:1:1 +I:30000:120 C:125:100:70 L:Human | Half-Elf | High-Elf | Dunadan | Elf H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Dwarf | Troll @@ -157,25 +157,25 @@ H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Dwarf | Troll ### The Magic Shop - 6 ### N:21:Dis(Dwarf) -I:30000:170:107:1:1 +I:30000:120 C:125:100:50 L:Petty-Dwarf | Dwarf | Half-Elf | Dunadan H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Human | Troll | Eagle N:22:Folco Boffin(Hobbit) -I:10000:200:110:4:8 +I:10000:140 C:110:100:80 L:Hobbit H:Dragon | Demon | Orc | Troll N:23:Ciryon(Dunadan) -I:25000:180:108:2:2 +I:25000:130 C:110:100:80 L:Human | Half-Elf | High-Elf | RohanKnight | Dunadan | Hobbit | Elf H:Dragon | Demon | Orc | Half-Ogre | Troll N:24:Arminas(Dark-Elf) -I:20000:190:109:3:4 +I:20000:130 C:125:100:70 L:Human | Dark-Elf | Elf H:Dragon | Demon | Beorning | Orc | High-Elf | Half-Ogre | Petty-Dwarf | Troll | Easterling @@ -183,25 +183,25 @@ H:Dragon | Demon | Beorning | Orc | High-Elf | Half-Ogre | Petty-Dwarf | Troll | ### The Black Market - 7 ### N:25:Dori(Dwarf) -I:30000:210:120:8:8 +I:30000:150 C:110:100:90 L:Dwarf | Easterling H:Dragon | Demon | Orc N:26:Halfred Greenhand(Hobbit) -I:30000:210:120:8:8 +I:30000:150 C:110:100:90 L:Hobbit H:Dragon | Demon | Troll N:27:Deorwine(Half-Elf) -I:30000:210:120:8:8 +I:30000:150 C:110:100:90 L:Half-Elf | Easterling H:Dragon | Demon | Dark-Elf N:28:Artanis(Wood-Elf) -I:30000:210:120:8:8 +I:30000:150 C:110:100:90 L:High-Elf | Elf | Easterling H:Dragon | Demon | Orc | Troll @@ -209,25 +209,25 @@ H:Dragon | Demon | Orc | Troll ### The Bookstore - 9 ### N:29:Dwalin(Dwarf) -I:20000:190:109:3:4 +I:20000:130 C:125:100:70 L:Human | Petty-Dwarf | Dwarf H:Dragon | Demon | Orc | Elf | Half-Ogre | Troll N:30:Tanta Hornblower(Hobbit) -I:10000:200:110:4:8 +I:10000:140 C:110:100:80 L:Human | Hobbit | Elf H:Dragon | Demon | Beorning | Orc | Troll N:31:Dorlas(Human) -I:30000:170:107:1:1 +I:30000:120 C:150:100:50 L:Human | RohanKnight | Dunadan H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll | Easterling N:32:Caranthir(High-Elf) -I:25000:180:108:2:2 +I:25000:130 C:110:100:80 L:Half-Elf | High-Elf | Elf H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Petty-Dwarf | Dwarf | Troll | Easterling @@ -235,25 +235,25 @@ H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Petty-Dwarf | Dwarf | Troll | Ea ### The Pet Shop - 0 ### N:33:Fili(Dwarf) -I:20000:190:109:3:4 +I:20000:130 C:125:100:70 L:RohanKnight | Petty-Dwarf | Dwarf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll N:34:Lalia Clayhanger(Hobbit) -I:25000:180:108:2:2 +I:25000:130 C:110:100:80 L:Human | Hobbit | Elf H:Dragon | Demon | Beorning | Orc | Troll N:35:Elfwine(Dunadan) -I:10000:200:110:4:8 +I:10000:140 C:110:100:80 L:Human | Half-Elf | High-Elf | RohanKnight | Dunadan | Elf H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Petty-Dwarf | Troll N:36:Edrahil(Dark-Elf) -I:30000:170:107:1:1 +I:30000:120 C:150:100:50 L:Dark-Elf | Elf | Easterling H:Dragon | Demon | Orc | High-Elf | Half-Ogre | Dwarf | Troll @@ -262,98 +262,98 @@ H:Dragon | Demon | Orc | High-Elf | Half-Ogre | Dwarf | Troll #Bree N:37:Uldrik(Human) -I:0:0:0:0:0 +I:0:0 C:0:0:0 L:Human | RohanKnight | Dunadan | Hobbit | H:Dragon | Demon | Orc | Half-Ogre | Troll #Minas Anor N:38:Aragorn (Dunadan) -I:0:0:0:0:0 +I:0:0 C:0:0:0 L:Human | High-Elf | RohanKnight | Dunadan | Hobbit | Elf H:Dragon | Demon | Orc | Half-Ogre | Petty-Dwarf | Troll #Khazad-Dum N:39:Gimli(Dwarf) -I:0:0:0:0:0 +I:0:0 C:0:0:0 L:RohanKnight | Dunadan | Hobbit | Elf | Dwarf H:Dragon | Demon | Orc | Half-Ogre | Troll #Beorn's Halls N:40:Deor(Beorning) -I:100:100:100:0:0 +I:100:100 C:110:100:90 L:Beorning | Dwarf | Maia | Hobbit | Ent H:Dragon | Demon | Orc | Half-Ogre | Troll #Dale N:41:Bard the Grim(Human) -I:100:100:100:0:0 +I:100:100 C:110:100:90 L:Human | Hobbit | Dwarf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll #Henneth Annun N:42:Halbarad(Dunadan) -I:100:100:100:0:0 +I:100:100 C:110:100:90 L:Human | High-Elf | Dunadan | Hobbit | Elf H:Dragon | Demon | Orc | Half-Ogre | Troll #Imladris N:43:Elrond Half-Elven -I:100:100:100:0:0 +I:100:100 C:110:100:90 L:Human | Half-Elf | High-Elf | RohanKnight | Dunadan | Hobbit | Elf | Dwarf | Ent H:Dragon | Demon | Orc | Half-Ogre | Troll #Helm's Deep N:44:Erkenbrand(RohanKnight) -I:100:100:100:0:0 +I:100:100 C:110:100:90 L:Human | Maia | RohanKnight | Dunadan | Hobbit | Elf | Dwarf | Ent H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Petty-Dwarf | Troll #Thranduil's Halls N:45:Legolas Greenleaf(Wood-Elf) -I:100:100:100:0:0 +I:100:100 C:110:100:90 L:High-Elf | Dunadan | Ent | Elf H:Dragon | Demon | Orc | Half-Ogre | Petty-Dwarf | Troll #Edoras N:46:Theoden(RohanKnight) -I:100:100:100:0:0 +I:100:100 C:110:100:90 L:Human | RohanKnight | Dunadan | Hobbit | Elf H:Dragon | Demon | Orc | Half-Ogre | Troll #Esgaroth N:47:The Master(Human) -I:100:100:100:0:0 +I:100:100 C:110:100:90 L:Human H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Troll #Hobbiton N:48:Samwise Gamgee(Hobbit) -I:100:100:100:0:0 +I:100:100 C:110:100:90 L:Hobbit | Elf | High-Elf | Dark-Elf H:Dragon | Demon | Orc | Half-Ogre | Troll #Osgiliath N:49:Eldacar(Human) -I:100:100:100:0:0 +I:100:100 C:110:100:90 L:Human | Half-Elf | High-Elf | RohanKnight | Dunadan | Hobbit | Elf H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Petty-Dwarf | Dwarf | Troll #Pelargir N:50:Earnil(Dunadan) -I:100:100:100:0:0 +I:100:100 C:110:100:90 L:Human | Half-Elf | High-Elf | RohanKnight | Dunadan | Hobbit | Elf H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Petty-Dwarf | Dwarf | Troll @@ -361,37 +361,37 @@ H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Petty-Dwarf | Dwarf | ### Caras Galadhon owners ### N:51:Galadriel(High-Elf) -I:15000:120:105:6:16 +I:15000:110 C:120:100:80 L:High-Elf | Half-Elf | Elf H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning N:52:Celeborn(High-Elf) -I:15000:120:105:6:16 +I:15000:110 C:120:100:80 L:High-Elf | Half-Elf | Elf H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning N:53:Aulendil(Elf) -I:30000:140:105:6:12 +I:30000:110 C:120:100:80 #L:Warrior | H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning N:54:Valceronwe(Elf) -I:30000:140:105:6:12 +I:30000:110 C:120:100:80 #L:Mage | Thaumaturgist | Sorceror H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning N:55:Voronwe(Elf) -I:30000:140:105:6:12 +I:30000:110 C:120:100:80 #L:Priest | Paladin H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning N:56:Celegail(Elf) -I:30000:140:105:6:12 +I:30000:110 C:120:100:80 #L:Ranger H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning @@ -399,71 +399,71 @@ H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning ### Gondolin owners ### N:57:Turgon(High-Elf) -I:30000:120:105:6:16 +I:30000:110 C:120:100:80 L:High-Elf | Half-Elf | Elf H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning | Easterling N:58:Pengolodh(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf | Elf H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning | Easterling N:59:Aerandir(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf | Elf H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning | Easterling N:60:Celebrimbor(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf | Elf #L:Warrior | H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning | Easterling N:61:Lomelosse(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf | Elf | H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning | Easterling N:62:Arlindel(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf | Elf #L:Harper | Ranger H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning | Easterling N:63:Sulraen(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf | Elf #L:Mage | Sorceror H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning | Easterling N:64:Firiel(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf | Elf | H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning | Easterling N:65:Earendur(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf | Elf H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning | Easterling N:66:Glorfindel(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf #L:Ranger H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning | Easterling N:67:Ecthelion(High-Elf) -I:0:120:105:6:16 +I:0:110 C:120:100:80 L:High-Elf | Half-Elf #L:Paladin @@ -473,70 +473,70 @@ H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning | Easterling #Bree N:68:Barliman Butterbur(Human) -I:100:170:108:4:10 +I:100:120 C:120:100:80 L:Dunadan | Hobbit | Human | H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning | Easterling #Pelargir N:69:Ciryatur(Dunadan) -I:100:170:108:4:10 +I:100:120 C:110:100:80 L:Dunadan | Human | RohanKnight H:Dragon | Demon | Orc | Troll | Half-Ogre | Beorning #Caras Galadhon N:70:Celebor(Elf) -I:100:170:108:4:10 +I:100:120 C:110:100:80 L:High-Elf | Elf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll | Easterling #Minas Anor N:71:Bregolas(Human) -I:100:170:108:4:10 +I:100:120 C:110:100:80 L:Human | RohanKnight | Dunadan H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll | Easterling #Khazad-Dum N:72:Thror(Dwarf) -I:100:170:108:4:10 +I:100:120 C:110:100:80 L:Petty-Dwarf | Dwarf H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | High-Elf | Troll #Dale N:73:Troin(Dwarf) -I:100:170:108:4:10 +I:100:120 C:110:100:80 L:Human | Dwarf H:Dragon | Demon | Orc | Half-Ogre | Troll #Edoras N:74:Theodwyn(Shieldmaiden) -I:100:170:108:4:10 +I:100:120 C:110:100:80 L:Human | RohanKnight | Dunadan H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll | Easterling #Esgaroth N:75:Garm(Human) -I:100:170:108:4:10 +I:100:120 C:110:100:80 L:Human | Dwarf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Petty-Dwarf | Troll #Hobbiton N:76:Rose Cotton(Hobbit) -I:100:170:108:4:10 +I:100:120 C:110:100:80 L:Human | High-Elf | Hobbit H:Dragon | Demon | Orc | Half-Ogre | Troll | Easterling #Osgiliath N:77:Palantir(Human) -I:100:170:108:4:10 +I:100:120 C:110:100:80 L:Human | High-Elf | RohanKnight | Dunadan | Elf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll | Easterling @@ -544,25 +544,25 @@ H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll | Easterling ### The Soothsayers ### N:78:Ori(Dwarf) -I:20000:190:109:3:4 +I:20000:130 C:125:100:70 L:Hobbit | Petty-Dwarf | Dwarf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll N:79:Tolman Gardner(Hobbit) -I:25000:180:108:2:2 +I:25000:130 C:150:100:50 L:Human | Hobbit | Elf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll N:80:Inziladun(Human) -I:10000:200:110:4:8 +I:10000:140 C:110:100:80 L:Human | Half-Elf | RohanKnight | Dunadan | Easterling H:Dragon | Demon | Beorning | Orc | Half-Ogre | Petty-Dwarf | Troll N:81:Gelmir(High-Elf) -I:30000:170:107:1:1 +I:30000:120 C:110:100:80 L:High-Elf | Dunadan | Elf H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Petty-Dwarf | Troll @@ -570,25 +570,25 @@ H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Petty-Dwarf | Troll ### The Eagles ### N:82:Palano(Eagle) -I:30000:170:110:1:1 +I:30000:130 C:125:100:50 L:Eagle H:Dragon | Demon | RohanKnight N:83:Eglad(Eagle) -I:30000:170:110:1:1 +I:30000:130 C:125:100:50 L:Eagle H:Dragon | Demon | Hobbit N:84:Hiron(Eagle) -I:30000:170:110:1:1 +I:30000:130 C:125:100:50 L:Eagle H:Dragon | Demon | Dunadan N:85:Grada(Eagle) -I:30000:170:110:1:1 +I:30000:130 C:125:100:50 L:Eagle H:Dragon | Demon | High-Elf @@ -596,25 +596,25 @@ H:Dragon | Demon | High-Elf ### The Librarians ### N:86:Frerin(Dwarf) -I:25000:180:108:2:2 +I:25000:130 C:150:100:50 L:Dwarf | Petty-Dwarf H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Troll N:87:Malva Headstrong(Hobbit) -I:20000:190:109:3:4 +I:20000:130 C:125:100:70 L:Human | Hobbit H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll N:88:Erendis(Half-Elf) -I:30000:170:107:1:1 +I:30000:120 C:110:100:80 L:Half-Elf | High-Elf | Dunadan | Elf | Easterling H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Petty-Dwarf | Dwarf | Troll N:89:Elemmakil(Wood-Elf) -I:10000:200:110:4:8 +I:10000:140 C:110:100:80 L:High-Elf | Dunadan | Elf H:Dragon | Demon | Orc | Half-Ogre | Troll @@ -622,25 +622,25 @@ H:Dragon | Demon | Orc | Half-Ogre | Troll ### The Casino Owners ### N:90:Fror(Dwarf) -I:20000:190:109:3:4 +I:20000:130 C:125:100:70 L:Hobbit | Petty-Dwarf | Dwarf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll N:91:Marmadas Brandybuck(Hobbit) -I:25000:180:108:2:2 +I:25000:130 C:150:100:50 L:Human | Hobbit | Elf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll N:92:Fastred(Human) -I:10000:200:110:4:8 +I:10000:140 C:110:100:80 L:Human | Half-Elf | RohanKnight | Dunadan | Easterling H:Dragon | Demon | Beorning | Orc | Half-Ogre | Petty-Dwarf | Troll N:93:Elured(High-Elf) -I:30000:170:107:1:1 +I:30000:120 C:110:100:80 L:High-Elf | Dunadan | Elf H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Petty-Dwarf | Troll @@ -648,25 +648,25 @@ H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Petty-Dwarf | Troll ### The Beastmasters ### N:94:Gloin(Dwarf) -I:30000:170:107:1:1 +I:30000:120 C:125:100:70 L:Human | Dwarf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll N:95:Milo Burrows(Hobbit) -I:20000:190:109:3:4 +I:20000:130 C:110:100:80 L:Human | Hobbit H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll N:96:Findegil(Dunadan) -I:25000:180:108:2:2 +I:25000:130 C:110:100:80 L:Human | High-Elf | Dunadan | Elf H:Dragon | Demon | Orc | Half-Ogre | Troll N:97:Elurin(Dark-Elf) -I:10000:200:110:4:8 +I:10000:140 C:150:100:50 L:Dark-Elf | Elf | Easterling H:Dragon | Demon | Orc | Half-Ogre | Petty-Dwarf | Dwarf | Troll @@ -676,25 +676,25 @@ H:Dragon | Demon | Orc | Half-Ogre | Petty-Dwarf | Dwarf | Troll #Fighters Hall N:98:Tarcil(Human) -I:30000:170:107:1:1 +I:30000:120 C:150:100:50 L:Human | RohanKnight | Dunadan H:Dragon | Demon | Orc | Half-Ogre | Troll | Easterling N:99:Ulbar(Easterling) -I:10000:200:110:4:8 +I:10000:140 C:110:100:80 L:Human | RohanKnight | Dunadan L:Half-Elf | High-Elf | Elf | Easterling N:100:Brego(RohanKnight) -I:25000:180:108:2:2 +I:25000:130 C:110:100:80 L:Human | RohanKnight | Dunadan H:Dragon | Demon | Beorning | Dark-Elf | Petty-Dwarf | Troll | Easterling N:101:Ostoher(Dunadan) -I:20000:190:109:3:4 +I:20000:130 C:125:100:70 L:Human | RohanKnight | Dunadan H:Dragon | Demon | Beorning | Orc | Half-Ogre | Dwarf | Troll | Easterling @@ -702,25 +702,25 @@ H:Dragon | Demon | Beorning | Orc | Half-Ogre | Dwarf | Troll | Easterling #Tower of Magery N:102:Arveleg(Human) -I:25000:180:108:2:2 +I:25000:130 C:125:100:70 L:Human | RohanKnight | Dunadan H:Dragon | Demon | Orc | Half-Ogre | Troll | Easterling N:103:Uldar(Easterling) -I:30000:170:107:1:1 +I:30000:120 C:110:100:80 L:Human | RohanKnight | Dunadan | Easterling L:Half-Elf | High-Elf | Elf N:104:Aldor(RohanKnight) -I:20000:190:109:3:4 +I:20000:130 C:150:100:50 L:Human | RohanKnight | Dunadan H:Dragon | Demon | Beorning | Dark-Elf | Petty-Dwarf | Troll | Easterling N:105:Tarannon(Dunadan) -I:10000:200:110:4:8 +I:10000:140 C:110:100:80 L:Human | RohanKnight | Dunadan H:Dragon | Demon | Beorning | Orc | Half-Ogre | Dwarf | Troll | Easterling @@ -728,25 +728,25 @@ H:Dragon | Demon | Beorning | Orc | Half-Ogre | Dwarf | Troll | Easterling #Inner Temple N:106:Eradan(Human) -I:30000:170:107:1:1 +I:30000:120 C:125:100:70 L:Human | RohanKnight | Dunadan H:Dragon | Demon | Orc | Half-Ogre | Troll N:107:Ulwise(Easterling) -I:25000:180:108:2:2 +I:25000:130 C:150:100:50 L:Human | RohanKnight | Dunadan | Easterling L:Half-Elf | High-Elf | Elf N:108:Gram(RohanKnight) -I:20000:190:109:3:4 +I:20000:130 C:110:100:80 L:Human | RohanKnight | Dunadan H:Dragon | Demon | Beorning | Dark-Elf | Petty-Dwarf | Troll | Easterling N:109:Minalcar(Dunadan) -I:10000:200:110:4:8 +I:10000:140 C:110:100:80 L:Human | RohanKnight | Dunadan H:Dragon | Demon | Beorning | Orc | Half-Ogre | Dwarf | Troll @@ -754,25 +754,25 @@ H:Dragon | Demon | Beorning | Orc | Half-Ogre | Dwarf | Troll #Paladins Guild N:110:Herion(Human) -I:30000:170:107:1:1 +I:30000:120 C:150:100:50 L:Human | RohanKnight | Dunadan | Easterling H:Dragon | Demon | Orc | Half-Ogre | Troll N:111:Ulgug(Easterling) -I:10000:200:110:4:8 +I:10000:140 C:110:100:80 L:Human | RohanKnight | Dunadan | Easterling L:Half-Elf | High-Elf | Elf N:112:Walda(RohanKnight) -I:25000:180:108:2:2 +I:25000:130 C:110:100:80 L:Human | RohanKnight | Dunadan H:Dragon | Demon | Beorning | Dark-Elf | Petty-Dwarf | Troll | Easterling N:113:Calimehtar(Dunadan) -I:20000:190:109:3:4 +I:20000:130 C:125:100:70 L:Human | RohanKnight | Dunadan H:Dragon | Demon | Beorning | Orc | Half-Ogre | Dwarf | Troll | Easterling @@ -780,25 +780,25 @@ H:Dragon | Demon | Beorning | Orc | Half-Ogre | Dwarf | Troll | Easterling #Rangers Guild N:114:Egalmoth(Human) -I:25000:180:108:2:2 +I:25000:130 C:125:100:70 L:Human | RohanKnight | Dunadan H:Dragon | Demon | Orc | Half-Ogre | Troll | Easterling N:115:Ulaf(Easterling) -I:30000:170:107:1:1 +I:30000:120 C:110:100:80 L:Human | RohanKnight | Dunadan | Easterling L:Half-Elf | High-Elf | Elf N:116:Fengel(RohanKnight) -I:20000:190:109:3:4 +I:20000:130 C:150:100:50 L:Human | RohanKnight | Dunadan H:Dragon | Demon | Beorning | Dark-Elf | Petty-Dwarf | Troll | Easterling N:117:Telemnar(Dunadan) -I:10000:200:110:4:8 +I:10000:140 C:110:100:80 L:Human | RohanKnight | Dunadan H:Dragon | Demon | Beorning | Orc | Half-Ogre | Dwarf | Troll @@ -808,25 +808,25 @@ H:Dragon | Demon | Beorning | Orc | Half-Ogre | Dwarf | Troll ### The Axesmiths ### N:118:Ris(Dwarf) -I:30000:200:130:1:1 +I:30000:150 C:150:100:50 L:Dwarf H:Dragon | Demon | Orc N:119:Malach Aradan(Human) -I:25000:300:150:2:2 +I:25000:200 C:125:100:60 L:Human | Easterling H:Dragon | Demon | Troll N:120:Indis(Half-Elf) -I:20000:250:140:3:4 +I:20000:170 C:115:100:70 L:Half-Elf | Easterling H:Dragon | Demon | Half-Ogre N:121:Rogdug(Half-Orc) -I:10000:150:120:4:8 +I:10000:130 C:125:100:80 L:Orc | Easterling H:Dragon | Demon | Elf @@ -834,25 +834,25 @@ H:Dragon | Demon | Elf ### The Haftedsmiths ### N:122:Sogur(Dwarf) -I:20000:250:140:3:4 +I:20000:170 C:125:100:80 L:Dwarf H:Dragon | Demon | Orc N:123:Manwendil(Human) -I:25000:300:150:2:2 +I:25000:200 C:115:100:70 L:Human | Easterling H:Dragon | Demon | Troll N:124:Lenwe(Half-Elf) -I:10000:150:120:4:8 +I:10000:130 C:150:100:50 L:Half-Elf | Easterling H:Dragon | Demon | Half-Ogre N:125:Ghaz(Half-Orc) -I:30000:200:130:1:1 +I:30000:150 C:125:100:60 L:Orc | Easterling H:Dragon | Demon | Elf @@ -860,25 +860,25 @@ H:Dragon | Demon | Elf ### The Polearmsmiths ### N:126:Tolin(Dwarf) -I:10000:150:120:4:8 +I:10000:130 C:115:100:70 L:Dwarf H:Dragon | Demon | Orc N:127:Narmacil(Human) -I:25000:300:150:2:2 +I:25000:200 C:125:100:80 L:Human | Easterling H:Dragon | Demon | Troll N:128:Lindir(Half-Elf) -I:20000:250:140:3:4 +I:20000:170 C:150:100:50 L:Half-Elf | Easterling H:Dragon | Demon | Half-Ogre N:129:Stogash(Half-Orc) -I:30000:200:130:1:1 +I:30000:150 C:125:100:60 L:Orc | Easterling H:Dragon | Demon | Elf @@ -886,25 +886,25 @@ H:Dragon | Demon | Elf ### The Swordsmiths ### N:130:Tis(Dwarf) -I:20000:250:140:3:4 +I:20000:170 C:125:100:80 L:Dwarf H:Dragon | Demon | Orc N:131:Nuneth(Human) -I:10000:150:120:4:8 +I:10000:130 C:125:100:60 L:Human | Easterling H:Dragon | Demon | Troll N:132:Mahtan(Half-Elf) -I:30000:200:130:1:1 +I:30000:150 C:115:100:70 L:Half-Elf | Easterling H:Dragon | Demon | Half-Ogre N:133:Rudak(Half-Orc) -I:25000:300:150:2:2 +I:25000:200 C:150:100:50 L:Orc | Easterling H:Dragon | Demon | Elf @@ -912,25 +912,25 @@ H:Dragon | Demon | Elf ### The Rare Jewellers ### N:134:Uin(Dwarf) -I:25000:300:150:2:2 +I:25000:200 C:115:100:70 L:Dwarf H:Dragon | Demon | Orc N:135:Ornendil(Human) -I:10000:150:120:4:8 +I:10000:130 C:125:100:60 L:Human | Easterling H:Dragon | Demon | Troll N:136:Malgalad(Half-Elf) -I:30000:200:130:1:1 +I:30000:150 C:125:100:80 L:Half-Elf | Easterling H:Dragon | Demon | Half-Ogre N:137:Ghashuf(Half-Orc) -I:20000:250:140:3:4 +I:20000:170 C:150:100:50 L:Orc | Easterling H:Dragon | Demon | Elf @@ -938,25 +938,25 @@ H:Dragon | Demon | Elf ### The Jewellers ### N:138:Vali(Dwarf) -I:25000:300:150:2:2 +I:25000:200 C:150:100:50 L:Dwarf H:Dragon | Demon | Orc N:139:Orodreth(Human) -I:30000:200:130:1:1 +I:30000:150 C:115:100:70 L:Human | Easterling H:Dragon | Demon | Troll N:140:Theodred(Half-Elf) -I:10000:150:120:4:8 +I:10000:130 C:125:100:80 L:Half-Elf | Easterling H:Dragon | Demon | Half-Ogre N:141:Rangush(Half-Orc) -I:20000:250:140:3:4 +I:20000:170 C:125:100:60 L:Orc | Easterling H:Dragon | Demon | Elf @@ -964,25 +964,25 @@ H:Dragon | Demon | Elf ### The Footwear Shop owners ### N:142:Nellas(Human) -I:10000:150:120:4:8 +I:10000:130 C:115:100:70 L:Human | Easterling H:Dragon | Demon | Troll N:143:Tindomiel(Half-Elf) -I:25000:300:150:2:2 +I:25000:200 C:125:100:80 L:Half-Elf | Easterling H:Dragon | Demon | Half-Ogre N:144:Ragnor(Half-Elf) -I:20000:250:140:3:4 +I:20000:170 C:150:100:50 L:Half-Elf | Easterling H:Dragon | Demon | Half-Ogre N:145:Idrish(Half-Orc) -I:30000:200:130:1:1 +I:30000:150 C:125:100:60 L:Orc | Easterling H:Dragon | Demon | Elf @@ -990,25 +990,25 @@ H:Dragon | Demon | Elf ### The Rare Footwear Shop owners ### N:146:Nerwen(Human) -I:20000:250:140:3:4 +I:20000:170 C:125:100:80 L:Human | Easterling H:Dragon | Demon | Troll N:147:Ulbar (Half-Elf) -I:10000:150:120:4:8 +I:10000:130 C:125:100:60 L:Half-Elf | Easterling H:Dragon | Demon | Half-Ogre N:148:Pelendur(Half-Elf) -I:30000:200:130:1:1 +I:30000:150 C:115:100:70 L:Half-Elf | Easterling H:Dragon | Demon | Half-Ogre N:149:Budgar(Half-Orc) -I:25000:300:150:2:2 +I:25000:200 C:150:100:50 L:Orc | Easterling H:Dragon | Demon | Elf @@ -1016,25 +1016,25 @@ H:Dragon | Demon | Elf ### The Dungeon Librarians ### N:150:Nom(Human) -I:25000:300:150:2:2 +I:25000:200 C:115:100:70 L:Human | Easterling H:Dragon | Demon | Troll N:151:Urwen (Half-Elf) -I:10000:150:120:4:8 +I:10000:130 C:125:100:60 L:Half-Elf | Easterling H:Dragon | Demon | Half-Ogre N:152:Rian(Half-Elf) -I:30000:200:130:1:1 +I:30000:150 C:125:100:80 L:Half-Elf | Easterling H:Dragon | Demon | Half-Ogre N:153:Mosrog(Half-Orc) -I:20000:250:140:3:4 +I:20000:170 C:150:100:50 L:Orc | Easterling H:Dragon | Demon | Elf @@ -1042,25 +1042,25 @@ H:Dragon | Demon | Elf ### The Expensive Black Marketeers ### N:154:Olwe(Human) -I:30000:300:150:8:8 +I:30000:200 C:125:100:90 L:Human | Easterling H:Dragon | Demon | Troll N:155:Valacar(Half-Elf) -I:30000:300:150:8:8 +I:30000:200 C:125:100:90 L:Half-Elf | Easterling H:Dragon | Demon | Half-Ogre N:156:Silmarien(Half-Elf) -I:30000:300:150:8:8 +I:30000:200 C:125:100:90 L:Half-Elf | Easterling H:Dragon | Demon | Half-Ogre N:157:Ghaz(Half-Orc) -I:30000:300:150:8:8 +I:30000:200 C:125:100:90 L:Orc | Easterling H:Dragon | Demon | Elf @@ -1068,25 +1068,25 @@ H:Dragon | Demon | Elf ### The Common Shop Owners ### N:158:Ioreth(Human) -I:25000:300:150:2:2 +I:25000:200 C:150:100:50 L:Human | Easterling H:Dragon | Demon | Troll N:159:Vidugavia(Half-Elf) -I:30000:200:130:1:1 +I:30000:150 C:115:100:70 L:Half-Elf | Easterling H:Dragon | Demon | Half-Ogre N:160:Soronto(Half-Elf) -I:10000:150:120:4:8 +I:10000:130 C:125:100:80 L:Half-Elf | Easterling H:Dragon | Demon | Half-Ogre N:161:Nazg(Half-Orc) -I:20000:250:140:3:4 +I:20000:170 C:125:100:60 L:Orc | Easterling H:Dragon | Demon | Elf @@ -1094,25 +1094,25 @@ H:Dragon | Demon | Elf ### The Dragon Hunters ### N:162:Oropher(Human) -I:10000:150:120:4:8 +I:10000:130 C:115:100:70 L:Human | Easterling H:Dragon | Demon | Troll N:163:Walda(Half-Elf) -I:25000:300:150:2:2 +I:25000:200 C:125:100:80 L:Half-Elf | Easterling H:Dragon | Demon | Half-Ogre N:164:Mithrellas(Half-Elf) -I:20000:250:140:3:4 +I:20000:170 C:150:100:50 L:Half-Elf | Easterling H:Dragon | Demon | Half-Ogre N:165:Urbag(Half-Orc) -I:30000:200:130:1:1 +I:30000:150 C:125:100:60 L:Orc | Easterling H:Dragon | Demon | Elf @@ -1120,25 +1120,25 @@ H:Dragon | Demon | Elf ### The Speed Ring Market Owners ### N:166:Orophin(Human) -I:20000:250:140:3:4 +I:20000:170 C:125:100:80 L:Human | Easterling H:Dragon | Demon | Troll N:167:Wulf(Half-Orc) -I:10000:150:120:4:8 +I:10000:130 C:125:100:60 L:Orc | Easterling H:Dragon | Demon | Elf N:168:Baguk(Half-Troll) -I:30000:200:130:1:1 +I:30000:150 C:115:100:70 L:Troll | Easterling H:Dragon | Demon | Human N:169:Zikram(Half-Orc) -I:25000:300:150:2:2 +I:25000:200 C:150:100:50 L:Orc | Easterling H:Dragon | Demon | Elf @@ -1146,25 +1146,25 @@ H:Dragon | Demon | Elf ### The Scribes ### N:170:Rumil(Human) -I:25000:300:150:2:2 +I:25000:200 C:115:100:70 L:Human | Easterling H:Dragon | Demon | Troll N:171:Saeros(Half-Elf) -I:10000:150:120:4:8 +I:10000:130 C:125:100:60 L:Half-Elf | Easterling H:Dragon | Demon | Half-Ogre N:172:Zartosh(Half-Orc) -I:30000:200:130:1:1 +I:30000:150 C:125:100:80 L:Orc | Easterling H:Dragon | Demon | Elf N:173:Shog(Half-Troll) -I:20000:250:140:3:4 +I:20000:170 C:150:100:50 L:Troll | Easterling H:Dragon | Demon | Human @@ -1172,25 +1172,25 @@ H:Dragon | Demon | Human ### The Potion Peddlers ### N:174:Zamin(Human) -I:25000:300:150:2:2 +I:25000:200 C:150:100:50 L:Human | Easterling H:Dragon | Demon | Troll N:175:Algosh(Half-Orc) -I:30000:200:130:1:1 +I:30000:150 C:115:100:70 L:Orc | Easterling H:Dragon | Demon | Elf N:176:Seghash(Half-Troll) -I:10000:150:120:4:8 +I:10000:130 C:125:100:80 L:Troll | Easterling H:Dragon | Demon | Human N:177:Kabbug(Half-Orc) -I:20000:250:140:3:4 +I:20000:170 C:125:100:60 L:Orc | Easterling H:Dragon | Demon | Elf @@ -1198,25 +1198,25 @@ H:Dragon | Demon | Elf ### The Master Archers ### N:178:Palin(Dwarf) -I:30000:170:107:1:1 +I:30000:120 C:125:100:70 L:Human | Dwarf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll | Easterling N:179:Wilcome Cotton(Hobbit) -I:20000:190:109:3:4 +I:20000:130 C:110:100:80 L:Human | Hobbit H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll | Easterling N:180:Inzilbeth(Dunadan) -I:25000:180:108:2:2 +I:25000:130 C:110:100:80 L:Human | High-Elf | Dunadan | Elf H:Dragon | Demon | Orc | Half-Ogre | Troll N:181:Gildor Inglorion(Dark-Elf) -I:10000:200:110:4:8 +I:10000:140 C:150:100:50 L:Dark-Elf | Elf | Easterling H:Dragon | Demon | Orc | Half-Ogre | Petty-Dwarf | Dwarf | Troll @@ -1226,25 +1226,25 @@ H:Dragon | Demon | Orc | Half-Ogre | Petty-Dwarf | Dwarf | Troll ### The Miners / Builders ### N:182:Gror(Dwarf) -I:20000:190:109:3:4 +I:20000:130 C:125:100:70 L:Half-Elf | Petty-Dwarf | Dwarf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll N:183:Saradoc Oldbuck(Hobbit) -I:30000:170:107:1:1 +I:30000:120 C:110:100:80 L:Human | High-Elf | Hobbit | Elf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll N:184:Gloredhel(Half-Elf) -I:10000:200:110:4:8 +I:10000:140 C:150:100:50 L:Human | Half-Elf | Dunadan | Elf | Easterling H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Troll N:185:Erellont(Wood-Elf) -I:25000:180:108:2:2 +I:25000:130 C:110:100:80 L:High-Elf | Dunadan | Hobbit | Elf H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Dwarf | Troll | Easterling @@ -1252,25 +1252,25 @@ H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Dwarf | Troll | Easterling ### The Hunters ### N:186:Kili(Dwarf) -I:20000:190:109:3:4 +I:20000:130 C:110:100:80 L:Petty-Dwarf | Dwarf H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Elf | Troll N:187:Ruby Bolger(Hobbit) -I:10000:200:110:4:8 +I:10000:140 C:150:100:50 L:Human | Half-Elf | High-Elf | Hobbit | Elf | Easterling H:Dragon | Demon | Beorning | Orc | Half-Ogre | Dwarf | Troll N:188:Goldwine(Human) -I:25000:180:108:2:2 +I:25000:130 C:110:100:80 L:Human | Half-Elf | RohanKnight | Dunadan | Elf | Easterling H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Troll N:189:Erestor(High-Elf) -I:30000:170:107:1:1 +I:30000:120 C:125:100:70 L:Human | Half-Elf | High-Elf | Dunadan | Elf H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Dwarf | Troll | Easterling @@ -1278,25 +1278,25 @@ H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Dwarf | Troll | East ### The Runecrafters ### N:190:Nori(Dwarf) -I:30000:170:107:1:1 +I:30000:120 C:150:100:50 L:Petty-Dwarf | Dwarf | Half-Elf | Dunadan H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Human | Troll | Eagle N:191:Camellia Sackville(Hobbit) -I:10000:200:110:4:8 +I:10000:140 C:110:100:80 L:Hobbit | Easterling H:Dragon | Demon | Orc | Troll N:192:Hador Lorindol(Dunadan) -I:25000:180:108:2:2 +I:25000:130 C:110:100:80 L:Human | Half-Elf | High-Elf | RohanKnight | Dunadan | Hobbit | Elf H:Dragon | Demon | Orc | Half-Ogre | Troll | Easterling N:193:Galathil(Dark-Elf) -I:20000:190:109:3:4 +I:20000:130 C:125:100:70 L:Human | Dark-Elf | Elf H:Dragon | Demon | Beorning | Orc | High-Elf | Half-Ogre | Petty-Dwarf | Troll @@ -1304,25 +1304,25 @@ H:Dragon | Demon | Beorning | Orc | High-Elf | Half-Ogre | Petty-Dwarf | Troll ### The Musicians ### N:194:Oin(Dwarf) -I:20000:190:109:3:4 +I:20000:130 C:125:100:70 L:Human | Petty-Dwarf | Dwarf H:Dragon | Demon | Orc | Elf | Half-Ogre | Troll | Easterling N:195:Robin Smallburrow(Hobbit) -I:10000:200:110:4:8 +I:10000:140 C:110:100:80 L:Human | Hobbit | Elf H:Dragon | Demon | Beorning | Orc | Troll | Easterling N:196:Hareth(Half-Elf) -I:30000:170:107:1:1 +I:30000:120 C:150:100:50 L:Human | RohanKnight | Dunadan H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll | Easterling N:197:Galdor(Wood-Elf) -I:25000:180:108:2:2 +I:25000:130 C:110:100:80 L:Half-Elf | High-Elf | Elf H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Petty-Dwarf | Dwarf | Troll | Easterling @@ -1330,25 +1330,25 @@ H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Petty-Dwarf | Dwarf | Troll | E ### The Precious Metalsmiths ### N:198:Gabil(Dwarf) -I:10000:150:120:4:8 +I:10000:130 C:115:100:70 L:Dwarf H:Dragon | Demon | Orc N:199:Isil(Human) -I:25000:300:150:2:2 +I:25000:200 C:125:100:80 L:Human | Easterling H:Dragon | Demon | Troll N:200:Grima(Half-Orc) -I:20000:250:140:3:4 +I:20000:170 C:150:100:50 L:Orc | Easterling H:Dragon | Demon | Elf N:201:Kosh(Half-Troll) -I:30000:200:130:1:1 +I:30000:150 C:125:100:60 L:Troll | Easterling H:Dragon | Demon | Human @@ -1356,25 +1356,25 @@ H:Dragon | Demon | Human ### The Mapmakers ### N:202:Pas(Dwarf) -I:20000:190:109:3:4 +I:20000:130 C:125:100:70 L:Half-Elf | Petty-Dwarf | Dwarf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll N:203:Isumbras Took(Hobbit) -I:30000:170:107:1:1 +I:30000:120 C:110:100:80 L:Human | High-Elf | Hobbit | Elf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll | Easterling N:204:Labadal(Half-Elf) -I:10000:200:110:4:8 +I:10000:140 C:150:100:50 L:Human | Half-Elf | Dunadan | Elf | Easterling H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Troll N:205:Guilin(Wood-Elf) -I:25000:180:108:2:2 +I:25000:130 C:110:100:80 L:High-Elf | Dunadan | Hobbit | Elf H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Dwarf | Troll @@ -1382,25 +1382,25 @@ H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Dwarf | Troll ### The Farmers ### N:206:Rili(Dwarf) -I:20000:190:109:3:4 +I:20000:130 C:110:100:80 L:Petty-Dwarf | Dwarf H:Dragon | Demon | Orc | Dark-Elf | Half-Ogre | Elf | Troll N:207:Wiseman Gamwich(Hobbit) -I:10000:200:110:4:8 +I:10000:140 C:150:100:50 L:Human | Half-Elf | High-Elf | Hobbit | Elf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Dwarf | Troll N:208:Lalaith(Human) -I:25000:180:108:2:2 +I:25000:130 C:110:100:80 L:Human | Half-Elf | RohanKnight | Dunadan | Elf H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Troll | Easterling N:209:Gwindor(High-Elf) -I:30000:170:107:1:1 +I:30000:120 C:125:100:70 L:Human | Half-Elf | High-Elf | Dunadan | Elf H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Dwarf | Troll @@ -1408,12 +1408,12 @@ H:Dragon | Demon | Beorning | Orc | Dark-Elf | Half-Ogre | Dwarf | Troll ### The Old Mage in Minas Anor ### N:210:Malbeth the Seer -I:20000:170:110:4:4 +I:20000:130 C:110:100:80 L:Human | RohanKnight | Dunadan | High-Elf H:Dragon | Demon | Beorning | Orc | Half-Ogre | Troll | Easterling ### For the Merchants' Guild ### N:211:Worm(Human) -I:30000:180:110:0:0 +I:30000:130 C:110:100:90 \ No newline at end of file diff --git a/src/defines.h b/src/defines.h index 37f0a8e9..d8a5d4f2 100644 --- a/src/defines.h +++ b/src/defines.h @@ -2679,7 +2679,6 @@ * Special Object Flags */ #define IDENT_SENSE 0x01 /* Item has been "sensed" */ -#define IDENT_FIXED 0x02 /* Item has been "haggled" */ #define IDENT_EMPTY 0x04 /* Item charges are known */ #define IDENT_KNOWN 0x08 /* Item abilities are known */ #define IDENT_STOREB 0x10 /* Item is storebought !!!! */ diff --git a/src/externs.h b/src/externs.h index 46675de7..655da661 100644 --- a/src/externs.h +++ b/src/externs.h @@ -239,7 +239,6 @@ extern bool_ stack_force_notes; extern bool_ stack_force_costs; extern bool_ view_reduce_lite; extern bool_ view_reduce_view; -extern bool_ auto_haggle; extern bool_ auto_scum; extern bool_ expand_look; extern bool_ expand_list; diff --git a/src/init1.c b/src/init1.c index 43d9690f..cc589bde 100644 --- a/src/init1.c +++ b/src/init1.c @@ -10250,18 +10250,15 @@ errr init_ow_info_txt(FILE *fp, char *buf) /* Process 'I' for "Info" (multiple lines line only) */ if (buf[0] == 'I') { - int cost, max_inf, min_inf, haggle, insult; + int cost, inf; /* Scan for the values */ - if (5 != sscanf(buf + 2, "%d:%d:%d:%d:%d", - &cost, &max_inf, &min_inf, &haggle, &insult)) return (1); + if (2 != sscanf(buf + 2, "%d:%d", + &cost, &inf)) return (1); /* Save the values */ ow_ptr->max_cost = cost; - ow_ptr->max_inflate = max_inf; - ow_ptr->min_inflate = min_inf; - ow_ptr->haggle_per = haggle; - ow_ptr->insult_max = insult; + ow_ptr->inflation = inf; /* Next... */ continue; diff --git a/src/loadsave.c b/src/loadsave.c index 48a982c6..1b142e59 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -1713,16 +1713,12 @@ static bool_ do_store(store_type *str, int flag) /* Some basic info */ do_s32b(&str->store_open, flag); - do_s16b(&str->insult_cur, flag); do_u16b(&str->owner, flag); if (flag == LS_SAVE) num = str->stock_num; /* Could be cleaner, done this way for benefit of the for loop later on */ do_byte(&num, flag); - do_s16b(&str->good_buy, flag); - do_s16b(&str->bad_buy, flag); - /* Last visit */ do_s32b(&str->last_visit, flag); diff --git a/src/store.c b/src/store.c index e1977920..ff5e89dc 100644 --- a/src/store.c +++ b/src/store.c @@ -43,59 +43,6 @@ static cptr comment_1[MAX_COMMENT_1] = "Taken!" }; -#define MAX_COMMENT_2A 2 - -static cptr comment_2a[MAX_COMMENT_2A] = -{ - "You try my patience. %s is final.", - "My patience grows thin. %s is final." -}; - -#define MAX_COMMENT_2B 12 - -static cptr comment_2b[MAX_COMMENT_2B] = -{ - "I can take no less than %s gold pieces.", - "I will accept no less than %s gold pieces.", - "Ha! No less than %s gold pieces.", - "You knave! No less than %s gold pieces.", - "That's a pittance! I want %s gold pieces.", - "That's an insult! I want %s gold pieces.", - "As if! How about %s gold pieces?", - "My gosh! How about %s gold pieces?", - "May the fleas of 1000 orcs molest you! Try %s gold pieces.", - "May your most favourite weapons rust! Try %s gold pieces.", - "May Morgoth find you tasty! Perhaps %s gold pieces?", - "Your mother was an Ogre! Perhaps %s gold pieces?" -}; - -#define MAX_COMMENT_3A 2 - -static cptr comment_3a[MAX_COMMENT_3A] = -{ - "You try my patience. %s is final.", - "My patience grows thin. %s is final." -}; - - -#define MAX_COMMENT_3B 12 - -static cptr comment_3b[MAX_COMMENT_3B] = -{ - "Perhaps %s gold pieces?", - "How about %s gold pieces?", - "I will pay no more than %s gold pieces.", - "I can afford no more than %s gold pieces.", - "Be reasonable. How about %s gold pieces?", - "I'll buy it as scrap for %s gold pieces.", - "That is too much! How about %s gold pieces?", - "That looks war surplus! Say %s gold pieces?", - "Never! %s is more like it.", - "That's an insult! %s is more like it.", - "%s gold pieces and be thankful for it!", - "%s gold pieces and not a copper more!" -}; - #define MAX_COMMENT_4A 4 static cptr comment_4a[MAX_COMMENT_4A] = @@ -116,31 +63,6 @@ static cptr comment_4b[MAX_COMMENT_4B] = "Out, out, out!" }; -#define MAX_COMMENT_5 8 - -static cptr comment_5[MAX_COMMENT_5] = -{ - "Try again.", - "Ridiculous!", - "You will have to do better than that!", - "Do you wish to do business or not?", - "You've got to be kidding!", - "You'd better be kidding!", - "You try my patience.", - "Hmmm, nice weather we're having." -}; - -#define MAX_COMMENT_6 4 - -static cptr comment_6[MAX_COMMENT_6] = -{ - "I must have heard you wrong.", - "I'm sorry, I missed that.", - "I'm sorry, what was that?", - "Sorry, what was that again?" -}; - - /* * Successful haggle. @@ -160,58 +82,6 @@ static void say_comment_1(void) } -/* - * Continue haggling (player is buying) - */ -static void say_comment_2(s32b value, int annoyed) -{ - char tmp_val[80]; - - /* Prepare a string to insert */ - strnfmt(tmp_val, 80, "%ld", (long)value); - - /* Final offer */ - if (annoyed > 0) - { - /* Formatted message */ - msg_format(comment_2a[rand_int(MAX_COMMENT_2A)], tmp_val); - } - - /* Normal offer */ - else - { - /* Formatted message */ - msg_format(comment_2b[rand_int(MAX_COMMENT_2B)], tmp_val); - } -} - - -/* - * Continue haggling (player is selling) - */ -static void say_comment_3(s32b value, int annoyed) -{ - char tmp_val[80]; - - /* Prepare a string to insert */ - strnfmt(tmp_val, 80, "%ld", (long)value); - - /* Final offer */ - if (annoyed > 0) - { - /* Formatted message */ - msg_format(comment_3a[rand_int(MAX_COMMENT_3A)], tmp_val); - } - - /* Normal offer */ - else - { - /* Formatted message */ - msg_format(comment_3b[rand_int(MAX_COMMENT_3B)], tmp_val); - } -} - - /* * Kick 'da bum out. -RAK- */ @@ -222,24 +92,6 @@ static void say_comment_4(void) } -/* - * You are insulting me - */ -static void say_comment_5(void) -{ - msg_print(comment_5[rand_int(MAX_COMMENT_5)]); -} - - -/* - * That makes no sense. - */ -static void say_comment_6(void) -{ - msg_print(comment_6[rand_int(5)]); -} - - /* * Messages for reacting to purchase prices. @@ -1564,62 +1416,6 @@ static void store_create(void) -/* - * Eliminate need to bargain if player has haggled well in the past - */ -static bool_ noneedtobargain(s32b minprice) -{ - s32b good = st_ptr->good_buy; - s32b bad = st_ptr->bad_buy; - - /* Cheap items are "boring" */ - if (minprice < 10L) return (TRUE); - - /* Perfect haggling */ - if (good == MAX_SHORT) return (TRUE); - - /* Reward good haggles, punish bad haggles, notice price */ - if (good > ((3 * bad) + (5 + (minprice / 50)))) return (TRUE); - - /* Return the flag */ - return (FALSE); -} - - -/* - * Update the bargain info - */ -static void updatebargain(s32b price, s32b minprice) -{ - /* Hack -- auto-haggle */ - if (auto_haggle) return; - - /* Cheap items are "boring" */ - if (minprice < 10L) return; - - /* Count the successful haggles */ - if (price == minprice) - { - /* Just count the good haggles */ - if (st_ptr->good_buy < MAX_SHORT) - { - st_ptr->good_buy++; - } - } - - /* Count the failed haggles */ - else - { - /* Just count the bad haggles */ - if (st_ptr->bad_buy < MAX_SHORT) - { - st_ptr->bad_buy++; - } - } -} - - - /* * Re-displays a single store entry */ @@ -1710,50 +1506,15 @@ static void display_entry(int pos) put_str(out_val, i + 6, 61); } - /* Display a "fixed" cost */ - if (o_ptr->ident & (IDENT_FIXED)) - { - /* Extract the "minimum" price */ - x = price_item(o_ptr, ot_ptr->min_inflate, FALSE); - - /* Can we buy one ? */ - if (x > p_ptr->au) color = TERM_L_DARK; - - /* Actually draw the price (not fixed) */ - strnfmt(out_val, 160, "%9ld F", (long)x); - c_put_str(color, out_val, i + 6, 68); - } - - /* Display a "taxed" cost */ - else if (auto_haggle) - { - /* Extract the "minimum" price */ - x = price_item(o_ptr, ot_ptr->min_inflate, FALSE); - - /* Hack -- Apply Sales Tax if needed */ - if (!noneedtobargain(x)) x += x / 10; - - /* Can we buy one ? */ - if (x > p_ptr->au) color = TERM_L_DARK; + /* Extract the "minimum" price */ + x = price_item(o_ptr, ot_ptr->inflation, FALSE); - /* Actually draw the price (with tax) */ - strnfmt(out_val, 160, "%9ld ", (long)x); - c_put_str(color, out_val, i + 6, 68); - } + /* Can we buy one ? */ + if (x > p_ptr->au) color = TERM_L_DARK; - /* Display a "haggle" cost */ - else - { - /* Extrect the "maximum" price */ - x = price_item(o_ptr, ot_ptr->max_inflate, FALSE); - - /* Can we buy one ? */ - if (x > p_ptr->au) color = TERM_L_DARK; - - /* Actually draw the price (not fixed) */ - strnfmt(out_val, 160, "%9ld ", (long)x); - c_put_str(color, out_val, i + 6, 68); - } + /* Actually draw the price */ + strnfmt(out_val, 160, "%9ld ", (long)x); + c_put_str(color, out_val, i + 6, 68); } } @@ -1946,220 +1707,57 @@ static int get_stock(int *com_val, cptr pmt, int i, int j) } -/* - * Increase the insult counter and get angry if too many -RAK- - */ -static int increase_insults(void) -{ - /* Increase insults */ - st_ptr->insult_cur++; - - /* Become insulted */ - if (st_ptr->insult_cur > ot_ptr->insult_max) - { - /* Complain */ - say_comment_4(); - - /* Reset insults */ - st_ptr->insult_cur = 0; - st_ptr->good_buy = 0; - st_ptr->bad_buy = 0; - - /* Open tomorrow */ - st_ptr->store_open = turn + 25000 + randint(25000); - - /* Closed */ - return (TRUE); - } - - /* Not closed */ - return (FALSE); -} - - -/* - * Decrease insults -RAK- - */ -static void decrease_insults(void) -{ - /* Decrease insults */ - if (st_ptr->insult_cur) st_ptr->insult_cur--; -} - - -/* - * Have insulted while haggling -RAK- - */ -static int haggle_insults(void) -{ - /* Increase insults */ - if (increase_insults()) return (TRUE); - - /* Display and flush insult */ - say_comment_5(); - - /* Still okay */ - return (FALSE); -} - - -/* - * Mega-Hack -- Enable "increments" - */ -static bool_ allow_inc = FALSE; - -/* - * Mega-Hack -- Last "increment" during haggling - */ -static s32b last_inc = 0L; - -/* - * Get a haggle +/** + * Prompt for a yes/no during selling/buying + * + * @return TRUE if 'yes' was selected, otherwise returns FALSE. */ -static int get_haggle(cptr pmt, s32b *poffer, s32b price, int final) +static bool_ prompt_yesno(cptr prompt) { - s32b i; - - cptr p; - - char buf[128]; - char out_val[160]; - - - /* Clear old increment if necessary */ - if (!allow_inc) last_inc = 0L; - - - /* Final offer */ - if (final) - { - strnfmt(buf, 128, "%s [accept] ", pmt); - } - - /* Old (negative) increment, and not final */ - else if (last_inc < 0) - { - strnfmt(buf, 128, "%s [-%ld] ", pmt, (long)(ABS(last_inc))); - } + cptr allowed = "yn\r\n"; + cptr yes = "y\r\n"; + char buf[128]; + bool_ ret; - /* Old (positive) increment, and not final */ - else if (last_inc > 0) - { - strnfmt(buf, 128, "%s [+%ld] ", pmt, (long)(ABS(last_inc))); - } - - /* Normal haggle */ - else - { - strnfmt(buf, 128, "%s ", pmt); - } + /* Build prompt */ + snprintf(buf, sizeof(buf), "%s [y/n/RET/ESC] ", prompt); - - /* Paranoia XXX XXX XXX */ + /* Prompt for it */ msg_print(NULL); + prt(buf, 0, 0); - - /* Ask until done */ + /* Get answer */ while (TRUE) { - /* Default */ - strcpy(out_val, ""); - - /* Ask the user for a response */ - if (!get_string(buf, out_val, 32)) return (FALSE); - - /* Skip leading spaces */ - for (p = out_val; *p == ' '; p++) /* loop */; + int key = inkey(); - /* Empty response */ - if (*p == '\0') - { - /* Accept current price */ - if (final) - { - *poffer = price; - last_inc = 0L; - break; - } - - /* Use previous increment */ - if (allow_inc && last_inc) - { - *poffer += last_inc; - break; - } + /* ESC means no. */ + if (key == ESCAPE) { + ret = FALSE; + break; } - /* Normal response */ - else - { - /* Extract a number */ - i = atol(p); - - /* Handle "incremental" number */ - if ((*p == '+' || *p == '-')) - { - /* Allow increments */ - if (allow_inc) - { - /* Use the given "increment" */ - *poffer += i; - last_inc = i; - break; - } - } - - /* Handle normal number */ - else - { - /* Use the given "number" */ - *poffer = i; - last_inc = 0L; - break; - } + /* Any other key must be in the allowed set to break the loop. */ + if ((strchr(allowed, key) != NULL) || quick_messages) { + /* Check for presence in the 'yes' set */ + ret = (strchr(yes, key) != NULL); + break; } - /* Warning */ - msg_print("Invalid response."); - msg_print(NULL); + /* Retry */ + bell(); } - /* Success */ - return (TRUE); -} - - -/* - * Receive an offer (from the player) - * - * Return TRUE if offer is NOT okay - */ -static bool_ receive_offer(cptr pmt, s32b *poffer, - s32b last_offer, int factor, - s32b price, int final) -{ - /* Haggle till done */ - while (TRUE) - { - /* Get a haggle (or cancel) */ - if (!get_haggle(pmt, poffer, price, final)) return (TRUE); - - /* Acceptable offer */ - if (((*poffer) * factor) >= (last_offer * factor)) break; - - /* Insult, and check for kicked out */ - if (haggle_insults()) return (TRUE); - - /* Reject offer (correctly) */ - (*poffer) = last_offer; - } + /* Erase the prompt */ + prt("", 0, 0); /* Success */ - return (FALSE); + return ret; } + /* * Haggling routine -RAK- * @@ -2167,176 +1765,42 @@ static bool_ receive_offer(cptr pmt, s32b *poffer, */ static bool_ purchase_haggle(object_type *o_ptr, s32b *price) { - s32b cur_ask, final_ask; - s32b last_offer, offer; - s32b x1, x2, x3; - s32b min_per, max_per; - int flag, loop_flag, noneed; - int annoyed = 0, final = FALSE; - + s32b cur_ask; bool_ cancel = FALSE; - - cptr pmt = "Asking"; - char out_val[160]; + char prompt[128]; + char o_name[80]; *price = 0; + /* Extract the price */ + cur_ask = price_item(o_ptr, ot_ptr->inflation, FALSE); - /* Extract the starting offer and the final offer */ - cur_ask = price_item(o_ptr, ot_ptr->max_inflate, FALSE); - final_ask = price_item(o_ptr, ot_ptr->min_inflate, FALSE); - - /* Determine if haggling is necessary */ - noneed = noneedtobargain(final_ask); - - /* No need to haggle */ - if (noneed || auto_haggle) - { - /* No need to haggle */ - if (noneed) - { - /* Message summary */ - msg_print("You eventually agree upon the price."); - msg_print(NULL); - } - - /* No haggle option */ - else - { - /* Message summary */ - msg_print("You quickly agree upon the price."); - msg_print(NULL); - - /* Apply Sales Tax */ - final_ask += final_ask / 10; - } - - /* Final price */ - cur_ask = final_ask; - - /* Go to final offer */ - pmt = "Final Offer"; - final = TRUE; - } - - - /* Haggle for the whole pile */ + /* Buy for the whole pile */ cur_ask *= o_ptr->number; - final_ask *= o_ptr->number; - - - /* Haggle parameters */ - min_per = ot_ptr->haggle_per; - max_per = min_per * 3; - /* Mega-Hack -- artificial "last offer" value */ - last_offer = object_value(o_ptr) * o_ptr->number; - last_offer = last_offer * (200 - (int)(ot_ptr->max_inflate)) / 100L; - if (last_offer <= 0) last_offer = 1; + /* Describe the object (fully) */ + object_desc_store(o_name, o_ptr, TRUE, 3); - /* No offer yet */ - offer = 0; - - /* No incremental haggling yet */ - allow_inc = FALSE; + /* Prompt */ + strnfmt(out_val, sizeof(out_val), "%s: " FMTs32b, "Price", cur_ask); + put_str(out_val, 1, 0); + strnfmt(prompt, sizeof(prompt), "Buy %s?", o_name); + cancel = !prompt_yesno(prompt); - /* Haggle until done */ - for (flag = FALSE; !flag; ) + /* Handle result */ + if (cancel) { - loop_flag = TRUE; - - while (!flag && loop_flag) - { - strnfmt(out_val, 160, "%s : %ld", pmt, (long)cur_ask); - put_str(out_val, 1, 0); - cancel = receive_offer("What do you offer? ", - &offer, last_offer, 1, cur_ask, final); - - if (cancel) - { - flag = TRUE; - } - else if (offer > cur_ask) - { - say_comment_6(); - offer = last_offer; - } - else if (offer == cur_ask) - { - flag = TRUE; - *price = offer; - } - else - { - loop_flag = FALSE; - } - } - - if (!flag) - { - x1 = 100 * (offer - last_offer) / (cur_ask - last_offer); - if (x1 < min_per) - { - if (haggle_insults()) - { - flag = TRUE; - cancel = TRUE; - } - } - else if (x1 > max_per) - { - x1 = x1 * 3 / 4; - if (x1 < max_per) x1 = max_per; - } - x2 = rand_range(x1 - 2, x1 + 2); - x3 = ((cur_ask - offer) * x2 / 100L) + 1; - /* don't let the price go up */ - if (x3 < 0) x3 = 0; - cur_ask -= x3; - - /* Too little */ - if (cur_ask < final_ask) - { - final = TRUE; - cur_ask = final_ask; - pmt = "Final Offer"; - annoyed++; - if (annoyed > 3) - { - (void)(increase_insults()); - cancel = TRUE; - flag = TRUE; - } - } - else if (offer >= cur_ask) - { - flag = TRUE; - *price = offer; - } - - if (!flag) - { - last_offer = offer; - allow_inc = TRUE; - prt("", 1, 0); - strnfmt(out_val, 160, "Your last offer: %ld", - (long)last_offer); - put_str(out_val, 1, 39); - say_comment_2(cur_ask, annoyed); - } - } + /* Cancel */ + return (TRUE); + } + else + { + *price = cur_ask; + /* Do not cancel */ + return (FALSE); } - - /* Cancel */ - if (cancel) return (TRUE); - - /* Update bargaining info */ - updatebargain(*price, final_ask); - - /* Do not cancel */ - return (FALSE); } @@ -2347,193 +1811,47 @@ static bool_ purchase_haggle(object_type *o_ptr, s32b *price) */ static bool_ sell_haggle(object_type *o_ptr, s32b *price) { - s32b purse, cur_ask, final_ask; - s32b last_offer = 0, offer = 0; - s32b x1, x2, x3; - s32b min_per, max_per; - - int flag, loop_flag, noneed; - int annoyed = 0, final = FALSE; - + s32b cur_ask; bool_ cancel = FALSE; - - cptr pmt = "Offer"; - char out_val[160]; + char prompt[128]; + char o_name[80]; *price = 0; + /* Extract price */ + cur_ask = price_item(o_ptr, ot_ptr->inflation, TRUE); - /* Obtain the starting offer and the final offer */ - cur_ask = price_item(o_ptr, ot_ptr->max_inflate, TRUE); - final_ask = price_item(o_ptr, ot_ptr->min_inflate, TRUE); - - /* Determine if haggling is necessary */ - noneed = noneedtobargain(final_ask); - - /* Get the owner's payout limit */ - purse = (s32b)(ot_ptr->max_cost); - - /* No need to haggle */ - if (noneed || auto_haggle || (final_ask >= purse)) - { - /* No reason to haggle */ - if (final_ask >= purse) - { - /* Message */ - msg_print("You instantly agree upon the price."); - msg_print(NULL); - - /* Offer full purse */ - final_ask = purse; - } - - /* No need to haggle */ - else if (noneed) - { - /* Message */ - msg_print("You eventually agree upon the price."); - msg_print(NULL); - } - - /* No haggle option */ - else - { - /* Message summary */ - msg_print("You quickly agree upon the price."); - msg_print(NULL); - - /* Apply Sales Tax */ - final_ask -= final_ask / 10; - } - - /* Final price */ - cur_ask = final_ask; - - /* Final offer */ - final = TRUE; - pmt = "Final Offer"; + /* Limit to shopkeeper's purse */ + if (cur_ask > ot_ptr->max_cost) { + cur_ask = ot_ptr->max_cost; } - /* Haggle for the whole pile */ + /* Sell the whole pile */ cur_ask *= o_ptr->number; - final_ask *= o_ptr->number; - - - /* XXX XXX XXX Display commands */ - - /* Haggling parameters */ - min_per = ot_ptr->haggle_per; - max_per = min_per * 3; - /* Mega-Hack -- artificial "last offer" value */ - last_offer = object_value(o_ptr) * o_ptr->number; - last_offer = last_offer * ot_ptr->max_inflate / 100L; + /* Describe the object (fully) */ + object_desc_store(o_name, o_ptr, TRUE, 3); - /* No offer yet */ - offer = 0; - - /* No incremental haggling yet */ - allow_inc = FALSE; + /* Prompt */ + strnfmt(out_val, sizeof(out_val), "%s: " FMTs32b, "Price", cur_ask); + put_str(out_val, 1, 0); + strnfmt(prompt, sizeof(prompt), "Sell %s?", o_name); + cancel = !prompt_yesno(prompt); - /* Haggle */ - for (flag = FALSE; !flag; ) + /* Handle result */ + if (cancel) { - while (1) - { - loop_flag = TRUE; - - strnfmt(out_val, 160, "%s : %ld", pmt, (long)cur_ask); - put_str(out_val, 1, 0); - cancel = receive_offer("What price do you ask? ", - &offer, last_offer, -1, cur_ask, final); - - if (cancel) - { - flag = TRUE; - } - else if (offer < cur_ask) - { - say_comment_6(); - /* rejected, reset offer for incremental haggling */ - offer = last_offer; - } - else if (offer == cur_ask) - { - flag = TRUE; - *price = offer; - } - else - { - loop_flag = FALSE; - } - - /* Stop */ - if (flag || !loop_flag) break; - } - - if (!flag) - { - x1 = 100 * (last_offer - offer) / (last_offer - cur_ask); - if (x1 < min_per) - { - if (haggle_insults()) - { - flag = TRUE; - cancel = TRUE; - } - } - else if (x1 > max_per) - { - x1 = x1 * 3 / 4; - if (x1 < max_per) x1 = max_per; - } - x2 = rand_range(x1 - 2, x1 + 2); - x3 = ((offer - cur_ask) * x2 / 100L) + 1; - /* don't let the price go down */ - if (x3 < 0) x3 = 0; - cur_ask += x3; - - if (cur_ask > final_ask) - { - cur_ask = final_ask; - final = TRUE; - pmt = "Final Offer"; - annoyed++; - if (annoyed > 3) - { - flag = TRUE; - (void)(increase_insults()); - } - } - else if (offer <= cur_ask) - { - flag = TRUE; - *price = offer; - } - - if (!flag) - { - last_offer = offer; - allow_inc = TRUE; - prt("", 1, 0); - strnfmt(out_val, 160, - "Your last bid %ld", (long)last_offer); - put_str(out_val, 1, 39); - say_comment_3(cur_ask, annoyed); - } - } + /* Cancel */ + return (TRUE); + } + else + { + *price = cur_ask; + /* Do not cancel */ + return (FALSE); } - - /* Cancel */ - if (cancel) return (TRUE); - - /* Update bargaining info */ - updatebargain(*price, final_ask); - - /* Do not cancel */ - return (FALSE); } /* @@ -2665,9 +1983,6 @@ void store_stole(void) j_ptr->found = OBJ_FOUND_STOLEN; j_ptr->found_aux1 = st_ptr->st_idx; - /* Hack -- clear the "fixed" flag from the item */ - j_ptr->ident &= ~(IDENT_FIXED); - /* "Hot" merchandise can't be sold back. It doesn't make sense to be able to sell back to a guy what you just stole from him. Also, without the discount one could fairly easily macro himself @@ -2765,11 +2080,6 @@ void store_stole(void) /* Complain */ say_comment_4(); - /* Reset insults */ - st_ptr->insult_cur = 0; - st_ptr->good_buy = 0; - st_ptr->bad_buy = 0; - /* Kicked out for a LONG time */ st_ptr->store_open = turn + 500000 + randint(500000); } @@ -2861,7 +2171,7 @@ void store_purchase(void) } /* Determine the "best" price (per item) */ - best = price_item(j_ptr, ot_ptr->min_inflate, FALSE); + best = price_item(j_ptr, ot_ptr->inflation, FALSE); /* Find out how many the player wants */ if (o_ptr->number > 1) @@ -2869,12 +2179,6 @@ void store_purchase(void) s32b q; - /* Hack -- note cost of "fixed" items */ - if ((cur_store_num != 7) && (o_ptr->ident & (IDENT_FIXED))) - { - msg_format("That costs %ld gold per item.", (long)(best)); - } - /* How many can we buy ? 99 if price is 0*/ if (cur_store_num == STORE_HOME) { @@ -2886,10 +2190,7 @@ void store_purchase(void) } else { - if (auto_haggle) - q = p_ptr->au / (best + (best / 10)); - else - q = p_ptr->au / best; + q = p_ptr->au / (best + (best / 10)); } if (o_ptr->number < q) q = o_ptr->number; @@ -2935,40 +2236,16 @@ void store_purchase(void) /* Attempt to buy it */ if (cur_store_num != 7) { - /* Fixed price, quick buy */ - if (o_ptr->ident & (IDENT_FIXED)) - { - /* Assume accept */ - choice = 0; - - /* Go directly to the "best" deal */ - price = (best * j_ptr->number); - } - - /* Haggle for it */ - else - { - /* Describe the object (fully) */ - object_desc_store(o_name, j_ptr, TRUE, 3); - - /* Message */ - msg_format("Buying %s (%c).", o_name, I2A(item)); - msg_print(NULL); + /* Haggle for a final price */ + choice = purchase_haggle(j_ptr, &price); - /* Haggle for a final price */ - choice = purchase_haggle(j_ptr, &price); - - /* Hack -- Got kicked out */ - if (st_ptr->store_open >= turn) return; - } + /* Hack -- Got kicked out */ + if (st_ptr->store_open >= turn) return; /* Player wants it */ if (choice == 0) { - /* Fix the item price (if "correctly" haggled) */ - if (price == (best * j_ptr->number)) o_ptr->ident |= (IDENT_FIXED); - /* Player can afford it */ if (p_ptr->au >= price) { @@ -2978,9 +2255,6 @@ void store_purchase(void) /* Make a sound */ sound(SOUND_BUY); - /* Be happy */ - decrease_insults(); - /* Spend the money */ p_ptr->au -= price; @@ -2994,9 +2268,6 @@ void store_purchase(void) j_ptr->found = OBJ_FOUND_STORE; j_ptr->found_aux1 = st_ptr->st_idx; - /* Hack -- clear the "fixed" flag from the item */ - j_ptr->ident &= ~(IDENT_FIXED); - /* Describe the transaction */ object_desc(o_name, j_ptr, TRUE, 3); @@ -3274,10 +2545,6 @@ void store_sell(void) /* Real store */ if ((cur_store_num != 7) && !museum) { - /* Describe the transaction */ - msg_format("Selling %s (%c).", o_name, index_to_label(item)); - msg_print(NULL); - /* Haggle for it */ choice = sell_haggle(q_ptr, &price); @@ -3293,9 +2560,6 @@ void store_sell(void) /* Make a sound */ sound(SOUND_SELL); - /* Be happy */ - decrease_insults(); - /* Get some money */ p_ptr->au += price; @@ -4188,10 +3452,7 @@ void store_shuffle(int which) /* Reset the owner data */ - st_ptr->insult_cur = 0; st_ptr->store_open = 0; - st_ptr->good_buy = 0; - st_ptr->bad_buy = 0; /* Hack -- discount all the items */ @@ -4206,9 +3467,6 @@ void store_shuffle(int which) if (!(o_ptr->art_name)) o_ptr->discount = 50; - /* Hack -- Items are no longer "fixed price" */ - o_ptr->ident &= ~(IDENT_FIXED); - /* Mega-Hack -- Note that the item is "on sale" */ o_ptr->note = quark_add("on sale"); } @@ -4238,9 +3496,6 @@ void store_maint(int town_num, int store_num) /* Activate the owner */ ot_ptr = &ow_info[st_ptr->owner]; - /* Store keeper forgives the player */ - st_ptr->insult_cur = 0; - /* Mega-Hack -- prune the black market */ if (st_info[st_ptr->st_idx].flags1 & SF1_ALL_ITEM) { @@ -4328,9 +3583,6 @@ void store_init(int town_num, int store_num) /* Initialize the store */ st_ptr->store_open = 0; - st_ptr->insult_cur = 0; - st_ptr->good_buy = 0; - st_ptr->bad_buy = 0; /* Nothing in stock */ st_ptr->stock_num = 0; diff --git a/src/tables.c b/src/tables.c index 1ebc52fd..2e01284a 100644 --- a/src/tables.c +++ b/src/tables.c @@ -1453,9 +1453,6 @@ option_type option_info[] = /*** Game-Play ***/ - { &auto_haggle, TRUE, 3, 0, - "auto_haggle", "Auto-haggle in stores" }, - { &auto_scum, TRUE, 3, 1, "auto_scum", "Auto-scum for good levels" }, diff --git a/src/types.h b/src/types.h index 538df721..bddb304b 100644 --- a/src/types.h +++ b/src/types.h @@ -1001,15 +1001,10 @@ struct owner_type s16b max_cost; /* Purse limit */ - byte max_inflate; /* Inflation (max) */ - byte min_inflate; /* Inflation (min) */ + s16b inflation; /* Inflation */ - byte haggle_per; /* Haggle unit */ - - byte insult_max; /* Insult limit */ - - u32b races[2][2]; /* Liked/hated races */ - u32b classes[2][2]; /* Liked/hated classes */ + u32b races[2][2]; /* Liked/hated races */ + u32b classes[2][2]; /* Liked/hated classes */ s16b costs[3]; /* Costs for liked people */ }; @@ -1029,11 +1024,6 @@ struct store_type u16b owner; /* Owner index */ - s16b insult_cur; /* Insult counter */ - - s16b good_buy; /* Number of "good" buys */ - s16b bad_buy; /* Number of "bad" buys */ - s32b store_open; /* Closed until this turn */ s32b last_visit; /* Last visited on this turn */ diff --git a/src/variable.c b/src/variable.c index 0cea5814..c77c3c7a 100644 --- a/src/variable.c +++ b/src/variable.c @@ -232,8 +232,6 @@ bool_ disturb_pets; /* Pets moving nearby disturb us */ /* Option Set 3 -- Game-Play */ -bool_ auto_haggle; /* Auto-haggle in stores */ - bool_ auto_scum; /* Auto-scum for good levels */ bool_ stack_allow_items; /* Allow weapons and armor to stack */ -- cgit v1.2.3 From 9e69576b7ebbda9bde3900b36fb081f819dc828a Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 16 Jul 2013 00:56:42 +0200 Subject: Add missing "m" C standard library --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 56713c7b..53923c57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -38,6 +38,9 @@ ENDIF() # Add definitions. ADD_DEFINITIONS(-DUSE_PRECISE_CMOVIE) +# Add standard math library +SET(LIBS ${LIBS} m) + # # JSON support # -- cgit v1.2.3 From f0fd8edb1fc36fd3dbe3b7df61da91b3daf9d4c6 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 16 Jul 2013 01:06:55 +0200 Subject: Remove auto_notes and take_notes options We always set them to TRUE now. --- lib/help/command.txt | 11 +++----- lib/help/option.txt | 8 ------ lib/mods/theme/help/command.txt | 11 +++----- lib/mods/theme/help/option.txt | 8 ------ src/birth.c | 5 +--- src/cmd4.c | 17 +++--------- src/dungeon.c | 2 +- src/externs.h | 1 - src/files.c | 17 ++++-------- src/spells2.c | 60 ++++++++++++++++++++--------------------- src/tables.c | 6 ----- src/variable.c | 3 --- src/xtra2.c | 10 +++---- 13 files changed, 51 insertions(+), 108 deletions(-) diff --git a/lib/help/command.txt b/lib/help/command.txt index 6616c252..2c2f1646 100644 --- a/lib/help/command.txt +++ b/lib/help/command.txt @@ -997,10 +997,8 @@ for a quantity will convert any "letters" into the maximal legal value. ~~~~~69 [[[[[GTake notes (:)] This command allows you to take notes, which will then appear in your - note file, if the birth-option "take_notes" was set (the default), or - in your message list (prefixed with "Note:"), if the option was not set. - The note file can be displayed through the "Display Current Knowledge" - command (~ or |). This command takes no time. + note file. The note file can be displayed through the "Display Current + Knowledge" command (~ or |). This command takes no time. ~~~~~123|Commands|Game status #####R--- Game Status Commands --- ~~~~~6 @@ -1054,9 +1052,8 @@ for a quantity will convert any "letters" into the maximal legal value. Display known dungeon towns Display notes - If the option "take_notes" is set shows you your notes file, where all - remarkable events are noted. You can add notes yourself by using the - "Take notes" command (:). + Shows you your notes file, where all remarkable events are noted. + You can add notes yourself by using the "Take notes" command (:). ~~~~~70 [[[[[GTime of the day (^T)] diff --git a/lib/help/option.txt b/lib/help/option.txt index 53121769..d3d9d53e 100644 --- a/lib/help/option.txt +++ b/lib/help/option.txt @@ -56,14 +56,6 @@ can also be viewed from the option menu while playing, but not changed then. but extremely deadly - imagine that Greater Checkerboard Vault with Lokkak on dungeon level 1! -#####GAllow notes to be written to a file [take_notes] - Allows any player-written notes (with the "|" command) to be written to - a file and kept (instead of being put in the message list). - -#####GAutomatically note important events [auto_notes] - Used in conjunction with the take_notes option, this option makes a note - each time you gain a level, kill a unique, find an artifact, etc. - #####GAllow use of some 'joke' monsters [joke_monsters] Allows monsters flagged as being some of DarkGod's jokes to be generated. diff --git a/lib/mods/theme/help/command.txt b/lib/mods/theme/help/command.txt index 6616c252..2c2f1646 100644 --- a/lib/mods/theme/help/command.txt +++ b/lib/mods/theme/help/command.txt @@ -997,10 +997,8 @@ for a quantity will convert any "letters" into the maximal legal value. ~~~~~69 [[[[[GTake notes (:)] This command allows you to take notes, which will then appear in your - note file, if the birth-option "take_notes" was set (the default), or - in your message list (prefixed with "Note:"), if the option was not set. - The note file can be displayed through the "Display Current Knowledge" - command (~ or |). This command takes no time. + note file. The note file can be displayed through the "Display Current + Knowledge" command (~ or |). This command takes no time. ~~~~~123|Commands|Game status #####R--- Game Status Commands --- ~~~~~6 @@ -1054,9 +1052,8 @@ for a quantity will convert any "letters" into the maximal legal value. Display known dungeon towns Display notes - If the option "take_notes" is set shows you your notes file, where all - remarkable events are noted. You can add notes yourself by using the - "Take notes" command (:). + Shows you your notes file, where all remarkable events are noted. + You can add notes yourself by using the "Take notes" command (:). ~~~~~70 [[[[[GTime of the day (^T)] diff --git a/lib/mods/theme/help/option.txt b/lib/mods/theme/help/option.txt index 46db5b0d..65352c6a 100644 --- a/lib/mods/theme/help/option.txt +++ b/lib/mods/theme/help/option.txt @@ -56,14 +56,6 @@ can also be viewed from the option menu while playing, but not changed then. but extremely deadly - imagine that Greater Checkerboard Vault with Lokkak on dungeon level 1! -#####GAllow notes to be written to a file [take_notes] - Allows any player-written notes (with the "|" command) to be written to - a file and kept (instead of being put in the message list). - -#####GAutomatically note important events [auto_notes] - Used in conjunction with the take_notes option, this option makes a note - each time you gain a level, kill a unique, find an artifact, etc. - #####GAllow use of some 'joke' monsters [joke_monsters] Allows monsters flagged as being some of DarkGod's jokes to be generated. diff --git a/src/birth.c b/src/birth.c index b219a1a0..9e7629c2 100644 --- a/src/birth.c +++ b/src/birth.c @@ -3466,10 +3466,7 @@ void player_birth(void) select_default_melee(); /* Make a note file if that option is set */ - if (take_notes) - { - add_note_type(NOTE_BIRTH); - } + add_note_type(NOTE_BIRTH); /* Note player birth in the message recall */ message_add(" ", TERM_L_BLUE); diff --git a/src/cmd4.c b/src/cmd4.c index e9db67d5..da606cc6 100644 --- a/src/cmd4.c +++ b/src/cmd4.c @@ -2788,16 +2788,8 @@ void do_cmd_note(void) /* Ignore empty notes */ if (!buf[0] || (buf[0] == ' ')) return; - if (take_notes) - { - /* Add note to file */ - add_note(buf, ' '); - } - else - { - /* Add note to message recall */ - msg_format("Note: %s", buf); - } + /* Add note to file */ + add_note(buf, ' '); } @@ -4270,7 +4262,7 @@ void do_cmd_knowledge(void) prt("(9) Display current fates", 12, 5); prt("(0) Display known traps", 13, 5); prt("(A) Display known dungeon towns", 14, 5); - if (take_notes) prt("(B) Display notes", 15, 5); + prt("(B) Display notes", 15, 5); /* Prompt */ prt("Command: ", 17, 0); @@ -4376,8 +4368,7 @@ void do_cmd_knowledge(void) case 'B': case 'b': { - if (take_notes) do_cmd_knowledge_notes(); - else bell(); + do_cmd_knowledge_notes(); break; } diff --git a/src/dungeon.c b/src/dungeon.c index de1a51fe..8df85977 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -5597,7 +5597,7 @@ void play_game(bool_ new_game) }; /* Hack - if note file exists, load it */ - if (!new_game && take_notes) + if (!new_game) { add_note_type(NOTE_ENTER_DUNGEON); } diff --git a/src/externs.h b/src/externs.h index 655da661..5fdd41e0 100644 --- a/src/externs.h +++ b/src/externs.h @@ -510,7 +510,6 @@ extern bool_ autoroll; extern bool_ point_based; extern bool_ maximize, preserve, special_lvls, ironman_rooms; extern bool_ inventory_no_move; -extern bool_ take_notes, auto_notes; extern bool_ *m_allow_special; extern bool_ *k_allow_special; extern bool_ *a_allow_special; diff --git a/src/files.c b/src/files.c index 7b1d10ce..cc209524 100644 --- a/src/files.c +++ b/src/files.c @@ -5533,11 +5533,8 @@ void close_game(void) /* Handle retirement */ if (total_winner) { - /* Write a note, if that option is on */ - if (take_notes) - { - add_note_type(NOTE_WINNER); - } + /* Make a note */ + add_note_type(NOTE_WINNER); kingly(); } @@ -5554,8 +5551,7 @@ void close_game(void) /* Show more info */ show_info(); - /* Write a note */ - if (take_notes) + /* Make a note */ { char long_day[30]; char buf[80]; @@ -5585,11 +5581,8 @@ void close_game(void) /* Save the game */ do_cmd_save_game(); - /* If note-taking enabled, write session end to notes file */ - if (take_notes) - { - add_note_type(NOTE_SAVE_GAME); - } + /* Make a note pf session end */ + add_note_type(NOTE_SAVE_GAME); /* Prompt for scores XXX XXX XXX */ prt("Press Return (or Escape).", 0, 40); diff --git a/src/spells2.c b/src/spells2.c index 19fb9f8f..8778e49f 100644 --- a/src/spells2.c +++ b/src/spells2.c @@ -4253,6 +4253,29 @@ static bool_ item_tester_hook_unknown(object_type *o_ptr) } + + +/* + * Make note of found artifacts. + */ +static void note_found_object(object_type *o_ptr) +{ + char note[150]; + char item_name[80]; + + if (artifact_p(o_ptr) || o_ptr->name1) + { + object_desc(item_name, o_ptr, FALSE, 0); + + /* Build note and write */ + sprintf(note, "Found The %s", item_name); + add_note(note, 'A'); + } +} + + + + /* * Identify an object in the inventory (or on the floor) * This routine does *not* automatically combine objects. @@ -4310,17 +4333,9 @@ bool_ ident_spell(void) o_name); } - /* If the item was an artifact, and if the auto-note is selected, write a message. */ - if (take_notes && auto_notes && (artifact_p(o_ptr) || o_ptr->name1)) - { - char note[150]; - char item_name[80]; - object_desc(item_name, o_ptr, FALSE, 0); + /* Make note of found artifacts */ + note_found_object(o_ptr); - /* Build note and write */ - sprintf(note, "Found The %s", item_name); - add_note(note, 'A'); - } /* Process the appropriate hooks */ identify_hooks(item, o_ptr, IDENT_NORMAL); @@ -4346,17 +4361,9 @@ bool_ ident_all(void) object_aware(o_ptr); object_known(o_ptr); - /* If the item was an artifact, and if the auto-note is selected, write a message. */ - if (take_notes && auto_notes && (artifact_p(o_ptr) || o_ptr->name1)) - { - char note[150]; - char item_name[80]; - object_desc(item_name, o_ptr, FALSE, 0); + /* Make note of found artifacts */ + note_found_object(o_ptr); - /* Build note and write */ - sprintf(note, "Found The %s", item_name); - add_note(note, 'A'); - } /* Process the appropriate hooks */ identify_hooks(-i, o_ptr, IDENT_NORMAL); } @@ -4428,17 +4435,8 @@ bool_ identify_fully(void) o_name); } - /* If the item was an artifact, and if the auto-note is selected, write a message. */ - if (take_notes && auto_notes && (artifact_p(o_ptr) || o_ptr->name1)) - { - char note[150]; - char item_name[80]; - object_desc(item_name, o_ptr, FALSE, 0); - - /* Build note and write */ - sprintf(note, "Found The %s", item_name); - add_note(note, 'A'); - } + /* Make note of found artifacts */ + note_found_object(o_ptr); /* Describe it fully */ object_out_desc(o_ptr, NULL, FALSE, TRUE); diff --git a/src/tables.c b/src/tables.c index 2e01284a..2087c64e 100644 --- a/src/tables.c +++ b/src/tables.c @@ -1598,12 +1598,6 @@ option_type option_info[] = { &ironman_rooms, FALSE, 6, 6, "ironman_rooms", "Always generate very unusual rooms" }, - { &take_notes, TRUE, 6, 7, - "take_notes", "Allow notes to be written to a file" }, - - { &auto_notes, TRUE, 6, 8, - "auto_notes", "Automatically note important events" }, - { &joke_monsters, FALSE, 6, 14, "joke_monsters", "Allow use of some 'joke' monsters" }, diff --git a/src/variable.c b/src/variable.c index c77c3c7a..08cabd39 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1272,9 +1272,6 @@ bool_ maximize, preserve, special_lvls, ironman_rooms; * selections */ bool_ inventory_no_move; -/* Notes patch */ -bool_ take_notes, auto_notes; - /* * Such an ugly hack ... */ diff --git a/src/xtra2.c b/src/xtra2.c index a0d500f2..f437c6d1 100644 --- a/src/xtra2.c +++ b/src/xtra2.c @@ -2089,11 +2089,7 @@ void check_experience(void) /* Gain this level's abilities */ apply_level_abilities(p_ptr->lev); - /* If auto-note taking enabled, write a note to the file. - * Only write this note when the level is gained for the first - * time. - */ - if (take_notes && auto_notes) + /* Note level gain */ { char note[80]; @@ -3437,8 +3433,8 @@ bool_ mon_take_hit(int m_idx, int dam, bool_ *fear, cptr note) } } - /* If the player kills a Unique, and the notes options are on, write a note */ - if ((r_ptr->flags1 & RF1_UNIQUE) && take_notes && auto_notes) + /* Make note of unique kills */ + if (r_ptr->flags1 & RF1_UNIQUE) { char note[80]; -- cgit v1.2.3 From a8a33056a073cb3f4213a1e845fe036dd3d53e0b Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 15 Jul 2013 23:00:30 +0200 Subject: Remove the stupid_monsters option It's always considered FALSE from now on. --- lib/help/option.txt | 11 ---- lib/mods/theme/help/option.txt | 11 ---- lib/mods/theme/user/all.prf | 3 - src/externs.h | 1 - src/files.c | 4 -- src/melee2.c | 131 ++++++++++++++++------------------------- src/tables.c | 3 - src/variable.c | 1 - 8 files changed, 50 insertions(+), 115 deletions(-) diff --git a/lib/help/option.txt b/lib/help/option.txt index d3d9d53e..c48d76a8 100644 --- a/lib/help/option.txt +++ b/lib/help/option.txt @@ -344,17 +344,6 @@ off at will during the course of the game. first having to observe such an attack upon you, and to use this information to choose the best attacks. -#####GMonsters behave stupidly [stupid_monsters] - ToME incorporates Keldon Jones' improved monster Artificial - Intelligence patch. While this patch most certainly makes monsters - behave more realistically, they will also be more deadly with the - improved AI. If you are a sissy, set this option to get the old, - really stupid monster AI. - Note that the new AI is a bit processing power expensive. If you have - an old computer (386sx) and ToME is running too slowly, you could - try turning stupid_monsters on. Or dumpster-dive for a Pentium so you can - run ToME. :-) - #####GAllow unusually small dungeon levels [small_levels] This option enables the creation of levels of varying sizes. Levels that are as small as one "screen" (80x24) are possible, and they can be diff --git a/lib/mods/theme/help/option.txt b/lib/mods/theme/help/option.txt index 65352c6a..6f538d91 100644 --- a/lib/mods/theme/help/option.txt +++ b/lib/mods/theme/help/option.txt @@ -344,17 +344,6 @@ off at will during the course of the game. first having to observe such an attack upon you, and to use this information to choose the best attacks. -#####GMonsters behave stupidly [stupid_monsters] - ToME incorporates Keldon Jones' improved monster Artificial - Intelligence patch. While this patch most certainly makes monsters - behave more realistically, they will also be more deadly with the - improved AI. If you are a sissy, set this option to get the old, - really stupid monster AI. - Note that the new AI is a bit processing power expensive. If you have - an old computer (386sx) and ToME is running too slowly, you could - try turning stupid_monsters on. Or dumpster-dive for a Pentium so you can - run ToME. :-) - #####GAllow unusually small dungeon levels [small_levels] This option enables the creation of levels of varying sizes. Levels that are as small as one "screen" (80x24) are possible, and they can be diff --git a/lib/mods/theme/user/all.prf b/lib/mods/theme/user/all.prf index e3da030f..fbb9de81 100644 --- a/lib/mods/theme/user/all.prf +++ b/lib/mods/theme/user/all.prf @@ -164,9 +164,6 @@ X:smart_learn # Option 'Monsters exploit players weaknesses' X:smart_cheat -# Option 'Monsters behave stupidly' -X:stupid_monsters - # Option 'Allow unusually small dungeon levels' Y:small_levels diff --git a/src/externs.h b/src/externs.h index 5fdd41e0..45734ac1 100644 --- a/src/externs.h +++ b/src/externs.h @@ -222,7 +222,6 @@ extern bool_ view_bright_lite; extern bool_ view_granite_lite; extern bool_ view_special_lite; extern bool_ plain_descriptions; -extern bool_ stupid_monsters; extern bool_ auto_destroy; extern bool_ wear_confirm; extern bool_ confirm_stairs; diff --git a/src/files.c b/src/files.c index cc209524..664c96d7 100644 --- a/src/files.c +++ b/src/files.c @@ -2675,9 +2675,6 @@ errr file_character(cptr name, bool_ full) if (PRACE_FLAGS(PR1_EXPERIMENTAL)) fprintf(fff, "\n You have done something experimental."); - if (stupid_monsters) - fprintf(fff, "\n Your opponents are behaving stupidly."); - { char desc[80]; cptr mimic; @@ -4286,7 +4283,6 @@ long total_points(void) if (p_ptr->preserve) mult -= 1; /* Penalize preserve, maximize modes */ if (p_ptr->maximize) mult -= 1; if (auto_scum) mult -= 4; - if (stupid_monsters) mult -= 10; if (small_levels) mult += ((always_small_level) ? 4 : 10); if (empty_levels) mult += 2; if (smart_learn) mult += 4; diff --git a/src/melee2.c b/src/melee2.c index 9dbdda86..4f63959d 100644 --- a/src/melee2.c +++ b/src/melee2.c @@ -2997,18 +2997,11 @@ bool_ make_attack_spell(int m_idx) /* Not allowed to cast spells */ if (!chance) return (FALSE); - if (stupid_monsters) - { - /* Only do spells occasionally */ - if (rand_int(100) >= chance) return (FALSE); - } - else - { - if (rand_int(100) >= chance) return (FALSE); + /* Only do spells occasionally */ + if (rand_int(100) >= chance) return (FALSE); - /* Sometimes forbid inate attacks (breaths) */ - if (rand_int(100) >= (chance * 2)) no_inate = TRUE; - } + /* Sometimes forbid inate attacks (breaths) */ + if (rand_int(100) >= (chance * 2)) no_inate = TRUE; /* XXX XXX XXX Handle "track_target" option (?) */ @@ -3031,11 +3024,8 @@ bool_ make_attack_spell(int m_idx) f5 = r_ptr->flags5; f6 = r_ptr->flags6; - if (!stupid_monsters) - { - /* Forbid inate attacks sometimes */ - if (no_inate) f4 = 0L; - } + /* Forbid inate attacks sometimes */ + if (no_inate) f4 = 0L; /* Hack -- allow "desperate" spells */ if ((r_ptr->flags2 & (RF2_SMART)) && @@ -3057,36 +3047,33 @@ bool_ make_attack_spell(int m_idx) /* No spells left */ if (!f4 && !f5 && !f6) return (FALSE); - if (!stupid_monsters) + /* Check for a clean bolt shot */ + if ((f4&(RF4_BOLT_MASK) || f5 & (RF5_BOLT_MASK) || + f6&(RF6_BOLT_MASK)) && + !(r_ptr->flags2 & (RF2_STUPID)) && + !clean_shot(m_ptr->fy, m_ptr->fx, y, x)) { - /* Check for a clean bolt shot */ - if ((f4&(RF4_BOLT_MASK) || f5 & (RF5_BOLT_MASK) || - f6&(RF6_BOLT_MASK)) && - !(r_ptr->flags2 & (RF2_STUPID)) && - !clean_shot(m_ptr->fy, m_ptr->fx, y, x)) - { - /* Remove spells that will only hurt friends */ - f4 &= ~(RF4_BOLT_MASK); - f5 &= ~(RF5_BOLT_MASK); - f6 &= ~(RF6_BOLT_MASK); - } - - /* Check for a possible summon */ - if ((f4 & (RF4_SUMMON_MASK) || f5 & (RF5_SUMMON_MASK) || - f6 & (RF6_SUMMON_MASK)) && - !(r_ptr->flags2 & (RF2_STUPID)) && - !(summon_possible(y, x))) - { - /* Remove summoning spells */ - f4 &= ~(RF4_SUMMON_MASK); - f5 &= ~(RF5_SUMMON_MASK); - f6 &= ~(RF6_SUMMON_MASK); - } + /* Remove spells that will only hurt friends */ + f4 &= ~(RF4_BOLT_MASK); + f5 &= ~(RF5_BOLT_MASK); + f6 &= ~(RF6_BOLT_MASK); + } - /* No spells left */ - if (!f4 && !f5 && !f6) return (FALSE); + /* Check for a possible summon */ + if ((f4 & (RF4_SUMMON_MASK) || f5 & (RF5_SUMMON_MASK) || + f6 & (RF6_SUMMON_MASK)) && + !(r_ptr->flags2 & (RF2_STUPID)) && + !(summon_possible(y, x))) + { + /* Remove summoning spells */ + f4 &= ~(RF4_SUMMON_MASK); + f5 &= ~(RF5_SUMMON_MASK); + f6 &= ~(RF6_SUMMON_MASK); } + /* No spells left */ + if (!f4 && !f5 && !f6) return (FALSE); + /* Extract the "inate" spells */ for (k = 0; k < 32; k++) { @@ -3117,32 +3104,25 @@ bool_ make_attack_spell(int m_idx) /* Get the monster name (or "it") */ monster_desc(m_name, m_ptr, 0x00); - if (stupid_monsters) - { - /* Choose a spell to cast */ - thrown_spell = spell[rand_int(num)]; - } - else - { - thrown_spell = choose_attack_spell(m_idx, spell, num); + /* Choose a spell to cast */ + thrown_spell = choose_attack_spell(m_idx, spell, num); - /* Abort if no spell was chosen */ - if (!thrown_spell) return (FALSE); + /* Abort if no spell was chosen */ + if (!thrown_spell) return (FALSE); - /* Calculate spell failure rate */ - failrate = 25 - (rlev + 3) / 4; + /* Calculate spell failure rate */ + failrate = 25 - (rlev + 3) / 4; - /* Hack -- Stupid monsters will never fail (for jellies and such) */ - if (r_ptr->flags2 & (RF2_STUPID)) failrate = 0; + /* Hack -- Stupid monsters will never fail (for jellies and such) */ + if (r_ptr->flags2 & (RF2_STUPID)) failrate = 0; - /* Check for spell failure (inate attacks never fail) */ - if ((thrown_spell >= 128) && (rand_int(100) < failrate)) - { - /* Message */ - msg_format("%^s tries to cast a spell, but fails.", m_name); + /* Check for spell failure (inate attacks never fail) */ + if ((thrown_spell >= 128) && (rand_int(100) < failrate)) + { + /* Message */ + msg_format("%^s tries to cast a spell, but fails.", m_name); - return (TRUE); - } + return (TRUE); } /* Can the player disrupt its puny attempts? */ @@ -5170,7 +5150,7 @@ static bool_ get_moves(int m_idx, int *mm) } } - if (!stupid_monsters && (is_friend(m_ptr) < 0)) + if (is_friend(m_ptr) < 0) { int tx = x2, ty = y2; @@ -5243,7 +5223,7 @@ static bool_ get_moves(int m_idx, int *mm) } /* Apply fear if possible and necessary */ - if ((stupid_monsters) || (is_friend(m_ptr) > 0)) + if (is_friend(m_ptr) > 0) { if (mon_will_run(m_idx)) { @@ -5275,11 +5255,8 @@ static bool_ get_moves(int m_idx, int *mm) } - if (!stupid_monsters) - { - /* Check for no move */ - if (!x && !y) return (FALSE); - } + /* Check for no move */ + if (!x && !y) return (FALSE); /* Extract the "absolute distances" */ ax = ABS(x); @@ -6523,16 +6500,8 @@ static void process_monster(int m_idx, bool_ is_frien) /* Normal movement */ else { - if (stupid_monsters) - { - /* Logical moves */ - get_moves(m_idx, mm); - } - else - { - /* Logical moves, may do nothing */ - if (!get_moves(m_idx, mm)) return; - } + /* Logical moves, may do nothing */ + if (!get_moves(m_idx, mm)) return; } /* Paranoia -- quest code could delete it */ @@ -7233,7 +7202,7 @@ static void process_monster(int m_idx, bool_ is_frien) /* If we haven't done anything, try casting a spell again */ - if (!do_turn && !do_move && !m_ptr->monfear && !stupid_monsters && + if (!do_turn && !do_move && !m_ptr->monfear && (is_friend(m_ptr) < 0)) { /* Cast spell */ diff --git a/src/tables.c b/src/tables.c index 2087c64e..dec13e70 100644 --- a/src/tables.c +++ b/src/tables.c @@ -1498,9 +1498,6 @@ option_type option_info[] = { &smart_cheat, FALSE, 3, 15, "smart_cheat", "Monsters exploit players weaknesses" }, - { &stupid_monsters, FALSE, 3, 16, - "stupid_monsters", "Monsters behave stupidly" }, - { &small_levels, TRUE, 3, 17, "small_levels", "Allow unusually small dungeon levels" }, diff --git a/src/variable.c b/src/variable.c index 08cabd39..ac67e308 100644 --- a/src/variable.c +++ b/src/variable.c @@ -223,7 +223,6 @@ bool_ empty_levels; /* Allow empty 'arena' levels */ bool_ always_small_level; /* Small levels */ bool_ player_symbols; /* Use varying symbols for the player char */ bool_ plain_descriptions; /* Plain object descriptions */ -bool_ stupid_monsters; /* Monsters use old AI */ bool_ auto_destroy; /* Known worthless items are destroyed without confirmation */ bool_ confirm_stairs; /* Prompt before staircases... */ bool_ wear_confirm; /* Confirm before putting on known cursed items */ -- cgit v1.2.3 From 97f71585f5dc7c7ea8636cf277404e41f76b0706 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 16 Jul 2013 07:51:08 +0200 Subject: Prevent friendly quest monsters in Theme --- src/birth.c | 10 ++++++++++ src/externs.h | 1 + src/modules.c | 6 +++--- src/tables.c | 4 ++++ src/types.h | 5 +++++ 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/birth.c b/src/birth.c index 9e7629c2..85939b8e 100644 --- a/src/birth.c +++ b/src/birth.c @@ -1375,6 +1375,16 @@ static void gen_random_quests(int n) /* Accept only monsters that are not good */ if (r_ptr->flags3 & RF3_GOOD) continue; + /* If module says a monster race is friendly, then skip */ + if (modules[game_module_idx].race_status != NULL) + { + s16b *status = (*modules[game_module_idx].race_status)(q_ptr->r_idx); + if ((status != NULL) && (*status >= 0)) + { + continue; + } + } + /* Assume no explosion attacks */ ok = TRUE; diff --git a/src/externs.h b/src/externs.h index 45734ac1..8fd9e5e5 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2302,6 +2302,7 @@ extern bool_ select_module(void); extern bool_ module_savefile_loadable(cptr savefile_mod); extern void tome_intro(); extern void theme_intro(); +extern s16b *theme_race_status(int r_idx); extern void init_hooks_module(); extern int find_module(cptr name); diff --git a/src/modules.c b/src/modules.c index 088dfbd7..26c3f271 100644 --- a/src/modules.c +++ b/src/modules.c @@ -770,7 +770,7 @@ static bool_ race_in_list(int r_idx, int race_idxs[]) /* * Monster racial alignment from Theme. */ -static s16b *compute_monster_status(int r_idx) +s16b *theme_race_status(int r_idx) { static s16b FRIEND_ = MSTATUS_FRIEND; static s16b *FRIEND = &FRIEND_; @@ -1107,7 +1107,7 @@ static bool_ theme_level_end_gen(void *data, void *in, void *out) { monster_type *m_ptr = &m_list[i]; int r_idx = m_ptr->r_idx; - s16b *status = compute_monster_status(r_idx); + s16b *status = theme_race_status(r_idx); if (status) { m_ptr->status = *status; @@ -1120,7 +1120,7 @@ static bool_ theme_level_end_gen(void *data, void *in, void *out) static bool_ theme_new_monster_end(void *data, void *in_, void *out) { hook_new_monster_end_in *in = (hook_new_monster_end_in *) in_; - s16b *status = compute_monster_status(in->m_ptr->r_idx); + s16b *status = theme_race_status(in->m_ptr->r_idx); if (status) { diff --git a/src/tables.c b/src/tables.c index dec13e70..1d5f1c49 100644 --- a/src/tables.c +++ b/src/tables.c @@ -4704,6 +4704,8 @@ module_type modules[MAX_MODULES] = { 6, 4, }, /* Intro function */ tome_intro, + /* Race status function: ToME requires no special handling */ + NULL }, { @@ -4724,6 +4726,8 @@ module_type modules[MAX_MODULES] = { 6, 5, }, /* Intro function */ theme_intro, + /* Race status function */ + theme_race_status } }; diff --git a/src/types.h b/src/types.h index bddb304b..d9cae3cf 100644 --- a/src/types.h +++ b/src/types.h @@ -2718,6 +2718,11 @@ struct module_type /* Function to show introduction to module */ void (*intro)(); + + /* Function to compute race status, i.e. whether monsters + are friendly/neutral towards the player. Returns NULL + to indicate that no override happens. */ + s16b *(*race_status)(int r_idx); }; /** -- cgit v1.2.3 From ed1d4f8d8ce99b213ded7d1b18572e71d2c3024f Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 16 Jul 2013 07:52:03 +0200 Subject: Sprinkle a little "static" around module-private functions --- src/modules.c | 2 +- src/q_rand.c | 23 ++++++++++++++--------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/modules.c b/src/modules.c index 26c3f271..8376e3fb 100644 --- a/src/modules.c +++ b/src/modules.c @@ -707,7 +707,7 @@ static bool_ orthanc_stair(void *data, void *in_, void *out_) /* * Movement from Theme */ -bool_ theme_push_past(void *data, void *in_, void *out_) +static bool_ theme_push_past(void *data, void *in_, void *out_) { hook_move_in *p = (hook_move_in *) in_; cave_type *c_ptr = &cave[p->y][p->x]; diff --git a/src/q_rand.c b/src/q_rand.c index 5a3b3ab2..0cc69a6d 100644 --- a/src/q_rand.c +++ b/src/q_rand.c @@ -17,7 +17,7 @@ bool_ is_randhero(int level) return result; } -void do_get_new_obj(int y, int x) +static void do_get_new_obj(int y, int x) { obj_theme theme; char *items[3]; @@ -94,7 +94,7 @@ void do_get_new_obj(int y, int x) } -void princess_death(s32b m_idx, s32b r_idx) +static void princess_death(s32b m_idx, s32b r_idx) { int r; @@ -136,7 +136,7 @@ void princess_death(s32b m_idx, s32b r_idx) } } -void hero_death(s32b m_idx, s32b r_idx) +static void hero_death(s32b m_idx, s32b r_idx) { random_quests[dun_level].done = TRUE; @@ -213,7 +213,7 @@ void hero_death(s32b m_idx, s32b r_idx) } } -bool_ quest_random_death_hook(char *fmt) +static bool_ quest_random_death_hook(char *fmt) { int r_idx; s32b m_idx; @@ -242,13 +242,15 @@ bool_ quest_random_death_hook(char *fmt) return (FALSE); } -bool_ quest_random_turn_hook(char *fmt) + +static bool_ quest_random_turn_hook(char *fmt) { quest[QUEST_RANDOM].data[0] = 0; quest[QUEST_RANDOM].data[1] = 0; return (FALSE); } -bool_ quest_random_feeling_hook(char *fmt) + +static bool_ quest_random_feeling_hook(char *fmt) { if (!(dungeon_flags1 & DF1_PRINCIPAL)) return (FALSE); if ((dun_level < 1) || (dun_level >= MAX_RANDOM_QUEST)) return (FALSE); @@ -266,7 +268,8 @@ bool_ quest_random_feeling_hook(char *fmt) cmsg_format(TERM_YELLOW, "You hear someone shouting: 'Leave me alone, stupid %s'", r_info[random_quests[dun_level].r_idx].name + r_name); return (FALSE); } -bool_ quest_random_gen_hero_hook(char *fmt) + +static bool_ quest_random_gen_hero_hook(char *fmt) { int i; @@ -296,7 +299,8 @@ bool_ quest_random_gen_hero_hook(char *fmt) return (FALSE); } -bool_ quest_random_gen_hook(char *fmt) + +static bool_ quest_random_gen_hook(char *fmt) { s32b x, y, bx0, by0; int xstart; @@ -378,7 +382,8 @@ bool_ quest_random_gen_hook(char *fmt) return (TRUE); } -bool_ quest_random_dump_hook(char *fmt) + +static bool_ quest_random_dump_hook(char *fmt) { static char *number[] = { "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" }; -- cgit v1.2.3 From 49fd23aa07484051adb9ad1ed13222e1767ec997 Mon Sep 17 00:00:00 2001 From: Elmo Todurov Date: Sun, 18 Aug 2013 22:28:31 +0300 Subject: Fixed autosqueltch class name matching --- src/squeltch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/squeltch.c b/src/squeltch.c index d79e1989..0c1e2902 100644 --- a/src/squeltch.c +++ b/src/squeltch.c @@ -885,7 +885,7 @@ static bool_ condition_eval(condition_type *c, object_type *o_ptr) sprintf(buf1, "%s", spp_ptr->title + c_name); strlower(buf1); - sprintf(buf2, "%s", c->race); + sprintf(buf2, "%s", c->klass); strlower(buf2); return streq(buf1, buf2); -- cgit v1.2.3 From cdca859c2968fe431818bbeb243f642c442e6043 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sat, 30 Jun 2012 20:49:19 +0200 Subject: C++: Remove bogus prototypes --- src/h-system.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/h-system.h b/src/h-system.h index c1b17e1f..1c021a61 100644 --- a/src/h-system.h +++ b/src/h-system.h @@ -99,15 +99,6 @@ # include #else # include -# ifndef strstr -extern char *strstr(); -# endif -# ifndef strchr -extern char *strchr(); -# endif -# ifndef strrchr -extern char *strrchr(); -# endif #endif #else @@ -118,10 +109,6 @@ extern char *strrchr(); -#if !defined(linux) && !defined(__MWERKS__) -extern long atol(); -#endif - #include -- cgit v1.2.3 From db7e4b8022220b10bbfc5c2ce675fa035ace307d Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 19 Jun 2012 19:32:29 +0200 Subject: C++: Add Boost dependency --- CMakeLists.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 53923c57..1f3115a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,16 @@ IF(JANSSON_FOUND) SET(LIBS ${LIBS} ${JANSSON_LIBRARIES}) ENDIF() +# +# BOOST +# +FIND_PACKAGE(Boost 1.48.0) + +IF(Boost_FOUND) + INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS}) + SET(LIBS ${LIBS} ${Boost_LIBRARIES}) +ENDIF() + # # X11 support (OPTIONAL) # -- cgit v1.2.3 From 1d65909b257cc84282da4a1192072615b716138c Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Thu, 21 Jun 2012 22:25:12 +0200 Subject: C++: Introduce types_fwd.h with forward declarations for types.h --- src/spell_type.h | 7 +--- src/types.h | 2 ++ src/types_fwd.h | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 6 deletions(-) create mode 100644 src/types_fwd.h diff --git a/src/spell_type.h b/src/spell_type.h index 32d6c7b6..bc3bdbec 100644 --- a/src/spell_type.h +++ b/src/spell_type.h @@ -4,17 +4,12 @@ #include "spell_type_fwd.h" #include "h-type.h" +#include "types_fwd.h" #ifdef __cplusplus extern "C" { #endif -/* - * Forward declarations - */ -struct device_allocation; -struct range_type; - /* * Casting type */ diff --git a/src/types.h b/src/types.h index d9cae3cf..2e871a40 100644 --- a/src/types.h +++ b/src/types.h @@ -1,5 +1,7 @@ /* File: types.h */ +#include "types_fwd.h" + /* Purpose: global type declarations */ /* diff --git a/src/types_fwd.h b/src/types_fwd.h new file mode 100644 index 00000000..581609e9 --- /dev/null +++ b/src/types_fwd.h @@ -0,0 +1,108 @@ +#ifndef H_8f0f494f_532d_4cfc_9578_bd4c6cff5953 +#define H_8f0f494f_532d_4cfc_9578_bd4c6cff5953 + +#ifdef __cplusplus +extern "C" { +#endif + +struct header; +struct obj_theme; +struct feature_type; +struct object_kind; +struct artifact_type; +struct ego_item_type; +struct randart_part_type; +struct randart_gen_type; +struct monster_blow; +struct monster_race; +struct monster_ego; +struct vault_type; +struct trap_type; +struct cave_type; +struct effect_type; +struct object_type; +struct monster_mind; +struct monster_type; +struct alloc_entry; +struct option_type; +struct owner_type; +struct store_type; +struct store_info_type; +struct store_action_type; +struct magic_type; +struct player_sex; +struct player_race; +struct player_race_mod; +struct player_spec; +struct player_class; +struct meta_class_type; +struct help_info; +struct player_type; +struct martial_arts; +struct magic_power; +struct border_type; +struct wilderness_type_info; +struct wilderness_map; +struct town_type; +struct alchemist_recipe; +struct artifact_select_flag; +struct deity_type; +struct tactic_info_type; +struct random_artifact; +struct activation; +struct music; +struct random_spell; +struct fate; +struct move_info_type; +struct rule_type; +struct dungeon_info_type; +struct inscription_info_type; +struct rune_spell; +struct flags_group; +struct power_type; +struct hook_move_in; +struct hook_get_in; +struct hook_end_turn_in; +struct hook_player_level_in; +struct hook_identify_in; +struct hook_give_in; +struct hook_eat_in; +struct hook_eat_out; +struct hook_stair_in; +struct hook_stair_out; +struct hook_new_monster_end_in; +struct quest_type; +struct random_quest; +struct monster_power; +struct tval_desc; +struct between_exit; +struct birther; +struct hooks_chain; +struct hist_type; +struct set_type; +struct cli_comm; +struct range_type; +struct dice_type; +struct device_allocation; +struct skill_type; +struct school_idx; +struct spell_type; +struct school_provider; +struct school_type; +struct spell_idx_list; +struct school_book_type; +struct gf_name_type; +struct timer_type; +struct list_type; +struct ability_type; +struct module_meta_type; +struct module_type; +struct corruption_type; +struct mimic_duration_type; +struct mimic_form_type; + +#ifdef __cplusplus +} +#endif + +#endif -- cgit v1.2.3 From b05113a48a2031282b5f4e65b97407a7bc8438c1 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 19 Jun 2012 20:03:42 +0200 Subject: C++: Move Automatizer to C++ --- .gitignore | 1 + src/CMakeLists.txt | 14 +- src/dungeon.c | 2 +- src/externs.h | 3 +- src/include/tome/enum_string_map.hpp | 58 + src/include/tome/squelch/automatizer.hpp | 159 + src/include/tome/squelch/automatizer_fwd.hpp | 10 + src/include/tome/squelch/condition.hpp | 635 ++++ src/include/tome/squelch/condition_fwd.hpp | 15 + src/include/tome/squelch/condition_metadata.hpp | 12 + .../tome/squelch/condition_metadata_fwd.hpp | 14 + src/include/tome/squelch/cursor.hpp | 50 + src/include/tome/squelch/cursor_fwd.hpp | 10 + src/include/tome/squelch/object_status.hpp | 28 + src/include/tome/squelch/object_status_fwd.hpp | 15 + src/include/tome/squelch/rule.hpp | 165 + src/include/tome/squelch/rule_fwd.hpp | 16 + src/include/tome/squelch/tree_printer.hpp | 49 + src/include/tome/squelch/tree_printer_fwd.hpp | 10 + src/init2.c | 7 +- src/squelch/CMakeLists.txt | 9 + src/squelch/automatizer.cc | 275 ++ src/squelch/condition.cc | 1068 ++++++ src/squelch/condition_metadata.cc | 492 +++ src/squelch/cursor.cc | 93 + src/squelch/object_status.cc | 149 + src/squelch/rule.cc | 325 ++ src/squelch/tree_printer.cc | 89 + src/squeltch.c | 3572 -------------------- src/squeltch.cc | 598 ++++ src/variable.c | 1 + 31 files changed, 4363 insertions(+), 3581 deletions(-) create mode 100644 src/include/tome/enum_string_map.hpp create mode 100644 src/include/tome/squelch/automatizer.hpp create mode 100644 src/include/tome/squelch/automatizer_fwd.hpp create mode 100644 src/include/tome/squelch/condition.hpp create mode 100644 src/include/tome/squelch/condition_fwd.hpp create mode 100644 src/include/tome/squelch/condition_metadata.hpp create mode 100644 src/include/tome/squelch/condition_metadata_fwd.hpp create mode 100644 src/include/tome/squelch/cursor.hpp create mode 100644 src/include/tome/squelch/cursor_fwd.hpp create mode 100644 src/include/tome/squelch/object_status.hpp create mode 100644 src/include/tome/squelch/object_status_fwd.hpp create mode 100644 src/include/tome/squelch/rule.hpp create mode 100644 src/include/tome/squelch/rule_fwd.hpp create mode 100644 src/include/tome/squelch/tree_printer.hpp create mode 100644 src/include/tome/squelch/tree_printer_fwd.hpp create mode 100644 src/squelch/CMakeLists.txt create mode 100644 src/squelch/automatizer.cc create mode 100644 src/squelch/condition.cc create mode 100644 src/squelch/condition_metadata.cc create mode 100644 src/squelch/cursor.cc create mode 100644 src/squelch/object_status.cc create mode 100644 src/squelch/rule.cc create mode 100644 src/squelch/tree_printer.cc delete mode 100644 src/squeltch.c create mode 100644 src/squeltch.cc diff --git a/.gitignore b/.gitignore index d7793155..f0ddf2c9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ *.o +lib*.a *.~* *.#* CMakeFiles diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 03c1771b..7f84a2d0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,10 +1,17 @@ +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) + +# Add subdirectories +ADD_SUBDIRECTORY (squelch) + +# Sources SET(SRCS main-gcu.c main-x11.c main-xaw.c main-sdl.c main-gtk2.c z-rand.c z-util.c z-form.c z-virt.c z-term.c variable.c tables.c plots.c util.c cave.c dungeon.c melee1.c melee2.c messages.c modules.c q_god.c - object1.c object2.c randart.c squeltch.c traps.c + object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c spells1.c spells2.c spells3.c spells4.c spells5.c spells6.c @@ -38,12 +45,9 @@ if(WIN32) endif(MINGW) endif(WIN32) - # tome executable -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) -INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/include) ADD_EXECUTABLE(tome ${EXECUTABLE_OPTIONS} ${SRCS}) -TARGET_LINK_LIBRARIES(tome ${LIBS}) +TARGET_LINK_LIBRARIES(tome squelch ${LIBS}) # Installation INSTALL(TARGETS tome diff --git a/src/dungeon.c b/src/dungeon.c index 8df85977..0b2551bf 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -5379,7 +5379,7 @@ static void load_all_pref_files(void) * rules on save and subsequent game load. */ /* sprintf(buf2, "%s.atm", player_name); */ /* path_build(buf, sizeof(buf), ANGBAND_DIR_USER, buf2); */ - /* automatizer_init(buf); */ + /* automatizer_load(buf); */ } /* diff --git a/src/externs.h b/src/externs.h index 8fd9e5e5..97e886a0 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2223,7 +2223,8 @@ extern void squeltch_grid(void); extern void do_cmd_automatizer(void); extern void automatizer_add_rule(object_type *o_ptr, bool_ destroy); extern bool_ automatizer_create; -extern void automatizer_init(cptr file_name); +extern void automatizer_init(); +extern void automatizer_load(cptr file_name); /* diff --git a/src/include/tome/enum_string_map.hpp b/src/include/tome/enum_string_map.hpp new file mode 100644 index 00000000..80ba7833 --- /dev/null +++ b/src/include/tome/enum_string_map.hpp @@ -0,0 +1,58 @@ +#ifndef H_ae6d0de3_c72e_4e67_9da2_975283fbd009 +#define H_ae6d0de3_c72e_4e67_9da2_975283fbd009 + +#include +#include +#include +#include + +/** + * Bidirectional mapping between enumerated values + * and strings. + */ +template +class EnumStringMap : boost::noncopyable { + +private: + typedef boost::bimap< E, std::string > bimap_type; + typedef typename bimap_type::value_type value_type; + + bimap_type bimap; + +public: + explicit EnumStringMap(std::initializer_list< std::pair > in) { + for (auto es : in) + { + bimap.insert(value_type(es.first, es.second)); + } + // Sanity check that there were no + // duplicate mappings. + assert(bimap.size() == in.size()); + } + + const char *stringify(E e) { + auto i = bimap.left.find(e); + assert(i != bimap.left.end() && "Missing mapping for enumerated value"); + return i->second.c_str(); + } + + E parse(const char *s) { + E e; + bool result = parse(s, &e); + assert(result && "Missing string->enum mapping"); + return e; + } + + bool parse(const char *s, E *e) { + auto i = bimap.right.find(s); + if (i == bimap.right.end()) + { + return false; + } + + *e = i->second; + return true; + } +}; + +#endif diff --git a/src/include/tome/squelch/automatizer.hpp b/src/include/tome/squelch/automatizer.hpp new file mode 100644 index 00000000..fae52a2b --- /dev/null +++ b/src/include/tome/squelch/automatizer.hpp @@ -0,0 +1,159 @@ +#ifndef H_53108fce_b059_4a82_99db_e1d4970ebd77 +#define H_53108fce_b059_4a82_99db_e1d4970ebd77 + +#include +#include +#include +#include + +#include "tome/squelch/rule_fwd.hpp" +#include "tome/squelch/cursor_fwd.hpp" +#include "tome/squelch/tree_printer_fwd.hpp" +#include "tome/squelch/condition_fwd.hpp" +#include "types_fwd.h" + +namespace squelch { + +/** + * Automatizer + */ +class Automatizer : public boost::noncopyable +{ +public: + Automatizer(std::shared_ptr tree_printer, + std::shared_ptr cursor) + : m_selected_rule(0) + , m_begin(0) + , m_tree_printer(tree_printer) + , m_cursor(cursor) + , m_rules() { + } + + /** + * Append a rule + */ + int append_rule(std::shared_ptr rule); + + /** + * Swap two rules + */ + void swap_rules(int i, int j); + + /** + * Apply all rules to the given object + */ + bool apply_rules(object_type *o_ptr, int item_idx) const; + + /** + * Build a JSON data structure to represent + * all the rules. + */ + std::shared_ptr to_json() const; + + /** + * Load rules from a JSON data structure. + */ + void load_json(json_t *json); + + /** + * Remove currently selected condition or rule. + */ + int remove_current_selection(); + + /** + * Reset view. + */ + void reset_view(); + + /** + * Show current rule + */ + void show_current() const; + + /** + * Scroll view up + */ + void scroll_up(); + + /** + * Scroll view down + */ + void scroll_down(); + + /** + * Scroll view left + */ + void scroll_left(); + + /** + * Scroll view right + */ + void scroll_right(); + + /** + * Move selection up + */ + void move_up(); + + /** + * Move selection down + */ + void move_down(); + + /** + * Move selection left + */ + void move_left(); + + /** + * Move selection right + */ + void move_right(); + + /** + * Add new condition to selected rule + */ + void add_new_condition(std::function ()> factory); + + /** + * Get rule names. The names are not stable across multiple + * calls to methods on this class. + */ + void get_rule_names(std::vector *names) const; + + /** + * Get current number of rules. + */ + int rules_count() const; + + /** + * Get the "beginning" rule. + */ + int rules_begin() const; + + /** + * Select a new rule. + */ + void select_rule(int selected_rule); + + /** + * Return selected rule index + */ + int selected_rule() const; + + /** + * Return selected rule + */ + std::shared_ptr current_rule(); + +private: + int m_selected_rule; + int m_begin; + std::shared_ptr m_tree_printer; + std::shared_ptr m_cursor; + std::vector < std::shared_ptr < Rule > > m_rules; +}; + +} // namespace + +#endif diff --git a/src/include/tome/squelch/automatizer_fwd.hpp b/src/include/tome/squelch/automatizer_fwd.hpp new file mode 100644 index 00000000..068f297a --- /dev/null +++ b/src/include/tome/squelch/automatizer_fwd.hpp @@ -0,0 +1,10 @@ +#ifndef H_cbf79126_fd24_4f80_8f2d_9dd69cb7010f +#define H_cbf79126_fd24_4f80_8f2d_9dd69cb7010f + +namespace squelch { + +class Automatizer; + +} // namespace + +#endif diff --git a/src/include/tome/squelch/condition.hpp b/src/include/tome/squelch/condition.hpp new file mode 100644 index 00000000..7aad5ff1 --- /dev/null +++ b/src/include/tome/squelch/condition.hpp @@ -0,0 +1,635 @@ +#ifndef H_e31ae6cc_eb8a_4909_ad6c_da485e4264a2 +#define H_e31ae6cc_eb8a_4909_ad6c_da485e4264a2 + +#include "tome/squelch/condition_fwd.hpp" + +#include +#include +#include +#include +#include + +#include "tome/squelch/cursor_fwd.hpp" +#include "tome/squelch/tree_printer_fwd.hpp" +#include "tome/squelch/object_status_fwd.hpp" +#include "tome/enum_string_map.hpp" +#include "types_fwd.h" + +namespace squelch { + +/** + * Types of matches used for conditions. + */ +enum class match_type { + AND , OR , NOT , NAME , CONTAIN , + INSCRIBED, DISCOUNT, SYMBOL , STATE , STATUS , + TVAL , SVAL , RACE , SUBRACE , CLASS , + LEVEL , SKILL , ABILITY, INVENTORY, EQUIPMENT }; + +/** + * Bidirectional map between enumeration values and strings. + */ +EnumStringMap &match_mapping(); + +/** + * Identification states an object can have: identified or not + * identified. + */ +enum class identification_state { + IDENTIFIED, NOT_IDENTIFIED }; + +/** + * Biredectional map between identification_state values and strings. + */ +EnumStringMap &identification_state_mapping(); + +/** + * Condition represents a tree of checks which + * can be applied to objects, the player, etc. + */ +class Condition : public boost::noncopyable +{ +public: + Condition(match_type match_) : match(match_) { + } + + void display(TreePrinter *, Cursor *) const; + + virtual bool is_match(object_type *) const = 0; + + virtual ~Condition() { + } + +public: + json_t *to_json() const; + + virtual void add_child(ConditionFactory const &factory) { + // Default is to not support children. + }; + + virtual void remove_child(Condition *c) { + // Nothing to do by default. + } + + virtual std::shared_ptr first_child() { + // No children. + return nullptr; + } + + virtual std::shared_ptr previous_child(Condition *) { + // Default no children, so no predecessor. + return nullptr; + } + + virtual std::shared_ptr next_child(Condition *) { + // Default no children, so no successor. + return nullptr; + } + + /** + * Parse condition from JSON + */ + static std::shared_ptr parse_condition(json_t *); + + /** + * Convert an (optional) condition to JSON. + */ + static json_t *optional_to_json(std::shared_ptr condition); + +protected: + virtual void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const = 0; + virtual void to_json(json_t *) const = 0; + + // What do we want to match? + match_type match; +}; + +/** + * Check for a specific TVAL + */ +class TvalCondition : public Condition +{ +public: + TvalCondition(uint8_t tval) + : Condition(match_type::TVAL) + , m_tval(tval) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(json_t *) const override; + +private: + uint8_t m_tval; +}; + +/** + * Check for object name + */ +class NameCondition : public Condition +{ +public: + NameCondition(std::string name) : + Condition(match_type::NAME), + m_name(name) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(json_t *) const override; + +private: + std::string m_name; +}; + +/** + * Check for infix of object name + */ +class ContainCondition : public Condition +{ +public: + ContainCondition(std::string contain) : + Condition(match_type::CONTAIN), + m_contain(contain) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(json_t *) const override; + +private: + std::string m_contain; +}; + +/** + * Check for specific SVAL + */ +class SvalCondition : public Condition +{ +public: + SvalCondition(uint8_t min, uint8_t max) + : Condition(match_type::SVAL) + , m_min(min) + , m_max(max) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(json_t *) const override; + +private: + uint8_t m_min; + uint8_t m_max; +}; + +/** + * Groupings of subconditions + */ +class GroupingCondition : public Condition +{ +public: + GroupingCondition(match_type match, + std::vector< std::shared_ptr > conditions = std::vector< std::shared_ptr >()) + : Condition(match) + , m_conditions(conditions) { + } + + virtual void add_condition(std::shared_ptr condition) { + if (condition) + { + m_conditions.push_back(condition); + } + } + + // Child manipulation + virtual void add_child(ConditionFactory const &factory) override; + virtual void remove_child(Condition *condition) override; + virtual std::shared_ptr first_child() override; + virtual std::shared_ptr previous_child(Condition *) override; + virtual std::shared_ptr next_child(Condition *current) override; + + // Parse a list of conditions from JSON property + static std::vector< std::shared_ptr > parse_conditions(json_t *); + +protected: + void to_json(json_t *) const override; + +protected: + std::vector< std::shared_ptr > m_conditions; +}; + +/** + * Conditions that are AND'ed together + */ +class AndCondition : public GroupingCondition +{ +public: + AndCondition() : GroupingCondition(match_type::AND) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; +}; + +/** + * Conditions that are OR'ed together + */ +class OrCondition : public GroupingCondition +{ +public: + OrCondition() : GroupingCondition(match_type::OR) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; +}; + +/** + * Check for object status + */ +class StatusCondition : public Condition +{ +public: + StatusCondition(status_type status) + : Condition(match_type::STATUS) + , m_status(status) { + } + +public: + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(json_t *) const override; + +private: + status_type m_status; +}; + +/** + * Check for player race + */ +class RaceCondition : public Condition +{ +public: + RaceCondition(std::string race) + : Condition(match_type::RACE) + , m_race(race) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(json_t *) const override; + +private: + std::string m_race; +}; + +/** + * Check player subrace + */ +class SubraceCondition : public Condition +{ +public: + SubraceCondition(std::string subrace) + : Condition(match_type::SUBRACE) + , m_subrace(subrace) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(json_t *) const override; + +private: + std::string m_subrace; +}; + +/** + * Check player class + */ +class ClassCondition : public Condition +{ +public: + ClassCondition(std::string klass) + : Condition(match_type::CLASS) + , m_class(klass) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(json_t *) const override; + +private: + std::string m_class; +}; + +/** + * Check object inscription + */ +class InscriptionCondition : public Condition +{ +public: + InscriptionCondition(std::string inscription) + : Condition(match_type::INSCRIBED) + , m_inscription(inscription) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(json_t *) const override; + +private: + std::string m_inscription; +}; + +/** + * Check object discount + */ +class DiscountCondition : public Condition +{ +public: + DiscountCondition(int min, int max) + : Condition(match_type::DISCOUNT) + , m_min(min) + , m_max(max) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(json_t *) const override; + +private: + int m_min; + int m_max; +}; + +/** + * Check player level + */ +class LevelCondition : public Condition +{ +public: + LevelCondition(int min, int max) + : Condition(match_type::LEVEL) + , m_min(min) + , m_max(max) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(json_t *) const override; + +private: + int m_min; + int m_max; +}; + +/** + * Check player's skill level + */ +class SkillCondition : public Condition +{ +public: + SkillCondition(uint16_t skill_idx, uint16_t min, uint16_t max) + : Condition(match_type::SKILL) + , m_skill_idx(skill_idx) + , m_min(min) + , m_max(max) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(json_t *) const override; + +private: + uint16_t m_skill_idx; + uint16_t m_min; + uint16_t m_max; +}; + +/** + * Check identification state + */ +class StateCondition : public Condition +{ +public: + StateCondition(identification_state state) + : Condition(match_type::STATE) + , m_state(state) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(json_t *) const override; + +private: + identification_state m_state; +}; + +/** + * Check object symbol + */ +class SymbolCondition : public Condition +{ +public: + SymbolCondition(char symbol) + : Condition(match_type::SYMBOL) + , m_symbol(symbol) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(json_t *) const override; + +private: + char m_symbol; +}; + +/** + * Check if player has a particular ability + */ +class AbilityCondition : public Condition +{ +public: + AbilityCondition(uint16_t ability_idx) + : Condition(match_type::ABILITY) + , m_ability_idx(ability_idx) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; + + void to_json(json_t *) const override; + +private: + uint16_t m_ability_idx; +}; + +/** + * Condition with a single subcondition + */ +class SingleSubconditionCondition : public Condition +{ +public: + SingleSubconditionCondition(match_type match, + std::shared_ptr subcondition) + : Condition(match) + , m_subcondition(subcondition) { + } + + virtual void add_child(std::function< std::shared_ptr () > const &factory) override; + + virtual void remove_child(Condition *c) override; + + virtual std::shared_ptr first_child() override; + +protected: + void to_json(json_t *) const override; + + static std::shared_ptr parse_single_subcondition( + json_t *condition_json); + +protected: + std::shared_ptr m_subcondition; +}; + +/** + * Condition which negates another condition + */ +class NotCondition : public SingleSubconditionCondition +{ +public: + NotCondition(std::shared_ptr subcondition = nullptr) + : SingleSubconditionCondition(match_type::NOT, subcondition) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; +}; + +/** + * Condition which checks if player inventory contains object(s) + * satisfying another condition. + */ +class InventoryCondition : public SingleSubconditionCondition +{ +public: + InventoryCondition(std::shared_ptr subcondition = nullptr) + : SingleSubconditionCondition(match_type::INVENTORY, subcondition) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; +}; + +/** + * Condition which checks if player equipment contains object(s) + * satisfying another condition. + */ +class EquipmentCondition : public SingleSubconditionCondition +{ +public: + EquipmentCondition(std::shared_ptr subcondition = nullptr) + : SingleSubconditionCondition(match_type::EQUIPMENT, subcondition) { + } + + bool is_match(object_type *) const override; + + static std::shared_ptr from_json(json_t *); + +protected: + void write_tree(TreePrinter *, Cursor *, uint8_t, uint8_t) const override; +}; + +} // namespace + +#endif diff --git a/src/include/tome/squelch/condition_fwd.hpp b/src/include/tome/squelch/condition_fwd.hpp new file mode 100644 index 00000000..744e7884 --- /dev/null +++ b/src/include/tome/squelch/condition_fwd.hpp @@ -0,0 +1,15 @@ +#ifndef H_1122f873_e83d_4af8_b6a8_a9e8db195473 +#define H_1122f873_e83d_4af8_b6a8_a9e8db195473 + +#include +#include + +namespace squelch { + +enum class match_type : int; +class Condition; +typedef std::function< std::shared_ptr () > ConditionFactory; + +} // namespace + +#endif diff --git a/src/include/tome/squelch/condition_metadata.hpp b/src/include/tome/squelch/condition_metadata.hpp new file mode 100644 index 00000000..fbb26bc3 --- /dev/null +++ b/src/include/tome/squelch/condition_metadata.hpp @@ -0,0 +1,12 @@ +#ifndef H_787198a1_aa3e_45c9_bc9f_fd7f490db78c +#define H_787198a1_aa3e_45c9_bc9f_fd7f490db78c + +#include "tome/squelch/condition_metadata_fwd.hpp" + +namespace squelch { + +std::shared_ptr new_condition_interactive(); + +} // namespace + +#endif diff --git a/src/include/tome/squelch/condition_metadata_fwd.hpp b/src/include/tome/squelch/condition_metadata_fwd.hpp new file mode 100644 index 00000000..1f57481b --- /dev/null +++ b/src/include/tome/squelch/condition_metadata_fwd.hpp @@ -0,0 +1,14 @@ +#ifndef H_7922f591_bdfd_491d_8561_b11225285fea +#define H_7922f591_bdfd_491d_8561_b11225285fea + +#include "tome/squelch/condition_fwd.hpp" + +#include + +namespace squelch { + +std::shared_ptr new_condition_interactive(); + +} // namespace + +#endif diff --git a/src/include/tome/squelch/cursor.hpp b/src/include/tome/squelch/cursor.hpp new file mode 100644 index 00000000..8dbfc6bf --- /dev/null +++ b/src/include/tome/squelch/cursor.hpp @@ -0,0 +1,50 @@ +#ifndef H_8a10111d_64a1_4af9_a85b_24ec8922d3fa +#define H_8a10111d_64a1_4af9_a85b_24ec8922d3fa + +#include +#include + +#include "tome/squelch/condition_fwd.hpp" + +namespace squelch { + +/** + * Cursor which maintains selected condition(s) + */ +class Cursor : public boost::noncopyable +{ +public: + bool is_selected(Condition const *condition) const; + + void push(Condition *condition) { + m_conditions.push_back(condition); + } + + Condition *pop(); + + Condition *current(); + + void clear() { + m_conditions.clear(); + } + + bool empty() const { + return m_conditions.empty(); + } + + std::size_t size() const { + return m_conditions.size(); + } + + void move_left(); + void move_right(); + void move_up(); + void move_down(); + +private: + std::deque m_conditions; +}; + +} // namespace + +#endif diff --git a/src/include/tome/squelch/cursor_fwd.hpp b/src/include/tome/squelch/cursor_fwd.hpp new file mode 100644 index 00000000..f07e9aa9 --- /dev/null +++ b/src/include/tome/squelch/cursor_fwd.hpp @@ -0,0 +1,10 @@ +#ifndef H_a4caa98a_1044_4192_b1af_27c2e8790cae +#define H_a4caa98a_1044_4192_b1af_27c2e8790cae + +namespace squelch { + +class Cursor; + +} // namespace + +#endif diff --git a/src/include/tome/squelch/object_status.hpp b/src/include/tome/squelch/object_status.hpp new file mode 100644 index 00000000..c52a35ea --- /dev/null +++ b/src/include/tome/squelch/object_status.hpp @@ -0,0 +1,28 @@ +#ifndef H_e3f9ebbe_ff9a_4687_a847_6101f094b483 +#define H_e3f9ebbe_ff9a_4687_a847_6101f094b483 + +#include "tome/enum_string_map.hpp" + +namespace squelch { + +/** + * Types of statuses for objects, e.g. "special" for artifacts and + * "average" for plain objects with no plusses. + */ +enum class status_type { + BAD , VERY_BAD, AVERAGE, GOOD, VERY_GOOD, + SPECIAL, TERRIBLE, NONE, CHEST_EMPTY, CHEST_DISARMED }; + +/** + * Bidirectional map between status_type values and strings. + */ +EnumStringMap &status_mapping(); + +/** + * Find the status of an object + */ +status_type object_status(object_type *o_ptr); + +} // namespace + +#endif diff --git a/src/include/tome/squelch/object_status_fwd.hpp b/src/include/tome/squelch/object_status_fwd.hpp new file mode 100644 index 00000000..10725050 --- /dev/null +++ b/src/include/tome/squelch/object_status_fwd.hpp @@ -0,0 +1,15 @@ +#ifndef H_3261a8ad_ee1c_4a2b_9d21_7c9955f09542 +#define H_3261a8ad_ee1c_4a2b_9d21_7c9955f09542 + +#include "types_fwd.h" +#include "tome/enum_string_map.hpp" + +namespace squelch { + +enum class status_type; +EnumStringMap &status_mapping(); +status_type object_status(object_type *o_ptr); + +} // namespace + +#endif diff --git a/src/include/tome/squelch/rule.hpp b/src/include/tome/squelch/rule.hpp new file mode 100644 index 00000000..d5cc5953 --- /dev/null +++ b/src/include/tome/squelch/rule.hpp @@ -0,0 +1,165 @@ +#ifndef H_c3dd858a_4663_44a0_8871_ff6c8148a613 +#define H_c3dd858a_4663_44a0_8871_ff6c8148a613 + +#include +#include + +#include "tome/squelch/condition_fwd.hpp" +#include "tome/squelch/cursor_fwd.hpp" +#include "tome/squelch/tree_printer_fwd.hpp" +#include "tome/enum_string_map.hpp" +#include "types_fwd.h" + +namespace squelch { + +/** + * Types of automatizer actions: destroy, pick up, and inscribe. + */ +enum class action_type { AUTO_DESTROY, AUTO_PICKUP, AUTO_INSCRIBE }; + +/** + * Bidirectional map between rule actions and strings. + */ +EnumStringMap &action_mapping(); + +/** + * Rules are the representation of "when condition X is true, do Y". + */ +class Rule : public boost::noncopyable +{ +public: + Rule(std::string name, + action_type action, + int module_idx, + std::shared_ptr condition) + : m_name(name) + , m_action(action) + , m_module_idx(module_idx) + , m_condition(condition) { + } + + /** + * Set the name of the rule + */ + void set_name(const char *new_name); + + /** + * Get the name of the rule + */ + const char *get_name() const; + + /** + * Get condition + */ + std::shared_ptr get_condition() const; + + /** + * Add new condition using a factory to instantiate the + * condition only if the rule permits adding a condition. + */ + void add_new_condition(Cursor *cursor, + ConditionFactory const &factory); + + /** + * Remove currently selected condition + */ + void delete_selected_condition(Cursor *cursor); + + /** + * Write out tree representing rule + */ + void write_tree(TreePrinter *p, Cursor *cursor) const; + + /** + * Apply rule to object + */ + bool apply_rule(object_type *o_ptr, int item_idx) const; + + /** + * Convert rule to JSON + */ + virtual json_t *to_json() const; + + /** + * Parse rule from JSON + */ + static std::shared_ptr parse_rule(json_t *); + +protected: + virtual bool do_apply_rule(object_type *, int) const = 0; + virtual void do_write_tree(TreePrinter *p) const = 0; + +protected: + // Rule name + std::string m_name; + // What does the rule do? + action_type m_action; + // Which module does this rule apply to? + int m_module_idx; + // Condition to check + std::shared_ptr m_condition; +}; + +/** + * Rule for destroying matching objects + */ +class DestroyRule : public Rule +{ +public: + DestroyRule(std::string name, + int module_idx, + std::shared_ptr condition) + : Rule(name, action_type::AUTO_DESTROY, module_idx, condition) { + } + +protected: + virtual bool do_apply_rule(object_type *o_ptr, int item_idx) const override; + virtual void do_write_tree(TreePrinter *p) const override; +}; + +/** + * Rule for picking up matching objects + */ +class PickUpRule : public Rule +{ +public: + + PickUpRule(std::string name, + int module_idx, + std::shared_ptr condition) + : Rule(name, action_type::AUTO_PICKUP, module_idx, condition) { + } + +protected: + virtual void do_write_tree(TreePrinter *p) const override; + virtual bool do_apply_rule(object_type *o_ptr, int item_idx) const override; +}; + +/** + * Rule for inscribing matching objects + */ +class InscribeRule : public Rule +{ +public: + InscribeRule(std::string name, + int module_idx, + std::shared_ptr condition, + std::string inscription) + : Rule(name, action_type::AUTO_INSCRIBE, module_idx, condition) + , m_inscription(inscription) { + } + + json_t *to_json() const override; + +protected: + virtual void do_write_tree(TreePrinter *p) const; + virtual bool do_apply_rule(object_type *o_ptr, int) const; + +private: + // Inscription to use for inscription rules. + std::string m_inscription; +}; + +} // namespace + +#endif diff --git a/src/include/tome/squelch/rule_fwd.hpp b/src/include/tome/squelch/rule_fwd.hpp new file mode 100644 index 00000000..091e77ef --- /dev/null +++ b/src/include/tome/squelch/rule_fwd.hpp @@ -0,0 +1,16 @@ +#ifndef H_4a8d2cfb_182c_4138_983d_606a9ac70784 +#define H_4a8d2cfb_182c_4138_983d_606a9ac70784 + +#include "tome/enum_string_map.hpp" + +namespace squelch { + +enum class action_type; + +EnumStringMap &action_mapping(); + +class Rule; + +} // namespace + +#endif diff --git a/src/include/tome/squelch/tree_printer.hpp b/src/include/tome/squelch/tree_printer.hpp new file mode 100644 index 00000000..e8ee1e56 --- /dev/null +++ b/src/include/tome/squelch/tree_printer.hpp @@ -0,0 +1,49 @@ +#ifndef H_3d6cc652_c674_4a84_911d_e8ec35cc992a +#define H_3d6cc652_c674_4a84_911d_e8ec35cc992a + +#include +#include + +namespace squelch { + +/** + * Printing trees. + */ +class TreePrinter : boost::noncopyable +{ +public: + TreePrinter(); + + void indent(); + + void dedent(); + + void reset(); + + void reset_scroll(); + + void scroll_up(); + + void scroll_down(); + + void scroll_left(); + + void scroll_right(); + + void write(uint8_t color, const char *line); + +private: + int m_indent; + int m_write_out_y; + int m_write_out_x; + int m_write_out_h; + int m_write_out_w; + int m_write_y; + int m_write_x; + int m_write_off_x; + int m_write_off_y; +}; + +} // namespace + +#endif diff --git a/src/include/tome/squelch/tree_printer_fwd.hpp b/src/include/tome/squelch/tree_printer_fwd.hpp new file mode 100644 index 00000000..d7d75453 --- /dev/null +++ b/src/include/tome/squelch/tree_printer_fwd.hpp @@ -0,0 +1,10 @@ +#ifndef H_4ce68eb3_c475_4fc4_8a70_0590c16dc684 +#define H_4ce68eb3_c475_4fc4_8a70_0590c16dc684 + +namespace squelch { + +class TreePrinter; + +} // namespace + +#endif diff --git a/src/init2.c b/src/init2.c index 9c1c2afa..a38cccee 100644 --- a/src/init2.c +++ b/src/init2.c @@ -2698,6 +2698,9 @@ void init_angband(void) /* Init random artifact names */ build_prob(artifact_names_list); + /* Initialize the automatizer */ + automatizer_init(); + /*** Load default user pref files ***/ /* Initialise feature info */ @@ -2727,9 +2730,9 @@ void init_angband(void) /* Process that file */ process_pref_file(buf); - /* Initialise the automatizer */ + /* Load automatizer rules */ path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "automat.atm"); - automatizer_init(buf); + automatizer_load(buf); /* Done */ note("[Initialisation complete]"); diff --git a/src/squelch/CMakeLists.txt b/src/squelch/CMakeLists.txt new file mode 100644 index 00000000..7b1495ba --- /dev/null +++ b/src/squelch/CMakeLists.txt @@ -0,0 +1,9 @@ +ADD_LIBRARY(squelch + automatizer.cc + condition.cc + condition_metadata.cc + cursor.cc + object_status.cc + rule.cc + tree_printer.cc +) diff --git a/src/squelch/automatizer.cc b/src/squelch/automatizer.cc new file mode 100644 index 00000000..0c0f571a --- /dev/null +++ b/src/squelch/automatizer.cc @@ -0,0 +1,275 @@ +#include "tome/squelch/automatizer_fwd.hpp" +#include "tome/squelch/automatizer.hpp" + +#include "tome/squelch/rule.hpp" +#include "tome/squelch/cursor.hpp" +#include "tome/squelch/tree_printer.hpp" +#include "angband.h" + +namespace squelch { + +/** + * Parse rules from JSON array + */ +static std::vector< std::shared_ptr < Rule > > parse_rules(json_t *rules_j) +{ + std::vector< std::shared_ptr < Rule > > rules; + + if (!json_is_array(rules_j)) + { + msg_format("Error 'rules' is not an array"); + return rules; + } + + for (size_t i = 0; i < json_array_size(rules_j); i++) + { + json_t *rule_j = json_array_get(rules_j, i); + auto rule = Rule::parse_rule(rule_j); + if (rule) + { + rules.push_back(rule); + } + } + + return rules; +} + +//---------------------------------------------------------- +// Automatizer +//---------------------------------------------------------- + +int Automatizer::append_rule(std::shared_ptr< Rule > rule) +{ + m_rules.push_back(rule); + return m_rules.size() - 1; +} + +void Automatizer::swap_rules(int i, int j) +{ + swap(m_rules.at(i), m_rules.at(j)); +} + +bool Automatizer::apply_rules(object_type *o_ptr, int item_idx) const +{ + for (auto rule : m_rules) + { + if (rule->apply_rule(o_ptr, item_idx)) + { + return true; + } + } + + return true; +} + +std::shared_ptr Automatizer::to_json() const +{ + auto rules_json = std::shared_ptr(json_array(), &json_decref); + + for (auto rule : m_rules) + { + json_array_append_new(rules_json.get(), rule->to_json()); + } + + return rules_json; +} + +void Automatizer::load_json(json_t *json) +{ + // Go through all the found rules + auto rules = parse_rules(json); + + // Load rule + for (auto rule : rules) + { + append_rule(rule); + } +} + +int Automatizer::remove_current_selection() +{ + assert(!m_rules.empty()); + + // Previously selected rule + int prev_selected_rule = m_selected_rule; + int new_selected_rule; + + // If the cursor is at the top level then we want to delete + // the rule itself + if (m_cursor->size() < 1) + { + // Remove rule + m_rules.erase(m_rules.begin() + m_selected_rule); + // Select previous + new_selected_rule = prev_selected_rule - 1; + } + else + { + // Delete the currently selected condition in rule. + m_rules.at(m_selected_rule)->delete_selected_condition(m_cursor.get()); + // Keep selection + new_selected_rule = m_selected_rule; + } + + // Do we need to adjust to select a different rule? + if ((prev_selected_rule != new_selected_rule) && (new_selected_rule >= 0)) + { + select_rule(new_selected_rule); + } + + // Return the selected rule. + return m_selected_rule; +} + +void Automatizer::reset_view() +{ + // Clear cursor + m_cursor->clear(); + + // Empty rules? + if (m_rules.empty()) + { + return; + } + + // Reset scroll position + m_tree_printer->reset_scroll(); + + // Put the top-level condition into cursor + auto condition = m_rules.at(m_selected_rule)->get_condition(); + if (condition) + { + m_cursor->push(condition.get()); + } +} + +void Automatizer::show_current() const +{ + if (m_rules.empty()) + { + return; + } + + m_tree_printer->reset(); + m_rules.at(m_selected_rule)->write_tree( + m_tree_printer.get(), + m_cursor.get()); +} + +void Automatizer::scroll_up() +{ + m_tree_printer->scroll_up(); +} + +void Automatizer::scroll_down() +{ + m_tree_printer->scroll_down(); +} + +void Automatizer::scroll_left() +{ + m_tree_printer->scroll_left(); +} + +void Automatizer::scroll_right() +{ + m_tree_printer->scroll_right(); +} + +void Automatizer::move_up() +{ + m_cursor->move_up(); +} + +void Automatizer::move_down() +{ + m_cursor->move_down(); +} + +void Automatizer::move_left() +{ + m_cursor->move_left(); +} + +void Automatizer::move_right() +{ + m_cursor->move_right(); +} + +void Automatizer::add_new_condition(std::function ()> factory) +{ + m_rules.at(m_selected_rule)->add_new_condition( + m_cursor.get(), + factory); +} + +void Automatizer::get_rule_names(std::vector *names) const +{ + names->resize(m_rules.size()); + for (size_t i = 0; i < m_rules.size(); i++) + { + (*names)[i] = m_rules.at(i)->get_name(); + } +} + +int Automatizer::rules_count() const +{ + return m_rules.size(); +} + +int Automatizer::rules_begin() const +{ + return m_begin; +} + +void Automatizer::select_rule(int selected_rule) +{ + m_selected_rule = selected_rule; + + int wid, hgt; + Term_get_size(&wid, &hgt); + + // Adjust selection to conform to bounds. + { + if (m_selected_rule < 0) + { + m_selected_rule = m_rules.size() - 1; + m_begin = m_selected_rule - hgt + 3; + if (m_begin < 0) + { + m_begin = 0; + } + } + + if (m_selected_rule < m_begin) + { + m_begin = m_selected_rule; + } + + if (m_selected_rule >= m_rules.size()) + { + m_selected_rule = 0; + m_begin = 0; + } + + if (m_selected_rule >= m_begin + hgt - 2) + { + m_begin++; + } + } + + // Adjust tree printer and cursor. + reset_view(); +} + +int Automatizer::selected_rule() const +{ + return m_selected_rule; +} + +std::shared_ptr Automatizer::current_rule() +{ + return m_rules.at(m_selected_rule); +} + +} // namespace diff --git a/src/squelch/condition.cc b/src/squelch/condition.cc new file mode 100644 index 00000000..2dc921ea --- /dev/null +++ b/src/squelch/condition.cc @@ -0,0 +1,1068 @@ +#include "tome/squelch/condition_fwd.hpp" +#include "tome/squelch/condition.hpp" + +#include + +#include "tome/squelch/cursor.hpp" +#include "tome/squelch/tree_printer.hpp" +#include "angband.h" +#include "quark.h" + +namespace squelch { + +EnumStringMap &match_mapping() +{ + // TODO: This is quite ugly and leads to valgrind complaints + static auto m = new EnumStringMap { + { match_type::AND, "and" }, + { match_type::OR, "or" }, + { match_type::NOT, "not" }, + { match_type::NAME, "name" }, + { match_type::CONTAIN, "contain" }, + { match_type::INSCRIBED, "inscribed" }, + { match_type::DISCOUNT, "discount" }, + { match_type::SYMBOL, "symbol" }, + { match_type::STATE, "state" }, + { match_type::STATUS, "status" }, + { match_type::TVAL, "tval" }, + { match_type::SVAL, "sval" }, + { match_type::RACE, "race" }, + { match_type::SUBRACE, "subrace" }, + { match_type::CLASS, "class" }, + { match_type::LEVEL, "level" }, + { match_type::SKILL, "skill" }, + { match_type::ABILITY, "ability" }, + { match_type::INVENTORY, "inventory" }, + { match_type::EQUIPMENT, "equipment" } }; + return *m; +}; + +EnumStringMap &identification_state_mapping() +{ + // TODO: This is quite ugly and leads to valgrind complaints + static auto m = new EnumStringMap { + { identification_state::IDENTIFIED, "identified" }, + { identification_state::NOT_IDENTIFIED, "not identified" } }; + return *m; +} + +json_t *Condition::to_json() const +{ + json_t *j = json_object(); + json_object_set_new(j, "type", + json_string(match_mapping().stringify(match))); + to_json(j); + return j; +} + +void Condition::display(TreePrinter *tree_printer, Cursor *cursor) const +{ + assert(tree_printer); + + // Use normal or "selected" colours? + uint8_t bcol = TERM_L_GREEN; + uint8_t ecol = TERM_GREEN; + if (cursor->is_selected(this)) + { + bcol = TERM_VIOLET; + ecol = TERM_VIOLET; + } + + // Indent a level and display tree. + tree_printer->indent(); + write_tree(tree_printer, cursor, ecol, bcol); + tree_printer->dedent(); +} + +std::shared_ptr Condition::parse_condition(json_t *condition_json) +{ + // Parsers for concrete types of conditions. + static std::map< match_type, + std::function< std::shared_ptr< Condition > ( json_t * ) > > parsers { + { match_type::AND, &AndCondition::from_json }, + { match_type::OR, &OrCondition::from_json }, + { match_type::NOT, &NotCondition::from_json }, + { match_type::INVENTORY, &InventoryCondition::from_json }, + { match_type::EQUIPMENT, &EquipmentCondition::from_json }, + { match_type::NAME, &NameCondition::from_json }, + { match_type::CONTAIN, &ContainCondition::from_json }, + { match_type::SYMBOL, &SymbolCondition::from_json }, + { match_type::INSCRIBED, &InscriptionCondition::from_json }, + { match_type::DISCOUNT, &DiscountCondition::from_json }, + { match_type::TVAL, &TvalCondition::from_json }, + { match_type::SVAL, &SvalCondition::from_json }, + { match_type::STATUS, &StatusCondition::from_json }, + { match_type::STATE, &StateCondition::from_json }, + { match_type::RACE, &RaceCondition::from_json }, + { match_type::SUBRACE, &SubraceCondition::from_json }, + { match_type::CLASS, &ClassCondition::from_json }, + { match_type::LEVEL, &LevelCondition::from_json }, + { match_type::SKILL, &SkillCondition::from_json }, + { match_type::ABILITY, &AbilityCondition::from_json } }; + + if ((condition_json == nullptr) || json_is_null(condition_json)) + { + return nullptr; + } + + cptr type_s = nullptr; + if (json_unpack(condition_json, + "{s:s}", + "type", &type_s) < 0) + { + msg_print("Missing/invalid 'type' in condition"); + return nullptr; + } + + match_type match; + if (!match_mapping().parse(type_s, &match)) + { + msg_format("Invalid 'type' in condition: %s", type_s); + return nullptr; + } + + // Look up parser and... parse + auto parser_i = parsers.find(match); + if (parser_i != parsers.end()) + { + return parser_i->second(condition_json); + } + + assert(false && "Missing parser"); + return nullptr; +} + +json_t *Condition::optional_to_json(std::shared_ptr condition) +{ + return condition + ? condition->to_json() + : json_null(); +} + +bool TvalCondition::is_match(object_type *o_ptr) const +{ + return (o_ptr->tval == m_tval); +} + +std::shared_ptr TvalCondition::from_json(json_t *j) +{ + int tval; + + if (json_unpack(j, "{s:i}", "tval", &tval) < 0) + { + msg_print("Missing/invalid 'tval' property"); + return nullptr; + } + + return std::make_shared(tval); +} + +void TvalCondition::to_json(json_t *j) const +{ + json_object_set_new(j, "tval", json_integer(m_tval)); +} + +void TvalCondition::write_tree(TreePrinter *p, Cursor *, uint8_t ecol, uint8_t bcol) const +{ + p->write(ecol, "Its "); + p->write(bcol, "tval"); + p->write(ecol, " is "); + p->write(ecol, "\""); + p->write(TERM_WHITE, format("%d", (int) m_tval)); + p->write(ecol, "\""); + p->write(TERM_WHITE, "\n"); +} + +bool NameCondition::is_match(object_type *o_ptr) const +{ + char buf1[128]; + object_desc(buf1, o_ptr, -1, 0); + + return boost::algorithm::iequals(m_name, buf1); +} + +std::shared_ptr NameCondition::from_json(json_t *j) +{ + cptr s = nullptr; + if (json_unpack(j, "{s:s}", "name", &s) < 0) + { + msg_print("Missing/invalid 'name' property"); + return nullptr; + } + return std::make_shared(s); +} + +void NameCondition::write_tree(TreePrinter *p, Cursor *cursor, uint8_t ecol, uint8_t bcol) const +{ + p->write(ecol, "Its "); + p->write(bcol, "name"); + p->write(ecol, " is \""); + p->write(TERM_WHITE, m_name.c_str()); + p->write(ecol, "\""); + p->write(TERM_WHITE, "\n"); +} + +void NameCondition::to_json(json_t *j) const +{ + json_object_set_new(j, "name", json_string(m_name.c_str())); +} + +bool ContainCondition::is_match(object_type *o_ptr) const +{ + char buf1[128]; + object_desc(buf1, o_ptr, -1, 0); + return boost::algorithm::icontains(buf1, m_contain); +} + +std::shared_ptr ContainCondition::from_json(json_t *j) +{ + cptr s = nullptr; + if (json_unpack(j, "{s:s}", "contain", &s) < 0) + { + msg_print("Missing/invalid 'contain' property"); + return nullptr; + } + return std::make_shared(s); +} + +void ContainCondition::write_tree(TreePrinter *p, Cursor *, uint8_t ecol, uint8_t bcol) const +{ + p->write(ecol, "Its "); + p->write(bcol, "name"); + p->write(ecol, " contains \""); + p->write(TERM_WHITE, m_contain.c_str()); + p->write(ecol, "\""); + p->write(TERM_WHITE, "\n"); +} + +void ContainCondition::to_json(json_t *j) const +{ + json_object_set_new(j, "contain", json_string(m_contain.c_str())); +} + +bool SvalCondition::is_match(object_type *o_ptr) const +{ + return (object_aware_p(o_ptr) && + (o_ptr->sval >= m_min) && + (o_ptr->sval <= m_max)); +} + +std::shared_ptr SvalCondition::from_json(json_t *j) +{ + int min, max; + + if (json_unpack(j, "{s:i,s:i}", + "min", &min, + "max", &max) < 0) + { + msg_print("Missing/invalid 'min'/'max' properties"); + return nullptr; + } + + return std::make_shared(min, max); +} + +void SvalCondition::write_tree(TreePrinter *p, Cursor *, uint8_t ecol, uint8_t bcol) const +{ + p->write(ecol, "Its "); + p->write(bcol, "sval"); + p->write(ecol, " is from "); + p->write(TERM_WHITE, format("%d", m_min)); + p->write(ecol, " to "); + p->write(TERM_WHITE, format("%d", m_max)); + p->write(TERM_WHITE, "\n"); +} + +void SvalCondition::to_json(json_t *j) const +{ + json_object_set_new(j, "min", json_integer(m_min)); + json_object_set_new(j, "max", json_integer(m_max)); +} + +void GroupingCondition::add_child(ConditionFactory const &factory) +{ + auto c_ptr = factory(); + if (c_ptr) + { + m_conditions.push_back(c_ptr); + } +} + +void GroupingCondition::remove_child(Condition *condition) +{ + std::remove_if( + std::begin(m_conditions), + std::end(m_conditions), + [&] (std::shared_ptr p) { + return p.get() == condition; + }); +} + +std::shared_ptr GroupingCondition::first_child() +{ + if (!m_conditions.empty()) + { + return m_conditions.front(); + } + return nullptr; +} + +std::shared_ptr GroupingCondition::previous_child(Condition *current) +{ + std::shared_ptr prev_condition; + + for (auto condition_p : m_conditions) + { + if (condition_p.get() == current) + { + // Do we have a previous child? + if (prev_condition) + { + return prev_condition; + } + else + { + // No predecessor + return nullptr; + } + } + // Keep track of predecessor + prev_condition = condition_p; + } + + return nullptr; +} + +std::shared_ptr GroupingCondition::next_child(Condition *current) +{ + for (auto it = m_conditions.begin(); + it != m_conditions.end(); + it++) + { + if (it->get() == current) + { + it++; + // Move to next child (if any) + if (it == m_conditions.end()) + { + // No successor + return nullptr; + } + + return *it; + } + } + + return nullptr; +} + +std::vector< std::shared_ptr > GroupingCondition::parse_conditions(json_t *j) +{ + json_t *conditions_j = json_object_get(j, "conditions"); + + if ((conditions_j == nullptr) || + (json_is_null(conditions_j))) + { + return std::vector< std::shared_ptr >(); + } + else if (!json_is_array(conditions_j)) + { + msg_print("'conditions' property has invalid type"); + return std::vector< std::shared_ptr >(); + } + else + { + std::vector< std::shared_ptr > subconditions; + for (size_t i = 0; i < json_array_size(conditions_j); i++) + { + json_t *subcondition_j = + json_array_get(conditions_j, i); + + std::shared_ptr subcondition = + parse_condition(subcondition_j); + + if (subcondition != nullptr) + { + subconditions.push_back(subcondition); + } + } + return subconditions; + } +} + +void GroupingCondition::to_json(json_t *j) const +{ + json_t *ja = json_array(); + for (auto condition_p : m_conditions) + { + json_array_append_new(ja, optional_to_json(condition_p)); + } + json_object_set_new(j, "conditions", ja); +} + +bool AndCondition::is_match(object_type *o_ptr) const +{ + for (auto condition_p : m_conditions) + { + if (!condition_p->is_match(o_ptr)) + { + return false; + } + } + return true; +} + +std::shared_ptr AndCondition::from_json(json_t *j) +{ + auto condition = std::make_shared(); + for (auto subcondition : parse_conditions(j)) + { + condition->add_condition(subcondition); + } + return condition; +} + +void AndCondition::write_tree(TreePrinter *p, Cursor *c, uint8_t ecol, uint8_t bcol) const +{ + p->write(ecol, "All of the following are true:"); + p->write(TERM_WHITE, "\n"); + + for (auto condition_p : m_conditions) + { + condition_p->display(p, c); + } +} + +bool OrCondition::is_match(object_type *o_ptr) const +{ + for (auto condition_p : m_conditions) + { + if (condition_p->is_match(o_ptr)) + { + return true; + } + } + return false; +} + +std::shared_ptr OrCondition::from_json(json_t *j) +{ + std::shared_ptr condition = + std::make_shared(); + + for (auto subcondition : parse_conditions(j)) + { + condition->add_condition(subcondition); + } + + return condition; +} + +void OrCondition::write_tree(TreePrinter *p, Cursor *c, uint8_t ecol, uint8_t bcol) const +{ + p->write(ecol, "At least one of the following are true:"); + p->write(TERM_WHITE, "\n"); + + for (auto condition_p : m_conditions) + { + condition_p->display(p, c); + } +} + +bool StatusCondition::is_match(object_type *o_ptr) const +{ + return m_status == object_status(o_ptr); +} + +std::shared_ptr StatusCondition::from_json(json_t *j) +{ + cptr s; + if (json_unpack(j, "{s:s}", "status", &s) < 0) + { + msg_print("Missing/invalid 'status' property"); + return nullptr; + } + + status_type status; + if (!status_mapping().parse(s, &status)) + { + msg_format("Invalid 'status' property: %s", s); + return nullptr; + } + + return std::make_shared(status); +} + +void StatusCondition::write_tree(TreePrinter *p, Cursor *, uint8_t ecol, uint8_t bcol) const +{ + p->write(ecol, "Its "); + p->write(bcol, "status"); + p->write(ecol, " is "); + p->write(ecol, "\""); + p->write(TERM_WHITE, status_mapping().stringify(m_status)); + p->write(ecol, "\""); + p->write(TERM_WHITE, "\n"); +} + +void StatusCondition::to_json(json_t *j) const +{ + json_object_set_new(j, "status", json_string(status_mapping().stringify(m_status))); +} + +bool RaceCondition::is_match(object_type *o_ptr) const +{ + return boost::algorithm::iequals(m_race, + rp_ptr->title + rp_name); +} + +std::shared_ptr RaceCondition::from_json(json_t *j) +{ + cptr s; + + if (json_unpack(j, "{s:s}", "race", &s) < 0) + { + msg_print("Missing/invalid 'race' property"); + return nullptr; + } + + return std::make_shared(s); +} + +void RaceCondition::write_tree(TreePrinter *p, Cursor *, uint8_t ecol, uint8_t bcol) const +{ + p->write(ecol, "Player "); + p->write(bcol, "race"); + p->write(ecol, " is "); + p->write(ecol, "\""); + p->write(TERM_WHITE, m_race.c_str()); + p->write(ecol, "\""); + p->write(TERM_WHITE, "\n"); +} + +void RaceCondition::to_json(json_t *j) const +{ + json_object_set_new(j, "race", json_string(m_race.c_str())); +} + +bool SubraceCondition::is_match(object_type *o_ptr) const +{ + return boost::algorithm::iequals(m_subrace, + rmp_ptr->title + rmp_name); +} + +std::shared_ptr SubraceCondition::from_json(json_t *j) +{ + cptr s; + + if (json_unpack(j, "{s:s}", "subrace", &s) < 0) + { + msg_print("Missing/invalid 'subrace' property"); + return nullptr; + } + + return std::make_shared(s); +} + +void SubraceCondition::write_tree(TreePrinter *p, Cursor *, uint8_t ecol, uint8_t bcol) const +{ + p->write(ecol, "Player "); + p->write(bcol, "subrace"); + p->write(ecol, " is "); + p->write(ecol, "\""); + p->write(TERM_WHITE, m_subrace.c_str()); + p->write(ecol, "\""); + p->write(TERM_WHITE, "\n"); +} + +void SubraceCondition::to_json(json_t *j) const +{ + json_object_set_new(j, "subrace", json_string(m_subrace.c_str())); +} + +bool ClassCondition::is_match(object_type *o_ptr) const +{ + return boost::algorithm::iequals(m_class, spp_ptr->title + c_name); +} + +std::shared_ptr ClassCondition::from_json(json_t *j) +{ + cptr s; + + if (json_unpack(j, "{s:s}", "class", &s) < 0) + { + msg_print("Missing/invalid 'class' property"); + return nullptr; + } + + return std::make_shared(s); +} + +void ClassCondition::write_tree(TreePrinter *p, Cursor *, uint8_t ecol, uint8_t bcol) const +{ + p->write(ecol, "Player "); + p->write(bcol, "class"); + p->write(ecol, " is "); + p->write(ecol, "\""); + p->write(TERM_WHITE, m_class.c_str()); + p->write(ecol, "\""); + p->write(TERM_WHITE, "\n"); +} + +void ClassCondition::to_json(json_t *j) const +{ + json_object_set_new(j, "class", json_string(m_class.c_str())); +} + +bool InscriptionCondition::is_match(object_type *o_ptr) const +{ + if (o_ptr->note == 0) + { + return false; + } + return boost::algorithm::icontains( + quark_str(o_ptr->note), + m_inscription); +} + +std::shared_ptr InscriptionCondition::from_json(json_t *j) +{ + cptr s = nullptr; + if (json_unpack(j, "{s:s}", "inscription", &s) < 0) + { + msg_print("Missing/invalid 'inscription' property"); + return nullptr; + } + return std::make_shared(s); +} + +void InscriptionCondition::write_tree(TreePrinter *p, Cursor *, uint8_t ecol, uint8_t bcol) const +{ + p->write(ecol, "It is "); + p->write(bcol, "inscribed"); + p->write(ecol, " with "); + p->write(ecol, "\""); + p->write(TERM_WHITE, m_inscription.c_str()); + p->write(ecol, "\""); + p->write(TERM_WHITE, "\n"); +} + +void InscriptionCondition::to_json(json_t *j) const +{ + json_object_set_new(j, "inscription", json_string(m_inscription.c_str())); +} + +bool DiscountCondition::is_match(object_type *o_ptr) const +{ + return (object_aware_p(o_ptr) && + (o_ptr->discount >= m_min) && + (o_ptr->discount <= m_max)); +} + +std::shared_ptr DiscountCondition::from_json(json_t *j) +{ + int min, max; + + if (json_unpack(j, "{s:i,s:i}", + "min", &min, + "max", &max) < 0) + { + msg_print("Missing/invalid 'min'/'max' properties"); + return nullptr; + } + + return std::make_shared(min, max); +} + +void DiscountCondition::write_tree(TreePrinter *p, Cursor *, uint8_t ecol, uint8_t bcol) const +{ + p->write(ecol, "Its "); + p->write(bcol, "discount"); + p->write(ecol, " is from "); + p->write(TERM_WHITE, format("%d", m_min)); + p->write(ecol, " to "); + p->write(TERM_WHITE, format("%d", m_max)); + p->write(TERM_WHITE, "\n"); +} + +void DiscountCondition::to_json(json_t *j) const +{ + json_object_set_new(j, "min", json_integer(m_min)); + json_object_set_new(j, "max", json_integer(m_max)); +} + +bool LevelCondition::is_match(object_type *) const +{ + return ((p_ptr->lev >= m_min) && + (p_ptr->lev <= m_max)); +} + +std::shared_ptr LevelCondition::from_json(json_t *j) +{ + int min, max; + if (json_unpack(j, "{s:i,s:i}", + "min", &min, + "max", &max) < 0) + { + msg_print("Missing/invalid 'min'/'max' properties"); + return nullptr; + } + + return std::make_shared(min, max); +} + +void LevelCondition::write_tree(TreePrinter *p, Cursor *, uint8_t ecol, uint8_t bcol) const +{ + p->write(ecol, "Your "); + p->write(bcol, "level"); + p->write(ecol, " is from "); + + p->write(TERM_WHITE, format("%d", m_min)); + p->write(ecol, " to "); + p->write(TERM_WHITE, format("%d", m_max)); + p->write(TERM_WHITE, "\n"); +} + +void LevelCondition::to_json(json_t *j) const +{ + json_object_set_new(j, "min", json_integer(m_min)); + json_object_set_new(j, "max", json_integer(m_max)); +} + +bool SkillCondition::is_match(object_type *) const +{ + uint16_t sk = get_skill(m_skill_idx); + return ((sk >= m_min) && + (sk <= m_max)); +} + +std::shared_ptr SkillCondition::from_json(json_t *j) +{ + cptr s; + int min, max; + if (json_unpack(j, "{s:i,s:i,s:s}", + "min", &min, + "max", &max, + "name", &s) < 0) + { + msg_print("Missing/invalid 'min'/'max'/'name' properties"); + return nullptr; + } + + uint16_t si = find_skill_i(s); + if (si < 0) + { + msg_print("Invalid 'name' property"); + return nullptr; + } + + return std::make_shared(si, min, max); +} + +void SkillCondition::write_tree(TreePrinter *p, Cursor *, uint8_t ecol, uint8_t bcol) const +{ + cptr skill_name = s_info[m_skill_idx].name + s_name; + + p->write(ecol, "Your skill in "); + p->write(bcol, skill_name); + p->write(ecol, " is from "); + p->write(TERM_WHITE, format("%d", (int) m_min)); + p->write(ecol, " to "); + p->write(TERM_WHITE, format("%d", (int) m_max)); + p->write(TERM_WHITE, "\n"); +} + +void SkillCondition::to_json(json_t *j) const +{ + json_object_set_new(j, "name", + json_string(s_info[m_skill_idx].name + s_name)); + json_object_set_new(j, "min", + json_integer(m_min)); + json_object_set_new(j, "max", + json_integer(m_max)); +} + +bool StateCondition::is_match(object_type *o_ptr) const +{ + switch (m_state) + { + case identification_state::IDENTIFIED: + return object_known_p(o_ptr); + case identification_state::NOT_IDENTIFIED: + return !object_known_p(o_ptr); + } + + assert(false); + return false; +} + +std::shared_ptr StateCondition::from_json(json_t *j) +{ + cptr s; + if (json_unpack(j, "{s:s}", "state", &s) < 0) + { + msg_print("Missing/invalid 'state' property"); + return nullptr; + } + + identification_state state; + if (!identification_state_mapping().parse(s, &state)) + { + msg_format("Invalid 'state' property: %s", s); + return nullptr; + } + + return std::make_shared(state); +} + +void StateCondition::write_tree(TreePrinter *p, Cursor *, uint8_t ecol, uint8_t bcol) const +{ + p->write(ecol, "Its "); + p->write(bcol, "state"); + p->write(ecol, " is "); + p->write(ecol, "\""); + p->write(TERM_WHITE, identification_state_mapping().stringify(m_state)); + p->write(ecol, "\""); + p->write(TERM_WHITE, "\n"); +} + +void StateCondition::to_json(json_t *j) const +{ + json_object_set_new(j, "state", + json_string(identification_state_mapping(). + stringify(m_state))); +} + +bool SymbolCondition::is_match(object_type *o_ptr) const +{ + object_kind *k_ptr = &k_info[o_ptr->k_idx]; + return k_ptr->d_char == m_symbol; +} + +std::shared_ptr SymbolCondition::from_json(json_t *j) +{ + cptr s_ = nullptr; + if (json_unpack(j, "{s:s}", "symbol", &s_) < 0) + { + msg_print("Missing/invalid 'symbol' property"); + return nullptr; + } + + std::string s(s_); + if (s.empty()) + { + msg_print("Invalid 'symbol' property: Too short"); + return nullptr; + } + if (s.size() > 1) + { + msg_print("Invalid 'symbol' property: Too long"); + return nullptr; + } + + return std::make_shared(s[0]); +} + +void SymbolCondition::write_tree(TreePrinter *p, Cursor *, uint8_t ecol, uint8_t bcol) const +{ + p->write(ecol, "Its "); + p->write(bcol, "symbol"); + p->write(ecol, " is "); + p->write(ecol, "\""); + p->write(TERM_WHITE, format("%c", m_symbol)); + p->write(ecol, "\""); + p->write(TERM_WHITE, "\n"); +} + +void SymbolCondition::to_json(json_t *j) const +{ + json_object_set_new(j, "symbol", + json_string(format("%c", m_symbol))); +} + +bool AbilityCondition::is_match(object_type *) const +{ + return has_ability(m_ability_idx); +} + +std::shared_ptr AbilityCondition::from_json(json_t *j) +{ + cptr a; + if (json_unpack(j, "{s:s}", "ability", &a) < 0) + { + msg_print("Missing/invalid 'ability' property"); + return nullptr; + } + + uint16_t ai = find_ability(a); + if (ai < 0) + { + msg_print("Invalid 'ability' property"); + return nullptr; + } + + return std::make_shared(ai); +} + +void AbilityCondition::write_tree(TreePrinter *p, Cursor *, uint8_t ecol, uint8_t bcol) const +{ + cptr ability_s = ab_info[m_ability_idx].name + ab_name; + + p->write(ecol, "You have the "); + p->write(bcol, ability_s); + p->write(ecol, " ability"); + p->write(TERM_WHITE, "\n"); +} + +void AbilityCondition::to_json(json_t *j) const +{ + cptr ability_s = ab_info[m_ability_idx].name + ab_name; + json_object_set_new(j, "ability", json_string(ability_s)); +} + +void SingleSubconditionCondition::add_child(std::function< std::shared_ptr () > const &factory) +{ + // If we already have a subcondition then we cannot + // add one. + if (!m_subcondition) + { + m_subcondition = factory(); + } +} + +void SingleSubconditionCondition::remove_child(Condition *c) +{ + if (m_subcondition.get() == c) { + m_subcondition.reset(); + } +} + +std::shared_ptr SingleSubconditionCondition::first_child() +{ + return m_subcondition; +} + +void SingleSubconditionCondition::to_json(json_t *j) const +{ + json_object_set_new(j, "condition", + optional_to_json(m_subcondition)); +} + +std::shared_ptr SingleSubconditionCondition::parse_single_subcondition(json_t *in_json) +{ + json_t *condition_j = + json_object_get(in_json, "condition"); + + if ((condition_j == nullptr) || + (json_is_null(condition_j))) + { + return nullptr; + } + else if (!json_is_object(condition_j)) + { + msg_format("Invalid 'condition' property"); + return nullptr; + } + else + { + return parse_condition(condition_j); + } +} + +bool NotCondition::is_match(object_type *o_ptr) const +{ + if (!m_subcondition) + { + return true; + } + + return !m_subcondition->is_match(o_ptr); +} + +std::shared_ptr NotCondition::from_json(json_t *j) +{ + return std::make_shared(parse_single_subcondition(j)); +} + +void NotCondition::write_tree(TreePrinter *p, Cursor *c, byte ecol, byte bcol) const +{ + p->write(ecol, "Negate the following:"); + p->write(TERM_WHITE, "\n"); + if (m_subcondition) + { + m_subcondition->display(p, c); + } +} + +bool InventoryCondition::is_match(object_type *) const +{ + if (!m_subcondition) + { + return false; + } + + for (int i = 0; i < INVEN_WIELD; i++) + { + if (m_subcondition->is_match(&p_ptr->inventory[i])) + { + return true; + } + } + + return false; +} + +std::shared_ptr InventoryCondition::from_json(json_t *j) +{ + return std::make_shared( + parse_single_subcondition(j)); +} + +void InventoryCondition::write_tree(TreePrinter *p, Cursor *c, byte ecol, byte bcol) const +{ + p->write(ecol, "Something in your "); + p->write(bcol, "inventory"); + p->write(ecol, " matches the following:"); + if (m_subcondition) + { + m_subcondition->display(p, c); + } + p->write(TERM_WHITE, "\n"); +} + +bool EquipmentCondition::is_match(object_type *) const +{ + if (!m_subcondition) + { + return false; + } + + for (int i = INVEN_WIELD; i < INVEN_TOTAL; i++) + { + if (m_subcondition->is_match(&p_ptr->inventory[i])) + { + return true; + } + } + + return false; +} + +std::shared_ptr EquipmentCondition::from_json(json_t *j) +{ + return std::make_shared( + parse_single_subcondition(j)); +} + +void EquipmentCondition::write_tree(TreePrinter *p, Cursor *c, byte ecol, byte bcol) const +{ + p->write(ecol, "Something in your "); + p->write(bcol, "equipment"); + p->write(ecol, " matches the following:"); + if (m_subcondition) + { + m_subcondition->display(p, c); + } + p->write(TERM_WHITE, "\n"); +} + +} // namespace diff --git a/src/squelch/condition_metadata.cc b/src/squelch/condition_metadata.cc new file mode 100644 index 00000000..766d44aa --- /dev/null +++ b/src/squelch/condition_metadata.cc @@ -0,0 +1,492 @@ +#include "tome/squelch/condition_metadata.hpp" +#include "tome/squelch/condition.hpp" + +#include + +#include "tome/squelch/object_status.hpp" +#include "angband.h" + +namespace squelch { + +static std::shared_ptr create_condition_name() +{ + cptr s = lua_input_box("Object name to match?", 79); + if (strlen(s) == 0) + { + return nullptr; + } + + return std::make_shared(s); +} + +static std::shared_ptr create_condition_contain() +{ + cptr s = lua_input_box("Word to find in object name?", 79); + if (strlen(s) == 0) + { + return nullptr; + } + + return std::make_shared(s); +} + +static std::shared_ptr create_condition_inscribed() +{ + cptr s = lua_input_box("Word to find in object inscription?", 79); + if (strlen(s) == 0) + { + return nullptr; + } + + return std::make_shared(s); +} + +static std::shared_ptr create_condition_discount() +{ + int min, max; + + { + cptr s = lua_input_box("Min discount?", 79); + if (sscanf(s, "%d", &min) < 1) + { + return nullptr; + } + } + + { + cptr s = lua_input_box("Max discount?", 79); + if (sscanf(s, "%d", &max) < 1) + { + return nullptr; + } + } + + return std::make_shared(min, max); +} + +static std::shared_ptr create_condition_symbol() +{ + char c; + cptr s = lua_input_box("Symbol to match?", 1); + if (sscanf(s, "%c", &c) < 1) + { + return nullptr; + } + + return std::make_shared(c); +} + +static std::shared_ptr create_condition_status() +{ + status_type status; + char c; + + c = lua_msg_box("[t]errible, [v]ery bad, [b]ad, " + "[a]verage, [G]ood, [V]ery good, [S]pecial?"); + + switch (c) + { + case 't': status = status_type::TERRIBLE; break; + case 'v': status = status_type::VERY_BAD; break; + case 'b': status = status_type::BAD; break; + case 'a': status = status_type::AVERAGE; break; + case 'G': status = status_type::GOOD; break; + case 'V': status = status_type::VERY_GOOD; break; + case 'S': status = status_type::SPECIAL; break; + default: return nullptr; + } + + return std::make_shared(status); +} + +static std::shared_ptr create_condition_state() +{ + char c = lua_msg_box("[i]dentified, [n]on identified?"); + + identification_state s; + switch (c) + { + case 'i': s = identification_state::IDENTIFIED; break; + case 'n': s = identification_state::NOT_IDENTIFIED; break; + default: return nullptr; + } + + return std::make_shared(s); +} + +static bool in_byte_range(int x) +{ + return (x >= 0) && (x < 256); +} + +static std::shared_ptr create_condition_tval() +{ + cptr s = lua_input_box("Tval to match?", 79); + int tval; + if (sscanf(s, "%d", &tval) < 1) + { + return nullptr; + } + + if (!in_byte_range(tval)) + { + return nullptr; + } + + return std::make_shared(tval); +} + +static std::shared_ptr create_condition_sval() +{ + int sval_min, sval_max; + + { + cptr s = lua_input_box("Min sval?", 79); + if ((sscanf(s, "%d", &sval_min) < 1) || + (!in_byte_range(sval_min))) + { + return nullptr; + } + } + + { + cptr s = lua_input_box("Max sval?", 79); + if ((sscanf(s, "%d", &sval_max) < 1) || + (!in_byte_range(sval_max))) + { + return nullptr; + } + } + + return std::make_shared(sval_min, sval_max); +} + +static std::shared_ptr create_condition_race() +{ + cptr s = lua_input_box("Player race to match?", 79); + if (strlen(s) == 0) + { + return nullptr; + } + + return std::make_shared(s); +} + +static std::shared_ptr create_condition_subrace() +{ + cptr s = lua_input_box("Player subrace to match?", 79); + if (strlen(s) == 0) + { + return nullptr; + } + + return std::make_shared(s); +} + +static std::shared_ptr create_condition_class() +{ + cptr s = lua_input_box("Player class to match?", 79); + if (strlen(s) == 0) + { + return nullptr; + } + + return std::make_shared(s); +} + +static std::shared_ptr create_condition_level() +{ + int min, max; + + { + cptr s = lua_input_box("Min player level?", 79); + if (sscanf(s, "%d", &min) < 1) + { + return nullptr; + } + } + + { + cptr s = lua_input_box("Max player level?", 79); + if (sscanf(s, "%d", &max) < 1) + { + return nullptr; + } + } + + return std::make_shared(min, max); +} + +static std::shared_ptr create_condition_skill() +{ + int min, max; + + { + cptr s = lua_input_box("Min skill level?", 79); + if (sscanf(s, "%d", &min) < 1) + { + return nullptr; + } + } + + { + cptr s = lua_input_box("Max skill level?", 79); + if (sscanf(s, "%d", &max) < 1) + { + return nullptr; + } + } + + s16b skill_idx; + { + cptr s = lua_input_box("Skill name?", 79); + if (strlen(s) == 0) + { + return nullptr; + } + + skill_idx = find_skill_i(s); + if (skill_idx < 0) + { + return nullptr; + } + } + + return std::make_shared(skill_idx, min, max); +} + +static std::shared_ptr create_condition_ability() +{ + cptr s = lua_input_box("Ability name?", 79); + if (strlen(s) == 0) + { + return nullptr; + } + + s16b ai = find_ability(s); + if (ai < 0) + { + return nullptr; + } + + return std::make_shared(ai); +} + +static void display_desc(match_type match_type_) +{ + int i = 0; + auto line = [&i] (const char *s) { + c_prt(TERM_WHITE, s, i + 1, 17); + i++; + }; + + switch (match_type_) + { + case match_type::AND: + line("Check is true if all rules within it are true"); + break; + + case match_type::OR: + line("Check is true if at least one rule within it is true"); + break; + + case match_type::NOT: + line("Invert the result of its child rule"); + break; + + case match_type::NAME: + line("Check is true if object name matches name"); + break; + + case match_type::CONTAIN: + line("Check is true if object name contains word"); + break; + + case match_type::INSCRIBED: + line("Check is true if object inscription contains word"); + break; + + case match_type::DISCOUNT: + line("Check is true if object discount is between two values"); + break; + + case match_type::SYMBOL: + line("Check is true if object symbol is ok"); + break; + + case match_type::STATE: + line("Check is true if object is identified/unidentified"); + break; + + case match_type::STATUS: + line("Check is true if object status is ok"); + break; + + case match_type::TVAL: + line("Check is true if object tval(from k_info.txt) is ok"); + + case match_type::SVAL: + line("Check is true if object sval(from k_info.txt) is between"); + line("two values"); + break; + + case match_type::RACE: + line("Check is true if player race is ok"); + break; + + case match_type::SUBRACE: + line("Check is true if player subrace is ok"); + break; + + case match_type::CLASS: + line("Check is true if player class is ok"); + break; + + case match_type::LEVEL: + line("Check is true if player level is between 2 values"); + break; + + case match_type::SKILL: + line("Check is true if player skill level is between 2 values"); + break; + + case match_type::ABILITY: + line("Check is true if player has the ability"); + break; + + case match_type::INVENTORY: + line("Check is true if something in player's inventory matches"); + line("the contained rule"); + break; + + case match_type::EQUIPMENT: + line("Check is true if something in player's equipment matches"); + line("the contained rule"); + break; + } +} + +std::shared_ptr new_condition_interactive() +{ + static std::vector condition_types = { + match_type::AND, + match_type::OR, + match_type::NOT, + match_type::NAME, + match_type::CONTAIN, + match_type::INSCRIBED, + match_type::DISCOUNT, + match_type::SYMBOL, + match_type::STATE, + match_type::STATUS, + match_type::TVAL, + match_type::SVAL, + match_type::RACE, + match_type::SUBRACE, + match_type::CLASS, + match_type::LEVEL, + match_type::SKILL, + match_type::ABILITY, + match_type::INVENTORY, + match_type::EQUIPMENT + }; + static std::vector condition_type_names; + + // Fill in types names? + if (condition_type_names.empty()) + { + for (auto condition_type : condition_types) + { + condition_type_names.push_back( + match_mapping().stringify(condition_type)); + } + } + + // Choose + int begin = 0, sel = 0; + while (1) + { + int wid, hgt; + Term_clear(); + Term_get_size(&wid, &hgt); + + display_list(0, 0, hgt - 1, 15, "Rule types", condition_type_names.data(), condition_types.size(), begin, sel, TERM_L_GREEN); + + display_desc(condition_types[sel]); + + char c = inkey(); + + if (c == ESCAPE) break; + else if (c == '8') + { + sel--; + if (sel < 0) + { + sel = condition_types.size() - 1; + begin = condition_types.size() - hgt; + if (begin < 0) begin = 0; + } + if (sel < begin) begin = sel; + } + else if (c == '2') + { + sel++; + if (sel >= condition_types.size()) + { + sel = 0; + begin = 0; + } + if (sel >= begin + hgt - 1) begin++; + } + else if (c == '\r') + { + switch (condition_types[sel]) + { + case match_type::AND: + return std::make_shared(); + case match_type::OR: + return std::make_shared(); + case match_type::NOT: + return std::make_shared(); + case match_type::NAME: + return create_condition_name(); + case match_type::CONTAIN: + return create_condition_contain(); + case match_type::INSCRIBED: + return create_condition_inscribed(); + case match_type::DISCOUNT: + return create_condition_discount(); + case match_type::SYMBOL: + return create_condition_symbol(); + case match_type::STATE: + return create_condition_state(); + case match_type::STATUS: + return create_condition_status(); + case match_type::TVAL: + return create_condition_tval(); + case match_type::SVAL: + return create_condition_sval(); + case match_type::RACE: + return create_condition_race(); + case match_type::SUBRACE: + return create_condition_subrace(); + case match_type::CLASS: + return create_condition_class(); + case match_type::LEVEL: + return create_condition_level(); + case match_type::SKILL: + return create_condition_skill(); + case match_type::ABILITY: + return create_condition_ability(); + case match_type::INVENTORY: + return std::make_shared(); + case match_type::EQUIPMENT: + return std::make_shared(); + + } + } + } + return nullptr; +} + +} // namespace diff --git a/src/squelch/cursor.cc b/src/squelch/cursor.cc new file mode 100644 index 00000000..db2f416d --- /dev/null +++ b/src/squelch/cursor.cc @@ -0,0 +1,93 @@ +#include "tome/squelch/cursor_fwd.hpp" +#include "tome/squelch/cursor.hpp" + +#include +#include + +#include "tome/squelch/condition.hpp" + +namespace squelch { + +bool Cursor::is_selected(Condition const *condition) const +{ + return std::end(m_conditions) != + std::find(std::begin(m_conditions), + std::end(m_conditions), + condition); +} + +Condition *Cursor::pop() +{ + assert(!m_conditions.empty()); + Condition *c = m_conditions.back(); + m_conditions.pop_back(); + return c; +} + +Condition *Cursor::current() +{ + assert(!m_conditions.empty()); + return m_conditions.back(); +} + +void Cursor::move_right() +{ + // Go right if the currently selected condition has children. + std::shared_ptr c = current()->first_child(); + if (c) + { + push(c.get()); + } +} + +void Cursor::move_left() +{ + if (size() > 1) + { + pop(); + } +} + +void Cursor::move_up() +{ + if (size() > 1) + { + Condition *prev_top = pop(); + + // Find previous child + std::shared_ptr prev_condition = + current()->previous_child(prev_top); + + // Do we have a previous child? + if (prev_condition) + { + push(prev_condition.get()); + } + else + { + push(prev_top); + } + } +} + +void Cursor::move_down() +{ + if (size() > 1) + { + Condition *prev_top = pop(); + + std::shared_ptr next_condition = + current()->next_child(prev_top); + + if (next_condition) + { + push(next_condition.get()); + } + else + { + push(prev_top); + } + } +} + +} // namespace diff --git a/src/squelch/object_status.cc b/src/squelch/object_status.cc new file mode 100644 index 00000000..53d2055a --- /dev/null +++ b/src/squelch/object_status.cc @@ -0,0 +1,149 @@ +#include "tome/squelch/object_status_fwd.hpp" +#include "tome/squelch/object_status.hpp" + +#include "angband.h" + +namespace squelch { + +EnumStringMap &status_mapping() +{ + // TODO: This is quite ugly and leads to valgrind complaints + static auto m = new EnumStringMap { + { status_type::BAD, "bad" }, + { status_type::VERY_BAD, "very bad" }, + { status_type::AVERAGE, "average" }, + { status_type::GOOD, "good" }, + { status_type::VERY_GOOD, "very good" }, + { status_type::SPECIAL, "special" }, + { status_type::TERRIBLE, "terrible" }, + { status_type::NONE, "none" }, + { status_type::CHEST_EMPTY, "(empty chest)" }, + { status_type::CHEST_DISARMED, "(disarmed chest)" } }; + return *m; +} + +status_type object_status(object_type *o_ptr) +{ + if (!object_known_p(o_ptr)) + { + switch (o_ptr->sense) + { + case SENSE_CURSED: return status_type::BAD; + case SENSE_WORTHLESS: return status_type::VERY_BAD; + case SENSE_AVERAGE: return status_type::AVERAGE; + case SENSE_GOOD_LIGHT: return status_type::GOOD; + case SENSE_GOOD_HEAVY: return status_type::GOOD; + case SENSE_EXCELLENT: return status_type::VERY_GOOD; + case SENSE_SPECIAL: return status_type::SPECIAL; + case SENSE_TERRIBLE: return status_type::TERRIBLE; + default: return status_type::NONE; + } + } + else + { + s16b slot = wield_slot_ideal(o_ptr, TRUE); + + if (artifact_p(o_ptr)) + { + if (!(o_ptr->ident & IDENT_CURSED)) + { + return status_type::SPECIAL; + } + else + { + return status_type::TERRIBLE; + } + } + else if ((o_ptr->name2 > 0) || + (o_ptr->name2b > 0)) + { + if (!(o_ptr->ident & IDENT_CURSED)) + { + return status_type::VERY_GOOD; + } + else + { + return status_type::VERY_BAD; + } + } + else if ((slot == INVEN_WIELD) || + (slot == INVEN_BOW) || + (slot == INVEN_AMMO) || + (slot == INVEN_TOOL)) + { + if (o_ptr->to_h + o_ptr->to_d < 0) + { + return status_type::BAD; + } + else if (o_ptr->to_h + o_ptr->to_d > 0) + { + return status_type::GOOD; + } + else + { + return status_type::AVERAGE; + } + } + else if ((slot >= INVEN_BODY) && + (slot <= INVEN_FEET)) + { + if (o_ptr->to_a < 0) + { + return status_type::BAD; + } + else if (o_ptr->to_a > 0) + { + return status_type::GOOD; + } + else + { + return status_type::AVERAGE; + } + } + else if (slot == INVEN_RING) + { + if ((o_ptr->to_d + o_ptr->to_h < 0) || + (o_ptr->to_a < 0) || + (o_ptr->pval < 0)) + { + return status_type::BAD; + } + else + { + return status_type::AVERAGE; + } + } + else if (slot == INVEN_NECK) + { + if (o_ptr->pval < 0) + { + return status_type::BAD; + } + else + { + return status_type::AVERAGE; + } + } + else if (o_ptr->tval == TV_CHEST) + { + if (o_ptr->pval == 0) + { + return status_type::CHEST_EMPTY; + } + else if (o_ptr->pval < 0) + { + return status_type::CHEST_DISARMED; + } + else + { + return status_type::AVERAGE; + } + } + else + { + return status_type::AVERAGE; + } + } +} + +} // namespace diff --git a/src/squelch/rule.cc b/src/squelch/rule.cc new file mode 100644 index 00000000..def034fd --- /dev/null +++ b/src/squelch/rule.cc @@ -0,0 +1,325 @@ +#include "tome/squelch/rule_fwd.hpp" +#include "tome/squelch/rule.hpp" + +#include "tome/squelch/cursor.hpp" +#include "tome/squelch/condition.hpp" +#include "tome/squelch/tree_printer.hpp" +#include "angband.h" +#include "quark.h" + +namespace squelch { + +EnumStringMap &action_mapping() +{ + static auto m = new EnumStringMap { + { action_type::AUTO_DESTROY, "destroy" }, + { action_type::AUTO_PICKUP, "pickup" }, + { action_type::AUTO_INSCRIBE, "inscribe" } }; + return *m; +} + +void Rule::set_name(const char *new_name) +{ + assert(new_name != nullptr); + m_name = new_name; +} + +const char *Rule::get_name() const +{ + return m_name.c_str(); +} + +std::shared_ptr Rule::get_condition() const +{ + return m_condition; +} + +json_t *Rule::to_json() const +{ + json_t *rule_json = json_object(); + json_object_set_new(rule_json, + "name", + json_string(m_name.c_str())); + json_object_set_new(rule_json, + "action", + json_string(action_mapping().stringify(m_action))); + json_object_set_new(rule_json, + "module", + json_string(modules[m_module_idx].meta.name)); + json_object_set_new(rule_json, + "condition", + Condition::optional_to_json(m_condition)); + return rule_json; +} + +void Rule::add_new_condition(Cursor *cursor, + ConditionFactory const &factory) +{ + // Top-level condition? + if (!m_condition) + { + // Sanity check for navigation stack + assert(cursor->empty()); + + // Create new top-level condition + m_condition = factory(); + + // Select the condition + if (m_condition) + { + cursor->push(m_condition.get()); + } + } + else + { + cursor->current()->add_child(factory); + } +} + +void Rule::delete_selected_condition(Cursor *cursor) +{ + assert(cursor->size() >= 1); + + if (cursor->size() == 1) + { + cursor->pop(); + m_condition.reset(); + } + else + { + Condition *prev_top = cursor->pop(); + Condition *top = cursor->current(); + + // Jump up a level; this is a simple way to ensure a + // valid cursor. We could be a little cleverer here by + // trying to move inside the current level, but it + // gets a little complicated. + cursor->move_left(); + + // Now we can remove the condition from its parent + top->remove_child(prev_top); + } +} + +void Rule::write_tree(TreePrinter *tree_printer, Cursor *cursor) const +{ + // Write out the main rule + do_write_tree(tree_printer); + + // Write out the condition + if (m_condition) + { + m_condition->display(tree_printer, cursor); + } +} + +bool Rule::apply_rule(object_type *o_ptr, int item_idx) const +{ + // Check module + if (m_module_idx != game_module_idx) + { + return false; + } + + // Check condition + if (m_condition && m_condition->is_match(o_ptr)) + { + return do_apply_rule(o_ptr, item_idx); + } + + // Doesn't apply + return false; +} + +std::shared_ptr Rule::parse_rule(json_t *rule_json) +{ + if (!json_is_object(rule_json)) + { + msg_print("Rule is not an object"); + return nullptr; + } + + // Retrieve the attributes + char *rule_name_s = nullptr; + char *rule_action_s = nullptr; + char *rule_module_s = nullptr; + if (json_unpack(rule_json, + "{s:s,s:s,s:s}", + "name", &rule_name_s, + "action", &rule_action_s, + "module", &rule_module_s) < 0) + { + msg_print("Rule missing required field(s)"); + return nullptr; + } + + // Convert attributes + action_type action; + if (!action_mapping().parse((cptr) rule_action_s, &action)) + { + msg_format("Invalid rule action '%s'", rule_action_s); + return nullptr; + } + + int module_idx = find_module((cptr) rule_module_s); + if (module_idx < 0) + { + msg_format("Skipping rule for unrecognized module '%s'", + (cptr) rule_module_s); + return nullptr; + } + + // Parse condition + std::shared_ptr condition = + Condition::parse_condition(json_object_get(rule_json, "condition")); + + // Parse rule + switch (action) + { + case action_type::AUTO_INSCRIBE: + { + json_t *rule_inscription_j = json_object_get(rule_json, "inscription"); + + if (rule_inscription_j == nullptr) + { + msg_print("Inscription rule missing 'inscription' attribute"); + return nullptr; + } + if (!json_is_string(rule_inscription_j)) + { + msg_print("Inscription rule 'inscription' attribute wrong type"); + return nullptr; + } + + std::string inscription = + json_string_value(rule_inscription_j); + return std::make_shared( + rule_name_s, module_idx, condition, inscription); + } + + case action_type::AUTO_PICKUP: + return std::make_shared( + rule_name_s, module_idx, condition); + + case action_type::AUTO_DESTROY: + return std::make_shared( + rule_name_s, module_idx, condition); + } + + assert(false); + return nullptr; +} + + +void DestroyRule::do_write_tree(TreePrinter *p) const +{ + p->write(TERM_GREEN, "A rule named \""); + p->write(TERM_WHITE, m_name.c_str()); + p->write(TERM_GREEN, "\" to "); + p->write(TERM_L_GREEN, "destroy"); + p->write(TERM_GREEN, " when"); + p->write(TERM_WHITE, "\n"); +} + +bool DestroyRule::do_apply_rule(object_type *o_ptr, int item_idx) const +{ + // Must be identified + if (object_aware_p(o_ptr) == FALSE) + { + return false; + } + + // Never destroy inscribed items + if (o_ptr->note) + { + return false; + } + + // Ignore artifacts; cannot be destroyed anyway + if (artifact_p(o_ptr)) + { + return false; + } + + // Cannot destroy CURSE_NO_DROP objects. + { + u32b f1, f2, f3, f4, f5, esp; + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + if ((f4 & TR4_CURSE_NO_DROP) != 0) + { + return false; + } + } + + // Destroy + msg_print(""); + inc_stack_size(item_idx, -o_ptr->number); + return true; +} + +void PickUpRule::do_write_tree(TreePrinter *p) const +{ + p->write(TERM_GREEN, "A rule named \""); + p->write(TERM_WHITE, m_name.c_str()); + p->write(TERM_GREEN, "\" to "); + p->write(TERM_L_GREEN, "pick up"); + p->write(TERM_GREEN, " when"); + p->write(TERM_WHITE, "\n"); +} + +bool PickUpRule::do_apply_rule(object_type *o_ptr, int item_idx) const +{ + if (item_idx >= 0) + { + return false; + } + + if (!inven_carry_okay(o_ptr)) + { + return false; + } + + msg_print(""); + object_pickup(-item_idx); + return true; +} + +json_t *InscribeRule::to_json() const +{ + json_t *j = Rule::to_json(); + + json_object_set_new(j, + "inscription", + json_string(m_inscription.c_str())); + + return j; +} + +void InscribeRule::do_write_tree(TreePrinter *p) const +{ + p->write(TERM_GREEN, "A rule named \""); + p->write(TERM_WHITE, m_name.c_str()); + p->write(TERM_GREEN, "\" to "); + p->write(TERM_L_GREEN, "inscribe"); + p->write(TERM_GREEN, " an item with \""); + p->write(TERM_WHITE, m_inscription.c_str()); + p->write(TERM_GREEN, "\" when"); + p->write(TERM_WHITE, "\n"); +} + +bool InscribeRule::do_apply_rule(object_type *o_ptr, int) const +{ + // Already inscribed? + if (o_ptr->note != 0) + { + return false; + } + + // Inscribe + msg_format("", m_inscription.c_str()); + o_ptr->note = quark_add(m_inscription.c_str()); + return true; +} + +} // namespace diff --git a/src/squelch/tree_printer.cc b/src/squelch/tree_printer.cc new file mode 100644 index 00000000..812933a9 --- /dev/null +++ b/src/squelch/tree_printer.cc @@ -0,0 +1,89 @@ +#include "tome/squelch/tree_printer_fwd.hpp" +#include "tome/squelch/tree_printer.hpp" + +#include "angband.h" + +namespace squelch { + +TreePrinter::TreePrinter() : m_indent(0) +{ + int wid, hgt; + // Output window + Term_get_size(&wid, &hgt); + m_write_out_y = 1; + m_write_out_x = 16; + m_write_out_h = hgt - 4 - 1; + m_write_out_w = wid - 1 - 15 - 1; + // Set position + reset(); + reset_scroll(); +} + +void TreePrinter::indent() { + m_indent++; +} + +void TreePrinter::dedent() { + m_indent--; +} + +void TreePrinter::reset() { + m_write_x = 0; + m_write_y = 0; +} + +void TreePrinter::reset_scroll() { + m_write_off_y = 0; + m_write_off_x = 0; +} + +void TreePrinter::scroll_up() { + m_write_off_y--; +} + +void TreePrinter::scroll_down() { + m_write_off_y++; +} + +void TreePrinter::scroll_left() { + m_write_off_x++; +} + +void TreePrinter::scroll_right() { + m_write_off_x--; +} + +void TreePrinter::write(uint8_t color, cptr line) +{ + cptr p = line; + + for (p = line; *p != '\0'; p++) + { + char c = *p; + int x = m_write_x - m_write_off_x + 3*m_indent; + int y = m_write_y - m_write_off_y; + + if (c != '\n') + { + if ((y >= 0) && + (y < m_write_out_h) && + (x >= 0) && + (x < m_write_out_w)) + { + Term_putch(x + m_write_out_x, + y + m_write_out_y, + color, + c); + } + + m_write_x += 1; + } + else + { + m_write_x = 0; + m_write_y += 1; + } + } +} + +} // namespace diff --git a/src/squeltch.c b/src/squeltch.c deleted file mode 100644 index 0c1e2902..00000000 --- a/src/squeltch.c +++ /dev/null @@ -1,3572 +0,0 @@ -/* File: squeltch.c */ - -/* Purpose: Automatizer */ - -/* - * Copyright (c) 2002 DarkGod - * - * This software may be copied and distributed for educational, research, and - * not for profit purposes provided that this copyright and statement are - * included in all such copies. - */ - -#include "angband.h" - -#include - -#include "quark.h" - -#define RULES_MAX 4096 -#define STACK_MAX 1024 - -typedef enum { BAD, VERY_BAD, AVERAGE, - GOOD, VERY_GOOD, SPECIAL, - TERRIBLE, NONE, CHEST_EMPTY, - CHEST_DISARMED } status_type; - -struct status_map_type { - status_type status; - cptr status_s; -}; - -status_type object_status(object_type *o_ptr) -{ - if (!object_known_p(o_ptr)) - { - switch (o_ptr->sense) - { - case SENSE_CURSED: return BAD; - case SENSE_WORTHLESS: return VERY_BAD; - case SENSE_AVERAGE: return AVERAGE; - case SENSE_GOOD_LIGHT: return GOOD; - case SENSE_GOOD_HEAVY: return GOOD; - case SENSE_EXCELLENT: return VERY_GOOD; - case SENSE_SPECIAL: return SPECIAL; - case SENSE_TERRIBLE: return TERRIBLE; - default: return NONE; - } - } - else - { - s16b slot = wield_slot_ideal(o_ptr, TRUE); - - if (artifact_p(o_ptr)) - { - if (!(o_ptr->ident & IDENT_CURSED)) - { - return SPECIAL; - } - else - { - return TERRIBLE; - } - } - else if ((o_ptr->name2 > 0) || - (o_ptr->name2b > 0)) - { - if (!(o_ptr->ident & IDENT_CURSED)) - { - return VERY_GOOD; - } - else - { - return VERY_BAD; - } - } - else if ((slot == INVEN_WIELD) || - (slot == INVEN_BOW) || - (slot == INVEN_AMMO) || - (slot == INVEN_TOOL)) - { - if (o_ptr->to_h + o_ptr->to_d < 0) - { - return BAD; - } - else if (o_ptr->to_h + o_ptr->to_d > 0) - { - return GOOD; - } - else - { - return AVERAGE; - } - } - else if ((slot >= INVEN_BODY) && - (slot <= INVEN_FEET)) - { - if (o_ptr->to_a < 0) - { - return BAD; - } - else if (o_ptr->to_a > 0) - { - return GOOD; - } - else - { - return AVERAGE; - } - } - else if (slot == INVEN_RING) - { - if ((o_ptr->to_d + o_ptr->to_h < 0) || - (o_ptr->to_a < 0) || - (o_ptr->pval < 0)) - { - return BAD; - } - else - { - return AVERAGE; - } - } - else if (slot == INVEN_NECK) - { - if (o_ptr->pval < 0) - { - return BAD; - } - else - { - return AVERAGE; - } - } - else if (o_ptr->tval == TV_CHEST) - { - if (o_ptr->pval == 0) - { - return CHEST_EMPTY; - } - else if (o_ptr->pval < 0) - { - return CHEST_DISARMED; - } - else - { - return AVERAGE; - } - } - else - { - return AVERAGE; - } - } -} - -#define STATUS_MAP_SIZE 10 -struct status_map_type status_map[STATUS_MAP_SIZE] = { - { BAD, "bad" }, - { VERY_BAD, "very bad" }, - { AVERAGE, "average" }, - { GOOD, "good" }, - { VERY_GOOD, "very good" }, - { SPECIAL, "special" }, - { TERRIBLE, "terrible" }, - { NONE, "none" }, - { CHEST_EMPTY, "(empty chest)" }, - { CHEST_DISARMED, "(disarmed chest)" }, -}; - -static cptr status_to_string(status_type status) -{ - int i; - - for (i = 0; i < STATUS_MAP_SIZE; i++) - { - if (status_map[i].status == status) - { - return status_map[i].status_s; - } - } - - assert(FALSE); - return NULL; -} - -static bool_ status_from_string(cptr s, status_type *status) -{ - int i; - - for (i = 0; i < STATUS_MAP_SIZE; i++) - { - if (streq(status_map[i].status_s, s)) - { - *status = status_map[i].status; - return TRUE; - } - } - - return FALSE; -} - -/* Type of automatizer actions */ -typedef enum { AUTO_DESTROY, - AUTO_PICKUP, - AUTO_INSCRIBE } action_type; - -/* Convert action to/from string */ -struct action_map_type { - action_type action; - cptr action_s; -}; - -#define ACTION_MAP_SIZE 3 -struct action_map_type action_map[ACTION_MAP_SIZE] = { - { AUTO_DESTROY, "destroy" }, - { AUTO_PICKUP, "pickup" }, - { AUTO_INSCRIBE, "inscribe" } -}; - -static cptr action_to_string(action_type action) -{ - int i = 0; - - for (i = 0; i < ACTION_MAP_SIZE; i++) - { - if (action == action_map[i].action) - { - return action_map[i].action_s; - } - } - - assert(FALSE); - return NULL; -} - -static bool_ action_from_string(cptr s, action_type *action) -{ - int i = 0; - - for (i = 0; i < ACTION_MAP_SIZE; i++) - { - if (streq(action_map[i].action_s, s)) - { - *action = action_map[i].action; - return TRUE; - } - } - - return FALSE; -} - -/* Identification state */ -typedef enum { IDENTIFIED, NOT_IDENTIFIED } identification_state; - -#define S_IDENTIFIED "identified" -#define S_NOT_IDENTIFIED "not identified" - -cptr identification_state_to_string(identification_state i) -{ - switch (i) - { - case IDENTIFIED: return S_IDENTIFIED; - case NOT_IDENTIFIED: return S_NOT_IDENTIFIED; - } - - assert(FALSE); - return NULL; -} - -bool_ identification_state_from_string(cptr s, identification_state *state) -{ - if (streq(s, S_IDENTIFIED)) - { - *state = IDENTIFIED; - return TRUE; - } - else if (streq(s, S_NOT_IDENTIFIED)) - { - *state = NOT_IDENTIFIED; - return TRUE; - } - else - { - return FALSE; - } -} - -/* Match type */ -typedef enum { M_AND , M_OR , M_NOT , M_NAME , M_CONTAIN , - M_INSCRIBED, M_DISCOUNT, M_SYMBOL , M_STATE , M_STATUS , - M_TVAL , M_SVAL , M_RACE , M_SUBRACE , M_CLASS , - M_LEVEL , M_SKILL , M_ABILITY, M_INVENTORY, M_EQUIPMENT } - match_type; - -struct match_type_map { - match_type i; - cptr s; -}; - -#define MATCH_TYPE_MAP_SIZE 20 -struct match_type_map match_type_map[MATCH_TYPE_MAP_SIZE] = { - { M_AND, "and" }, - { M_OR, "or" }, - { M_NOT, "not" }, - { M_NAME, "name" }, - { M_CONTAIN, "contain" }, - { M_INSCRIBED, "inscribed" }, - { M_DISCOUNT, "discount" }, - { M_SYMBOL, "symbol" }, - { M_STATE, "state" }, - { M_STATUS, "status" }, - { M_TVAL, "tval" }, - { M_SVAL, "sval" }, - { M_RACE, "race" }, - { M_SUBRACE, "subrace" }, - { M_CLASS, "class" }, - { M_LEVEL, "level" }, - { M_SKILL, "skill" }, - { M_ABILITY, "ability" }, - { M_INVENTORY, "inventory" }, - { M_EQUIPMENT, "equipment" }, -}; - -cptr match_type_to_string(match_type m) -{ - int i; - - for (i = 0; i < MATCH_TYPE_MAP_SIZE; i++) - { - if (match_type_map[i].i == m) - { - return match_type_map[i].s; - } - } - - assert(FALSE); - return NULL; -} - -bool_ match_type_from_string(cptr s, match_type *match) -{ - int i; - - for (i = 0; i < MATCH_TYPE_MAP_SIZE; i++) - { - if (streq(match_type_map[i].s, s)) - { - *match = match_type_map[i].i; - return TRUE; - } - } - - return FALSE; -} - -/* Forward declarations */ -typedef struct condition_type condition_type; -struct condition_type; - -/* List of conditions */ -typedef struct condition_list condition_list; -struct condition_list { - condition_type *condition; - condition_list *next; -}; - -int compare_condition_list(condition_list *a, condition_list *b) -{ - assert(FALSE); -} - -SGLIB_DEFINE_LIST_PROTOTYPES(condition_list, compare_condition_list, next); -SGLIB_DEFINE_LIST_FUNCTIONS(condition_list, compare_condition_list, next); - -/* Condition instance */ -struct condition_type -{ - /* What do we want to match? */ - match_type match; - /* Sub-conditions for logical connectives; if applicable */ - struct { - condition_list *c; - } conditions; - /* Sub-condition for cases where there is only a single subcondition */ - condition_type *subcondition; - /* Tval to match if applicable. */ - byte tval; - /* Sval range if applicable. */ - struct { - byte min; - byte max; - } sval_range; - /* Discount range. */ - struct { - int min; - int max; - } discount; - /* Level range */ - struct { - int min; - int max; - } level_range; - /* Skill range */ - struct { - s16b min; - s16b max; - s16b skill_idx; - } skill_range; - /* Identification state to match if applicable */ - identification_state identification_state; - /* Status to match if applicable */ - status_type status; - /* Name to match */ - char *name; - /* Symbol to match if applicable */ - char symbol; - /* Inscription to find */ - char *inscription; - /* Subrace to match if applicable */ - char *subrace; - /* Race to match if applicable */ - char *race; - /* Class to match if applicable */ - char *klass; - /* Ability to match if applicable */ - s16b ability; - /* Comment */ - char *comment; -}; - -static condition_type *condition_new(match_type match) -{ - condition_type *cp = malloc(sizeof(condition_type)); - memset(cp, 0, sizeof(condition_type)); - cp->match = match; - return cp; -} - -static condition_type *condition_new_tval(byte tval) -{ - condition_type *cp = condition_new(M_TVAL); - cp->tval = tval; - return cp; -} - -static condition_type *condition_new_sval(byte min, byte max) -{ - condition_type *cp = condition_new(M_SVAL); - cp->sval_range.min = min; - cp->sval_range.max = max; - return cp; -} - -static condition_type *condition_new_and() -{ - condition_type *cp = condition_new(M_AND); - return cp; -} - -static condition_type *condition_new_or() -{ - condition_type *cp = condition_new(M_OR); - return cp; -} - -static condition_type *condition_new_not() -{ - condition_type *cp = condition_new(M_NOT); - return cp; -} - -static condition_type *condition_new_name(cptr name) -{ - condition_type *cp = condition_new(M_NAME); - cp->name = strdup(name); - return cp; -} - -static condition_type *condition_new_contain(cptr name) -{ - condition_type *cp = condition_new(M_CONTAIN); - cp->name = strdup(name); - return cp; -} - -static condition_type *condition_new_inscribed(cptr name) -{ - condition_type *cp = condition_new(M_INSCRIBED); - cp->inscription = strdup(name); - return cp; -} - -static condition_type *condition_new_status(status_type status) -{ - condition_type *cp = condition_new(M_STATUS); - cp->status = status; - return cp; -} - -static condition_type *condition_new_state(identification_state state) -{ - condition_type *cp = condition_new(M_STATE); - cp->identification_state = state; - return cp; -} - -static condition_type *condition_new_discount(int min, int max) -{ - condition_type *cp = condition_new(M_DISCOUNT); - cp->discount.min = min; - cp->discount.max = max; - return cp; -} - -static condition_type *condition_new_symbol(char c) -{ - condition_type *cp = condition_new(M_SYMBOL); - cp->symbol = c; - return cp; -} - -static condition_type *condition_new_race(cptr race) -{ - condition_type *cp = condition_new(M_RACE); - cp->race = strdup(race); - return cp; -} - -static condition_type *condition_new_subrace(cptr subrace) -{ - condition_type *cp = condition_new(M_SUBRACE); - cp->subrace = strdup(subrace); - return cp; -} - -static condition_type *condition_new_class(cptr klass) -{ - condition_type *cp = condition_new(M_CLASS); - cp->klass = strdup(klass); - return cp; -} - -static condition_type *condition_new_level(int min, int max) -{ - condition_type *cp = condition_new(M_LEVEL); - cp->level_range.min = min; - cp->level_range.max = max; - return cp; -} - -static condition_type *condition_new_skill(s16b min, s16b max, s16b skill_idx) -{ - condition_type *cp = condition_new(M_SKILL); - cp->skill_range.min = min; - cp->skill_range.max = max; - cp->skill_range.skill_idx = skill_idx; - return cp; -} - -static condition_type *condition_new_ability(s16b ability_idx) -{ - condition_type *cp = condition_new(M_ABILITY); - cp->ability = ability_idx; - return cp; -} - -static condition_type *condition_new_inventory() -{ - condition_type *cp = condition_new(M_INVENTORY); - return cp; -} - -static condition_type *condition_new_equipment() -{ - condition_type *cp = condition_new(M_EQUIPMENT); - return cp; -} - -static void condition_and_add(condition_type *and_c, condition_type *c) -{ - assert(and_c != NULL); - assert(c != NULL); - assert((and_c->match == M_AND) || (and_c->match == M_OR)); - - condition_list *cl = malloc(sizeof(condition_list)); - cl->condition = c; - cl->next = NULL; - - sglib_condition_list_add(&and_c->conditions.c, cl); -} - -static void condition_or_add(condition_type *or_c, condition_type *c) -{ - condition_and_add(or_c, c); -} - -static void condition_destroy(condition_type **cp) -{ - condition_type *c = NULL; - assert(cp != NULL); - assert(*cp != NULL); - - c = *cp; - - /* Free sub-conditions if any */ - { - condition_list *current = NULL; - condition_list *next = NULL; - - for (current = c->conditions.c; - current != NULL; - current = next) - { - condition_destroy(¤t->condition); - next = current->next; - free(current); - } - } - - /* Free sub-condition if any */ - if (c->subcondition) - { - condition_destroy(&c->subcondition); - } - - /* Free name if any */ - if (c->name) - { - free(c->name); - c->name = NULL; - } - - /* Free inscription if any */ - if (c->inscription) - { - free(c->inscription); - c->inscription = NULL; - } - - /* Free subrace if any */ - if (c->subrace) - { - free(c->subrace); - c->subrace = NULL; - } - - /* Free race if any */ - if (c->race) - { - free(c->race); - c->race = NULL; - } - - /* Free class if any */ - if (c->klass) - { - free(c->klass); - c->klass = NULL; - } - - /* Free comment if any */ - if (c->comment) - { - free(c->comment); - c->comment = NULL; - } - - /* Free the condition itself */ - free(*cp); - *cp = NULL; -} - -static bool_ condition_eval(condition_type *c, object_type *o_ptr) -{ - bool_ is_and = (c->match == M_AND); - bool_ is_or = (c->match == M_OR); - - switch (c->match) - { - case M_AND: - case M_OR: - { - struct sglib_condition_list_iterator it; - struct condition_list *child = NULL; - - for (child = sglib_condition_list_it_init(&it, c->conditions.c); - child != NULL; - child = sglib_condition_list_it_next(&it)) - { - if (is_and && (!condition_eval(child->condition, o_ptr))) - { - return FALSE; - } - - if (is_or && condition_eval(child->condition, o_ptr)) - { - return TRUE; - } - } - - if (is_and) - { - return TRUE; - } - else - { - return FALSE; - } - } - - case M_NOT: - { - if (c->subcondition == NULL) - { - return TRUE; - } - - return !condition_eval(c->subcondition, o_ptr); - } - - case M_INVENTORY: - { - int i; - - if (c->subcondition == NULL) - { - return FALSE; - } - - for (i = 0; i < INVEN_WIELD; i++) - { - if (condition_eval(c->subcondition, &p_ptr->inventory[i])) - { - return TRUE; - } - } - - return FALSE; - } - - case M_EQUIPMENT: - { - int i; - - if (c->subcondition == NULL) - { - return FALSE; - } - - for (i = INVEN_WIELD; i < INVEN_TOTAL; i++) - { - if (condition_eval(c->subcondition, &p_ptr->inventory[i])) - { - return TRUE; - } - } - - return FALSE; - } - - case M_NAME: - { - char buf1[128]; - char buf2[128]; - - object_desc(buf1, o_ptr, -1, 0); - strlower(buf1); - - sprintf(buf2, "%s", c->name); - strlower(buf2); - - return streq(buf1, buf2); - } - - case M_CONTAIN: - { - char buf1[128]; - char buf2[128]; - - object_desc(buf1, o_ptr, -1, 0); - strlower(buf1); - - sprintf(buf2, "%s", c->name); - strlower(buf2); - - return (strstr(buf1, buf2) != NULL); - } - - case M_SYMBOL: - { - object_kind *k_ptr = &k_info[o_ptr->k_idx]; - - return k_ptr->d_char == c->symbol; - } - - case M_INSCRIBED: - { - char buf1[128]; - char buf2[128]; - - if (o_ptr->note == 0) - { - return FALSE; - } - - sprintf(buf1, "%s", quark_str(o_ptr->note)); - strlower(buf1); - - sprintf(buf2, "%s", c->inscription); - strlower(buf2); - - return (strstr(buf1, buf2) != NULL); - } - - case M_DISCOUNT: - { - return (object_aware_p(o_ptr) && - (o_ptr->discount >= c->discount.min) && - (o_ptr->discount <= c->discount.max)); - } - - case M_TVAL: - { - return (o_ptr->tval == c->tval); - } - - case M_SVAL: - { - return (object_aware_p(o_ptr) && - (o_ptr->sval >= c->sval_range.min) && - (o_ptr->sval <= c->sval_range.max)); - } - - case M_STATUS: - { - return c->status == object_status(o_ptr); - } - - case M_STATE: - { - switch (c->identification_state) - { - case IDENTIFIED: - return object_known_p(o_ptr); - case NOT_IDENTIFIED: - return !object_known_p(o_ptr); - default: - assert(FALSE); - } - } - - case M_RACE: - { - char buf1[128]; - char buf2[128]; - - sprintf(buf1, "%s", rp_ptr->title + rp_name); - strlower(buf1); - - sprintf(buf2, "%s", c->race); - strlower(buf2); - - return streq(buf1, buf2); - } - - case M_SUBRACE: - { - char buf1[128]; - char buf2[128]; - - sprintf(buf1, "%s", rmp_ptr->title + rmp_name); - strlower(buf1); - - sprintf(buf2, "%s", c->subrace); - strlower(buf2); - - return streq(buf1, buf2); - } - - case M_CLASS: - { - char buf1[128]; - char buf2[128]; - - sprintf(buf1, "%s", spp_ptr->title + c_name); - strlower(buf1); - - sprintf(buf2, "%s", c->klass); - strlower(buf2); - - return streq(buf1, buf2); - } - - case M_LEVEL: - { - return ((p_ptr->lev >= c->level_range.min) && - (p_ptr->lev <= c->level_range.max)); - } - - case M_SKILL: - { - s16b sk = get_skill(c->skill_range.skill_idx); - return ((sk >= c->skill_range.min) && - (sk <= c->skill_range.max)); - } - - case M_ABILITY: - { - return has_ability(c->ability); - } - - } - - /* Don't match by default */ - return FALSE; -} - -static json_t *condition_to_json(condition_type *c) -{ - json_t *json = NULL; - - if (c == NULL) - { - return json_null(); - } - - json = json_object(); - json_object_set_new(json, "type", - json_string(match_type_to_string(c->match))); - - switch (c->match) - { - case M_AND: - case M_OR: - { - struct sglib_condition_list_iterator it; - struct condition_list *child = NULL; - - json_t *conditions_json = json_array(); - - for (child = sglib_condition_list_it_init(&it, c->conditions.c); - child != NULL; - child = sglib_condition_list_it_next(&it)) - { - json_array_append_new(conditions_json, - condition_to_json(child->condition)); - } - - json_object_set_new(json, "conditions", conditions_json); - break; - } - - case M_NOT: - case M_INVENTORY: - case M_EQUIPMENT: - { - json_object_set_new(json, "condition", - condition_to_json(c->subcondition)); - break; - } - - case M_NAME: - { - json_object_set_new(json, "name", - json_string(c->name)); - break; - } - - case M_CONTAIN: - { - json_object_set_new(json, "contain", - json_string(c->name)); - break; - } - - case M_SYMBOL: - { - json_object_set_new(json, "symbol", - json_string(format("%c", c->symbol))); - break; - } - - case M_INSCRIBED: - { - json_object_set_new(json, "inscription", - json_string(c->inscription)); - break; - } - - case M_DISCOUNT: - { - json_object_set_new(json, "min", - json_integer(c->discount.min)); - json_object_set_new(json, "max", - json_integer(c->discount.max)); - break; - } - - case M_TVAL: - { - json_object_set_new(json, "tval", - json_integer(c->tval)); - break; - } - - case M_SVAL: - { - json_object_set_new(json, "min", - json_integer(c->sval_range.min)); - json_object_set_new(json, "max", - json_integer(c->sval_range.max)); - break; - } - - case M_STATUS: - { - json_object_set_new(json, "status", - json_string(status_to_string(c->status))); - break; - } - - case M_STATE: - { - json_object_set_new(json, "state", - json_string(identification_state_to_string(c->identification_state))); - break; - } - - case M_RACE: - { - json_object_set_new(json, "race", - json_string(c->race)); - break; - } - - case M_SUBRACE: - { - json_object_set_new(json, "subrace", - json_string(c->subrace)); - break; - } - - case M_CLASS: - { - json_object_set_new(json, "class", - json_string(c->klass)); - break; - } - - case M_LEVEL: - { - json_object_set_new(json, "min", - json_integer(c->level_range.min)); - json_object_set_new(json, "max", - json_integer(c->level_range.max)); - break; - } - - case M_SKILL: - { - json_object_set_new(json, "name", - json_string(s_info[c->skill_range.skill_idx].name + s_name)); - json_object_set_new(json, "min", - json_integer(c->skill_range.min)); - json_object_set_new(json, "max", - json_integer(c->skill_range.max)); - break; - } - - case M_ABILITY: - { - json_object_set_new(json, "ability", - json_string(ab_info[c->ability].name + ab_name)); - break; - } - - } - - return json; -} - -/* - * Cursor to maintain position in condition tree - */ -static condition_type *cursor_stack[STACK_MAX]; -static int cursor_count = 0; - -static void cursor_push(condition_type *condition) -{ - assert(cursor_count < STACK_MAX); - - cursor_stack[cursor_count] = condition; - cursor_count++; -} - -static condition_type *cursor_pop() -{ - condition_type *c = NULL; - - assert(cursor_count > 0); - - c = cursor_stack[cursor_count-1]; - cursor_stack[cursor_count] = NULL; - cursor_count--; - return c; -} - -static condition_type *cursor_top() -{ - assert(cursor_count > 0); - - return cursor_stack[cursor_count - 1]; -} - -static void cursor_clear() -{ - while (cursor_count > 0) - { - cursor_pop(); - } -} - -/* Rule */ -typedef struct arule_type arule_type; -struct arule_type { - /* Rule name */ - char *name; - /* Which action do we take? */ - action_type action; /* Which action to take */ - /* Which module does this rule apply to? */ - int module_idx; - /* Inscription to use for inscription rules. */ - char *inscription; - /* Condition. */ - condition_type *condition; /* Condition for rule match */ -}; - -/* Initialize a rule */ -static arule_type *rule_new(cptr name, action_type action, int module_idx, condition_type *condition, cptr inscription) -{ - arule_type *rp = malloc(sizeof(arule_type)); - rp->name = strdup(name); - rp->action = action; - rp->module_idx = module_idx; - rp->condition = condition; - rp->inscription = (inscription == NULL) ? NULL : strdup(inscription); - return rp; -} - -static void rule_set_name(arule_type *rule, cptr new_name) -{ - if (rule->name) - { - free(rule->name); - } - - rule->name = strdup(new_name); -} - -static void rule_destroy(arule_type **rp) -{ - if ((*rp)->name) - { - free((*rp)->name); - } - - if ((*rp)->inscription) - { - free((*rp)->inscription); - } - - if ((*rp)->condition) - { - condition_destroy(&(*rp)->condition); - } - - free(*rp); - *rp = NULL; -} - -/* Current list of rules. */ -static arule_type *rules[RULES_MAX]; -static int rules_count = 0; /* Number of rules currently in list */ - -static int rules_append(arule_type *rule) -{ - assert(rules_count < RULES_MAX); - - rules[rules_count] = rule; - rules_count++; - return rules_count-1; -} - -static void rules_remove(arule_type *rule) -{ - int i, j; - - for (i = 0; i < rules_count; i++) - { - if (rules[i] == rule) - { - /* Free the rule */ - rule_destroy(&rule); - /* Move rest of rest "up" */ - for (j = i+1; j < rules_count; j++) - { - rules[j-1] = rules[j]; - } - /* We're done */ - rules_count--; - return; - } - } -} - -static void rules_swap(int i, int j) -{ - arule_type *tmp_rptr = NULL; - - assert(i >= 0); - assert(i < rules_count); - - assert(j >= 0); - assert(j < rules_count); - - tmp_rptr = rules[i]; - rules[i] = rules[j]; - rules[j] = tmp_rptr; -} - -static bool_* automatizer_auto_destroy(object_type *o_ptr, int item_idx) -{ - static bool_ TRUE_VAL = TRUE; - - /* Must be identified */ - if (object_aware_p(o_ptr) == FALSE) - { - return NULL; - } - - /* Inscribed things won't be destroyed! */ - if (o_ptr->note) - { - return NULL; - } - - /* Ignore artifacts; cannot be destroyed anyway. */ - if (artifact_p(o_ptr)) - { - return NULL; - } - - /* Cannot destroy CURSE_NO_DROP objects. */ - { - u32b f1, f2, f3, f4, f5, esp; - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - if ((f4 & TR4_CURSE_NO_DROP) != 0) - { - return NULL; - } - } - - /* Destroy! */ - msg_print(""); - - inc_stack_size(item_idx, -o_ptr->number); - return &TRUE_VAL; -} - -static bool_* automatizer_auto_pickup(object_type *o_ptr, int item_idx) -{ - static bool_ TRUE_VAL = TRUE; - - if (item_idx >= 0) - { - return NULL; - } - - if (!inven_carry_okay(o_ptr)) - { - return NULL; - } - - msg_print(""); - - object_pickup(-item_idx); - return &TRUE_VAL; -} - -/* Apply rules */ -static bool_ apply_rule(arule_type *rule, object_type *o_ptr, int item_idx) -{ - /* Check module */ - if (rule->module_idx != game_module_idx) - { - return FALSE; - } - - /* Check condition */ - assert (rule->condition != NULL); - if (condition_eval(rule->condition, o_ptr)) - { - switch (rule->action) - { - - case AUTO_DESTROY: - { - automatizer_auto_destroy(o_ptr, item_idx); - break; - } - - case AUTO_PICKUP: - { - automatizer_auto_pickup(o_ptr, item_idx); - break; - } - - case AUTO_INSCRIBE: - { - /* Already inscribed? */ - if (o_ptr->note != 0) - { - return FALSE; - } - - /* Inscribe */ - msg_format("", rule->inscription); - o_ptr->note = quark_add(rule->inscription); - break; - } - - } - - return TRUE; - } - - return FALSE; -} - -static bool_ apply_rules(object_type *o_ptr, int item_idx) -{ - int i; - - for (i = 0; i < rules_count; i++) - { - if (apply_rule(rules[i], o_ptr, item_idx)) - { - return TRUE; - } - } - - /* Don't keep trying */ - return FALSE; -} - -static json_t *rule_to_json(arule_type *rule) -{ - json_t *rule_json = json_object(); - - json_object_set_new(rule_json, - "name", - json_string(rule->name)); - json_object_set_new(rule_json, - "action", - json_string(action_to_string(rule->action))); - json_object_set_new(rule_json, - "module", - json_string(modules[rule->module_idx].meta.name)); - - if (rule->inscription) - { - json_object_set_new(rule_json, - "inscription", - json_string(rule->inscription)); - } - - json_object_set_new(rule_json, - "condition", - condition_to_json(rule->condition)); - - return rule_json; -} - -static json_t *rules_to_json() -{ - int i; - json_t *rules_json = json_array(); - - for (i = 0; i < rules_count; i++) - { - json_array_append_new(rules_json, rule_to_json(rules[i])); - } - - return rules_json; -} - -/* Check the floor for "crap" */ -void squeltch_grid(void) -{ - s16b this_o_idx, next_o_idx = 0; - - if (!automatizer_enabled) return; - - /* Scan the pile of objects */ - for (this_o_idx = cave[p_ptr->py][p_ptr->px].o_idx; this_o_idx; this_o_idx = next_o_idx) - { - /* Acquire object */ - object_type * o_ptr = &o_list[this_o_idx]; - - /* We've now seen one of these */ - if (!k_info[o_ptr->k_idx].flavor) - { - object_aware(o_ptr); - } - - /* Acquire next object */ - next_o_idx = o_ptr->next_o_idx; - - /* Apply rules */ - apply_rules(o_ptr, -this_o_idx); - } -} - - -/* Check the inventory for "crap" */ -void squeltch_inventory(void) -{ - int i; - int num_iter = 0; - bool_ found = TRUE; - - if (!automatizer_enabled) return; - - while (found && num_iter ++ < 100) - { - /* Sometimes an index in the inventory is skipped */ - found = FALSE; - - for (i = 0; i < INVEN_PACK; i++) - { - object_type *o_ptr = &p_ptr->inventory[i]; - - if (apply_rules(o_ptr, i)) - { - found = TRUE; - break; - } - } - } - if (num_iter >= 100) - { - cmsg_format(TERM_VIOLET, "'apply_rules' ran too often."); - } -} - -/********************** The interface **********************/ -static void get_rule_names(cptr *list) -{ - int i; - - for (i = 0; i < rules_count; i++) - { - list[i] = rules[i]->name; - } -} - -typedef struct condition_metadata condition_metadata; -struct condition_metadata { - match_type match; - cptr description[3]; - condition_type *(*create_condition)(); -}; - -#define TYPES_LIST_SIZE 21 - -static condition_type *create_condition_name() -{ - cptr s = lua_input_box("Object name to match?", 79); - if (strlen(s) == 0) - { - return NULL; - } - - return condition_new_name(s); -} - -static condition_type *create_condition_contain() -{ - cptr s = lua_input_box("Word to find in object name?", 79); - if (strlen(s) == 0) - { - return NULL; - } - - return condition_new_contain(s); -} - -static condition_type *create_condition_inscribed() -{ - cptr s = lua_input_box("Word to find in object inscription?", 79); - if (strlen(s) == 0) - { - return NULL; - } - - return condition_new_inscribed(s); -} - -static condition_type *create_condition_discount() -{ - int min, max; - - { - cptr s = lua_input_box("Min discount?", 79); - if (sscanf(s, "%d", &min) < 1) - { - return NULL; - } - } - - { - cptr s = lua_input_box("Max discount?", 79); - if (sscanf(s, "%d", &max) < 1) - { - return NULL; - } - } - - return condition_new_discount(min, max); -} - -static condition_type *create_condition_symbol() -{ - char c; - cptr s = lua_input_box("Symbol to match?", 1); - if (sscanf(s, "%c", &c) < 1) - { - return NULL; - } - - return condition_new_symbol(c); -} - -static condition_type *create_condition_status() -{ - status_type status; - char c; - - c = lua_msg_box("[t]errible, [v]ery bad, [b]ad, " - "[a]verage, [G]ood, [V]ery good, [S]pecial?"); - - switch (c) - { - case 't': status = TERRIBLE; break; - case 'v': status = VERY_BAD; break; - case 'b': status = BAD; break; - case 'a': status = AVERAGE; break; - case 'G': status = GOOD; break; - case 'V': status = VERY_GOOD; break; - case 'S': status = SPECIAL; break; - default: return NULL; - } - - return condition_new_status(status); -} - -static condition_type *create_condition_state() -{ - identification_state s; - char c; - - c = lua_msg_box("[i]dentified, [n]on identified?"); - - switch (c) - { - case 'i': s = IDENTIFIED; break; - case 'n': s = NOT_IDENTIFIED; break; - default: return NULL; - } - - return condition_new_state(s); -} - -static condition_type *create_condition_tval() -{ - int tval; - cptr s = lua_input_box("Tval to match?", 79); - if (sscanf(s, "%d", &tval) < 1) - { - return NULL; - } - - return condition_new_tval(tval); -} - -static condition_type *create_condition_sval() -{ - int sval_min, sval_max; - - { - cptr s = lua_input_box("Min sval?", 79); - if (sscanf(s, "%d", &sval_min) < 1) - { - return NULL; - } - } - - { - cptr s = lua_input_box("Max sval?", 79); - if (sscanf(s, "%d", &sval_max) < 1) - { - return NULL; - } - } - - return condition_new_sval(sval_min, sval_max); -} - -static condition_type *create_condition_race() -{ - cptr s = lua_input_box("Player race to match?", 79); - if (strlen(s) == 0) - { - return NULL; - } - - return condition_new_race(s); -} - -static condition_type *create_condition_subrace() -{ - cptr s = lua_input_box("Player subrace to match?", 79); - if (strlen(s) == 0) - { - return NULL; - } - - return condition_new_subrace(s); -} - -static condition_type *create_condition_class() -{ - cptr s = lua_input_box("Player class to match?", 79); - if (strlen(s) == 0) - { - return NULL; - } - - return condition_new_class(s); -} - -static condition_type *create_condition_level() -{ - int min, max; - - { - cptr s = lua_input_box("Min player level?", 79); - if (sscanf(s, "%d", &min) < 1) - { - return NULL; - } - } - - { - cptr s = lua_input_box("Max player level?", 79); - if (sscanf(s, "%d", &max) < 1) - { - return NULL; - } - } - - return condition_new_level(min, max); -} - -static condition_type *create_condition_skill() -{ - int min, max; - s16b skill_idx; - - { - cptr s = lua_input_box("Min skill level?", 79); - if (sscanf(s, "%d", &min) < 1) - { - return NULL; - } - } - - { - cptr s = lua_input_box("Max skill level?", 79); - if (sscanf(s, "%d", &max) < 1) - { - return NULL; - } - } - - { - cptr s = lua_input_box("Skill name?", 79); - if (strlen(s) == 0) - { - return NULL; - } - - skill_idx = find_skill_i(s); - if (skill_idx < 0) - { - return NULL; - } - } - - return condition_new_skill(min, max, skill_idx); -} - -static condition_type *create_condition_ability() -{ - s16b ai; - cptr s = lua_input_box("Ability name?", 79); - if (strlen(s) == 0) - { - return NULL; - } - - ai = find_ability(s); - if (ai < 0) - { - return NULL; - } - - return condition_new_ability(ai); -} - -static condition_metadata types_list[TYPES_LIST_SIZE] = -{ - { M_AND, - { "Check is true if all rules within it are true", - NULL }, - condition_new_and, - }, - { M_OR, - { "Check is true if at least one rule within it is true", - NULL }, - condition_new_or, - }, - { M_NOT, - { "Invert the result of its child rule", - NULL }, - condition_new_not, - }, - { M_NAME, - { "Check is true if object name matches name", - NULL }, - create_condition_name, - }, - { M_CONTAIN, - { "Check is true if object name contains word", - NULL }, - create_condition_contain, - }, - { M_INSCRIBED, - { "Check is true if object inscription contains word", - NULL }, - create_condition_inscribed, - }, - { M_DISCOUNT, - { "Check is true if object discount is between two values", - NULL }, - create_condition_discount, - }, - { M_SYMBOL, - { "Check is true if object symbol is ok", - NULL }, - create_condition_symbol, - }, - { M_STATE, - { "Check is true if object is identified/unidentified", - NULL }, - create_condition_state, - }, - { M_STATUS, - { "Check is true if object status is ok", - NULL }, - create_condition_status, - }, - { M_TVAL, - { "Check is true if object tval(from k_info.txt) is ok", - NULL }, - create_condition_tval, - }, - { M_SVAL, - { "Check is true if object sval(from k_info.txt) is between", - "two values", - NULL }, - create_condition_sval, - }, - { M_RACE, - { "Check is true if player race is ok", - NULL }, - create_condition_race, - }, - { M_SUBRACE, - { "Check is true if player subrace is ok", - NULL }, - create_condition_subrace, - }, - { M_CLASS, - { "Check is true if player class is ok", - NULL }, - create_condition_class, - }, - { M_LEVEL, - { "Check is true if player level is between 2 values", - NULL }, - create_condition_level, - }, - { M_SKILL, - { "Check is true if player skill level is between 2 values", - NULL }, - create_condition_skill, - }, - { M_ABILITY, - { "Check is true if player has the ability", - NULL }, - create_condition_ability, - }, - { M_INVENTORY, - { "Check is true if something in player's inventory matches", - "the contained rule", - NULL }, - condition_new_inventory, - }, - { M_EQUIPMENT, - { "Check is true if something in player's equipment matches", - "the contained rule", - NULL }, - condition_new_equipment, - }, -}; - -static void display_desc(condition_metadata *condition_metadata) -{ - int i; - - assert(condition_metadata != NULL); - - for (i = 0; condition_metadata->description[i] != NULL; i++) - { - c_prt(TERM_WHITE, condition_metadata->description[i], i + 1, 17); - } -} - -/* Create a new rule */ -static condition_metadata *automatizer_select_condition_type() -{ - int wid, hgt, max = TYPES_LIST_SIZE, begin = 0, sel = 0, i; - char c; - cptr types_names[TYPES_LIST_SIZE]; - - /* Create list of names for display */ - for (i = 0; i < TYPES_LIST_SIZE; i++) - { - types_names[i] = match_type_to_string(types_list[i].match); - } - - while (1) - { - Term_clear(); - Term_get_size(&wid, &hgt); - - display_list(0, 0, hgt - 1, 15, "Rule types", types_names, max, begin, sel, TERM_L_GREEN); - - display_desc(&types_list[sel]); - - c = inkey(); - - if (c == ESCAPE) break; - else if (c == '8') - { - sel--; - if (sel < 0) - { - sel = max - 1; - begin = max - hgt; - if (begin < 0) begin = 0; - } - if (sel < begin) begin = sel; - } - else if (c == '2') - { - sel++; - if (sel >= max) - { - sel = 0; - begin = 0; - } - if (sel >= begin + hgt - 1) begin++; - } - else if (c == '\r') - { - return &types_list[sel]; - } - } - return NULL; -} - -static void adjust_begin(int *begin, int *sel, int max, int hgt) -{ - if (*sel < 0) - { - *sel = max - 1; - *begin = *sel - hgt + 3; - if (*begin < 0) *begin = 0; - } - if (*sel < *begin) *begin = *sel; - - if (*sel >= max) - { - *sel = 0; - *begin = 0; - } - if (*sel >= *begin + hgt - 2) (*begin)++; -} - -static int create_new_rule() -{ - action_type action; - char name[20] = { '\0' }; - char *inscription = NULL; - int wid = 0, hgt = 0; - char typ; - arule_type *rule = NULL; - - Term_get_size(&wid, &hgt); - - sprintf(name, "%s", "No name"); - if (!input_box("Name?", hgt / 2, wid / 2, name, sizeof(name)+1)) - { - return -1; - } - - typ = lua_msg_box("[D]estroy, [P]ickup, [I]nscribe?"); - - switch (typ) - { - case 'd': - case 'D': - action = AUTO_DESTROY; - break; - - case 'p': - case 'P': - action = AUTO_PICKUP; - break; - - case 'i': - case 'I': - { - char *i = NULL; - - action = AUTO_INSCRIBE; - - i = lua_input_box("Inscription?", 79); - if ((i == NULL) || (strlen(i) == 0)) - { - return -1; - } - - inscription = i; - - break; - } - - default: - return -1; - } - - /* Make rule */ - rule = rule_new(name, action, game_module_idx, NULL, inscription); - - /* Append to list of rules */ - return rules_append(rule); -} - -static void add_child(condition_type *current) -{ - condition_metadata *metadata = NULL; - - switch (current->match) - { - case M_NOT: - case M_EQUIPMENT: - case M_INVENTORY: - { - if (current->subcondition != NULL) - { - return; - } - - metadata = automatizer_select_condition_type(); - if (metadata == NULL) - { - return; - } - - current->subcondition = metadata->create_condition(); - break; - } - - case M_AND: - metadata = automatizer_select_condition_type(); - if (metadata == NULL) - { - return; - } - condition_and_add(current, metadata->create_condition()); - break; - - case M_OR: - metadata = automatizer_select_condition_type(); - if (metadata == NULL) - { - return; - } - condition_or_add(current, metadata->create_condition()); - break; - - default: - /* No other types of conditions have children */ - break; - } -} - -static int tree_indent = 0; -static int tree_write_out_y = 0; -static int tree_write_out_x = 0; -static int tree_write_out_h = 0; -static int tree_write_out_w = 0; -static int tree_write_y = 0; -static int tree_write_x = 0; -static int tree_write_off_x = 0; -static int tree_write_off_y = 0; - -static void tree_write(byte color, cptr line) -{ - cptr p = line; - - for (p = line; *p != '\0'; p++) - { - char c = *p; - int x = tree_write_x - tree_write_off_x + 3*tree_indent; - int y = tree_write_y - tree_write_off_y; - - if (c != '\n') - { - if ((y >= 0) && - (y < tree_write_out_h) && - (x >= 0) && - (x < tree_write_out_w)) - { - Term_putch(x + tree_write_out_x, - y + tree_write_out_y, - color, - c); - } - - tree_write_x += 1; - } - else - { - tree_write_x = 0; - tree_write_y += 1; - } - } -} - -static void display_condition(condition_type *condition) -{ - byte bcol = TERM_L_GREEN; - byte ecol = TERM_GREEN; - int i; - - assert(condition != NULL); - - /* If this condition is present in the cursor stack, - then we use the "active" colors. */ - for (i = 0; i < cursor_count; i++) - { - if (cursor_stack[i] == condition) - { - bcol = TERM_VIOLET; - ecol = TERM_VIOLET; - break; - } - } - - tree_indent++; - - switch (condition->match) - { - case M_INVENTORY: - case M_EQUIPMENT: - { - cptr where_s = (condition->match == M_INVENTORY) - ? "inventory" - : "equipment"; - - tree_write(ecol, "Something in your "); - tree_write(bcol, where_s); - tree_write(ecol, " matches the following:"); - tree_write(TERM_WHITE, "\n"); - break; - } - - case M_SKILL: - { - cptr skill_name = - s_info[condition->skill_range.skill_idx].name + s_name; - - tree_write(ecol, "Your skill in "); - tree_write(bcol, skill_name); - tree_write(ecol, " is from "); - tree_write(TERM_WHITE, format("%d", (int) condition->skill_range.min)); - tree_write(ecol, " to "); - tree_write(TERM_WHITE, format("%d", (int) condition->skill_range.max)); - tree_write(TERM_WHITE, "\n"); - break; - } - - case M_ABILITY: - { - cptr ability_name = - ab_info[condition->ability].name + ab_name; - - tree_write(ecol, "You have the "); - tree_write(bcol, ability_name); - tree_write(ecol, " ability"); - tree_write(TERM_WHITE, "\n"); - break; - } - - case M_LEVEL: - { - tree_write(ecol, "Your "); - tree_write(bcol, "level"); - tree_write(ecol, " is from "); - - tree_write(TERM_WHITE, format("%d", condition->level_range.min)); - tree_write(ecol, " to "); - tree_write(TERM_WHITE, format("%d", condition->level_range.max)); - tree_write(TERM_WHITE, "\n"); - break; - } - - case M_SVAL: - { - tree_write(ecol, "Its "); - tree_write(bcol, "sval"); - tree_write(ecol, " is from "); - tree_write(TERM_WHITE, format("%d", condition->sval_range.min)); - tree_write(ecol, " to "); - tree_write(TERM_WHITE, format("%d", condition->sval_range.max)); - tree_write(TERM_WHITE, "\n"); - break; - } - - case M_DISCOUNT: - { - tree_write(ecol, "Its "); - tree_write(bcol, "discount"); - tree_write(ecol, " is from "); - tree_write(TERM_WHITE, format("%d", condition->discount.min)); - tree_write(ecol, " to "); - tree_write(TERM_WHITE, format("%d", condition->discount.max)); - tree_write(TERM_WHITE, "\n"); - break; - } - - case M_AND: - { - struct sglib_condition_list_iterator it; - struct condition_list *child = NULL; - - tree_write(ecol, "All of the following are true:"); - tree_write(TERM_WHITE, "\n"); - - for (child = sglib_condition_list_it_init(&it, condition->conditions.c); - child != NULL; - child = sglib_condition_list_it_next(&it)) - { - display_condition(child->condition); - } - - break; - } - - case M_OR: - { - struct sglib_condition_list_iterator it; - struct condition_list *child = NULL; - - tree_write(ecol, "At least one of the following are true:"); - tree_write(TERM_WHITE, "\n"); - - for (child = sglib_condition_list_it_init(&it, condition->conditions.c); - child != NULL; - child = sglib_condition_list_it_next(&it)) - { - display_condition(child->condition); - } - - break; - } - - case M_NOT: - { - tree_write(ecol, "Negate the following:"); - tree_write(TERM_WHITE, "\n"); - display_condition(condition->subcondition); - break; - } - - case M_NAME: - { - tree_write(ecol, "Its "); - tree_write(bcol, "name"); - tree_write(ecol, " is \""); - tree_write(TERM_WHITE, condition->name); - tree_write(ecol, "\""); - tree_write(TERM_WHITE, "\n"); - break; - } - - case M_CONTAIN: - { - tree_write(ecol, "Its "); - tree_write(bcol, "name"); - tree_write(ecol, " contains \""); - tree_write(TERM_WHITE, condition->name); - tree_write(ecol, "\""); - tree_write(TERM_WHITE, "\n"); - break; - } - - case M_INSCRIBED: - { - tree_write(ecol, "It is "); - tree_write(bcol, "inscribed"); - tree_write(ecol, " with "); - tree_write(ecol, "\""); - tree_write(TERM_WHITE, condition->inscription); - tree_write(ecol, "\""); - tree_write(TERM_WHITE, "\n"); - break; - } - - case M_SYMBOL: - { - tree_write(ecol, "Its "); - tree_write(bcol, "symbol"); - tree_write(ecol, " is "); - tree_write(ecol, "\""); - tree_write(TERM_WHITE, format("%c", condition->symbol)); - tree_write(ecol, "\""); - tree_write(TERM_WHITE, "\n"); - break; - } - - case M_STATE: - { - tree_write(ecol, "Its "); - tree_write(bcol, "state"); - tree_write(ecol, " is "); - tree_write(ecol, "\""); - tree_write(TERM_WHITE, identification_state_to_string(condition->identification_state)); - tree_write(ecol, "\""); - tree_write(TERM_WHITE, "\n"); - break; - } - - case M_STATUS: - { - tree_write(ecol, "Its "); - tree_write(bcol, "status"); - tree_write(ecol, " is "); - tree_write(ecol, "\""); - tree_write(TERM_WHITE, status_to_string(condition->status)); - tree_write(ecol, "\""); - tree_write(TERM_WHITE, "\n"); - break; - } - - case M_TVAL: - { - tree_write(ecol, "Its "); - tree_write(bcol, "tval"); - tree_write(ecol, " is "); - tree_write(ecol, "\""); - tree_write(TERM_WHITE, format("%d", condition->tval)); - tree_write(ecol, "\""); - tree_write(TERM_WHITE, "\n"); - break; - } - - case M_RACE: - { - tree_write(ecol, "Player "); - tree_write(bcol, "race"); - tree_write(ecol, " is "); - tree_write(ecol, "\""); - tree_write(TERM_WHITE, condition->race); - tree_write(ecol, "\""); - tree_write(TERM_WHITE, "\n"); - break; - } - - case M_SUBRACE: - { - tree_write(ecol, "Player "); - tree_write(bcol, "subrace"); - tree_write(ecol, " is "); - tree_write(ecol, "\""); - tree_write(TERM_WHITE, condition->subrace); - tree_write(ecol, "\""); - tree_write(TERM_WHITE, "\n"); - break; - } - - case M_CLASS: - { - tree_write(ecol, "Player "); - tree_write(bcol, "class"); - tree_write(ecol, " is "); - tree_write(ecol, "\""); - tree_write(TERM_WHITE, condition->klass); - tree_write(ecol, "\""); - tree_write(TERM_WHITE, "\n"); - break; - } - - } - - tree_indent--; -} - -static void display_rule(arule_type *rule) -{ - cptr action_s; - int hgt, wid; - - action_s = action_to_string(rule->action); - - Term_get_size(&wid, &hgt); - - tree_write_out_y = 1; - tree_write_out_x = 16; - tree_write_out_h = hgt - 4 - 1; - tree_write_out_w = wid - 1 - 15 - 1; - tree_write_y = 0; - tree_write_x = 0; - - switch (rule->action) - { - case AUTO_DESTROY: - case AUTO_PICKUP: - { - tree_write(TERM_GREEN, "A rule named \""); - tree_write(TERM_WHITE, rule->name); - tree_write(TERM_GREEN, "\" to "); - tree_write(TERM_L_GREEN, action_s); - tree_write(TERM_GREEN, " when"); - tree_write(TERM_WHITE, "\n"); - break; - } - - case AUTO_INSCRIBE: - { - tree_write(TERM_GREEN, "A rule named \""); - tree_write(TERM_WHITE, rule->name); - tree_write(TERM_GREEN, "\" to "); - tree_write(TERM_L_GREEN, "inscribe"); - tree_write(TERM_GREEN, " an item with \""); - tree_write(TERM_WHITE, rule->inscription); - tree_write(TERM_GREEN, "\" when"); - tree_write(TERM_WHITE, "\n"); - break; - } - - } - - /* Write out the condition */ - if (rule->condition != NULL) - { - display_condition(rule->condition); - } -} - -static void adjust_current(int sel) -{ - if (rules_count == 0) - { - cursor_clear(); - return; - } - - tree_write_off_y = 0; - tree_write_off_x = 0; - - /* Put the top-level condition into cursor */ - cursor_clear(); - if (rules[sel]->condition != NULL) - { - cursor_push(rules[sel]->condition); - } -} - -static void tree_scroll_up() -{ - tree_write_off_y = tree_write_off_y - 1; -} - -static void tree_scroll_down() -{ - tree_write_off_y = tree_write_off_y + 1; -} - -static void tree_scroll_left() -{ - tree_write_off_x = tree_write_off_x + 1; -} - -static void tree_scroll_right() -{ - tree_write_off_x = tree_write_off_x - 1; -} - -static void automatizer_save_rules() -{ - char name[30] = { '\0' }; - char buf[1025]; - char ch; - int hgt, wid; - - Term_get_size(&wid, &hgt); - - sprintf(name, "automat.atm"); - if (!input_box("Save name?", hgt / 2, wid / 2, name, sizeof(name)+1)) - { - return; - } - - /* Build the filename */ - path_build(buf, 1024, ANGBAND_DIR_USER, name); - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - if (file_exist(buf)) - { - c_put_str(TERM_WHITE, "File exists, continue?[y/n]", - hgt / 2, - wid / 2 - 14); - ch = inkey(); - if ((ch != 'Y') && (ch != 'y')) - { - return; - } - } - - /* Write to file */ - { - json_t *rules_json = rules_to_json(); - int status = json_dump_file(rules_json, buf, JSON_INDENT(2) | JSON_SORT_KEYS); - if (status == 0) - { - c_put_str(TERM_WHITE, "Saved rules in file ", - hgt / 2, - wid / 2 - 14); - } - else - { - c_put_str(TERM_WHITE, "Saving rules failed! ", - hgt / 2, - wid / 2 - 14); - } - - /* Deallocate JSON */ - json_decref(rules_json); - - /* Wait for keypress */ - inkey(); - } -} - -static void rename_rule(arule_type *rule) -{ - char name[16]; - int wid, hgt; - - assert(rule != NULL); - - Term_get_size(&wid, &hgt); - - sprintf(name, "%s", rule->name); - if (input_box("New name?", hgt / 2, wid / 2, name, sizeof(name)-1)) - { - rule_set_name(rule, name); - } -} - -static void add_new_condition(arule_type *current_rule) -{ - /* Top-level condition? */ - if (current_rule->condition == NULL) - { - condition_metadata *metadata = NULL; - - /* Sanity check for navigation stack */ - assert(cursor_count == 0); - - /* Select type of clause */ - metadata = automatizer_select_condition_type(); - if (metadata == NULL) - { - return; - } - - /* Create the condition directly; we can - always add a top-level condition so there's - no need for the sanity checking in - add_child(). */ - current_rule->condition = metadata->create_condition(); - if (current_rule->condition != NULL) - { - cursor_push(current_rule->condition); - } - } - else - { - condition_type *current_condition = cursor_top(); - add_child(current_condition); - } -} - -static void tree_go_right() -{ - condition_type *top = cursor_top(); - - /* Can only go right if the currently selected condition - has children. */ - switch (top->match) - { - case M_AND: - case M_OR: - { - /* Pick first child */ - struct sglib_condition_list_iterator it; - condition_list *i = sglib_condition_list_it_init(&it, top->conditions.c); - /* Move right if possible */ - if (i != NULL) - { - cursor_push(i->condition); - } - break; - } - - case M_NOT: - case M_INVENTORY: - case M_EQUIPMENT: - { - if (top->subcondition != NULL) - { - cursor_push(top->subcondition); - } - break; - } - - default: - /* Not possible to move */ - break; - } -} - -static void tree_go_left() -{ - if (cursor_count > 1) - { - cursor_pop(); - } -} - -static void tree_go_up() -{ - if (cursor_count > 1) - { - condition_type *prev_top = cursor_pop(); - condition_type *top = cursor_top(); - - switch (top->match) - { - case M_AND: - case M_OR: - { - struct sglib_condition_list_iterator it; - condition_list *child = NULL; - condition_list *prev_child = NULL; - - /* We have a list of children */ - for (child = sglib_condition_list_it_init(&it, top->conditions.c); - child != NULL; - child = sglib_condition_list_it_next(&it)) - { - if (child->condition == prev_top) - { - /* Do we have a previous child? */ - if (prev_child == NULL) - { - /* No predecessor; don't move */ - cursor_push(prev_top); - break; - } - else - { - cursor_push(prev_child->condition); - break; /* Done */ - } - } - /* Keep track of previous child */ - prev_child = child; - } - - break; - } - - default: - { - /* No other match types have children; restore - original top. */ - cursor_push(prev_top); - break; - } - - } - } -} - -static void tree_go_down() -{ - if (cursor_count > 1) - { - condition_type *prev_top = cursor_pop(); - condition_type *top = cursor_top(); - - switch (top->match) - { - case M_AND: - case M_OR: - { - struct sglib_condition_list_iterator it; - condition_list *child = NULL; - - /* We have a list of children */ - for (child = sglib_condition_list_it_init(&it, top->conditions.c); - child != NULL; - child = sglib_condition_list_it_next(&it)) - { - if (child->condition == prev_top) - { - /* Move to next child (if any) */ - child = sglib_condition_list_it_next(&it); - if (child == NULL) - { - /* No successor; don't move */ - cursor_push(prev_top); - break; - } - else - { - cursor_push(child->condition); - break; /* Done */ - } - } - } - - break; - } - - default: - { - /* No other match types have multiple children; restore - original top. */ - cursor_push(prev_top); - break; - } - - } - } -} - -static int automatizer_del_self(int sel) -{ - /* If the cursor is at the top level then - we want to delete the rule itself */ - if (cursor_count < 1) - { - rules_remove(rules[sel]); - return sel - 1; /* Move selection up */ - } - else if (cursor_count == 1) - { - cursor_pop(); - condition_destroy(&rules[sel]->condition); - return sel; - } - else - { - condition_type *prev_top = cursor_pop(); - condition_type *top = cursor_top(); - - /* Jump up a level; this is a simple way to ensure a - valid cursor. We could be a little cleverer here by - trying to move inside the current level, but it's a - little complicated. */ - tree_go_left(); - - /* Now we can remove the condition from its parent */ - switch (top->match) - { - - case M_AND: - case M_OR: - { - struct sglib_condition_list_iterator it; - condition_list *item = NULL; - - /* We have a list of children */ - for (item = sglib_condition_list_it_init(&it, top->conditions.c); - item != NULL; - item = sglib_condition_list_it_next(&it)) - { - if (item->condition == prev_top) - { - /* Found */ - break; - } - } - - /* Must have found item; otherwise internal structure - is damaged. */ - assert (item != NULL); - sglib_condition_list_delete(&top->conditions.c, item); - - /* Destroy the condition */ - condition_destroy(&prev_top); - break; - } - - case M_NOT: - case M_EQUIPMENT: - case M_INVENTORY: - { - assert(top->subcondition != NULL); - condition_destroy(&top->subcondition); - break; - } - - default: - /* If we get here, something's wrong with the - navigation structures. */ - assert(FALSE); - break; - } - - /* Keep selection */ - return sel; - } -} - -#define ACTIVE_LIST 0 -#define ACTIVE_RULE 1 -void do_cmd_automatizer() -{ - int wid = 0, hgt = 0; - char c; - int max, begin = 0, sel = 0; - int active = ACTIVE_LIST; - cptr keys; - cptr keys2; - cptr keys3; - cptr rule_names[RULES_MAX]; - - Term_get_size(&wid, &hgt); - - if (!automatizer_enabled) - { - if (msg_box("Automatizer is currently disabled, enable it? (y/n)", hgt / 2, wid / 2) == 'y') - { - automatizer_enabled = TRUE; - } - else - return; - } - - screen_save(); - - adjust_current(sel); - - while (1) - { - Term_clear(); - Term_get_size(&wid, &hgt); - - max = rules_count; - get_rule_names(rule_names); - display_list(0, 0, hgt - 1, 15, "Rules", rule_names, max, begin, sel, (active == ACTIVE_LIST) ? TERM_L_GREEN : TERM_GREEN); - - draw_box(0, 15, hgt - 4, wid - 1 - 15); - if (active == ACTIVE_RULE) - { - keys = "#Bup#W/#Bdown#W/#Bleft#W/#Bright#W to navitage rule, #B9#W/#B3#W/#B7#W/#B1#W to scroll"; - keys2 = "#Btab#W for switch, #Ba#Wdd clause, #Bd#Welete clause/rule"; - keys3 = "#G?#W for Automatizer help"; - } - else - { - keys = "#Bup#W/#Bdown#W to scroll, #Btab#W to switch to the rule window"; - keys2 = "#Bu#W/#Bd#W to move rules, #Bn#Wew rule, #Br#Wename rule, #Bs#Wave rules"; - keys3 = "#Rk#W to #rdisable#W the automatizer, #G?#W for Automatizer help"; - } - display_message(17, hgt - 3, strlen(keys), TERM_WHITE, keys); - display_message(17, hgt - 2, strlen(keys2), TERM_WHITE, keys2); - display_message(17, hgt - 1, strlen(keys3), TERM_WHITE, keys3); - - if (max) - { - display_rule(rules[sel]); - } - - c = inkey(); - - if (c == ESCAPE) break; - if (active == ACTIVE_LIST) - { - if (c == '?') - { - screen_save(); - show_file("automat.txt", "Automatizer help", 0, 0); - screen_load(); - } - else if (c == '8') - { - if (!max) continue; - sel--; - adjust_begin(&begin, &sel, max, hgt); - adjust_current(sel); - } - else if (c == '2') - { - if (!max) continue; - sel++; - adjust_begin(&begin, &sel, max, hgt); - adjust_current(sel); - } - else if (c == 'u') - { - if (sel > 0) - { - rules_swap(sel-1, sel); - sel -= 1; - - adjust_begin(&begin, &sel, max, hgt); - adjust_current(sel); - } - } - else if (c == 'd') - { - if (!max) continue; - - if (sel < rules_count - 1) - { - rules_swap(sel, sel+1); - sel += 1; - - adjust_begin(&begin, &sel, max, hgt); - adjust_current(sel); - } - } - else if (c == 'n') - { - int i = create_new_rule(); - if (i >= 0) - { - sel = i; - adjust_current(sel); - active = ACTIVE_RULE; - } - } - else if (c == 's') - { - automatizer_save_rules(); - } - else if (c == 'r') - { - if (!max) continue; - - rename_rule(rules[sel]); - continue; - } - else if (c == 'k') - { - automatizer_enabled = FALSE; - break; - } - else if (c == '\t') - { - if (!max) continue; - active = ACTIVE_RULE; - } - } - else if (active == ACTIVE_RULE) - { - if (c == '?') - { - screen_save(); - show_file("automat.txt", "Automatizer help", 0, 0); - screen_load(); - } - else if (c == '8') - { - tree_go_up(); - } - else if (c == '2') - { - tree_go_down(); - } - else if (c == '6') - { - tree_go_right(); - } - else if (c == '4') - { - tree_go_left(); - } - else if (c == '9') - { - tree_scroll_up(); - } - else if (c == '3') - { - tree_scroll_down(); - } - else if (c == '7') - { - tree_scroll_left(); - } - else if (c == '1') - { - tree_scroll_right(); - } - else if (c == 'a') - { - add_new_condition(rules[sel]); - } - else if (c == 'd') - { - if (max) - { - int new_sel; - - new_sel = automatizer_del_self(sel); - if ((sel != new_sel) && (new_sel >= 0)) - { - sel = new_sel; - adjust_begin(&begin, &sel, max, hgt); - adjust_current(sel); - } - else if (new_sel == -1) - { - active = ACTIVE_LIST; - } - } - } - else if (c == '\t') - { - active = ACTIVE_LIST; - } - } - } - - screen_load(); -} - -static void easy_add_rule(action_type action, cptr mode, bool_ do_status, object_type *o_ptr) -{ - condition_type *condition = NULL; - - if (streq(mode, "tval")) - { - condition = condition_new_tval(o_ptr->tval); - } - else if (streq(mode, "tsval")) - { - condition_type *sval_condition = - condition_new_sval(o_ptr->sval, o_ptr->sval); - condition_type *tval_condition = - condition_new_tval(o_ptr->tval); - - condition = condition_new_and(); - condition_and_add(condition, tval_condition); - condition_and_add(condition, sval_condition); - } - else if (streq(mode, "name")) - { - char buf[128]; - object_desc(buf, o_ptr, -1, 0); - strlower(buf); - - condition = condition_new_name(buf); - } - - /* Use object status? */ - if (do_status == TRUE) - { - status_type status = object_status(o_ptr); - condition_type *status_condition = - condition_new_status(status); - condition_type *and_condition = - condition_new_and(); - - condition_and_add(and_condition, condition); - condition_and_add(and_condition, status_condition); - /* Replace condition */ - condition = and_condition; - } - - /* Build rule */ - { - static arule_type *rule = NULL; - /* Make rule */ - rule = rule_new(action_to_string(action), - action, - game_module_idx, - condition, - NULL); - - /* Append to list of rules */ - rules_append(rule); - } - - msg_print("Rule added. Please go to the Automatizer screen (press = then T)"); - msg_print("to save the modified ruleset."); -} - -/* Add a new rule in an easy way */ -bool_ automatizer_create = FALSE; -void automatizer_add_rule(object_type *o_ptr, bool_ destroy) -{ - char ch; - bool_ do_status = FALSE; - action_type action = AUTO_DESTROY; - - if (!destroy) - { - action = AUTO_PICKUP; - } - - while (TRUE) - { - if (!get_com(format("%s all of the same [T]ype, [F]amily or [N]ame, also use [S]tatus (%s)? ", (destroy) ? "Destroy" : "Pickup", (do_status) ? "Yes" : "No"), &ch)) - { - break; - } - - if (ch == 'S' || ch == 's') - { - do_status = !do_status; - continue; - } - - if (ch == 'T' || ch == 't') - { - easy_add_rule(action, "tsval", do_status, o_ptr); - break; - } - - if (ch == 'F' || ch == 'f') - { - easy_add_rule(action, "tval", do_status, o_ptr); - break; - } - - if (ch == 'N' || ch == 'n') - { - easy_add_rule(action, "name", do_status, o_ptr); - break; - } - } -} - -static condition_type *parse_condition(json_t *condition_json) -{ - cptr type_s = NULL; - match_type match; - - if ((condition_json == NULL) || json_is_null(condition_json)) - { - return NULL; - } - - if (json_unpack(condition_json, - "{s:s}", - "type", &type_s) < 0) - { - msg_print("Missing/invalid 'type' in condition"); - return NULL; - } - - if (!match_type_from_string(type_s, &match)) - { - msg_format("Invalid 'type' in condition: %s", type_s); - return NULL; - } - - switch (match) - { - case M_AND: - case M_OR: - { - json_t *conditions_j = json_object_get(condition_json, - "conditions"); - - if ((conditions_j == NULL) || - (json_is_null(conditions_j))) - { - return NULL; - } - else if (json_is_array(conditions_j)) - { - int i; - json_t *subcondition_j = NULL; - condition_type *condition = condition_new(match); - condition_type *subcondition = NULL; - - for (i = 0; i < json_array_size(conditions_j); i++) - { - subcondition_j = - json_array_get(conditions_j, i); - subcondition = - parse_condition(subcondition_j); - - if (subcondition != NULL) - { - condition_and_add(condition, subcondition); - } - } - - return condition; - } - else - { - msg_print("'conditions' property has invalid type"); - return NULL; - } - - break; - } - - case M_NOT: - case M_INVENTORY: - case M_EQUIPMENT: - { - json_t *condition_j = json_object_get(condition_json, - "condition"); - - if ((condition_j == NULL) || - (json_is_null(condition_j))) - { - return NULL; - } - else if (json_is_object(condition_j)) - { - condition_type *condition = - condition_new(match); - condition->subcondition = - parse_condition(condition_j); - return condition; - } - else - { - msg_print("Invlalid 'condition' property"); - return NULL; - } - } - - case M_NAME: - { - cptr s = NULL; - if (json_unpack(condition_json, - "{s:s}", - "name", &s) < 0) - { - msg_print("Missing/invalid 'name' property"); - return NULL; - } - - return condition_new_name(s); - } - - case M_CONTAIN: - { - cptr s = NULL; - if (json_unpack(condition_json, - "{s:s}", - "contain", &s) < 0) - { - msg_print("Missing/invalid 'contain' property"); - return NULL; - } - - return condition_new_contain(s); - } - - case M_SYMBOL: - { - cptr s = NULL; - int sl; - if (json_unpack(condition_json, "{s:s}", "symbol", &s) < 0) - { - msg_print("Missing/invalid 'symbol' property"); - return NULL; - } - - sl = strlen(s); - if (sl == 0) - { - msg_print("Invalid 'symbol' property: Too short"); - return NULL; - } - if (sl > 1) - { - msg_print("Invalid 'symbol' property: Too long"); - return NULL; - } - - return condition_new_symbol(s[0]); - } - - case M_INSCRIBED: - { - cptr s = NULL; - if (json_unpack(condition_json, "{s:s}", "inscription", &s) < 0) - { - msg_print("Missing/invalid 'inscription' property"); - return NULL; - } - - return condition_new_inscribed(s); - } - - case M_DISCOUNT: - { - int min, max; - - if (json_unpack(condition_json, "{s:i,s:i}", - "min", &min, - "max", &max) < 0) - { - msg_print("Missing/invalid 'min'/'max' properties"); - return NULL; - } - - return condition_new_discount(min, max); - } - - case M_TVAL: - { - int tval; - - if (json_unpack(condition_json, "{s:i}", "tval", &tval) < 0) - { - msg_print("Missing/invalid 'tval' property"); - return NULL; - } - - return condition_new_tval(tval); - } - - case M_SVAL: - { - int min, max; - - if (json_unpack(condition_json, "{s:i,s:i}", - "min", &min, - "max", &max) < 0) - { - msg_print("Missing/invalid 'min'/'max' properties"); - return NULL; - } - - return condition_new_sval(min, max); - } - - case M_STATUS: - { - cptr s; - status_type status; - - if (json_unpack(condition_json, "{s:s}", "status", &s) < 0) - { - msg_print("Missing/invalid 'status' property"); - return NULL; - } - - if (!status_from_string(s, &status)) - { - msg_format("Invalid 'status' property: %s", s); - return NULL; - } - - return condition_new_status(status); - } - - case M_STATE: - { - cptr s; - identification_state state; - - if (json_unpack(condition_json, "{s:s}", "state", &s) < 0) - { - msg_print("Missing/invalid 'state' property"); - return NULL; - } - - if (!identification_state_from_string(s, &state)) - { - msg_format("Invalid 'state' property: %s", s); - return NULL; - } - - return condition_new_state(state); - } - - case M_RACE: - { - cptr s; - - if (json_unpack(condition_json, "{s:s}", "race", &s) < 0) - { - msg_print("Missing/invalid 'race' property"); - return NULL; - } - - return condition_new_race(s); - } - - case M_SUBRACE: - { - cptr s; - - if (json_unpack(condition_json, "{s:s}", "subrace", &s) < 0) - { - msg_print("Missing/invalid 'subrace' property"); - return NULL; - } - - return condition_new_subrace(s); - } - - case M_CLASS: - { - cptr s; - - if (json_unpack(condition_json, "{s:s}", "class", &s) < 0) - { - msg_print("Missing/invalid 'class' property"); - return NULL; - } - - return condition_new_class(s); - } - - case M_LEVEL: - { - int min, max; - - if (json_unpack(condition_json, "{s:i,s:i}", - "min", &min, - "max", &max) < 0) - { - msg_print("Missing/invalid 'min'/'max' properties"); - return NULL; - } - - return condition_new_level(min, max); - } - - case M_SKILL: - { - cptr s; - s16b si; - int min, max; - - if (json_unpack(condition_json, "{s:i,s:i,s:s}", - "min", &min, - "max", &max, - "name", &s) < 0) - { - msg_print("Missing/invalid 'min'/'max'/'name' properties"); - return NULL; - } - - si = find_skill_i(s); - if (si < 0) - { - msg_print("Invalid 'name' property"); - return NULL; - } - - return condition_new_skill(min, max, si); - } - - case M_ABILITY: - { - cptr a; - s16b ai; - - if (json_unpack(condition_json, "{s:s}", - "ability", &a) < 0) - { - msg_print("Missing/invalid 'ability' property"); - return NULL; - } - - ai = find_ability(a); - if (ai < 0) - { - msg_print("Invalid 'ability' property"); - return NULL; - } - - return condition_new_ability(ai); - } - - } - - /* Could not parse */ - return NULL; -} - -static void parse_rule(json_t *rule_json) -{ - char *rule_name_s = NULL; - char *rule_action_s = NULL; - char *rule_module_s = NULL; - json_t *rule_inscription_j = NULL; - arule_type *rule = NULL; - action_type action; - int module_idx; - - if (!json_is_object(rule_json)) - { - msg_print("Rule is not an object"); - return; - } - - /* Retrieve the attributes */ - if (json_unpack(rule_json, - "{s:s,s:s,s:s}", - "name", &rule_name_s, - "action", &rule_action_s, - "module", &rule_module_s) < 0) - { - msg_print("Rule missing required field(s)"); - return; - } - - /* Get the optional inscription */ - rule_inscription_j = json_object_get(rule_json, "inscription"); - - /* Convert attributes */ - if (!action_from_string((cptr) rule_action_s, &action)) - { - msg_format("Invalid rule action '%s'", rule_action_s); - return; - } - - module_idx = find_module((cptr) rule_module_s); - if (module_idx < 0) - { - msg_format("Skipping rule for unrecognized module '%s'", - (cptr) rule_module_s); - return; - } - - /* Sanity check: Inscription */ - if (action == AUTO_INSCRIBE) - { - if (rule_inscription_j == NULL) - { - msg_print("Inscription rule missing 'inscription' attribute"); - return; - } - if (!json_is_string(rule_inscription_j)) - { - msg_print("Inscription rule 'inscription' attribute wrong type"); - return; - } - } - - /* Create rule */ - rule = rule_new(rule_name_s, - action, - module_idx, - NULL, - json_string_value(rule_inscription_j)); - rules_append(rule); - - /* Parse the conditions */ - rule->condition = parse_condition(json_object_get(rule_json, "condition")); -} - -static void parse_rules(json_t *rules) -{ - int i; - - if (!json_is_array(rules)) - { - msg_format("Error 'rules' is not an array"); - return; - } - - for (i = 0; i < json_array_size(rules); i++) - { - json_t *rule = json_array_get(rules, i); - parse_rule(rule); - } -} - -/** - * Initialize the automatizer. This function may be called multiple - * times with different file names -- it should NOT clear any - * automatizer state (including loaded rules). - */ -void automatizer_init(cptr file_path) -{ - json_t *rules_json = NULL; - json_error_t error; - - /* Does the file exist? */ - if (!file_exist(file_path)) - { - /* No big deal, we'll just skip */ - goto out; - } - - /* Parse file */ - rules_json = json_load_file(file_path, 0, &error); - if (rules_json == NULL) - { - msg_format("Error parsing automatizer rules from '%s'.", file_path); - msg_format("Line %d, Column %d", error.line, error.column); - msg_print(NULL); - goto out; - } - - /* Go through all the found rules */ - parse_rules(rules_json); - -out: - if (rules_json == NULL) - { - json_decref(rules_json); - } -} diff --git a/src/squeltch.cc b/src/squeltch.cc new file mode 100644 index 00000000..560b3d01 --- /dev/null +++ b/src/squeltch.cc @@ -0,0 +1,598 @@ +/* File: squeltch.c */ + +/* Purpose: Automatizer */ + +/* + * Copyright (c) 2002 DarkGod + * Copyright (c) 2012 Bardur Arantsson + * + * This software may be copied and distributed for educational, research, and + * not for profit purposes provided that this copyright and statement are + * included in all such copies. + */ + +#include "angband.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "tome/squelch/tree_printer.hpp" +#include "tome/squelch/condition.hpp" +#include "tome/squelch/condition_metadata.hpp" +#include "tome/squelch/rule.hpp" +#include "tome/squelch/cursor.hpp" +#include "tome/squelch/object_status.hpp" +#include "tome/squelch/automatizer.hpp" + +using squelch::action_type; +using squelch::action_mapping; + +using squelch::status_type; + +using squelch::Rule; +using squelch::DestroyRule; +using squelch::PickUpRule; +using squelch::InscribeRule; + +using squelch::Condition; +using squelch::AndCondition; +using squelch::TvalCondition; +using squelch::SvalCondition; +using squelch::NameCondition; +using squelch::StatusCondition; + +static squelch::Automatizer *automatizer = nullptr; + +void squeltch_grid(void) +{ + if (!automatizer_enabled) + { + return; + } + + // Scan the pile of objects + s16b next_o_idx = 0; + for (s16b this_o_idx = cave[p_ptr->py][p_ptr->px].o_idx; + this_o_idx; + this_o_idx = next_o_idx) + { + // Acquire object + object_type * o_ptr = &o_list[this_o_idx]; + + // We've now seen one of these + if (!k_info[o_ptr->k_idx].flavor) + { + object_aware(o_ptr); + } + + // Acquire next object + next_o_idx = o_ptr->next_o_idx; + + // Apply rules + automatizer->apply_rules(o_ptr, -this_o_idx); + } +} + +void squeltch_inventory(void) +{ + if (!automatizer_enabled) + { + return; + } + + for (int num_iter = 0; num_iter < 100; num_iter++) + { + for (int i = 0; i < INVEN_PACK; i++) + { + object_type *o_ptr = &p_ptr->inventory[i]; + if (automatizer->apply_rules(o_ptr, i)) + { + return; + } + } + } + + cmsg_format(TERM_VIOLET, "'apply_rules' ran too often."); +} + +static int create_new_rule() +{ + char name[20] = { '\0' }; + int wid = 0, hgt = 0; + + Term_get_size(&wid, &hgt); + + sprintf(name, "%s", "No name"); + if (!input_box("Name?", hgt / 2, wid / 2, name, sizeof(name)+1)) + { + return -1; + } + + char typ = lua_msg_box("[D]estroy, [P]ickup, [I]nscribe?"); + + std::shared_ptr rule; + switch (typ) + { + case 'd': + case 'D': + rule = std::make_shared(name, game_module_idx, nullptr); + break; + + case 'p': + case 'P': + rule = std::make_shared(name, game_module_idx, nullptr); + break; + + case 'i': + case 'I': + { + cptr i = lua_input_box("Inscription?", 79); + if ((i == nullptr) || (strlen(i) == 0)) + { + return -1; + } + + rule = std::make_shared( + name, game_module_idx, nullptr, std::string(i)); + + break; + } + + default: + return -1; + } + + return automatizer->append_rule(rule); +} + +static void automatizer_save_rules() +{ + char name[30] = { '\0' }; + char buf[1025]; + char ch; + int hgt, wid; + + Term_get_size(&wid, &hgt); + + sprintf(name, "automat.atm"); + if (!input_box("Save name?", hgt / 2, wid / 2, name, sizeof(name)+1)) + { + return; + } + + // Build the filename + path_build(buf, 1024, ANGBAND_DIR_USER, name); + + // File type is "TEXT" + FILE_TYPE(FILE_TYPE_TEXT); + + if (file_exist(buf)) + { + c_put_str(TERM_WHITE, "File exists, continue?[y/n]", + hgt / 2, + wid / 2 - 14); + ch = inkey(); + if ((ch != 'Y') && (ch != 'y')) + { + return; + } + } + + // Write to file + { + auto rules_json = automatizer->to_json(); + + int status = json_dump_file(rules_json.get(), buf, + JSON_INDENT(2) | + JSON_SORT_KEYS); + if (status == 0) + { + c_put_str(TERM_WHITE, "Saved rules in file ", + hgt / 2, + wid / 2 - 14); + } + else + { + c_put_str(TERM_WHITE, "Saving rules failed! ", + hgt / 2, + wid / 2 - 14); + } + + // Wait for keypress + inkey(); + } +} + +static void rename_rule(Rule *rule) +{ + char name[16]; + int wid, hgt; + + assert(rule != nullptr); + + Term_get_size(&wid, &hgt); + + sprintf(name, "%s", rule->get_name()); + if (input_box("New name?", hgt / 2, wid / 2, name, sizeof(name)-1)) + { + rule->set_name(name); + } +} + +#define ACTIVE_LIST 0 +#define ACTIVE_RULE 1 +void do_cmd_automatizer() +{ + int wid = 0, hgt = 0; + int active = ACTIVE_LIST; + cptr keys; + cptr keys2; + cptr keys3; + std::vector rule_names; + + Term_get_size(&wid, &hgt); + + if (!automatizer_enabled) + { + if (msg_box("Automatizer is currently disabled, enable it? (y/n)", hgt / 2, wid / 2) == 'y') + { + automatizer_enabled = TRUE; + } + else + return; + } + + screen_save(); + + automatizer->reset_view(); + + while (1) + { + Term_clear(); + Term_get_size(&wid, &hgt); + + automatizer->get_rule_names(&rule_names); + + display_list(0, 0, hgt - 1, 15, "Rules", rule_names.data(), automatizer->rules_count(), automatizer->rules_begin(), automatizer->selected_rule(), (active == ACTIVE_LIST) ? TERM_L_GREEN : TERM_GREEN); + + draw_box(0, 15, hgt - 4, wid - 1 - 15); + if (active == ACTIVE_RULE) + { + keys = "#Bup#W/#Bdown#W/#Bleft#W/#Bright#W to navitage rule, #B9#W/#B3#W/#B7#W/#B1#W to scroll"; + keys2 = "#Btab#W for switch, #Ba#Wdd clause, #Bd#Welete clause/rule"; + keys3 = "#G?#W for Automatizer help"; + } + else + { + keys = "#Bup#W/#Bdown#W to scroll, #Btab#W to switch to the rule window"; + keys2 = "#Bu#W/#Bd#W to move rules, #Bn#Wew rule, #Br#Wename rule, #Bs#Wave rules"; + keys3 = "#Rk#W to #rdisable#W the automatizer, #G?#W for Automatizer help"; + } + display_message(17, hgt - 3, strlen(keys), TERM_WHITE, keys); + display_message(17, hgt - 2, strlen(keys2), TERM_WHITE, keys2); + display_message(17, hgt - 1, strlen(keys3), TERM_WHITE, keys3); + + automatizer->show_current(); + + char c = inkey(); + + if (c == ESCAPE) break; + if (active == ACTIVE_LIST) + { + if (c == '?') + { + screen_save(); + show_file("automat.txt", "Automatizer help", 0, 0); + screen_load(); + } + else if (c == '8') + { + if (!automatizer->rules_count()) continue; + + automatizer->select_rule( + automatizer->selected_rule() - 1); + } + else if (c == '2') + { + if (!automatizer->rules_count()) continue; + + automatizer->select_rule( + automatizer->selected_rule() + 1); + } + else if (c == 'u') + { + int sel = automatizer->selected_rule(); + if (sel > 0) + { + automatizer->swap_rules(sel-1, sel); + automatizer->select_rule(sel-1); + } + } + else if (c == 'd') + { + if (!automatizer->rules_count()) continue; + + int sel = automatizer->selected_rule(); + if (sel < automatizer->rules_count() - 1) + { + automatizer->swap_rules(sel, sel+1); + automatizer->select_rule(sel+1); + } + } + else if (c == 'n') + { + int i = create_new_rule(); + if (i >= 0) + { + automatizer->select_rule(i); + active = ACTIVE_RULE; + } + } + else if (c == 's') + { + automatizer_save_rules(); + } + else if (c == 'r') + { + if (!automatizer->rules_count()) continue; + + rename_rule(automatizer->current_rule().get()); + continue; + } + else if (c == 'k') + { + automatizer_enabled = FALSE; + break; + } + else if (c == '\t') + { + if (!automatizer->rules_count()) continue; + + active = ACTIVE_RULE; + } + } + else if (active == ACTIVE_RULE) + { + if (c == '?') + { + screen_save(); + show_file("automat.txt", "Automatizer help", 0, 0); + screen_load(); + } + else if (c == '8') + { + automatizer->move_up(); + } + else if (c == '2') + { + automatizer->move_down(); + } + else if (c == '6') + { + automatizer->move_right(); + } + else if (c == '4') + { + automatizer->move_left(); + } + else if (c == '9') + { + automatizer->scroll_up(); + } + else if (c == '3') + { + automatizer->scroll_down(); + } + else if (c == '7') + { + automatizer->scroll_left(); + } + else if (c == '1') + { + automatizer->scroll_right(); + } + else if (c == 'a') + { + automatizer->add_new_condition( + squelch::new_condition_interactive); + } + else if (c == 'd') + { + if (!automatizer->rules_count()) + { + continue; + } + + int new_sel = + automatizer->remove_current_selection(); + + if (new_sel == -1) + { + active = ACTIVE_LIST; + } + } + else if (c == '\t') + { + active = ACTIVE_LIST; + } + } + } + + screen_load(); +} + +enum class add_rule_mode { TVAL, TSVAL, NAME }; + +static void easy_add_rule(action_type action, add_rule_mode mode, bool do_status, object_type *o_ptr) +{ + std::shared_ptr condition; + + switch (mode) + { + + case add_rule_mode::TVAL: + condition = std::make_shared(o_ptr->tval); + break; + + case add_rule_mode::TSVAL: + { + auto andCondition = std::make_shared(); + + andCondition->add_condition( + std::make_shared(o_ptr->tval)); + andCondition->add_condition( + std::make_shared(o_ptr->sval, o_ptr->sval)); + + condition = andCondition; + break; + } + + case add_rule_mode::NAME: + { + char buf[128]; + object_desc(buf, o_ptr, -1, 0); + + condition = std::make_shared(buf); + break; + } + + } + + // Use object status? + if (do_status) + { + status_type status = squelch::object_status(o_ptr); + + auto andCondition = std::make_shared(); + + andCondition->add_condition( + std::shared_ptr(condition)); // cycle + andCondition->add_condition( + std::make_shared(status)); + + // Replace condition; breaks cycle + condition = andCondition; + } + + // Rule name + auto rule_name = action_mapping().stringify(action); + + // Append to list of rules + switch (action) + { + case action_type::AUTO_DESTROY: + automatizer->append_rule( + std::make_shared( + rule_name, game_module_idx, condition)); + break; + + case action_type::AUTO_PICKUP: + automatizer->append_rule( + std::make_shared( + rule_name, game_module_idx, condition)); + break; + + case action_type::AUTO_INSCRIBE: + assert(false); + break; + } + + msg_print("Rule added. Please go to the Automatizer screen (press = then T)"); + msg_print("to save the modified ruleset."); +} + +void automatizer_add_rule(object_type *o_ptr, bool_ destroy) +{ + bool do_status = false; + action_type action = destroy + ? action_type::AUTO_DESTROY + : action_type::AUTO_PICKUP; + + while (true) + { + char ch; + + if (!get_com(format("%s all of the same [T]ype, [F]amily or [N]ame, also use [S]tatus (%s)? ", (destroy) ? "Destroy" : "Pickup", (do_status) ? "Yes" : "No"), &ch)) + { + break; + } + + if (ch == 'S' || ch == 's') + { + do_status = !do_status; + continue; + } + + if (ch == 'T' || ch == 't') + { + easy_add_rule(action, add_rule_mode::TSVAL, do_status, o_ptr); + break; + } + + if (ch == 'F' || ch == 'f') + { + easy_add_rule(action, add_rule_mode::TVAL, do_status, o_ptr); + break; + } + + if (ch == 'N' || ch == 'n') + { + easy_add_rule(action, add_rule_mode::NAME, do_status, o_ptr); + break; + } + } +} + +/** + * Initialize the automatizer. + */ +void automatizer_init() +{ + // Only permit single initialization. + assert(automatizer == nullptr); + + // Set up dependencies + auto tree_printer(std::make_shared()); + auto cursor(std::make_shared()); + + // Initialize + automatizer = new squelch::Automatizer(tree_printer, cursor); +} + +/** + * Load automatizer file. This function may be called multiple times + * with different file names -- it should NOT clear any automatizer + * state (including loaded rules). + */ +void automatizer_load(cptr file_path) +{ + assert(file_path != NULL); + assert(automatizer != NULL); + + // Does the file exist? + if (!file_exist(file_path)) + { + return; // Not fatal; just skip + } + + // Parse file + json_error_t error; + std::shared_ptr rules_json( + json_load_file(file_path, 0, &error), + &json_decref); + if (rules_json == nullptr) + { + msg_format("Error parsing automatizer rules from '%s'.", file_path); + msg_format("Line %d, Column %d", error.line, error.column); + msg_print(nullptr); + return; + } + + // Load rules + automatizer->load_json(rules_json.get()); +} diff --git a/src/variable.c b/src/variable.c index ac67e308..a921432c 100644 --- a/src/variable.c +++ b/src/variable.c @@ -1405,6 +1405,7 @@ bool_ option_ingame_help = TRUE; * Automatizer enabled status */ bool_ automatizer_enabled = FALSE; +bool_ automatizer_create = FALSE; /* * Location of the last teleportation thath affected the level -- cgit v1.2.3 From 1014b3342b9a61a5477b06b566271b5216edbbe3 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 17:54:01 +0100 Subject: Split library quest from plots.c --- src/CMakeLists.txt | 2 +- src/bldg.c | 1 + src/plots.c | 3 --- src/plots.h | 5 ----- src/q_library.c | 4 +++- src/q_library.h | 15 +++++++++++++++ src/tables.c | 1 + 7 files changed, 21 insertions(+), 10 deletions(-) create mode 100644 src/q_library.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7f84a2d0..a7ae81ef 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,7 +10,7 @@ SET(SRCS z-rand.c z-util.c z-form.c z-virt.c z-term.c variable.c tables.c plots.c util.c cave.c dungeon.c melee1.c melee2.c messages.c modules.c - q_god.c + q_god.c q_library.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/bldg.c b/src/bldg.c index 6b785d2a..920f297f 100644 --- a/src/bldg.c +++ b/src/bldg.c @@ -14,6 +14,7 @@ */ #include "angband.h" +#include "q_library.h" /* hack as in leave_store in store.c */ static bool_ leave_bldg = FALSE; diff --git a/src/plots.c b/src/plots.c index afc59350..6399c436 100644 --- a/src/plots.c +++ b/src/plots.c @@ -396,8 +396,5 @@ bool_ quest_null_hook(int q) /*************************** Bounty Quest *************************/ #include "q_bounty.c" -/************************** Library Quest *************************/ -#include "q_library.c" - /************************* Fireproofing Quest *********************/ #include "q_fireprof.c" diff --git a/src/plots.h b/src/plots.h index 91115856..a0b96189 100644 --- a/src/plots.h +++ b/src/plots.h @@ -53,11 +53,6 @@ extern bool_ quest_bounty_drop_item(); extern bool_ quest_bounty_get_item(); extern bool_ quest_bounty_describe(FILE *fff); -/******* Plot Library Quest *******/ -extern bool_ quest_library_init_hook(int q); -extern bool_ quest_library_describe(FILE *fff); -extern void quest_library_building(bool_ *paid, bool_ *recreate); - /******* Plot Fireproof Quest *********/ extern void quest_fireproof_building(bool_ *paid, bool_ *recreate); extern bool_ quest_fireproof_init_hook(int q); diff --git a/src/q_library.c b/src/q_library.c index bbbcae4c..6e412719 100644 --- a/src/q_library.c +++ b/src/q_library.c @@ -1,4 +1,6 @@ -#undef cquest +#include "q_library.h" +#include "quark.h" + #define cquest (quest[QUEST_LIBRARY]) #define print_hook(fmt,...) do { fprintf(hook_file, fmt, ##__VA_ARGS__); } while (0) diff --git a/src/q_library.h b/src/q_library.h new file mode 100644 index 00000000..24504282 --- /dev/null +++ b/src/q_library.h @@ -0,0 +1,15 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_library_init_hook(int q); +bool_ quest_library_describe(FILE *fff); +void quest_library_building(bool_ *paid, bool_ *recreate); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index 1d5f1c49..bffc0fb2 100644 --- a/src/tables.c +++ b/src/tables.c @@ -11,6 +11,7 @@ */ #include "angband.h" +#include "q_library.h" -- cgit v1.2.3 From fb0511aaa96c7a6089f39508703a8e0479b709f1 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 18:04:40 +0100 Subject: Split fireproofing quest from plots.c --- src/CMakeLists.txt | 2 +- src/bldg.c | 1 + src/externs.h | 2 ++ src/plots.c | 9 ++++++--- src/plots.h | 5 ----- src/q_fireprof.c | 7 ++++--- src/q_fireprof.h | 15 +++++++++++++++ src/tables.c | 1 + 8 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 src/q_fireprof.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a7ae81ef..ea4206e1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,7 +10,7 @@ SET(SRCS z-rand.c z-util.c z-form.c z-virt.c z-term.c variable.c tables.c plots.c util.c cave.c dungeon.c melee1.c melee2.c messages.c modules.c - q_god.c q_library.c + q_god.c q_library.c q_fireprof.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/bldg.c b/src/bldg.c index 920f297f..b17e8130 100644 --- a/src/bldg.c +++ b/src/bldg.c @@ -15,6 +15,7 @@ #include "angband.h" #include "q_library.h" +#include "q_fireprof.h" /* hack as in leave_store in store.c */ static bool_ leave_bldg = FALSE; diff --git a/src/externs.h b/src/externs.h index 97e886a0..11bdc3f3 100644 --- a/src/externs.h +++ b/src/externs.h @@ -573,6 +573,8 @@ extern void add_hook_script(int h_idx, char *script, cptr name); extern void del_hook(int h_idx, hook_type hook); extern void del_hook_name(int h_idx, cptr name); extern s32b get_next_arg(char *fmt); +extern char* get_next_arg_str(char *fmt); +extern object_type *get_next_arg_obj(); extern int process_hooks_restart; extern hook_return process_hooks_return[20]; extern bool_ process_hooks_ret(int h_idx, char *ret, char *fmt, ...); diff --git a/src/plots.c b/src/plots.c index 6399c436..376cd8d6 100644 --- a/src/plots.c +++ b/src/plots.c @@ -205,6 +205,12 @@ char* get_next_arg_str(char *fmt) } } } +object_type* get_next_arg_obj() { + object_type *o_ptr = param_pile[get_next_arg_pile_pos++].o_ptr; + assert(o_ptr != NULL); + return o_ptr; +} + /* Actually process the hooks */ int process_hooks_restart = FALSE; @@ -395,6 +401,3 @@ bool_ quest_null_hook(int q) /*************************** Bounty Quest *************************/ #include "q_bounty.c" - -/************************* Fireproofing Quest *********************/ -#include "q_fireprof.c" diff --git a/src/plots.h b/src/plots.h index a0b96189..211fdbb3 100644 --- a/src/plots.h +++ b/src/plots.h @@ -53,11 +53,6 @@ extern bool_ quest_bounty_drop_item(); extern bool_ quest_bounty_get_item(); extern bool_ quest_bounty_describe(FILE *fff); -/******* Plot Fireproof Quest *********/ -extern void quest_fireproof_building(bool_ *paid, bool_ *recreate); -extern bool_ quest_fireproof_init_hook(int q); -extern bool_ quest_fireproof_describe(FILE *fff); - /******* Plot God Quest **************/ extern bool_ quest_god_describe(FILE *); extern bool_ quest_god_init_hook(int q); diff --git a/src/q_fireprof.c b/src/q_fireprof.c index 3afa348f..e252af4f 100644 --- a/src/q_fireprof.c +++ b/src/q_fireprof.c @@ -1,4 +1,6 @@ -#undef cquest +#include "q_fireprof.h" +#include "quark.h" + #define cquest (quest[QUEST_FIREPROOF]) #define print_hook(fmt,...) do { fprintf(hook_file, fmt, ##__VA_ARGS__); } while (0) @@ -379,8 +381,7 @@ void quest_fireproof_building(bool_ *paid, bool_ *recreate) static bool_ fireproof_get_hook(char *fmt) { - object_type *o_ptr = param_pile[0].o_ptr; - assert(o_ptr != NULL); + object_type *o_ptr = get_next_arg_obj(); /* check that player is in the quest, haven't picked up the * item already, and check that it's the real item and not another one diff --git a/src/q_fireprof.h b/src/q_fireprof.h new file mode 100644 index 00000000..eb6a048c --- /dev/null +++ b/src/q_fireprof.h @@ -0,0 +1,15 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern void quest_fireproof_building(bool_ *paid, bool_ *recreate); +extern bool_ quest_fireproof_init_hook(int q); +extern bool_ quest_fireproof_describe(FILE *fff); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index bffc0fb2..af3e2764 100644 --- a/src/tables.c +++ b/src/tables.c @@ -12,6 +12,7 @@ #include "angband.h" #include "q_library.h" +#include "q_fireprof.h" -- cgit v1.2.3 From ad687f1dab21fee379ccf70fbe4fc27c2e66409f Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 18:09:59 +0100 Subject: Split bounty hunter quest from plots.c --- src/CMakeLists.txt | 2 +- src/bldg.c | 1 + src/plots.c | 3 --- src/plots.h | 6 ------ src/q_bounty.c | 3 ++- src/q_bounty.h | 17 +++++++++++++++++ src/tables.c | 1 + 7 files changed, 22 insertions(+), 11 deletions(-) create mode 100644 src/q_bounty.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ea4206e1..a5316cb4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,7 +10,7 @@ SET(SRCS z-rand.c z-util.c z-form.c z-virt.c z-term.c variable.c tables.c plots.c util.c cave.c dungeon.c melee1.c melee2.c messages.c modules.c - q_god.c q_library.c q_fireprof.c + q_god.c q_library.c q_fireprof.c q_bounty.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/bldg.c b/src/bldg.c index b17e8130..a182df65 100644 --- a/src/bldg.c +++ b/src/bldg.c @@ -16,6 +16,7 @@ #include "angband.h" #include "q_library.h" #include "q_fireprof.h" +#include "q_bounty.h" /* hack as in leave_store in store.c */ static bool_ leave_bldg = FALSE; diff --git a/src/plots.c b/src/plots.c index 376cd8d6..668d04ce 100644 --- a/src/plots.c +++ b/src/plots.c @@ -398,6 +398,3 @@ bool_ quest_null_hook(int q) /*************************** Other plot ***************************/ #include "q_narsil.c" #include "q_thrain.c" - -/*************************** Bounty Quest *************************/ -#include "q_bounty.c" diff --git a/src/plots.h b/src/plots.h index 211fdbb3..df3cc927 100644 --- a/src/plots.h +++ b/src/plots.h @@ -47,12 +47,6 @@ extern bool_ quest_evil_init_hook(int q_idx); extern bool_ quest_narsil_init_hook(int q_idx); extern bool_ quest_thrain_init_hook(int q_idx); -/******* Plot Bounty Quest ********/ -extern bool_ quest_bounty_init_hook(int q_idx); -extern bool_ quest_bounty_drop_item(); -extern bool_ quest_bounty_get_item(); -extern bool_ quest_bounty_describe(FILE *fff); - /******* Plot God Quest **************/ extern bool_ quest_god_describe(FILE *); extern bool_ quest_god_init_hook(int q); diff --git a/src/q_bounty.c b/src/q_bounty.c index 01b119be..b7cd150e 100644 --- a/src/q_bounty.c +++ b/src/q_bounty.c @@ -1,4 +1,5 @@ -#undef cquest +#include "q_bounty.h" + #define cquest (quest[QUEST_BOUNTY]) #define bounty_quest_monster (cquest.data[0]) diff --git a/src/q_bounty.h b/src/q_bounty.h new file mode 100644 index 00000000..c0a4027c --- /dev/null +++ b/src/q_bounty.h @@ -0,0 +1,17 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/******* Plot Bounty Quest ********/ +extern bool_ quest_bounty_init_hook(int q_idx); +extern bool_ quest_bounty_drop_item(); +extern bool_ quest_bounty_get_item(); +extern bool_ quest_bounty_describe(FILE *fff); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index af3e2764..82ccdb9e 100644 --- a/src/tables.c +++ b/src/tables.c @@ -13,6 +13,7 @@ #include "angband.h" #include "q_library.h" #include "q_fireprof.h" +#include "q_bounty.h" -- cgit v1.2.3 From 7ab6f5007e8a4db9f2f19fd9a88347adfc36dcd9 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 18:14:18 +0100 Subject: Split Thrain quest from plots.c --- src/CMakeLists.txt | 2 +- src/plots.c | 1 - src/plots.h | 1 - src/q_thrain.c | 5 ++++- src/q_thrain.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 src/q_thrain.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a5316cb4..bd706b04 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,7 +10,7 @@ SET(SRCS z-rand.c z-util.c z-form.c z-virt.c z-term.c variable.c tables.c plots.c util.c cave.c dungeon.c melee1.c melee2.c messages.c modules.c - q_god.c q_library.c q_fireprof.c q_bounty.c + q_god.c q_library.c q_fireprof.c q_bounty.c q_thrain.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index 668d04ce..db0d1096 100644 --- a/src/plots.c +++ b/src/plots.c @@ -397,4 +397,3 @@ bool_ quest_null_hook(int q) /*************************** Other plot ***************************/ #include "q_narsil.c" -#include "q_thrain.c" diff --git a/src/plots.h b/src/plots.h index df3cc927..7b2396ec 100644 --- a/src/plots.h +++ b/src/plots.h @@ -45,7 +45,6 @@ extern bool_ quest_evil_init_hook(int q_idx); /******* Plot Other *********/ extern bool_ quest_narsil_init_hook(int q_idx); -extern bool_ quest_thrain_init_hook(int q_idx); /******* Plot God Quest **************/ extern bool_ quest_god_describe(FILE *); diff --git a/src/q_thrain.c b/src/q_thrain.c index 6180706c..1b505a20 100644 --- a/src/q_thrain.c +++ b/src/q_thrain.c @@ -1,4 +1,7 @@ -#undef cquest +#include "q_thrain.h" +#include "quark.h" +#include "messages.h" + #define cquest (quest[QUEST_THRAIN]) bool_ quest_thrain_death_hook(char *fmt) diff --git a/src/q_thrain.h b/src/q_thrain.h new file mode 100644 index 00000000..04c85823 --- /dev/null +++ b/src/q_thrain.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern bool_ quest_thrain_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index 82ccdb9e..a391e7d5 100644 --- a/src/tables.c +++ b/src/tables.c @@ -14,6 +14,7 @@ #include "q_library.h" #include "q_fireprof.h" #include "q_bounty.h" +#include "q_thrain.h" -- cgit v1.2.3 From ed1ec7f8250ae3665fbe577f4812574a9a32ab0c Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 18:22:25 +0100 Subject: Split Narsil quest from plots.c --- src/CMakeLists.txt | 1 + src/plots.c | 3 --- src/plots.h | 3 --- src/q_narsil.c | 4 +++- src/q_narsil.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 src/q_narsil.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bd706b04..8dc8c234 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,6 +11,7 @@ SET(SRCS variable.c tables.c plots.c util.c cave.c dungeon.c melee1.c melee2.c messages.c modules.c q_god.c q_library.c q_fireprof.c q_bounty.c q_thrain.c + q_narsil.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index db0d1096..19c6afcb 100644 --- a/src/plots.c +++ b/src/plots.c @@ -394,6 +394,3 @@ bool_ quest_null_hook(int q) /************************* Khazad-dum plot ************************/ #include "q_evil.c" - -/*************************** Other plot ***************************/ -#include "q_narsil.c" diff --git a/src/plots.h b/src/plots.h index 7b2396ec..7c0b8b00 100644 --- a/src/plots.h +++ b/src/plots.h @@ -43,9 +43,6 @@ extern bool_ quest_between_init_hook(int q_idx); /******* Plot Khazad-dum *********/ extern bool_ quest_evil_init_hook(int q_idx); -/******* Plot Other *********/ -extern bool_ quest_narsil_init_hook(int q_idx); - /******* Plot God Quest **************/ extern bool_ quest_god_describe(FILE *); extern bool_ quest_god_init_hook(int q); diff --git a/src/q_narsil.c b/src/q_narsil.c index 27ec218e..3fe8b19f 100644 --- a/src/q_narsil.c +++ b/src/q_narsil.c @@ -1,4 +1,6 @@ -#undef cquest +#include "q_narsil.h" + + #define cquest (quest[QUEST_NARSIL]) bool_ quest_narsil_move_hook(char *fmt) diff --git a/src/q_narsil.h b/src/q_narsil.h new file mode 100644 index 00000000..227c0db7 --- /dev/null +++ b/src/q_narsil.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_narsil_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index a391e7d5..bd399994 100644 --- a/src/tables.c +++ b/src/tables.c @@ -15,6 +15,7 @@ #include "q_fireprof.h" #include "q_bounty.h" #include "q_thrain.h" +#include "q_narsil.h" -- cgit v1.2.3 From ddd8786965ed3e020d83ec940584c6c529ab9875 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 18:25:59 +0100 Subject: Split Khazad-dum quest from plots.c --- src/CMakeLists.txt | 2 +- src/plots.c | 3 --- src/plots.h | 3 --- src/q_evil.c | 3 ++- src/q_evil.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 src/q_evil.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8dc8c234..2b930392 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,7 +11,7 @@ SET(SRCS variable.c tables.c plots.c util.c cave.c dungeon.c melee1.c melee2.c messages.c modules.c q_god.c q_library.c q_fireprof.c q_bounty.c q_thrain.c - q_narsil.c + q_narsil.c q_evil.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index 19c6afcb..c8f007b2 100644 --- a/src/plots.c +++ b/src/plots.c @@ -391,6 +391,3 @@ bool_ quest_null_hook(int q) /************************* Minas Anor plot ************************/ #include "q_haunted.c" #include "q_betwen.c" - -/************************* Khazad-dum plot ************************/ -#include "q_evil.c" diff --git a/src/plots.h b/src/plots.h index 7c0b8b00..f4e6fac3 100644 --- a/src/plots.h +++ b/src/plots.h @@ -40,9 +40,6 @@ extern bool_ quest_invasion_init_hook(int q_idx); extern bool_ quest_haunted_init_hook(int q_idx); extern bool_ quest_between_init_hook(int q_idx); -/******* Plot Khazad-dum *********/ -extern bool_ quest_evil_init_hook(int q_idx); - /******* Plot God Quest **************/ extern bool_ quest_god_describe(FILE *); extern bool_ quest_god_init_hook(int q); diff --git a/src/q_evil.c b/src/q_evil.c index a143f65c..4f4d59cd 100644 --- a/src/q_evil.c +++ b/src/q_evil.c @@ -1,4 +1,5 @@ -#undef cquest +#include "q_evil.h" + #define cquest (quest[QUEST_EVIL]) bool_ quest_evil_gen_hook(char *fmt) diff --git a/src/q_evil.h b/src/q_evil.h new file mode 100644 index 00000000..8b6739e9 --- /dev/null +++ b/src/q_evil.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_evil_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index bd399994..cfb2c867 100644 --- a/src/tables.c +++ b/src/tables.c @@ -16,6 +16,7 @@ #include "q_bounty.h" #include "q_thrain.h" #include "q_narsil.h" +#include "q_evil.h" -- cgit v1.2.3 From 1462a5fbe4ec3e4c87e489c283c6c4cbc0d5316b Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 18:33:52 +0100 Subject: Split "Between cities" quest from plots.c --- src/CMakeLists.txt | 2 +- src/plots.c | 1 - src/plots.h | 1 - src/q_betwen.c | 3 ++- src/q_betwen.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 src/q_betwen.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2b930392..255531bb 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,7 +11,7 @@ SET(SRCS variable.c tables.c plots.c util.c cave.c dungeon.c melee1.c melee2.c messages.c modules.c q_god.c q_library.c q_fireprof.c q_bounty.c q_thrain.c - q_narsil.c q_evil.c + q_narsil.c q_evil.c q_betwen.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index c8f007b2..79b49eed 100644 --- a/src/plots.c +++ b/src/plots.c @@ -390,4 +390,3 @@ bool_ quest_null_hook(int q) /************************* Minas Anor plot ************************/ #include "q_haunted.c" -#include "q_betwen.c" diff --git a/src/plots.h b/src/plots.h index f4e6fac3..4ea20472 100644 --- a/src/plots.h +++ b/src/plots.h @@ -38,7 +38,6 @@ extern bool_ quest_invasion_init_hook(int q_idx); /******* Plot Minas Anor *********/ extern bool_ quest_haunted_init_hook(int q_idx); -extern bool_ quest_between_init_hook(int q_idx); /******* Plot God Quest **************/ extern bool_ quest_god_describe(FILE *); diff --git a/src/q_betwen.c b/src/q_betwen.c index e6452dd9..1814cf2b 100644 --- a/src/q_betwen.c +++ b/src/q_betwen.c @@ -1,4 +1,5 @@ -#undef cquest +#include "q_betwen.h" + #define cquest (quest[QUEST_BETWEEN]) bool_ quest_between_move_hook(char *fmt) diff --git a/src/q_betwen.h b/src/q_betwen.h new file mode 100644 index 00000000..80ce5e42 --- /dev/null +++ b/src/q_betwen.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_between_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index cfb2c867..67a35ffd 100644 --- a/src/tables.c +++ b/src/tables.c @@ -17,6 +17,7 @@ #include "q_thrain.h" #include "q_narsil.h" #include "q_evil.h" +#include "q_betwen.h" -- cgit v1.2.3 From cbd585203f4701e3ce9096815b76e8a14223783b Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 18:37:51 +0100 Subject: Split "Haunted House" quest from plots.c --- src/CMakeLists.txt | 2 +- src/plots.c | 3 --- src/plots.h | 3 --- src/q_haunted.c | 3 ++- src/q_haunted.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 src/q_haunted.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 255531bb..6f90cf63 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,7 +11,7 @@ SET(SRCS variable.c tables.c plots.c util.c cave.c dungeon.c melee1.c melee2.c messages.c modules.c q_god.c q_library.c q_fireprof.c q_bounty.c q_thrain.c - q_narsil.c q_evil.c q_betwen.c + q_narsil.c q_evil.c q_betwen.c q_haunted.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index 79b49eed..e26b726b 100644 --- a/src/plots.c +++ b/src/plots.c @@ -387,6 +387,3 @@ bool_ quest_null_hook(int q) #include "q_eol.c" #include "q_nirna.c" #include "q_invas.c" - -/************************* Minas Anor plot ************************/ -#include "q_haunted.c" diff --git a/src/plots.h b/src/plots.h index 4ea20472..3eb18bf3 100644 --- a/src/plots.h +++ b/src/plots.h @@ -36,9 +36,6 @@ extern bool_ quest_eol_init_hook(int q_idx); extern bool_ quest_nirnaeth_init_hook(int q_idx); extern bool_ quest_invasion_init_hook(int q_idx); -/******* Plot Minas Anor *********/ -extern bool_ quest_haunted_init_hook(int q_idx); - /******* Plot God Quest **************/ extern bool_ quest_god_describe(FILE *); extern bool_ quest_god_init_hook(int q); diff --git a/src/q_haunted.c b/src/q_haunted.c index db8992bc..efd5a47c 100644 --- a/src/q_haunted.c +++ b/src/q_haunted.c @@ -1,4 +1,5 @@ -#undef cquest +#include "q_haunted.h" + #define cquest (quest[QUEST_HAUNTED]) bool_ quest_haunted_gen_hook(char *fmt) diff --git a/src/q_haunted.h b/src/q_haunted.h new file mode 100644 index 00000000..332ec199 --- /dev/null +++ b/src/q_haunted.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_haunted_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index 67a35ffd..2fd10764 100644 --- a/src/tables.c +++ b/src/tables.c @@ -18,6 +18,7 @@ #include "q_narsil.h" #include "q_evil.h" #include "q_betwen.h" +#include "q_haunted.h" -- cgit v1.2.3 From ed23f9e34987846c22d0f679d230c225c977a19f Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 18:40:14 +0100 Subject: Split "Invasion of Gondolin" quest from plots.c --- src/CMakeLists.txt | 2 +- src/plots.c | 1 - src/plots.h | 1 - src/q_invas.c | 3 ++- src/q_invas.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 src/q_invas.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6f90cf63..c41f3019 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,7 +11,7 @@ SET(SRCS variable.c tables.c plots.c util.c cave.c dungeon.c melee1.c melee2.c messages.c modules.c q_god.c q_library.c q_fireprof.c q_bounty.c q_thrain.c - q_narsil.c q_evil.c q_betwen.c q_haunted.c + q_narsil.c q_evil.c q_betwen.c q_haunted.c q_invas.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index e26b726b..5cc0ef1c 100644 --- a/src/plots.c +++ b/src/plots.c @@ -386,4 +386,3 @@ bool_ quest_null_hook(int q) #include "q_dragons.c" #include "q_eol.c" #include "q_nirna.c" -#include "q_invas.c" diff --git a/src/plots.h b/src/plots.h index 3eb18bf3..737972a5 100644 --- a/src/plots.h +++ b/src/plots.h @@ -34,7 +34,6 @@ extern bool_ quest_poison_init_hook(int q_idx); extern bool_ quest_dragons_init_hook(int q_idx); extern bool_ quest_eol_init_hook(int q_idx); extern bool_ quest_nirnaeth_init_hook(int q_idx); -extern bool_ quest_invasion_init_hook(int q_idx); /******* Plot God Quest **************/ extern bool_ quest_god_describe(FILE *); diff --git a/src/q_invas.c b/src/q_invas.c index 985062af..5a52457f 100644 --- a/src/q_invas.c +++ b/src/q_invas.c @@ -1,4 +1,5 @@ -#undef cquest +#include "q_invas.h" + #define cquest (quest[QUEST_INVASION]) bool_ quest_invasion_gen_hook(char *fmt) diff --git a/src/q_invas.h b/src/q_invas.h new file mode 100644 index 00000000..dc34e76a --- /dev/null +++ b/src/q_invas.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_invasion_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index 2fd10764..b6bcb668 100644 --- a/src/tables.c +++ b/src/tables.c @@ -19,6 +19,7 @@ #include "q_evil.h" #include "q_betwen.h" #include "q_haunted.h" +#include "q_invas.h" -- cgit v1.2.3 From 1837ed317dc2ed3a741588f6fcb5e3bda58d3887 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 18:42:45 +0100 Subject: Split "Nirnaeth Arnoiedad" quest from plots.c --- src/CMakeLists.txt | 1 + src/plots.c | 1 - src/plots.h | 1 - src/q_nirna.c | 3 ++- src/q_nirna.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 src/q_nirna.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c41f3019..69b57480 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,6 +12,7 @@ SET(SRCS melee1.c melee2.c messages.c modules.c q_god.c q_library.c q_fireprof.c q_bounty.c q_thrain.c q_narsil.c q_evil.c q_betwen.c q_haunted.c q_invas.c + q_nirna.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index 5cc0ef1c..2662d7d7 100644 --- a/src/plots.c +++ b/src/plots.c @@ -385,4 +385,3 @@ bool_ quest_null_hook(int q) /************************** Gondolin plot *************************/ #include "q_dragons.c" #include "q_eol.c" -#include "q_nirna.c" diff --git a/src/plots.h b/src/plots.h index 737972a5..f8ac52a8 100644 --- a/src/plots.h +++ b/src/plots.h @@ -33,7 +33,6 @@ extern bool_ quest_poison_init_hook(int q_idx); /******* Plot Gondolin *********/ extern bool_ quest_dragons_init_hook(int q_idx); extern bool_ quest_eol_init_hook(int q_idx); -extern bool_ quest_nirnaeth_init_hook(int q_idx); /******* Plot God Quest **************/ extern bool_ quest_god_describe(FILE *); diff --git a/src/q_nirna.c b/src/q_nirna.c index be856d31..07991487 100644 --- a/src/q_nirna.c +++ b/src/q_nirna.c @@ -1,4 +1,5 @@ -#undef cquest +#include "q_nirna.h" + #define cquest (quest[QUEST_NIRNAETH]) bool_ quest_nirnaeth_gen_hook(char *fmt) diff --git a/src/q_nirna.h b/src/q_nirna.h new file mode 100644 index 00000000..1c4a050b --- /dev/null +++ b/src/q_nirna.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_nirnaeth_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index b6bcb668..5f0f050f 100644 --- a/src/tables.c +++ b/src/tables.c @@ -20,6 +20,7 @@ #include "q_betwen.h" #include "q_haunted.h" #include "q_invas.h" +#include "q_nirna.h" -- cgit v1.2.3 From 0c07f2b07c4730762effd27955d7d13aa49dba74 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 18:48:47 +0100 Subject: =?UTF-8?q?Split=20E=C3=B6l=20&=20God=20quests=20from=20plots.c?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/CMakeLists.txt | 2 +- src/plots.c | 1 - src/plots.h | 5 ----- src/q_eol.c | 3 ++- src/q_eol.h | 13 +++++++++++++ src/q_god.c | 5 ++--- src/q_god.h | 14 ++++++++++++++ src/tables.c | 2 ++ 8 files changed, 34 insertions(+), 11 deletions(-) create mode 100644 src/q_eol.h create mode 100644 src/q_god.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 69b57480..1bf537b5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,7 +12,7 @@ SET(SRCS melee1.c melee2.c messages.c modules.c q_god.c q_library.c q_fireprof.c q_bounty.c q_thrain.c q_narsil.c q_evil.c q_betwen.c q_haunted.c q_invas.c - q_nirna.c + q_nirna.c q_eol.c q_god.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index 2662d7d7..683fca7d 100644 --- a/src/plots.c +++ b/src/plots.c @@ -384,4 +384,3 @@ bool_ quest_null_hook(int q) /************************** Gondolin plot *************************/ #include "q_dragons.c" -#include "q_eol.c" diff --git a/src/plots.h b/src/plots.h index f8ac52a8..6fb521db 100644 --- a/src/plots.h +++ b/src/plots.h @@ -32,8 +32,3 @@ extern bool_ quest_poison_init_hook(int q_idx); /******* Plot Gondolin *********/ extern bool_ quest_dragons_init_hook(int q_idx); -extern bool_ quest_eol_init_hook(int q_idx); - -/******* Plot God Quest **************/ -extern bool_ quest_god_describe(FILE *); -extern bool_ quest_god_init_hook(int q); diff --git a/src/q_eol.c b/src/q_eol.c index 5b1cf78e..3d9b13c8 100644 --- a/src/q_eol.c +++ b/src/q_eol.c @@ -1,4 +1,5 @@ -#undef cquest +#include "q_eol.h" + #define cquest (quest[QUEST_EOL]) bool_ quest_eol_gen_hook(char *fmt) diff --git a/src/q_eol.h b/src/q_eol.h new file mode 100644 index 00000000..c3abbf1e --- /dev/null +++ b/src/q_eol.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_eol_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/q_god.c b/src/q_god.c index 82f90a25..50f54762 100644 --- a/src/q_god.c +++ b/src/q_god.c @@ -1,9 +1,8 @@ -#include "angband.h" +#include "q_god.h" +#include "quark.h" #include -#include "quark.h" - #define cquest (quest[QUEST_GOD]) #define cquest_quests_given (cquest.data[0]) #define cquest_relics_found (cquest.data[1]) diff --git a/src/q_god.h b/src/q_god.h new file mode 100644 index 00000000..2f3ce104 --- /dev/null +++ b/src/q_god.h @@ -0,0 +1,14 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_god_describe(FILE *); +bool_ quest_god_init_hook(int q); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index 5f0f050f..f8f22870 100644 --- a/src/tables.c +++ b/src/tables.c @@ -21,6 +21,8 @@ #include "q_haunted.h" #include "q_invas.h" #include "q_nirna.h" +#include "q_eol.h" +#include "q_god.h" -- cgit v1.2.3 From 2542e580af280396ec1c4ce3b9f3ad76fe40d38e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 18:52:27 +0100 Subject: Split "Dragons!" quest from plots.c --- src/CMakeLists.txt | 2 +- src/plots.c | 3 --- src/plots.h | 3 --- src/q_dragons.c | 3 ++- src/q_dragons.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 src/q_dragons.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1bf537b5..de4be38d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,7 +12,7 @@ SET(SRCS melee1.c melee2.c messages.c modules.c q_god.c q_library.c q_fireprof.c q_bounty.c q_thrain.c q_narsil.c q_evil.c q_betwen.c q_haunted.c q_invas.c - q_nirna.c q_eol.c q_god.c + q_nirna.c q_eol.c q_god.c q_dragons.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index 683fca7d..b78d9362 100644 --- a/src/plots.c +++ b/src/plots.c @@ -381,6 +381,3 @@ bool_ quest_null_hook(int q) #include "q_wolves.c" #include "q_spider.c" #include "q_poison.c" - -/************************** Gondolin plot *************************/ -#include "q_dragons.c" diff --git a/src/plots.h b/src/plots.h index 6fb521db..56c2a61b 100644 --- a/src/plots.h +++ b/src/plots.h @@ -29,6 +29,3 @@ extern bool_ quest_shroom_init_hook(int q_idx); extern bool_ quest_wolves_init_hook(int q_idx); extern bool_ quest_spider_init_hook(int q_idx); extern bool_ quest_poison_init_hook(int q_idx); - -/******* Plot Gondolin *********/ -extern bool_ quest_dragons_init_hook(int q_idx); diff --git a/src/q_dragons.c b/src/q_dragons.c index 025e8ecd..cd6ebf2c 100644 --- a/src/q_dragons.c +++ b/src/q_dragons.c @@ -1,4 +1,5 @@ -#undef cquest +#include "q_dragons.h" + #define cquest (quest[QUEST_DRAGONS]) bool_ quest_dragons_gen_hook(char *fmt) diff --git a/src/q_dragons.h b/src/q_dragons.h new file mode 100644 index 00000000..2d3acc5a --- /dev/null +++ b/src/q_dragons.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_dragons_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index f8f22870..160594d7 100644 --- a/src/tables.c +++ b/src/tables.c @@ -23,6 +23,7 @@ #include "q_nirna.h" #include "q_eol.h" #include "q_god.h" +#include "q_dragons.h" -- cgit v1.2.3 From e69588809fa4ce2cae244decaac3ebd0762f258a Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 18:54:48 +0100 Subject: Split "Poisoned Water" quest from plots.c --- src/CMakeLists.txt | 2 +- src/plots.c | 1 - src/plots.h | 1 - src/q_poison.c | 5 ++++- src/q_poison.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 src/q_poison.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index de4be38d..b607d199 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,7 +12,7 @@ SET(SRCS melee1.c melee2.c messages.c modules.c q_god.c q_library.c q_fireprof.c q_bounty.c q_thrain.c q_narsil.c q_evil.c q_betwen.c q_haunted.c q_invas.c - q_nirna.c q_eol.c q_god.c q_dragons.c + q_nirna.c q_eol.c q_god.c q_dragons.c q_poison.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index b78d9362..2072a391 100644 --- a/src/plots.c +++ b/src/plots.c @@ -380,4 +380,3 @@ bool_ quest_null_hook(int q) /*************************** Lorien plot **************************/ #include "q_wolves.c" #include "q_spider.c" -#include "q_poison.c" diff --git a/src/plots.h b/src/plots.h index 56c2a61b..51db424d 100644 --- a/src/plots.h +++ b/src/plots.h @@ -28,4 +28,3 @@ extern bool_ quest_shroom_init_hook(int q_idx); /******* Plot Lorien *********/ extern bool_ quest_wolves_init_hook(int q_idx); extern bool_ quest_spider_init_hook(int q_idx); -extern bool_ quest_poison_init_hook(int q_idx); diff --git a/src/q_poison.c b/src/q_poison.c index 0c3987df..152b7d59 100644 --- a/src/q_poison.c +++ b/src/q_poison.c @@ -1,4 +1,7 @@ -#undef cquest +#include "q_poison.h" +#include "quark.h" +#include "messages.h" + #define cquest (quest[QUEST_POISON]) static int wild_locs[4][2] = diff --git a/src/q_poison.h b/src/q_poison.h new file mode 100644 index 00000000..73fcd0e5 --- /dev/null +++ b/src/q_poison.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_poison_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index 160594d7..6553490d 100644 --- a/src/tables.c +++ b/src/tables.c @@ -24,6 +24,7 @@ #include "q_eol.h" #include "q_god.h" #include "q_dragons.h" +#include "q_poison.h" -- cgit v1.2.3 From 1491a1fe626d1cde5541a8de284193eafd5bbed2 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 19:00:45 +0100 Subject: Split Spider quest from plots.c --- src/CMakeLists.txt | 1 + src/plots.c | 1 - src/plots.h | 1 - src/q_spider.c | 3 ++- src/q_spider.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 src/q_spider.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b607d199..15516dac 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,6 +13,7 @@ SET(SRCS q_god.c q_library.c q_fireprof.c q_bounty.c q_thrain.c q_narsil.c q_evil.c q_betwen.c q_haunted.c q_invas.c q_nirna.c q_eol.c q_god.c q_dragons.c q_poison.c + q_spider.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index 2072a391..45f2a87d 100644 --- a/src/plots.c +++ b/src/plots.c @@ -379,4 +379,3 @@ bool_ quest_null_hook(int q) /*************************** Lorien plot **************************/ #include "q_wolves.c" -#include "q_spider.c" diff --git a/src/plots.h b/src/plots.h index 51db424d..40bdf4d8 100644 --- a/src/plots.h +++ b/src/plots.h @@ -27,4 +27,3 @@ extern bool_ quest_shroom_init_hook(int q_idx); /******* Plot Lorien *********/ extern bool_ quest_wolves_init_hook(int q_idx); -extern bool_ quest_spider_init_hook(int q_idx); diff --git a/src/q_spider.c b/src/q_spider.c index a739535b..b8731a33 100644 --- a/src/q_spider.c +++ b/src/q_spider.c @@ -1,4 +1,5 @@ -#undef cquest +#include "q_spider.h" + #define cquest (quest[QUEST_SPIDER]) bool_ quest_spider_gen_hook(char *fmt) diff --git a/src/q_spider.h b/src/q_spider.h new file mode 100644 index 00000000..2a4dab27 --- /dev/null +++ b/src/q_spider.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_spider_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index 6553490d..cc36f2f6 100644 --- a/src/tables.c +++ b/src/tables.c @@ -25,6 +25,7 @@ #include "q_god.h" #include "q_dragons.h" #include "q_poison.h" +#include "q_spider.h" -- cgit v1.2.3 From 60d422ca9be29752ffb7d6d3a734845c46a89e28 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 19:03:20 +0100 Subject: Split "Wolves!" quest from plots.c --- src/CMakeLists.txt | 2 +- src/plots.c | 3 --- src/plots.h | 3 --- src/q_wolves.c | 3 ++- src/q_wolves.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 src/q_wolves.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 15516dac..01281443 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,7 +13,7 @@ SET(SRCS q_god.c q_library.c q_fireprof.c q_bounty.c q_thrain.c q_narsil.c q_evil.c q_betwen.c q_haunted.c q_invas.c q_nirna.c q_eol.c q_god.c q_dragons.c q_poison.c - q_spider.c + q_spider.c q_wolves.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index 45f2a87d..fabd118e 100644 --- a/src/plots.c +++ b/src/plots.c @@ -376,6 +376,3 @@ bool_ quest_null_hook(int q) #include "q_wight.c" #include "q_nazgul.c" #include "q_shroom.c" - -/*************************** Lorien plot **************************/ -#include "q_wolves.c" diff --git a/src/plots.h b/src/plots.h index 40bdf4d8..41dcd087 100644 --- a/src/plots.h +++ b/src/plots.h @@ -24,6 +24,3 @@ extern bool_ quest_troll_init_hook(int q_idx); extern bool_ quest_wight_init_hook(int q_idx); extern bool_ quest_nazgul_init_hook(int q_idx); extern bool_ quest_shroom_init_hook(int q_idx); - -/******* Plot Lorien *********/ -extern bool_ quest_wolves_init_hook(int q_idx); diff --git a/src/q_wolves.c b/src/q_wolves.c index 2ec14cc2..badbd319 100644 --- a/src/q_wolves.c +++ b/src/q_wolves.c @@ -1,4 +1,5 @@ -#undef cquest +#include "q_wolves.h" + #define cquest (quest[QUEST_WOLVES]) bool_ quest_wolves_gen_hook(char *fmt) diff --git a/src/q_wolves.h b/src/q_wolves.h new file mode 100644 index 00000000..f006716f --- /dev/null +++ b/src/q_wolves.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_wolves_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index cc36f2f6..4a2c4b34 100644 --- a/src/tables.c +++ b/src/tables.c @@ -26,6 +26,7 @@ #include "q_dragons.h" #include "q_poison.h" #include "q_spider.h" +#include "q_wolves.h" -- cgit v1.2.3 From e4aad7f42f675137e877f2c8ca3dd8a0da2fc6aa Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 19:06:26 +0100 Subject: Split Mushroom quest from plots.c --- src/CMakeLists.txt | 2 +- src/plots.c | 1 - src/plots.h | 1 - src/q_shroom.c | 4 +++- src/q_shroom.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 src/q_shroom.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 01281443..17a0e0a8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,7 +13,7 @@ SET(SRCS q_god.c q_library.c q_fireprof.c q_bounty.c q_thrain.c q_narsil.c q_evil.c q_betwen.c q_haunted.c q_invas.c q_nirna.c q_eol.c q_god.c q_dragons.c q_poison.c - q_spider.c q_wolves.c + q_spider.c q_wolves.c q_shroom.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index fabd118e..0b9b36fa 100644 --- a/src/plots.c +++ b/src/plots.c @@ -375,4 +375,3 @@ bool_ quest_null_hook(int q) #include "q_troll.c" #include "q_wight.c" #include "q_nazgul.c" -#include "q_shroom.c" diff --git a/src/plots.h b/src/plots.h index 41dcd087..df713fb9 100644 --- a/src/plots.h +++ b/src/plots.h @@ -23,4 +23,3 @@ extern bool_ quest_hobbit_init_hook(int q_idx); extern bool_ quest_troll_init_hook(int q_idx); extern bool_ quest_wight_init_hook(int q_idx); extern bool_ quest_nazgul_init_hook(int q_idx); -extern bool_ quest_shroom_init_hook(int q_idx); diff --git a/src/q_shroom.c b/src/q_shroom.c index c0133e74..96e1ac81 100644 --- a/src/q_shroom.c +++ b/src/q_shroom.c @@ -1,4 +1,6 @@ -#undef cquest +#include "q_shroom.h" +#include "messages.h" + #define cquest (quest[QUEST_SHROOM]) bool_ quest_shroom_speak_hook(char *fmt); diff --git a/src/q_shroom.h b/src/q_shroom.h new file mode 100644 index 00000000..bb47b12a --- /dev/null +++ b/src/q_shroom.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_shroom_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index 4a2c4b34..75457f61 100644 --- a/src/tables.c +++ b/src/tables.c @@ -27,6 +27,7 @@ #include "q_poison.h" #include "q_spider.h" #include "q_wolves.h" +#include "q_shroom.h" -- cgit v1.2.3 From 0a7cd1758c9e5f321f8652ada9b6637b352999ec Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 19:08:32 +0100 Subject: Split Nazgul quest from plots.c --- src/CMakeLists.txt | 2 +- src/plots.c | 1 - src/plots.h | 1 - src/q_nazgul.c | 3 ++- src/q_nazgul.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 src/q_nazgul.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 17a0e0a8..2ffa3748 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,7 +13,7 @@ SET(SRCS q_god.c q_library.c q_fireprof.c q_bounty.c q_thrain.c q_narsil.c q_evil.c q_betwen.c q_haunted.c q_invas.c q_nirna.c q_eol.c q_god.c q_dragons.c q_poison.c - q_spider.c q_wolves.c q_shroom.c + q_spider.c q_wolves.c q_shroom.c q_nazgul.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index 0b9b36fa..75370362 100644 --- a/src/plots.c +++ b/src/plots.c @@ -374,4 +374,3 @@ bool_ quest_null_hook(int q) #include "q_hobbit.c" #include "q_troll.c" #include "q_wight.c" -#include "q_nazgul.c" diff --git a/src/plots.h b/src/plots.h index df713fb9..1320e295 100644 --- a/src/plots.h +++ b/src/plots.h @@ -22,4 +22,3 @@ extern bool_ quest_thieves_init_hook(int q_idx); extern bool_ quest_hobbit_init_hook(int q_idx); extern bool_ quest_troll_init_hook(int q_idx); extern bool_ quest_wight_init_hook(int q_idx); -extern bool_ quest_nazgul_init_hook(int q_idx); diff --git a/src/q_nazgul.c b/src/q_nazgul.c index 66d3dc98..b386b70f 100644 --- a/src/q_nazgul.c +++ b/src/q_nazgul.c @@ -1,4 +1,5 @@ -#undef cquest +#include "q_nazgul.h" + #define cquest (quest[QUEST_NAZGUL]) bool_ quest_nazgul_gen_hook(char *fmt) diff --git a/src/q_nazgul.h b/src/q_nazgul.h new file mode 100644 index 00000000..60720e3f --- /dev/null +++ b/src/q_nazgul.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_nazgul_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index 75457f61..e08bfcb2 100644 --- a/src/tables.c +++ b/src/tables.c @@ -28,6 +28,7 @@ #include "q_spider.h" #include "q_wolves.h" #include "q_shroom.h" +#include "q_nazgul.h" -- cgit v1.2.3 From 2e797029ff1940b4c327b916900f4fb6004c7e69 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 19:11:04 +0100 Subject: Split Wight quest from plots.c --- src/CMakeLists.txt | 2 +- src/plots.c | 1 - src/plots.h | 1 - src/q_wight.c | 4 +++- src/q_wight.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 src/q_wight.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2ffa3748..83e75b6b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -13,7 +13,7 @@ SET(SRCS q_god.c q_library.c q_fireprof.c q_bounty.c q_thrain.c q_narsil.c q_evil.c q_betwen.c q_haunted.c q_invas.c q_nirna.c q_eol.c q_god.c q_dragons.c q_poison.c - q_spider.c q_wolves.c q_shroom.c q_nazgul.c + q_spider.c q_wolves.c q_shroom.c q_nazgul.c q_wight.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index 75370362..e0ad0e3e 100644 --- a/src/plots.c +++ b/src/plots.c @@ -373,4 +373,3 @@ bool_ quest_null_hook(int q) #include "q_thief.c" #include "q_hobbit.c" #include "q_troll.c" -#include "q_wight.c" diff --git a/src/plots.h b/src/plots.h index 1320e295..259bfaf3 100644 --- a/src/plots.h +++ b/src/plots.h @@ -21,4 +21,3 @@ extern bool_ quest_ultra_evil_init_hook(int q_idx); extern bool_ quest_thieves_init_hook(int q_idx); extern bool_ quest_hobbit_init_hook(int q_idx); extern bool_ quest_troll_init_hook(int q_idx); -extern bool_ quest_wight_init_hook(int q_idx); diff --git a/src/q_wight.c b/src/q_wight.c index 3f6b2c34..4be72fc2 100644 --- a/src/q_wight.c +++ b/src/q_wight.c @@ -1,4 +1,6 @@ -#undef cquest +#include "q_wight.h" +#include "quark.h" + #define cquest (quest[QUEST_WIGHT]) bool_ quest_wight_gen_hook(char *fmt) diff --git a/src/q_wight.h b/src/q_wight.h new file mode 100644 index 00000000..31b58882 --- /dev/null +++ b/src/q_wight.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_wight_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index e08bfcb2..756a3216 100644 --- a/src/tables.c +++ b/src/tables.c @@ -29,6 +29,7 @@ #include "q_wolves.h" #include "q_shroom.h" #include "q_nazgul.h" +#include "q_wight.h" -- cgit v1.2.3 From 4ce0078105404cc577cf74662fbc5d67b964f364 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 19:13:16 +0100 Subject: Split Troll quest from plots.c --- src/CMakeLists.txt | 1 + src/plots.c | 1 - src/plots.h | 1 - src/q_troll.c | 3 ++- src/q_troll.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 src/q_troll.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 83e75b6b..ef6f04b6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,6 +14,7 @@ SET(SRCS q_narsil.c q_evil.c q_betwen.c q_haunted.c q_invas.c q_nirna.c q_eol.c q_god.c q_dragons.c q_poison.c q_spider.c q_wolves.c q_shroom.c q_nazgul.c q_wight.c + q_troll.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index e0ad0e3e..8fecd439 100644 --- a/src/plots.c +++ b/src/plots.c @@ -372,4 +372,3 @@ bool_ quest_null_hook(int q) /**************************** Bree plot ***************************/ #include "q_thief.c" #include "q_hobbit.c" -#include "q_troll.c" diff --git a/src/plots.h b/src/plots.h index 259bfaf3..d3710037 100644 --- a/src/plots.h +++ b/src/plots.h @@ -20,4 +20,3 @@ extern bool_ quest_ultra_evil_init_hook(int q_idx); /******* Plot Bree *********/ extern bool_ quest_thieves_init_hook(int q_idx); extern bool_ quest_hobbit_init_hook(int q_idx); -extern bool_ quest_troll_init_hook(int q_idx); diff --git a/src/q_troll.c b/src/q_troll.c index c314d2a7..b3875418 100644 --- a/src/q_troll.c +++ b/src/q_troll.c @@ -1,4 +1,5 @@ -#undef cquest +#include "q_troll.h" + #define cquest (quest[QUEST_TROLL]) bool_ quest_troll_gen_hook(char *fmt) diff --git a/src/q_troll.h b/src/q_troll.h new file mode 100644 index 00000000..759baa86 --- /dev/null +++ b/src/q_troll.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_troll_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index 756a3216..6c721685 100644 --- a/src/tables.c +++ b/src/tables.c @@ -30,6 +30,7 @@ #include "q_shroom.h" #include "q_nazgul.h" #include "q_wight.h" +#include "q_troll.h" -- cgit v1.2.3 From 693aaaefe39c119490d592ed12c0a4de84d38915 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 19:15:41 +0100 Subject: Split Hobbit quest from plots.c --- src/CMakeLists.txt | 2 +- src/plots.c | 1 - src/plots.h | 1 - src/q_hobbit.c | 4 +++- src/q_hobbit.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 18 insertions(+), 4 deletions(-) create mode 100644 src/q_hobbit.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ef6f04b6..6f0974f3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,7 +14,7 @@ SET(SRCS q_narsil.c q_evil.c q_betwen.c q_haunted.c q_invas.c q_nirna.c q_eol.c q_god.c q_dragons.c q_poison.c q_spider.c q_wolves.c q_shroom.c q_nazgul.c q_wight.c - q_troll.c + q_troll.c q_hobbit.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index 8fecd439..51b986a3 100644 --- a/src/plots.c +++ b/src/plots.c @@ -371,4 +371,3 @@ bool_ quest_null_hook(int q) /**************************** Bree plot ***************************/ #include "q_thief.c" -#include "q_hobbit.c" diff --git a/src/plots.h b/src/plots.h index d3710037..47d54dbd 100644 --- a/src/plots.h +++ b/src/plots.h @@ -19,4 +19,3 @@ extern bool_ quest_ultra_evil_init_hook(int q_idx); /******* Plot Bree *********/ extern bool_ quest_thieves_init_hook(int q_idx); -extern bool_ quest_hobbit_init_hook(int q_idx); diff --git a/src/q_hobbit.c b/src/q_hobbit.c index b80638ad..fd15a94a 100644 --- a/src/q_hobbit.c +++ b/src/q_hobbit.c @@ -1,4 +1,6 @@ -#undef cquest +#include "q_hobbit.h" +#include "messages.h" + #define cquest (quest[QUEST_HOBBIT]) bool_ quest_hobbit_town_gen_hook(char *fmt) diff --git a/src/q_hobbit.h b/src/q_hobbit.h new file mode 100644 index 00000000..6295ae10 --- /dev/null +++ b/src/q_hobbit.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_hobbit_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index 6c721685..be79733f 100644 --- a/src/tables.c +++ b/src/tables.c @@ -31,6 +31,7 @@ #include "q_nazgul.h" #include "q_wight.h" #include "q_troll.h" +#include "q_hobbit.h" -- cgit v1.2.3 From 82224d3c88d07a02ec1db676d3bbb7d4b07bea0f Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 19:20:02 +0100 Subject: Split "Thieves!" quest from plots.c --- src/CMakeLists.txt | 2 +- src/plots.c | 3 --- src/plots.h | 3 --- src/q_thief.c | 3 ++- src/q_thief.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 17 insertions(+), 8 deletions(-) create mode 100644 src/q_thief.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6f0974f3..f9fc4a34 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,7 +14,7 @@ SET(SRCS q_narsil.c q_evil.c q_betwen.c q_haunted.c q_invas.c q_nirna.c q_eol.c q_god.c q_dragons.c q_poison.c q_spider.c q_wolves.c q_shroom.c q_nazgul.c q_wight.c - q_troll.c q_hobbit.c + q_troll.c q_hobbit.c q_thief.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index 51b986a3..d3cc6827 100644 --- a/src/plots.c +++ b/src/plots.c @@ -368,6 +368,3 @@ bool_ quest_null_hook(int q) #include "q_one.c" #include "q_ultrag.c" #include "q_ultrae.c" - -/**************************** Bree plot ***************************/ -#include "q_thief.c" diff --git a/src/plots.h b/src/plots.h index 47d54dbd..d5cc364d 100644 --- a/src/plots.h +++ b/src/plots.h @@ -16,6 +16,3 @@ extern bool_ quest_sauron_init_hook(int q_idx); extern bool_ quest_morgoth_init_hook(int q_idx); extern bool_ quest_ultra_good_init_hook(int q_idx); extern bool_ quest_ultra_evil_init_hook(int q_idx); - -/******* Plot Bree *********/ -extern bool_ quest_thieves_init_hook(int q_idx); diff --git a/src/q_thief.c b/src/q_thief.c index 6b033f8c..b341c572 100644 --- a/src/q_thief.c +++ b/src/q_thief.c @@ -1,4 +1,5 @@ -#undef cquest +#include "q_thief.h" + #define cquest (quest[QUEST_THIEVES]) bool_ quest_thieves_gen_hook(char *fmt) diff --git a/src/q_thief.h b/src/q_thief.h new file mode 100644 index 00000000..1962ee34 --- /dev/null +++ b/src/q_thief.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_thieves_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index be79733f..2d4a0275 100644 --- a/src/tables.c +++ b/src/tables.c @@ -32,6 +32,7 @@ #include "q_wight.h" #include "q_troll.h" #include "q_hobbit.h" +#include "q_thief.h" -- cgit v1.2.3 From a7abd11f574fc89620ddafa9ebac4f7fa50a1a7a Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 19:22:40 +0100 Subject: Split "Ultra Evil" quest from plots.c --- src/CMakeLists.txt | 2 +- src/plots.c | 2 +- src/plots.h | 1 - src/q_ultrae.c | 5 +---- src/q_ultrae.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 src/q_ultrae.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f9fc4a34..3aea4af5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,7 +14,7 @@ SET(SRCS q_narsil.c q_evil.c q_betwen.c q_haunted.c q_invas.c q_nirna.c q_eol.c q_god.c q_dragons.c q_poison.c q_spider.c q_wolves.c q_shroom.c q_nazgul.c q_wight.c - q_troll.c q_hobbit.c q_thief.c + q_troll.c q_hobbit.c q_thief.c q_ultrae.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index d3cc6827..ed4c65ea 100644 --- a/src/plots.c +++ b/src/plots.c @@ -367,4 +367,4 @@ bool_ quest_null_hook(int q) #include "q_main.c" #include "q_one.c" #include "q_ultrag.c" -#include "q_ultrae.c" + diff --git a/src/plots.h b/src/plots.h index d5cc364d..56253e6d 100644 --- a/src/plots.h +++ b/src/plots.h @@ -15,4 +15,3 @@ extern bool_ quest_one_init_hook(int q_idx); extern bool_ quest_sauron_init_hook(int q_idx); extern bool_ quest_morgoth_init_hook(int q_idx); extern bool_ quest_ultra_good_init_hook(int q_idx); -extern bool_ quest_ultra_evil_init_hook(int q_idx); diff --git a/src/q_ultrae.c b/src/q_ultrae.c index 78471df5..44f54158 100644 --- a/src/q_ultrae.c +++ b/src/q_ultrae.c @@ -1,8 +1,5 @@ -/* - * Here takes place the Evil ultra ending - */ +#include "q_ultrae.h" -#undef cquest #define cquest (quest[QUEST_ULTRA_EVIL]) bool_ quest_ultra_evil_init_hook(int q) diff --git a/src/q_ultrae.h b/src/q_ultrae.h new file mode 100644 index 00000000..3f97fcb3 --- /dev/null +++ b/src/q_ultrae.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_ultra_evil_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index 2d4a0275..52fb4db6 100644 --- a/src/tables.c +++ b/src/tables.c @@ -33,6 +33,7 @@ #include "q_troll.h" #include "q_hobbit.h" #include "q_thief.h" +#include "q_ultrae.h" -- cgit v1.2.3 From 5478165ad9d479ca9a5135e42ba139cae15aa5e6 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 19:24:43 +0100 Subject: Split "Ultra Good" quest from plots.c --- src/CMakeLists.txt | 2 +- src/plots.c | 1 - src/plots.h | 1 - src/q_ultrag.c | 5 +---- src/q_ultrag.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 16 insertions(+), 7 deletions(-) create mode 100644 src/q_ultrag.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3aea4af5..42468279 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,7 +14,7 @@ SET(SRCS q_narsil.c q_evil.c q_betwen.c q_haunted.c q_invas.c q_nirna.c q_eol.c q_god.c q_dragons.c q_poison.c q_spider.c q_wolves.c q_shroom.c q_nazgul.c q_wight.c - q_troll.c q_hobbit.c q_thief.c q_ultrae.c + q_troll.c q_hobbit.c q_thief.c q_ultrae.c q_ultrag.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index ed4c65ea..f8a87df4 100644 --- a/src/plots.c +++ b/src/plots.c @@ -366,5 +366,4 @@ bool_ quest_null_hook(int q) /**************************** Main plot ***************************/ #include "q_main.c" #include "q_one.c" -#include "q_ultrag.c" diff --git a/src/plots.h b/src/plots.h index 56253e6d..75a6101c 100644 --- a/src/plots.h +++ b/src/plots.h @@ -14,4 +14,3 @@ extern bool_ quest_necro_init_hook(int q_idx); extern bool_ quest_one_init_hook(int q_idx); extern bool_ quest_sauron_init_hook(int q_idx); extern bool_ quest_morgoth_init_hook(int q_idx); -extern bool_ quest_ultra_good_init_hook(int q_idx); diff --git a/src/q_ultrag.c b/src/q_ultrag.c index a5a09f2d..a5d28369 100644 --- a/src/q_ultrag.c +++ b/src/q_ultrag.c @@ -1,8 +1,5 @@ -/* - * Here takes place the Good ultra ending - */ +#include "q_ultrag.h" -#undef cquest #define cquest (quest[QUEST_ULTRA_GOOD]) bool_ quest_ultra_good_move_hook(char *fmt) diff --git a/src/q_ultrag.h b/src/q_ultrag.h new file mode 100644 index 00000000..09d9f80c --- /dev/null +++ b/src/q_ultrag.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_ultra_good_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index 52fb4db6..68c973c2 100644 --- a/src/tables.c +++ b/src/tables.c @@ -34,6 +34,7 @@ #include "q_hobbit.h" #include "q_thief.h" #include "q_ultrae.h" +#include "q_ultrag.h" -- cgit v1.2.3 From 410376a132361a76e79c2c079e2e0ab6650fec71 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 19:26:38 +0100 Subject: Split "The One" quest from plots.c --- src/CMakeLists.txt | 1 + src/plots.c | 1 - src/plots.h | 1 - src/q_one.c | 3 ++- src/q_one.h | 13 +++++++++++++ src/tables.c | 1 + 6 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 src/q_one.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 42468279..3e08f7ec 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,6 +15,7 @@ SET(SRCS q_nirna.c q_eol.c q_god.c q_dragons.c q_poison.c q_spider.c q_wolves.c q_shroom.c q_nazgul.c q_wight.c q_troll.c q_hobbit.c q_thief.c q_ultrae.c q_ultrag.c + q_one.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index f8a87df4..ff6610d0 100644 --- a/src/plots.c +++ b/src/plots.c @@ -365,5 +365,4 @@ bool_ quest_null_hook(int q) /**************************** Main plot ***************************/ #include "q_main.c" -#include "q_one.c" diff --git a/src/plots.h b/src/plots.h index 75a6101c..8143f455 100644 --- a/src/plots.h +++ b/src/plots.h @@ -11,6 +11,5 @@ extern bool_ quest_random_describe(FILE *fff); /******* Plot main ********/ extern bool_ quest_necro_init_hook(int q_idx); -extern bool_ quest_one_init_hook(int q_idx); extern bool_ quest_sauron_init_hook(int q_idx); extern bool_ quest_morgoth_init_hook(int q_idx); diff --git a/src/q_one.c b/src/q_one.c index 4bfeaf3e..f9c71a91 100644 --- a/src/q_one.c +++ b/src/q_one.c @@ -1,4 +1,5 @@ -#undef cquest +#include "q_one.h" + #define cquest (quest[QUEST_ONE]) bool_ quest_one_move_hook(char *fmt) diff --git a/src/q_one.h b/src/q_one.h new file mode 100644 index 00000000..3b0313a7 --- /dev/null +++ b/src/q_one.h @@ -0,0 +1,13 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_one_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index 68c973c2..937ba05d 100644 --- a/src/tables.c +++ b/src/tables.c @@ -35,6 +35,7 @@ #include "q_thief.h" #include "q_ultrae.h" #include "q_ultrag.h" +#include "q_one.h" -- cgit v1.2.3 From a9c3fa61b870baab20e4ef2f8a2eaa071f8abb56 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 19:30:32 +0100 Subject: Split the main quests from plots.c --- src/CMakeLists.txt | 2 +- src/plots.c | 14 -------------- src/plots.h | 5 ----- src/q_main.c | 12 ++++++++++++ src/q_main.h | 15 +++++++++++++++ src/tables.c | 1 + 6 files changed, 29 insertions(+), 20 deletions(-) create mode 100644 src/q_main.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3e08f7ec..0213a49a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,7 +15,7 @@ SET(SRCS q_nirna.c q_eol.c q_god.c q_dragons.c q_poison.c q_spider.c q_wolves.c q_shroom.c q_nazgul.c q_wight.c q_troll.c q_hobbit.c q_thief.c q_ultrae.c q_ultrag.c - q_one.c + q_one.c q_main.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/plots.c b/src/plots.c index ff6610d0..c8fb2506 100644 --- a/src/plots.c +++ b/src/plots.c @@ -343,16 +343,6 @@ bool_ process_hooks_new(int h_idx, void *in, void *out) /******** Plots & Quest stuff ********/ -static void quest_describe(int q_idx) -{ - int i = 0; - - while ((i < 10) && (quest[q_idx].desc[i][0] != '\0')) - { - cmsg_print(TERM_YELLOW, quest[q_idx].desc[i++]); - } -} - /* Catch-all quest hook */ bool_ quest_null_hook(int q) { @@ -362,7 +352,3 @@ bool_ quest_null_hook(int q) /************************** Random Quests *************************/ #include "q_rand.c" - -/**************************** Main plot ***************************/ -#include "q_main.c" - diff --git a/src/plots.h b/src/plots.h index 8143f455..1269df2d 100644 --- a/src/plots.h +++ b/src/plots.h @@ -8,8 +8,3 @@ extern bool_ quest_null_hook(int q); extern bool_ is_randhero(int level); extern bool_ quest_random_init_hook(int q_idx); extern bool_ quest_random_describe(FILE *fff); - -/******* Plot main ********/ -extern bool_ quest_necro_init_hook(int q_idx); -extern bool_ quest_sauron_init_hook(int q_idx); -extern bool_ quest_morgoth_init_hook(int q_idx); diff --git a/src/q_main.c b/src/q_main.c index a13b0790..4eef2298 100644 --- a/src/q_main.c +++ b/src/q_main.c @@ -1,3 +1,15 @@ +#include "q_main.h" + +static void quest_describe(int q_idx) +{ + int i = 0; + + while ((i < 10) && (quest[q_idx].desc[i][0] != '\0')) + { + cmsg_print(TERM_YELLOW, quest[q_idx].desc[i++]); + } +} + bool_ quest_main_monsters_hook(char *fmt) { s32b r_idx; diff --git a/src/q_main.h b/src/q_main.h new file mode 100644 index 00000000..618a2386 --- /dev/null +++ b/src/q_main.h @@ -0,0 +1,15 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ quest_necro_init_hook(int q_idx); +bool_ quest_sauron_init_hook(int q_idx); +bool_ quest_morgoth_init_hook(int q_idx); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index 937ba05d..d6fb29a9 100644 --- a/src/tables.c +++ b/src/tables.c @@ -36,6 +36,7 @@ #include "q_ultrae.h" #include "q_ultrag.h" #include "q_one.h" +#include "q_main.h" -- cgit v1.2.3 From 96f2a22e37c54c474954fc1443f4f7ffef55c468 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 19:34:15 +0100 Subject: Split random quests from plots.c --- src/CMakeLists.txt | 2 +- src/birth.c | 2 +- src/cave.c | 1 + src/plots.c | 3 --- src/plots.h | 5 ----- src/q_rand.c | 2 ++ src/q_rand.h | 15 +++++++++++++++ src/tables.c | 1 + 8 files changed, 21 insertions(+), 10 deletions(-) create mode 100644 src/q_rand.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0213a49a..fcddce9d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,7 +15,7 @@ SET(SRCS q_nirna.c q_eol.c q_god.c q_dragons.c q_poison.c q_spider.c q_wolves.c q_shroom.c q_nazgul.c q_wight.c q_troll.c q_hobbit.c q_thief.c q_ultrae.c q_ultrag.c - q_one.c q_main.c + q_one.c q_main.c q_rand.c object1.c object2.c randart.c squeltch.cc traps.c monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c diff --git a/src/birth.c b/src/birth.c index 85939b8e..844c3be8 100644 --- a/src/birth.c +++ b/src/birth.c @@ -11,8 +11,8 @@ */ #include "angband.h" - #include "messages.h" +#include "q_rand.h" /* * How often the autoroller will update the display and pause diff --git a/src/cave.c b/src/cave.c index ab1ce56e..9f26196a 100644 --- a/src/cave.c +++ b/src/cave.c @@ -4,6 +4,7 @@ #include "angband.h" +#include "q_rand.h" /* diff --git a/src/plots.c b/src/plots.c index c8fb2506..09200bb7 100644 --- a/src/plots.c +++ b/src/plots.c @@ -349,6 +349,3 @@ bool_ quest_null_hook(int q) /* Do nothing */ return (FALSE); } - -/************************** Random Quests *************************/ -#include "q_rand.c" diff --git a/src/plots.h b/src/plots.h index 1269df2d..b7a0dec5 100644 --- a/src/plots.h +++ b/src/plots.h @@ -3,8 +3,3 @@ /* Purpose: extern plots declarations */ extern bool_ quest_null_hook(int q); - -/******* Random Quests ********/ -extern bool_ is_randhero(int level); -extern bool_ quest_random_init_hook(int q_idx); -extern bool_ quest_random_describe(FILE *fff); diff --git a/src/q_rand.c b/src/q_rand.c index 0cc69a6d..998379e2 100644 --- a/src/q_rand.c +++ b/src/q_rand.c @@ -1,3 +1,5 @@ +#include "q_rand.h" + static int randquest_hero[] = { 20, 13, 15, 16, 9, 17, 18, 8, -1 }; bool_ is_randhero(int level) diff --git a/src/q_rand.h b/src/q_rand.h new file mode 100644 index 00000000..ea88b56c --- /dev/null +++ b/src/q_rand.h @@ -0,0 +1,15 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +bool_ is_randhero(int level); +bool_ quest_random_init_hook(int q_idx); +bool_ quest_random_describe(FILE *fff); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/tables.c b/src/tables.c index d6fb29a9..33330e80 100644 --- a/src/tables.c +++ b/src/tables.c @@ -37,6 +37,7 @@ #include "q_ultrag.h" #include "q_one.h" #include "q_main.h" +#include "q_rand.h" -- cgit v1.2.3 From 7482630bbf8dec872743d42d627fe51b90d1d5fc Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Sun, 24 Mar 2013 19:40:55 +0100 Subject: Remove unneeded includes --- src/plots.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/plots.c b/src/plots.c index 09200bb7..065cef54 100644 --- a/src/plots.c +++ b/src/plots.c @@ -14,9 +14,6 @@ #include -#include "messages.h" -#include "quark.h" - /******** Hooks stuff *********/ FILE *hook_file; -- cgit v1.2.3 From d1bc64bd22673bc72bafd7e200cbbea6eacb06c1 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 25 Mar 2013 10:13:47 +0100 Subject: Use #pragma once instead of include guards --- src/spell_type.h | 5 +---- src/spell_type_fwd.h | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/spell_type.h b/src/spell_type.h index bc3bdbec..eef6ce44 100644 --- a/src/spell_type.h +++ b/src/spell_type.h @@ -1,5 +1,4 @@ -#ifndef H_e7e01ebf_e19f_439d_b88d_cad51446a7a0 -#define H_e7e01ebf_e19f_439d_b88d_cad51446a7a0 +#pragma once #include "spell_type_fwd.h" @@ -94,5 +93,3 @@ bool_ spell_type_dependencies_satisfied(spell_type *spell); #ifdef __cplusplus } // extern "C" #endif - -#endif diff --git a/src/spell_type_fwd.h b/src/spell_type_fwd.h index 4664592c..e6c88145 100644 --- a/src/spell_type_fwd.h +++ b/src/spell_type_fwd.h @@ -1,5 +1,4 @@ -#ifndef H_ce003b12_cf58_444f_a927_5451f6dd8af1 -#define H_ce003b12_cf58_444f_a927_5451f6dd8af1 +#pragma once #ifdef __cplusplus extern "C" { @@ -23,5 +22,3 @@ struct spell_type; #ifdef __cplusplus } // extern "C" #endif - -#endif -- cgit v1.2.3 From 63bb0520dcdb6177533fe3b412fd72ee1ce6d711 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 25 Mar 2013 10:59:33 +0100 Subject: Split out data types --- src/CMakeLists.txt | 2 +- src/device_allocation.c | 26 +++++++++++++++++++++++++ src/device_allocation.h | 31 ++++++++++++++++++++++++++++++ src/device_allocation_fwd.h | 17 ++++++++++++++++ src/externs.h | 6 ------ src/lua_bind.c | 1 + src/object2.c | 2 ++ src/range.c | 2 +- src/range.h | 15 +++++++++++++++ src/range_fwd.h | 4 ++++ src/spell_type.c | 3 +++ src/spell_type.h | 4 +++- src/spells4.c | 25 ------------------------ src/spells5.c | 2 ++ src/string_list.c | 2 +- src/string_list.h | 22 +++++++++++++++++++++ src/types.h | 47 --------------------------------------------- src/types_fwd.h | 2 -- 18 files changed, 129 insertions(+), 84 deletions(-) create mode 100644 src/device_allocation.c create mode 100644 src/device_allocation.h create mode 100644 src/device_allocation_fwd.h create mode 100644 src/range.h create mode 100644 src/range_fwd.h create mode 100644 src/string_list.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fcddce9d..cf0b88b2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,7 +20,7 @@ SET(SRCS monster1.c monster2.c monster3.c xtra1.c xtra2.c skills.c powers.c gods.c spells1.c spells2.c spells3.c spells4.c spells5.c spells6.c - spell_type.c + spell_type.c device_allocation.c corrupt.c joke.c mimic.c status.c files.c notes.c loadsave.c string_list.c cmd1.c cmd2.c cmd3.c cmd4.c cmd5.c cmd6.c cmd7.c diff --git a/src/device_allocation.c b/src/device_allocation.c new file mode 100644 index 00000000..e64f0401 --- /dev/null +++ b/src/device_allocation.c @@ -0,0 +1,26 @@ +#include "device_allocation.h" + +int compare_device_allocation(device_allocation *a, device_allocation *b) +{ + return SGLIB_NUMERIC_COMPARATOR(a->tval, b->tval); +} + +SGLIB_DEFINE_LIST_FUNCTIONS(device_allocation, compare_device_allocation, next); + +void device_allocation_init(device_allocation *device_allocation, byte tval) +{ + assert(device_allocation != NULL); + + device_allocation->tval = tval; + device_allocation->rarity = 0; + range_init(&device_allocation->base_level, 0, 0); + range_init(&device_allocation->max_level, 0, 0); + device_allocation->next = NULL; +} + +device_allocation *device_allocation_new(byte tval) +{ + device_allocation *d = malloc(sizeof(device_allocation)); + device_allocation_init(d, tval); + return d; +} diff --git a/src/device_allocation.h b/src/device_allocation.h new file mode 100644 index 00000000..e620270f --- /dev/null +++ b/src/device_allocation.h @@ -0,0 +1,31 @@ +#pragma once + +#include "device_allocation_fwd.h" +#include "range.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Device allocation for skill + */ +struct device_allocation +{ + byte tval; + s32b rarity; + range_type base_level; + range_type max_level; + /* Next device allocation in the list */ + device_allocation *next; +}; + +int compare_device_allocation(device_allocation *a, device_allocation *b); +SGLIB_DEFINE_LIST_PROTOTYPES(device_allocation, compare_device_allocation, next); + +void device_allocation_init(struct device_allocation *device_allocation, byte tval); +struct device_allocation *device_allocation_new(byte tval); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/device_allocation_fwd.h b/src/device_allocation_fwd.h new file mode 100644 index 00000000..7bc0e0b0 --- /dev/null +++ b/src/device_allocation_fwd.h @@ -0,0 +1,17 @@ +#pragma once + +#include "angband.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct device_allocation device_allocation; +struct device_allocation; + +void device_allocation_init(struct device_allocation *device_allocation, byte tval); +struct device_allocation *device_allocation_new(byte tval); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/externs.h b/src/externs.h index 11bdc3f3..f139a1e1 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1920,9 +1920,6 @@ int spell_x(int sval, int pval, int i); bool_ school_book_contains_spell(int sval, s32b spell_idx); void lua_cast_school_spell(s32b spell_idx, bool_ no_cost); -void device_allocation_init(device_allocation *device_allocation, byte tval); -device_allocation *device_allocation_new(byte tval); - void dice_init(dice_type *dice, long base, long num, long sides); bool_ dice_parse(dice_type *dice, cptr s); void dice_parse_checked(dice_type *dice, cptr s); @@ -1943,9 +1940,6 @@ school_type *school_at(int index); void mana_school_calc_mana(int *msp); -/* range.c */ -extern void range_init(range_type *range, s32b min, s32b max); - /* randart.c */ extern int get_activation_power(void); extern void build_prob(cptr learn); diff --git a/src/lua_bind.c b/src/lua_bind.c index a15e9eb8..a3e2b0bb 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -15,6 +15,7 @@ #include #include "spell_type.h" +#include "range.h" /* * Monsters diff --git a/src/object2.c b/src/object2.c index b82691ea..cf688c15 100644 --- a/src/object2.c +++ b/src/object2.c @@ -13,6 +13,8 @@ #include "angband.h" #include "spell_type.h" +#include "device_allocation.h" + /* * Calculate the player's total inventory weight. diff --git a/src/range.c b/src/range.c index 647f0576..0cb21469 100644 --- a/src/range.c +++ b/src/range.c @@ -1,4 +1,4 @@ -#include +#include "range.h" void range_init(range_type *range, s32b min, s32b max) { diff --git a/src/range.h b/src/range.h new file mode 100644 index 00000000..0d840c18 --- /dev/null +++ b/src/range.h @@ -0,0 +1,15 @@ +#pragma once + +#include "range_fwd.h" +#include "angband.h" + +/* + * Range + */ +struct range_type +{ + s32b min; + s32b max; +}; + +void range_init(range_type *range, s32b min, s32b max); diff --git a/src/range_fwd.h b/src/range_fwd.h new file mode 100644 index 00000000..b5eef3fa --- /dev/null +++ b/src/range_fwd.h @@ -0,0 +1,4 @@ +#pragma once + +typedef struct range_type range_type; +struct range_type; diff --git a/src/spell_type.c b/src/spell_type.c index b8bec0cd..f0f8ee93 100644 --- a/src/spell_type.c +++ b/src/spell_type.c @@ -1,4 +1,7 @@ #include "spell_type.h" +#include "string_list.h" +#include "range.h" +#include "device_allocation.h" #include "angband.h" diff --git a/src/spell_type.h b/src/spell_type.h index eef6ce44..7f985bca 100644 --- a/src/spell_type.h +++ b/src/spell_type.h @@ -4,6 +4,8 @@ #include "h-type.h" #include "types_fwd.h" +#include "device_allocation_fwd.h" +#include "range_fwd.h" #ifdef __cplusplus extern "C" { @@ -64,7 +66,7 @@ void spell_type_describe(spell_type *spell, cptr line); void spell_type_add_school(spell_type *spell, s32b school_idx); void spell_type_set_device_charges(spell_type *spell, cptr charges_s); -void spell_type_add_device_allocation(spell_type *spell, struct device_allocation *a); +void spell_type_add_device_allocation(spell_type *spell, device_allocation *a); spell_type *spell_type_new(cptr name); diff --git a/src/spells4.c b/src/spells4.c index c977742d..f01930ec 100644 --- a/src/spells4.c +++ b/src/spells4.c @@ -630,31 +630,6 @@ void lua_cast_school_spell(s32b s, bool_ no_cost) p_ptr->window |= PW_PLAYER; } -void device_allocation_init(device_allocation *device_allocation, byte tval) -{ - assert(device_allocation != NULL); - - device_allocation->tval = tval; - device_allocation->rarity = 0; - range_init(&device_allocation->base_level, 0, 0); - range_init(&device_allocation->max_level, 0, 0); - device_allocation->next = NULL; -} - -device_allocation *device_allocation_new(byte tval) -{ - device_allocation *d = malloc(sizeof(device_allocation)); - device_allocation_init(d, tval); - return d; -} - -int compare_device_allocation(device_allocation *a, device_allocation *b) -{ - return SGLIB_NUMERIC_COMPARATOR(a->tval, b->tval); -} - -SGLIB_DEFINE_LIST_FUNCTIONS(device_allocation, compare_device_allocation, next); - void dice_init(dice_type *dice, long base, long num, long sides) { assert(dice != NULL); diff --git a/src/spells5.c b/src/spells5.c index 7ad0d3b9..72eddb76 100644 --- a/src/spells5.c +++ b/src/spells5.c @@ -3,6 +3,8 @@ #include #include "spell_type.h" +#include "device_allocation.h" + static spell_type *spell_new(s32b *index, cptr id, cptr name) { diff --git a/src/string_list.c b/src/string_list.c index 8a63cc3c..2d658e1c 100644 --- a/src/string_list.c +++ b/src/string_list.c @@ -1,4 +1,4 @@ -#include "angband.h" +#include "string_list.h" int compare_string_list(string_list *a, string_list *b) { diff --git a/src/string_list.h b/src/string_list.h new file mode 100644 index 00000000..bd88602f --- /dev/null +++ b/src/string_list.h @@ -0,0 +1,22 @@ +#pragma once + +#include "sglib.h" +#include "angband.h" + +/* + * String list. + */ +typedef struct string_list string_list; +struct string_list { + /* The string list owns the string */ + cptr s; + /* Next */ + string_list *next; +}; + +int compare_string_list(string_list *a, string_list *b); +SGLIB_DEFINE_LIST_PROTOTYPES(string_list, compare_string, next); + +void string_list_init(string_list *sl, cptr s); /* Initialize element; copies string */ +void string_list_destroy(string_list *sl); /* Destroy element */ +void string_list_append(string_list **slist, cptr s); /* Append string */ diff --git a/src/types.h b/src/types.h index 2e871a40..5d336815 100644 --- a/src/types.h +++ b/src/types.h @@ -48,25 +48,6 @@ */ -/* - * String list. - */ -typedef struct string_list string_list; -struct string_list { - /* The string list owns the string */ - cptr s; - /* Next */ - string_list *next; -}; - -int compare_string_list(string_list *a, string_list *b); -SGLIB_DEFINE_LIST_PROTOTYPES(string_list, compare_string, next); - -void string_list_init(string_list *sl, cptr s); /* Initialize element; copies string */ -void string_list_destroy(string_list *sl); /* Destroy element */ -void string_list_append(string_list **slist, cptr s); /* Append string */ - - /* * Template file header information (see "init.c"). 16 bytes. @@ -2487,16 +2468,6 @@ struct cli_comm s16b key; /* Key to convert command to. */ }; -/* - * Range - */ -typedef struct range_type range_type; -struct range_type -{ - s32b min; - s32b max; -}; - /* * Dice */ @@ -2508,24 +2479,6 @@ struct dice_type long sides; /* Sides per dice */ }; -/* - * Device allocation for skill - */ -typedef struct device_allocation device_allocation; -struct device_allocation -{ - byte tval; - s32b rarity; - range_type base_level; - range_type max_level; - /* Next device allocation in the list */ - device_allocation *next; -}; - -int compare_device_allocation(device_allocation *a, device_allocation *b); -SGLIB_DEFINE_LIST_PROTOTYPES(device_allocation, compare_device_allocation, next); - - /* * Skills ! */ diff --git a/src/types_fwd.h b/src/types_fwd.h index 581609e9..4c7084f9 100644 --- a/src/types_fwd.h +++ b/src/types_fwd.h @@ -81,9 +81,7 @@ struct hooks_chain; struct hist_type; struct set_type; struct cli_comm; -struct range_type; struct dice_type; -struct device_allocation; struct skill_type; struct school_idx; struct spell_type; -- cgit v1.2.3 From 07abe10e701b6e6d5acbfc79db665e29bceeb0ab Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 25 Mar 2013 11:19:10 +0100 Subject: Split "dice" out --- src/CMakeLists.txt | 2 +- src/dice.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/dice.h | 13 ++++++++ src/dice_fwd.h | 12 +++++++ src/externs.h | 6 ---- src/spell_type.c | 1 + src/spells4.c | 93 ----------------------------------------------------- src/types.h | 11 ------- src/types_fwd.h | 1 - 9 files changed, 121 insertions(+), 112 deletions(-) create mode 100644 src/dice.c create mode 100644 src/dice.h create mode 100644 src/dice_fwd.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cf0b88b2..74d71c68 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,7 +24,7 @@ SET(SRCS corrupt.c joke.c mimic.c status.c files.c notes.c loadsave.c string_list.c cmd1.c cmd2.c cmd3.c cmd4.c cmd5.c cmd6.c cmd7.c - help.c hiscore.c range.c + help.c hiscore.c range.c dice.c generate.c gen_maze.c gen_evol.c wild.c levels.c store.c bldg.c cmovie.c wizard2.c init2.c birth.c wizard1.c init1.c main.c diff --git a/src/dice.c b/src/dice.c new file mode 100644 index 00000000..ea9b7533 --- /dev/null +++ b/src/dice.c @@ -0,0 +1,94 @@ +#include "dice.h" + +void dice_init(dice_type *dice, long base, long num, long sides) +{ + assert(dice != NULL); + + dice->base = base; + dice->num = num; + dice->sides = sides; +} + +bool_ dice_parse(dice_type *dice, cptr s) +{ + long base, num, sides; + + if (sscanf(s, "%ld+%ldd%ld", &base, &num, &sides) == 3) + { + dice_init(dice, base, num, sides); + return TRUE; + } + + if (sscanf(s, "%ld+d%ld", &base, &sides) == 2) + { + dice_init(dice, base, 1, sides); + return TRUE; + } + + if (sscanf(s, "d%ld", &sides) == 1) + { + dice_init(dice, 0, 1, sides); + return TRUE; + } + + if (sscanf(s, "%ldd%ld", &num, &sides) == 2) + { + dice_init(dice, 0, num, sides); + return TRUE; + } + + if (sscanf(s, "%ld", &base) == 1) + { + dice_init(dice, base, 0, 0); + return TRUE; + } + + return FALSE; +} + +void dice_parse_checked(dice_type *dice, cptr s) +{ + bool_ result = dice_parse(dice, s); + if (!result) + { + abort(); + } +} + +long dice_roll(dice_type *dice) +{ + assert(dice != NULL); + return dice->base + damroll(dice->num, dice->sides); +} + +void dice_print(dice_type *dice, char *output) +{ + char buf[16]; + + output[0] = '\0'; + + if (dice->base > 0) + { + sprintf(buf, "%ld", dice->base); + strcat(output, buf); + } + + if ((dice->num > 0) || (dice->sides > 0)) + { + if (dice->base > 0) + { + strcat(output, "+"); + } + + if (dice->num > 1) + { + sprintf(buf, "%ld", dice->num); + strcat(output, buf); + } + + strcat(output, "d"); + + sprintf(buf, "%ld", dice->sides); + strcat(output, buf); + } +} diff --git a/src/dice.h b/src/dice.h new file mode 100644 index 00000000..3253f348 --- /dev/null +++ b/src/dice.h @@ -0,0 +1,13 @@ +#pragma once + +#include "dice_fwd.h" + +/** + * Dice + */ +struct dice_type +{ + long base; /* Base value to which roll is added. */ + long num; /* Number of dice */ + long sides; /* Sides per dice */ +}; diff --git a/src/dice_fwd.h b/src/dice_fwd.h new file mode 100644 index 00000000..ffc8fbfa --- /dev/null +++ b/src/dice_fwd.h @@ -0,0 +1,12 @@ +#pragma once + +#include "angband.h" + +typedef struct dice_type dice_type; +struct dice_type; + +void dice_init(dice_type *dice, long base, long num, long sides); +bool_ dice_parse(dice_type *dice, cptr s); +void dice_parse_checked(dice_type *dice, cptr s); +long dice_roll(dice_type *dice); +void dice_print(dice_type *dice, char *buf); diff --git a/src/externs.h b/src/externs.h index f139a1e1..cf8702bd 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1920,12 +1920,6 @@ int spell_x(int sval, int pval, int i); bool_ school_book_contains_spell(int sval, s32b spell_idx); void lua_cast_school_spell(s32b spell_idx, bool_ no_cost); -void dice_init(dice_type *dice, long base, long num, long sides); -bool_ dice_parse(dice_type *dice, cptr s); -void dice_parse_checked(dice_type *dice, cptr s); -long dice_roll(dice_type *dice); -void dice_print(dice_type *dice, char *buf); - /* spells5.c */ void school_spells_init(); spell_type *spell_at(s32b index); diff --git a/src/spell_type.c b/src/spell_type.c index f0f8ee93..ab219be5 100644 --- a/src/spell_type.c +++ b/src/spell_type.c @@ -2,6 +2,7 @@ #include "string_list.h" #include "range.h" #include "device_allocation.h" +#include "dice.h" #include "angband.h" diff --git a/src/spells4.c b/src/spells4.c index f01930ec..5a099483 100644 --- a/src/spells4.c +++ b/src/spells4.c @@ -629,96 +629,3 @@ void lua_cast_school_spell(s32b s, bool_ no_cost) p_ptr->redraw |= PR_MANA; p_ptr->window |= PW_PLAYER; } - -void dice_init(dice_type *dice, long base, long num, long sides) -{ - assert(dice != NULL); - - dice->base = base; - dice->num = num; - dice->sides = sides; -} - -bool_ dice_parse(dice_type *dice, cptr s) -{ - long base, num, sides; - - if (sscanf(s, "%ld+%ldd%ld", &base, &num, &sides) == 3) - { - dice_init(dice, base, num, sides); - return TRUE; - } - - if (sscanf(s, "%ld+d%ld", &base, &sides) == 2) - { - dice_init(dice, base, 1, sides); - return TRUE; - } - - if (sscanf(s, "d%ld", &sides) == 1) - { - dice_init(dice, 0, 1, sides); - return TRUE; - } - - if (sscanf(s, "%ldd%ld", &num, &sides) == 2) - { - dice_init(dice, 0, num, sides); - return TRUE; - } - - if (sscanf(s, "%ld", &base) == 1) - { - dice_init(dice, base, 0, 0); - return TRUE; - } - - return FALSE; -} - -void dice_parse_checked(dice_type *dice, cptr s) -{ - bool_ result = dice_parse(dice, s); - if (!result) - { - abort(); - } -} - -long dice_roll(dice_type *dice) -{ - assert(dice != NULL); - return dice->base + damroll(dice->num, dice->sides); -} - -void dice_print(dice_type *dice, char *output) -{ - char buf[16]; - - output[0] = '\0'; - - if (dice->base > 0) - { - sprintf(buf, "%ld", dice->base); - strcat(output, buf); - } - - if ((dice->num > 0) || (dice->sides > 0)) - { - if (dice->base > 0) - { - strcat(output, "+"); - } - - if (dice->num > 1) - { - sprintf(buf, "%ld", dice->num); - strcat(output, buf); - } - - strcat(output, "d"); - - sprintf(buf, "%ld", dice->sides); - strcat(output, buf); - } -} diff --git a/src/types.h b/src/types.h index 5d336815..92aa428b 100644 --- a/src/types.h +++ b/src/types.h @@ -2468,17 +2468,6 @@ struct cli_comm s16b key; /* Key to convert command to. */ }; -/* - * Dice - */ -typedef struct dice_type dice_type; -struct dice_type -{ - long base; /* Base value to which roll is added. */ - long num; /* Number of dice */ - long sides; /* Sides per dice */ -}; - /* * Skills ! */ diff --git a/src/types_fwd.h b/src/types_fwd.h index 4c7084f9..d5b2ec7d 100644 --- a/src/types_fwd.h +++ b/src/types_fwd.h @@ -81,7 +81,6 @@ struct hooks_chain; struct hist_type; struct set_type; struct cli_comm; -struct dice_type; struct skill_type; struct school_idx; struct spell_type; -- cgit v1.2.3 From eb657ada4c1ec432fc0e3aec0b9f4d796efed428 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 25 Mar 2013 13:10:24 +0100 Subject: Split hooks into separate header --- src/CMakeLists.txt | 2 +- src/angband.h | 1 - src/birth.c | 1 + src/bldg.c | 1 + src/cmd1.c | 1 + src/cmd2.c | 1 + src/cmd3.c | 1 + src/cmd4.c | 1 + src/cmd6.c | 1 + src/cmd7.c | 3 +- src/dungeon.c | 1 + src/externs.h | 22 ---- src/files.c | 1 + src/generate.c | 2 + src/help.c | 1 + src/hooks.c | 275 ++++++++++++++++++++++++++++++++++++++++++ src/hooks.h | 18 +++ src/init2.c | 1 + src/loadsave.c | 3 +- src/melee2.c | 1 + src/modules.c | 5 +- src/monster2.c | 1 + src/object1.c | 1 + src/object2.c | 1 + src/plots.c | 348 ----------------------------------------------------- src/plots.h | 5 - src/powers.c | 1 + src/q_betwen.c | 19 ++- src/q_dragons.c | 7 +- src/q_eol.c | 16 ++- src/q_evil.c | 7 +- src/q_fireprof.c | 7 +- src/q_god.c | 17 +-- src/q_haunted.c | 7 +- src/q_hobbit.c | 19 ++- src/q_invas.c | 19 ++- src/q_library.c | 3 +- src/q_library.h | 1 + src/q_main.c | 17 ++- src/q_narsil.c | 11 +- src/q_nazgul.c | 16 ++- src/q_nirna.c | 13 +- src/q_one.c | 28 +++-- src/q_poison.c | 16 ++- src/q_rand.c | 13 +- src/q_rand.h | 1 + src/q_shroom.c | 18 ++- src/q_spider.c | 10 +- src/q_thief.c | 11 +- src/q_thrain.c | 15 ++- src/q_troll.c | 10 +- src/q_ultrag.c | 12 +- src/q_wight.c | 10 +- src/q_wolves.c | 7 +- src/script.c | 1 + src/skills.c | 1 + src/spells2.c | 1 + src/store.c | 1 + src/tables.c | 2 +- src/types.h | 2 +- src/wild.c | 1 + src/wizard2.c | 1 + src/xtra1.c | 1 + src/xtra2.c | 1 + 64 files changed, 542 insertions(+), 500 deletions(-) create mode 100644 src/hooks.c create mode 100644 src/hooks.h delete mode 100644 src/plots.c delete mode 100644 src/plots.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 74d71c68..ba0fd9d2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,7 +8,7 @@ ADD_SUBDIRECTORY (squelch) SET(SRCS main-gcu.c main-x11.c main-xaw.c main-sdl.c main-gtk2.c z-rand.c z-util.c z-form.c z-virt.c z-term.c - variable.c tables.c plots.c util.c cave.c dungeon.c + variable.c tables.c hooks.c util.c cave.c dungeon.c melee1.c melee2.c messages.c modules.c q_god.c q_library.c q_fireprof.c q_bounty.c q_thrain.c q_narsil.c q_evil.c q_betwen.c q_haunted.c q_invas.c diff --git a/src/angband.h b/src/angband.h index 6bfbb984..7cceb7bd 100644 --- a/src/angband.h +++ b/src/angband.h @@ -57,7 +57,6 @@ extern "C" { #include "types.h" #include "spell_type_fwd.h" #include "externs.h" -#include "plots.h" /***** Some copyright messages follow below *****/ diff --git a/src/birth.c b/src/birth.c index 844c3be8..c6b612d3 100644 --- a/src/birth.c +++ b/src/birth.c @@ -12,6 +12,7 @@ #include "angband.h" #include "messages.h" +#include "hooks.h" #include "q_rand.h" /* diff --git a/src/bldg.c b/src/bldg.c index a182df65..468e3c1d 100644 --- a/src/bldg.c +++ b/src/bldg.c @@ -14,6 +14,7 @@ */ #include "angband.h" +#include "hooks.h" #include "q_library.h" #include "q_fireprof.h" #include "q_bounty.h" diff --git a/src/cmd1.c b/src/cmd1.c index a349ac12..46fc15eb 100644 --- a/src/cmd1.c +++ b/src/cmd1.c @@ -13,6 +13,7 @@ #include "angband.h" #include "quark.h" +#include "hooks.h" #define MAX_VAMPIRIC_DRAIN 100 diff --git a/src/cmd2.c b/src/cmd2.c index 20ef50af..28a3dc1e 100644 --- a/src/cmd2.c +++ b/src/cmd2.c @@ -11,6 +11,7 @@ */ #include "angband.h" +#include "hooks.h" void do_cmd_immovable_special(void); diff --git a/src/cmd3.c b/src/cmd3.c index d648a0dc..9f4170bc 100644 --- a/src/cmd3.c +++ b/src/cmd3.c @@ -13,6 +13,7 @@ #include "angband.h" #include "quark.h" +#include "hooks.h" /* * Display p_ptr->inventory diff --git a/src/cmd4.c b/src/cmd4.c index da606cc6..b74bfff9 100644 --- a/src/cmd4.c +++ b/src/cmd4.c @@ -13,6 +13,7 @@ #include "angband.h" #include "messages.h" +#include "hooks.h" /* * Hack -- redraw the screen diff --git a/src/cmd6.c b/src/cmd6.c index bfe364e5..80f61816 100644 --- a/src/cmd6.c +++ b/src/cmd6.c @@ -13,6 +13,7 @@ #include "angband.h" #include "spell_type.h" +#include "hooks.h" /* * Forward declare diff --git a/src/cmd7.c b/src/cmd7.c index 3d3b1bb2..02f84437 100644 --- a/src/cmd7.c +++ b/src/cmd7.c @@ -14,6 +14,7 @@ #include "angband.h" #include "quark.h" +#include "hooks.h" /* * Describe class powers of Mindcrafters @@ -816,7 +817,7 @@ void do_cmd_mimic_lore() p_ptr->update |= (PU_BONUS); } -static bool_ mimic_forbid_travel(char *fmt) +static bool_ mimic_forbid_travel(const char *fmt) { u32b value = p_ptr->mimic_extra >> 16; u32b att = p_ptr->mimic_extra & 0xFFFF; diff --git a/src/dungeon.c b/src/dungeon.c index 0b2551bf..5b462bb8 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -15,6 +15,7 @@ #include #include "quark.h" +#include "hooks.h" #include "spell_type.h" #define TY_CURSE_CHANCE 100 diff --git a/src/externs.h b/src/externs.h index cf8702bd..28e99e1c 100644 --- a/src/externs.h +++ b/src/externs.h @@ -561,28 +561,6 @@ extern deity_type deity_info[MAX_GODS]; extern timer_type *gl_timers; extern const char *get_version_string(); -/* plots.c */ -extern FILE *hook_file; -extern bool_ check_hook(int h_idx); -extern void wipe_hooks(void); -extern void dump_hooks(int h_idx); -extern void init_hooks(void); -extern hooks_chain* add_hook(int h_idx, hook_type hook, cptr name); -extern void add_hook_new(int h_idx, bool_ (*hook_f)(void *, void *, void *), cptr name, void *data); -extern void add_hook_script(int h_idx, char *script, cptr name); -extern void del_hook(int h_idx, hook_type hook); -extern void del_hook_name(int h_idx, cptr name); -extern s32b get_next_arg(char *fmt); -extern char* get_next_arg_str(char *fmt); -extern object_type *get_next_arg_obj(); -extern int process_hooks_restart; -extern hook_return process_hooks_return[20]; -extern bool_ process_hooks_ret(int h_idx, char *ret, char *fmt, ...); -extern bool_ process_hooks(int h_idx, char *fmt, ...); -extern bool_ process_hooks_new(int h_idx, void *in, void *out); - -extern void initialize_bookable_spells(); - /* help.c */ extern void init_hooks_help(); extern void help_race(cptr race); diff --git a/src/files.c b/src/files.c index 664c96d7..c97315fc 100644 --- a/src/files.c +++ b/src/files.c @@ -13,6 +13,7 @@ #include "angband.h" #include "hiscore.h" +#include "hooks.h" /* diff --git a/src/generate.c b/src/generate.c index 44e331a6..652d2bee 100644 --- a/src/generate.c +++ b/src/generate.c @@ -11,6 +11,8 @@ */ #include "angband.h" +#include "hooks.h" + #define SAFE_MAX_ATTEMPTS 5000 /* diff --git a/src/help.c b/src/help.c index 7aae360e..4c14da9d 100644 --- a/src/help.c +++ b/src/help.c @@ -12,6 +12,7 @@ */ #include "angband.h" +#include "hooks.h" #define DESC_MAX 14 #define TRIGGERED_HELP_MAX 19 diff --git a/src/hooks.c b/src/hooks.c new file mode 100644 index 00000000..2b70e90d --- /dev/null +++ b/src/hooks.c @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2001 James E. Wilson, Robert A. Koeneke, DarkGod + * + * This software may be copied and distributed for educational, research, and + * not for profit purposes provided that this copyright and statement are + * included in all such copies. + */ +#include "hooks.h" +#include "angband.h" +#include + +/******** Hooks stuff *********/ +FILE *hook_file; + +#define MAX_ARGS 50 + +static hooks_chain *hooks_heads[MAX_HOOKS]; + +/* Wipe hooks and init them with quest hooks */ +void wipe_hooks() +{ + int i; + + for (i = 0; i < MAX_HOOKS; i++) + { + hooks_heads[i] = NULL; + } +} +void init_hooks() +{ + int i; + + for (i = 0; i < MAX_Q_IDX; i++) + { + if (quest[i].init != NULL) + { + quest[i].init(i); + } + } +} + +/* Add a hook */ +hooks_chain* add_hook(int h_idx, hook_type hook, cptr name) +{ + hooks_chain *new_, *c = hooks_heads[h_idx]; + + /* Find it */ + while ((c != NULL) && (strcmp(c->name, name))) + { + c = c->next; + } + + /* If not already in the list, add it */ + if (c == NULL) + { + MAKE(new_, hooks_chain); + new_->hook = hook; + sprintf(new_->name, "%s", name); + new_->next = hooks_heads[h_idx]; + hooks_heads[h_idx] = new_; + return (new_); + } + else return (c); +} + +void add_hook_new(int h_idx, bool_ (*hook_f)(void *, void *, void *), cptr name, void *data) +{ + hooks_chain *c = add_hook(h_idx, NULL, name); + c->hook_f = hook_f; + c->hook_data = data; + c->type = HOOK_TYPE_NEW; +} + +/* Remove a hook */ +void del_hook(int h_idx, hook_type hook) +{ + hooks_chain *c = hooks_heads[h_idx], *p = NULL; + + /* Find it */ + while ((c != NULL) && (c->hook != hook)) + { + p = c; + c = c->next; + } + + /* Remove it */ + if (c != NULL) + { + if (p == NULL) + { + hooks_heads[h_idx] = c->next; + FREE(c, hooks_chain); + } + else + { + p->next = c->next; + FREE(c, hooks_chain); + } + } +} + +/* get the next argument */ +static hook_return param_pile[MAX_ARGS]; +static int get_next_arg_pos = 0; +static int get_next_arg_pile_pos = 0; +s32b get_next_arg(const char *fmt) +{ + while (TRUE) + { + switch (fmt[get_next_arg_pos++]) + { + case 'd': + case 'l': + return (param_pile[get_next_arg_pile_pos++].num); + case ')': + get_next_arg_pos--; + return 0; + case '(': + case ',': + break; + } + } +} +char* get_next_arg_str(const char *fmt) +{ + while (TRUE) + { + switch (fmt[get_next_arg_pos++]) + { + case 's': + return (char*)(param_pile[get_next_arg_pile_pos++].str); + case ')': + get_next_arg_pos--; + return 0; + case '(': + case ',': + break; + } + } +} +object_type* get_next_arg_obj() { + object_type *o_ptr = param_pile[get_next_arg_pile_pos++].o_ptr; + assert(o_ptr != NULL); + return o_ptr; +} + + +/* Actually process the hooks */ +int process_hooks_restart = FALSE; +hook_return process_hooks_return[20]; +static bool_ vprocess_hooks_return (int h_idx, char *ret, char *fmt, va_list *ap) +{ + hooks_chain *c = hooks_heads[h_idx]; + va_list real_ap; + + while (c != NULL) + { + if (c->type == HOOK_TYPE_C) + { + int i = 0, nb = 0; + + /* Push all args in the pile */ + i = 0; + COPY(&real_ap, ap, va_list); + while (fmt[i]) + { + switch (fmt[i]) + { + case 'O': + param_pile[nb++].o_ptr = va_arg(real_ap, object_type *); + break; + case 's': + param_pile[nb++].str = va_arg(real_ap, char *); + break; + case 'd': + case 'l': + param_pile[nb++].num = va_arg(real_ap, s32b); + break; + case '(': + case ')': + case ',': + break; + } + i++; + } + + get_next_arg_pos = 0; + get_next_arg_pile_pos = 0; + if (c->hook(fmt)) + { + return TRUE; + } + + /* Should we restart ? */ + if (process_hooks_restart) + { + c = hooks_heads[h_idx]; + process_hooks_restart = FALSE; + } + else + { + c = c->next; + } + } + else if (c->type == HOOK_TYPE_NEW) + { + /* Skip; handled in process_hooks_new */ + c = c->next; + } + else + { + msg_format("Unkown hook type %d, name %s", c->type, c->name); + c = c->next; + } + } + + return FALSE; +} + +bool_ process_hooks_ret(int h_idx, char *ret, char *fmt, ...) +{ + va_list ap; + bool_ r; + + va_start(ap, fmt); + r = vprocess_hooks_return (h_idx, ret, fmt, &ap); + va_end(ap); + return (r); +} + +bool_ process_hooks(int h_idx, char *fmt, ...) +{ + va_list ap; + bool_ ret; + + va_start(ap, fmt); + ret = vprocess_hooks_return (h_idx, "", fmt, &ap); + va_end(ap); + return (ret); +} + +bool_ process_hooks_new(int h_idx, void *in, void *out) +{ + hooks_chain *c = hooks_heads[h_idx]; + + while (c != NULL) + { + /* Only new-style hooks; skip the rest. */ + if (c->type != HOOK_TYPE_NEW) + { + c = c->next; + continue; + } + + /* Invoke hook function; stop processing if + the hook returns TRUE */ + if (c->hook_f(c->hook_data, in, out)) + { + return TRUE; + } + + /* Should we restart processing at the beginning? */ + if (process_hooks_restart) + { + c = hooks_heads[h_idx]; + process_hooks_restart = FALSE; + } + else + { + c = c->next; + } + } + + return FALSE; +} diff --git a/src/hooks.h b/src/hooks.h new file mode 100644 index 00000000..0c83cf84 --- /dev/null +++ b/src/hooks.h @@ -0,0 +1,18 @@ +#pragma once + +#include "angband.h" + +extern FILE *hook_file; +extern void wipe_hooks(void); +extern void init_hooks(void); +extern hooks_chain* add_hook(int h_idx, hook_type hook, cptr name); +extern void add_hook_new(int h_idx, bool_ (*hook_f)(void *, void *, void *), cptr name, void *data); +extern void del_hook(int h_idx, hook_type hook); +extern s32b get_next_arg(const char *fmt); +extern char* get_next_arg_str(const char *fmt); +extern object_type *get_next_arg_obj(); +extern int process_hooks_restart; +extern hook_return process_hooks_return[20]; +extern bool_ process_hooks_ret(int h_idx, char *ret, char *fmt, ...); +extern bool_ process_hooks(int h_idx, char *fmt, ...); +extern bool_ process_hooks_new(int h_idx, void *in, void *out); diff --git a/src/init2.c b/src/init2.c index a38cccee..815d1255 100644 --- a/src/init2.c +++ b/src/init2.c @@ -8,6 +8,7 @@ #include "messages.h" #include "quark.h" +#include "hooks.h" /* * This file is used to initialise various variables and arrays for the diff --git a/src/loadsave.c b/src/loadsave.c index 1b142e59..1800298d 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -8,6 +8,7 @@ #include "messages.h" #include "quark.h" +#include "hooks.h" static void do_byte(byte *, int); static void do_bool(bool_ *, int); @@ -2715,7 +2716,7 @@ static bool_ do_savefile_aux(int flag) } /* Init the hooks */ - if (flag == LS_LOAD) + if ((flag == LS_LOAD) && (quest[i].init != NULL)) { quest[i].init(i); } diff --git a/src/melee2.c b/src/melee2.c index 4f63959d..bc3fc75b 100644 --- a/src/melee2.c +++ b/src/melee2.c @@ -19,6 +19,7 @@ #include "messages.h" #include "quark.h" +#include "hooks.h" #define SPEAK_CHANCE 8 #define GRINDNOISE 20 diff --git a/src/modules.c b/src/modules.c index 8376e3fb..7b11b568 100644 --- a/src/modules.c +++ b/src/modules.c @@ -1,7 +1,3 @@ -/* File: modules.c */ - -/* Purpose: T-engine modules */ - /* * Copyright (c) 2003 DarkGod * @@ -11,6 +7,7 @@ */ #include "angband.h" +#include "hooks.h" static void module_reset_dir_aux(cptr *dir, cptr new_path) { diff --git a/src/monster2.c b/src/monster2.c index 5ed4758a..4c4df91d 100644 --- a/src/monster2.c +++ b/src/monster2.c @@ -11,6 +11,7 @@ */ #include "angband.h" +#include "hooks.h" #define MAX_HORROR 20 #define MAX_FUNNY 22 diff --git a/src/object1.c b/src/object1.c index dd27c27e..72ccd5af 100644 --- a/src/object1.c +++ b/src/object1.c @@ -14,6 +14,7 @@ #include "quark.h" #include "spell_type.h" +#include "hooks.h" /* * Hack -- note that "TERM_MULTI" is now just "TERM_VIOLET". diff --git a/src/object2.c b/src/object2.c index cf688c15..3e55ed00 100644 --- a/src/object2.c +++ b/src/object2.c @@ -14,6 +14,7 @@ #include "spell_type.h" #include "device_allocation.h" +#include "hooks.h" /* diff --git a/src/plots.c b/src/plots.c deleted file mode 100644 index 065cef54..00000000 --- a/src/plots.c +++ /dev/null @@ -1,348 +0,0 @@ -/* File: plots.c */ - -/* Purpose: plots & quests */ - -/* - * Copyright (c) 2001 James E. Wilson, Robert A. Koeneke, DarkGod - * - * This software may be copied and distributed for educational, research, and - * not for profit purposes provided that this copyright and statement are - * included in all such copies. - */ - -#include "angband.h" - -#include - -/******** Hooks stuff *********/ -FILE *hook_file; - -#define MAX_ARGS 50 - -static hooks_chain *hooks_heads[MAX_HOOKS]; - -/* Wipe hooks and init them with quest hooks */ -void wipe_hooks() -{ - int i; - - for (i = 0; i < MAX_HOOKS; i++) - { - hooks_heads[i] = NULL; - } -} -void init_hooks() -{ - int i; - - for (i = 0; i < MAX_Q_IDX; i++) - { - if (quest[i].init != NULL) - { - quest[i].init(i); - } - } -} - -void dump_hooks(int h_idx) -{ - int min = 0, max = MAX_HOOKS, i; - - if (h_idx != -1) - { - min = h_idx; - max = h_idx + 1; - } - - for (i = min; i < max; i++) - { - hooks_chain *c = hooks_heads[i]; - - /* Find it */ - while (c != NULL) - { - msg_format("%s(%s)", c->name, (c->type == HOOK_TYPE_C) ? "C" : "Lua"); - - c = c->next; - } - } -} - -/* Check a hook */ -bool_ check_hook(int h_idx) -{ - hooks_chain *c = hooks_heads[h_idx]; - - return (c != NULL); -} - -/* Add a hook */ -hooks_chain* add_hook(int h_idx, hook_type hook, cptr name) -{ - hooks_chain *new_, *c = hooks_heads[h_idx]; - - /* Find it */ - while ((c != NULL) && (strcmp(c->name, name))) - { - c = c->next; - } - - /* If not already in the list, add it */ - if (c == NULL) - { - MAKE(new_, hooks_chain); - new_->hook = hook; - sprintf(new_->name, "%s", name); - new_->next = hooks_heads[h_idx]; - hooks_heads[h_idx] = new_; - return (new_); - } - else return (c); -} - -void add_hook_new(int h_idx, bool_ (*hook_f)(void *, void *, void *), cptr name, void *data) -{ - hooks_chain *c = add_hook(h_idx, NULL, name); - c->hook_f = hook_f; - c->hook_data = data; - c->type = HOOK_TYPE_NEW; -} - -/* Remove a hook */ -void del_hook(int h_idx, hook_type hook) -{ - hooks_chain *c = hooks_heads[h_idx], *p = NULL; - - /* Find it */ - while ((c != NULL) && (c->hook != hook)) - { - p = c; - c = c->next; - } - - /* Remove it */ - if (c != NULL) - { - if (p == NULL) - { - hooks_heads[h_idx] = c->next; - FREE(c, hooks_chain); - } - else - { - p->next = c->next; - FREE(c, hooks_chain); - } - } -} - -void del_hook_name(int h_idx, cptr name) -{ - hooks_chain *c = hooks_heads[h_idx], *p = NULL; - - /* Find it */ - while ((c != NULL) && (strcmp(c->name, name))) - { - p = c; - c = c->next; - } - - /* Remove it */ - if (c != NULL) - { - if (p == NULL) - { - hooks_heads[h_idx] = c->next; - FREE(c, hooks_chain); - } - else - { - p->next = c->next; - FREE(c, hooks_chain); - } - } -} - -/* get the next argument */ -static hook_return param_pile[MAX_ARGS]; -static int get_next_arg_pos = 0; -static int get_next_arg_pile_pos = 0; -s32b get_next_arg(char *fmt) -{ - while (TRUE) - { - switch (fmt[get_next_arg_pos++]) - { - case 'd': - case 'l': - return (param_pile[get_next_arg_pile_pos++].num); - case ')': - get_next_arg_pos--; - return 0; - case '(': - case ',': - break; - } - } -} -char* get_next_arg_str(char *fmt) -{ - while (TRUE) - { - switch (fmt[get_next_arg_pos++]) - { - case 's': - return (char*)(param_pile[get_next_arg_pile_pos++].str); - case ')': - get_next_arg_pos--; - return 0; - case '(': - case ',': - break; - } - } -} -object_type* get_next_arg_obj() { - object_type *o_ptr = param_pile[get_next_arg_pile_pos++].o_ptr; - assert(o_ptr != NULL); - return o_ptr; -} - - -/* Actually process the hooks */ -int process_hooks_restart = FALSE; -hook_return process_hooks_return[20]; -static bool_ vprocess_hooks_return (int h_idx, char *ret, char *fmt, va_list *ap) -{ - hooks_chain *c = hooks_heads[h_idx]; - va_list real_ap; - - while (c != NULL) - { - if (c->type == HOOK_TYPE_C) - { - int i = 0, nb = 0; - - /* Push all args in the pile */ - i = 0; - COPY(&real_ap, ap, va_list); - while (fmt[i]) - { - switch (fmt[i]) - { - case 'O': - param_pile[nb++].o_ptr = va_arg(real_ap, object_type *); - break; - case 's': - param_pile[nb++].str = va_arg(real_ap, char *); - break; - case 'd': - case 'l': - param_pile[nb++].num = va_arg(real_ap, s32b); - break; - case '(': - case ')': - case ',': - break; - } - i++; - } - - get_next_arg_pos = 0; - get_next_arg_pile_pos = 0; - if (c->hook(fmt)) - { - return TRUE; - } - - /* Should we restart ? */ - if (process_hooks_restart) - { - c = hooks_heads[h_idx]; - process_hooks_restart = FALSE; - } - else - { - c = c->next; - } - } - else if (c->type == HOOK_TYPE_NEW) - { - /* Skip; handled in process_hooks_new */ - c = c->next; - } - else - { - msg_format("Unkown hook type %d, name %s", c->type, c->name); - c = c->next; - } - } - - return FALSE; -} - -bool_ process_hooks_ret(int h_idx, char *ret, char *fmt, ...) -{ - va_list ap; - bool_ r; - - va_start(ap, fmt); - r = vprocess_hooks_return (h_idx, ret, fmt, &ap); - va_end(ap); - return (r); -} - -bool_ process_hooks(int h_idx, char *fmt, ...) -{ - va_list ap; - bool_ ret; - - va_start(ap, fmt); - ret = vprocess_hooks_return (h_idx, "", fmt, &ap); - va_end(ap); - return (ret); -} - -bool_ process_hooks_new(int h_idx, void *in, void *out) -{ - hooks_chain *c = hooks_heads[h_idx]; - - while (c != NULL) - { - /* Only new-style hooks; skip the rest. */ - if (c->type != HOOK_TYPE_NEW) - { - c = c->next; - continue; - } - - /* Invoke hook function; stop processing if - the hook returns TRUE */ - if (c->hook_f(c->hook_data, in, out)) - { - return TRUE; - } - - /* Should we restart processing at the beginning? */ - if (process_hooks_restart) - { - c = hooks_heads[h_idx]; - process_hooks_restart = FALSE; - } - else - { - c = c->next; - } - } - - return FALSE; -} - -/******** Plots & Quest stuff ********/ - -/* Catch-all quest hook */ -bool_ quest_null_hook(int q) -{ - /* Do nothing */ - return (FALSE); -} diff --git a/src/plots.h b/src/plots.h deleted file mode 100644 index b7a0dec5..00000000 --- a/src/plots.h +++ /dev/null @@ -1,5 +0,0 @@ -/* File: plots.h */ - -/* Purpose: extern plots declarations */ - -extern bool_ quest_null_hook(int q); diff --git a/src/powers.c b/src/powers.c index afc4a13a..7001a859 100644 --- a/src/powers.c +++ b/src/powers.c @@ -13,6 +13,7 @@ #include "angband.h" #include "quark.h" +#include "hooks.h" /* * Note: return value indicates the amount of mana to use diff --git a/src/q_betwen.c b/src/q_betwen.c index 1814cf2b..6f4072ca 100644 --- a/src/q_betwen.c +++ b/src/q_betwen.c @@ -1,8 +1,9 @@ #include "q_betwen.h" +#include "hooks.h" #define cquest (quest[QUEST_BETWEEN]) -bool_ quest_between_move_hook(char *fmt) +static bool_ quest_between_move_hook(const char *fmt) { s32b y; s32b x; @@ -50,7 +51,8 @@ bool_ quest_between_move_hook(char *fmt) return FALSE; } -bool_ quest_between_gen_hook(char *fmt) + +static bool_ quest_between_gen_hook(const char *fmt) { int x, y; int xstart = 2; @@ -84,7 +86,8 @@ bool_ quest_between_gen_hook(char *fmt) return TRUE; } -bool_ quest_between_finish_hook(char *fmt) + +static bool_ quest_between_finish_hook(const char *fmt) { s32b q_idx; object_type forge, *q_ptr; @@ -122,7 +125,8 @@ bool_ quest_between_finish_hook(char *fmt) return TRUE; } -bool_ quest_between_death_hook(char *fmt) + +static bool_ quest_between_death_hook(const char *fmt) { int i, mcnt = 0; @@ -151,7 +155,8 @@ bool_ quest_between_death_hook(char *fmt) return FALSE; } -bool_ quest_between_dump_hook(char *fmt) + +static bool_ quest_between_dump_hook(const char *fmt) { if (cquest.status >= QUEST_STATUS_COMPLETED) { @@ -160,7 +165,8 @@ bool_ quest_between_dump_hook(char *fmt) } return (FALSE); } -bool_ quest_between_forbid_hook(char *fmt) + +static bool_ quest_between_forbid_hook(const char *fmt) { s32b q_idx; q_idx = get_next_arg(fmt); @@ -174,6 +180,7 @@ bool_ quest_between_forbid_hook(char *fmt) } return (FALSE); } + bool_ quest_between_init_hook(int q) { if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED)) diff --git a/src/q_dragons.c b/src/q_dragons.c index cd6ebf2c..e63f662a 100644 --- a/src/q_dragons.c +++ b/src/q_dragons.c @@ -1,8 +1,9 @@ #include "q_dragons.h" +#include "hooks.h" #define cquest (quest[QUEST_DRAGONS]) -bool_ quest_dragons_gen_hook(char *fmt) +static bool_ quest_dragons_gen_hook(const char *fmt) { int x, y, i; int xstart = 2; @@ -90,7 +91,7 @@ bool_ quest_dragons_gen_hook(char *fmt) return TRUE; } -bool_ quest_dragons_death_hook(char *fmt) +static bool_ quest_dragons_death_hook(const char *fmt) { int i, mcnt = 0; @@ -122,7 +123,7 @@ bool_ quest_dragons_death_hook(char *fmt) return FALSE; } -bool_ quest_dragons_finish_hook(char *fmt) +static bool_ quest_dragons_finish_hook(const char *fmt) { s32b q_idx; diff --git a/src/q_eol.c b/src/q_eol.c index 3d9b13c8..4f0aa498 100644 --- a/src/q_eol.c +++ b/src/q_eol.c @@ -1,8 +1,9 @@ #include "q_eol.h" +#include "hooks.h" #define cquest (quest[QUEST_EOL]) -bool_ quest_eol_gen_hook(char *fmt) +static bool_ quest_eol_gen_hook(const char *fmt) { int x, y; bool_ done = FALSE; @@ -82,7 +83,8 @@ bool_ quest_eol_gen_hook(char *fmt) return TRUE; } -bool_ quest_eol_finish_hook(char *fmt) + +static bool_ quest_eol_finish_hook(const char *fmt) { object_type forge, *q_ptr; s32b q_idx; @@ -114,7 +116,8 @@ bool_ quest_eol_finish_hook(char *fmt) return TRUE; } -bool_ quest_eol_fail_hook(char *fmt) + +static bool_ quest_eol_fail_hook(const char *fmt) { s32b q_idx; @@ -132,7 +135,8 @@ bool_ quest_eol_fail_hook(char *fmt) return TRUE; } -bool_ quest_eol_death_hook(char *fmt) + +static bool_ quest_eol_death_hook(const char *fmt) { s32b r_idx, m_idx; @@ -152,7 +156,8 @@ bool_ quest_eol_death_hook(char *fmt) return FALSE; } -bool_ quest_eol_stair_hook(char *fmt) + +static bool_ quest_eol_stair_hook(const char *fmt) { monster_race *r_ptr = &r_info[test_monster_name("Eol, the Dark Elf")]; cptr down; @@ -182,6 +187,7 @@ bool_ quest_eol_stair_hook(char *fmt) return FALSE; } + bool_ quest_eol_init_hook(int q) { if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED)) diff --git a/src/q_evil.c b/src/q_evil.c index 4f4d59cd..64a9fabc 100644 --- a/src/q_evil.c +++ b/src/q_evil.c @@ -1,8 +1,9 @@ #include "q_evil.h" +#include "hooks.h" #define cquest (quest[QUEST_EVIL]) -bool_ quest_evil_gen_hook(char *fmt) +static bool_ quest_evil_gen_hook(const char *fmt) { int x, y, i; int xstart = 2; @@ -55,7 +56,7 @@ bool_ quest_evil_gen_hook(char *fmt) return TRUE; } -bool_ quest_evil_death_hook(char *fmt) +static bool_ quest_evil_death_hook(const char *fmt) { int i, mcnt = 0; @@ -89,7 +90,7 @@ bool_ quest_evil_death_hook(char *fmt) return FALSE; } -bool_ quest_evil_finish_hook(char *fmt) +static bool_ quest_evil_finish_hook(const char *fmt) { s32b q_idx; diff --git a/src/q_fireprof.c b/src/q_fireprof.c index e252af4f..a515335f 100644 --- a/src/q_fireprof.c +++ b/src/q_fireprof.c @@ -1,5 +1,6 @@ #include "q_fireprof.h" #include "quark.h" +#include "hooks.h" #define cquest (quest[QUEST_FIREPROOF]) @@ -379,7 +380,7 @@ void quest_fireproof_building(bool_ *paid, bool_ *recreate) } } -static bool_ fireproof_get_hook(char *fmt) +static bool_ fireproof_get_hook(const char *fmt) { object_type *o_ptr = get_next_arg_obj(); @@ -398,7 +399,7 @@ static bool_ fireproof_get_hook(char *fmt) return FALSE; } -static bool_ fireproof_stair_hook(char *fmt) +static bool_ fireproof_stair_hook(const char *fmt) { /* only ask this if player about to go up stairs of quest and * hasn't retrieved item */ @@ -480,7 +481,7 @@ bool_ quest_fireproof_describe(FILE *hook_file) return TRUE; } -static bool_ fireproof_gen_hook(char *fmt) +static bool_ fireproof_gen_hook(const char *fmt) { fireproof_settings const *settings = fireproof_get_settings(); diff --git a/src/q_god.c b/src/q_god.c index 50f54762..26b44a30 100644 --- a/src/q_god.c +++ b/src/q_god.c @@ -1,5 +1,6 @@ #include "q_god.h" #include "quark.h" +#include "hooks.h" #include @@ -864,7 +865,7 @@ static void quest_god_set_god_dungeon_attributes_mandos() d_info[DUNGEON_GOD].rules[0].mflags3 = RF3_UNDEAD | RF3_EVIL; } -static bool_ quest_god_level_end_gen_hook(char *fmt) +static bool_ quest_god_level_end_gen_hook(const char *fmt) { /* Check for dungeon */ if ((dungeon_type != DUNGEON_GOD) || @@ -921,7 +922,7 @@ static bool_ quest_god_level_end_gen_hook(char *fmt) return FALSE; } -static bool_ quest_god_player_level_hook(char *fmt) +static bool_ quest_god_player_level_hook(const char *fmt) { s32b gained = get_next_arg(fmt); @@ -981,7 +982,7 @@ static bool_ quest_god_player_level_hook(char *fmt) return FALSE; } -static bool_ quest_god_get_hook(char *fmt) +static bool_ quest_god_get_hook(const char *fmt) { s32b item; object_type *o_ptr = NULL; @@ -1039,7 +1040,7 @@ static bool_ quest_god_get_hook(char *fmt) return FALSE; } -static bool_ quest_god_char_dump_hook(char *fmt) +static bool_ quest_god_char_dump_hook(const char *fmt) { if (cquest_quests_given > 0) { @@ -1140,26 +1141,26 @@ static void quest_god_dungeon_setup(int d_idx) set_god_dungeon_attributes(); } -static bool_ quest_god_enter_dungeon_hook(char *fmt) +static bool_ quest_god_enter_dungeon_hook(const char *fmt) { s32b d_idx = get_next_arg(fmt); quest_god_dungeon_setup(d_idx); return FALSE; } -static bool_ quest_god_gen_level_begin_hook(char *fmt) +static bool_ quest_god_gen_level_begin_hook(const char *fmt) { quest_god_dungeon_setup(dungeon_type); return FALSE; } -static bool_ quest_god_stair_hook(char *fmt) +static bool_ quest_god_stair_hook(const char *fmt) { quest_god_dungeon_setup(dungeon_type); return FALSE; } -static bool_ quest_god_birth_objects_hook(char *fmt) +static bool_ quest_god_birth_objects_hook(const char *fmt) { cquest_quests_given = 0; cquest_relics_found = 0; diff --git a/src/q_haunted.c b/src/q_haunted.c index efd5a47c..83f97cb2 100644 --- a/src/q_haunted.c +++ b/src/q_haunted.c @@ -1,8 +1,9 @@ #include "q_haunted.h" +#include "hooks.h" #define cquest (quest[QUEST_HAUNTED]) -bool_ quest_haunted_gen_hook(char *fmt) +static bool_ quest_haunted_gen_hook(const char *fmt) { int x, y, i, m_idx; int xstart = 2; @@ -87,7 +88,7 @@ bool_ quest_haunted_gen_hook(char *fmt) return TRUE; } -bool_ quest_haunted_death_hook(char *fmt) +static bool_ quest_haunted_death_hook(const char *fmt) { int i, mcnt = 0; @@ -119,7 +120,7 @@ bool_ quest_haunted_death_hook(char *fmt) return FALSE; } -bool_ quest_haunted_finish_hook(char *fmt) +static bool_ quest_haunted_finish_hook(const char *fmt) { s32b q_idx; diff --git a/src/q_hobbit.c b/src/q_hobbit.c index fd15a94a..a6a1f140 100644 --- a/src/q_hobbit.c +++ b/src/q_hobbit.c @@ -1,9 +1,10 @@ #include "q_hobbit.h" #include "messages.h" +#include "hooks.h" #define cquest (quest[QUEST_HOBBIT]) -bool_ quest_hobbit_town_gen_hook(char *fmt) +static bool_ quest_hobbit_town_gen_hook(const char *fmt) { int x = 1, y = 1, tries = 10000; s32b small; @@ -35,7 +36,8 @@ bool_ quest_hobbit_town_gen_hook(char *fmt) return FALSE; } -bool_ quest_hobbit_gen_hook(char *fmt) + +static bool_ quest_hobbit_gen_hook(const char *fmt) { int x = 1, y = 1, tries = 10000; @@ -62,7 +64,8 @@ bool_ quest_hobbit_gen_hook(char *fmt) return FALSE; } -bool_ quest_hobbit_give_hook(char *fmt) + +static bool_ quest_hobbit_give_hook(const char *fmt) { object_type *o_ptr; monster_type *m_ptr; @@ -92,7 +95,8 @@ bool_ quest_hobbit_give_hook(char *fmt) return TRUE; } -bool_ quest_hobbit_speak_hook(char *fmt) + +static bool_ quest_hobbit_speak_hook(const char *fmt) { s32b m_idx = get_next_arg(fmt); @@ -108,7 +112,8 @@ bool_ quest_hobbit_speak_hook(char *fmt) } return (TRUE); } -bool_ quest_hobbit_chat_hook(char *fmt) + +static bool_ quest_hobbit_chat_hook(const char *fmt) { monster_type *m_ptr; s32b m_idx; @@ -160,7 +165,8 @@ bool_ quest_hobbit_chat_hook(char *fmt) return TRUE; } -bool_ quest_hobbit_dump_hook(char *fmt) + +static bool_ quest_hobbit_dump_hook(const char *fmt) { if (cquest.status >= QUEST_STATUS_COMPLETED) { @@ -168,6 +174,7 @@ bool_ quest_hobbit_dump_hook(char *fmt) } return (FALSE); } + bool_ quest_hobbit_init_hook(int q_idx) { /* Get a level to place the hobbit */ diff --git a/src/q_invas.c b/src/q_invas.c index 5a52457f..10cb5dc6 100644 --- a/src/q_invas.c +++ b/src/q_invas.c @@ -1,8 +1,9 @@ #include "q_invas.h" +#include "hooks.h" #define cquest (quest[QUEST_INVASION]) -bool_ quest_invasion_gen_hook(char *fmt) +static bool_ quest_invasion_gen_hook(const char *fmt) { int x, y; int xstart = 2; @@ -44,7 +45,8 @@ bool_ quest_invasion_gen_hook(char *fmt) return TRUE; } -bool_ quest_invasion_ai_hook(char *fmt) + +static bool_ quest_invasion_ai_hook(const char *fmt) { monster_type *m_ptr; s32b m_idx; @@ -83,7 +85,8 @@ bool_ quest_invasion_ai_hook(char *fmt) return (FALSE); } -bool_ quest_invasion_turn_hook(char *fmt) + +static bool_ quest_invasion_turn_hook(const char *fmt) { if (cquest.status != QUEST_STATUS_UNTAKEN) return (FALSE); if (p_ptr->lev < 45) return (FALSE); @@ -107,7 +110,8 @@ bool_ quest_invasion_turn_hook(char *fmt) process_hooks_restart = TRUE; return (FALSE); } -bool_ quest_invasion_dump_hook(char *fmt) + +static bool_ quest_invasion_dump_hook(const char *fmt) { if (cquest.status == QUEST_STATUS_FAILED) { @@ -119,7 +123,8 @@ bool_ quest_invasion_dump_hook(char *fmt) } return (FALSE); } -bool_ quest_invasion_death_hook(char *fmt) + +static bool_ quest_invasion_death_hook(const char *fmt) { s32b r_idx, m_idx; @@ -139,7 +144,8 @@ bool_ quest_invasion_death_hook(char *fmt) return FALSE; } -bool_ quest_invasion_stair_hook(char *fmt) + +static bool_ quest_invasion_stair_hook(const char *fmt) { cptr down; @@ -182,6 +188,7 @@ bool_ quest_invasion_stair_hook(char *fmt) return TRUE; } + bool_ quest_invasion_init_hook(int q_idx) { add_hook(HOOK_END_TURN, quest_invasion_turn_hook, "invasion_turn"); diff --git a/src/q_library.c b/src/q_library.c index 6e412719..36d2cd0b 100644 --- a/src/q_library.c +++ b/src/q_library.c @@ -1,5 +1,6 @@ #include "q_library.h" #include "quark.h" +#include "hooks.h" #define cquest (quest[QUEST_LIBRARY]) @@ -375,7 +376,7 @@ static bool_ quest_library_stair_hook() } } -static bool_ quest_library_monster_death_hook(char *fmt) +static bool_ quest_library_monster_death_hook(const char *fmt) { int i, count = -1; diff --git a/src/q_library.h b/src/q_library.h index 24504282..0ba02970 100644 --- a/src/q_library.h +++ b/src/q_library.h @@ -9,6 +9,7 @@ extern "C" { bool_ quest_library_init_hook(int q); bool_ quest_library_describe(FILE *fff); void quest_library_building(bool_ *paid, bool_ *recreate); +void initialize_bookable_spells(); #ifdef __cplusplus } // extern "C" diff --git a/src/q_main.c b/src/q_main.c index 4eef2298..f0e6214e 100644 --- a/src/q_main.c +++ b/src/q_main.c @@ -1,4 +1,5 @@ #include "q_main.h" +#include "hooks.h" static void quest_describe(int q_idx) { @@ -10,7 +11,7 @@ static void quest_describe(int q_idx) } } -bool_ quest_main_monsters_hook(char *fmt) +static bool_ quest_main_monsters_hook(const char *fmt) { s32b r_idx; r_idx = get_next_arg(fmt); @@ -29,7 +30,8 @@ bool_ quest_main_monsters_hook(char *fmt) } return FALSE; } -bool_ quest_morgoth_hook(char *fmt) + +static bool_ quest_morgoth_hook(const char *fmt) { /* Using test_monster_name() here would be a lot less ugly, but would take much more time */ monster_race *r_ptr = &r_info[862]; @@ -79,7 +81,8 @@ bool_ quest_morgoth_hook(char *fmt) } return (FALSE); } -bool_ quest_morgoth_dump_hook(char *fmt) + +static bool_ quest_morgoth_dump_hook(const char *fmt) { if (quest[QUEST_MORGOTH].status >= QUEST_STATUS_COMPLETED) { @@ -90,6 +93,7 @@ bool_ quest_morgoth_dump_hook(char *fmt) } return (FALSE); } + bool_ quest_morgoth_init_hook(int q_idx) { if ((quest[QUEST_MORGOTH].status >= QUEST_STATUS_TAKEN) && (quest[QUEST_MORGOTH].status < QUEST_STATUS_FINISHED)) @@ -101,7 +105,7 @@ bool_ quest_morgoth_init_hook(int q_idx) return (FALSE); } -bool_ quest_sauron_hook(char *fmt) +static bool_ quest_sauron_hook(const char *fmt) { /* Using test_monster_name() here would be a lot less ugly, but would take much more time */ monster_race *r_ptr = &r_info[860]; @@ -125,7 +129,7 @@ bool_ quest_sauron_hook(char *fmt) return (FALSE); } -bool_ quest_sauron_resurect_hook(char *fmt) +static bool_ quest_sauron_resurect_hook(const char *fmt) { s32b m_idx = get_next_arg(fmt); monster_type *m_ptr = &m_list[m_idx]; @@ -155,7 +159,7 @@ bool_ quest_sauron_init_hook(int q_idx) return (FALSE); } -bool_ quest_necro_hook(char *fmt) +static bool_ quest_necro_hook(const char *fmt) { /* Using test_monster_name() here would be a lot less ugly, but would take much more time */ monster_race *r_ptr = &r_info[819]; @@ -177,6 +181,7 @@ bool_ quest_necro_hook(char *fmt) } return (FALSE); } + bool_ quest_necro_init_hook(int q_idx) { if ((quest[QUEST_NECRO].status >= QUEST_STATUS_TAKEN) && (quest[QUEST_NECRO].status < QUEST_STATUS_FINISHED)) diff --git a/src/q_narsil.c b/src/q_narsil.c index 3fe8b19f..521e344b 100644 --- a/src/q_narsil.c +++ b/src/q_narsil.c @@ -1,9 +1,9 @@ #include "q_narsil.h" - +#include "hooks.h" #define cquest (quest[QUEST_NARSIL]) -bool_ quest_narsil_move_hook(char *fmt) +static bool_ quest_narsil_move_hook(const char *fmt) { s32b y, x; cave_type *c_ptr; @@ -58,7 +58,8 @@ bool_ quest_narsil_move_hook(char *fmt) return TRUE; } -bool_ quest_narsil_dump_hook(char *fmt) + +static bool_ quest_narsil_dump_hook(const char *fmt) { if (cquest.status >= QUEST_STATUS_COMPLETED) { @@ -66,7 +67,8 @@ bool_ quest_narsil_dump_hook(char *fmt) } return (FALSE); } -bool_ quest_narsil_identify_hook(char *fmt) + +static bool_ quest_narsil_identify_hook(const char *fmt) { if (cquest.status == QUEST_STATUS_UNTAKEN) { @@ -98,6 +100,7 @@ bool_ quest_narsil_identify_hook(char *fmt) return (FALSE); } + bool_ quest_narsil_init_hook(int q_idx) { if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED)) diff --git a/src/q_nazgul.c b/src/q_nazgul.c index b386b70f..5573b40b 100644 --- a/src/q_nazgul.c +++ b/src/q_nazgul.c @@ -1,8 +1,9 @@ #include "q_nazgul.h" +#include "hooks.h" #define cquest (quest[QUEST_NAZGUL]) -bool_ quest_nazgul_gen_hook(char *fmt) +static bool_ quest_nazgul_gen_hook(const char *fmt) { int m_idx, x = 1, y = 1, tries = 10000; s32b small; @@ -34,7 +35,8 @@ bool_ quest_nazgul_gen_hook(char *fmt) return FALSE; } -bool_ quest_nazgul_finish_hook(char *fmt) + +static bool_ quest_nazgul_finish_hook(const char *fmt) { object_type forge, *q_ptr; s32b q_idx; @@ -64,7 +66,8 @@ bool_ quest_nazgul_finish_hook(char *fmt) return TRUE; } -bool_ quest_nazgul_dump_hook(char *fmt) + +static bool_ quest_nazgul_dump_hook(const char *fmt) { if (cquest.status >= QUEST_STATUS_COMPLETED) { @@ -72,7 +75,8 @@ bool_ quest_nazgul_dump_hook(char *fmt) } return (FALSE); } -bool_ quest_nazgul_forbid_hook(char *fmt) + +static bool_ quest_nazgul_forbid_hook(const char *fmt) { s32b q_idx; q_idx = get_next_arg(fmt); @@ -86,7 +90,8 @@ bool_ quest_nazgul_forbid_hook(char *fmt) } return (FALSE); } -bool_ quest_nazgul_death_hook(char *fmt) + +static bool_ quest_nazgul_death_hook(const char *fmt) { s32b r_idx, m_idx; @@ -103,6 +108,7 @@ bool_ quest_nazgul_death_hook(char *fmt) return (FALSE); } + bool_ quest_nazgul_init_hook(int q_idx) { if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED)) diff --git a/src/q_nirna.c b/src/q_nirna.c index 07991487..d9e178c3 100644 --- a/src/q_nirna.c +++ b/src/q_nirna.c @@ -1,8 +1,9 @@ #include "q_nirna.h" +#include "hooks.h" #define cquest (quest[QUEST_NIRNAETH]) -bool_ quest_nirnaeth_gen_hook(char *fmt) +static bool_ quest_nirnaeth_gen_hook(const char *fmt) { int x, y; int xstart = 2; @@ -40,7 +41,8 @@ bool_ quest_nirnaeth_gen_hook(char *fmt) return TRUE; } -bool_ quest_nirnaeth_finish_hook(char *fmt) + +static bool_ quest_nirnaeth_finish_hook(const char *fmt) { s32b q_idx; @@ -77,7 +79,8 @@ bool_ quest_nirnaeth_finish_hook(char *fmt) return TRUE; } -bool_ quest_nirnaeth_death_hook(char *fmt) + +static bool_ quest_nirnaeth_death_hook(const char *fmt) { if (p_ptr->inside_quest != QUEST_NIRNAETH) return FALSE; @@ -85,7 +88,8 @@ bool_ quest_nirnaeth_death_hook(char *fmt) return FALSE; } -bool_ quest_nirnaeth_stair_hook(char *fmt) + +static bool_ quest_nirnaeth_stair_hook(const char *fmt) { if (p_ptr->inside_quest != QUEST_NIRNAETH) return FALSE; @@ -97,6 +101,7 @@ bool_ quest_nirnaeth_stair_hook(char *fmt) process_hooks_restart = TRUE; return (FALSE); } + bool_ quest_nirnaeth_init_hook(int q_idx) { if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED)) diff --git a/src/q_one.c b/src/q_one.c index f9c71a91..de80afad 100644 --- a/src/q_one.c +++ b/src/q_one.c @@ -1,8 +1,9 @@ #include "q_one.h" +#include "hooks.h" #define cquest (quest[QUEST_ONE]) -bool_ quest_one_move_hook(char *fmt) +static bool_ quest_one_move_hook(const char *fmt) { s32b y, x; cave_type *c_ptr; @@ -67,7 +68,8 @@ bool_ quest_one_move_hook(char *fmt) return FALSE; } -bool_ quest_one_drop_hook(char *fmt) + +static bool_ quest_one_drop_hook(const char *fmt) { s32b o_idx; object_type *o_ptr; @@ -97,7 +99,8 @@ bool_ quest_one_drop_hook(char *fmt) return TRUE; } -bool_ quest_one_wield_hook(char *fmt) + +static bool_ quest_one_wield_hook(const char *fmt) { s32b o_idx; object_type *o_ptr; @@ -154,7 +157,8 @@ bool_ quest_one_wield_hook(char *fmt) return FALSE; } -bool_ quest_one_hp_hook(char *fmt) + +static bool_ quest_one_hp_hook(const char *fmt) { if (cquest.status == QUEST_STATUS_FAILED_DONE) { @@ -171,7 +175,8 @@ bool_ quest_one_hp_hook(char *fmt) } return (FALSE); } -bool_ quest_one_die_hook(char *fmt) + +static bool_ quest_one_die_hook(const char *fmt) { if (cquest.status == QUEST_STATUS_FAILED_DONE) { @@ -190,7 +195,8 @@ bool_ quest_one_die_hook(char *fmt) } return (FALSE); } -bool_ quest_one_identify_hook(char *fmt) + +static bool_ quest_one_identify_hook(const char *fmt) { s32b item; @@ -212,7 +218,8 @@ bool_ quest_one_identify_hook(char *fmt) return (FALSE); } -bool_ quest_one_death_hook(char *fmt) + +static bool_ quest_one_death_hook(const char *fmt) { s32b r_idx, m_idx; bool_ ok = FALSE; @@ -292,7 +299,8 @@ bool_ quest_one_death_hook(char *fmt) return (FALSE); } -bool_ quest_one_dump_hook(char *fmt) + +static bool_ quest_one_dump_hook(const char *fmt) { if (cquest.status == QUEST_STATUS_FINISHED) { @@ -304,7 +312,8 @@ bool_ quest_one_dump_hook(char *fmt) } return (FALSE); } -bool_ quest_one_gen_hook(char *fmt) + +static bool_ quest_one_gen_hook(const char *fmt) { s32b x, y, tries = 10000; @@ -334,6 +343,7 @@ bool_ quest_one_gen_hook(char *fmt) return (FALSE); } + bool_ quest_one_init_hook(int q_idx) { if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED)) diff --git a/src/q_poison.c b/src/q_poison.c index 152b7d59..a63dca96 100644 --- a/src/q_poison.c +++ b/src/q_poison.c @@ -1,6 +1,7 @@ #include "q_poison.h" #include "quark.h" #include "messages.h" +#include "hooks.h" #define cquest (quest[QUEST_POISON]) @@ -24,7 +25,7 @@ static bool_ create_molds_hook(int r_idx) else return FALSE; } -bool_ quest_poison_gen_hook(char *fmt) +static bool_ quest_poison_gen_hook(const char *fmt) { int cy = 1, cx = 1, x, y, tries = 10000, r_idx; bool_ (*old_get_mon_num_hook)(int r_idx); @@ -101,7 +102,8 @@ bool_ quest_poison_gen_hook(char *fmt) return FALSE; } -bool_ quest_poison_finish_hook(char *fmt) + +static bool_ quest_poison_finish_hook(const char *fmt) { object_type forge, *q_ptr; s32b q_idx; @@ -132,7 +134,8 @@ bool_ quest_poison_finish_hook(char *fmt) return TRUE; } -bool_ quest_poison_dump_hook(char *fmt) + +static bool_ quest_poison_dump_hook(const char *fmt) { if (cquest.status >= QUEST_STATUS_COMPLETED) { @@ -140,7 +143,8 @@ bool_ quest_poison_dump_hook(char *fmt) } return (FALSE); } -bool_ quest_poison_quest_hook(char *fmt) + +static bool_ quest_poison_quest_hook(const char *fmt) { object_type forge, *q_ptr; s32b q_idx; @@ -163,7 +167,8 @@ bool_ quest_poison_quest_hook(char *fmt) return FALSE; } -bool_ quest_poison_drop_hook(char *fmt) + +static bool_ quest_poison_drop_hook(const char *fmt) { s32b mcnt = 0, i, x, y, o_idx; object_type *o_ptr; @@ -216,6 +221,7 @@ bool_ quest_poison_drop_hook(char *fmt) } return FALSE; } + bool_ quest_poison_init_hook(int q_idx) { /* Get a place to place the poison */ diff --git a/src/q_rand.c b/src/q_rand.c index 998379e2..4296d85d 100644 --- a/src/q_rand.c +++ b/src/q_rand.c @@ -1,4 +1,5 @@ #include "q_rand.h" +#include "hooks.h" static int randquest_hero[] = { 20, 13, 15, 16, 9, 17, 18, 8, -1 }; @@ -215,7 +216,7 @@ static void hero_death(s32b m_idx, s32b r_idx) } } -static bool_ quest_random_death_hook(char *fmt) +static bool_ quest_random_death_hook(const char *fmt) { int r_idx; s32b m_idx; @@ -245,14 +246,14 @@ static bool_ quest_random_death_hook(char *fmt) return (FALSE); } -static bool_ quest_random_turn_hook(char *fmt) +static bool_ quest_random_turn_hook(const char *fmt) { quest[QUEST_RANDOM].data[0] = 0; quest[QUEST_RANDOM].data[1] = 0; return (FALSE); } -static bool_ quest_random_feeling_hook(char *fmt) +static bool_ quest_random_feeling_hook(const char *fmt) { if (!(dungeon_flags1 & DF1_PRINCIPAL)) return (FALSE); if ((dun_level < 1) || (dun_level >= MAX_RANDOM_QUEST)) return (FALSE); @@ -271,7 +272,7 @@ static bool_ quest_random_feeling_hook(char *fmt) return (FALSE); } -static bool_ quest_random_gen_hero_hook(char *fmt) +static bool_ quest_random_gen_hero_hook(const char *fmt) { int i; @@ -302,7 +303,7 @@ static bool_ quest_random_gen_hero_hook(char *fmt) return (FALSE); } -static bool_ quest_random_gen_hook(char *fmt) +static bool_ quest_random_gen_hook(const char *fmt) { s32b x, y, bx0, by0; int xstart; @@ -385,7 +386,7 @@ static bool_ quest_random_gen_hook(char *fmt) return (TRUE); } -static bool_ quest_random_dump_hook(char *fmt) +static bool_ quest_random_dump_hook(const char *fmt) { static char *number[] = { "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" }; diff --git a/src/q_rand.h b/src/q_rand.h index ea88b56c..6d4e5eba 100644 --- a/src/q_rand.h +++ b/src/q_rand.h @@ -6,6 +6,7 @@ extern "C" { #endif +void initialize_random_quests(int n); bool_ is_randhero(int level); bool_ quest_random_init_hook(int q_idx); bool_ quest_random_describe(FILE *fff); diff --git a/src/q_shroom.c b/src/q_shroom.c index 96e1ac81..d402c818 100644 --- a/src/q_shroom.c +++ b/src/q_shroom.c @@ -1,11 +1,12 @@ #include "q_shroom.h" #include "messages.h" +#include "hooks.h" #define cquest (quest[QUEST_SHROOM]) -bool_ quest_shroom_speak_hook(char *fmt); +static bool_ quest_shroom_speak_hook(const char *fmt); -bool_ quest_shroom_town_gen_hook(char *fmt) +static bool_ quest_shroom_town_gen_hook(const char *fmt) { int m_idx, x = 1, y = 1, tries = 10000; s32b small; @@ -83,7 +84,8 @@ bool_ quest_shroom_town_gen_hook(char *fmt) return FALSE; } -bool_ quest_shroom_death_hook(char *fmt) + +static bool_ quest_shroom_death_hook(const char *fmt) { s32b r_idx, m_idx; @@ -101,7 +103,8 @@ bool_ quest_shroom_death_hook(char *fmt) return FALSE; } -bool_ quest_shroom_give_hook(char *fmt) + +static bool_ quest_shroom_give_hook(const char *fmt) { object_type *o_ptr; monster_type *m_ptr; @@ -185,7 +188,8 @@ bool_ quest_shroom_give_hook(char *fmt) return TRUE; } -bool_ quest_shroom_speak_hook(char *fmt) + +static bool_ quest_shroom_speak_hook(const char *fmt) { s32b m_idx = get_next_arg(fmt); @@ -222,7 +226,8 @@ bool_ quest_shroom_speak_hook(char *fmt) } return (TRUE); } -bool_ quest_shroom_chat_hook(char *fmt) + +static bool_ quest_shroom_chat_hook(const char *fmt) { monster_type *m_ptr; s32b m_idx; @@ -267,6 +272,7 @@ bool_ quest_shroom_chat_hook(char *fmt) return TRUE; } + bool_ quest_shroom_init_hook(int q_idx) { /* Get a number of 'shrooms */ diff --git a/src/q_spider.c b/src/q_spider.c index b8731a33..03305f59 100644 --- a/src/q_spider.c +++ b/src/q_spider.c @@ -1,8 +1,9 @@ #include "q_spider.h" +#include "hooks.h" #define cquest (quest[QUEST_SPIDER]) -bool_ quest_spider_gen_hook(char *fmt) +static bool_ quest_spider_gen_hook(const char *fmt) { int x, y; int xstart = 2; @@ -31,7 +32,8 @@ bool_ quest_spider_gen_hook(char *fmt) return TRUE; } -bool_ quest_spider_death_hook(char *fmt) + +static bool_ quest_spider_death_hook(const char *fmt) { int i, mcnt = 0; @@ -67,7 +69,8 @@ bool_ quest_spider_death_hook(char *fmt) return (FALSE); } -bool_ quest_spider_finish_hook(char *fmt) + +static bool_ quest_spider_finish_hook(const char *fmt) { object_type forge, *q_ptr; s32b q_idx; @@ -97,6 +100,7 @@ bool_ quest_spider_finish_hook(char *fmt) return TRUE; } + bool_ quest_spider_init_hook(int q_idx) { if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED)) diff --git a/src/q_thief.c b/src/q_thief.c index b341c572..912309a9 100644 --- a/src/q_thief.c +++ b/src/q_thief.c @@ -1,8 +1,9 @@ #include "q_thief.h" +#include "hooks.h" #define cquest (quest[QUEST_THIEVES]) -bool_ quest_thieves_gen_hook(char *fmt) +static bool_ quest_thieves_gen_hook(const char *fmt) { int x, y; int xstart = 2; @@ -62,7 +63,8 @@ bool_ quest_thieves_gen_hook(char *fmt) return TRUE; } -bool_ quest_thieves_hook(char *fmt) + +static bool_ quest_thieves_hook(const char *fmt) { int i, mcnt = 0; @@ -114,7 +116,8 @@ bool_ quest_thieves_hook(char *fmt) } return FALSE; } -bool_ quest_thieves_finish_hook(char *fmt) + +static bool_ quest_thieves_finish_hook(const char *fmt) { s32b q_idx; @@ -147,7 +150,7 @@ bool_ quest_thieves_finish_hook(char *fmt) return TRUE; } -bool_ quest_thieves_feeling_hook(char *fmt) +static bool_ quest_thieves_feeling_hook(const char *fmt) { if (p_ptr->inside_quest != QUEST_THIEVES) return FALSE; diff --git a/src/q_thrain.c b/src/q_thrain.c index 1b505a20..c22b39e9 100644 --- a/src/q_thrain.c +++ b/src/q_thrain.c @@ -1,10 +1,11 @@ #include "q_thrain.h" #include "quark.h" #include "messages.h" +#include "hooks.h" #define cquest (quest[QUEST_THRAIN]) -bool_ quest_thrain_death_hook(char *fmt) +static bool_ quest_thrain_death_hook(const char *fmt) { s32b m_idx; int r, x, y; @@ -90,7 +91,7 @@ bool_ quest_thrain_death_hook(char *fmt) return (FALSE); } -bool_ quest_thrain_gen_hook(char *fmt) +static bool_ quest_thrain_gen_hook(const char *fmt) { s32b x, y, bx0, by0; int xstart; @@ -161,7 +162,8 @@ bool_ quest_thrain_gen_hook(char *fmt) return (TRUE); } -bool_ quest_thrain_feeling_hook(char *fmt) + +static bool_ quest_thrain_feeling_hook(const char *fmt) { if (dungeon_type != DUNGEON_DOL_GULDUR) return (FALSE); if (cquest.data[0] != dun_level) return (FALSE); @@ -173,7 +175,8 @@ bool_ quest_thrain_feeling_hook(char *fmt) return (FALSE); } -bool_ quest_thrain_move_hook(char *fmt) + +static bool_ quest_thrain_move_hook(const char *fmt) { s32b y; s32b x; @@ -204,12 +207,14 @@ bool_ quest_thrain_move_hook(char *fmt) return (FALSE); } -bool_ quest_thrain_turn_hook(char *fmt) + +static bool_ quest_thrain_turn_hook(const char *fmt) { cquest.data[1] = 0; cquest.data[2] = 0; return (FALSE); } + bool_ quest_thrain_init_hook(int q) { if (!cquest.data[0]) diff --git a/src/q_troll.c b/src/q_troll.c index b3875418..4a38f2d0 100644 --- a/src/q_troll.c +++ b/src/q_troll.c @@ -1,8 +1,9 @@ #include "q_troll.h" +#include "hooks.h" #define cquest (quest[QUEST_TROLL]) -bool_ quest_troll_gen_hook(char *fmt) +static bool_ quest_troll_gen_hook(const char *fmt) { int x, y; int xstart = 2; @@ -94,7 +95,8 @@ bool_ quest_troll_gen_hook(char *fmt) cquest.data[0] = FALSE; return TRUE; } -bool_ quest_troll_finish_hook(char *fmt) + +static bool_ quest_troll_finish_hook(const char *fmt) { s32b q_idx; @@ -114,7 +116,8 @@ bool_ quest_troll_finish_hook(char *fmt) return TRUE; } -bool_ quest_troll_death_hook(char *fmt) + +static bool_ quest_troll_death_hook(const char *fmt) { int x, y, xstart = 2, ystart = 2; s32b r_idx, m_idx; @@ -167,6 +170,7 @@ bool_ quest_troll_death_hook(char *fmt) return FALSE; } + bool_ quest_troll_init_hook(int q_idx) { if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED)) diff --git a/src/q_ultrag.c b/src/q_ultrag.c index a5d28369..0eb50d15 100644 --- a/src/q_ultrag.c +++ b/src/q_ultrag.c @@ -1,8 +1,9 @@ #include "q_ultrag.h" +#include "hooks.h" #define cquest (quest[QUEST_ULTRA_GOOD]) -bool_ quest_ultra_good_move_hook(char *fmt) +static bool_ quest_ultra_good_move_hook(const char *fmt) { s32b y, x; cave_type *c_ptr; @@ -74,7 +75,7 @@ bool_ quest_ultra_good_move_hook(char *fmt) return FALSE; } -bool_ quest_ultra_good_stair_hook(char *fmt) +static bool_ quest_ultra_good_stair_hook(const char *fmt) { cptr dir; @@ -137,7 +138,7 @@ bool_ quest_ultra_good_stair_hook(char *fmt) return FALSE; } -bool_ quest_ultra_good_recall_hook(char *fmt) +static bool_ quest_ultra_good_recall_hook(const char *fmt) { if ((dungeon_type != DUNGEON_VOID) && (dungeon_type != DUNGEON_NETHER_REALM)) return FALSE; @@ -146,7 +147,7 @@ bool_ quest_ultra_good_recall_hook(char *fmt) return TRUE; } -bool_ quest_ultra_good_death_hook(char *fmt) +static bool_ quest_ultra_good_death_hook(const char *fmt) { s32b m_idx = get_next_arg(fmt); @@ -232,7 +233,8 @@ bool_ quest_ultra_good_death_hook(char *fmt) } return (FALSE); } -bool_ quest_ultra_good_dump_hook(char *fmt) + +static bool_ quest_ultra_good_dump_hook(const char *fmt) { if (quest[QUEST_ULTRA_GOOD].status >= QUEST_STATUS_TAKEN) { diff --git a/src/q_wight.c b/src/q_wight.c index 4be72fc2..ce4c5ac4 100644 --- a/src/q_wight.c +++ b/src/q_wight.c @@ -1,9 +1,10 @@ #include "q_wight.h" #include "quark.h" +#include "hooks.h" #define cquest (quest[QUEST_WIGHT]) -bool_ quest_wight_gen_hook(char *fmt) +static bool_ quest_wight_gen_hook(const char *fmt) { int x, y; int xstart = 2; @@ -103,7 +104,8 @@ bool_ quest_wight_gen_hook(char *fmt) return TRUE; } -bool_ quest_wight_death_hook(char *fmt) + +static bool_ quest_wight_death_hook(const char *fmt) { s32b r_idx, m_idx; @@ -127,7 +129,8 @@ bool_ quest_wight_death_hook(char *fmt) return (FALSE); } -bool_ quest_wight_finish_hook(char *fmt) + +static bool_ quest_wight_finish_hook(const char *fmt) { s32b q_idx; q_idx = get_next_arg(fmt); @@ -146,6 +149,7 @@ bool_ quest_wight_finish_hook(char *fmt) return TRUE; } + bool_ quest_wight_init_hook(int q_idx) { if ((cquest.status >= QUEST_STATUS_TAKEN) && (cquest.status < QUEST_STATUS_FINISHED)) diff --git a/src/q_wolves.c b/src/q_wolves.c index badbd319..5da28ee7 100644 --- a/src/q_wolves.c +++ b/src/q_wolves.c @@ -1,8 +1,9 @@ #include "q_wolves.h" +#include "hooks.h" #define cquest (quest[QUEST_WOLVES]) -bool_ quest_wolves_gen_hook(char *fmt) +static bool_ quest_wolves_gen_hook(const char *fmt) { int x, y, i; int xstart = 2; @@ -70,7 +71,7 @@ bool_ quest_wolves_gen_hook(char *fmt) return TRUE; } -bool_ quest_wolves_death_hook(char *fmt) +static bool_ quest_wolves_death_hook(const char *fmt) { int i, mcnt = 0; @@ -102,7 +103,7 @@ bool_ quest_wolves_death_hook(char *fmt) return FALSE; } -bool_ quest_wolves_finish_hook(char *fmt) +static bool_ quest_wolves_finish_hook(const char *fmt) { s32b q_idx; diff --git a/src/script.c b/src/script.c index 40f43f95..a9407352 100644 --- a/src/script.c +++ b/src/script.c @@ -11,6 +11,7 @@ */ #include "angband.h" +#include "q_library.h" void init_lua_init() diff --git a/src/skills.c b/src/skills.c index 4df3c1b3..12d5da56 100644 --- a/src/skills.c +++ b/src/skills.c @@ -13,6 +13,7 @@ #include "angband.h" #include +#include "hooks.h" /* * Advance the skill point of the skill specified by i and diff --git a/src/spells2.c b/src/spells2.c index 8778e49f..3e3ac568 100644 --- a/src/spells2.c +++ b/src/spells2.c @@ -11,6 +11,7 @@ */ #include "angband.h" +#include "hooks.h" #define WEIRD_LUCK 12 #define BIAS_LUCK 20 diff --git a/src/store.c b/src/store.c index ff5e89dc..fb413eb8 100644 --- a/src/store.c +++ b/src/store.c @@ -14,6 +14,7 @@ #include "spell_type.h" #include "quark.h" +#include "hooks.h" #define STORE_GENERAL_STORE "General Store" #define STORE_ARMOURY "Armoury" diff --git a/src/tables.c b/src/tables.c index 33330e80..20d24966 100644 --- a/src/tables.c +++ b/src/tables.c @@ -3493,7 +3493,7 @@ quest_type quest[MAX_Q_IDX] = 0, NULL, - quest_null_hook, + NULL, {0, 0}, NULL, }, diff --git a/src/types.h b/src/types.h index 92aa428b..b9529436 100644 --- a/src/types.h +++ b/src/types.h @@ -2226,7 +2226,7 @@ struct power_type }; /* Hooks */ -typedef bool_ (*hook_type)(char *fmt); +typedef bool_ (*hook_type)(const char *fmt); typedef struct hook_move_in hook_move_in; struct hook_move_in { diff --git a/src/wild.c b/src/wild.c index 279b79d9..76ad3136 100644 --- a/src/wild.c +++ b/src/wild.c @@ -11,6 +11,7 @@ */ #include "angband.h" +#include "hooks.h" diff --git a/src/wizard2.c b/src/wizard2.c index 66ddaa38..eb391437 100644 --- a/src/wizard2.c +++ b/src/wizard2.c @@ -11,6 +11,7 @@ */ #include "angband.h" +#include "hooks.h" void do_cmd_wizard_body(s16b); extern void status_main(void); diff --git a/src/xtra1.c b/src/xtra1.c index 638a2102..821fe508 100644 --- a/src/xtra1.c +++ b/src/xtra1.c @@ -13,6 +13,7 @@ #include "angband.h" #include "messages.h" +#include "hooks.h" /* * Converts stat num into a six-char (right justified) string diff --git a/src/xtra2.c b/src/xtra2.c index f437c6d1..84f3b540 100644 --- a/src/xtra2.c +++ b/src/xtra2.c @@ -16,6 +16,7 @@ #include #include "quark.h" +#include "hooks.h" /* * Invoke The Rush -- cgit v1.2.3 From d777849861081855a9fdc3a6c71ef9510884190e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 25 Mar 2013 13:41:34 +0100 Subject: Sprinkle a little "const" around --- src/types.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/types.h b/src/types.h index b9529436..f0cdec0f 100644 --- a/src/types.h +++ b/src/types.h @@ -2214,10 +2214,10 @@ struct flags_group typedef struct power_type power_type; struct power_type { - char *name; /* Name */ - char *desc_text; /* Text describing power */ - char *gain_text; /* Text displayed on gaining the power */ - char *lose_text; /* Text displayed on losing the power */ + const char *name; /* Name */ + const char *desc_text; /* Text describing power */ + const char *gain_text; /* Text displayed on gaining the power */ + const char *lose_text; /* Text displayed on losing the power */ byte level; /* Min level */ byte cost; /* Mana/Life cost */ -- cgit v1.2.3 From 3f0417be80c0cd9bae1d2aa9a81bc0bcc9ef4841 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 25 Mar 2013 13:48:04 +0100 Subject: Remove monster_mind --- src/loadsave.c | 11 ----------- src/monster2.c | 7 ------- src/types.h | 18 ------------------ 3 files changed, 36 deletions(-) diff --git a/src/loadsave.c b/src/loadsave.c index 1800298d..85c05260 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -1554,17 +1554,6 @@ static void do_monster(monster_type *m_ptr, int flag) do_byte(&m_ptr->blow[i].d_side, flag); } - /* Mind */ - tmp = (m_ptr->mind) ? TRUE : FALSE; - do_byte((byte*)&tmp, flag); - if (tmp) - { - if (flag == LS_LOAD) - { - MAKE(m_ptr->mind, monster_mind); - } - } - /* Special race */ tmp = (m_ptr->sr_ptr) ? TRUE : FALSE; do_byte((byte*)&tmp, flag); diff --git a/src/monster2.c b/src/monster2.c index 4c4df91d..9d79f73a 100644 --- a/src/monster2.c +++ b/src/monster2.c @@ -495,8 +495,6 @@ void delete_monster_idx(int i) /* Delete mind & special race if needed */ if (m_ptr->sr_ptr) KILL(m_ptr->sr_ptr, monster_race); - if (m_ptr->mind) - KILL(m_ptr->mind, monster_mind); /* Wipe the Monster */ m_ptr = WIPE(m_ptr, monster_type); @@ -619,8 +617,6 @@ static void compact_monsters_aux(int i1, int i2) /* Delete mind & special race if needed */ if (m_list[i1].sr_ptr) KILL(m_list[i1].sr_ptr, monster_race); - if (m_list[i1].mind) - KILL(m_list[i1].mind, monster_mind); /* Wipe the hole */ m_ptr = WIPE(&m_list[i1], monster_type); @@ -743,8 +739,6 @@ void wipe_m_list(void) /* Delete mind & special race if needed */ if (m_ptr->sr_ptr) KILL(m_ptr->sr_ptr, monster_race); - if (m_ptr->mind) - KILL(m_ptr->mind, monster_mind); /* Wipe the Monster */ @@ -2360,7 +2354,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status) /* No special, no mind */ m_ptr->sr_ptr = place_monster_one_race; - m_ptr->mind = NULL; /* Place the monster at the location */ m_ptr->fy = y; diff --git a/src/types.h b/src/types.h index f0cdec0f..2339a9ce 100644 --- a/src/types.h +++ b/src/types.h @@ -835,22 +835,6 @@ struct object_type }; -/* - * Monster mind, use for skills and such - */ -typedef struct monster_mind monster_mind; -struct monster_mind -{ - /* - * Without this, bcc can't compile because it does not - * allow empty structure. Remove this when you add some - * variables to this structure. -- Kusunose - */ - byte dummy; -}; - - - /* * Monster information, for a specific monster. * @@ -910,8 +894,6 @@ struct monster_type s16b possessor; /* Is it under the control of a possessor ? */ monster_race *sr_ptr; /* Does it have a specific race(not in r_info) */ - - monster_mind *mind; /* Does it have a mind? */ }; -- cgit v1.2.3 From de312e85022558780a3357a655b9742793b6484f Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 25 Mar 2013 16:43:50 +0100 Subject: Remove unused second parameter for disturb() --- src/cave.c | 7 +- src/cmd1.c | 38 +++--- src/cmd2.c | 18 +-- src/dungeon.c | 34 +++--- src/externs.h | 2 +- src/files.c | 2 +- src/melee1.c | 8 +- src/melee2.c | 370 ++++++++++++++++++++++++++++----------------------------- src/monster2.c | 8 +- src/object1.c | 2 +- src/spells1.c | 10 +- src/traps.c | 2 +- src/xtra2.c | 24 ++-- 13 files changed, 260 insertions(+), 265 deletions(-) diff --git a/src/cave.c b/src/cave.c index 9f26196a..2a02f017 100644 --- a/src/cave.c +++ b/src/cave.c @@ -4899,15 +4899,10 @@ void object_track(object_type *o_ptr) * * The first arg indicates a major disturbance, which affects search. * - * The second arg is currently unused, but could induce output flush. - * * All disturbance cancels repeated commands, resting, and running. */ -void disturb(int stop_search, int unused_flag) +void disturb(int stop_search) { - /* Unused */ - unused_flag = unused_flag; - /* Cancel auto-commands */ /* command_new = 0; */ diff --git a/src/cmd1.c b/src/cmd1.c index 46fc15eb..ff493174 100644 --- a/src/cmd1.c +++ b/src/cmd1.c @@ -563,7 +563,7 @@ void search(void) msg_print("You have found a trap."); /* Disturb */ - disturb(0, 0); + disturb(0); } /* Secret door */ @@ -578,7 +578,7 @@ void search(void) lite_spot(y, x); /* Disturb */ - disturb(0, 0); + disturb(0); } /* Scan all objects in the grid */ @@ -609,7 +609,7 @@ void search(void) object_known(o_ptr); /* Notice it */ - disturb(0, 0); + disturb(0); } } } @@ -645,7 +645,7 @@ static void hit_trap(void) /* Disturb the player */ - disturb(0, 0); + disturb(0); /* Get the cave grid */ c_ptr = &cave[p_ptr->py][p_ptr->px]; @@ -815,7 +815,7 @@ static void carried_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath, if (!effect || check_hit2(power, rlev, ac)) { /* Always disturbing */ - disturb(1, 0); + disturb(1); /* Describe the attack method */ switch (method) @@ -1208,7 +1208,7 @@ static void carried_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath, case RBM_CHARGE: { /* Disturb */ - disturb(1, 0); + disturb(1); /* Message */ msg_format("%s misses %s.", sym_name, t_name); @@ -1334,7 +1334,7 @@ static void incarnate_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath, if (!effect || check_hit2(power, rlev, ac)) { /* Always disturbing */ - disturb(1, 0); + disturb(1); /* Describe the attack method */ switch (method) @@ -1727,7 +1727,7 @@ static void incarnate_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath, case RBM_CHARGE: { /* Disturb */ - disturb(1, 0); + disturb(1); /* Message */ msg_format("You miss %s.", t_name); @@ -2187,7 +2187,7 @@ void py_attack(int y, int x, int max_blow) int weap; /* Disturb the player */ - disturb(0, 0); + disturb(0); if (r_info[p_ptr->body_monster].flags1 & RF1_NEVER_BLOW) { @@ -3210,7 +3210,7 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm) oktomove = FALSE; /* Disturb the player */ - disturb(0, 0); + disturb(0); if (p_ptr->prob_travel) { @@ -3327,7 +3327,7 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm) energy_use = 0; } - disturb(0, 0); /* To avoid a loop with running */ + disturb(0); /* To avoid a loop with running */ oktomove = FALSE; } @@ -3350,7 +3350,7 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm) if (old_dtrap && !new_dtrap) { /* Disturb player */ - disturb(0, 0); + disturb(0); /* but don't take a turn */ energy_use = 0; @@ -3459,7 +3459,7 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm) if (c_ptr->feat == FEAT_SHOP) { /* Disturb */ - disturb(0, 0); + disturb(0); /* Hack -- Enter store */ command_new = '_'; @@ -3482,7 +3482,7 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm) !(f_info[cave[y][x].feat].flags1 & FF1_DOOR)) { /* Disturb */ - disturb(0, 0); + disturb(0); if (!(c_ptr->info & (CAVE_TRDT))) { @@ -3501,7 +3501,7 @@ void move_player_aux(int dir, int do_pickup, int run, bool_ disarm) else if (c_ptr->inscription) { /* Disturb */ - disturb(0, 0); + disturb(0); msg_format("There is an inscription here: %s", inscription_info[c_ptr->inscription].text); @@ -4284,7 +4284,7 @@ void run_step(int dir) msg_print("You cannot run in that direction."); /* Disturb */ - disturb(0, 0); + disturb(0); /* Done */ return; @@ -4304,7 +4304,7 @@ void run_step(int dir) if (run_test()) { /* Disturb */ - disturb(0, 0); + disturb(0); /* Done */ return; @@ -4336,7 +4336,7 @@ void step_effects(int y, int x, int do_pickup) if (cave[y][x].feat == FEAT_SHOP) { /* Disturb */ - disturb(0, 0); + disturb(0); /* Hack -- Enter store */ command_new = KTRL('V'); @@ -4346,7 +4346,7 @@ void step_effects(int y, int x, int do_pickup) else if (cave[y][x].t_idx != 0) { /* Disturb */ - disturb(0, 0); + disturb(0); if (!(cave[y][x].info & CAVE_TRDT)) { diff --git a/src/cmd2.c b/src/cmd2.c index 28a3dc1e..67f25098 100644 --- a/src/cmd2.c +++ b/src/cmd2.c @@ -1225,7 +1225,7 @@ void do_cmd_open(void) process_hooks(HOOK_OPEN, "(d)", is_quest(dun_level)); /* Cancel repeat unless we may continue */ - if (!more) disturb(0, 0); + if (!more) disturb(0); } @@ -1378,7 +1378,7 @@ void do_cmd_close(void) } /* Cancel repeat unless we may continue */ - if (!more) disturb(0, 0); + if (!more) disturb(0); } @@ -1822,7 +1822,7 @@ void do_cmd_tunnel(void) } /* Cancel repetition unless we can continue */ - if (!more) disturb(0, 0); + if (!more) disturb(0); } @@ -2235,7 +2235,7 @@ void do_cmd_disarm(void) } /* Cancel repeat unless told not to */ - if (!more) disturb(0, 0); + if (!more) disturb(0); } @@ -2444,7 +2444,7 @@ void do_cmd_bash(void) } /* Unless valid action taken, cancel bash */ - if (!more) disturb(0, 0); + if (!more) disturb(0); } @@ -2532,7 +2532,7 @@ void do_cmd_alter(void) } /* Cancel repetition unless we can continue */ - if (!more) disturb(0, 0); + if (!more) disturb(0); } @@ -2699,7 +2699,7 @@ static void do_cmd_walk_jump(int pickup, bool_ disarm) } /* Cancel repeat unless we may continue */ - if (!more) disturb(0, 0); + if (!more) disturb(0); } @@ -2811,7 +2811,7 @@ void do_cmd_stay(int pickup) if (c_ptr->feat == FEAT_SHOP) { /* Disturb */ - disturb(0, 0); + disturb(0); /* Hack -- enter store */ command_new = '_'; @@ -4364,7 +4364,7 @@ void do_cmd_unwalk() } /* Cancel repetition unless we can continue */ - if (!more) disturb(0, 0); + if (!more) disturb(0); } diff --git a/src/dungeon.c b/src/dungeon.c index 5b462bb8..5f3d9ab6 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -1013,7 +1013,7 @@ static void process_world_corruptions() } else { - disturb(0, 0); + disturb(0); msg_print("Your corruption takes over you, you teleport!"); teleport_player(50); } @@ -1800,7 +1800,7 @@ static void process_world(void) { /* Message */ msg_print("You faint from the lack of food."); - disturb(1, 0); + disturb(1); /* Hack -- faint (bypass free action) */ (void)set_paralyzed(1 + rand_int(5)); @@ -2443,7 +2443,7 @@ static void process_world(void) att &= ~(CLASS_LEGS); att &= ~(CLASS_WALL); - if (disturb_state) disturb(0, 0); + if (disturb_state) disturb(0); } p_ptr->update |= (PU_BODY); @@ -2780,7 +2780,7 @@ static void process_world(void) if (!be_silent) { cmsg_print(TERM_L_DARK, "The Black Breath saps your soul!"); - disturb(0, 0); + disturb(0); } } @@ -2819,14 +2819,14 @@ static void process_world(void) /* The light is now out */ else if (o_ptr->timeout < 1) { - disturb(0, 0); + disturb(0); cmsg_print(TERM_YELLOW, "Your light has gone out!"); } /* The light is getting dim */ else if ((o_ptr->timeout < 100) && (o_ptr->timeout % 10 == 0)) { - if (disturb_minor) disturb(0, 0); + if (disturb_minor) disturb(0); cmsg_print(TERM_YELLOW, "Your light is growing faint."); } } @@ -2869,7 +2869,7 @@ static void process_world(void) if (p_ptr->csp < 0) { p_ptr->csp = 0; - disturb(0, 0); + disturb(0); } /* Redraw */ @@ -2888,7 +2888,7 @@ static void process_world(void) if (p_ptr->csp < 0) { p_ptr->csp = 0; - disturb(0, 0); + disturb(0); p_ptr->maintain_sum = 0; } @@ -2915,7 +2915,7 @@ static void process_world(void) if (p_ptr->chp == 0) { - disturb(0, 0); + disturb(0); } /* Redraw */ @@ -2976,7 +2976,7 @@ static void process_world(void) { if ((o_ptr->ident & IDENT_CURSED) && !p_ptr->anti_tele) { - disturb(0, 0); + disturb(0); /* Teleport player */ teleport_player(40); @@ -2991,7 +2991,7 @@ static void process_world(void) } else if (get_check("Teleport? ")) { - disturb(0, 0); + disturb(0); teleport_player(50); } } @@ -3330,7 +3330,7 @@ static void process_world(void) if (p_ptr->word_recall == 0) { /* Disturbing! */ - disturb(0, 0); + disturb(0); /* Determine the level */ if (p_ptr->inside_quest) @@ -4554,7 +4554,7 @@ void process_player(void) /* Stop resting */ if ((p_ptr->chp == p_ptr->mhp) && (p_ptr->csp >= p_ptr->msp)) { - disturb(0, 0); + disturb(0); } } @@ -4585,7 +4585,7 @@ void process_player(void) if (stop) { - disturb(0, 0); + disturb(0); } p_ptr->redraw |= (PR_STATE); } @@ -4607,7 +4607,7 @@ void process_player(void) flush(); /* Disturb */ - disturb(0, 0); + disturb(0); /* Hack -- Show a Message */ msg_print("Cancelled."); @@ -4657,7 +4657,7 @@ void process_player(void) o_ptr = &p_ptr->inventory[item]; /* Disturbing */ - disturb(0, 0); + disturb(0); /* Warning */ msg_print("Your pack overflows!"); @@ -5003,7 +5003,7 @@ static void dungeon(void) /* Disturb */ - disturb(1, 0); + disturb(1); /* Track maximum player level */ if (p_ptr->max_plv < p_ptr->lev) diff --git a/src/externs.h b/src/externs.h index 28e99e1c..41b59cb3 100644 --- a/src/externs.h +++ b/src/externs.h @@ -614,7 +614,7 @@ extern void scatter(int *yp, int *xp, int y, int x, int d); extern void health_track(int m_idx); extern void monster_race_track(int r_idx, int ego); extern void object_track(object_type *o_ptr); -extern void disturb(int stop_search, int flush_output); +extern void disturb(int stop_search); extern int is_quest(int level); extern int random_quest_number(void); extern int new_effect(int type, int dam, int time, int cy, int cx, int rad, s32b flags); diff --git a/src/files.c b/src/files.c index c97315fc..d056c125 100644 --- a/src/files.c +++ b/src/files.c @@ -4216,7 +4216,7 @@ void do_cmd_save_game(void) if (!is_autosave) { /* Disturb the player */ - disturb(1, 0); + disturb(1); } /* Clear messages */ diff --git a/src/melee1.c b/src/melee1.c index 157656a9..cc0f8ee3 100644 --- a/src/melee1.c +++ b/src/melee1.c @@ -261,7 +261,7 @@ bool_ carried_make_attack_normal(int r_idx) if (!effect || check_hit(power, rlev)) { /* Always disturbing */ - disturb(1, 0); + disturb(1); /* Hack -- Apply "protection from evil" */ if ((p_ptr->protevil > 0) && @@ -1280,7 +1280,7 @@ bool_ carried_make_attack_normal(int r_idx) case RBM_CHARGE: /* Disturbing */ - disturb(1, 0); + disturb(1); /* Message */ msg_format("%s misses you.", sym_name); @@ -1525,7 +1525,7 @@ bool_ make_attack_normal(int m_idx, byte divis) int chance = p_ptr->dodge_chance - ((rlev * 5) / 6); /* Always disturbing */ - disturb(1, 0); + disturb(1); if ((chance > 0) && magik(chance)) { @@ -3011,7 +3011,7 @@ bool_ make_attack_normal(int m_idx, byte divis) if (m_ptr->ml) { /* Disturbing */ - disturb(1, 0); + disturb(1); /* Message */ msg_format("%^s misses you.", m_name); diff --git a/src/melee2.c b/src/melee2.c index bc3fc75b..0a139f89 100644 --- a/src/melee2.c +++ b/src/melee2.c @@ -1156,7 +1156,7 @@ static bool_ monst_spell_monst(int m_idx) case 96 + 0: { if (!direct) break; - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_m) monster_msg("You hear a shriek."); else monster_msg("%^s shrieks at %s.", m_name, t_name); wake_up = TRUE; @@ -1172,7 +1172,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_S_ANIMAL */ case 96 + 2: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically summons an animal!", m_name); for (k = 0; k < 1; k++) @@ -1189,7 +1189,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_ROCKET */ case 96 + 3: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear an explosion!"); else if (blind) monster_msg("%^s shoots something.", m_name); else monster_msg("%^s fires a rocket at %s.", m_name, t_name); @@ -1201,7 +1201,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_ARROW_1 */ case 96 + 4: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear a strange noise."); else if (blind) monster_msg("%^s makes a strange noise.", m_name); else monster_msg("%^s fires an arrow at %s.", m_name, t_name); @@ -1213,7 +1213,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_ARROW_2 */ case 96 + 5: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear a strange noise."); else if (blind) monster_msg("%^s makes a strange noise.", m_name); else monster_msg("%^s fires an arrow at %s.", m_name, t_name); @@ -1225,7 +1225,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_ARROW_3 */ case 96 + 6: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear a strange noise."); else if (blind) monster_msg("%^s makes a strange noise.", m_name); @@ -1239,7 +1239,7 @@ static bool_ monst_spell_monst(int m_idx) case 96 + 7: { if (!see_either) monster_msg("You hear a strange noise."); - else if (disturb_other) disturb(1, 0); + else if (disturb_other) disturb(1); if (blind) monster_msg("%^s makes a strange noise.", m_name); else monster_msg("%^s fires a missile at %s.", m_name, t_name); sound(SOUND_SHOOT); @@ -1250,7 +1250,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_ACID */ case 96 + 8: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes acid at %s.", m_name, t_name); @@ -1263,7 +1263,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_ELEC */ case 96 + 9: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes lightning at %s.", m_name, t_name); @@ -1276,7 +1276,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_FIRE */ case 96 + 10: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes fire at %s.", m_name, t_name); @@ -1289,7 +1289,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_COLD */ case 96 + 11: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes frost at %s.", m_name, t_name); @@ -1302,7 +1302,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_POIS */ case 96 + 12: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes gas at %s.", m_name, t_name); @@ -1315,7 +1315,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_NETH */ case 96 + 13: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes nether at %s.", m_name, t_name); @@ -1328,7 +1328,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_LITE */ case 96 + 14: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes light at %s.", m_name, t_name); @@ -1341,7 +1341,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_DARK */ case 96 + 15: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes darkness at %s.", m_name, t_name); @@ -1354,7 +1354,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_CONF */ case 96 + 16: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes confusion at %s.", m_name, t_name); @@ -1367,7 +1367,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_SOUN */ case 96 + 17: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes sound at %s.", m_name, t_name); @@ -1380,7 +1380,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_CHAO */ case 96 + 18: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes chaos at %s.", m_name, t_name); @@ -1393,7 +1393,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_DISE */ case 96 + 19: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes disenchantment at %s.", m_name, t_name); @@ -1406,7 +1406,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_NEXU */ case 96 + 20: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes nexus at %s.", m_name, t_name); @@ -1419,7 +1419,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_TIME */ case 96 + 21: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes time at %s.", m_name, t_name); @@ -1432,7 +1432,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_INER */ case 96 + 22: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes inertia at %s.", m_name, t_name); @@ -1445,7 +1445,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_GRAV */ case 96 + 23: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes gravity at %s.", m_name, t_name); @@ -1458,7 +1458,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_SHAR */ case 96 + 24: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes shards at %s.", m_name, t_name); @@ -1471,7 +1471,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_PLAS */ case 96 + 25: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes plasma at %s.", m_name, t_name); @@ -1484,7 +1484,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_WALL */ case 96 + 26: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes force at %s.", m_name, t_name); @@ -1497,7 +1497,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_MANA */ case 96 + 27: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes magical energy at %s.", m_name, t_name); @@ -1510,7 +1510,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BA_NUKE */ case 96 + 28: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear someone mumble."); else if (blind) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s casts a ball of radiation at %s.", m_name, t_name); @@ -1523,7 +1523,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_NUKE */ case 96 + 29: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes toxic waste at %s.", m_name, t_name); @@ -1536,7 +1536,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BA_CHAO */ case 96 + 30: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear someone mumble frighteningly."); else if (blind) monster_msg("%^s mumbles frighteningly.", m_name); else monster_msg("%^s invokes a raw Chaos upon %s.", m_name, t_name); @@ -1549,7 +1549,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF4_BR_DISI -> Breathe Disintegration */ case 96 + 31: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg("You hear breathing noise."); else if (blind) monster_msg("%^s breathes.", m_name); else monster_msg("%^s breathes disintegration at %s.", m_name, t_name); @@ -1562,7 +1562,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF5_BA_ACID */ case 128 + 0: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg ("You hear someone mumble."); else if (blind) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s casts an acid ball at %s.", m_name, t_name); @@ -1573,7 +1573,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF5_BA_ELEC */ case 128 + 1: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg ("You hear someone mumble."); else if (blind) monster_msg("%^s mumbles.", m_name); @@ -1585,7 +1585,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF5_BA_FIRE */ case 128 + 2: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg ("You hear someone mumble."); else if (blind) monster_msg("%^s mumbles.", m_name); @@ -1597,7 +1597,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF5_BA_COLD */ case 128 + 3: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg ("You hear someone mumble."); else if (blind) monster_msg("%^s mumbles.", m_name); @@ -1609,7 +1609,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF5_BA_POIS */ case 128 + 4: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg ("You hear someone mumble."); else if (blind) monster_msg("%^s mumbles.", m_name); @@ -1621,7 +1621,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF5_BA_NETH */ case 128 + 5: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg ("You hear someone mumble."); else if (blind) monster_msg("%^s mumbles.", m_name); @@ -1633,7 +1633,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF5_BA_WATE */ case 128 + 6: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg ("You hear someone mumble."); else if (blind) monster_msg("%^s mumbles.", m_name); @@ -1646,7 +1646,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF5_BA_MANA */ case 128 + 7: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg ("You hear someone mumble powerfully."); else if (blind) monster_msg("%^s mumbles powerfully.", m_name); @@ -1658,7 +1658,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF5_BA_DARK */ case 128 + 8: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_either) monster_msg ("You hear someone mumble powerfully."); else if (blind) monster_msg("%^s mumbles powerfully.", m_name); @@ -1713,7 +1713,7 @@ static bool_ monst_spell_monst(int m_idx) { if (!direct) break; - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!seen) { @@ -1758,7 +1758,7 @@ static bool_ monst_spell_monst(int m_idx) case 128 + 11: { if (!direct) break; - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!seen) { /* */ @@ -1804,7 +1804,7 @@ static bool_ monst_spell_monst(int m_idx) case 128 + 12: { if (!direct) break; - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s points at %s and curses.", m_name, t_name); if (t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10) @@ -1825,7 +1825,7 @@ static bool_ monst_spell_monst(int m_idx) case 128 + 13: { if (!direct) break; - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s points at %s and curses horribly.", m_name, t_name); if (t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10) @@ -1845,7 +1845,7 @@ static bool_ monst_spell_monst(int m_idx) case 128 + 14: { if (!direct) break; - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s points at %s, incanting terribly!", m_name, t_name); if (t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10) @@ -1865,7 +1865,7 @@ static bool_ monst_spell_monst(int m_idx) case 128 + 15: { if (!direct) break; - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s points at %s, screaming the word 'DIE!'", m_name, t_name); if (t_ptr->level > randint((rlev - 10) < 1 ? 1 : (rlev - 10)) + 10) @@ -1884,7 +1884,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF5_BO_ACID */ case 128 + 16: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s casts an acid bolt at %s.", m_name, t_name); monst_bolt_monst(m_idx, y, x, GF_ACID, @@ -1895,7 +1895,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF5_BO_ELEC */ case 128 + 17: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s casts a lightning bolt at %s.", m_name, t_name); monst_bolt_monst(m_idx, y, x, GF_ELEC, @@ -1906,7 +1906,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF5_BO_FIRE */ case 128 + 18: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s casts a fire bolt at %s.", m_name, t_name); monst_bolt_monst(m_idx, y, x, GF_FIRE, @@ -1917,7 +1917,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF5_BO_COLD */ case 128 + 19: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s casts a frost bolt at %s.", m_name, t_name); monst_bolt_monst(m_idx, y, x, GF_COLD, @@ -1935,7 +1935,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF5_BO_NETH */ case 128 + 21: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s casts a nether bolt at %s.", m_name, t_name); monst_bolt_monst(m_idx, y, x, GF_NETHER, @@ -1946,7 +1946,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF5_BO_WATE */ case 128 + 22: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s casts a water bolt at %s.", m_name, t_name); monst_bolt_monst(m_idx, y, x, GF_WATER, @@ -1957,7 +1957,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF5_BO_MANA */ case 128 + 23: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s casts a mana bolt at %s.", m_name, t_name); monst_bolt_monst(m_idx, y, x, GF_MANA, @@ -1968,7 +1968,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF5_BO_PLAS */ case 128 + 24: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s casts a plasma bolt at %s.", m_name, t_name); monst_bolt_monst(m_idx, y, x, GF_PLASMA, @@ -1979,7 +1979,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF5_BO_ICEE */ case 128 + 25: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s casts an ice bolt at %s.", m_name, t_name); monst_bolt_monst(m_idx, y, x, GF_ICE, @@ -1990,7 +1990,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF5_MISSILE */ case 128 + 26: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s casts a magic missile at %s.", m_name, t_name); monst_bolt_monst(m_idx, y, x, GF_MISSILE, @@ -2002,7 +2002,7 @@ static bool_ monst_spell_monst(int m_idx) case 128 + 27: { if (!direct) break; - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles, and you hear scary noises.", m_name); else monster_msg("%^s casts a fearful illusion at %s.", m_name, t_name); if (tr_ptr->flags3 & RF3_NO_FEAR) @@ -2026,7 +2026,7 @@ static bool_ monst_spell_monst(int m_idx) case 128 + 28: { if (!direct) break; - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s casts a spell, burning %s%s eyes.", m_name, t_name, (!strcmp(t_name, "it") ? "s" : "'s")); @@ -2052,7 +2052,7 @@ static bool_ monst_spell_monst(int m_idx) case 128 + 29: { if (!direct) break; - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles, and you hear puzzling noises.", m_name); else monster_msg("%^s creates a mesmerising illusion in front of %s.", m_name, t_name); if (tr_ptr->flags3 & RF3_NO_CONF) @@ -2076,7 +2076,7 @@ static bool_ monst_spell_monst(int m_idx) case 128 + 30: { if (!direct) break; - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!blind && see_either) monster_msg("%^s drains power from %s%s muscles.", m_name, t_name, (!strcmp(t_name, "it") ? "s" : "'s")); if (tr_ptr->flags1 & RF1_UNIQUE) @@ -2100,7 +2100,7 @@ static bool_ monst_spell_monst(int m_idx) case 128 + 31: { if (!direct) break; - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!blind && see_m) monster_msg("%^s stares intently at %s.", m_name, t_name); if ((tr_ptr->flags1 & RF1_UNIQUE) || (tr_ptr->flags3 & RF3_NO_STUN)) @@ -2124,7 +2124,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_HASTE */ case 160 + 0: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) { monster_msg("%^s mumbles.", m_name); @@ -2155,7 +2155,7 @@ static bool_ monst_spell_monst(int m_idx) case 160 + 1: { if (!direct) break; - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (!see_m) monster_msg("You hear someone invoke the Hand of Doom!"); else if (!blind) monster_msg("%^s invokes the Hand of Doom on %s.", m_name, t_name); else @@ -2186,7 +2186,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_HEAL */ case 160 + 2: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); /* Message */ if (blind || !see_m) @@ -2251,7 +2251,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_S_ANIMALS */ case 160 + 3: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically summons some animals!", m_name); for (k = 0; k < 4; k++) @@ -2268,7 +2268,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_BLINK */ case 160 + 4: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (see_m) monster_msg("%^s blinks away.", m_name); teleport_away(m_idx, 10); break; @@ -2280,7 +2280,7 @@ static bool_ monst_spell_monst(int m_idx) if (dungeon_flags2 & DF2_NO_TELEPORT) break; /* No teleport on special levels */ else { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (see_m) monster_msg("%^s teleports away.", m_name); teleport_away(m_idx, MAX_SIGHT * 2 + 5); break; @@ -2303,7 +2303,7 @@ static bool_ monst_spell_monst(int m_idx) else { bool_ resists_tele = FALSE; - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); monster_msg("%^s teleports %s away.", m_name, t_name); @@ -2349,7 +2349,7 @@ static bool_ monst_spell_monst(int m_idx) case 160 + 9: { if (!direct) break; - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s gestures in shadow.", m_name); if (seen) @@ -2383,7 +2383,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_S_BUG */ case 160 + 13: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically codes some software bugs.", m_name); for (k = 0; k < 6; k++) @@ -2400,7 +2400,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_S_RNG */ case 160 + 14: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically codes some RNGs.", m_name); for (k = 0; k < 6; k++) @@ -2418,7 +2418,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_S_THUNDERLORD */ case 160 + 15: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically summons a Thunderlord!", m_name); for (k = 0; k < 1; k++) @@ -2435,7 +2435,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_SUMMON_KIN */ case 160 + 16: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically summons %s %s.", m_name, m_poss, @@ -2458,7 +2458,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_S_HI_DEMON */ case 160 + 17: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically summons greater demons!", m_name); if (blind && count) monster_msg("You hear heavy steps nearby."); @@ -2472,7 +2472,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_S_MONSTER */ case 160 + 18: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically summons help!", m_name); for (k = 0; k < 1; k++) @@ -2489,7 +2489,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_S_MONSTERS */ case 160 + 19: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically summons monsters!", m_name); for (k = 0; k < 8; k++) @@ -2506,7 +2506,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_S_ANT */ case 160 + 20: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically summons ants.", m_name); for (k = 0; k < 6; k++) @@ -2523,7 +2523,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_S_SPIDER */ case 160 + 21: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically summons spiders.", m_name); for (k = 0; k < 6; k++) @@ -2540,7 +2540,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_S_HOUND */ case 160 + 22: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically summons hounds.", m_name); for (k = 0; k < 6; k++) @@ -2557,7 +2557,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_S_HYDRA */ case 160 + 23: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically summons hydras.", m_name); for (k = 0; k < 6; k++) @@ -2574,7 +2574,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_S_ANGEL */ case 160 + 24: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically summons an angel!", m_name); for (k = 0; k < 1; k++) @@ -2591,7 +2591,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_S_DEMON */ case 160 + 25: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically summons a demon!", m_name); for (k = 0; k < 1; k++) @@ -2608,7 +2608,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_S_UNDEAD */ case 160 + 26: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically summons an undead adversary!", m_name); for (k = 0; k < 1; k++) @@ -2625,7 +2625,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_S_DRAGON */ case 160 + 27: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically summons a dragon!", m_name); for (k = 0; k < 1; k++) @@ -2642,7 +2642,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_S_HI_UNDEAD */ case 160 + 28: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically summons greater undead!", m_name); for (k = 0; k < 8; k++) @@ -2662,7 +2662,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_S_HI_DRAGON */ case 160 + 29: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically summons ancient dragons!", m_name); for (k = 0; k < 8; k++) @@ -2682,7 +2682,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_S_WRAITH */ case 160 + 30: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically summons a wraith!", m_name); @@ -2702,7 +2702,7 @@ static bool_ monst_spell_monst(int m_idx) /* RF6_S_UNIQUE */ case 160 + 31: { - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); if (blind || !see_m) monster_msg("%^s mumbles.", m_name); else monster_msg("%^s magically summons special opponents!", m_name); for (k = 0; k < 8; k++) @@ -3154,7 +3154,7 @@ bool_ make_attack_spell(int m_idx) case 96 + 0: { if (!direct) break; - disturb(1, 0); + disturb(1); msg_format("%^s makes a high pitched shriek.", m_name); aggravate_monsters(m_idx); break; @@ -3169,7 +3169,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_S_ANIMAL */ case 96 + 2: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically summons an animal!", m_name); for (k = 0; k < 1; k++) @@ -3183,7 +3183,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_ROCKET */ case 96 + 3: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s shoots something.", m_name); else msg_format("%^s fires a rocket.", m_name); breath(m_idx, GF_ROCKET, @@ -3195,7 +3195,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_ARROW_1 */ case 96 + 4: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s makes a strange noise.", m_name); else msg_format("%^s fires an arrow.", m_name); bolt(m_idx, GF_ARROW, damroll(1, 6)); @@ -3206,7 +3206,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_ARROW_2 */ case 96 + 5: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s makes a strange noise.", m_name); else msg_format("%^s fires an arrow!", m_name); bolt(m_idx, GF_ARROW, damroll(3, 6)); @@ -3217,7 +3217,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_ARROW_3 */ case 96 + 6: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s makes a strange noise.", m_name); else msg_format("%^s fires a missile.", m_name); bolt(m_idx, GF_ARROW, damroll(5, 6)); @@ -3228,7 +3228,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_ARROW_4 */ case 96 + 7: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s makes a strange noise.", m_name); else msg_format("%^s fires a missile!", m_name); bolt(m_idx, GF_ARROW, damroll(7, 6)); @@ -3239,7 +3239,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_ACID */ case 96 + 8: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes acid.", m_name); breath(m_idx, GF_ACID, @@ -3251,7 +3251,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_ELEC */ case 96 + 9: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes lightning.", m_name); breath(m_idx, GF_ELEC, @@ -3263,7 +3263,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_FIRE */ case 96 + 10: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes fire.", m_name); breath(m_idx, GF_FIRE, @@ -3275,7 +3275,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_COLD */ case 96 + 11: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes frost.", m_name); breath(m_idx, GF_COLD, @@ -3287,7 +3287,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_POIS */ case 96 + 12: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes gas.", m_name); breath(m_idx, GF_POIS, @@ -3300,7 +3300,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_NETH */ case 96 + 13: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes nether.", m_name); breath(m_idx, GF_NETHER, @@ -3312,7 +3312,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_LITE */ case 96 + 14: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes light.", m_name); breath(m_idx, GF_LITE, @@ -3324,7 +3324,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_DARK */ case 96 + 15: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes darkness.", m_name); breath(m_idx, GF_DARK, @@ -3336,7 +3336,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_CONF */ case 96 + 16: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes confusion.", m_name); breath(m_idx, GF_CONFUSION, @@ -3348,7 +3348,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_SOUN */ case 96 + 17: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes sound.", m_name); breath(m_idx, GF_SOUND, @@ -3360,7 +3360,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_CHAO */ case 96 + 18: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes chaos.", m_name); breath(m_idx, GF_CHAOS, @@ -3372,7 +3372,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_DISE */ case 96 + 19: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes disenchantment.", m_name); breath(m_idx, GF_DISENCHANT, @@ -3384,7 +3384,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_NEXU */ case 96 + 20: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes nexus.", m_name); breath(m_idx, GF_NEXUS, @@ -3396,7 +3396,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_TIME */ case 96 + 21: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes time.", m_name); breath(m_idx, GF_TIME, @@ -3407,7 +3407,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_INER */ case 96 + 22: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes inertia.", m_name); breath(m_idx, GF_INERTIA, @@ -3418,7 +3418,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_GRAV */ case 96 + 23: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes gravity.", m_name); breath(m_idx, GF_GRAVITY, @@ -3429,7 +3429,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_SHAR */ case 96 + 24: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes shards.", m_name); breath(m_idx, GF_SHARDS, @@ -3441,7 +3441,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_PLAS */ case 96 + 25: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes plasma.", m_name); breath(m_idx, GF_PLASMA, @@ -3452,7 +3452,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_WALL */ case 96 + 26: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes force.", m_name); breath(m_idx, GF_FORCE, @@ -3463,7 +3463,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_MANA */ case 96 + 27: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes magical energy.", m_name); breath(m_idx, GF_MANA, @@ -3474,7 +3474,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BA_NUKE */ case 96 + 28: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s casts a ball of radiation.", m_name); breath(m_idx, GF_NUKE, (rlev + damroll(10, 6)), 2); @@ -3485,7 +3485,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_NUKE */ case 96 + 29: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes toxic waste.", m_name); breath(m_idx, GF_NUKE, @@ -3497,7 +3497,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BA_CHAO */ case 96 + 30: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles frighteningly.", m_name); else msg_format("%^s invokes a raw chaos.", m_name); breath(m_idx, GF_CHAOS, (rlev * 2) + damroll(10, 10), 4); @@ -3508,7 +3508,7 @@ bool_ make_attack_spell(int m_idx) /* RF4_BR_DISI -> Disintegration breath! */ case 96 + 31: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s breathes.", m_name); else msg_format("%^s breathes disintegration.", m_name); breath(m_idx, GF_DISINTEGRATE, @@ -3521,7 +3521,7 @@ bool_ make_attack_spell(int m_idx) /* RF5_BA_ACID */ case 128 + 0: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s casts an acid ball.", m_name); breath(m_idx, GF_ACID, @@ -3533,7 +3533,7 @@ bool_ make_attack_spell(int m_idx) /* RF5_BA_ELEC */ case 128 + 1: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s casts a lightning ball.", m_name); breath(m_idx, GF_ELEC, @@ -3545,7 +3545,7 @@ bool_ make_attack_spell(int m_idx) /* RF5_BA_FIRE */ case 128 + 2: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s casts a fire ball.", m_name); breath(m_idx, GF_FIRE, @@ -3557,7 +3557,7 @@ bool_ make_attack_spell(int m_idx) /* RF5_BA_COLD */ case 128 + 3: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s casts a frost ball.", m_name); breath(m_idx, GF_COLD, @@ -3569,7 +3569,7 @@ bool_ make_attack_spell(int m_idx) /* RF5_BA_POIS */ case 128 + 4: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s casts a stinking cloud.", m_name); breath(m_idx, GF_POIS, @@ -3581,7 +3581,7 @@ bool_ make_attack_spell(int m_idx) /* RF5_BA_NETH */ case 128 + 5: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s casts a nether ball.", m_name); breath(m_idx, GF_NETHER, @@ -3593,7 +3593,7 @@ bool_ make_attack_spell(int m_idx) /* RF5_BA_WATE */ case 128 + 6: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s gestures fluidly.", m_name); msg_print("You are engulfed in a whirlpool."); @@ -3605,7 +3605,7 @@ bool_ make_attack_spell(int m_idx) /* RF5_BA_MANA */ case 128 + 7: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles powerfully.", m_name); else msg_format("%^s invokes a mana storm.", m_name); breath(m_idx, GF_MANA, @@ -3616,7 +3616,7 @@ bool_ make_attack_spell(int m_idx) /* RF5_BA_DARK */ case 128 + 8: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles powerfully.", m_name); else msg_format("%^s invokes a darkness storm.", m_name); breath(m_idx, GF_DARK, @@ -3634,7 +3634,7 @@ bool_ make_attack_spell(int m_idx) int r1; /* Disturb if legal */ - disturb(1, 0); + disturb(1); /* Basic message */ msg_format("%^s draws psychic energy from you!", m_name); @@ -3687,7 +3687,7 @@ bool_ make_attack_spell(int m_idx) case 128 + 10: { if (!direct) break; - disturb(1, 0); + disturb(1); if (!seen) { msg_print("You feel something focusing on your mind."); @@ -3724,7 +3724,7 @@ bool_ make_attack_spell(int m_idx) case 128 + 11: { if (!direct) break; - disturb(1, 0); + disturb(1); if (!seen) { msg_print("You feel something focusing on your mind."); @@ -3773,7 +3773,7 @@ bool_ make_attack_spell(int m_idx) case 128 + 12: { if (!direct) break; - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s points at you and curses.", m_name); if (rand_int(100) < p_ptr->skill_sav) @@ -3792,7 +3792,7 @@ bool_ make_attack_spell(int m_idx) case 128 + 13: { if (!direct) break; - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s points at you and curses horribly.", m_name); if (rand_int(100) < p_ptr->skill_sav) @@ -3811,7 +3811,7 @@ bool_ make_attack_spell(int m_idx) case 128 + 14: { if (!direct) break; - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles loudly.", m_name); else msg_format("%^s points at you, incanting terribly!", m_name); if (rand_int(100) < p_ptr->skill_sav) @@ -3830,7 +3830,7 @@ bool_ make_attack_spell(int m_idx) case 128 + 15: { if (!direct) break; - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s screams the word 'DIE!'", m_name); else msg_format("%^s points at you, screaming the word DIE!", m_name); if (rand_int(100) < p_ptr->skill_sav) @@ -3848,7 +3848,7 @@ bool_ make_attack_spell(int m_idx) /* RF5_BO_ACID */ case 128 + 16: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s casts a acid bolt.", m_name); bolt(m_idx, GF_ACID, damroll(7, 8) + (rlev / 3)); @@ -3860,7 +3860,7 @@ bool_ make_attack_spell(int m_idx) /* RF5_BO_ELEC */ case 128 + 17: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s casts a lightning bolt.", m_name); bolt(m_idx, GF_ELEC, damroll(4, 8) + (rlev / 3)); @@ -3872,7 +3872,7 @@ bool_ make_attack_spell(int m_idx) /* RF5_BO_FIRE */ case 128 + 18: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s casts a fire bolt.", m_name); bolt(m_idx, GF_FIRE, damroll(9, 8) + (rlev / 3)); @@ -3884,7 +3884,7 @@ bool_ make_attack_spell(int m_idx) /* RF5_BO_COLD */ case 128 + 19: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s casts a frost bolt.", m_name); bolt(m_idx, GF_COLD, damroll(6, 8) + (rlev / 3)); @@ -3903,7 +3903,7 @@ bool_ make_attack_spell(int m_idx) /* RF5_BO_NETH */ case 128 + 21: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s casts a nether bolt.", m_name); bolt(m_idx, GF_NETHER, 30 + damroll(5, 5) + (rlev * 3) / 2); @@ -3915,7 +3915,7 @@ bool_ make_attack_spell(int m_idx) /* RF5_BO_WATE */ case 128 + 22: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s casts a water bolt.", m_name); bolt(m_idx, GF_WATER, damroll(10, 10) + (rlev)); @@ -3926,7 +3926,7 @@ bool_ make_attack_spell(int m_idx) /* RF5_BO_MANA */ case 128 + 23: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s casts a mana bolt.", m_name); bolt(m_idx, GF_MANA, randint(rlev * 7 / 2) + 50); @@ -3937,7 +3937,7 @@ bool_ make_attack_spell(int m_idx) /* RF5_BO_PLAS */ case 128 + 24: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s casts a plasma bolt.", m_name); bolt(m_idx, GF_PLASMA, 10 + damroll(8, 7) + (rlev)); @@ -3948,7 +3948,7 @@ bool_ make_attack_spell(int m_idx) /* RF5_BO_ICEE */ case 128 + 25: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s casts an ice bolt.", m_name); bolt(m_idx, GF_ICE, damroll(6, 6) + (rlev)); @@ -3960,7 +3960,7 @@ bool_ make_attack_spell(int m_idx) /* RF5_MISSILE */ case 128 + 26: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s casts a magic missile.", m_name); bolt(m_idx, GF_MISSILE, damroll(2, 6) + (rlev / 3)); @@ -3972,7 +3972,7 @@ bool_ make_attack_spell(int m_idx) case 128 + 27: { if (!direct) break; - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles, and you hear scary noises.", m_name); else msg_format("%^s casts a fearful illusion.", m_name); if (p_ptr->resist_fear) @@ -3995,7 +3995,7 @@ bool_ make_attack_spell(int m_idx) case 128 + 28: { if (!direct) break; - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s casts a spell, burning your eyes!", m_name); if (p_ptr->resist_blind) @@ -4018,7 +4018,7 @@ bool_ make_attack_spell(int m_idx) case 128 + 29: { if (!direct) break; - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles, and you hear puzzling noises.", m_name); else msg_format("%^s creates a mesmerizing illusion.", m_name); if (p_ptr->resist_conf) @@ -4041,7 +4041,7 @@ bool_ make_attack_spell(int m_idx) case 128 + 30: { if (!direct) break; - disturb(1, 0); + disturb(1); msg_format("%^s drains power from your muscles!", m_name); if (p_ptr->free_act) { @@ -4063,7 +4063,7 @@ bool_ make_attack_spell(int m_idx) case 128 + 31: { if (!direct) break; - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s stares deep into your eyes!", m_name); if (p_ptr->free_act) @@ -4087,7 +4087,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_HASTE */ case 160 + 0: { - disturb(1, 0); + disturb(1); if (blind) { msg_format("%^s mumbles.", m_name); @@ -4117,7 +4117,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_HAND_DOOM */ case 160 + 1: { - disturb(1, 0); + disturb(1); msg_format("%^s invokes the Hand of Doom!", m_name); if (rand_int(100) < p_ptr->skill_sav) { @@ -4138,7 +4138,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_HEAL */ case 160 + 2: { - disturb(1, 0); + disturb(1); /* Message */ if (blind) @@ -4202,7 +4202,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_S_ANIMALS */ case 160 + 3: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically summons some animals!", m_name); for (k = 0; k < 4; k++) @@ -4216,7 +4216,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_BLINK */ case 160 + 4: { - disturb(1, 0); + disturb(1); msg_format("%^s blinks away.", m_name); teleport_away(m_idx, 10); break; @@ -4225,7 +4225,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_TPORT */ case 160 + 5: { - disturb(1, 0); + disturb(1); msg_format("%^s teleports away.", m_name); teleport_away(m_idx, MAX_SIGHT * 2 + 5); break; @@ -4235,7 +4235,7 @@ bool_ make_attack_spell(int m_idx) case 160 + 6: { if (!direct) break; - disturb(1, 0); + disturb(1); msg_format("%^s commands you to return.", m_name); teleport_player_to(m_ptr->fy, m_ptr->fx); break; @@ -4245,7 +4245,7 @@ bool_ make_attack_spell(int m_idx) case 160 + 7: { if (!direct) break; - disturb(1, 0); + disturb(1); msg_format("%^s teleports you away.", m_name); teleport_player(100); break; @@ -4255,7 +4255,7 @@ bool_ make_attack_spell(int m_idx) case 160 + 8: { if (!direct) break; - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles strangely.", m_name); else msg_format("%^s gestures at your feet.", m_name); if (p_ptr->resist_nexus) @@ -4278,7 +4278,7 @@ bool_ make_attack_spell(int m_idx) case 160 + 9: { if (!direct) break; - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s gestures in shadow.", m_name); (void)unlite_area(0, 3); @@ -4289,7 +4289,7 @@ bool_ make_attack_spell(int m_idx) case 160 + 10: { if (!direct) break; - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles, and then cackles evilly.", m_name); else msg_format("%^s casts a spell and cackles evilly.", m_name); (void)trap_creation(); @@ -4300,7 +4300,7 @@ bool_ make_attack_spell(int m_idx) case 160 + 11: { if (!direct) break; - disturb(1, 0); + disturb(1); msg_format("%^s tries to blank your mind.", m_name); if (rand_int(100) < p_ptr->skill_sav) @@ -4321,7 +4321,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_S_BUG */ case 160 + 13: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically codes some software bugs.", m_name); for (k = 0; k < 6; k++) @@ -4335,7 +4335,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_S_RNG */ case 160 + 14: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically codes some RNGs.", m_name); for (k = 0; k < 6; k++) @@ -4349,7 +4349,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_S_THUNDERLORD */ case 160 + 15: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically summons a Thunderlord!", m_name); for (k = 0; k < 1; k++) @@ -4363,7 +4363,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_SUMMON_KIN */ case 160 + 16: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically summons %s %s.", m_name, m_poss, @@ -4383,7 +4383,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_S_HI_DEMON */ case 160 + 17: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically summons greater demons!", m_name); if (blind && count) msg_print("You hear heavy steps nearby."); @@ -4394,7 +4394,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_S_MONSTER */ case 160 + 18: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically summons help!", m_name); for (k = 0; k < 1; k++) @@ -4408,7 +4408,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_S_MONSTERS */ case 160 + 19: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically summons monsters!", m_name); for (k = 0; k < 8; k++) @@ -4422,7 +4422,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_S_ANT */ case 160 + 20: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically summons ants.", m_name); for (k = 0; k < 6; k++) @@ -4436,7 +4436,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_S_SPIDER */ case 160 + 21: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically summons spiders.", m_name); for (k = 0; k < 6; k++) @@ -4450,7 +4450,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_S_HOUND */ case 160 + 22: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically summons hounds.", m_name); for (k = 0; k < 6; k++) @@ -4464,7 +4464,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_S_HYDRA */ case 160 + 23: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically summons hydras.", m_name); for (k = 0; k < 6; k++) @@ -4478,7 +4478,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_S_ANGEL */ case 160 + 24: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically summons an angel!", m_name); for (k = 0; k < 1; k++) @@ -4492,7 +4492,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_S_DEMON */ case 160 + 25: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically summons a demon!", m_name); for (k = 0; k < 1; k++) @@ -4506,7 +4506,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_S_UNDEAD */ case 160 + 26: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically summons an undead adversary!", m_name); for (k = 0; k < 1; k++) @@ -4520,7 +4520,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_S_DRAGON */ case 160 + 27: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically summons a dragon!", m_name); for (k = 0; k < 1; k++) @@ -4534,7 +4534,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_S_HI_UNDEAD */ case 160 + 28: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically summons greater undead!", m_name); for (k = 0; k < 8; k++) @@ -4551,7 +4551,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_S_HI_DRAGON */ case 160 + 29: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically summons ancient dragons!", m_name); for (k = 0; k < 8; k++) @@ -4568,7 +4568,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_S_WRAITH */ case 160 + 30: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically summons Wraith!", m_name); @@ -4588,7 +4588,7 @@ bool_ make_attack_spell(int m_idx) /* RF6_S_UNIQUE */ case 160 + 31: { - disturb(1, 0); + disturb(1); if (blind) msg_format("%^s mumbles.", m_name); else msg_format("%^s magically summons special opponents!", m_name); for (k = 0; k < 8; k++) @@ -5542,7 +5542,7 @@ static bool_ monst_attack_monst(int m_idx, int t_idx) if (!effect || check_hit2(power, rlev, ac)) { /* Always disturbing */ - if (disturb_other) disturb(1, 0); + if (disturb_other) disturb(1); /* Describe the attack method */ switch (method) @@ -5947,7 +5947,7 @@ static bool_ monst_attack_monst(int m_idx, int t_idx) if (m_ptr->ml) { /* Disturbing */ - disturb(1, 0); + disturb(1); /* Message */ monster_msg("%^s misses %s.", m_name, t_name); @@ -6742,7 +6742,7 @@ static void process_monster(int m_idx, bool_ is_frien) msg_print("You hear a door burst open!"); /* Disturb (sometimes) */ - if (disturb_minor) disturb(0, 0); + if (disturb_minor) disturb(0); /* The door was bashed open */ did_bash_door = TRUE; @@ -7044,7 +7044,7 @@ static void process_monster(int m_idx, bool_ is_frien) { /* Disturb */ if ((is_friend(m_ptr) < 0) || disturb_pets) - disturb(0, 0); + disturb(0); } /* Check for monster trap */ diff --git a/src/monster2.c b/src/monster2.c index 9d79f73a..175bf991 100644 --- a/src/monster2.c +++ b/src/monster2.c @@ -1884,7 +1884,7 @@ void update_mon(int m_idx, bool_ full) /* Disturb on appearance */ if (disturb_move) { - if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1, 0); + if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1); } } @@ -1924,7 +1924,7 @@ void update_mon(int m_idx, bool_ full) /* Disturb on disappearance*/ if (disturb_move) { - if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1, 0); + if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1); } } } @@ -1951,7 +1951,7 @@ void update_mon(int m_idx, bool_ full) /* Disturb on appearance */ if (disturb_near) { - if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1, 0); + if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1); } } @@ -1972,7 +1972,7 @@ void update_mon(int m_idx, bool_ full) /* Disturb on disappearance */ if (disturb_near) { - if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1, 0); + if (disturb_pets || (is_friend(m_ptr) <= 0)) disturb(1); } } } diff --git a/src/object1.c b/src/object1.c index 72ccd5af..a5dbc3d5 100644 --- a/src/object1.c +++ b/src/object1.c @@ -6253,7 +6253,7 @@ void py_pickup_floor(int pickup) next_o_idx = o_ptr->next_o_idx; /* Hack -- disturb */ - disturb(0, 0); + disturb(0); /* Pick up gold */ if (o_ptr->tval == TV_GOLD) diff --git a/src/spells1.c b/src/spells1.c index 5aec03bf..45bea042 100644 --- a/src/spells1.c +++ b/src/spells1.c @@ -175,7 +175,7 @@ void teleport_player_directed(int rad, int dir) if (c_ptr->feat == FEAT_SHOP) { /* Disturb */ - disturb(0, 0); + disturb(0); /* Hack -- enter store */ command_new = '_'; @@ -1294,7 +1294,7 @@ void take_hit(int damage, cptr hit_from) if (death) return; /* Disturb */ - disturb(1, 0); + disturb(1); /* Apply "invulnerability" */ if (p_ptr->invuln && (damage < 9000)) @@ -1527,7 +1527,7 @@ void take_sanity_hit(int damage, cptr hit_from) if (death) return; /* Disturb */ - disturb(1, 0); + disturb(1); /* Hurt the player */ @@ -7216,7 +7216,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad project(0, 0, t_y, t_x, dam, typ, (PROJECT_STOP | PROJECT_KILL)); - disturb(1, 0); + disturb(1); return TRUE; } @@ -8118,7 +8118,7 @@ static bool_ project_p(int who, int r, int y, int x, int dam, int typ, int a_rad /* Disturb */ - disturb(1, 0); + disturb(1); /* Return "Anything seen?" */ diff --git a/src/traps.c b/src/traps.c index 999f9acc..bb56bb20 100644 --- a/src/traps.c +++ b/src/traps.c @@ -1974,7 +1974,7 @@ void player_activate_door_trap(s16b y, s16b x) !(f_info[c_ptr->feat].flags1 & FF1_DOOR)) return; /* Disturb */ - disturb(0, 0); + disturb(0); /* Message */ msg_print("You found a trap!"); diff --git a/src/xtra2.c b/src/xtra2.c index 84f3b540..3e0a1800 100644 --- a/src/xtra2.c +++ b/src/xtra2.c @@ -119,7 +119,7 @@ bool_ set_parasite(int v, int r) if (!notice) return (FALSE); /* Disturb */ - if (disturb_state) disturb(0, 0); + if (disturb_state) disturb(0); /* Recalculate bonuses */ p_ptr->update |= (PU_BONUS); @@ -173,7 +173,7 @@ static bool_ set_simple_field( /* Disturb */ if (disturb_state) - disturb(0, 0); + disturb(0); /* Recalculate bonuses */ p_ptr->update |= (PU_BONUS); @@ -520,7 +520,7 @@ bool_ set_mimic(int v, int p, int level) if (!notice) return (FALSE); /* Disturb */ - if (disturb_state) disturb(0, 0); + if (disturb_state) disturb(0); /* Redraw title */ p_ptr->redraw |= (PR_TITLE); @@ -817,7 +817,7 @@ bool_ set_fast(int v, int p) if (!notice) return (FALSE); /* Disturb */ - if (disturb_state) disturb(0, 0); + if (disturb_state) disturb(0); /* Recalculate bonuses */ p_ptr->update |= (PU_BONUS); @@ -1179,7 +1179,7 @@ bool_ set_tim_thunder(int v, int p1, int p2) if (!notice) return (FALSE); /* Disturb */ - if (disturb_state) disturb(0, 0); + if (disturb_state) disturb(0); /* Recalculate bonuses */ p_ptr->update |= (PU_BONUS); @@ -1406,7 +1406,7 @@ bool_ set_tim_regen(int v, int p) if (!notice) return (FALSE); /* Disturb */ - if (disturb_state) disturb(0, 0); + if (disturb_state) disturb(0); /* Handle stuff */ handle_stuff(); @@ -1546,7 +1546,7 @@ bool_ set_stun(int v) /* None */ case 0: msg_print("You are no longer stunned."); - if (disturb_state) disturb(0, 0); + if (disturb_state) disturb(0); break; } @@ -1561,7 +1561,7 @@ bool_ set_stun(int v) if (!notice) return (FALSE); /* Disturb */ - if (disturb_state) disturb(0, 0); + if (disturb_state) disturb(0); /* Recalculate bonuses */ p_ptr->update |= (PU_BONUS); @@ -1754,7 +1754,7 @@ bool_ set_cut(int v) /* None */ case 0: msg_print("You are no longer bleeding."); - if (disturb_state) disturb(0, 0); + if (disturb_state) disturb(0); break; } @@ -1769,7 +1769,7 @@ bool_ set_cut(int v) if (!notice) return (FALSE); /* Disturb */ - if (disturb_state) disturb(0, 0); + if (disturb_state) disturb(0); /* Recalculate bonuses */ p_ptr->update |= (PU_BONUS); @@ -1983,7 +1983,7 @@ bool_ set_food(int v) if (!notice) return (FALSE); /* Disturb */ - if (disturb_state) disturb(0, 0); + if (disturb_state) disturb(0); /* Recalculate bonuses */ p_ptr->update |= (PU_BONUS); @@ -3690,7 +3690,7 @@ void verify_panel(void) panel_col_min = pcol_min; /* Hack -- optional disturb on "panel change" */ - if (disturb_panel && !center_player) disturb(0, 0); + if (disturb_panel && !center_player) disturb(0); /* Recalculate the boundaries */ panel_bounds(); -- cgit v1.2.3 From 8cdd45b0b475e910ebe393bc96e6497b2ffeb292 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Mon, 25 Mar 2013 17:28:24 +0100 Subject: Separate spell failure chance calculation for devices/school spells --- src/lua_bind.c | 107 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 60 insertions(+), 47 deletions(-) diff --git a/src/lua_bind.c b/src/lua_bind.c index a3e2b0bb..2e8a7083 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -101,63 +101,76 @@ int get_mana(s32b s) return get_level(s, mana_range.max, mana_range.min); } -/** Returns spell chance of failure for spell */ -s32b spell_chance(s32b s) +/** Returns spell change of failure for spell cast from a device */ +static s32b spell_chance_device(s32b s) { - spell_type *s_ptr = spell_at(s); + spell_type *s_ptr = spell_at(s); int level = get_level(s, 50, 1); + int minfail; + s32b chance = spell_type_failure_rate(s_ptr); - /* Extract the base spell failure rate */ - if (get_level_use_stick > -1) + /* Reduce failure rate by "effective" level adjustment */ + chance -= (level - 1); + + /* Extract the minimum failure rate */ + minfail = 15 - get_skill_scale(SKILL_DEVICE, 25); + + /* Return the chance */ + return clamp_failure_chance(chance, minfail); +} + +/** Returns spell chance of failure for a school spell. */ +static s32b spell_chance_school(s32b s) +{ + spell_type *s_ptr = spell_at(s); + int level = get_level(s, 50, 1); + s32b chance = spell_type_failure_rate(s_ptr); + int mana = get_mana(s); + int cur_mana = get_power(s); + int stat = spell_type_casting_stat(s_ptr); + int stat_ind = p_ptr->stat_ind[stat]; + int minfail; + + /* Reduce failure rate by "effective" level adjustment */ + chance -= 3 * (level - 1); + + /* Reduce failure rate by INT/WIS adjustment */ + chance -= 3 * (adj_mag_stat[stat_ind] - 1); + + /* Not enough mana to cast */ + if (chance < 0) chance = 0; + if (mana > cur_mana) + { + chance += 15 * (mana - cur_mana); + } + + /* Extract the minimum failure rate */ + minfail = adj_mag_fail[stat_ind]; + + /* Must have Perfect Casting to get below 5% */ + if (!(has_ability(AB_PERFECT_CASTING))) { - int minfail; - s32b chance = spell_type_failure_rate(s_ptr); + if (minfail < 5) minfail = 5; + } - /* Reduce failure rate by "effective" level adjustment */ - chance -= (level - 1); + /* Hack -- Priest prayer penalty for "edged" weapons -DGK */ + if ((forbid_non_blessed()) && (p_ptr->icky_wield)) chance += 25; - /* Extract the minimum failure rate */ - minfail = 15 - get_skill_scale(SKILL_DEVICE, 25); + /* Return the chance */ + return clamp_failure_chance(chance, minfail); +} - /* Return the chance */ - return clamp_failure_chance(chance, minfail); +/** Returns spell chance of failure for spell */ +s32b spell_chance(s32b s) +{ + /* Extract the base spell failure rate */ + if (get_level_use_stick > -1) + { + return spell_chance_device(s); } else { - s32b chance = spell_type_failure_rate(s_ptr); - int mana = get_mana(s); - int cur_mana = get_power(s); - int stat = spell_type_casting_stat(s_ptr); - int stat_ind = p_ptr->stat_ind[stat]; - int minfail; - - /* Reduce failure rate by "effective" level adjustment */ - chance -= 3 * (level - 1); - - /* Reduce failure rate by INT/WIS adjustment */ - chance -= 3 * (adj_mag_stat[stat_ind] - 1); - - /* Not enough mana to cast */ - if (chance < 0) chance = 0; - if (mana > cur_mana) - { - chance += 15 * (mana - cur_mana); - } - - /* Extract the minimum failure rate */ - minfail = adj_mag_fail[stat_ind]; - - /* Must have Perfect Casting to get below 5% */ - if (!(has_ability(AB_PERFECT_CASTING))) - { - if (minfail < 5) minfail = 5; - } - - /* Hack -- Priest prayer penalty for "edged" weapons -DGK */ - if ((forbid_non_blessed()) && (p_ptr->icky_wield)) chance += 25; - - /* Return the chance */ - return clamp_failure_chance(chance, minfail); + return spell_chance_school(s); } } -- cgit v1.2.3 From 9eb646ef8c1f2824a113a111516d1c73d798746c Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Mar 2013 17:11:00 +0100 Subject: Constness fixes --- src/externs.h | 4 ++-- src/files.c | 2 +- src/hooks.c | 6 +++--- src/hooks.h | 12 ++++++++++-- src/xtra2.c | 2 +- 5 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/externs.h b/src/externs.h index 41b59cb3..4ba664b4 100644 --- a/src/externs.h +++ b/src/externs.h @@ -858,7 +858,7 @@ extern void display_scores(int from, int to); extern errr predict_score(void); extern void predict_score_gui(bool_ *initialized, bool_ *game_in_progress); extern void close_game(void); -extern errr get_rnd_line(char * file_name, char * output); +extern errr get_rnd_line(const char * file_name, char * output); extern char *get_line(char* fname, cptr fdir, char *linbuf, int line); extern void do_cmd_knowledge_corruptions(void); extern void race_legends(void); @@ -2062,7 +2062,7 @@ extern void set_subrace_title(int racem, cptr name); extern void switch_subrace(int racem, bool_ copy_old); extern void drop_from_wild(void); extern void clean_wish_name(char *buf, char *name); -extern bool_ test_object_wish(char *name, object_type *o_ptr, object_type *forge, char *what); +extern bool_ test_object_wish(char *name, object_type *o_ptr, object_type *forge, const char *what); extern bool_ set_roots(int v, s16b ac, s16b dam); extern bool_ set_project(int v, s16b gf, s16b dam, s16b rad, s16b flag); extern bool_ set_rush(int v); diff --git a/src/files.c b/src/files.c index d056c125..ad8322cf 100644 --- a/src/files.c +++ b/src/files.c @@ -5593,7 +5593,7 @@ void close_game(void) /* * Grab a randomly selected line in lib/file/file_name */ -errr get_rnd_line(char *file_name, char *output) +errr get_rnd_line(const char *file_name, char *output) { FILE *fp; diff --git a/src/hooks.c b/src/hooks.c index 2b70e90d..08418035 100644 --- a/src/hooks.c +++ b/src/hooks.c @@ -148,7 +148,7 @@ object_type* get_next_arg_obj() { /* Actually process the hooks */ int process_hooks_restart = FALSE; hook_return process_hooks_return[20]; -static bool_ vprocess_hooks_return (int h_idx, char *ret, char *fmt, va_list *ap) +static bool_ vprocess_hooks_return (int h_idx, const char *ret, const char *fmt, va_list *ap) { hooks_chain *c = hooks_heads[h_idx]; va_list real_ap; @@ -217,7 +217,7 @@ static bool_ vprocess_hooks_return (int h_idx, char *ret, char *fmt, va_list *ap return FALSE; } -bool_ process_hooks_ret(int h_idx, char *ret, char *fmt, ...) +bool_ process_hooks_ret(int h_idx, const char *ret, const char *fmt, ...) { va_list ap; bool_ r; @@ -228,7 +228,7 @@ bool_ process_hooks_ret(int h_idx, char *ret, char *fmt, ...) return (r); } -bool_ process_hooks(int h_idx, char *fmt, ...) +bool_ process_hooks(int h_idx, const char *fmt, ...) { va_list ap; bool_ ret; diff --git a/src/hooks.h b/src/hooks.h index 0c83cf84..8ea87bc3 100644 --- a/src/hooks.h +++ b/src/hooks.h @@ -2,6 +2,10 @@ #include "angband.h" +#ifdef __cplusplus +extern "C" { +#endif + extern FILE *hook_file; extern void wipe_hooks(void); extern void init_hooks(void); @@ -13,6 +17,10 @@ extern char* get_next_arg_str(const char *fmt); extern object_type *get_next_arg_obj(); extern int process_hooks_restart; extern hook_return process_hooks_return[20]; -extern bool_ process_hooks_ret(int h_idx, char *ret, char *fmt, ...); -extern bool_ process_hooks(int h_idx, char *fmt, ...); +extern bool_ process_hooks_ret(int h_idx, const char *ret, const char *fmt, ...); +extern bool_ process_hooks(int h_idx, const char *fmt, ...); extern bool_ process_hooks_new(int h_idx, void *in, void *out); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/xtra2.c b/src/xtra2.c index 3e0a1800..53abc149 100644 --- a/src/xtra2.c +++ b/src/xtra2.c @@ -5472,7 +5472,7 @@ void set_grace(s32b v) handle_stuff(); } -bool_ test_object_wish(char *name, object_type *o_ptr, object_type *forge, char *what) +bool_ test_object_wish(char *name, object_type *o_ptr, object_type *forge, const char *what) { int i, j, jb, save_aware; char buf[200]; -- cgit v1.2.3 From 3460e3351b130e5b9ad075385f5e5052e449136e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Mar 2013 17:24:43 +0100 Subject: Fix erroneous use of "h-type" instead of "h-basic" --- src/hiscore.h | 7 ++----- src/messages.h | 11 ++++++++--- src/quark.h | 7 ++----- src/spell_type.h | 2 +- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/hiscore.h b/src/hiscore.h index 0eed91b4..c74525a1 100644 --- a/src/hiscore.h +++ b/src/hiscore.h @@ -1,7 +1,6 @@ -#ifndef H_267bf1c1_eada_4b18_9558_d96330fa7258 -#define H_267bf1c1_eada_4b18_9558_d96330fa7258 +#pragma once -#include "h-type.h" +#include "h-basic.h" #ifdef __cplusplus extern "C" { @@ -85,5 +84,3 @@ int highscore_add(int highscore_fd, high_score *score); #ifdef __cplusplus } // extern "C" #endif - -#endif diff --git a/src/messages.h b/src/messages.h index 401c5727..0e9e2d14 100644 --- a/src/messages.h +++ b/src/messages.h @@ -1,7 +1,10 @@ -#ifndef H_f6dac2dc_0449_4764_9942_1c1fe7a70bc4 -#define H_f6dac2dc_0449_4764_9942_1c1fe7a70bc4 +#pragma once -#include "h-type.h" +#include "h-basic.h" + +#ifdef __cplusplus +extern "C" { +#endif void message_init(); s16b message_num(); @@ -10,4 +13,6 @@ byte message_color(int age); byte message_type(int age); void message_add(cptr msg, byte color); +#ifdef __cplusplus +} // extern "C" #endif diff --git a/src/quark.h b/src/quark.h index 9488b105..1eec6eae 100644 --- a/src/quark.h +++ b/src/quark.h @@ -1,7 +1,6 @@ -#ifndef H_eeb941c7_1a44_405a_8db3_ba14732c5b94 -#define H_eeb941c7_1a44_405a_8db3_ba14732c5b94 +#pragma once -#include "h-type.h" +#include "h-basic.h" #ifdef __cplusplus extern "C" { @@ -14,5 +13,3 @@ s16b quark_add(cptr str); #ifdef __cplusplus } // extern "C" #endif - -#endif diff --git a/src/spell_type.h b/src/spell_type.h index 7f985bca..48d52ef0 100644 --- a/src/spell_type.h +++ b/src/spell_type.h @@ -2,7 +2,7 @@ #include "spell_type_fwd.h" -#include "h-type.h" +#include "h-basic.h" #include "types_fwd.h" #include "device_allocation_fwd.h" #include "range_fwd.h" -- cgit v1.2.3 From 03d0833d8b0124ce7f39aec6842b1b252002d296 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Mar 2013 17:45:12 +0100 Subject: Remove unused place_monster_one_race global --- src/externs.h | 1 - src/monster2.c | 42 ++---------------------------------------- 2 files changed, 2 insertions(+), 41 deletions(-) diff --git a/src/externs.h b/src/externs.h index 4ba664b4..ee6359fd 100644 --- a/src/externs.h +++ b/src/externs.h @@ -1005,7 +1005,6 @@ extern void message_pain(int m_idx, int dam); extern void update_smart_learn(int m_idx, int what); extern bool_ summon_specific_friendly(int y1, int x1, int lev, int type, bool_ Group_ok); extern bool_ place_monster_one_no_drop; -extern monster_race *place_monster_one_race; extern s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status); extern s16b player_place(int y, int x); extern void monster_drop_carried_objects(monster_type *m_ptr); diff --git a/src/monster2.c b/src/monster2.c index 175bf991..845434b1 100644 --- a/src/monster2.c +++ b/src/monster2.c @@ -2106,7 +2106,6 @@ bool_ kind_is_randart(int k_idx) bool_ bypass_r_ptr_max_num = FALSE; int place_monster_result = 0; bool_ place_monster_one_no_drop = FALSE; -monster_race *place_monster_one_race = NULL; s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status) { int i; @@ -2122,23 +2121,15 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status) cptr name = (r_name + r_ptr->name); - /* Grab the special race if needed */ - if (place_monster_one_race) - { - r_ptr = place_monster_one_race; - } - /* DO NOT PLACE A MONSTER IN THE SMALL SCALE WILDERNESS !!! */ if (p_ptr->wild_mode) { - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } /* Verify location */ if (!in_bounds(y, x)) { - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } @@ -2146,7 +2137,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status) if (!cave_empty_bold(y, x)) { if (wizard) cmsg_format(TERM_L_RED, "WARNING: Refused monster(%d): EMPTY BOLD", r_idx); - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } @@ -2154,26 +2144,22 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status) if ((cave[y][x].info & CAVE_FREE) && (!m_allow_special[r_idx])) { if (wizard) cmsg_format(TERM_L_RED, "WARNING: Refused monster(%d): CAVE_FREE", r_idx); - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } /* Hack -- no creation on glyph of warding */ if (cave[y][x].feat == FEAT_GLYPH) { - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } if (cave[y][x].feat == FEAT_MINOR_GLYPH) { - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } /* Nor on the between */ if (cave[y][x].feat == FEAT_BETWEEN) { - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } @@ -2181,7 +2167,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status) if ((cave[y][x].feat >= FEAT_ALTAR_HEAD) && (cave[y][x].feat <= FEAT_ALTAR_TAIL)) { - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } @@ -2189,53 +2174,40 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status) if ((cave[y][x].feat >= FEAT_PATTERN_START) && (cave[y][x].feat <= FEAT_PATTERN_XTRA2)) { - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } /* Paranoia */ if (!r_idx) { - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } /* Paranoia */ if (!r_ptr->name) { - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } /* Are we allowed to continue ? */ if (process_hooks(HOOK_NEW_MONSTER, "(d)", r_idx)) { - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } /* Ego Uniques are NOT to be created */ if ((r_ptr->flags1 & RF1_UNIQUE) && ego) { - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } /* Now could we generate an Ego Monster */ /* Grab the special race if needed */ - if (place_monster_one_race) - { - r_ptr = place_monster_one_race; - } - else - { - r_ptr = race_info_idx(r_idx, ego); - } + r_ptr = race_info_idx(r_idx, ego); if (!monster_can_cross_terrain(cave[y][x].feat, r_ptr)) { if (wizard) cmsg_print(TERM_L_RED, "WARNING: Refused monster: cannot cross terrain"); - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } @@ -2243,7 +2215,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status) if ((r_ptr->flags9 & RF9_SPECIAL_GENE) && (!m_allow_special[r_idx])) { if (wizard) cmsg_format(TERM_L_RED, "WARNING: Refused monster(%d): SPECIAL_GENE", r_idx); - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } @@ -2251,7 +2222,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status) if ((r_ptr->flags7 & RF7_SPIRIT) && (dungeon_type != DUNGEON_VOID)) { if (wizard) cmsg_format(TERM_L_RED, "WARNING: Refused monster(%d): SPIRIT in non VOID", r_idx); - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } @@ -2259,7 +2229,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status) if (r_ptr->flags9 & RF9_NEVER_GENE) { if (wizard) cmsg_print(TERM_L_RED, "WARNING: Refused monster: NEVER_GENE"); - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } @@ -2268,7 +2237,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status) { /* Cannot create */ if (wizard) cmsg_format(TERM_L_RED, "WARNING: Refused monster %d: unique not unique", r_idx); - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } @@ -2276,7 +2244,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status) if (r_ptr->on_saved) { if (wizard) cmsg_print(TERM_L_RED, "WARNING: Refused monster: unique already on saved level"); - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } @@ -2285,7 +2252,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status) { /* Cannot create */ if (wizard) cmsg_format(TERM_L_RED, "WARNING: Refused monster %d: cur_num >= max_num", r_idx); - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } @@ -2294,7 +2260,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status) { /* Cannot create */ if (wizard) cmsg_print(TERM_L_RED, "WARNING: FORCE_DEPTH"); - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } @@ -2340,7 +2305,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status) /* Mega-Hack -- catch "failure" */ if (!c_ptr->m_idx) { - if (place_monster_one_race) KILL(place_monster_one_race, monster_race); return 0; } @@ -2353,7 +2317,7 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status) m_ptr->ego = ego; /* No special, no mind */ - m_ptr->sr_ptr = place_monster_one_race; + m_ptr->sr_ptr = NULL; /* Place the monster at the location */ m_ptr->fy = y; @@ -2649,8 +2613,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status) r_ptr->on_saved = TRUE; } - place_monster_one_race = NULL; - /* Processs hooks */ { hook_new_monster_end_in in = { m_ptr }; -- cgit v1.2.3 From 241732af058f9b161c88a9775ba3f3390fff490e Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Mar 2013 17:51:02 +0100 Subject: Remove unused sr_ptr monster_type field --- src/defines.h | 2 +- src/loadsave.c | 64 ---------------------------------------------------------- src/monster2.c | 16 --------------- src/object1.c | 1 - src/types.h | 2 -- 5 files changed, 1 insertion(+), 84 deletions(-) diff --git a/src/defines.h b/src/defines.h index d8a5d4f2..2c2d388d 100644 --- a/src/defines.h +++ b/src/defines.h @@ -4180,7 +4180,7 @@ #define MEGO_CHANCE 18 /* % chances of getting ego monsters */ -#define race_inf(m_ptr) (((m_ptr)->sr_ptr) ? (m_ptr)->sr_ptr : race_info_idx((m_ptr)->r_idx, (m_ptr)->ego)) +#define race_inf(m_ptr) (race_info_idx((m_ptr)->r_idx, (m_ptr)->ego)) /* Object generation */ #define OBJ_GENE_TREASURE 20 diff --git a/src/loadsave.c b/src/loadsave.c index 85c05260..f68d974c 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -1509,7 +1509,6 @@ static void do_item(object_type *o_ptr, int flag) static void do_monster(monster_type *m_ptr, int flag) { int i; - bool_ tmp; /* Read the monster race */ do_s16b(&m_ptr->r_idx, flag); @@ -1553,69 +1552,6 @@ static void do_monster(monster_type *m_ptr, int flag) do_byte(&m_ptr->blow[i].d_dice, flag); do_byte(&m_ptr->blow[i].d_side, flag); } - - /* Special race */ - tmp = (m_ptr->sr_ptr) ? TRUE : FALSE; - do_byte((byte*)&tmp, flag); - if (tmp) - { - if (flag == LS_LOAD) - { - MAKE(m_ptr->sr_ptr, monster_race); - } - do_u32b(&m_ptr->sr_ptr->name, flag); - do_u32b(&m_ptr->sr_ptr->text, flag); - - do_u16b(&m_ptr->sr_ptr->hdice, flag); - do_u16b(&m_ptr->sr_ptr->hside, flag); - - do_s16b(&m_ptr->sr_ptr->ac, flag); - - do_s16b(&m_ptr->sr_ptr->sleep, flag); - do_byte(&m_ptr->sr_ptr->aaf, flag); - do_byte(&m_ptr->sr_ptr->speed, flag); - - do_s32b(&m_ptr->sr_ptr->mexp, flag); - - do_s32b(&m_ptr->sr_ptr->weight, flag); - - do_byte(&m_ptr->sr_ptr->freq_inate, flag); - do_byte(&m_ptr->sr_ptr->freq_spell, flag); - - do_u32b(&m_ptr->sr_ptr->flags1, flag); - do_u32b(&m_ptr->sr_ptr->flags2, flag); - do_u32b(&m_ptr->sr_ptr->flags3, flag); - do_u32b(&m_ptr->sr_ptr->flags4, flag); - do_u32b(&m_ptr->sr_ptr->flags5, flag); - do_u32b(&m_ptr->sr_ptr->flags6, flag); - do_u32b(&m_ptr->sr_ptr->flags7, flag); - do_u32b(&m_ptr->sr_ptr->flags8, flag); - do_u32b(&m_ptr->sr_ptr->flags9, flag); - - /* Attacks */ - for (i = 0; i < 4; i++) - { - do_byte(&m_ptr->sr_ptr->blow[i].method, flag); - do_byte(&m_ptr->sr_ptr->blow[i].effect, flag); - do_byte(&m_ptr->sr_ptr->blow[i].d_dice, flag); - do_byte(&m_ptr->sr_ptr->blow[i].d_side, flag); - } - - for (i = 0; i < BODY_MAX; i++) - do_byte(&m_ptr->sr_ptr->body_parts[i], flag); - - do_byte(&m_ptr->sr_ptr->level, flag); - do_byte(&m_ptr->sr_ptr->rarity, flag); - - do_byte((byte*)&m_ptr->sr_ptr->d_char, flag); - do_byte(&m_ptr->sr_ptr->d_attr, flag); - - do_byte((byte*)&m_ptr->sr_ptr->x_char, flag); - do_byte(&m_ptr->sr_ptr->x_attr, flag); - - do_s16b(&m_ptr->sr_ptr->max_num, flag); - do_byte(&m_ptr->sr_ptr->cur_num, flag); - } } diff --git a/src/monster2.c b/src/monster2.c index 845434b1..d09f5cf6 100644 --- a/src/monster2.c +++ b/src/monster2.c @@ -492,10 +492,6 @@ void delete_monster_idx(int i) delete_object_idx(this_o_idx); } - /* Delete mind & special race if needed */ - if (m_ptr->sr_ptr) - KILL(m_ptr->sr_ptr, monster_race); - /* Wipe the Monster */ m_ptr = WIPE(m_ptr, monster_type); @@ -614,10 +610,6 @@ static void compact_monsters_aux(int i1, int i2) /* Structure copy */ COPY(&m_list[i2], &m_list[i1], monster_type); - /* Delete mind & special race if needed */ - if (m_list[i1].sr_ptr) - KILL(m_list[i1].sr_ptr, monster_race); - /* Wipe the hole */ m_ptr = WIPE(&m_list[i1], monster_type); } @@ -736,11 +728,6 @@ void wipe_m_list(void) /* Monster is gone */ cave[m_ptr->fy][m_ptr->fx].m_idx = 0; - /* Delete mind & special race if needed */ - if (m_ptr->sr_ptr) - KILL(m_ptr->sr_ptr, monster_race); - - /* Wipe the Monster */ m_ptr = WIPE(m_ptr, monster_type); } @@ -2316,9 +2303,6 @@ s16b place_monster_one(int y, int x, int r_idx, int ego, bool_ slp, int status) m_ptr->r_idx = r_idx; m_ptr->ego = ego; - /* No special, no mind */ - m_ptr->sr_ptr = NULL; - /* Place the monster at the location */ m_ptr->fy = y; m_ptr->fx = x; diff --git a/src/object1.c b/src/object1.c index a5dbc3d5..35dfbd5c 100644 --- a/src/object1.c +++ b/src/object1.c @@ -1615,7 +1615,6 @@ void object_desc(char *buf, object_type *o_ptr, int pref, int mode) char name[80]; monster_type monster; - monster.sr_ptr = 0; monster.r_idx = o_ptr->pval; monster.ego = o_ptr->pval2; monster.ml = TRUE; diff --git a/src/types.h b/src/types.h index 2339a9ce..7cd9a8a1 100644 --- a/src/types.h +++ b/src/types.h @@ -892,8 +892,6 @@ struct monster_type s16b target; /* Monster target */ s16b possessor; /* Is it under the control of a possessor ? */ - - monster_race *sr_ptr; /* Does it have a specific race(not in r_info) */ }; -- cgit v1.2.3 From 00030f75bc94779d8e0ac4f6941e626bff216a02 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Mar 2013 19:26:04 +0100 Subject: Fixups for include guards and __cplusplus --- src/h-basic.h | 10 ++++++---- src/h-config.h | 9 ++++++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/h-basic.h b/src/h-basic.h index b5ea5d87..a65780a5 100644 --- a/src/h-basic.h +++ b/src/h-basic.h @@ -1,7 +1,8 @@ -/* File: h-basic.h */ +#pragma once -#ifndef INCLUDED_H_BASIC_H -#define INCLUDED_H_BASIC_H +#ifdef __cplusplus +extern "C" { +#endif /* * The most basic "include" file. @@ -21,5 +22,6 @@ /* Basic constants and macros */ #include "h-define.h" +#ifdef __cplusplus +} // extern "C" #endif - diff --git a/src/h-config.h b/src/h-config.h index 53670e8f..307a7a27 100644 --- a/src/h-config.h +++ b/src/h-config.h @@ -1,7 +1,8 @@ -/* File: h-config.h */ +#pragma once -#ifndef INCLUDED_H_CONFIG_H -#define INCLUDED_H_CONFIG_H +#ifdef __cplusplus +extern "C" { +#endif /* * Choose the hardware, operating system, and compiler. @@ -271,4 +272,6 @@ # endif #endif +#ifdef __cplusplus +} // extern "C" #endif -- cgit v1.2.3 From 4daab005e482c0c94072e58edcc88ebd454a67cb Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Mar 2013 19:31:32 +0100 Subject: Disable stricmp -> strcasecmp remapping for Linux It seems to interfere with compilation using C++ --- src/h-config.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/h-config.h b/src/h-config.h index 307a7a27..3ebaa87f 100644 --- a/src/h-config.h +++ b/src/h-config.h @@ -248,10 +248,12 @@ extern "C" { /* * Linux has "stricmp()" with a different name */ +/* #if defined(linux) # define HAS_STRICMP # define stricmp strcasecmp #endif +*/ /* -- cgit v1.2.3 From 3ae7efc14c41b8676b3ad01d17a1b61acaad77f8 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Mar 2013 20:38:15 +0100 Subject: Const correctness --- src/cmd7.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd7.c b/src/cmd7.c index 02f84437..eaed8996 100644 --- a/src/cmd7.c +++ b/src/cmd7.c @@ -2784,7 +2784,7 @@ void alchemist_display_recipe(int tval, int sval, int ego) char selectchar[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*():;,.<=>[]{}/=?+'~"; byte selectitem[256]; -void strip_and_print(char *str, int color, int num) +void strip_and_print(const char *str, int color, int num) { int row = 2 + (num % 20), col = 40 * (num / 20); int ch, max_len = 0; @@ -3132,7 +3132,7 @@ int alchemist_recipe_select(int *tval, int sval, int ego, bool_ recipe) int choice[60]; int validc[60]; - char *string; + const char *string; /* Save and clear the screen */ @@ -4789,8 +4789,8 @@ void brand_ammo(int brand_type, int bolts_only) if ((a < INVEN_PACK) && (rand_int(100) < 50)) { object_type *o_ptr = &p_ptr->inventory[a]; - char *ammo_name; - char *aura_name; + const char *ammo_name; + const char *aura_name; char msg[48]; int aura_type, r; -- cgit v1.2.3 From e6a089b5bd1575fc2d54398101f507eb4eb1f7b5 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Mar 2013 20:36:58 +0100 Subject: Remove superfluous parameter from gain_random_corruption call --- src/cmd5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd5.c b/src/cmd5.c index 9571ce99..95ae0346 100644 --- a/src/cmd5.c +++ b/src/cmd5.c @@ -326,7 +326,7 @@ void do_poly_self(void) while ((power > rand_int(15)) && (rand_int(3) == 0)) { power -= 7; - (void) gain_random_corruption(0); + gain_random_corruption(); } if (power > rand_int(5)) -- cgit v1.2.3 From 2555c9c470fc19b77c24d3e534670c8e3904f186 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Mar 2013 21:22:54 +0100 Subject: Add missing parameter type and use of "try" Since C++ requires parameter types and "try" is a C++ keyword --- src/joke.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/joke.c b/src/joke.c index 0ff01557..ed07dcd3 100644 --- a/src/joke.c +++ b/src/joke.c @@ -1,10 +1,10 @@ #include "angband.h" -static void gen_joke_place_monster(r_idx) +static void gen_joke_place_monster(int r_idx) { - int try; + int try_; - for (try = 0; try < 1000; try++) + for (try_ = 0; try_ < 1000; try_++) { int x = randint(cur_hgt - 4) + 2; int y = randint(cur_wid - 4) + 2; -- cgit v1.2.3 From 27dfc9125b6fff1ec4dc869f6f644c45ec31d74f Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Mar 2013 21:36:30 +0100 Subject: Fix format strings to avoid casts This gets rid of old-style casts for C++ conversion --- src/cmd4.c | 4 ++-- src/cmd7.c | 4 ++-- src/powers.c | 2 +- src/store.c | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/cmd4.c b/src/cmd4.c index b74bfff9..0353f014 100644 --- a/src/cmd4.c +++ b/src/cmd4.c @@ -3820,7 +3820,7 @@ static void do_cmd_knowledge_kill_count(void) } else { - fprintf(fff, "You have defeated %ld enemies.\n\n", (long int) Total); + fprintf(fff, "You have defeated " FMTs32b " enemies.\n\n", Total); } } @@ -3874,7 +3874,7 @@ static void do_cmd_knowledge_kill_count(void) } fprintf(fff, "----------------------------------------------\n"); - fprintf(fff, " Total: %ld creature%s killed.\n", (long int) Total, (Total == 1 ? "" : "s")); + fprintf(fff, " Total: " FMTs32b " creature%s killed.\n", Total, (Total == 1 ? "" : "s")); /* Close the file */ my_fclose(fff); diff --git a/src/cmd7.c b/src/cmd7.c index eaed8996..c9be0c66 100644 --- a/src/cmd7.c +++ b/src/cmd7.c @@ -1229,10 +1229,10 @@ int show_flags(byte group, int pval) (items < 26) ? I2A(items) : ('0' + items - 26), al_name + a_select_flags[i].desc); if ( wizard || alchemist_has_stone()) - sprintf(ttt, "%c) %s (exp %ld)", + sprintf(ttt, "%c) %s (exp " FMTu32b ")", (items < 26) ? I2A(items) : ('0' + items - 26), al_name + a_select_flags[i].desc, - (long int) a_select_flags[i].xp); + a_select_flags[i].xp); /* Note: Somebody is VERY clever, and it wasn't me. Text printed as * TERM_DARK is actually printed as TERM_BLUE *SPACES* to prevent the diff --git a/src/powers.c b/src/powers.c index 7001a859..d6ecdecf 100644 --- a/src/powers.c +++ b/src/powers.c @@ -226,7 +226,7 @@ static void power_activate(int power) else o_ptr = &o_list[0 - idx]; /* Appraise it */ - sprintf(value, "%i au", (int)object_value(o_ptr)); + sprintf(value, FMTs32b " au", object_value(o_ptr)); /* Inscribe the value */ /* Get the original inscription */ diff --git a/src/store.c b/src/store.c index fb413eb8..99d8dfa6 100644 --- a/src/store.c +++ b/src/store.c @@ -1619,7 +1619,7 @@ void display_store(void) put_str(buf, 3, 10); /* Show the max price in the store (above prices) */ - strnfmt(buf, 80, "%s (%ld)", store_name, (long)(ot_ptr->max_cost)); + strnfmt(buf, 80, "%s (" FMTs16b ")", store_name, ot_ptr->max_cost); prt(buf, 3, 50); /* Label the item descriptions */ @@ -2273,7 +2273,7 @@ void store_purchase(void) object_desc(o_name, j_ptr, TRUE, 3); /* Message */ - msg_format("You bought %s for %ld gold.", o_name, (long)price); + msg_format("You bought %s for " FMTs32b " gold.", o_name, price); /* Erase the inscription */ j_ptr->note = 0; @@ -2605,7 +2605,7 @@ void store_sell(void) object_desc(o_name, q_ptr, TRUE, 3); /* Describe the result (in message buffer) */ - msg_format("You sold %s for %ld gold.", o_name, (long)price); + msg_format("You sold %s for " FMTs32b " gold.", o_name, price); /* Analyze the prices (and comment verbally) */ purchase_analyze(price, value, dummy); -- cgit v1.2.3 From b525c0b6164a46fcf358256bb693c71801569708 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Mar 2013 21:54:47 +0100 Subject: Remove unnecessary casts --- src/cmd4.c | 60 +++++++++++++++++++++++++++++----------------------------- src/cmd6.c | 10 +++++----- src/generate.c | 2 +- src/skills.c | 13 +++++++++---- src/wild.c | 8 ++++---- 5 files changed, 49 insertions(+), 44 deletions(-) diff --git a/src/cmd4.c b/src/cmd4.c index 0353f014..3a6ef2cc 100644 --- a/src/cmd4.c +++ b/src/cmd4.c @@ -2368,10 +2368,10 @@ void do_cmd_visuals(void) /* Analyze */ if (i == 'n') r = (r + max_r_idx + 1) % max_r_idx; if (i == 'N') r = (r + max_r_idx - 1) % max_r_idx; - if (i == 'a') r_ptr->x_attr = (byte)(ca + 1); - if (i == 'A') r_ptr->x_attr = (byte)(ca - 1); - if (i == 'c') r_ptr->x_char = (byte)(cc + 1); - if (i == 'C') r_ptr->x_char = (byte)(cc - 1); + if (i == 'a') r_ptr->x_attr = (ca + 1); + if (i == 'A') r_ptr->x_attr = (ca - 1); + if (i == 'c') r_ptr->x_char = (cc + 1); + if (i == 'C') r_ptr->x_char = (cc - 1); } } @@ -2388,10 +2388,10 @@ void do_cmd_visuals(void) { object_kind *k_ptr = &k_info[k]; - byte da = (byte)k_ptr->d_attr; - char dc = (byte)k_ptr->d_char; - byte ca = (byte)k_ptr->x_attr; - char cc = (byte)k_ptr->x_char; + byte da = k_ptr->d_attr; + char dc = k_ptr->d_char; + byte ca = k_ptr->x_attr; + char cc = k_ptr->x_char; /* Label the object */ Term_putstr(5, 17, -1, TERM_WHITE, @@ -2437,10 +2437,10 @@ void do_cmd_visuals(void) /* Analyze */ if (i == 'n') k = (k + max_k_idx + 1) % max_k_idx; if (i == 'N') k = (k + max_k_idx - 1) % max_k_idx; - if (i == 'a') k_info[k].x_attr = (byte)(ca + 1); - if (i == 'A') k_info[k].x_attr = (byte)(ca - 1); - if (i == 'c') k_info[k].x_char = (byte)(cc + 1); - if (i == 'C') k_info[k].x_char = (byte)(cc - 1); + if (i == 'a') k_info[k].x_attr = (ca + 1); + if (i == 'A') k_info[k].x_attr = (ca - 1); + if (i == 'c') k_info[k].x_char = (cc + 1); + if (i == 'C') k_info[k].x_char = (cc - 1); } } @@ -2457,10 +2457,10 @@ void do_cmd_visuals(void) { feature_type *f_ptr = &f_info[f]; - byte da = (byte)f_ptr->d_attr; - char dc = (byte)f_ptr->d_char; - byte ca = (byte)f_ptr->x_attr; - char cc = (byte)f_ptr->x_char; + byte da = f_ptr->d_attr; + char dc = f_ptr->d_char; + byte ca = f_ptr->x_attr; + char cc = f_ptr->x_char; /* Label the object */ Term_putstr(5, 17, -1, TERM_WHITE, @@ -2506,10 +2506,10 @@ void do_cmd_visuals(void) /* Analyze */ if (i == 'n') f = (f + max_f_idx + 1) % max_f_idx; if (i == 'N') f = (f + max_f_idx - 1) % max_f_idx; - if (i == 'a') f_info[f].x_attr = (byte)(ca + 1); - if (i == 'A') f_info[f].x_attr = (byte)(ca - 1); - if (i == 'c') f_info[f].x_char = (byte)(cc + 1); - if (i == 'C') f_info[f].x_char = (byte)(cc - 1); + if (i == 'a') f_info[f].x_attr = (ca + 1); + if (i == 'A') f_info[f].x_attr = (ca - 1); + if (i == 'c') f_info[f].x_char = (cc + 1); + if (i == 'C') f_info[f].x_char = (cc - 1); if (i == 'd') { f_info[f].x_char = f_ptr->d_char; @@ -2734,16 +2734,16 @@ void do_cmd_colors(void) if (i == ESCAPE) break; /* Analyze */ - if (i == 'n') a = (byte)(a + 1); - if (i == 'N') a = (byte)(a - 1); - if (i == 'k') angband_color_table[a][0] = (byte)(angband_color_table[a][0] + 1); - if (i == 'K') angband_color_table[a][0] = (byte)(angband_color_table[a][0] - 1); - if (i == 'r') angband_color_table[a][1] = (byte)(angband_color_table[a][1] + 1); - if (i == 'R') angband_color_table[a][1] = (byte)(angband_color_table[a][1] - 1); - if (i == 'g') angband_color_table[a][2] = (byte)(angband_color_table[a][2] + 1); - if (i == 'G') angband_color_table[a][2] = (byte)(angband_color_table[a][2] - 1); - if (i == 'b') angband_color_table[a][3] = (byte)(angband_color_table[a][3] + 1); - if (i == 'B') angband_color_table[a][3] = (byte)(angband_color_table[a][3] - 1); + if (i == 'n') a = (a + 1); + if (i == 'N') a = (a - 1); + if (i == 'k') angband_color_table[a][0] = (angband_color_table[a][0] + 1); + if (i == 'K') angband_color_table[a][0] = (angband_color_table[a][0] - 1); + if (i == 'r') angband_color_table[a][1] = (angband_color_table[a][1] + 1); + if (i == 'R') angband_color_table[a][1] = (angband_color_table[a][1] - 1); + if (i == 'g') angband_color_table[a][2] = (angband_color_table[a][2] + 1); + if (i == 'G') angband_color_table[a][2] = (angband_color_table[a][2] - 1); + if (i == 'b') angband_color_table[a][3] = (angband_color_table[a][3] + 1); + if (i == 'B') angband_color_table[a][3] = (angband_color_table[a][3] - 1); /* Hack -- react to changes */ Term_xtra(TERM_XTRA_REACT, 0); diff --git a/src/cmd6.c b/src/cmd6.c index 80f61816..b8a9f1df 100644 --- a/src/cmd6.c +++ b/src/cmd6.c @@ -4677,7 +4677,7 @@ int ring_of_power() /* Rewrite this -- pelpel */ if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2), (plev > 47 ? SUMMON_HI_UNDEAD_NO_UNIQUES : SUMMON_UNDEAD), - (bool_)(((plev > 24) && (randint(3) == 1)) ? TRUE : FALSE))) + (((plev > 24) && (randint(3) == 1)) ? TRUE : FALSE))) { msg_print("Cold winds begin to blow around you, " "carrying with them the stench of decay..."); @@ -5677,7 +5677,7 @@ const char *activation_aux(object_type * o_ptr, bool_ doit, int item) else { if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2), - SUMMON_THUNDERLORD, (bool_)(plev == 50 ? TRUE : FALSE))) + SUMMON_THUNDERLORD, (plev == 50 ? TRUE : FALSE))) { msg_print("A Thunderlord comes from thin air!"); msg_print("'I will help you in your difficult task.'"); @@ -6372,7 +6372,7 @@ const char *activation_aux(object_type * o_ptr, bool_ doit, int item) else { if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2), - SUMMON_ELEMENTAL, (bool_)(plev == 50 ? TRUE : FALSE))) + SUMMON_ELEMENTAL, (plev == 50 ? TRUE : FALSE))) { msg_print("An elemental materialises..."); msg_print("It seems obedient to you."); @@ -6398,7 +6398,7 @@ const char *activation_aux(object_type * o_ptr, bool_ doit, int item) else { if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2), - SUMMON_DEMON, (bool_)(plev == 50 ? TRUE : FALSE))) + SUMMON_DEMON, (plev == 50 ? TRUE : FALSE))) { msg_print("The area fills with a stench of sulphur and brimstone."); msg_print("'What is thy bidding... Master?'"); @@ -6426,7 +6426,7 @@ const char *activation_aux(object_type * o_ptr, bool_ doit, int item) { if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2), (plev > 47 ? SUMMON_HI_UNDEAD_NO_UNIQUES : SUMMON_UNDEAD), - (bool_)(((plev > 24) && (randint(3) == 1)) ? TRUE : FALSE))) + (((plev > 24) && (randint(3) == 1)) ? TRUE : FALSE))) { msg_print("Cold winds begin to blow around you, carrying with them the stench of decay..."); msg_print("Ancient, long-dead forms arise from the ground to serve you!"); diff --git a/src/generate.c b/src/generate.c index 652d2bee..b06129ab 100644 --- a/src/generate.c +++ b/src/generate.c @@ -1006,7 +1006,7 @@ static void place_random_door(int y, int x) else { /* Create jammed door */ - cave_set_feat(y, x, FEAT_DOOR_HEAD + 0x08 + (byte)rand_int(8)); + cave_set_feat(y, x, FEAT_DOOR_HEAD + 0x08 + rand_int(8)); } } diff --git a/src/skills.c b/src/skills.c index 12d5da56..900b6452 100644 --- a/src/skills.c +++ b/src/skills.c @@ -37,9 +37,14 @@ void increase_skill(int i, s16b *invest) if (((s_info[i].value + s_info[i].mod) / SKILL_STEP) >= (p_ptr->lev + max_skill_overage + 1)) { int hgt, wid; + char buf[256]; + + sprintf(buf, + "Cannot raise a skill value above " FMTs32b " + player level.", + max_skill_overage); Term_get_size(&wid, &hgt); - msg_box(format("Cannot raise a skill value above %i + player level.", max_skill_overage), (int)(hgt / 2), (int)(wid / 2)); + msg_box(buf, hgt / 2, wid / 2); return; } @@ -576,7 +581,7 @@ void do_cmd_skill() flush(); /* Ask we can commit the change */ - if (msg_box("Save and use these skill values? (y/n)", (int)(hgt / 2), (int)(wid / 2)) != 'y') + if (msg_box("Save and use these skill values? (y/n)", hgt / 2, wid / 2) != 'y') { /* User declines -- restore the skill values before exiting */ @@ -1566,7 +1571,7 @@ void gain_ability(int ab) if (!can_learn_ability(ab)) { - msg_box("You cannot learn this ability.", (int)(hgt / 2), (int)(wid / 2)); + msg_box("You cannot learn this ability.", hgt / 2, wid / 2); return; } @@ -1574,7 +1579,7 @@ void gain_ability(int ab) flush(); /* Ask we can commit the change */ - if (msg_box("Learn this ability(this is permanent)? (y/n)", (int)(hgt / 2), (int)(wid / 2)) != 'y') + if (msg_box("Learn this ability(this is permanent)? (y/n)", hgt / 2, wid / 2) != 'y') { return; } diff --git a/src/wild.c b/src/wild.c index 76ad3136..13a221d0 100644 --- a/src/wild.c +++ b/src/wild.c @@ -191,10 +191,10 @@ int generate_area(int y, int x, bool_ border, bool_ corner, bool_ refresh) * ToDo: calculate the medium height of the adjacent * terrains for every corner. */ - cave_set_feat(1, 1, (byte)rand_int(MAX_WILD_TERRAIN)); - cave_set_feat(MAX_HGT - 2, 1, (byte)rand_int(MAX_WILD_TERRAIN)); - cave_set_feat(1, MAX_WID - 2, (byte)rand_int(MAX_WILD_TERRAIN)); - cave_set_feat(MAX_HGT - 2, MAX_WID - 2, (byte)rand_int(MAX_WILD_TERRAIN)); + cave_set_feat(1, 1, rand_int(MAX_WILD_TERRAIN)); + cave_set_feat(MAX_HGT - 2, 1, rand_int(MAX_WILD_TERRAIN)); + cave_set_feat(1, MAX_WID - 2, rand_int(MAX_WILD_TERRAIN)); + cave_set_feat(MAX_HGT - 2, MAX_WID - 2, rand_int(MAX_WILD_TERRAIN)); if (!corner) { -- cgit v1.2.3 From 763f107919b356e295ce372734a82d79661848aa Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Mar 2013 22:52:25 +0100 Subject: Constness fix --- src/q_rand.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/q_rand.c b/src/q_rand.c index 4296d85d..84d721b8 100644 --- a/src/q_rand.c +++ b/src/q_rand.c @@ -388,7 +388,7 @@ static bool_ quest_random_gen_hook(const char *fmt) static bool_ quest_random_dump_hook(const char *fmt) { - static char *number[] = + static const char *number[] = { "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" }; int i, valid = 0, lscnt = 0, pcnt = 0; -- cgit v1.2.3 From 9519fbdcfe2b2aad12c95e006a94403c1817355a Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Mar 2013 23:02:33 +0100 Subject: Add missing hook function parameters in q_library --- src/q_library.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/q_library.c b/src/q_library.c index 36d2cd0b..b54a9e48 100644 --- a/src/q_library.c +++ b/src/q_library.c @@ -297,7 +297,7 @@ static void library_quest_fill_book() screen_load(); } -static bool_ quest_library_gen_hook() +static bool_ quest_library_gen_hook(const char *fmt) { /* Only if player doing this quest */ if (p_ptr->inside_quest != QUEST_LIBRARY) @@ -340,7 +340,7 @@ static bool_ quest_library_gen_hook() return TRUE; } -static bool_ quest_library_stair_hook() +static bool_ quest_library_stair_hook(const char *fmt) { bool_ ret; -- cgit v1.2.3 From 3ceb6ba12f66db6df2e1b73e02de33a8950564de Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Mar 2013 06:32:45 +0100 Subject: Move extern declarations in wizard*.c to externs.h --- src/dungeon.c | 6 ------ src/externs.h | 7 +++++++ src/status.c | 3 +-- src/wizard1.c | 8 +------- src/wizard2.c | 19 +------------------ 5 files changed, 10 insertions(+), 33 deletions(-) diff --git a/src/dungeon.c b/src/dungeon.c index 5f3d9ab6..5eb38c51 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -3434,12 +3434,6 @@ static bool_ enter_debug_mode(void) } -/* - * Hack -- Declare the Debug Routines - */ -extern void do_cmd_debug(void); - - /* * Parse and execute the current command * Give "Warning" on illegal commands. diff --git a/src/externs.h b/src/externs.h index ee6359fd..ce388136 100644 --- a/src/externs.h +++ b/src/externs.h @@ -2173,9 +2173,13 @@ extern int get_fbranch(void); extern int get_flevel(void); extern bool_ get_dungeon_save(char *buf); +/* wizard1.c */ +extern void do_cmd_spoilers(); + /* wizard2.c */ extern void do_cmd_wiz_cure_all(void); extern void do_cmd_wiz_named_friendly(int r_idx, bool_ slp); +extern void do_cmd_debug(); extern tval_desc2 tvals[]; /* notes.c */ @@ -2263,6 +2267,9 @@ extern bool_ easy_floor; /* script.c */ extern void init_lua_init(void); +/* status.c */ +extern void status_main(); + /* modules.c */ extern void module_reset_dir(cptr dir, cptr new_path); extern cptr force_module; diff --git a/src/status.c b/src/status.c index 967a8323..c6306693 100644 --- a/src/status.c +++ b/src/status.c @@ -34,7 +34,6 @@ static void status_companion(void); void status_sight(void); void status_attr(void); void status_combat(void); -void status_main(void); void status_move(void); void status_item(void); void az_line(int, u32b[INVEN_TOTAL - INVEN_WIELD + 2][7]); @@ -373,7 +372,7 @@ void status_res(void) } } -void status_main(void) +void status_main() { int do_quit = 0; char c; diff --git a/src/wizard1.c b/src/wizard1.c index 7daef324..ab7635d7 100644 --- a/src/wizard1.c +++ b/src/wizard1.c @@ -2652,16 +2652,10 @@ static void spoil_spells(cptr fname) } - -/* - * Forward declare - */ -extern void do_cmd_spoilers(void); - /* * Create Spoiler files -BEN- */ -void do_cmd_spoilers(void) +void do_cmd_spoilers() { int i; diff --git a/src/wizard2.c b/src/wizard2.c index eb391437..a843b7c9 100644 --- a/src/wizard2.c +++ b/src/wizard2.c @@ -13,9 +13,6 @@ #include "angband.h" #include "hooks.h" -void do_cmd_wizard_body(s16b); -extern void status_main(void); - /* * Adds a lvl to a monster */ @@ -1578,25 +1575,11 @@ extern void do_cmd_wiz_body(s16b bidx) } -/* - * External function - */ -extern void do_cmd_spoilers(void); - - - -/* - * Hack -- declare external function - */ -extern void do_cmd_debug(void); - - - /* * Ask for and parse a "debug command" * The "command_arg" may have been set. */ -void do_cmd_debug(void) +void do_cmd_debug() { int x, y; char cmd; -- cgit v1.2.3 From acca45d6a22406a74d5dc56e00ff0c6ad8e478b8 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Mar 2013 23:00:48 +0100 Subject: Constness fixes --- src/birth.c | 8 +- src/externs.h | 286 +++++++++++++++++++++++++++---------------------------- src/files.c | 6 +- src/lua_bind.c | 6 +- src/object1.c | 2 +- src/q_god.c | 8 +- src/spell_type.c | 16 ++-- src/spell_type.h | 14 +-- src/spells3.c | 278 ++++++++++++++++++++++++++--------------------------- src/status.c | 20 ++-- src/wizard1.c | 2 +- src/wizard2.c | 2 +- 12 files changed, 324 insertions(+), 324 deletions(-) diff --git a/src/birth.c b/src/birth.c index c6b612d3..60a6b3ee 100644 --- a/src/birth.c +++ b/src/birth.c @@ -58,7 +58,7 @@ static s32b auto_round; static s32b last_round; /* Human */ -static char *human_syllable1[] = +static const char *human_syllable1[] = { "Ab", "Ac", "Ad", "Af", "Agr", "Ast", "As", "Al", "Adw", "Adr", "Ar", "B", "Br", "C", "Cr", "Ch", "Cad", "D", "Dr", "Dw", "Ed", "Eth", "Et", @@ -68,7 +68,7 @@ static char *human_syllable1[] = "Tr", "Th", "V", "Y", "Z", "W", "Wic", }; -static char *human_syllable2[] = +static const char *human_syllable2[] = { "a", "ae", "au", "ao", "are", "ale", "ali", "ay", "ardo", "e", "ei", "ea", "eri", "era", "ela", "eli", "enda", "erra", "i", "ia", "ie", @@ -76,7 +76,7 @@ static char *human_syllable2[] = "ore", "u", "y", }; -static char *human_syllable3[] = +static const char *human_syllable3[] = { "a", "and", "b", "bwyn", "baen", "bard", "c", "ctred", "cred", "ch", "can", "d", "dan", "don", "der", "dric", "dfrid", "dus", "f", "g", @@ -95,7 +95,7 @@ static char *human_syllable3[] = */ static void create_random_name(int race, char *name) { - char *syl1, *syl2, *syl3; + const char *syl1, *syl2, *syl3; int idx; diff --git a/src/externs.h b/src/externs.h index ce388136..99792082 100644 --- a/src/externs.h +++ b/src/externs.h @@ -859,11 +859,11 @@ extern errr predict_score(void); extern void predict_score_gui(bool_ *initialized, bool_ *game_in_progress); extern void close_game(void); extern errr get_rnd_line(const char * file_name, char * output); -extern char *get_line(char* fname, cptr fdir, char *linbuf, int line); +extern char *get_line(const char* fname, cptr fdir, char *linbuf, int line); extern void do_cmd_knowledge_corruptions(void); extern void race_legends(void); extern void show_highclass(int building); -extern errr get_xtra_line(char * file_name, monster_type *m_ptr, char * output); +extern errr get_xtra_line(const char * file_name, monster_type *m_ptr, char * output); /* gen_maze.c */ extern bool_ level_generate_maze(); @@ -1362,17 +1362,17 @@ extern s32b THUNDERSTORM; extern s32b STERILIZE; casting_result air_noxious_cloud(int); -char *air_noxious_cloud_info(); +const char *air_noxious_cloud_info(); casting_result air_wings_of_winds(int); -char *air_wings_of_winds_info(); +const char *air_wings_of_winds_info(); casting_result air_invisibility(int); -char *air_invisibility_info(); +const char *air_invisibility_info(); casting_result air_poison_blood(int); -char *air_poison_blood_info(); +const char *air_poison_blood_info(); casting_result air_thunderstorm(int); -char *air_thunderstorm_info(); +const char *air_thunderstorm_info(); casting_result air_sterilize(int); -char *air_sterilize_info(); +const char *air_sterilize_info(); extern s32b BLINK; extern s32b DISARM; @@ -1382,17 +1382,17 @@ extern s32b RECALL; extern s32b PROBABILITY_TRAVEL; casting_result convey_blink(int); -char *convey_blink_info(); +const char *convey_blink_info(); casting_result convey_disarm(int); -char *convey_disarm_info(); +const char *convey_disarm_info(); casting_result convey_teleport(int); -char *convey_teleport_info(); +const char *convey_teleport_info(); casting_result convey_teleport_away(int); -char *convey_teleport_away_info(); +const char *convey_teleport_away_info(); casting_result convey_recall(int); -char *convey_recall_info(); +const char *convey_recall_info(); casting_result convey_probability_travel(int); -char *convey_probability_travel_info(); +const char *convey_probability_travel_info(); extern s32b DEMON_BLADE; extern s32b DEMON_MADNESS; @@ -1405,23 +1405,23 @@ extern s32b DISCHARGE_MINION; extern s32b CONTROL_DEMON; casting_result demonology_demon_blade(int); -char *demonology_demon_blade_info(); +const char *demonology_demon_blade_info(); casting_result demonology_demon_madness(int); -char *demonology_demon_madness_info(); +const char *demonology_demon_madness_info(); casting_result demonology_demon_field(int); -char *demonology_demon_field_info(); +const char *demonology_demon_field_info(); casting_result demonology_doom_shield(int); -char *demonology_doom_shield_info(); +const char *demonology_doom_shield_info(); casting_result demonology_unholy_word(int); -char *demonology_unholy_word_info(); +const char *demonology_unholy_word_info(); casting_result demonology_demon_cloak(int); -char *demonology_demon_cloak_info(); +const char *demonology_demon_cloak_info(); casting_result demonology_summon_demon(int); -char *demonology_summon_demon_info(); +const char *demonology_summon_demon_info(); casting_result demonology_discharge_minion(int); -char *demonology_discharge_minion_info(); +const char *demonology_discharge_minion_info(); casting_result demonology_control_demon(int); -char *demonology_control_demon_info(); +const char *demonology_control_demon_info(); extern s32b STARIDENTIFY; extern s32b IDENTIFY; @@ -1431,17 +1431,17 @@ extern s32b REVEALWAYS; extern s32b SENSEMONSTERS; casting_result divination_greater_identify(int); -char *divination_greater_identify_info(); +const char *divination_greater_identify_info(); casting_result divination_identify(int); -char *divination_identify_info(); +const char *divination_identify_info(); casting_result divination_vision(int); -char *divination_vision_info(); +const char *divination_vision_info(); casting_result divination_sense_hidden(int); -char *divination_sense_hidden_info(); +const char *divination_sense_hidden_info(); casting_result divination_reveal_ways(int); -char *divination_reveal_ways_info(); +const char *divination_reveal_ways_info(); casting_result divination_sense_monsters(int); -char *divination_sense_monsters_info(); +const char *divination_sense_monsters_info(); extern s32b STONESKIN; extern s32b DIG; @@ -1450,15 +1450,15 @@ extern s32b STRIKE; extern s32b SHAKE; casting_result earth_stone_skin(int); -char *earth_stone_skin_info(); +const char *earth_stone_skin_info(); casting_result earth_dig(int); -char *earth_dig_info(); +const char *earth_dig_info(); casting_result earth_stone_prison(int); -char *earth_stone_prison_info(); +const char *earth_stone_prison_info(); casting_result earth_strike(int); -char *earth_strike_info(); +const char *earth_strike_info(); casting_result earth_shake(int); -char *earth_shake_info(); +const char *earth_shake_info(); extern s32b ERU_SEE; extern s32b ERU_LISTEN; @@ -1466,13 +1466,13 @@ extern s32b ERU_UNDERSTAND; extern s32b ERU_PROT; casting_result eru_see_the_music(int); -char *eru_see_the_music_info(); +const char *eru_see_the_music_info(); casting_result eru_listen_to_the_music(int); -char *eru_listen_to_the_music_info(); +const char *eru_listen_to_the_music_info(); casting_result eru_know_the_music(int); -char *eru_know_the_music_info(); +const char *eru_know_the_music_info(); casting_result eru_lay_of_protection(int); -char *eru_lay_of_protection_info(); +const char *eru_lay_of_protection_info(); extern s32b GLOBELIGHT; extern s32b FIREFLASH; @@ -1481,15 +1481,15 @@ extern s32b FIREWALL; extern s32b FIREGOLEM; casting_result fire_globe_of_light(int); -char *fire_globe_of_light_info(); +const char *fire_globe_of_light_info(); casting_result fire_fireflash(int); -char *fire_fireflash_info(); +const char *fire_fireflash_info(); casting_result fire_fiery_shield(int); -char *fire_fiery_shield_info(); +const char *fire_fiery_shield_info(); casting_result fire_firewall(int); -char *fire_firewall_info(); +const char *fire_firewall_info(); casting_result fire_golem(int); -char *fire_golem_info(); +const char *fire_golem_info(); extern s32b CALL_THE_ELEMENTS; extern s32b CHANNEL_ELEMENTS; @@ -1501,25 +1501,25 @@ extern s32b GROW_BARRIER; extern s32b ELEMENTAL_MINION; casting_result geomancy_call_the_elements(int); -char *geomancy_call_the_elements_info(); +const char *geomancy_call_the_elements_info(); casting_result geomancy_channel_elements(int); -char *geomancy_channel_elements_info(); +const char *geomancy_channel_elements_info(); casting_result geomancy_elemental_wave(int); -char *geomancy_elemental_wave_info(); +const char *geomancy_elemental_wave_info(); casting_result geomancy_vaporize(int); -char *geomancy_vaporize_info(); +const char *geomancy_vaporize_info(); bool_ geomancy_vaporize_depends(); casting_result geomancy_geolysis(int); -char *geomancy_geolysis_info(); +const char *geomancy_geolysis_info(); bool_ geomancy_geolysis_depends(); casting_result geomancy_dripping_tread(int); -char *geomancy_dripping_tread_info(); +const char *geomancy_dripping_tread_info(); bool_ geomancy_dripping_tread_depends(); casting_result geomancy_grow_barrier(int); -char *geomancy_grow_barrier_info(); +const char *geomancy_grow_barrier_info(); bool_ geomancy_grow_barrier_depends(); casting_result geomancy_elemental_minion(int); -char *geomancy_elemental_minion_info(); +const char *geomancy_elemental_minion_info(); extern s32b MANATHRUST; extern s32b DELCURSES; @@ -1527,13 +1527,13 @@ extern s32b RESISTS; extern s32b MANASHIELD; casting_result mana_manathrust(int); -char *mana_manathrust_info(); +const char *mana_manathrust_info(); casting_result mana_remove_curses(int); -char *mana_remove_curses_info(); +const char *mana_remove_curses_info(); casting_result mana_elemental_shield(int); -char *mana_elemental_shield_info(); +const char *mana_elemental_shield_info(); casting_result mana_disruption_shield(int); -char *mana_disruption_shield_info(); +const char *mana_disruption_shield_info(); extern s32b MANWE_SHIELD; extern s32b MANWE_AVATAR; @@ -1541,13 +1541,13 @@ extern s32b MANWE_BLESS; extern s32b MANWE_CALL; casting_result manwe_wind_shield(int); -char *manwe_wind_shield_info(); +const char *manwe_wind_shield_info(); casting_result manwe_avatar(int); -char *manwe_avatar_info(); +const char *manwe_avatar_info(); casting_result manwe_blessing(int); -char *manwe_blessing_info(); +const char *manwe_blessing_info(); casting_result manwe_call(int); -char *manwe_call_info(); +const char *manwe_call_info(); extern s32b MELKOR_CURSE; extern s32b MELKOR_CORPSE_EXPLOSION; @@ -1556,11 +1556,11 @@ extern s32b MELKOR_MIND_STEAL; void do_melkor_curse(int m_idx); casting_result melkor_curse(int); -char *melkor_curse_info(); +const char *melkor_curse_info(); casting_result melkor_corpse_explosion(int); -char *melkor_corpse_explosion_info(); +const char *melkor_corpse_explosion_info(); casting_result melkor_mind_steal(int); -char *melkor_mind_steal_info(); +const char *melkor_mind_steal_info(); extern s32b RECHARGE; extern s32b SPELLBINDER; @@ -1570,15 +1570,15 @@ extern s32b INERTIA_CONTROL; extern timer_type *TIMER_INERTIA_CONTROL; casting_result meta_recharge(int); -char *meta_recharge_info(); +const char *meta_recharge_info(); casting_result meta_spellbinder(int); -char *meta_spellbinder_info(); +const char *meta_spellbinder_info(); casting_result meta_disperse_magic(int); -char *meta_disperse_magic_info(); +const char *meta_disperse_magic_info(); casting_result meta_tracker(int); -char *meta_tracker_info(); +const char *meta_tracker_info(); casting_result meta_inertia_control(int); -char *meta_inertia_control_info(); +const char *meta_inertia_control_info(); void meta_inertia_control_timer_callback(); void meta_inertia_control_calc_mana(int *msp); @@ -1590,13 +1590,13 @@ extern s32b ARMOROFFEAR; extern s32b STUN; casting_result mind_charm(int); -char *mind_charm_info(); +const char *mind_charm_info(); casting_result mind_confuse(int); -char *mind_confuse_info(); +const char *mind_confuse_info(); casting_result mind_armor_of_fear(int); -char *mind_armor_of_fear_info(); +const char *mind_armor_of_fear_info(); casting_result mind_stun(int); -char *mind_stun_info(); +const char *mind_stun_info(); extern s32b MAGELOCK; extern s32b SLOWMONSTER; @@ -1604,24 +1604,24 @@ extern s32b ESSENCESPEED; extern s32b BANISHMENT; casting_result tempo_magelock(int); -char *tempo_magelock_info(); +const char *tempo_magelock_info(); casting_result tempo_slow_monster(int); -char *tempo_slow_monster_info(); +const char *tempo_slow_monster_info(); casting_result tempo_essence_of_speed(int); -char *tempo_essence_of_speed_info(); +const char *tempo_essence_of_speed_info(); casting_result tempo_banishment(int); -char *tempo_banishment_info(); +const char *tempo_banishment_info(); extern s32b TULKAS_AIM; extern s32b TULKAS_WAVE; extern s32b TULKAS_SPIN; casting_result tulkas_divine_aim(int); -char *tulkas_divine_aim_info(); +const char *tulkas_divine_aim_info(); casting_result tulkas_wave_of_power(int); -char *tulkas_wave_of_power_info(); +const char *tulkas_wave_of_power_info(); casting_result tulkas_whirlwind(int); -char *tulkas_whirlwind_info(); +const char *tulkas_whirlwind_info(); extern s32b DRAIN; extern s32b GENOCIDE; @@ -1632,13 +1632,13 @@ int udun_in_book(s32b sval, s32b pval); int levels_in_book(s32b sval, s32b pval); casting_result udun_drain(int); -char *udun_drain_info(); +const char *udun_drain_info(); casting_result udun_genocide(int); -char *udun_genocide_info(); +const char *udun_genocide_info(); casting_result udun_wraithform(int); -char *udun_wraithform_info(); +const char *udun_wraithform_info(); casting_result udun_flame_of_udun(int); -char *udun_flame_of_udun_info(); +const char *udun_flame_of_udun_info(); extern s32b TIDALWAVE; extern s32b ICESTORM; @@ -1647,15 +1647,15 @@ extern s32b VAPOR; extern s32b GEYSER; casting_result water_tidal_wave(int); -char *water_tidal_wave_info(); +const char *water_tidal_wave_info(); casting_result water_ice_storm(int); -char *water_ice_storm_info(); +const char *water_ice_storm_info(); casting_result water_ent_potion(int); -char *water_ent_potion_info(); +const char *water_ent_potion_info(); casting_result water_vapor(int); -char *water_vapor_info(); +const char *water_vapor_info(); casting_result water_geyser(int); -char *water_geyser_info(); +const char *water_geyser_info(); extern s32b YAVANNA_CHARM_ANIMAL; extern s32b YAVANNA_GROW_GRASS; @@ -1664,15 +1664,15 @@ extern s32b YAVANNA_WATER_BITE; extern s32b YAVANNA_UPROOT; casting_result yavanna_charm_animal(int); -char *yavanna_charm_animal_info(); +const char *yavanna_charm_animal_info(); casting_result yavanna_grow_grass(int); -char *yavanna_grow_grass_info(); +const char *yavanna_grow_grass_info(); casting_result yavanna_tree_roots(int); -char *yavanna_tree_roots_info(); +const char *yavanna_tree_roots_info(); casting_result yavanna_water_bite(int); -char *yavanna_water_bite_info(); +const char *yavanna_water_bite_info(); casting_result yavanna_uproot(int); -char *yavanna_uproot_info(); +const char *yavanna_uproot_info(); extern s32b GROWTREE; extern s32b HEALING; @@ -1682,17 +1682,17 @@ extern s32b SUMMONANNIMAL; extern s32b GROW_ATHELAS; casting_result nature_grow_trees(int); -char *nature_grow_trees_info(); +const char *nature_grow_trees_info(); casting_result nature_healing(int); -char *nature_healing_info(); +const char *nature_healing_info(); casting_result nature_recovery(int); -char *nature_recovery_info(); +const char *nature_recovery_info(); casting_result nature_regeneration(int); -char *nature_regeneration_info(); +const char *nature_regeneration_info(); casting_result nature_summon_animal(int); -char *nature_summon_animal_info(); +const char *nature_summon_animal_info(); casting_result nature_grow_athelas(int); -char *nature_grow_athelas_info(); +const char *nature_grow_athelas_info(); extern s32b DEVICE_HEAL_MONSTER; extern s32b DEVICE_SPEED_MONSTER; @@ -1710,33 +1710,33 @@ extern s32b DEVICE_RADAGAST; extern s32b DEVICE_VALAROMA; casting_result device_heal_monster(int); -char *device_heal_monster_info(); +const char *device_heal_monster_info(); casting_result device_haste_monster(int); -char *device_haste_monster_info(); +const char *device_haste_monster_info(); casting_result device_wish(int); -char *device_wish_info(); +const char *device_wish_info(); casting_result device_summon_monster(int); -char *device_summon_monster_info(); +const char *device_summon_monster_info(); casting_result device_mana(int); -char *device_mana_info(); +const char *device_mana_info(); casting_result device_nothing(int); -char *device_nothing_info(); +const char *device_nothing_info(); casting_result device_lebohaum(int); -char *device_lebohaum_info(); +const char *device_lebohaum_info(); casting_result device_maggot(int); -char *device_maggot_info(); +const char *device_maggot_info(); casting_result device_holy_fire(int); -char *device_holy_fire_info(); +const char *device_holy_fire_info(); casting_result device_eternal_flame(int); -char *device_eternal_flame_info(); +const char *device_eternal_flame_info(); casting_result device_durandil(int); -char *device_durandil_info(); +const char *device_durandil_info(); casting_result device_thunderlords(int); -char *device_thunderlords_info(); +const char *device_thunderlords_info(); casting_result device_radagast(int); -char *device_radagast_info(); +const char *device_radagast_info(); casting_result device_valaroma(int); -char *device_valaroma_info(); +const char *device_valaroma_info(); extern s32b MUSIC_STOP; extern s32b MUSIC_HOLD; @@ -1753,51 +1753,51 @@ extern s32b MUSIC_YLMIR; extern s32b MUSIC_AMBARKANTA; casting_result music_stop_singing_spell(int); -char *music_stop_singing_info(); +const char *music_stop_singing_info(); int music_holding_pattern_lasting(); casting_result music_holding_pattern_spell(int); -char *music_holding_pattern_info(); +const char *music_holding_pattern_info(); int music_illusion_pattern_lasting(); casting_result music_illusion_pattern_spell(int); -char *music_illusion_pattern_info(); +const char *music_illusion_pattern_info(); int music_stun_pattern_lasting(); casting_result music_stun_pattern_spell(int); -char *music_stun_pattern_info(); +const char *music_stun_pattern_info(); int music_song_of_the_sun_lasting(); casting_result music_song_of_the_sun_spell(int); -char *music_song_of_the_sun_info(); +const char *music_song_of_the_sun_info(); int music_flow_of_life_lasting(); casting_result music_flow_of_life_spell(int); -char *music_flow_of_life_info(); +const char *music_flow_of_life_info(); int music_heroic_ballad_lasting(); casting_result music_heroic_ballad_spell(int); -char *music_heroic_ballad_info(); +const char *music_heroic_ballad_info(); int music_hobbit_melodies_lasting(); casting_result music_hobbit_melodies_spell(int); -char *music_hobbit_melodies_info(); +const char *music_hobbit_melodies_info(); int music_clairaudience_lasting(); casting_result music_clairaudience_spell(int); -char *music_clairaudience_info(); +const char *music_clairaudience_info(); casting_result music_blow_spell(int); -char *music_blow_info(); +const char *music_blow_info(); casting_result music_gush_of_wind_spell(int); -char *music_gush_of_wind_info(); +const char *music_gush_of_wind_info(); casting_result music_horns_of_ylmir_spell(int); -char *music_horns_of_ylmir_info(); +const char *music_horns_of_ylmir_info(); casting_result music_ambarkanta_spell(int); -char *music_ambarkanta_info(); +const char *music_ambarkanta_info(); extern s32b AULE_FIREBRAND; extern s32b AULE_ENCHANT_WEAPON; @@ -1805,13 +1805,13 @@ extern s32b AULE_ENCHANT_ARMOUR; extern s32b AULE_CHILD; casting_result aule_firebrand_spell(int); -char *aule_firebrand_info(); +const char *aule_firebrand_info(); casting_result aule_enchant_weapon_spell(int); -char *aule_enchant_weapon_info(); +const char *aule_enchant_weapon_info(); casting_result aule_enchant_armour_spell(int); -char *aule_enchant_armour_info(); +const char *aule_enchant_armour_info(); casting_result aule_child_spell(int); -char *aule_child_info(); +const char *aule_child_info(); extern s32b MANDOS_TEARS_LUTHIEN; extern s32b MANDOS_SPIRIT_FEANTURI; @@ -1819,13 +1819,13 @@ extern s32b MANDOS_TALE_DOOM; extern s32b MANDOS_CALL_HALLS; casting_result mandos_tears_of_luthien_spell(int); -char *mandos_tears_of_luthien_info(); +const char *mandos_tears_of_luthien_info(); casting_result mandos_spirit_of_the_feanturi_spell(int); -char *mandos_spirit_of_the_feanturi_info(); +const char *mandos_spirit_of_the_feanturi_info(); casting_result mandos_tale_of_doom_spell(int); -char *mandos_tale_of_doom_info(); +const char *mandos_tale_of_doom_info(); casting_result mandos_call_to_the_halls_spell(int); -char *mandos_call_to_the_halls_info(); +const char *mandos_call_to_the_halls_info(); extern s32b ULMO_BELEGAER; extern s32b ULMO_DRAUGHT_ULMONAN; @@ -1833,13 +1833,13 @@ extern s32b ULMO_CALL_ULUMURI; extern s32b ULMO_WRATH; casting_result ulmo_song_of_belegaer_spell(int); -char *ulmo_song_of_belegaer_info(); +const char *ulmo_song_of_belegaer_info(); casting_result ulmo_draught_of_ulmonan_spell(int); -char *ulmo_draught_of_ulmonan_info(); +const char *ulmo_draught_of_ulmonan_info(); casting_result ulmo_call_of_the_ulumuri_spell(int); -char *ulmo_call_of_the_ulumuri_info(); +const char *ulmo_call_of_the_ulumuri_info(); casting_result ulmo_wrath_of_ulmo_spell(int); -char *ulmo_wrath_of_ulmo_info(); +const char *ulmo_wrath_of_ulmo_info(); extern s32b VARDA_LIGHT_VALINOR; extern s32b VARDA_CALL_ALMAREN; @@ -1847,13 +1847,13 @@ extern s32b VARDA_EVENSTAR; extern s32b VARDA_STARKINDLER; casting_result varda_light_of_valinor_spell(int); -char *varda_light_of_valinor_info(); +const char *varda_light_of_valinor_info(); casting_result varda_call_of_almaren_spell(int); -char *varda_call_of_almaren_info(); +const char *varda_call_of_almaren_info(); casting_result varda_evenstar_spell(int); -char *varda_evenstar_info(); +const char *varda_evenstar_info(); casting_result varda_star_kindler_spell(int); -char *varda_star_kindler_info(); +const char *varda_star_kindler_info(); /* spells4.c */ @@ -2302,8 +2302,8 @@ extern s32b get_level_use_stick; extern void set_target(int y, int x); extern void get_target(int dir, int *y, int *x); -extern void get_map_size(char *name, int *ysize, int *xsize); -extern void load_map(char *name, int *y, int *x); +extern void get_map_size(const char *name, int *ysize, int *xsize); +extern void load_map(const char *name, int *y, int *x); extern int lua_get_new_bounty_monster(int lev); diff --git a/src/files.c b/src/files.c index ad8322cf..a599af23 100644 --- a/src/files.c +++ b/src/files.c @@ -1030,7 +1030,7 @@ static void prt_lnum(cptr header, s32b num, int row, int col, byte color) * Print number with header at given row, column */ static void prt_num(cptr header, int num, int row, int col, byte color, - char *space) + cptr space) { int len = strlen(header); char out_val[32]; @@ -5670,7 +5670,7 @@ errr get_rnd_line(const char *file_name, char *output) * * Caution: 'linbuf' should be at least 80 byte long. */ -char *get_line(char* fname, cptr fdir, char *linbuf, int line) +char *get_line(const char* fname, cptr fdir, char *linbuf, int line) { FILE* fp; int i; @@ -5718,7 +5718,7 @@ char *get_line(char* fname, cptr fdir, char *linbuf, int line) * understand such complexities -- and added extra error checkings * and made sure fd is always closed -- pelpel */ -errr get_xtra_line(char *file_name, monster_type *m_ptr, char *output) +errr get_xtra_line(const char *file_name, monster_type *m_ptr, char *output) { FILE *fp; char buf[1024]; diff --git a/src/lua_bind.c b/src/lua_bind.c index 2e8a7083..b56f8dd8 100644 --- a/src/lua_bind.c +++ b/src/lua_bind.c @@ -213,7 +213,7 @@ void get_target(int dir, int *y, int *x) } /* Level gen */ -void get_map_size(char *name, int *ysize, int *xsize) +void get_map_size(const char *name, int *ysize, int *xsize) { *xsize = 0; *ysize = 0; @@ -221,7 +221,7 @@ void get_map_size(char *name, int *ysize, int *xsize) process_dungeon_file(name, ysize, xsize, cur_hgt, cur_wid, TRUE, TRUE); } -void load_map(char *name, int *y, int *x) +void load_map(const char *name, int *y, int *x) { /* Set the correct monster hook */ set_mon_num_hook(); @@ -307,7 +307,7 @@ char *lua_input_box(cptr title, int max) strcpy(buf, ""); Term_get_size(&wid, &hgt); if (!input_box(title, hgt / 2, wid / 2, buf, (max > 79) ? 79 : max)) - return ""; + return buf; return buf; } diff --git a/src/object1.c b/src/object1.c index 35dfbd5c..2a555581 100644 --- a/src/object1.c +++ b/src/object1.c @@ -2882,7 +2882,7 @@ bool_ object_out_desc(object_type *o_ptr, FILE *fff, bool_ trim_down, bool_ wait { u32b f1, f2, f3, f4, f5, esp; - char *txt; + const char *txt; cptr vp[64]; byte vc[64]; diff --git a/src/q_god.c b/src/q_god.c index 26b44a30..3310c214 100644 --- a/src/q_god.c +++ b/src/q_god.c @@ -149,8 +149,8 @@ static byte get_relic_num() assert(FALSE); } -static void get_home_coordinates(int *home1_y, int *home1_x, char **home1, - int *home2_y, int *home2_x, char **home2) +static void get_home_coordinates(int *home1_y, int *home1_x, const char **home1, + int *home2_y, int *home2_x, const char **home2) { /* Which are the waypoints? */ if (p_ptr->pgod != GOD_MELKOR) @@ -223,8 +223,8 @@ static void print_directions(bool_ feel_it, void (*pfunc)(cptr, void *), void *p { int home1_y, home1_x; int home2_y, home2_x; - char *home1 = NULL; - char *home2 = NULL; + const char *home1 = NULL; + const char *home2 = NULL; char *home1_axis = NULL; char *home2_axis = NULL; cptr home1_distance = NULL; diff --git a/src/spell_type.c b/src/spell_type.c index ab219be5..9948ba8e 100644 --- a/src/spell_type.c +++ b/src/spell_type.c @@ -18,7 +18,7 @@ struct spell_type string_list *description; /* List of strings */ casting_result (*effect_func)(int o_idx); /* Spell effect function */ - char* (*info_func)(); /* Information function */ + const char* (*info_func)(); /* Information function */ int (*lasting_func)(); /* Lasting effect function */ bool_ (*depend_func)(); /* Check dependencies */ @@ -91,7 +91,7 @@ void spell_type_set_inertia(spell_type *spell, s32b difficulty, s32b delay) void spell_type_init_music(spell_type *spell, s16b minimum_pval, - char* (*info_func)(), + const char* (*info_func)(), casting_result (*effect_func)(int o_idx)) { assert(spell != NULL); @@ -111,7 +111,7 @@ void spell_type_init_music(spell_type *spell, void spell_type_init_music_lasting(spell_type *spell, s16b minimum_pval, - char* (*info_func)(), + const char* (*info_func)(), casting_result (*effect_func)(int o_idx), int (*lasting_func)()) { @@ -127,7 +127,7 @@ void spell_type_init_music_lasting(spell_type *spell, void spell_type_init_mage(spell_type *spell, random_type random_type, s32b school_idx, - char* (*info_func)(), + const char* (*info_func)(), casting_result (*effect_func)(int o_idx)) { assert(spell != NULL); @@ -157,7 +157,7 @@ void spell_type_init_mage(spell_type *spell, void spell_type_init_priest(spell_type *spell, s32b school_idx, - char* (*info_func)(), + const char* (*info_func)(), casting_result (*effect_func)(int o_idx)) { assert(spell != NULL); @@ -173,7 +173,7 @@ void spell_type_init_priest(spell_type *spell, } void spell_type_init_device(spell_type *spell, - char* (*info_func)(), + const char* (*info_func)(), casting_result (*effect_func)(int o_idx)) { assert(spell != NULL); @@ -186,7 +186,7 @@ void spell_type_init_device(spell_type *spell, } void spell_type_init_demonology(spell_type *spell, - char* (*info_func)(), + const char* (*info_func)(), casting_result (*effect_func)(int o_idx)) { spell_type_init_mage(spell, @@ -197,7 +197,7 @@ void spell_type_init_demonology(spell_type *spell, } void spell_type_init_geomancy(spell_type *spell, - char* (*info_func)(), + const char* (*info_func)(), casting_result (*effect_func)(int o_idx), bool_ (*depend_func)()) { diff --git a/src/spell_type.h b/src/spell_type.h index 48d52ef0..956f35a5 100644 --- a/src/spell_type.h +++ b/src/spell_type.h @@ -28,30 +28,30 @@ typedef enum { RANDOM, NO_RANDOM } random_type; void spell_type_init(spell_type *spell, cptr name); void spell_type_init_music(spell_type *spell, s16b minimum_pval, - char* (*info_func)(), + const char* (*info_func)(), casting_result (*effect_func)(int o_idx)); void spell_type_init_music_lasting(spell_type *spell, s16b minimum_pval, - char* (*info_func)(), + const char* (*info_func)(), casting_result (*effect_func)(int o_idx), int (*lasting_func)()); void spell_type_init_mage(spell_type *spell, random_type random_type, s32b school_idx, - char* (*info_func)(), + const char* (*info_func)(), casting_result (*effect_func)(int o_idx)); void spell_type_init_priest(spell_type *spell, s32b school_idx, - char* (*info_func)(), + const char* (*info_func)(), casting_result (*effect_func)(int o_idx)); void spell_type_init_device(spell_type *spell, - char* (*info_func)(), + const char* (*info_func)(), casting_result (*effect_func)(int o_idx)); void spell_type_init_demonology(spell_type *spell, - char* (*info_func)(), + const char* (*info_func)(), casting_result (*effect_func)(int o_idx)); void spell_type_init_geomancy(spell_type *spell, - char* (*info_func)(), + const char* (*info_func)(), casting_result (*effect_func)(int o_idx), bool_ (*depend_func)()); diff --git a/src/spells3.c b/src/spells3.c index 269e861a..84993bc2 100644 --- a/src/spells3.c +++ b/src/spells3.c @@ -219,7 +219,7 @@ casting_result air_noxious_cloud(int item) return CAST_OBVIOUS; } -char *air_noxious_cloud_info() +const char *air_noxious_cloud_info() { static char buf[128]; sprintf(buf, @@ -249,7 +249,7 @@ casting_result air_wings_of_winds(int item) return CAST_HIDDEN; } -char *air_wings_of_winds_info() +const char *air_wings_of_winds_info() { static char buf[128]; sprintf(buf, "dur " FMTs32b "+d10", (5 + get_level_s(AIRWINGS, 25))); @@ -266,7 +266,7 @@ casting_result air_invisibility(int item) return CAST_HIDDEN; } -char *air_invisibility_info() +const char *air_invisibility_info() { static char buf[128]; sprintf(buf, "dur " FMTs32b "+d20 power " FMTs32b, @@ -293,7 +293,7 @@ casting_result air_poison_blood(int item) return result; } -char *air_poison_blood_info() +const char *air_poison_blood_info() { static char buf[128]; sprintf(buf, @@ -312,7 +312,7 @@ casting_result air_thunderstorm(int item) return CAST_HIDDEN; } -char *air_thunderstorm_info() +const char *air_thunderstorm_info() { static char buf[128]; sprintf(buf, @@ -329,7 +329,7 @@ casting_result air_sterilize(int item) return CAST_OBVIOUS; } -char *air_sterilize_info() +const char *air_sterilize_info() { static char buf[128]; sprintf(buf, @@ -356,7 +356,7 @@ casting_result convey_blink(int item) } } -char *convey_blink_info() +const char *convey_blink_info() { static char buf[128]; sprintf(buf, @@ -378,7 +378,7 @@ casting_result convey_disarm(int item) return result; } -char *convey_disarm_info() +const char *convey_disarm_info() { return ""; } @@ -390,7 +390,7 @@ casting_result convey_teleport(int item) return CAST_OBVIOUS; } -char *convey_teleport_info() +const char *convey_teleport_info() { static char buf[128]; sprintf(buf, @@ -426,7 +426,7 @@ casting_result convey_teleport_away(int item) } } -char *convey_teleport_away_info() +const char *convey_teleport_away_info() { return ""; } @@ -495,7 +495,7 @@ casting_result convey_recall(int item) } } -char *convey_recall_info() +const char *convey_recall_info() { static char buf[128]; int d = recall_get_d(); @@ -512,7 +512,7 @@ casting_result convey_probability_travel(int item) return cast(set_prob_travel(randint(20) + get_level_s(PROBABILITY_TRAVEL, 60))); } -char *convey_probability_travel_info() +const char *convey_probability_travel_info() { static char buf[128]; sprintf(buf, @@ -544,7 +544,7 @@ casting_result demonology_demon_blade(int item) PROJECT_STOP | PROJECT_KILL)); } -char *demonology_demon_blade_info() +const char *demonology_demon_blade_info() { static char buf[128]; sprintf(buf, @@ -595,7 +595,7 @@ casting_result demonology_demon_madness(int item) return result; } -char *demonology_demon_madness_info() +const char *demonology_demon_madness_info() { static char buf[128]; sprintf(buf, @@ -621,7 +621,7 @@ casting_result demonology_demon_field(int item) 30 + get_level_s(DEMON_FIELD, 100))); } -char *demonology_demon_field_info() +const char *demonology_demon_field_info() { static char buf[128]; sprintf(buf, @@ -640,7 +640,7 @@ casting_result demonology_doom_shield(int item) 10 + get_level_s(DOOM_SHIELD, 15))); } -char *demonology_doom_shield_info() +const char *demonology_doom_shield_info() { static char buf[128]; sprintf(buf, @@ -708,7 +708,7 @@ casting_result demonology_unholy_word(int item) } } -char *demonology_unholy_word_info() +const char *demonology_unholy_word_info() { static char buf[128]; sprintf(buf, @@ -722,7 +722,7 @@ casting_result demonology_demon_cloak(int item) return cast(set_tim_reflect(randint(5) + 5 + get_level(DEMON_CLOAK, 15, 0))); } -char *demonology_demon_cloak_info() +const char *demonology_demon_cloak_info() { static char buf[128]; sprintf(buf, @@ -762,7 +762,7 @@ casting_result demonology_summon_demon(int item) } } -char *demonology_summon_demon_info() +const char *demonology_summon_demon_info() { static char buf[128]; sprintf(buf, @@ -813,7 +813,7 @@ casting_result demonology_discharge_minion(int item) } } -char *demonology_discharge_minion_info() +const char *demonology_discharge_minion_info() { static char buf[128]; sprintf(buf, @@ -834,7 +834,7 @@ casting_result demonology_control_demon(int item) return cast(fire_ball(GF_CONTROL_DEMON, dir, 50 + get_level_s(CONTROL_DEMON, 250), 0)); } -char *demonology_control_demon_info() +const char *demonology_control_demon_info() { static char buf[128]; sprintf(buf, @@ -856,7 +856,7 @@ casting_result divination_greater_identify(int item) return CAST_OBVIOUS; } -char *divination_greater_identify_info() +const char *divination_greater_identify_info() { return ""; } @@ -887,7 +887,7 @@ casting_result divination_identify(int item) } } -char *divination_identify_info() +const char *divination_identify_info() { static char buf[128]; @@ -916,7 +916,7 @@ casting_result divination_vision(int item) } -char *divination_vision_info() +const char *divination_vision_info() { return ""; } @@ -934,7 +934,7 @@ casting_result divination_sense_hidden(int item) return result; } -char *divination_sense_hidden_info() +const char *divination_sense_hidden_info() { static char buf[128]; @@ -963,7 +963,7 @@ casting_result divination_reveal_ways(int item) return result; } -char *divination_reveal_ways_info() +const char *divination_reveal_ways_info() { static char buf[128]; sprintf(buf, @@ -984,7 +984,7 @@ casting_result divination_sense_monsters(int item) return result; } -char *divination_sense_monsters_info() +const char *divination_sense_monsters_info() { static char buf[128]; @@ -1022,7 +1022,7 @@ casting_result earth_stone_skin(int item) 3 + get_level_s(STONESKIN, 5))); } -char *earth_stone_skin_info() +const char *earth_stone_skin_info() { static char buf[128]; @@ -1057,7 +1057,7 @@ casting_result earth_dig(int item) return cast(wall_to_mud(dir)); } -char *earth_dig_info() +const char *earth_dig_info() { return ""; } @@ -1083,7 +1083,7 @@ casting_result earth_stone_prison(int item) return CAST_OBVIOUS; } -char *earth_stone_prison_info() +const char *earth_stone_prison_info() { return ""; } @@ -1108,7 +1108,7 @@ casting_result earth_strike(int item) } } -char *earth_strike_info() +const char *earth_strike_info() { static char buf[128]; int dmg = 50 + get_level_s(STRIKE, 50); @@ -1145,7 +1145,7 @@ casting_result earth_shake(int item) return CAST_OBVIOUS; } -char *earth_shake_info() +const char *earth_shake_info() { static char buf[128]; sprintf(buf, "rad " FMTs32b, (4 + get_level_s(SHAKE, 10))); @@ -1177,7 +1177,7 @@ casting_result eru_see_the_music(int item) return result; } -char *eru_see_the_music_info() +const char *eru_see_the_music_info() { static char buf[128]; sprintf(buf, @@ -1207,7 +1207,7 @@ casting_result eru_listen_to_the_music(int item) return result; } -char *eru_listen_to_the_music_info() +const char *eru_listen_to_the_music_info() { return ""; } @@ -1225,7 +1225,7 @@ casting_result eru_know_the_music(int item) } } -char *eru_know_the_music_info() +const char *eru_know_the_music_info() { return ""; } @@ -1235,7 +1235,7 @@ casting_result eru_lay_of_protection(int item) return cast(fire_ball(GF_MAKE_GLYPH, 0, 1, 1 + get_level(ERU_PROT, 2, 0))); } -char *eru_lay_of_protection_info() +const char *eru_lay_of_protection_info() { static char buf[128]; sprintf(buf, @@ -1271,7 +1271,7 @@ casting_result fire_globe_of_light(int item) return result; } -char *fire_globe_of_light_info() +const char *fire_globe_of_light_info() { static char buf[128]; @@ -1309,7 +1309,7 @@ casting_result fire_fireflash(int item) 2 + get_level_s(FIREFLASH, 5))); } -char *fire_fireflash_info() +const char *fire_fireflash_info() { static char buf[128]; sprintf(buf, @@ -1334,7 +1334,7 @@ casting_result fire_fiery_shield(int item) 5 + get_level_s(FIERYAURA, 7))); } -char *fire_fiery_shield_info() +const char *fire_fiery_shield_info() { static char buf[128]; sprintf(buf, @@ -1365,7 +1365,7 @@ casting_result fire_firewall(int item) return CAST_OBVIOUS; } -char *fire_firewall_info() +const char *fire_firewall_info() { static char buf[128]; sprintf(buf, @@ -1422,7 +1422,7 @@ casting_result fire_golem(int ignored) return CAST_OBVIOUS; } -char *fire_golem_info() +const char *fire_golem_info() { static char buf[128]; sprintf(buf, @@ -1451,7 +1451,7 @@ casting_result geomancy_call_the_elements(int item) return CAST_OBVIOUS; } -char *geomancy_call_the_elements_info() +const char *geomancy_call_the_elements_info() { static char buf[128]; sprintf(buf, @@ -1466,7 +1466,7 @@ casting_result geomancy_channel_elements(int item) return CAST_OBVIOUS; } -char *geomancy_channel_elements_info() +const char *geomancy_channel_elements_info() { return ""; } @@ -1576,7 +1576,7 @@ casting_result geomancy_elemental_wave(int item) } } -char *geomancy_elemental_wave_info() +const char *geomancy_elemental_wave_info() { return ""; } @@ -1627,7 +1627,7 @@ casting_result geomancy_vaporize(int item) } } -char *geomancy_vaporize_info() +const char *geomancy_vaporize_info() { static char buf[128]; sprintf(buf, @@ -1657,7 +1657,7 @@ casting_result geomancy_geolysis(int item) return CAST_OBVIOUS; } -char *geomancy_geolysis_info() +const char *geomancy_geolysis_info() { static char buf[128]; sprintf(buf, @@ -1687,7 +1687,7 @@ casting_result geomancy_dripping_tread(int item) return CAST_OBVIOUS; } -char *geomancy_dripping_tread_info() +const char *geomancy_dripping_tread_info() { static char buf[128]; sprintf(buf, @@ -1717,7 +1717,7 @@ casting_result geomancy_grow_barrier(int item) return CAST_OBVIOUS; } -char *geomancy_grow_barrier_info() +const char *geomancy_grow_barrier_info() { return ""; } @@ -1852,7 +1852,7 @@ casting_result geomancy_elemental_minion(int item) } } -char *geomancy_elemental_minion_info() +const char *geomancy_elemental_minion_info() { static char buf[128]; sprintf(buf, @@ -1882,7 +1882,7 @@ casting_result mana_manathrust(int item) return cast(fire_bolt(GF_MANA, dir, damroll(num, sides))); } -char *mana_manathrust_info() +const char *mana_manathrust_info() { s16b num = 0; s16b sides = 0; @@ -1917,7 +1917,7 @@ casting_result mana_remove_curses(int item) return result; } -char *mana_remove_curses_info() +const char *mana_remove_curses_info() { return ""; } @@ -1949,7 +1949,7 @@ casting_result mana_elemental_shield(int item) return res; } -char *mana_elemental_shield_info() +const char *mana_elemental_shield_info() { static char buf[128]; sprintf(buf, @@ -1975,7 +1975,7 @@ casting_result mana_disruption_shield(int item) return NO_CAST; } -char *mana_disruption_shield_info() +const char *mana_disruption_shield_info() { static char buf[128]; sprintf(buf, @@ -2010,7 +2010,7 @@ casting_result manwe_wind_shield(int item) return res; } -char *manwe_wind_shield_info() +const char *manwe_wind_shield_info() { static char buf[128]; @@ -2047,7 +2047,7 @@ casting_result manwe_avatar(int item) p_ptr->lev)); } -char *manwe_avatar_info() +const char *manwe_avatar_info() { static char buf[128]; sprintf(buf, @@ -2081,7 +2081,7 @@ casting_result manwe_blessing(int item) return res; } -char *manwe_blessing_info() +const char *manwe_blessing_info() { static char buf[128]; sprintf(buf, @@ -2110,7 +2110,7 @@ casting_result manwe_call(int item) return NO_CAST; } -char *manwe_call_info() +const char *manwe_call_info() { static char buf[128]; sprintf(buf, @@ -2230,7 +2230,7 @@ casting_result melkor_curse(int item) } } -char *melkor_curse_info() +const char *melkor_curse_info() { return ""; } @@ -2243,7 +2243,7 @@ casting_result melkor_corpse_explosion(int item) 2 + get_level_s(MELKOR_CORPSE_EXPLOSION, 5))); } -char *melkor_corpse_explosion_info() +const char *melkor_corpse_explosion_info() { static char buf[128]; sprintf(buf, @@ -2293,7 +2293,7 @@ casting_result melkor_mind_steal(int item) } } -char *melkor_mind_steal_info() +const char *melkor_mind_steal_info() { static char buf[128]; sprintf(buf, @@ -2307,7 +2307,7 @@ casting_result meta_recharge(int item) return cast(recharge(60 + get_level_s(RECHARGE, 140))); } -char *meta_recharge_info() +const char *meta_recharge_info() { static char buf[128]; sprintf(buf, @@ -2419,7 +2419,7 @@ casting_result meta_spellbinder(int item) } } -char *meta_spellbinder_info() +const char *meta_spellbinder_info() { static char buf[128]; sprintf(buf, @@ -2465,7 +2465,7 @@ casting_result meta_disperse_magic(int item) return res; } -char *meta_disperse_magic_info() +const char *meta_disperse_magic_info() { return ""; } @@ -2484,7 +2484,7 @@ casting_result meta_tracker(int item) return CAST_OBVIOUS; } -char *meta_tracker_info() +const char *meta_tracker_info() { return ""; } @@ -2547,7 +2547,7 @@ casting_result meta_inertia_control(int item) return CAST_OBVIOUS; } -char *meta_inertia_control_info() +const char *meta_inertia_control_info() { static char buf[128]; sprintf(buf, @@ -2619,7 +2619,7 @@ casting_result mind_charm(int item) } } -char *mind_charm_info() +const char *mind_charm_info() { static char buf[128]; sprintf(buf, @@ -2661,7 +2661,7 @@ casting_result mind_confuse(int item) } } -char *mind_confuse_info() +const char *mind_confuse_info() { static char buf[128]; sprintf(buf, @@ -2694,7 +2694,7 @@ casting_result mind_armor_of_fear(int item) mind_armor_of_fear_power_dice())); } -char *mind_armor_of_fear_info() +const char *mind_armor_of_fear_info() { static char buf[128]; sprintf(buf, @@ -2729,7 +2729,7 @@ casting_result mind_stun(int item) } } -char *mind_stun_info() +const char *mind_stun_info() { static char buf[128]; sprintf(buf, @@ -2778,7 +2778,7 @@ casting_result tempo_magelock(int item) } } -char *tempo_magelock_info() +const char *tempo_magelock_info() { return ""; } @@ -2809,7 +2809,7 @@ casting_result tempo_slow_monster(int item) } } -char *tempo_slow_monster_info() +const char *tempo_slow_monster_info() { static char buf[128]; s32b pwr = tempo_slow_monster_power(); @@ -2845,7 +2845,7 @@ casting_result tempo_essence_of_speed(int item) return NO_CAST; } -char *tempo_essence_of_speed_info() +const char *tempo_essence_of_speed_info() { static char buf[128]; sprintf(buf, @@ -2876,7 +2876,7 @@ casting_result tempo_banishment(int item) return result; } -char *tempo_banishment_info() +const char *tempo_banishment_info() { static char buf[128]; sprintf(buf, @@ -2899,7 +2899,7 @@ casting_result tulkas_divine_aim(int item) return result; } -char *tulkas_divine_aim_info() +const char *tulkas_divine_aim_info() { static char buf[128]; sprintf(buf, @@ -2920,7 +2920,7 @@ casting_result tulkas_wave_of_power(int item) return cast(fire_bolt(GF_ATTACK, dir, get_level_s(TULKAS_WAVE, p_ptr->num_blow))); } -char *tulkas_wave_of_power_info() +const char *tulkas_wave_of_power_info() { static char buf[128]; sprintf(buf, @@ -2934,7 +2934,7 @@ casting_result tulkas_whirlwind(int item) return cast(fire_ball(GF_ATTACK, 0, 1, 1)); } -char *tulkas_whirlwind_info() +const char *tulkas_whirlwind_info() { return ""; } @@ -3068,7 +3068,7 @@ casting_result udun_drain(int ignored) return CAST_OBVIOUS; } -char *udun_drain_info() +const char *udun_drain_info() { return ""; } @@ -3094,7 +3094,7 @@ casting_result udun_genocide(int item) return CAST_OBVIOUS; } -char *udun_genocide_info() +const char *udun_genocide_info() { return ""; } @@ -3109,7 +3109,7 @@ casting_result udun_wraithform(int item) return cast(set_shadow(randint(30) + udun_wraithform_base_duration())); } -char *udun_wraithform_info() +const char *udun_wraithform_info() { static char buf[128]; sprintf(buf, @@ -3130,7 +3130,7 @@ casting_result udun_flame_of_udun(int item) get_level_s(FLAMEOFUDUN, 50))); } -char *udun_flame_of_udun_info() +const char *udun_flame_of_udun_info() { static char buf[128]; sprintf(buf, @@ -3160,7 +3160,7 @@ casting_result water_tidal_wave(int item) return CAST_OBVIOUS; } -char *water_tidal_wave_info() +const char *water_tidal_wave_info() { static char buf[128]; sprintf(buf, @@ -3204,7 +3204,7 @@ casting_result water_ice_storm(int item) return CAST_OBVIOUS; } -char *water_ice_storm_info() +const char *water_ice_storm_info() { static char buf[128]; sprintf(buf, @@ -3237,7 +3237,7 @@ casting_result water_ent_potion(int item) return CAST_OBVIOUS; } -char *water_ent_potion_info() +const char *water_ent_potion_info() { if (get_level_s(ENTPOTION, 50) >= 12) { @@ -3278,7 +3278,7 @@ casting_result water_vapor(int item) return CAST_OBVIOUS; } -char *water_vapor_info() +const char *water_vapor_info() { static char buf[128]; sprintf(buf, @@ -3314,7 +3314,7 @@ casting_result water_geyser(int item) damroll(dice, sides))); } -char *water_geyser_info() +const char *water_geyser_info() { static char buf[128]; int dice, sides; @@ -3353,7 +3353,7 @@ casting_result yavanna_charm_animal(int item) charm_animal_radius())); } -char *yavanna_charm_animal_info() +const char *yavanna_charm_animal_info() { static char buf[128]; sprintf(buf, @@ -3374,7 +3374,7 @@ casting_result yavanna_grow_grass(int item) return CAST_OBVIOUS; } -char *yavanna_grow_grass_info() +const char *yavanna_grow_grass_info() { static char buf[128]; sprintf(buf, @@ -3405,7 +3405,7 @@ casting_result yavanna_tree_roots(int item) tree_roots_damage())); } -char *yavanna_tree_roots_info() +const char *yavanna_tree_roots_info() { static char buf[128]; sprintf(buf, @@ -3442,7 +3442,7 @@ casting_result yavanna_water_bite(int item) PROJECT_STOP | PROJECT_KILL)); } -char *yavanna_water_bite_info() +const char *yavanna_water_bite_info() { static char buf[128]; sprintf(buf, @@ -3501,7 +3501,7 @@ casting_result yavanna_uproot(int item) } } -char *yavanna_uproot_info() +const char *yavanna_uproot_info() { static char buf[128]; sprintf(buf, @@ -3521,7 +3521,7 @@ casting_result nature_grow_trees(int item) return CAST_OBVIOUS; } -char *nature_grow_trees_info() +const char *nature_grow_trees_info() { static char buf[128]; sprintf(buf, @@ -3545,7 +3545,7 @@ casting_result nature_healing(int item) return cast(hp_player(nature_healing_hp())); } -char *nature_healing_info() +const char *nature_healing_info() { static char buf[128]; sprintf(buf, @@ -3582,7 +3582,7 @@ casting_result nature_recovery(int item) return result; } -char *nature_recovery_info() +const char *nature_recovery_info() { return ""; } @@ -3607,7 +3607,7 @@ casting_result nature_regeneration(int item) return NO_CAST; } -char *nature_regeneration_info() +const char *nature_regeneration_info() { static char buf[128]; sprintf(buf, @@ -3632,7 +3632,7 @@ casting_result nature_summon_animal(int item) TRUE)); } -char *nature_summon_animal_info() +const char *nature_summon_animal_info() { static char buf[128]; sprintf(buf, @@ -3653,7 +3653,7 @@ casting_result nature_grow_athelas(int item) return CAST_HIDDEN; } -char *nature_grow_athelas_info() +const char *nature_grow_athelas_info() { return ""; } @@ -3675,7 +3675,7 @@ casting_result device_heal_monster(int item) return cast(fire_ball(GF_OLD_HEAL, dir, device_heal_monster_hp(), 0)); } -char *device_heal_monster_info() +const char *device_heal_monster_info() { static char buf[128]; sprintf(buf, @@ -3696,7 +3696,7 @@ casting_result device_haste_monster(int item) return cast(fire_ball(GF_OLD_SPEED, dir, 1, 0)); } -char *device_haste_monster_info() +const char *device_haste_monster_info() { return "speed +10"; } @@ -3707,7 +3707,7 @@ casting_result device_wish(int item) return CAST_OBVIOUS; } -char *device_wish_info() +const char *device_wish_info() { return ""; } @@ -3725,7 +3725,7 @@ casting_result device_summon_monster(int item) return result; } -char *device_summon_monster_info() +const char *device_summon_monster_info() { return ""; } @@ -3741,7 +3741,7 @@ casting_result device_mana(int item) return CAST_OBVIOUS; } -char *device_mana_info() +const char *device_mana_info() { static char buf[128]; sprintf(buf, @@ -3755,7 +3755,7 @@ casting_result device_nothing(int item) return CAST_HIDDEN; } -char *device_nothing_info() +const char *device_nothing_info() { return ""; } @@ -3769,7 +3769,7 @@ casting_result device_lebohaum(int item) return CAST_OBVIOUS; } -char *device_lebohaum_info() +const char *device_lebohaum_info() { return ""; } @@ -3786,7 +3786,7 @@ casting_result device_maggot(int item) return cast(fire_ball(GF_TURN_ALL, dir, 40, 2)); } -char *device_maggot_info() +const char *device_maggot_info() { return "power 40 rad 2"; } @@ -3801,7 +3801,7 @@ casting_result device_holy_fire(int item) return cast(project_hack(GF_HOLY_FIRE, holy_fire_damage())); } -char *device_holy_fire_info() +const char *device_holy_fire_info() { static char buf[128]; sprintf(buf, @@ -3892,7 +3892,7 @@ casting_result device_eternal_flame(int flame_item) return CAST_OBVIOUS; } -char *device_eternal_flame_info() +const char *device_eternal_flame_info() { return ""; } @@ -3914,7 +3914,7 @@ casting_result device_durandil(int item) return CAST_OBVIOUS; } -char *device_durandil_info() +const char *device_durandil_info() { return ""; } @@ -3957,7 +3957,7 @@ casting_result device_thunderlords(int item) } } -char *device_thunderlords_info() +const char *device_thunderlords_info() { return ""; } @@ -3996,7 +3996,7 @@ casting_result device_radagast(int item) return CAST_OBVIOUS; } -char *device_radagast_info() +const char *device_radagast_info() { return ""; } @@ -4008,7 +4008,7 @@ casting_result device_valaroma(int item) return CAST_HIDDEN; } -char *device_valaroma_info() +const char *device_valaroma_info() { return ""; } @@ -4024,7 +4024,7 @@ casting_result music_stop_singing_spell(int item) return CAST_OBVIOUS; } -char *music_stop_singing_info() +const char *music_stop_singing_info() { return ""; } @@ -4046,7 +4046,7 @@ casting_result music_holding_pattern_spell(int item) return CAST_OBVIOUS; } -char *music_holding_pattern_info() +const char *music_holding_pattern_info() { static char buf[128]; sprintf(buf, @@ -4072,7 +4072,7 @@ casting_result music_illusion_pattern_spell(int item) return CAST_OBVIOUS; } -char *music_illusion_pattern_info() +const char *music_illusion_pattern_info() { static char buf[128]; sprintf(buf, @@ -4098,7 +4098,7 @@ casting_result music_stun_pattern_spell(int item) return CAST_OBVIOUS; } -char *music_stun_pattern_info() +const char *music_stun_pattern_info() { static char buf[128]; sprintf(buf, @@ -4119,7 +4119,7 @@ casting_result music_song_of_the_sun_spell(int item) return CAST_OBVIOUS; } -char *music_song_of_the_sun_info() +const char *music_song_of_the_sun_info() { return ""; } @@ -4141,7 +4141,7 @@ casting_result music_flow_of_life_spell(int item) return CAST_OBVIOUS; } -char *music_flow_of_life_info() +const char *music_flow_of_life_info() { static char buf[128]; sprintf(buf, @@ -4174,7 +4174,7 @@ casting_result music_heroic_ballad_spell(int item) return CAST_OBVIOUS; } -char *music_heroic_ballad_info() +const char *music_heroic_ballad_info() { return ""; } @@ -4195,7 +4195,7 @@ casting_result music_hobbit_melodies_spell(int item) return CAST_OBVIOUS; } -char *music_hobbit_melodies_info() +const char *music_hobbit_melodies_info() { static char buf[128]; if (get_level_s(MUSIC_TIME, 50) >= 15) @@ -4228,7 +4228,7 @@ casting_result music_clairaudience_spell(int item) return CAST_OBVIOUS; } -char *music_clairaudience_info() +const char *music_clairaudience_info() { static char buf[128]; @@ -4253,7 +4253,7 @@ casting_result music_blow_spell(int item) return CAST_OBVIOUS; } -char *music_blow_info() +const char *music_blow_info() { static char buf[128]; sprintf(buf, @@ -4273,7 +4273,7 @@ casting_result music_gush_of_wind_spell(int item) return CAST_OBVIOUS; } -char *music_gush_of_wind_info() +const char *music_gush_of_wind_info() { static char buf[128]; sprintf(buf, @@ -4289,7 +4289,7 @@ casting_result music_horns_of_ylmir_spell(int item) return CAST_OBVIOUS; } -char *music_horns_of_ylmir_info() +const char *music_horns_of_ylmir_info() { static char buf[128]; sprintf(buf, @@ -4304,7 +4304,7 @@ casting_result music_ambarkanta_spell(int item) return CAST_OBVIOUS; } -char *music_ambarkanta_info() +const char *music_ambarkanta_info() { return ""; } @@ -4332,7 +4332,7 @@ casting_result aule_firebrand_spell(int item) PROJECT_STOP | PROJECT_KILL)); } -char *aule_firebrand_info() +const char *aule_firebrand_info() { s32b level = get_level_s(AULE_FIREBRAND, 50); static char buf[128]; @@ -4404,7 +4404,7 @@ casting_result aule_enchant_weapon_spell(int ignored) return CAST_OBVIOUS; } -char *aule_enchant_weapon_info() +const char *aule_enchant_weapon_info() { static char buf[128]; sprintf(buf, @@ -4478,7 +4478,7 @@ casting_result aule_enchant_armour_spell(int ignored) return CAST_OBVIOUS; } -char *aule_enchant_armour_info() +const char *aule_enchant_armour_info() { static char buf[128]; sprintf(buf, @@ -4507,7 +4507,7 @@ casting_result aule_child_spell(int item) } } -char *aule_child_info() +const char *aule_child_info() { static char buf[128]; sprintf(buf, @@ -4533,7 +4533,7 @@ casting_result mandos_tears_of_luthien_spell(int item) return result; } -char *mandos_tears_of_luthien_info() +const char *mandos_tears_of_luthien_info() { static char buf[128]; sprintf(buf, @@ -4565,7 +4565,7 @@ casting_result mandos_spirit_of_the_feanturi_spell(int item) return result; } -char *mandos_spirit_of_the_feanturi_info() +const char *mandos_spirit_of_the_feanturi_info() { static char buf[128]; s32b level = get_level_s(MANDOS_SPIRIT_FEANTURI, 50) ; @@ -4590,7 +4590,7 @@ casting_result mandos_tale_of_doom_spell(int item) return cast(set_tim_precognition(tale_of_doom_duration())); } -char *mandos_tale_of_doom_info() +const char *mandos_tale_of_doom_info() { static char buf[128]; sprintf(buf, @@ -4628,7 +4628,7 @@ casting_result mandos_call_to_the_halls_spell(int item) #undef N_SUMMONS } -char *mandos_call_to_the_halls_info() +const char *mandos_call_to_the_halls_info() { static char buf[128]; sprintf(buf, @@ -4659,7 +4659,7 @@ casting_result ulmo_song_of_belegaer_spell(int item) damroll(dice, sides))); } -char *ulmo_song_of_belegaer_info() +const char *ulmo_song_of_belegaer_info() { static char buf[128]; int dice, sides; @@ -4705,7 +4705,7 @@ casting_result ulmo_draught_of_ulmonan_spell(int item) return result; } -char *ulmo_draught_of_ulmonan_info() +const char *ulmo_draught_of_ulmonan_info() { static char buf[128]; sprintf(buf, @@ -4745,7 +4745,7 @@ casting_result ulmo_call_of_the_ulumuri_spell(int item) #undef N_SUMMONS } -char *ulmo_call_of_the_ulumuri_info() +const char *ulmo_call_of_the_ulumuri_info() { static char buf[128]; sprintf(buf, @@ -4785,7 +4785,7 @@ casting_result ulmo_wrath_of_ulmo_spell(int item) return CAST_OBVIOUS; } -char *ulmo_wrath_of_ulmo_info() +const char *ulmo_wrath_of_ulmo_info() { static char buf[128]; sprintf(buf, @@ -4831,7 +4831,7 @@ casting_result varda_light_of_valinor_spell(int item) return result; } -char *varda_light_of_valinor_info() +const char *varda_light_of_valinor_info() { static char buf[128]; if (get_level_s(VARDA_LIGHT_VALINOR, 50) >= 15) @@ -4862,7 +4862,7 @@ casting_result varda_call_of_almaren_spell(int item) return CAST_OBVIOUS; } -char *varda_call_of_almaren_info() +const char *varda_call_of_almaren_info() { return ""; } @@ -4879,7 +4879,7 @@ casting_result varda_evenstar_spell(int item) return CAST_OBVIOUS; } -char *varda_evenstar_info() +const char *varda_evenstar_info() { return ""; } @@ -4914,7 +4914,7 @@ casting_result varda_star_kindler_spell(int item) return CAST_OBVIOUS; } -char *varda_star_kindler_info() +const char *varda_star_kindler_info() { static char buf[128]; sprintf(buf, diff --git a/src/status.c b/src/status.c index c6306693..650a4ace 100644 --- a/src/status.c +++ b/src/status.c @@ -17,12 +17,12 @@ #include "angband.h" -static void row_trival(char*, s16b, u32b, s16b, u32b, int, u32b[INVEN_TOTAL - INVEN_WIELD + 2][7]); -static void row_bival(char*, s16b, u32b, int, u32b[INVEN_TOTAL - INVEN_WIELD + 2][7]); -static void row_npval(char*, s16b, u32b, int, u32b[INVEN_TOTAL - INVEN_WIELD + 2][7]); -static void statline(char*, int, u32b, int, u32b[INVEN_TOTAL - INVEN_WIELD + 2][7]); +static void row_trival(const char*, s16b, u32b, s16b, u32b, int, u32b[INVEN_TOTAL - INVEN_WIELD + 2][7]); +static void row_bival(const char*, s16b, u32b, int, u32b[INVEN_TOTAL - INVEN_WIELD + 2][7]); +static void row_npval(const char*, s16b, u32b, int, u32b[INVEN_TOTAL - INVEN_WIELD + 2][7]); +static void statline(const char*, int, u32b, int, u32b[INVEN_TOTAL - INVEN_WIELD + 2][7]); static void row_hd_bon(int, int, u32b[INVEN_TOTAL - INVEN_WIELD + 2][7]); -static void row_count(char*, s16b, u32b, int, s16b, u32b, int, s16b, u32b, int, s16b, u32b, int, int, u32b[INVEN_TOTAL - INVEN_WIELD + 2][7]); +static void row_count(const char*, s16b, u32b, int, s16b, u32b, int, s16b, u32b, int, s16b, u32b, int, int, u32b[INVEN_TOTAL - INVEN_WIELD + 2][7]); static int row_x_start = 0; static void status_count(s32b val1, int v1, s32b val2, int v2, s32b val3, int v3, s32b val4, int v4, byte ypos, byte xpos); @@ -525,7 +525,7 @@ static void status_count(s32b val1, int v1, s32b val2, int v2, s32b val3, int v3 status_numeric(v, ypos, xpos); } -static void row_count(char* statname, s16b row1, u32b flag1, int v1, s16b row2, u32b flag2, int v2, s16b row3, u32b flag3, int v3, s16b row4, u32b flag4, int v4, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7]) +static void row_count(const char* statname, s16b row1, u32b flag1, int v1, s16b row2, u32b flag2, int v2, s16b row3, u32b flag3, int v3, s16b row4, u32b flag4, int v4, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7]) { int i; int x = row_x_start; @@ -542,7 +542,7 @@ static void row_count(char* statname, s16b row1, u32b flag1, int v1, s16b row2, } } -static void row_trival(char* statname, s16b row, u32b flag, s16b row2, u32b flag2, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7]) +static void row_trival(const char* statname, s16b row, u32b flag, s16b row2, u32b flag2, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7]) { int i; int x = row_x_start; @@ -560,7 +560,7 @@ static void row_trival(char* statname, s16b row, u32b flag, s16b row2, u32b flag } } -static void row_bival(char* statname, s16b row, u32b flag, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7]) +static void row_bival(const char* statname, s16b row, u32b flag, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7]) { int i; int x = row_x_start; @@ -575,7 +575,7 @@ static void row_bival(char* statname, s16b row, u32b flag, int yo, u32b flag_arr } } -static void row_npval(char* statname, s16b row, u32b flag, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7]) +static void row_npval(const char* statname, s16b row, u32b flag, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7]) /* Displays nicely a pval-based status row */ { int i; @@ -604,7 +604,7 @@ static void row_npval(char* statname, s16b row, u32b flag, int yo, u32b flag_arr } } -static void statline(char* statname, int statidx, u32b flag, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7]) +static void statline(const char* statname, int statidx, u32b flag, int yo, u32b flag_arr[INVEN_TOTAL - INVEN_WIELD + 2][7]) /* Displays a status row for a primary stat */ { int i; diff --git a/src/wizard1.c b/src/wizard1.c index ab7635d7..11f96f61 100644 --- a/src/wizard1.c +++ b/src/wizard1.c @@ -2325,7 +2325,7 @@ static void spoil_mon_info(cptr fname) } -char *long_intro = +const char *long_intro = "Essences are the tools of the trade for Alchemists, " "and unfortunately are useless for any other class. " "Alchemists use essences to create magical items for them to use.\n\n" diff --git a/src/wizard2.c b/src/wizard2.c index a843b7c9..e336f068 100644 --- a/src/wizard2.c +++ b/src/wizard2.c @@ -887,7 +887,7 @@ static void wiz_statistics(object_type *o_ptr) long i, matches, better, worse, other; char ch; - char *quality; + const char *quality; bool_ good, great; -- cgit v1.2.3 From dc34bf59b8be15e654a902f54387805be69f6fda Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Mar 2013 06:53:00 +0100 Subject: Remove dead code --- src/dungeon.c | 5 ----- src/types.h | 6 ------ src/util.c | 16 ---------------- 3 files changed, 27 deletions(-) diff --git a/src/dungeon.c b/src/dungeon.c index 5eb38c51..df3b41aa 100644 --- a/src/dungeon.c +++ b/src/dungeon.c @@ -5271,11 +5271,6 @@ static void dungeon(void) /* Process the appropriate hooks */ process_hooks(HOOK_END_TURN, "(d)", is_quest(dun_level)); - { - hook_end_turn_in in = { is_quest(dun_level) }; - process_hooks_new(HOOK_END_TURN, &in, NULL); - } - /* Make it pulsate and live !!!! */ if ((dungeon_flags1 & DF1_EVOLVE) && dun_level) { diff --git a/src/types.h b/src/types.h index 7cd9a8a1..8a035da6 100644 --- a/src/types.h +++ b/src/types.h @@ -2220,11 +2220,6 @@ struct hook_get_in { int o_idx; }; -typedef struct hook_end_turn_in hook_end_turn_in; -struct hook_end_turn_in { - bool_ is_quest; -}; - typedef struct hook_player_level_in hook_player_level_in; struct hook_player_level_in { int gained_levels; @@ -2382,7 +2377,6 @@ struct hooks_chain bool_ (*hook_f)(void *, void *, void *); void *hook_data; char name[40]; - char script[40]; byte type; hooks_chain *next; }; diff --git a/src/util.c b/src/util.c index e8a0bad7..52184f0b 100644 --- a/src/util.c +++ b/src/util.c @@ -1507,22 +1507,6 @@ errr macro_add(cptr pat, cptr act) -/* -* Initialize the "macro" package -*/ -errr macro_init(void) -{ - /* Macro patterns */ - C_MAKE(macro__pat, MACRO_MAX, cptr); - - /* Macro actions */ - C_MAKE(macro__act, MACRO_MAX, cptr); - - /* Success */ - return (0); -} - - /* * Local "need flush" variable */ -- cgit v1.2.3 From 98dea0131750e12a545b3d4efbf6bf945f2f8f6f Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Mar 2013 06:40:36 +0100 Subject: Add __cplusplus conditionals --- src/dice.h | 8 ++++++++ src/dice_fwd.h | 8 ++++++++ src/range.h | 8 ++++++++ src/range_fwd.h | 8 ++++++++ src/string_list.h | 8 ++++++++ 5 files changed, 40 insertions(+) diff --git a/src/dice.h b/src/dice.h index 3253f348..9b07357e 100644 --- a/src/dice.h +++ b/src/dice.h @@ -2,6 +2,10 @@ #include "dice_fwd.h" +#ifdef __cplusplus +extern "C" { +#endif + /** * Dice */ @@ -11,3 +15,7 @@ struct dice_type long num; /* Number of dice */ long sides; /* Sides per dice */ }; + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/dice_fwd.h b/src/dice_fwd.h index ffc8fbfa..be1ed85f 100644 --- a/src/dice_fwd.h +++ b/src/dice_fwd.h @@ -2,6 +2,10 @@ #include "angband.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct dice_type dice_type; struct dice_type; @@ -10,3 +14,7 @@ bool_ dice_parse(dice_type *dice, cptr s); void dice_parse_checked(dice_type *dice, cptr s); long dice_roll(dice_type *dice); void dice_print(dice_type *dice, char *buf); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/range.h b/src/range.h index 0d840c18..0cd049dc 100644 --- a/src/range.h +++ b/src/range.h @@ -3,6 +3,10 @@ #include "range_fwd.h" #include "angband.h" +#ifdef __cplusplus +extern "C" { +#endif + /* * Range */ @@ -13,3 +17,7 @@ struct range_type }; void range_init(range_type *range, s32b min, s32b max); + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/range_fwd.h b/src/range_fwd.h index b5eef3fa..1e76e354 100644 --- a/src/range_fwd.h +++ b/src/range_fwd.h @@ -1,4 +1,12 @@ #pragma once +#ifdef __cplusplus +extern "C" { +#endif + typedef struct range_type range_type; struct range_type; + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/string_list.h b/src/string_list.h index bd88602f..1d9c2a36 100644 --- a/src/string_list.h +++ b/src/string_list.h @@ -3,6 +3,10 @@ #include "sglib.h" #include "angband.h" +#ifdef __cplusplus +extern "C" { +#endif + /* * String list. */ @@ -20,3 +24,7 @@ SGLIB_DEFINE_LIST_PROTOTYPES(string_list, compare_string, next); void string_list_init(string_list *sl, cptr s); /* Initialize element; copies string */ void string_list_destroy(string_list *sl); /* Destroy element */ void string_list_append(string_list **slist, cptr s); /* Append string */ + +#ifdef __cplusplus +} // extern "C" +#endif -- cgit v1.2.3 From c8a1e6c1bb7bf1da89ccbe985173ec13b123b64a Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Mar 2013 08:48:28 +0100 Subject: Remove duplicate defintions --- src/variable.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/variable.c b/src/variable.c index a921432c..4a07180d 100644 --- a/src/variable.c +++ b/src/variable.c @@ -859,15 +859,6 @@ char *ba_name; header *ow_head; owner_type *ow_info; char *ow_name; -/* char *ow_text; */ - -/* - * The dungeon types arrays - */ -header *d_head; -dungeon_info_type *d_info; -char *d_name; -char *d_text; /* * Hack -- The special Angband "System Suffix" @@ -1346,11 +1337,6 @@ int max_bg_idx; */ s32b extra_savefile_parts = 0; -/* - * Quests - */ -quest_type quest[MAX_Q_IDX]; - /* * Display the player as a special symbol when in bad health ? */ -- cgit v1.2.3 From 67dd3b38ff1311dbd3a37895f6bf0e81b0341bbf Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Mar 2013 10:07:14 +0100 Subject: Eliminate pointless pointless fake_{name,text}_size globals --- src/externs.h | 2 - src/init1.c | 80 +++++++++++++++---------------- src/init2.c | 151 ++++++++++++++-------------------------------------------- 3 files changed, 76 insertions(+), 157 deletions(-) diff --git a/src/externs.h b/src/externs.h index 99792082..20f094dd 100644 --- a/src/externs.h +++ b/src/externs.h @@ -929,8 +929,6 @@ extern void init_angband(void); extern errr init_buildings(void); extern s16b error_idx; extern s16b error_line; -extern u32b fake_name_size; -extern u32b fake_text_size; /* joke.c */ extern bool_ gen_joke_monsters(void *data, void *in, void *out); diff --git a/src/init1.c b/src/init1.c index cc589bde..076ca70e 100644 --- a/src/init1.c +++ b/src/init1.c @@ -1934,7 +1934,7 @@ errr init_player_info_txt(FILE *fp, char *buf) rp_ptr = &race_info[i]; /* Hack -- Verify space */ - if (rp_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (rp_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!rp_ptr->title) rp_ptr->title = ++rp_head->name_size; @@ -1963,7 +1963,7 @@ errr init_player_info_txt(FILE *fp, char *buf) s = buf + 4; /* Hack -- Verify space */ - if (rp_head->text_size + strlen(s) + 8 > fake_text_size) return (7); + if (rp_head->text_size + strlen(s) + 8 > FAKE_TEXT_SIZE) return (7); /* Advance and Save the text index */ if (!rp_ptr->desc) @@ -2308,7 +2308,7 @@ errr init_player_info_txt(FILE *fp, char *buf) rmp_ptr = &race_mod_info[i]; /* Hack -- Verify space */ - if (rmp_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (rmp_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!rmp_ptr->title) rmp_ptr->title = ++rmp_head->name_size; @@ -2340,7 +2340,7 @@ errr init_player_info_txt(FILE *fp, char *buf) else rmp_ptr->place = FALSE; /* Hack -- Verify space */ - if (rmp_head->text_size + strlen(s) + 8 > fake_text_size) return (7); + if (rmp_head->text_size + strlen(s) + 8 > FAKE_TEXT_SIZE) return (7); /* Advance and Save the text index */ if (!rmp_ptr->desc) @@ -2722,7 +2722,7 @@ errr init_player_info_txt(FILE *fp, char *buf) c_ptr = &class_info[i]; /* Hack -- Verify space */ - if (c_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (c_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!c_ptr->title) c_ptr->title = ++c_head->name_size; @@ -2756,7 +2756,7 @@ errr init_player_info_txt(FILE *fp, char *buf) s = buf + 6; /* Hack -- Verify space */ - if (c_head->text_size + strlen(s) + 8 > fake_text_size) return (7); + if (c_head->text_size + strlen(s) + 8 > FAKE_TEXT_SIZE) return (7); switch (buf[4]) { @@ -3133,7 +3133,7 @@ errr init_player_info_txt(FILE *fp, char *buf) s_ptr = &c_ptr->spec[spec_idx]; /* Hack -- Verify space */ - if (c_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (c_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!s_ptr->title) s_ptr->title = ++c_head->name_size; @@ -3160,7 +3160,7 @@ errr init_player_info_txt(FILE *fp, char *buf) s = buf + 6; /* Hack -- Verify space */ - if (c_head->text_size + strlen(s) + 8 > fake_text_size) return (7); + if (c_head->text_size + strlen(s) + 8 > FAKE_TEXT_SIZE) return (7); /* Advance and Save the text index */ if (!s_ptr->desc) @@ -3501,7 +3501,7 @@ errr init_v_info_txt(FILE *fp, char *buf, bool_ start) v_ptr = &v_info[i]; /* Hack -- Verify space */ - if (v_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (v_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!v_ptr->name) v_ptr->name = ++v_head->name_size; @@ -3526,7 +3526,7 @@ errr init_v_info_txt(FILE *fp, char *buf, bool_ start) s = buf + 2; /* Hack -- Verify space */ - if (v_head->text_size + strlen(s) + 8 > fake_text_size) return (7); + if (v_head->text_size + strlen(s) + 8 > FAKE_TEXT_SIZE) return (7); /* Advance and Save the text index */ if (!v_ptr->text) v_ptr->text = ++v_head->text_size; @@ -3755,7 +3755,7 @@ errr init_f_info_txt(FILE *fp, char *buf) f_ptr = &f_info[i]; /* Hack -- Verify space */ - if (f_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (f_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!f_ptr->name) f_ptr->name = ++f_head->name_size; @@ -3788,7 +3788,7 @@ errr init_f_info_txt(FILE *fp, char *buf) s = buf + 4; /* Hack -- Verify space */ - if (f_head->text_size + strlen(s) + 8 > fake_text_size) return (7); + if (f_head->text_size + strlen(s) + 8 > FAKE_TEXT_SIZE) return (7); switch (buf[2]) { @@ -4188,7 +4188,7 @@ errr init_k_info_txt(FILE *fp, char *buf) k_ptr = &k_info[i]; /* Hack -- Verify space */ - if (k_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (k_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!k_ptr->name) k_ptr->name = ++k_head->name_size; @@ -4217,7 +4217,7 @@ errr init_k_info_txt(FILE *fp, char *buf) s = buf + 2; /* Hack -- Verify space */ - if (k_head->text_size + strlen(s) + 8 > fake_text_size) return (7); + if (k_head->text_size + strlen(s) + 8 > FAKE_TEXT_SIZE) return (7); /* Advance and Save the text index */ if (!k_ptr->text) k_ptr->text = ++k_head->text_size; @@ -4821,7 +4821,7 @@ errr init_al_info_txt(FILE *fp, char *buf) s = buf + 2; /* Hack -- Verify space */ - if (al_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (al_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ a_ptr->item_descp = ++al_head->name_size; @@ -4843,7 +4843,7 @@ errr init_al_info_txt(FILE *fp, char *buf) s = buf + 2; /* Hack -- Verify space */ - if (al_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (al_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ a_ptr->desc = ++al_head->name_size; @@ -4865,7 +4865,7 @@ errr init_al_info_txt(FILE *fp, char *buf) s = buf + 2; /* Hack -- Verify space */ - if (al_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (al_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); if (a_ptr->item_desc) return (7); @@ -5098,7 +5098,7 @@ errr init_a_info_txt(FILE *fp, char *buf) a_ptr = &a_info[i]; /* Hack -- Verify space */ - if (a_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (a_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!a_ptr->name) a_ptr->name = ++a_head->name_size; @@ -5140,7 +5140,7 @@ errr init_a_info_txt(FILE *fp, char *buf) s = buf + 2; /* Hack -- Verify space */ - if (a_head->text_size + strlen(s) + 8 > fake_text_size) return (7); + if (a_head->text_size + strlen(s) + 8 > FAKE_TEXT_SIZE) return (7); /* Advance and Save the text index */ if (!a_ptr->text) a_ptr->text = ++a_head->text_size; @@ -5440,7 +5440,7 @@ errr init_set_info_txt(FILE *fp, char *buf) set_ptr = &set_info[i]; /* Hack -- Verify space */ - if (set_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (set_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!set_ptr->name) set_ptr->name = ++set_head->name_size; @@ -5484,7 +5484,7 @@ errr init_set_info_txt(FILE *fp, char *buf) s = buf + 2; /* Hack -- Verify space */ - if (set_head->text_size + strlen(s) + 8 > fake_text_size) return (7); + if (set_head->text_size + strlen(s) + 8 > FAKE_TEXT_SIZE) return (7); /* Advance and Save the text index */ if (!set_ptr->desc) set_ptr->desc = ++set_head->text_size; @@ -5789,7 +5789,7 @@ errr init_s_info_txt(FILE *fp, char *buf) s_ptr = &s_info[i]; /* Hack -- Verify space */ - if (s_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (s_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!s_ptr->name) s_ptr->name = ++s_head->name_size; @@ -5823,7 +5823,7 @@ errr init_s_info_txt(FILE *fp, char *buf) s = buf + 2; /* Hack -- Verify space */ - if (s_head->text_size + strlen(s) + 8 > fake_text_size) return (7); + if (s_head->text_size + strlen(s) + 8 > FAKE_TEXT_SIZE) return (7); /* Advance and Save the text index */ if (!s_ptr->desc) @@ -5862,7 +5862,7 @@ errr init_s_info_txt(FILE *fp, char *buf) txt++; /* Hack -- Verify space */ - if (s_head->text_size + strlen(txt) + 8 > fake_text_size) return (7); + if (s_head->text_size + strlen(txt) + 8 > FAKE_TEXT_SIZE) return (7); /* Advance and Save the text index */ if (!s_ptr->action_desc) s_ptr->action_desc = ++s_head->text_size; @@ -6051,7 +6051,7 @@ errr init_ab_info_txt(FILE *fp, char *buf) ab_ptr = &ab_info[i]; /* Hack -- Verify space */ - if (ab_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (ab_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!ab_ptr->name) ab_ptr->name = ++ab_head->name_size; @@ -6090,7 +6090,7 @@ errr init_ab_info_txt(FILE *fp, char *buf) s = buf + 2; /* Hack -- Verify space */ - if (ab_head->text_size + strlen(s) + 8 > fake_text_size) return (7); + if (ab_head->text_size + strlen(s) + 8 > FAKE_TEXT_SIZE) return (7); /* Advance and Save the text index */ if (!ab_ptr->desc) @@ -6129,7 +6129,7 @@ errr init_ab_info_txt(FILE *fp, char *buf) txt++; /* Hack -- Verify space */ - if (ab_head->text_size + strlen(txt) + 8 > fake_text_size) return (7); + if (ab_head->text_size + strlen(txt) + 8 > FAKE_TEXT_SIZE) return (7); /* Advance and Save the text index */ if (!ab_ptr->action_desc) ab_ptr->action_desc = ++ab_head->text_size; @@ -6616,7 +6616,7 @@ errr init_e_info_txt(FILE *fp, char *buf) e_ptr = &e_info[i]; /* Hack -- Verify space */ - if (e_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (e_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!e_ptr->name) e_ptr->name = ++e_head->name_size; @@ -7549,7 +7549,7 @@ errr init_r_info_txt(FILE *fp, char *buf) r_ptr = &r_info[i]; /* Hack -- Verify space */ - if (r_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (r_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!r_ptr->name) r_ptr->name = ++r_head->name_size; @@ -7582,7 +7582,7 @@ errr init_r_info_txt(FILE *fp, char *buf) s = buf + 2; /* Hack -- Verify space */ - if (r_head->text_size + strlen(s) + 8 > fake_text_size) return (7); + if (r_head->text_size + strlen(s) + 8 > FAKE_TEXT_SIZE) return (7); /* Advance and Save the text index */ if (!r_ptr->text) r_ptr->text = ++r_head->text_size; @@ -8192,7 +8192,7 @@ errr init_re_info_txt(FILE *fp, char *buf) re_ptr = &re_info[i]; /* Hack -- Verify space */ - if (re_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (re_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!re_ptr->name) re_ptr->name = ++re_head->name_size; @@ -8733,7 +8733,7 @@ errr init_t_info_txt(FILE *fp, char *buf) t_ptr = &t_info[i]; /* Hack -- Verify space */ - if (t_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (t_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!t_ptr->name) t_ptr->name = ++t_head->name_size; @@ -8787,7 +8787,7 @@ errr init_t_info_txt(FILE *fp, char *buf) s = buf + 2; /* Hack -- Verify space */ - if (t_head->text_size + strlen(s) + 8 > fake_text_size) return (7); + if (t_head->text_size + strlen(s) + 8 > FAKE_TEXT_SIZE) return (7); /* Advance and Save the text index */ if (!t_ptr->text) t_ptr->text = ++t_head->text_size; @@ -9106,7 +9106,7 @@ errr init_d_info_txt(FILE *fp, char *buf) d_ptr = &d_info[i]; /* Hack -- Verify space */ - if (d_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (d_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!d_ptr->name) d_ptr->name = ++d_head->name_size; @@ -9165,7 +9165,7 @@ errr init_d_info_txt(FILE *fp, char *buf) s = buf + 6; /* Hack -- Verify space */ - if (d_head->text_size + strlen(s) + 8 > fake_text_size) return (7); + if (d_head->text_size + strlen(s) + 8 > FAKE_TEXT_SIZE) return (7); /* Advance and Save the text index */ if (!d_ptr->text) d_ptr->text = ++d_head->text_size; @@ -9751,7 +9751,7 @@ errr init_st_info_txt(FILE *fp, char *buf) st_ptr = &st_info[i]; /* Hack -- Verify space */ - if (st_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (st_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!st_ptr->name) st_ptr->name = ++st_head->name_size; @@ -10040,7 +10040,7 @@ errr init_ba_info_txt(FILE *fp, char *buf) ba_ptr = &ba_info[i]; /* Hack -- Verify space */ - if (ba_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (ba_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!ba_ptr->name) ba_ptr->name = ++ba_head->name_size; @@ -10210,7 +10210,7 @@ errr init_ow_info_txt(FILE *fp, char *buf) ow_ptr = &ow_info[i]; /* Hack -- Verify space */ - if (ow_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (ow_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!ow_ptr->name) ow_ptr->name = ++ow_head->name_size; @@ -10454,7 +10454,7 @@ errr init_wf_info_txt(FILE *fp, char *buf) wf_ptr = &wf_info[i]; /* Hack -- Verify space */ - if (wf_head->name_size + strlen(s) + 8 > fake_name_size) return (7); + if (wf_head->name_size + strlen(s) + 8 > FAKE_NAME_SIZE) return (7); /* Advance and Save the name index */ if (!wf_ptr->name) wf_ptr->name = ++wf_head->name_size; @@ -10479,7 +10479,7 @@ errr init_wf_info_txt(FILE *fp, char *buf) s = buf + 2; /* Hack -- Verify space */ - if (wf_head->text_size + strlen(s) + 8 > fake_text_size) return (7); + if (wf_head->text_size + strlen(s) + 8 > FAKE_TEXT_SIZE) return (7); /* Advance and Save the text index */ if (!wf_ptr->text) wf_ptr->text = ++wf_head->text_size; diff --git a/src/init2.c b/src/init2.c index 815d1255..50329509 100644 --- a/src/init2.c +++ b/src/init2.c @@ -224,14 +224,6 @@ s16b error_idx; s16b error_line; -/* - * Hack -- help initialise the fake "name" and "text" arrays when - * parsing an "ascii" template file. - */ -u32b fake_name_size; -u32b fake_text_size; - - /* * Standard error message text */ @@ -288,16 +280,12 @@ static errr init_f_info(void) /*** Make the fake arrays ***/ - /* Fake the size of "f_name" and "f_text" */ - fake_name_size = FAKE_NAME_SIZE; - fake_text_size = FAKE_TEXT_SIZE; - /* Allocate the "f_info" array */ C_MAKE(f_info, f_head->info_num, feature_type); /* Hack -- make "fake" arrays */ - C_MAKE(f_name, fake_name_size, char); - C_MAKE(f_text, fake_text_size, char); + C_MAKE(f_name, FAKE_NAME_SIZE, char); + C_MAKE(f_text, FAKE_TEXT_SIZE, char); /*** Load the ascii template file ***/ @@ -372,16 +360,12 @@ static errr init_k_info(void) /*** Make the fake arrays ***/ - /* Fake the size of "k_name" and "k_text" */ - fake_name_size = FAKE_NAME_SIZE; - fake_text_size = FAKE_TEXT_SIZE; - /* Allocate the "k_info" array */ C_MAKE(k_info, k_head->info_num, object_kind); /* Hack -- make "fake" arrays */ - C_MAKE(k_name, fake_name_size, char); - C_MAKE(k_text, fake_text_size, char); + C_MAKE(k_name, FAKE_NAME_SIZE, char); + C_MAKE(k_text, FAKE_TEXT_SIZE, char); /*** Load the ascii template file ***/ @@ -456,16 +440,12 @@ static errr init_set_info(void) /*** Make the fake arrays ***/ - /* Fake the size of "set_name" and "set_text" */ - fake_name_size = FAKE_NAME_SIZE; - fake_text_size = FAKE_TEXT_SIZE; - /* Allocate the "set_info" array */ C_MAKE(set_info, set_head->info_num, set_type); /* Hack -- make "fake" arrays */ - C_MAKE(set_name, fake_name_size, char); - C_MAKE(set_text, fake_text_size, char); + C_MAKE(set_name, FAKE_NAME_SIZE, char); + C_MAKE(set_text, FAKE_TEXT_SIZE, char); /*** Load the ascii template file ***/ @@ -539,16 +519,12 @@ static errr init_a_info(void) /*** Make the fake arrays ***/ - /* Fake the size of "a_name" and "a_text" */ - fake_name_size = FAKE_NAME_SIZE; - fake_text_size = FAKE_TEXT_SIZE; - /* Allocate the "a_info" array */ C_MAKE(a_info, a_head->info_num, artifact_type); /* Hack -- make "fake" arrays */ - C_MAKE(a_name, fake_name_size, char); - C_MAKE(a_text, fake_text_size, char); + C_MAKE(a_name, FAKE_NAME_SIZE, char); + C_MAKE(a_text, FAKE_TEXT_SIZE, char); /*** Load the ascii template file ***/ @@ -622,16 +598,12 @@ static errr init_s_info(void) /*** Make the fake arrays ***/ - /* Fake the size of "a_name" and "a_text" */ - fake_name_size = FAKE_NAME_SIZE; - fake_text_size = FAKE_TEXT_SIZE; - /* Allocate the "s_info" array */ C_MAKE(s_info, s_head->info_num, skill_type); /* Hack -- make "fake" arrays */ - C_MAKE(s_name, fake_name_size, char); - C_MAKE(s_text, fake_text_size, char); + C_MAKE(s_name, FAKE_NAME_SIZE, char); + C_MAKE(s_text, FAKE_TEXT_SIZE, char); /*** Load the ascii template file ***/ @@ -704,16 +676,12 @@ static errr init_ab_info(void) /*** Make the fake arrays ***/ - /* Fake the size of "a_name" and "a_text" */ - fake_name_size = FAKE_NAME_SIZE; - fake_text_size = FAKE_TEXT_SIZE; - /* Allocate the "ab_info" array */ C_MAKE(ab_info, ab_head->info_num, ability_type); /* Hack -- make "fake" arrays */ - C_MAKE(ab_name, fake_name_size, char); - C_MAKE(ab_text, fake_text_size, char); + C_MAKE(ab_name, FAKE_NAME_SIZE, char); + C_MAKE(ab_text, FAKE_TEXT_SIZE, char); /*** Load the ascii template file ***/ @@ -787,16 +755,12 @@ static errr init_e_info(void) /*** Make the fake arrays ***/ - /* Fake the size of "e_name" and "e_text" */ - fake_name_size = FAKE_NAME_SIZE; - fake_text_size = FAKE_TEXT_SIZE; - /* Allocate the "e_info" array */ C_MAKE(e_info, e_head->info_num, ego_item_type); /* Hack -- make "fake" arrays */ - C_MAKE(e_name, fake_name_size, char); - C_MAKE(e_text, fake_text_size, char); + C_MAKE(e_name, FAKE_NAME_SIZE, char); + C_MAKE(e_text, FAKE_TEXT_SIZE, char); /*** Load the ascii template file ***/ @@ -870,10 +834,6 @@ static errr init_ra_info(void) /*** Make the fake arrays ***/ - /* Fake the size of "ra_name" and "ra_text" */ - fake_name_size = FAKE_NAME_SIZE; - fake_text_size = FAKE_TEXT_SIZE; - /* Allocate the "ra_info" array */ C_MAKE(ra_info, ra_head->info_num, randart_part_type); @@ -945,16 +905,12 @@ static errr init_r_info(void) /*** Make the fake arrays ***/ - /* Assume the size of "r_name" and "r_text" */ - fake_name_size = FAKE_NAME_SIZE; - fake_text_size = FAKE_TEXT_SIZE; - /* Allocate the "r_info" array */ C_MAKE(r_info, r_head->info_num, monster_race); /* Hack -- make "fake" arrays */ - C_MAKE(r_name, fake_name_size, char); - C_MAKE(r_text, fake_text_size, char); + C_MAKE(r_name, FAKE_NAME_SIZE, char); + C_MAKE(r_text, FAKE_TEXT_SIZE, char); /*** Load the ascii template file ***/ @@ -1028,14 +984,11 @@ static errr init_re_info(void) /*** Make the fake arrays ***/ - /* Assume the size of "re_name" */ - fake_name_size = FAKE_NAME_SIZE; - /* Allocate the "re_info" array */ C_MAKE(re_info, re_head->info_num, monster_ego); /* Hack -- make "fake" arrays */ - C_MAKE(re_name, fake_name_size, char); + C_MAKE(re_name, FAKE_NAME_SIZE, char); /*** Load the ascii template file ***/ @@ -1108,16 +1061,12 @@ static errr init_d_info(void) /*** Make the fake arrays ***/ - /* Assume the size of "d_name" and "d_text" */ - fake_name_size = FAKE_NAME_SIZE; - fake_text_size = FAKE_TEXT_SIZE; - /* Allocate the "d_info" array */ C_MAKE(d_info, d_head->info_num, dungeon_info_type); /* Hack -- make "fake" arrays */ - C_MAKE(d_name, fake_name_size, char); - C_MAKE(d_text, fake_text_size, char); + C_MAKE(d_name, FAKE_NAME_SIZE, char); + C_MAKE(d_text, FAKE_TEXT_SIZE, char); /*** Load the ascii template file ***/ @@ -1211,30 +1160,26 @@ static errr init_player_info(void) /*** Make the fake arrays ***/ - /* Assume the size of "rp_name" and "rp_text" */ - fake_name_size = FAKE_NAME_SIZE; - fake_text_size = FAKE_TEXT_SIZE; - /* Allocate the "rp_info" array */ C_MAKE(race_info, rp_head->info_num, player_race); /* Hack -- make "fake" arrays */ - C_MAKE(rp_name, fake_name_size, char); - C_MAKE(rp_text, fake_text_size, char); + C_MAKE(rp_name, FAKE_NAME_SIZE, char); + C_MAKE(rp_text, FAKE_TEXT_SIZE, char); /* Allocate the "rmp_info" array */ C_MAKE(race_mod_info, rmp_head->info_num, player_race_mod); /* Hack -- make "fake" arrays */ - C_MAKE(rmp_name, fake_name_size, char); - C_MAKE(rmp_text, fake_text_size, char); + C_MAKE(rmp_name, FAKE_NAME_SIZE, char); + C_MAKE(rmp_text, FAKE_TEXT_SIZE, char); /* Allocate the "c_info" array */ C_MAKE(class_info, c_head->info_num, player_class); /* Hack -- make "fake" arrays */ - C_MAKE(c_name, fake_name_size, char); - C_MAKE(c_text, fake_text_size, char); + C_MAKE(c_name, FAKE_NAME_SIZE, char); + C_MAKE(c_text, FAKE_TEXT_SIZE, char); /* Allocate the "bg" array */ C_MAKE(bg, max_bg_idx, hist_type); @@ -1320,14 +1265,11 @@ static errr init_st_info(void) /*** Make the fake arrays ***/ - /* Assume the size of "st_name" and "st_text" */ - fake_name_size = FAKE_NAME_SIZE; - /* Allocate the "st_info" array */ C_MAKE(st_info, st_head->info_num, store_info_type); /* Hack -- make "fake" arrays */ - C_MAKE(st_name, fake_name_size, char); + C_MAKE(st_name, FAKE_NAME_SIZE, char); /*** Load the ascii template file ***/ @@ -1399,14 +1341,11 @@ static errr init_ow_info(void) /*** Make the fake arrays ***/ - /* Assume the size of "ow_name" and "ow_text" */ - fake_name_size = FAKE_NAME_SIZE; - /* Allocate the "ow_info" array */ C_MAKE(ow_info, ow_head->info_num, owner_type); /* Hack -- make "fake" arrays */ - C_MAKE(ow_name, fake_name_size, char); + C_MAKE(ow_name, FAKE_NAME_SIZE, char); /*** Load the ascii template file ***/ @@ -1478,14 +1417,11 @@ static errr init_ba_info(void) /*** Make the fake arrays ***/ - /* Assume the size of "ba_name" and "ba_text" */ - fake_name_size = FAKE_NAME_SIZE; - /* Allocate the "ba_info" array */ C_MAKE(ba_info, ba_head->info_num, store_action_type); /* Hack -- make "fake" arrays */ - C_MAKE(ba_name, fake_name_size, char); + C_MAKE(ba_name, FAKE_NAME_SIZE, char); /*** Load the ascii template file ***/ @@ -1557,16 +1493,12 @@ static errr init_wf_info(void) /*** Make the fake arrays ***/ - /* Assume the size of "wf_name" and "wf_text" */ - fake_name_size = FAKE_NAME_SIZE; - fake_text_size = FAKE_TEXT_SIZE; - /* Allocate the "r_info" array */ C_MAKE(wf_info, wf_head->info_num, wilderness_type_info); /* Hack -- make "fake" arrays */ - C_MAKE(wf_name, fake_name_size, char); - C_MAKE(wf_text, fake_text_size, char); + C_MAKE(wf_name, FAKE_NAME_SIZE, char); + C_MAKE(wf_text, FAKE_TEXT_SIZE, char); /*** Load the ascii template file ***/ @@ -1640,16 +1572,12 @@ static errr init_t_info(void) /*** Make the fake arrays ***/ - /* Fake the size of "t_name" and "t_text" */ - fake_name_size = FAKE_NAME_SIZE; - fake_text_size = FAKE_TEXT_SIZE; - /* Allocate the "t_info" array */ C_MAKE(t_info, t_head->info_num, trap_type); /* Hack -- make "fake" arrays */ - C_MAKE(t_name, fake_name_size, char); - C_MAKE(t_text, fake_text_size, char); + C_MAKE(t_name, FAKE_NAME_SIZE, char); + C_MAKE(t_text, FAKE_TEXT_SIZE, char); /*** Load the ascii template file ***/ @@ -1721,9 +1649,6 @@ errr init_al_info(void) - fake_text_size = FAKE_TEXT_SIZE; - fake_name_size = FAKE_NAME_SIZE; - /* Allocate the "al_info" array */ C_MAKE(alchemist_recipes, al_head->info_num, alchemist_recipe); @@ -1733,11 +1658,11 @@ errr init_al_info(void) than 32*5*sizeof(artifact_select_flag) = 10 int and 5 bytes which is the maximum size of the a_select_flags array */ - C_MAKE(al_name, fake_name_size, char); + C_MAKE(al_name, FAKE_NAME_SIZE, char); { char *hack; - C_MAKE(hack, fake_text_size, char); + C_MAKE(hack, FAKE_TEXT_SIZE, char); a_select_flags = (artifact_select_flag *) hack; } @@ -1812,16 +1737,12 @@ errr init_v_info(void) /*** Make the fake arrays ***/ - /* Fake the size of "v_name" and "v_text" */ - fake_name_size = FAKE_NAME_SIZE; - fake_text_size = FAKE_TEXT_SIZE; - /* Allocate the "k_info" array */ C_MAKE(v_info, v_head->info_num, vault_type); /* Hack -- make "fake" arrays */ - C_MAKE(v_name, fake_name_size, char); - C_MAKE(v_text, fake_text_size, char); + C_MAKE(v_name, FAKE_NAME_SIZE, char); + C_MAKE(v_text, FAKE_TEXT_SIZE, char); /*** Load the ascii template file ***/ -- cgit v1.2.3 From 45d2d5c39869cce42d0f2b7b5fc65c5a0d7014bb Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Mar 2013 08:26:51 +0100 Subject: Constness fixes --- src/init2.c | 2 +- src/loadsave.c | 85 ++++++++++++++++++++++++++++++++++------------------------ 2 files changed, 51 insertions(+), 36 deletions(-) diff --git a/src/init2.c b/src/init2.c index 50329509..f5001e0d 100644 --- a/src/init2.c +++ b/src/init2.c @@ -2398,7 +2398,7 @@ void init_angband(void) FILE *fp; - char *news_file; + const char *news_file; char buf[1024]; diff --git a/src/loadsave.c b/src/loadsave.c index f68d974c..818cbb62 100644 --- a/src/loadsave.c +++ b/src/loadsave.c @@ -34,7 +34,7 @@ static void morejunk(void); static bool_ do_inventory(int); static bool_ do_dungeon(int, bool_); static void do_grid(int); -static void my_sentinel(char *, u16b, int); +static void my_sentinel(const char *, u16b, int); static void do_ver_s16b(s16b *, u32b, s16b, int); @@ -1138,39 +1138,49 @@ static void do_s32b(s32b *ip, int flag) do_u32b((u32b *)ip, flag); } -static void do_string(char *str, int max, int flag) -/* Max is ignored for writing */ +static void save_string(const char *str) { - if (flag == LS_LOAD) + while (*str) { - int i; + do_byte((byte*)str, LS_SAVE); + str++; + } + do_byte((byte*)str, LS_SAVE); +} - /* Read the string */ - for (i = 0; TRUE; i++) - { - byte tmp8u; +static void load_string(char *str, int max) +{ + int i; - /* Read a byte */ - do_byte(&tmp8u, LS_LOAD); + /* Read the string */ + for (i = 0; TRUE; i++) + { + byte tmp8u; - /* Collect string while legal */ - if (i < max) str[i] = tmp8u; + /* Read a byte */ + do_byte(&tmp8u, LS_LOAD); - /* End of string */ - if (!tmp8u) break; - } - /* Terminate */ - str[max - 1] = '\0'; + /* Collect string while legal */ + if (i < max) str[i] = tmp8u; + + /* End of string */ + if (!tmp8u) break; + } + /* Terminate */ + str[max - 1] = '\0'; +} + +static void do_string(char *str, int max, int flag) +/* Max is ignored for writing */ +{ + if (flag == LS_LOAD) + { + load_string(str, max); return; } if (flag == LS_SAVE) { - while (*str) - { - do_byte((byte*)str, flag); - str++; - } - do_byte((byte*)str, flag); /* Output a terminator */ + save_string(str); return; } printf("FATAL: do_string passed flag %d\n", flag); @@ -1377,31 +1387,36 @@ static void do_item(object_type *o_ptr, int flag) { char buf[128]; /* Inscription */ - do_string(buf, 128, LS_LOAD); - /* Save the inscription */ - if (buf[0]) o_ptr->note = quark_add(buf); - - do_string(buf, 128, LS_LOAD); - if (buf[0]) o_ptr->art_name = quark_add(buf); + load_string(buf, 128); + if (buf[0]) + { + o_ptr->note = quark_add(buf); + } + /* Artifact name */ + load_string(buf, 128); + if (buf[0]) + { + o_ptr->art_name = quark_add(buf); + } } if (flag == LS_SAVE) { /* Save the inscription (if any) */ if (o_ptr->note) { - do_string((char *)quark_str(o_ptr->note), 0, LS_SAVE); + save_string(quark_str(o_ptr->note)); } else { - do_string("", 0, LS_SAVE); + save_string(""); } if (o_ptr->art_name) { - do_string((char *)quark_str(o_ptr->art_name), 0, LS_SAVE); + save_string(quark_str(o_ptr->art_name)); } else { - do_string("", 0, LS_SAVE); + save_string(""); } } @@ -3137,7 +3152,7 @@ static void do_grid(int flag) } } -static void my_sentinel(char *place, u16b value, int flag) +static void my_sentinel(const char *place, u16b value, int flag) /* This function lets us know exactly where a savefile is broken by reading/writing conveniently a sentinel at this spot */ -- cgit v1.2.3 From b9f824effb037a53556e02955cace6c09ff646c3 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Wed, 27 Mar 2013 10:26:47 +0100 Subject: Hide vformat in z-form.c --- src/z-form.c | 2 +- src/z-form.h | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/z-form.c b/src/z-form.c index b3d5d005..340147af 100644 --- a/src/z-form.c +++ b/src/z-form.c @@ -647,7 +647,7 @@ uint vstrnfmt(char *buf, uint max, cptr fmt, va_list vp) * Do a vstrnfmt (see above) into a (growable) static buffer. * This buffer is usable for very short term formatting of results. */ -char *vformat(cptr fmt, va_list vp) +static char *vformat(cptr fmt, va_list vp) { static char *format_buf = NULL; static huge format_len = 0; diff --git a/src/z-form.h b/src/z-form.h index 2dcfa96c..752cf249 100644 --- a/src/z-form.h +++ b/src/z-form.h @@ -32,9 +32,6 @@ extern uint strnfmt(char *buf, uint max, cptr fmt, ...); /* Simple interface to "vstrnfmt()", assuming infinite length */ extern uint strfmt(char *buf, cptr fmt, ...); -/* Format arguments into a static resizing buffer */ -extern char *vformat(cptr fmt, va_list vp); - /* Simple interface to "vformat()" */ extern char *format(cptr fmt, ...); -- cgit v1.2.3 From cbef37bd5bfb938a2303ee3887520c08be85d8e8 Mon Sep 17 00:00:00 2001 From: Bardur Arantsson Date: Tue, 26 Mar 2013 17:10:10 +0100 Subject: Switch almost everything over to C++ --- src/CMakeLists.txt | 44 +- src/birth.c | 3942 ------------- src/birth.cc | 3949 +++++++++++++ src/bldg.c | 2234 ------- src/bldg.cc | 2234 +++++++ src/cave.c | 5022 ---------------- src/cave.cc | 4952 ++++++++++++++++ src/cmd1.c | 5147 ----------------- src/cmd1.cc | 5147 +++++++++++++++++ src/cmd2.c | 5182 ----------------- src/cmd2.cc | 5182 +++++++++++++++++ src/cmd3.c | 2333 -------- src/cmd3.cc | 2267 ++++++++ src/cmd4.c | 4632 --------------- src/cmd4.cc | 4607 +++++++++++++++ src/cmd5.c | 2471 -------- src/cmd5.cc | 2471 ++++++++ src/cmd6.c | 7792 ------------------------- src/cmd6.cc | 7792 +++++++++++++++++++++++++ src/cmd7.c | 7632 ------------------------ src/cmd7.cc | 7632 ++++++++++++++++++++++++ src/cmovie.c | 496 -- src/cmovie.cc | 500 ++ src/corrupt.c | 973 ---- src/corrupt.cc | 973 ++++ src/device_allocation.c | 26 - src/device_allocation.cc | 26 + src/dice.c | 94 - src/dice.cc | 94 + src/dungeon.c | 5849 ------------------- src/dungeon.cc | 5849 +++++++++++++++++++ src/externs.h | 7 +- src/files.c | 5842 ------------------- src/files.cc | 5813 +++++++++++++++++++ src/gen_evol.c | 156 - src/gen_evol.cc | 156 + src/gen_maze.c | 294 - src/gen_maze.cc | 292 + src/generate.c | 8864 ---------------------------- src/generate.cc | 8849 ++++++++++++++++++++++++++++ src/gods.c | 200 - src/gods.cc | 200 + src/help.c | 750 --- src/help.cc | 750 +++ src/hiscore.c | 85 - src/hiscore.cc | 85 + src/hooks.c | 275 - src/hooks.cc | 276 + src/include/tome/make_array.hpp | 13 + src/init1.c | 11816 -------------------------------------- src/init1.cc | 11816 ++++++++++++++++++++++++++++++++++++++ src/init2.c | 2663 --------- src/init2.cc | 2476 ++++++++ src/joke.c | 34 - src/joke.cc | 34 + src/levels.c | 234 - src/levels.cc | 234 + src/loadsave.c | 3177 ---------- src/loadsave.cc | 3190 ++++++++++ src/lua_bind.c | 356 -- src/lua_bind.cc | 356 ++ src/melee1.c | 3065 ---------- src/melee1.cc | 3065 ++++++++++ src/melee2.c | 7561 ------------------------ src/melee2.cc | 7561 ++++++++++++++++++++++++ src/messages.c | 364 -- src/messages.cc | 365 ++ src/mimic.c | 694 --- src/mimic.cc | 694 +++ src/modules.c | 1215 ---- src/modules.cc | 1215 ++++ src/monster1.c | 1901 ------ src/monster1.cc | 1901 ++++++ src/monster2.c | 3979 ------------- src/monster2.cc | 3979 +++++++++++++ src/monster3.c | 706 --- src/monster3.cc | 706 +++ src/notes.c | 188 - src/notes.cc | 188 + src/object1.c | 6696 --------------------- src/object1.cc | 6696 +++++++++++++++++++++ src/object2.c | 6697 --------------------- src/object2.cc | 6695 +++++++++++++++++++++ src/powers.c | 1406 ----- src/powers.cc | 1406 +++++ src/q_betwen.c | 196 - src/q_betwen.cc | 196 + src/q_bounty.c | 112 - src/q_bounty.cc | 112 + src/q_dragons.c | 152 - src/q_dragons.cc | 152 + src/q_eol.c | 202 - src/q_eol.cc | 202 + src/q_evil.c | 119 - src/q_evil.cc | 119 + src/q_fireprof.c | 588 -- src/q_fireprof.cc | 588 ++ src/q_god.c | 1196 ---- src/q_god.cc | 1196 ++++ src/q_haunted.c | 149 - src/q_haunted.cc | 149 + src/q_hobbit.c | 207 - src/q_hobbit.cc | 207 + src/q_invas.c | 204 - src/q_invas.cc | 204 + src/q_library.c | 510 -- src/q_library.cc | 510 ++ src/q_main.c | 193 - src/q_main.cc | 193 + src/q_narsil.c | 113 - src/q_narsil.cc | 113 + src/q_nazgul.c | 123 - src/q_nazgul.cc | 123 + src/q_nirna.c | 115 - src/q_nirna.cc | 115 + src/q_one.c | 365 -- src/q_one.cc | 365 ++ src/q_poison.c | 247 - src/q_poison.cc | 247 + src/q_rand.c | 473 -- src/q_rand.cc | 469 ++ src/q_shroom.c | 304 - src/q_shroom.cc | 304 + src/q_spider.c | 113 - src/q_spider.cc | 113 + src/q_thief.c | 176 - src/q_thief.cc | 176 + src/q_thrain.c | 241 - src/q_thrain.cc | 241 + src/q_troll.c | 183 - src/q_troll.cc | 183 + src/q_ultrae.c | 8 - src/q_ultrae.cc | 8 + src/q_ultrag.c | 275 - src/q_ultrag.cc | 275 + src/q_wight.c | 162 - src/q_wight.cc | 162 + src/q_wolves.c | 132 - src/q_wolves.cc | 132 + src/quark.c | 88 - src/quark.cc | 92 + src/randart.c | 477 -- src/randart.cc | 478 ++ src/range.c | 9 - src/range.cc | 9 + src/script.c | 29 - src/script.cc | 29 + src/skills.c | 1842 ------ src/skills.cc | 1814 ++++++ src/spell_type.c | 469 -- src/spell_type.cc | 472 ++ src/spell_type.h | 4 +- src/spells1.c | 9347 ------------------------------ src/spells1.cc | 9347 ++++++++++++++++++++++++++++++ src/spells2.c | 8450 --------------------------- src/spells2.cc | 8449 +++++++++++++++++++++++++++ src/spells3.c | 4926 ---------------- src/spells3.cc | 4924 ++++++++++++++++ src/spells4.c | 631 -- src/spells4.cc | 631 ++ src/spells5.c | 2426 -------- src/spells5.cc | 2426 ++++++++ src/spells6.c | 392 -- src/spells6.cc | 401 ++ src/status.c | 772 --- src/status.cc | 772 +++ src/store.c | 3935 ------------- src/store.cc | 3935 +++++++++++++ src/string_list.c | 52 - src/string_list.cc | 52 + src/tables.c | 4761 --------------- src/tables.cc | 4761 +++++++++++++++ src/traps.c | 3180 ---------- src/traps.cc | 3180 ++++++++++ src/types.h | 16 +- src/util.c | 4029 ------------- src/util.cc | 4023 +++++++++++++ src/util.hpp | 8 + src/variable.c | 1443 ----- src/variable.cc | 1441 +++++ src/wild.c | 1280 ----- src/wild.cc | 1272 ++++ src/wizard1.c | 2750 --------- src/wizard1.cc | 2748 +++++++++ src/wizard2.c | 1894 ------ src/wizard2.cc | 1894 ++++++ src/xtra1.c | 4954 ---------------- src/xtra1.cc | 4954 ++++++++++++++++ src/xtra2.c | 5825 ------------------- src/xtra2.cc | 5825 +++++++++++++++++++ src/z-virt.h | 4 - 191 files changed, 193504 insertions(+), 193910 deletions(-) delete mode 100644 src/birth.c create mode 100644 src/birth.cc delete mode 100644 src/bldg.c create mode 100644 src/bldg.cc delete mode 100644 src/cave.c create mode 100644 src/cave.cc delete mode 100644 src/cmd1.c create mode 100644 src/cmd1.cc delete mode 100644 src/cmd2.c create mode 100644 src/cmd2.cc delete mode 100644 src/cmd3.c create mode 100644 src/cmd3.cc delete mode 100644 src/cmd4.c create mode 100644 src/cmd4.cc delete mode 100644 src/cmd5.c create mode 100644 src/cmd5.cc delete mode 100644 src/cmd6.c create mode 100644 src/cmd6.cc delete mode 100644 src/cmd7.c create mode 100644 src/cmd7.cc delete mode 100644 src/cmovie.c create mode 100644 src/cmovie.cc delete mode 100644 src/corrupt.c create mode 100644 src/corrupt.cc delete mode 100644 src/device_allocation.c create mode 100644 src/device_allocation.cc delete mode 100644 src/dice.c create mode 100644 src/dice.cc delete mode 100644 src/dungeon.c create mode 100644 src/dungeon.cc delete mode 100644 src/files.c create mode 100644 src/files.cc delete mode 100644 src/gen_evol.c create mode 100644 src/gen_evol.cc delete mode 100644 src/gen_maze.c create mode 100644 src/gen_maze.cc delete mode 100644 src/generate.c create mode 100644 src/generate.cc delete mode 100644 src/gods.c create mode 100644 src/gods.cc delete mode 100644 src/help.c create mode 100644 src/help.cc delete mode 100644 src/hiscore.c create mode 100644 src/hiscore.cc delete mode 100644 src/hooks.c create mode 100644 src/hooks.cc create mode 100644 src/include/tome/make_array.hpp delete mode 100644 src/init1.c create mode 100644 src/init1.cc delete mode 100644 src/init2.c create mode 100644 src/init2.cc delete mode 100644 src/joke.c create mode 100644 src/joke.cc delete mode 100644 src/levels.c create mode 100644 src/levels.cc delete mode 100644 src/loadsave.c create mode 100644 src/loadsave.cc delete mode 100644 src/lua_bind.c create mode 100644 src/lua_bind.cc delete mode 100644 src/melee1.c create mode 100644 src/melee1.cc delete mode 100644 src/melee2.c create mode 100644 src/melee2.cc delete mode 100644 src/messages.c create mode 100644 src/messages.cc delete mode 100644 src/mimic.c create mode 100644 src/mimic.cc delete mode 100644 src/modules.c create mode 100644 src/modules.cc delete mode 100644 src/monster1.c create mode 100644 src/monster1.cc delete mode 100644 src/monster2.c create mode 100644 src/monster2.cc delete mode 100644 src/monster3.c create mode 100644 src/monster3.cc delete mode 100644 src/notes.c create mode 100644 src/notes.cc delete mode 100644 src/object1.c create mode 100644 src/object1.cc delete mode 100644 src/object2.c create mode 100644 src/object2.cc delete mode 100644 src/powers.c create mode 100644 src/powers.cc delete mode 100644 src/q_betwen.c create mode 100644 src/q_betwen.cc delete mode 100644 src/q_bounty.c create mode 100644 src/q_bounty.cc delete mode 100644 src/q_dragons.c create mode 100644 src/q_dragons.cc delete mode 100644 src/q_eol.c create mode 100644 src/q_eol.cc delete mode 100644 src/q_evil.c create mode 100644 src/q_evil.cc delete mode 100644 src/q_fireprof.c create mode 100644 src/q_fireprof.cc delete mode 100644 src/q_god.c create mode 100644 src/q_god.cc delete mode 100644 src/q_haunted.c create mode 100644 src/q_haunted.cc delete mode 100644 src/q_hobbit.c create mode 100644 src/q_hobbit.cc delete mode 100644 src/q_invas.c create mode 100644 src/q_invas.cc delete mode 100644 src/q_library.c create mode 100644 src/q_library.cc delete mode 100644 src/q_main.c create mode 100644 src/q_main.cc delete mode 100644 src/q_narsil.c create mode 100644 src/q_narsil.cc delete mode 100644 src/q_nazgul.c create mode 100644 src/q_nazgul.cc delete mode 100644 src/q_nirna.c create mode 100644 src/q_nirna.cc delete mode 100644 src/q_one.c create mode 100644 src/q_one.cc delete mode 100644 src/q_poison.c create mode 100644 src/q_poison.cc delete mode 100644 src/q_rand.c create mode 100644 src/q_rand.cc delete mode 100644 src/q_shroom.c create mode 100644 src/q_shroom.cc delete mode 100644 src/q_spider.c create mode 100644 src/q_spider.cc delete mode 100644 src/q_thief.c create mode 100644 src/q_thief.cc delete mode 100644 src/q_thrain.c create mode 100644 src/q_thrain.cc delete mode 100644 src/q_troll.c create mode 100644 src/q_troll.cc delete mode 100644 src/q_ultrae.c create mode 100644 src/q_ultrae.cc delete mode 100644 src/q_ultrag.c create mode 100644 src/q_ultrag.cc delete mode 100644 src/q_wight.c create mode 100644 src/q_wight.cc delete mode 100644 src/q_wolves.c create mode 100644 src/q_wolves.cc delete mode 100644 src/quark.c create mode 100644 src/quark.cc delete mode 100644 src/randart.c create mode 100644 src/randart.cc delete mode 100644 src/range.c create mode 100644 src/range.cc delete mode 100644 src/script.c create mode 100644 src/script.cc delete mode 100644 src/skills.c create mode 100644 src/skills.cc delete mode 100644 src/spell_type.c create mode 100644 src/spell_type.cc delete mode 100644 src/spells1.c create mode 100644 src/spells1.cc delete mode 100644 src/spells2.c create mode 100644 src/spells2.cc delete mode 100644 src/spells3.c create mode 100644 src/spells3.cc delete mode 100644 src/spells4.c create mode 100644 src/spells4.cc delete mode 100644 src/spells5.c create mode 100644 src/spells5.cc delete mode 100644 src/spells6.c create mode 100644 src/spells6.cc delete mode 100644 src/status.c create mode 100644 src/status.cc delete mode 100644 src/store.c create mode 100644 src/store.cc delete mode 100644 src/string_list.c create mode 100644 src/string_list.cc delete mode 100644 src/tables.c create mode 100644 src/tables.cc delete mode 100644 src/traps.c create mode 100644 src/traps.cc delete mode 100644 src/util.c create mode 100644 src/util.cc create mode 100644 src/util.hpp delete mode 100644 src/variable.c create mode 100644 src/variable.cc delete mode 100644 src/wild.c create mode 100644 src/wild.cc delete mode 100644 src/wizard1.c create mode 100644 src/wizard1.cc delete mode 100644 src/wizard2.c create mode 100644 src/wizard2.cc delete mode 100644 src/xtra1.c create mode 100644 src/xtra1.cc delete mode 100644 src/xtra2.c create mode 100644 src/xtra2.cc diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ba0fd9d2..221dfa2b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,29 +8,29 @@ ADD_SUBDIRECTORY (squelch) SET(SRCS main-gcu.c main-x11.c main-xaw.c main-sdl.c main-gtk2.c z-rand.c z-util.c z-form.c z-virt.c z-term.c - variable.c tables.c hooks.c util.c cave.c dungeon.c - melee1.c melee2.c messages.c modules.c - q_god.c q_library.c q_fireprof.c q_bounty.c q_thrain.c - q_narsil.c q_evil.c q_betwen.c q_haunted.c q_invas.c - q_nirna.c q_eol.c q_god.c q_dragons.c q_poison.c - q_spider.c q_wolves.c q_shroom.c q_nazgul.c q_wight.c - q_troll.c q_hobbit.c q_thief.c q_ultrae.c q_ultrag.c - q_one.c q_main.c q_rand.c - object1.c object2.c randart.c squeltch.cc traps.c - monster1.c monster2.c monster3.c - xtra1.c xtra2.c skills.c powers.c gods.c - spells1.c spells2.c spells3.c spells4.c spells5.c spells6.c - spell_type.c device_allocation.c - corrupt.c joke.c mimic.c - status.c files.c notes.c loadsave.c string_list.c - cmd1.c cmd2.c cmd3.c cmd4.c cmd5.c cmd6.c cmd7.c - help.c hiscore.c range.c dice.c - generate.c gen_maze.c gen_evol.c wild.c levels.c store.c bldg.c - cmovie.c - wizard2.c init2.c birth.c wizard1.c init1.c main.c - quark.c + variable.cc tables.cc hooks.cc util.cc cave.cc dungeon.cc + melee1.cc melee2.cc messages.cc modules.cc + q_god.cc q_library.cc q_fireprof.cc q_bounty.cc q_thrain.cc + q_narsil.cc q_evil.cc q_betwen.cc q_haunted.cc q_invas.cc + q_nirna.cc q_eol.cc q_god.cc q_dragons.cc q_poison.cc + q_spider.cc q_wolves.cc q_shroom.cc q_nazgul.cc q_wight.cc + q_troll.cc q_hobbit.cc q_thief.cc q_ultrae.cc q_ultrag.cc + q_one.cc q_main.cc q_rand.cc + object1.cc object2.cc randart.cc squeltch.cc traps.cc + monster1.cc monster2.cc monster3.cc + xtra1.cc xtra2.cc skills.cc powers.cc gods.cc + spells1.cc spells2.cc spells3.cc spells4.cc spells5.cc spells6.cc + spell_type.cc device_allocation.cc + corrupt.cc joke.cc mimic.cc + status.cc files.cc notes.cc loadsave.cc string_list.cc + cmd1.cc cmd2.cc cmd3.cc cmd4.cc cmd5.cc cmd6.cc cmd7.cc + help.cc hiscore.cc range.cc dice.cc + generate.cc gen_maze.cc gen_evol.cc wild.cc levels.cc store.cc bldg.cc + cmovie.cc + wizard1.cc wizard2.cc init1.cc init2.cc birth.cc main.c + quark.cc # Lua bits: - lua_bind.c script.c + lua_bind.cc script.cc ) # Need a few additional source files for Windows. diff --git a/src/birth.c b/src/birth.c deleted file mode 100644 index 60a6b3ee..00000000 --- a/src/birth.c +++ /dev/null @@ -1,3942 +0,0 @@ -/* File: birth.c */ - -/* Purpose: create a player character */ - -/* - * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke - * - * This software may be copied and distributed for educational, research, and - * not for profit purposes provided that this copyright and statement are - * included in all such copies. - */ - -#include "angband.h" -#include "messages.h" -#include "hooks.h" -#include "q_rand.h" - -/* - * How often the autoroller will update the display and pause - * to check for user interuptions. - * Bigger values will make the autoroller faster, but slower - * system may have problems because the user can't stop the - * autoroller for this number of rolls. - */ -#define AUTOROLLER_STEP 25L - -/* - * Maximum number of tries for selection of a proper quest monster - */ -#define MAX_TRIES 100 - -/* Max quests */ -static byte max_quests = 0; - -/* - * Current stats - */ -static s16b stat_use[6]; - -/* - * Autoroll limit - */ -static s16b stat_limit[6]; - -/* - * Autoroll matches - */ -static s32b stat_match[6]; - -/* - * Autoroll round - */ -static s32b auto_round; - -/* - * Last round - */ -static s32b last_round; - -/* Human */ -static const char *human_syllable1[] = -{ - "Ab", "Ac", "Ad", "Af", "Agr", "Ast", "As", "Al", "Adw", "Adr", "Ar", - "B", "Br", "C", "Cr", "Ch", "Cad", "D", "Dr", "Dw", "Ed", "Eth", "Et", - "Er", "El", "Eow", "F", "Fr", "G", "Gr", "Gw", "Gal", "Gl", "H", "Ha", - "Ib", "Jer", "K", "Ka", "Ked", "L", "Loth", "Lar", "Leg", "M", "Mir", - "N", "Nyd", "Ol", "Oc", "On", "P", "Pr", "R", "Rh", "S", "Sev", "T", - "Tr", "Th", "V", "Y", "Z", "W", "Wic", -}; - -static const char *human_syllable2[] = -{ - "a", "ae", "au", "ao", "are", "ale", "ali", "ay", "ardo", "e", "ei", - "ea", "eri", "era", "ela", "eli", "enda", "erra", "i", "ia", "ie", - "ire", "ira", "ila", "ili", "ira", "igo", "o", "oa", "oi", "oe", - "ore", "u", "y", -}; - -static const char *human_syllable3[] = -{ - "a", "and", "b", "bwyn", "baen", "bard", "c", "ctred", "cred", "ch", - "can", "d", "dan", "don", "der", "dric", "dfrid", "dus", "f", "g", - "gord", "gan", "l", "li", "lgrin", "lin", "lith", "lath", "loth", - "ld", "ldric", "ldan", "m", "mas", "mos", "mar", "mond", "n", - "nydd", "nidd", "nnon", "nwan", "nyth", "nad", "nn", "nnor", "nd", - "p", "r", "ron", "rd", "s", "sh", "seth", "sean", "t", "th", "tha", - "tlan", "trem", "tram", "v", "vudd", "w", "wan", "win", "wyn", "wyr", - "wyr", "wyth", -}; - -/* - * Random Name Generator - * based on a Javascript by Michael Hensley - * "http://geocities.com/timessquare/castle/6274/" - */ -static void create_random_name(int race, char *name) -{ - const char *syl1, *syl2, *syl3; - - int idx; - - - /* Paranoia */ - if (!name) return; - - /* Select the monster type */ - switch (race) - { - /* Create the monster name */ - - /* Use human ones */ - default: - { - idx = rand_int(sizeof(human_syllable1) / sizeof(char *)); - syl1 = human_syllable1[idx]; - idx = rand_int(sizeof(human_syllable2) / sizeof(char *)); - syl2 = human_syllable2[idx]; - idx = rand_int(sizeof(human_syllable3) / sizeof(char *)); - syl3 = human_syllable3[idx]; - - break; - } - } - - /* Concatenate selected syllables */ - strnfmt(name, 32, "%s%s%s", syl1, syl2, syl3); -} - - -void print_desc_aux(cptr txt, int y, int xx) -{ - int i = -1, x = xx; - - - while (txt[++i] != 0) - { - if (txt[i] == '\n') - { - x = xx; - y++; - } - else - { - Term_putch(x++, y, TERM_YELLOW, txt[i]); - } - } -} - -void print_desc(cptr txt) -{ - print_desc_aux(txt, 12, 1); -} - -/* - * Save the current data for later - */ -static void save_prev_data(void) -{ - int i; - - - /*** Save the current data ***/ - - /* Save the data */ - previous_char.sex = p_ptr->psex; - previous_char.race = p_ptr->prace; - previous_char.rmod = p_ptr->pracem; - previous_char.pclass = p_ptr->pclass; - previous_char.spec = p_ptr->pspec; - - previous_char.quests = max_quests; - - previous_char.god = p_ptr->pgod; - previous_char.grace = p_ptr->grace; - - previous_char.age = p_ptr->age; - previous_char.wt = p_ptr->wt; - previous_char.ht = p_ptr->ht; - previous_char.sc = p_ptr->sc; - previous_char.au = p_ptr->au; - - /* Save the stats */ - for (i = 0; i < 6; i++) - { - previous_char.stat[i] = p_ptr->stat_max[i]; - } - previous_char.luck = p_ptr->luck_base; - - /* Save the weapon specialty */ - previous_char.weapon = 0; - - /* Save the history */ - for (i = 0; i < 4; i++) - { - strcpy(previous_char.history[i], history[i]); - } -} - - -/* - * Load the previous data - */ -static void load_prev_data(bool_ save) -{ - int i; - - birther temp; - - - /*** Save the current data ***/ - - /* Save the data */ - temp.age = p_ptr->age; - temp.wt = p_ptr->wt; - temp.ht = p_ptr->ht; - temp.sc = p_ptr->sc; - temp.au = p_ptr->au; - - /* Save the stats */ - for (i = 0; i < 6; i++) - { - temp.stat[i] = p_ptr->stat_max[i]; - } - temp.luck = p_ptr->luck_base; - - /* Save the weapon specialty */ - temp.weapon = 0; - - /* Save the history */ - for (i = 0; i < 4; i++) - { - strcpy(temp.history[i], history[i]); - } - - - /*** Load the previous data ***/ - - /* Load the data */ - p_ptr->age = previous_char.age; - p_ptr->wt = previous_char.wt; - p_ptr->ht = previous_char.ht; - p_ptr->sc = previous_char.sc; - p_ptr->au = previous_char.au; - - /* Load the stats */ - for (i = 0; i < 6; i++) - { - p_ptr->stat_max[i] = previous_char.stat[i]; - p_ptr->stat_cur[i] = previous_char.stat[i]; - } - p_ptr->luck_base = previous_char.luck; - p_ptr->luck_max = previous_char.luck; - - /* Load the history */ - for (i = 0; i < 4; i++) - { - strcpy(history[i], previous_char.history[i]); - } - - - /*** Save the current data ***/ - if (!save) return; - - /* Save the data */ - previous_char.age = temp.age; - previous_char.wt = temp.wt; - previous_char.ht = temp.ht; - previous_char.sc = temp.sc; - previous_char.au = temp.au; - - /* Save the stats */ - for (i = 0; i < 6; i++) - { - previous_char.stat[i] = temp.stat[i]; - } - previous_char.luck = temp.luck; - - /* Save the chaos patron */ - previous_char.chaos_patron = temp.chaos_patron; - - /* Save the weapon specialty */ - previous_char.weapon = temp.weapon; - - /* Save the history */ - for (i = 0; i < 4; i++) - { - strcpy(previous_char.history[i], temp.history[i]); - } -} - - - - -/* - * Returns adjusted stat -JK- Algorithm by -JWT- - * - * auto_roll is boolean and states maximum changes should be used rather - * than random ones to allow specification of higher values to wait for - * - * The "p_ptr->maximize" code is important -BEN- - */ -static int adjust_stat(int value, int amount, int auto_roll) -{ - int i; - - - /* Negative amounts */ - if (amount < 0) - { - /* Apply penalty */ - for (i = 0; i < (0 - amount); i++) - { - if (value >= 18 + 10) - { - value -= 10; - } - else if (value > 18) - { - value = 18; - } - else if (value > 3) - { - value--; - } - } - } - - /* Positive amounts */ - else if (amount > 0) - { - /* Apply reward */ - for (i = 0; i < amount; i++) - { - if (value < 18) - { - value++; - } - else if (p_ptr->maximize) - { - value += 10; - } - else if (value < 18 + 70) - { - value += ((auto_roll ? 15 : randint(15)) + 5); - } - else if (value < 18 + 90) - { - value += ((auto_roll ? 6 : randint(6)) + 2); - } - else if (value < 18 + 100) - { - value++; - } - } - } - - /* Return the result */ - return (value); -} - - - - -/* - * Roll for a characters stats - * - * For efficiency, we include a chunk of "calc_bonuses()". - */ -static void get_stats(void) -{ - int i, j; - - int bonus; - - int dice[18]; - - - /* Roll and verify some stats */ - while (TRUE) - { - /* Roll some dice */ - for (j = i = 0; i < 18; i++) - { - /* Roll the dice */ - dice[i] = randint(3 + i % 3); - - /* Collect the maximum */ - j += dice[i]; - } - - /* - * Verify totals - * - * 57 was 54... I hate 'magic numbers' :< TY - * - * (d3 + d4 + d5) ~= 7.5 (+- 4.5) - * with 5 makes avg. stat value of 12.5 (min 8, max 17) - * - * (d3 + d4 + d5) x 6 ~= 45 (+- 18) - * - * So the original value (still used by Vanilla as of 2.9.3) - * allows (avg - 2)..(avg + 8), while this Z version - * (avg - 2)..(avg + 11). I don't understand what TY meant - * by "magic numbers", but I like big stats :) -- pelpel - * - */ - if ((j > 42) && (j < 57)) break; - } - - /* Acquire the stats */ - for (i = 0; i < 6; i++) - { - /* Extract 5 + 1d3 + 1d4 + 1d5 */ - j = 5 + dice[3 * i] + dice[3 * i + 1] + dice[3 * i + 2]; - - /* Save that value */ - p_ptr->stat_max[i] = j; - - /* Obtain a "bonus" for "race" and "class" */ - bonus = rp_ptr->r_adj[i] + rmp_ptr->r_adj[i] + cp_ptr->c_adj[i]; - - /* Variable stat maxes */ - if (p_ptr->maximize) - { - /* Start fully healed */ - p_ptr->stat_cur[i] = p_ptr->stat_max[i]; - - /* Efficiency -- Apply the racial/class bonuses */ - stat_use[i] = modify_stat_value(p_ptr->stat_max[i], bonus); - } - - /* Fixed stat maxes */ - else - { - /* Apply the bonus to the stat (somewhat randomly) */ - stat_use[i] = adjust_stat(p_ptr->stat_max[i], bonus, FALSE); - - /* Save the resulting stat maximum */ - p_ptr->stat_cur[i] = p_ptr->stat_max[i] = stat_use[i]; - } - - /* No temporary drain (yet...) */ - p_ptr->stat_cnt[i] = 0; - p_ptr->stat_los[i] = 0; - } - - /* Get luck */ - p_ptr->luck_base = rp_ptr->luck + rmp_ptr->luck + rand_range( -5, 5); - p_ptr->luck_max = p_ptr->luck_base; -} - - -/* - * Roll for some info that the auto-roller ignores - */ -static void get_extra(void) -{ - int i, j, min_value, max_value; - - - /* Level one */ - p_ptr->max_plv = p_ptr->lev = 1; - - /* Experience factor */ - p_ptr->expfact = rp_ptr->r_exp + rmp_ptr->r_exp + cp_ptr->c_exp; - - /* Initialize arena and rewards information -KMW- */ - p_ptr->arena_number = 0; - p_ptr->inside_arena = 0; - p_ptr->inside_quest = 0; - p_ptr->exit_bldg = TRUE; /* only used for arena now -KMW- */ - - /* Hitdice */ - p_ptr->hitdie = rp_ptr->r_mhp + rmp_ptr->r_mhp + cp_ptr->c_mhp; - - /* Initial hitpoints */ - p_ptr->mhp = p_ptr->hitdie; - - /* Minimum hitpoints at highest level */ - min_value = (PY_MAX_LEVEL * (p_ptr->hitdie - 1) * 3) / 8; - min_value += PY_MAX_LEVEL; - - /* Maximum hitpoints at highest level */ - max_value = (PY_MAX_LEVEL * (p_ptr->hitdie - 1) * 5) / 8; - max_value += PY_MAX_LEVEL; - - /* Pre-calculate level 1 hitdice */ - player_hp[0] = p_ptr->hitdie; - - /* Roll out the hitpoints */ - while (TRUE) - { - /* Roll the hitpoint values */ - for (i = 1; i < PY_MAX_LEVEL; i++) - { - j = randint(p_ptr->hitdie); - player_hp[i] = player_hp[i - 1] + j; - } - - /* XXX Could also require acceptable "mid-level" hitpoints */ - - /* Require "valid" hitpoints at highest level */ - if (player_hp[PY_MAX_LEVEL - 1] < min_value) continue; - if (player_hp[PY_MAX_LEVEL - 1] > max_value) continue; - - /* Acceptable */ - break; - } - - p_ptr->tactic = 4; - p_ptr->movement = 4; -} - - -/* - * Get the racial history, and social class, using the "history charts". - */ -static void get_history(void) -{ - int i, n, chart, roll, social_class; - - char *s, *t; - - char buf[240]; - - - /* Clear the previous history strings */ - for (i = 0; i < 4; i++) history[i][0] = '\0'; - - /* Clear the history text */ - buf[0] = '\0'; - - /* Initial social class */ - social_class = randint(4); - - /* Starting place */ - chart = rp_ptr->chart; - - /* Process the history */ - while (chart) - { - /* Start over */ - i = 0; - - /* Roll for nobility */ - roll = randint(100); - - - /* Access the proper entry in the table */ - while ((chart != bg[i].chart) || (roll > bg[i].roll)) i++; - - /* Acquire the textual history */ - (void)strcat(buf, bg[i].info + rp_text); - - /* Add in the social class */ - social_class += (int)(bg[i].bonus) - 50; - - /* Enter the next chart */ - chart = bg[i].next; - } - - - - /* Verify social class */ - if (social_class > 100) social_class = 100; - else if (social_class < 1) social_class = 1; - - /* Save the social class */ - p_ptr->sc = social_class; - - - /* Skip leading spaces */ - for (s = buf; *s == ' '; s++) /* loop */; - - /* Get apparent length */ - n = strlen(s); - - /* Kill trailing spaces */ - while ((n > 0) && (s[n - 1] == ' ')) s[--n] = '\0'; - - - /* Start at first line */ - i = 0; - - /* Collect the history */ - while (TRUE) - { - /* Extract remaining length */ - n = strlen(s); - - /* All done */ - if (n < 60) - { - /* Save one line of history */ - strcpy(history[i++], s); - - /* All done */ - break; - } - - /* Find a reasonable break-point */ - for (n = 60; ((n > 0) && (s[n - 1] != ' ')); n--) /* loop */; - - /* Save next location */ - t = s + n; - - /* Wipe trailing spaces */ - while ((n > 0) && (s[n - 1] == ' ')) s[--n] = '\0'; - - /* Save one line of history */ - strcpy(history[i++], s); - - /* Start next line */ - for (s = t; *s == ' '; s++) /* loop */; - } -} - - -/* - * Fill the random_artifacts array with relevant info. - */ -errr init_randart(void) -{ - int i; - - long cost; - - random_artifact* ra_ptr; - - char buf[80]; - - - for (i = 0; i < MAX_RANDARTS; i++) - { - ra_ptr = &random_artifacts[i]; - - strcpy(ra_ptr->name_short, - get_line("rart_s.txt", ANGBAND_DIR_FILE, buf, i)); - strcpy(ra_ptr->name_full, - get_line("rart_f.txt", ANGBAND_DIR_FILE, buf, i)); - - ra_ptr->attr = randint(15); - ra_ptr->activation = rand_int(MAX_T_ACT); - ra_ptr->generated = FALSE; - - cost = randnor(0, 250); - - if (cost < 0) cost = 0; - - ra_ptr->cost = cost; - } - - return 0; -} - - -/* - * A helper function for get_ahw(), also called by polymorph code - */ -void get_height_weight(void) -{ - int h_mean, h_stddev; - - int w_mean, w_stddev; - - - /* Extract mean and standard deviation -- Male */ - if (p_ptr->psex == SEX_MALE) - { - h_mean = rp_ptr->m_b_ht + rmp_ptr->m_b_ht; - h_stddev = rp_ptr->m_m_ht + rmp_ptr->m_m_ht; - - w_mean = rp_ptr->m_b_wt + rmp_ptr->m_b_wt; - w_stddev = rp_ptr->m_m_wt + rmp_ptr->m_m_wt; - } - - /* Female */ - else if (p_ptr->psex == SEX_FEMALE) - { - h_mean = rp_ptr->f_b_ht + rmp_ptr->f_b_ht; - h_stddev = rp_ptr->f_m_ht + rmp_ptr->f_m_ht; - - w_mean = rp_ptr->f_b_wt + rmp_ptr->f_b_wt; - w_stddev = rp_ptr->f_m_wt + rmp_ptr->f_m_wt; - } - - /* Neuter XXX */ - else - { - h_mean = (rp_ptr->m_b_ht + rmp_ptr->m_b_ht + - rp_ptr->f_b_ht + rmp_ptr->f_b_ht) / 2, - h_stddev = (rp_ptr->m_m_ht + rmp_ptr->m_m_ht + - rp_ptr->f_m_ht + rmp_ptr->f_m_ht) / 2; - - w_mean = (rp_ptr->m_b_wt + rmp_ptr->m_b_wt + - rp_ptr->f_b_wt + rmp_ptr->f_b_wt) / 2, - w_stddev = (rp_ptr->m_m_wt + rmp_ptr->m_m_wt + - rp_ptr->f_m_wt + rmp_ptr->f_m_wt) / 2; - } - - /* Calculate height/weight */ - p_ptr->ht = randnor(h_mean, h_stddev); - p_ptr->wt = randnor(w_mean, w_stddev); - - /* Weight/height shouldn't be negative */ - if (p_ptr->ht < 1) p_ptr->ht = 1; - if (p_ptr->wt < 1) p_ptr->wt = 1; -} - - -/* - * Computes character's age, height, and weight - */ -static void get_ahw(void) -{ - /* Calculate the age */ - p_ptr->age = rp_ptr->b_age + rmp_ptr->b_age + - randint(rp_ptr->m_age + rmp_ptr->m_age); - - /* Calculate the height/weight */ - get_height_weight(); -} - - - - -/* - * Get the player's starting money - */ -static void get_money(void) -{ - int i, gold; - - - /* Social Class determines starting gold */ - gold = (p_ptr->sc * 6) + randint(100) + 300; - - /* Process the stats */ - for (i = 0; i < 6; i++) - { - /* Mega-Hack -- reduce gold for high stats */ - if (stat_use[i] >= 18 + 50) gold -= 300; - else if (stat_use[i] >= 18 + 20) gold -= 200; - else if (stat_use[i] > 18) gold -= 150; - else gold -= (stat_use[i] - 8) * 10; - } - - /* Minimum 100 gold */ - if (gold < 100) gold = 100; - - /* Save the gold */ - p_ptr->au = gold; -} - - - -/* - * Display stat values, subset of "put_stats()" - * - * See 'display_player()' for basic method. - */ -static void birth_put_stats(void) -{ - int i, p; - - byte attr; - - char buf[80]; - - - /* Put the stats (and percents) */ - for (i = 0; i < 6; i++) - { - /* Put the stat */ - cnv_stat(p_ptr->stat_use[i], buf); - c_put_str(TERM_L_GREEN, buf, 2 + i, 66); - - /* Put the percent */ - if (stat_match[i]) - { - p = 1000L * stat_match[i] / auto_round; - attr = (p < 100) ? TERM_YELLOW : TERM_L_GREEN; - strnfmt(buf, 80, "%3d.%d%%", p / 10, p % 10); - c_put_str(attr, buf, 2 + i, 73); - } - - /* Never happened */ - else - { - c_put_str(TERM_RED, "(NONE)", 2 + i, 73); - } - } -} - - -/* - * Clear all the global "character" data - */ -static void player_wipe(void) -{ - int i, j; - - - /* Wipe special levels */ - wipe_saved(); - - /* Hack -- zero the struct */ - p_ptr = WIPE(p_ptr, player_type); - - /* Not dead yet */ - p_ptr->lives = 0; - - /* Wipe the history */ - for (i = 0; i < 4; i++) - { - for (j = 0; j < 60; j++) - { - if (j < 59) history[i][j] = ' '; - else history[i][j] = '\0'; - } - } - - /* Wipe the towns */ - for (i = 0; i < max_d_idx; i++) - { - for (j = 0; j < MAX_DUNGEON_DEPTH; j++) - { - special_lvl[j][i] = 0; - } - } - - /* Wipe the towns */ - for (i = max_real_towns + 1; i < max_towns; i++) - { - town_info[i].flags = 0; - } - - /* Wipe the quests */ - for (i = 0; i < MAX_Q_IDX; i++) - { - quest[i].status = QUEST_STATUS_UNTAKEN; - for (j = 0; j < sizeof(quest[i].data)/sizeof(quest[i].data[0]); j++) - { - quest[i].data[j] = 0; - } - } - - /* Wipe the rune spells */ - rune_num = 0; - for (i = 0; i < MAX_RUNES; i++) - { - strcpy(rune_spells[i].name, ""); - rune_spells[i].type = 0; - rune_spells[i].rune2 = 0; - rune_spells[i].mana = 0; - } - - /* No items */ - inven_cnt = 0; - equip_cnt = 0; - - /* Clear the inventory */ - for (i = 0; i < INVEN_TOTAL; i++) - { - object_wipe(&p_ptr->inventory[i]); - } - - /* Generate random artifacts */ - init_randart(); - - /* Start with no artifacts made yet */ - for (i = 0; i < max_a_idx; i++) - { - artifact_type *a_ptr = &a_info[i]; - a_ptr->cur_num = 0; - } - - /* Reset the "objects" */ - for (i = 1; i < max_k_idx; i++) - { - object_kind *k_ptr = &k_info[i]; - - /* Reset "tried" */ - k_ptr->tried = FALSE; - - /* Reset "aware" */ - k_ptr->aware = FALSE; - - /* Reset "know" */ - k_ptr->know = FALSE; - - /* Reset "artifact" */ - k_ptr->artifact = 0; - } - - - /* Reset the "monsters" */ - for (i = 1; i < max_r_idx; i++) - { - monster_race *r_ptr = &r_info[i]; - - /* Hack -- Reset the counter */ - r_ptr->cur_num = 0; - - /* Hack -- Reset the max counter */ - r_ptr->max_num = 100; - - /* Hack -- Reset the max counter */ - if (r_ptr->flags1 & RF1_UNIQUE) r_ptr->max_num = 1; - if (r_ptr->flags3 & RF3_UNIQUE_4) r_ptr->max_num = 4; - - /* Clear player kills */ - r_ptr->r_pkills = 0; - - /* Clear saved flag */ - r_ptr->on_saved = FALSE; - } - - - /* Hack -- Well fed player */ - p_ptr->food = PY_FOOD_FULL - 1; - - /* Wipe the alchemists' recipes */ - for ( i = 0 ; i < 32 ; i++) - alchemist_known_egos[i] = 0; - for ( i = 0 ; i < 6 ; i++) - alchemist_known_artifacts[i] = 0; - alchemist_gained = 0; - - /* Clear "cheat" options */ - cheat_peek = FALSE; - cheat_hear = FALSE; - cheat_room = FALSE; - cheat_xtra = FALSE; - cheat_know = FALSE; - cheat_live = FALSE; - - /* Assume no winning game */ - total_winner = 0; - has_won = FALSE; - - /* Assume no cheating */ - noscore = 0; - wizard = 0; - - /* Assume no innate spells */ - spell_num = 0; - - /* Clear the fate */ - for (i = 0; i < MAX_FATES; i++) - { - fates[i].fate = 0; - } - p_ptr->no_mortal = FALSE; - - /* Player don't have the black breath from the beginning !*/ - p_ptr->black_breath = FALSE; - - /* Default pet command settings */ - p_ptr->pet_follow_distance = 6; - p_ptr->pet_open_doors = FALSE; - p_ptr->pet_pickup_items = FALSE; - - /* Body changing initialisation */ - p_ptr->body_monster = 0; - p_ptr->disembodied = FALSE; - - /* Wipe the bounties */ - total_bounties = 0; - - /* Wipe spells */ - p_ptr->xtra_spells = 0; - - /* Wipe xtra hp */ - p_ptr->hp_mod = 0; - - /* Wipe the monsters */ - wipe_m_list(); - - /* Wipe the doppleganger */ - doppleganger = 0; - - /* Wipe the recall depths */ - for (i = 0; i < max_d_idx; i++) - { - max_dlv[i] = 0; - } - - /* Wipe the known inscription list */ - for (i = 0; i < MAX_INSCRIPTIONS; i++) - { - inscription_info[i].know = FALSE; - } - - /* Wipe the known traps list */ - for (i = 0; i < max_t_idx; i++) - { - t_info[i].known = 0; - t_info[i].ident = FALSE; - } - - /* Reset wild_mode to FALSE */ - p_ptr->wild_mode = FALSE; - p_ptr->old_wild_mode = FALSE; - - /* Initialize allow_one_death */ - p_ptr->allow_one_death = 0; - - p_ptr->loan = p_ptr->loan_time = 0; - - /* Wipe the power list */ - for (i = 0; i < POWER_MAX; i++) - { - p_ptr->powers_mod[i] = 0; - } - - /* No companions killed */ - p_ptr->companion_killed = 0; - - /* Inertia control */ - p_ptr->inertia_controlled_spell = -1; - - /* Automatic stat-gain */ - p_ptr->last_rewarded_level = 1; -} - - -/* Create an object */ -void outfit_obj(int tv, int sv, int pval, int dd, int ds) -{ - object_type forge; - object_type *q_ptr; - - /* Get local object */ - q_ptr = &forge; - q_ptr->pval = 0; - q_ptr->pval2 = 0; - - /* Hack -- Give the player an object */ - object_prep(q_ptr, lookup_kind(tv, sv)); - - if (pval) - q_ptr->pval = pval; - - /* These objects are "storebought" */ - q_ptr->ident |= IDENT_MENTAL; - q_ptr->number = damroll(dd, ds); - - object_aware(q_ptr); - object_known(q_ptr); - (void)inven_carry(q_ptr, FALSE); -} - - -/* - * Give the player an object. - */ -static void player_outfit_object(int qty, int tval, int sval) -{ - object_type forge; - object_type *q_ptr = &forge; - object_prep(q_ptr, lookup_kind(tval, sval)); - q_ptr->number = qty; - object_aware(q_ptr); - object_known(q_ptr); - (void)inven_carry(q_ptr, FALSE); -} - - -/* - * Give player a spell book. - */ -static void player_outfit_spellbook(cptr spell_name) -{ - object_type forge; - object_type *q_ptr = &forge; - object_prep(q_ptr, lookup_kind(TV_BOOK, 255)); - q_ptr->pval = find_spell(spell_name); - q_ptr->ident |= IDENT_MENTAL | IDENT_KNOWN; - inven_carry(q_ptr, FALSE); -} - - -/* - * Init players with some belongings - * - * Having an item makes the player "aware" of its purpose. - */ -static void player_outfit(void) -{ - int i; - cptr class_name = spp_ptr->title + c_name; - cptr subrace_name = rmp_ptr->title + rmp_name; - - /* - * Get an adventurer guide describing a bit of the - * wilderness. - */ - { - /* Hack -- Give the player an adventurer guide */ - player_outfit_object(1, TV_PARCHMENT, 20); - } - - /* - * Provide spell books - */ - if (game_module_idx == MODULE_TOME) - { - if (streq(class_name, "Ranger")) - { - player_outfit_spellbook("Phase Door"); - } - } - if (streq(class_name, "Geomancer")) - { - player_outfit_spellbook("Geyser"); - } - if (streq(class_name, "Priest(Eru)")) - { - player_outfit_spellbook("See the Music"); - } - if (streq(class_name, "Priest(Manwe)")) - { - player_outfit_spellbook("Manwe's Blessing"); - } - if (streq(class_name, "Druid")) - { - player_outfit_spellbook("Charm Animal"); - } - if (streq(class_name, "Dark-Priest")) - { - player_outfit_spellbook("Curse"); - } - if (streq(class_name, "Paladin")) - { - player_outfit_spellbook("Divine Aim"); - } - if (game_module_idx == MODULE_THEME) - { - /* Priests */ - if (streq(class_name, "Stonewright")) - { - player_outfit_spellbook("Firebrand"); - } - if (streq(class_name, "Priest(Varda)")) - { - player_outfit_spellbook("Light of Valinor"); - } - if (streq(class_name, "Priest(Ulmo)")) - { - player_outfit_spellbook("Song of Belegaer"); - } - if (streq(class_name, "Priest(Mandos)")) - { - player_outfit_spellbook("Tears of Luthien"); - } - - /* Dragons */ - if (streq(subrace_name, "Red")) - { - player_outfit_spellbook("Globe of Light"); - } - if (streq(subrace_name, "Black")) - { - player_outfit_spellbook("Geyser"); - } - if (streq(subrace_name, "Green")) - { - player_outfit_spellbook("Noxious Cloud"); - } - if (streq(subrace_name, "Blue")) - { - player_outfit_spellbook("Stone Skin"); - } - if (streq(subrace_name, "White")) - { - player_outfit_spellbook("Sense Monsters"); - } - if (streq(subrace_name, "Ethereal")) - { - player_outfit_spellbook("Recharge"); - } - - /* Demons */ - if (streq(subrace_name, "(Aewrog)")) - { - player_outfit_spellbook("Charm"); - } - if (streq(subrace_name, "(Narrog)")) - { - player_outfit_spellbook("Phase Door"); - } - - /* Peace-mages */ - if (streq(class_name, "Peace-mage")) - { - player_outfit_spellbook("Phase Door"); - } - - /* Wainriders */ - if (streq(class_name, "Wainrider")) - { - player_outfit_spellbook("Curse"); - } - } - - if (streq(class_name, "Mimic")) - { - object_type forge; - object_type *q_ptr = &forge; - - object_prep(q_ptr, lookup_kind(TV_CLOAK, SV_MIMIC_CLOAK)); - q_ptr->pval2 = resolve_mimic_name("Mouse"); - q_ptr->ident |= IDENT_MENTAL | IDENT_KNOWN; - inven_carry(q_ptr, FALSE); - } - - if (game_module_idx == MODULE_THEME) - { - /* Give everyone a scroll of WoR. */ - player_outfit_object(1, TV_SCROLL, SV_SCROLL_WORD_OF_RECALL); - - /* Identify everything in pack. */ - identify_pack_fully(); - } - - if (streq(rmp_ptr->title + rmp_name, "Vampire")) - { - player_gain_corruption(CORRUPT_VAMPIRE_TEETH); - player_gain_corruption(CORRUPT_VAMPIRE_STRENGTH); - player_gain_corruption(CORRUPT_VAMPIRE_VAMPIRE); - } - - process_hooks(HOOK_BIRTH_OBJECTS, "()"); - meta_inertia_control_hook_birth_objects(); - - { - /* Hack -- Give the player some food */ - int qty = (byte)rand_range(3, 7); - player_outfit_object(qty, TV_FOOD, SV_FOOD_RATION); - } - - { - object_type forge; - object_type *q_ptr = &forge; - /* Hack -- Give the player some torches */ - object_prep(q_ptr, lookup_kind(TV_LITE, SV_LITE_TORCH)); - q_ptr->number = (byte)rand_range(3, 7); - q_ptr->timeout = rand_range(3, 7) * 500; - object_aware(q_ptr); - object_known(q_ptr); - (void)inven_carry(q_ptr, FALSE); - } - - /* Rogues have a better knowledge of traps */ - if (has_ability(AB_TRAPPING)) - { - t_info[TRAP_OF_DAGGER_I].known = randint(50) + 50; - t_info[TRAP_OF_POISON_NEEDLE].known = randint(50) + 50; - t_info[TRAP_OF_FIRE_BOLT].known = randint(50) + 50; - t_info[TRAP_OF_DAGGER_I].ident = TRUE; - t_info[TRAP_OF_POISON_NEEDLE].ident = TRUE; - t_info[TRAP_OF_FIRE_BOLT].ident = TRUE; - - /* Hack -- Give the player a some ammo for the traps */ - object_type forge; - object_type *q_ptr = &forge; - object_prep(q_ptr, lookup_kind(TV_SHOT, SV_AMMO_NORMAL)); - q_ptr->number = (byte)rand_range(5, 15); - object_aware(q_ptr); - object_known(q_ptr); - - /* These objects are "storebought" */ - q_ptr->ident |= IDENT_MENTAL; - - (void)inven_carry(q_ptr, FALSE); - } - - /* Hack -- Give the player some useful objects */ - for (i = 0; i < rp_ptr->obj_num; i++) - outfit_obj(rp_ptr->obj_tval[i], rp_ptr->obj_sval[i], rp_ptr->obj_pval[i], rp_ptr->obj_dd[i], rp_ptr->obj_ds[i]); - for (i = 0; i < rmp_ptr->obj_num; i++) - outfit_obj(rmp_ptr->obj_tval[i], rmp_ptr->obj_sval[i], rmp_ptr->obj_pval[i], rmp_ptr->obj_dd[i], rmp_ptr->obj_ds[i]); - for (i = 0; i < cp_ptr->obj_num; i++) - outfit_obj(cp_ptr->obj_tval[i], cp_ptr->obj_sval[i], cp_ptr->obj_pval[i], cp_ptr->obj_dd[i], cp_ptr->obj_ds[i]); - for (i = 0; i < cp_ptr->spec[p_ptr->pspec].obj_num; i++) - outfit_obj(cp_ptr->spec[p_ptr->pspec].obj_tval[i], cp_ptr->spec[p_ptr->pspec].obj_sval[i], cp_ptr->spec[p_ptr->pspec].obj_pval[i], cp_ptr->spec[p_ptr->pspec].obj_dd[i], cp_ptr->spec[p_ptr->pspec].obj_ds[i]); -} - - -/* Possible number(and layout) or random quests */ -#define MAX_RANDOM_QUESTS_TYPES ((8 * 3) + (8 * 1)) -int random_quests_types[MAX_RANDOM_QUESTS_TYPES] = -{ - 1, 5, 6, 7, 10, 11, 12, 14, /* Princess type */ - 1, 5, 6, 7, 10, 11, 12, 14, /* Princess type */ - 1, 5, 6, 7, 10, 11, 12, 14, /* Princess type */ - 20, 13, 15, 16, 9, 17, 18, 8, /* Hero Sword Quest */ -}; - -/* Enforce OoD monsters until this level */ -#define RQ_LEVEL_CAP 49 - -static void gen_random_quests(int n) -{ - int step, lvl, i, k; - int old_type = dungeon_type; - - /* Factor dlev value by 1000 to keep precision */ - step = (98 * 1000) / n; - - lvl = step / 2; - - quest[QUEST_RANDOM].status = QUEST_STATUS_TAKEN; - - for (i = 0; i < n; i++) - { - monster_race *r_ptr = &r_info[2]; - - int rl = (lvl / 1000) + 1; - - int min_level; - - int tries = 5000; - - random_quest *q_ptr = &random_quests[rl]; - - int j; - - /* Find the appropriate dungeon */ - for (j = 0; j < max_d_idx; j++) - { - dungeon_info_type *d_ptr = &d_info[j]; - - if (!(d_ptr->flags1 & DF1_PRINCIPAL)) continue; - - if ((d_ptr->mindepth <= rl) && (rl <= d_ptr->maxdepth)) - { - dungeon_type = j; - break; - } - } - - q_ptr->type = random_quests_types[rand_int(MAX_RANDOM_QUESTS_TYPES)]; - - /* XXX XXX XXX Try until valid choice is found */ - while (tries) - { - bool_ ok; - - tries--; - - /* Random monster 5 - 10 levels out of depth */ - q_ptr->r_idx = get_mon_num(rl + 4 + randint(6)); - - if (!q_ptr->r_idx) continue; - - r_ptr = &r_info[q_ptr->r_idx]; - - /* Accept only monsters that can be generated */ - if (r_ptr->flags9 & RF9_SPECIAL_GENE) continue; - if (r_ptr->flags9 & RF9_NEVER_GENE) continue; - - /* Accept only monsters that are not breeders */ - if (r_ptr->flags4 & RF4_MULTIPLY) continue; - - /* Forbid joke monsters */ - if (r_ptr->flags8 & RF8_JOKEANGBAND) continue; - - /* Accept only monsters that are not friends */ - if (r_ptr->flags7 & RF7_PET) continue; - - /* Refuse nazguls */ - if (r_ptr->flags7 & RF7_NAZGUL) continue; - - /* Accept only monsters that are not good */ - if (r_ptr->flags3 & RF3_GOOD) continue; - - /* If module says a monster race is friendly, then skip */ - if (modules[game_module_idx].race_status != NULL) - { - s16b *status = (*modules[game_module_idx].race_status)(q_ptr->r_idx); - if ((status != NULL) && (*status >= 0)) - { - continue; - } - } - - /* Assume no explosion attacks */ - ok = TRUE; - - /* Reject monsters with exploding attacks */ - for (k = 0; k < 4; k++) - { - if (r_ptr->blow[k].method == RBM_EXPLODE) ok = FALSE; - } - if (!ok) continue; - - /* No mutliple uniques */ - if ((r_ptr->flags1 & RF1_UNIQUE) && - ((q_ptr->type != 1) || (r_ptr->max_num == -1))) continue; - - /* No single non uniques */ - if ((!(r_ptr->flags1 & RF1_UNIQUE)) && (q_ptr->type == 1)) continue; - - /* Level restriction */ - min_level = (rl > RQ_LEVEL_CAP) ? RQ_LEVEL_CAP : rl; - - /* Accept monsters matching the level restriction */ - if (r_ptr->level > min_level) break; - } - - /* Arg could not find anything ??? */ - if (!tries) - { - if (wizard) - { - message_add(format("Could not find quest monster on lvl %d", rl), TERM_RED); - } - q_ptr->type = 0; - } - else - { - if (r_ptr->flags1 & RF1_UNIQUE) - { - r_ptr->max_num = -1; - } - - q_ptr->done = FALSE; - - if (wizard) - { - message_add(format("Quest for %d on lvl %d", - q_ptr->r_idx, rl), TERM_RED); - } - } - - lvl += step; - } - - dungeon_type = old_type; -} - -int dump_classes(s16b *classes, int sel, u32b *restrictions) -{ - int n = 0; - - char buf[80]; - char *desc; - - cptr str; - - C_MAKE(desc, c_head->text_size, char); - - /* Clean up */ - clear_from(12); - - while (classes[n] != -1) - { - cptr mod = ""; - char p2 = ')', p1 = ' '; - - /* Analyze */ - p_ptr->pclass = classes[n]; - cp_ptr = &class_info[p_ptr->pclass]; - str = cp_ptr->title + c_name; - - if (sel == n) - { - p1 = '['; - p2 = ']'; - } - - /* Display */ - strnfmt(buf, 80, "%c%c%c %s%s", p1, - (n <= 25) ? I2A(n) : I2D(n - 26), p2, str, mod); - - /* Print some more info */ - if (sel == n) - { - strnfmt(desc, c_head->text_size, "%s%s", cp_ptr->desc + c_text, - cp_ptr->flags1 & PR1_EXPERIMENTAL ? "\nEXPERIMENTAL" : ""); - print_desc(desc); - - if (!(restrictions[classes[n] / 32] & BIT(classes[n])) || - cp_ptr->flags1 & PR1_EXPERIMENTAL) - c_put_str(TERM_BLUE, buf, 18 + (n / 4), 1 + 20 * (n % 4)); - else - c_put_str(TERM_L_BLUE, buf, 18 + (n / 4), 1 + 20 * (n % 4)); - } - else - { - if (!(restrictions[classes[n] / 32] & BIT(classes[n])) || - cp_ptr->flags1 & PR1_EXPERIMENTAL) - c_put_str(TERM_SLATE, buf, 18 + (n / 4), 1 + 20 * (n % 4)); - else - put_str(buf, 18 + (n / 4), 1 + 20 * (n % 4)); - } - n++; - } - - C_FREE(desc, c_head->text_size, char); - - return (n); -} - -int dump_specs(int sel) -{ - int n = 0; - - char buf[80]; - char *desc; - - cptr str; - - C_MAKE(desc, c_head->text_size, char); - - /* Clean up */ - clear_from(12); - - for (n = 0; n < MAX_SPEC; n++) - { - char p2 = ')', p1 = ' '; - - /* Found the last one ? */ - if (!class_info[p_ptr->pclass].spec[n].title) break; - - /* Analyze */ - p_ptr->pspec = n; - spp_ptr = &class_info[p_ptr->pclass].spec[p_ptr->pspec]; - str = spp_ptr->title + c_name; - - if (sel == n) - { - p1 = '['; - p2 = ']'; - } - - /* Display */ - strnfmt(buf, 80, "%c%c%c %s", p1, I2A(n), p2, str); - - /* Print some more info */ - if (sel == n) - { - strnfmt(desc, c_head->text_size, "%s%s", spp_ptr->desc + c_text, - spp_ptr->flags1 & PR1_EXPERIMENTAL ? "\nEXPERIMENTAL" : ""); - print_desc(desc); - - if (spp_ptr->flags1 & PR1_EXPERIMENTAL) - c_put_str(TERM_BLUE, buf, 18 + (n / 4), 1 + 20 * (n % 4)); - else - c_put_str(TERM_L_BLUE, buf, 18 + (n / 4), 1 + 20 * (n % 4)); - } - else - { - if (spp_ptr->flags1 & PR1_EXPERIMENTAL) - c_put_str(TERM_SLATE, buf, 18 + (n / 4), 1 + 20 * (n % 4)); - else - put_str(buf, 18 + (n / 4), 1 + 20 * (n % 4)); - } - } - - C_FREE(desc, c_head->text_size, char); - - return (n); -} - -int dump_races(int sel) -{ - int n = 0; - - char buf[80]; - char *desc; - - cptr str; - - C_MAKE(desc, rp_head->text_size, char); - - /* Clean up */ - clear_from(12); - - for (n = 0; n < max_rp_idx; n++) - { - char p2 = ')', p1 = ' '; - - /* Analyze */ - p_ptr->prace = n; - rp_ptr = &race_info[p_ptr->prace]; - str = rp_ptr->title + rp_name; - - if (sel == n) - { - p1 = '['; - p2 = ']'; - } - - /* Display */ - strnfmt(buf, 80, "%c%c%c %s", p1, I2A(n), p2, str); - - /* Print some more info */ - if (sel == n) - { - strnfmt(desc, rp_head->text_size, "%s%s", rp_ptr->desc + rp_text, - rp_ptr->flags1 & PR1_EXPERIMENTAL ? "\nEXPERIMENTAL" : ""); - print_desc(desc); - - if (rp_ptr->flags1 & PR1_EXPERIMENTAL) - c_put_str(TERM_BLUE, buf, 18 + (n / 5), 1 + 15 * (n % 5)); - else - c_put_str(TERM_L_BLUE, buf, 18 + (n / 5), 1 + 15 * (n % 5)); - } - else - { - if (rp_ptr->flags1 & PR1_EXPERIMENTAL) - c_put_str(TERM_SLATE, buf, 18 + (n / 5), 1 + 15 * (n % 5)); - else - put_str(buf, 18 + (n / 5), 1 + 15 * (n % 5)); - } - } - - C_FREE(desc, rp_head->text_size, char); - - return (n); -} - - -int dump_rmods(int sel, int *racem, int max) -{ - int n = 0; - - char buf[80]; - char *desc; - - cptr str; - - C_MAKE(desc, rmp_head->text_size, char); - - /* Clean up */ - clear_from(12); - - /* Dump races */ - for (n = 0; n < max; n++) - { - char p2 = ')', p1 = ' '; - - /* Analyze */ - p_ptr->pracem = racem[n]; - rmp_ptr = &race_mod_info[p_ptr->pracem]; - str = rmp_ptr->title + rmp_name; - - if (sel == n) - { - p1 = '['; - p2 = ']'; - } - - /* Display */ - if (racem[n]) - strnfmt(buf, 80, "%c%c%c %s", p1, I2A(n), p2, str); - else - strnfmt(buf, 80, "%c%c%c Classical", p1, I2A(n), p2); - - /* Print some more info */ - if (sel == n) - { - strnfmt(desc, rmp_head->text_size, "%s%s", rmp_ptr->desc + rmp_text, - rmp_ptr->flags1 & PR1_EXPERIMENTAL ? "\nEXPERIMENTAL" : ""); - print_desc(desc); - - if (rmp_ptr->flags1 & PR1_EXPERIMENTAL) - c_put_str(TERM_BLUE, buf, 18 + (n / 5), 1 + 15 * (n % 5)); - else - c_put_str(TERM_L_BLUE, buf, 18 + (n / 5), 1 + 15 * (n % 5)); - } - else - { - if (rmp_ptr->flags1 & PR1_EXPERIMENTAL) - c_put_str(TERM_SLATE, buf, 18 + (n / 5), 1 + 15 * (n % 5)); - else - put_str(buf, 18 + (n / 5), 1 + 15 * (n % 5)); - } - } - - C_FREE(desc, rmp_head->text_size, char); - - return (n); -} - -int dump_gods(int sel, int *choice, int max) -{ - int i, j; - char buf[80]; - cptr str; - - /* Clean up */ - clear_from(12); - - Term_putstr(5, 17, -1, TERM_WHITE, - "You can choose to worship a god, some class must start with a god."); - - for (i = 0; i < max; i++) - { - char p2 = ')', p1 = ' '; - int n = choice[i]; - deity_type *g_ptr = &deity_info[0]; - - if (!n) str = "No God"; - else - { - g_ptr = &deity_info[n]; - str = g_ptr->name; - } - - if (sel == i) - { - p1 = '['; - p2 = ']'; - } - - /* Display */ - strnfmt(buf, 80, "%c%c%c %s", p1, I2A(i), p2, str); - - /* Print some more info */ - if (sel == i) - { - if (n) - { - /* Display the first four lines of the god description */ - for (j = 0; j < 4; j++) - if (strcmp(g_ptr->desc[j], "")) - print_desc_aux(g_ptr->desc[j], 12 + j, 1); - } - else print_desc("You can begin as an atheist and still convert to a god later."); - - c_put_str(TERM_L_BLUE, buf, 20 + (i / 4), 1 + 20 * (i % 4)); - } - else - { - put_str(buf, 20 + (i / 4), 1 + 20 * (i % 4)); - } - } - - return (max); -} - - -/* Ask questions */ -static bool_ do_quick_start = FALSE; - -static bool_ player_birth_aux_ask() -{ - int i, k, n, v, sel; - - int racem[100], max_racem = 0; - - u32b restrictions[2]; - - cptr str; - - char c; - - char p2 = ')'; - - char buf[200]; - char inp[200]; - - s16b *class_types; - - /*** Intro ***/ - - /* Clear screen */ - Term_clear(); - - /* Title everything */ - put_str("Name :", 2, 1); - put_str("Sex :", 3, 1); - put_str("Race :", 4, 1); - put_str("Class :", 5, 1); - - /* Dump the default name */ - c_put_str(TERM_L_BLUE, player_name, 2, 9); - - - /*** Instructions ***/ - - /* Display some helpful information */ - Term_putstr(5, 8, -1, TERM_WHITE, - "Please answer the following questions. Most of the questions"); - Term_putstr(5, 9, -1, TERM_WHITE, - "display a set of standard answers, and many will also accept"); - Term_putstr(5, 10, -1, TERM_WHITE, - "some special responses, including 'Q' to quit, 'S' to restart,"); - Term_putstr(5, 11, -1, TERM_WHITE, - "and '?' for help. Note that 'Q' and 'S' must be capitalized."); - - - /*** Quick Start ***/ - - if (previous_char.quick_ok) - { - /* Extra info */ - Term_putstr(1, 15, -1, TERM_WHITE, - "Do you want to use the quick start function(same character as your last one)."); - - /* Choose */ - while (1) - { - put_str("Use quick start (y/n)?", 20, 2); - c = inkey(); - if (c == 'Q') quit(NULL); - else if (c == 'S') return (FALSE); - else if ((c == 'y') || (c == 'Y')) - { - do_quick_start = TRUE; - break; - } - else - { - do_quick_start = FALSE; - break; - } - } - } - - /* Clean up */ - clear_from(15); - - /*** Player sex ***/ - - if (do_quick_start) - { - k = previous_char.sex; - } - else - { - /* Extra info */ - Term_putstr(5, 15, -1, TERM_WHITE, - "Your 'sex' does not have any significant gameplay effects."); - - /* Prompt for "Sex" */ - for (n = 0; n < MAX_SEXES; n++) - { - /* Analyze */ - p_ptr->psex = n; - sp_ptr = &sex_info[p_ptr->psex]; - str = sp_ptr->title; - - /* Display */ - strnfmt(buf, 200, "%c%c %s", I2A(n), p2, str); - put_str(buf, 21 + (n / 5), 2 + 15 * (n % 5)); - } - - /* Choose */ - while (1) - { - strnfmt(buf, 200, "Choose a sex (%c-%c), * for random, = for options: ", I2A(0), I2A(n - 1)); - put_str(buf, 20, 2); - c = inkey(); - if (c == 'Q') quit(NULL); - if (c == 'S') return (FALSE); - if (c == '*') - { - k = rand_int(MAX_SEXES); - break; - } - k = (islower(c) ? A2I(c) : -1); - if ((k >= 0) && (k < n)) break; - if (c == '?') do_cmd_help(); - else if (c == '=') - { - screen_save(); - do_cmd_options_aux(6, "Startup Options", FALSE); - screen_load(); - } - else bell(); - } - } - - /* Set sex */ - p_ptr->psex = k; - sp_ptr = &sex_info[p_ptr->psex]; - str = sp_ptr->title; - - /* Display */ - c_put_str(TERM_L_BLUE, str, 3, 9); - - /* Clean up */ - clear_from(15); - - - /*** Player race ***/ - - if (do_quick_start) - { - k = previous_char.race; - } - else - { - /* Only one choice = instant choice */ - if (max_rp_idx == 1) - k = 0; - else - { - /* Extra info */ - Term_putstr(5, 16, -1, TERM_WHITE, - "Your 'race' determines various intrinsic factors and bonuses."); - - /* Dump races */ - sel = 0; - n = dump_races(sel); - - /* Choose */ - while (1) - { - strnfmt(buf, 200, "Choose a race (%c-%c), * for a random choice, = for options, 8/2/4/6 for movement: ", - I2A(0), I2A(max_rp_idx - 1)); - put_str(buf, 17, 2); - - c = inkey(); - if (c == 'Q') quit(NULL); - if (c == 'S') return (FALSE); - if (c == '*') - { - k = rand_int(max_rp_idx); - break; - } - k = (islower(c) ? A2I(c) : -1); - if ((k >= 0) && (k < n)) break; - if (c == '?') - { - help_race(race_info[sel].title + rp_name); - } - else if (c == '=') - { - screen_save(); - do_cmd_options_aux(6, "Startup Options", FALSE); - screen_load(); - } - else if (c == '2') - { - sel += 5; - if (sel >= n) sel %= 5; - dump_races(sel); - } - else if (c == '8') - { - sel -= 5; - if (sel < 0) sel = n - 1 -( ( -sel) % 5); - /* C's modulus operator does not have defined - results for negative first values. Damn. */ - dump_races(sel); - } - else if (c == '6') - { - sel++; - if (sel >= n) sel = 0; - dump_races(sel); - } - else if (c == '4') - { - sel--; - if (sel < 0) sel = n - 1; - dump_races(sel); - } - else if (c == '\r') - { - k = sel; - break; - } - else bell(); - } - } - } - /* Set race */ - p_ptr->prace = k; - rp_ptr = &race_info[p_ptr->prace]; - str = rp_ptr->title + rp_name; - - /* Display */ - c_put_str(TERM_L_BLUE, str, 4, 9); - - /* Get a random name */ - if (!do_quick_start) create_random_name(p_ptr->prace, player_name); - - /* Display */ - c_put_str(TERM_L_BLUE, player_name, 2, 9); - - /* Clean up */ - clear_from(12); - - - /*** Player race mod ***/ - if (do_quick_start) - { - k = previous_char.rmod; - p_ptr->pracem = k; - rmp_ptr = &race_mod_info[p_ptr->pracem]; - } - else - { - /* Only one choice = instant choice */ - if (max_rmp_idx == 1) - k = 0; - else - { - for (n = 0; n < 100; n++) racem[n] = 0; - - max_racem = 0; - for (n = 0; n < max_rmp_idx; n++) - { - /* Analyze */ - p_ptr->pracem = n; - rmp_ptr = &race_mod_info[p_ptr->pracem]; - - /* Must be an ok choice */ - if (!(BIT(p_ptr->prace) & rmp_ptr->choice[p_ptr->prace / 32])) continue; - - /* Ok thats a possibility */ - racem[max_racem++] = n; - } - - /* Ah ! nothing found, lets use the default */ - if (!max_racem) p_ptr->pracem = 0; - /* Only one ? use it */ - else if (max_racem == 1) p_ptr->pracem = racem[0]; - /* We got to ask the player */ - else - { - /* Extra info */ - Term_putstr(5, 15, -1, TERM_WHITE, - "Your 'race modifier' determines various intrinsic factors and bonuses."); - - /* Dump races */ - sel = 0; - n = dump_rmods(sel, racem, max_racem); - - /* Choose */ - while (1) - { - strnfmt(buf, 200, "Choose a race modifier (%c-%c), * for a random choice, = for options: ", - I2A(0), I2A(max_racem - 1)); - put_str(buf, 17, 2); - c = inkey(); - if (c == 'Q') quit(NULL); - if (c == 'S') return (FALSE); - if (c == '*') - { - do - { - k = rand_int(max_racem); - } - while (!(BIT(racem[k]) & rmp_ptr->choice[racem[k] / 32])); - break; - } - else if (c == '?') - { - help_subrace(race_mod_info[racem[sel]].title + rmp_name); - } - - k = (islower(c) ? A2I(c) : -1); - if ((k >= 0) && (k < max_racem) && - (BIT(p_ptr->prace) & race_mod_info[racem[k]].choice[p_ptr->prace / 32])) break; - - else if (c == '=') - { - screen_save(); - do_cmd_options_aux(6, "Startup Options", FALSE); - screen_load(); - } - else if (c == '2') - { - sel += 5; - if (sel >= n) sel = sel - n + 1; - dump_rmods(sel, racem, max_racem); - } - else if (c == '8') - { - sel -= 5; - if (sel < 0) sel = n - 1 + sel; - dump_rmods(sel, racem, max_racem); - } - else if (c == '6') - { - sel++; - if (sel >= n) sel = 0; - dump_rmods(sel, racem, max_racem); - } - else if (c == '4') - { - sel--; - if (sel < 0) sel = n - 1; - dump_rmods(sel, racem, max_racem); - } - else if (c == '\r') - { - k = sel; - break; - } - else bell(); - } - - /* Set race */ - p_ptr->pracem = racem[k]; - } - rmp_ptr = &race_mod_info[p_ptr->pracem]; - - /* Display */ - c_put_str(TERM_L_BLUE, get_player_race_name(p_ptr->prace, p_ptr->pracem), 4, 9); - } - } - - /* Clean up */ - clear_from(12); - - - /*** Player class ***/ - if (do_quick_start) - { - k = previous_char.pclass; - p_ptr->pclass = k; - cp_ptr = &class_info[p_ptr->pclass]; - k = previous_char.spec; - p_ptr->pspec = k; - spp_ptr = &class_info[p_ptr->pclass].spec[p_ptr->pspec]; - } - else - { - int z; - - for (z = 0; z < 2; z++) - restrictions[z] = (rp_ptr->choice[z] | rmp_ptr->pclass[z]) & (~rmp_ptr->mclass[z]); - - if (max_mc_idx > 1) - { - /* Extra info */ - Term_putstr(5, 13, -1, TERM_WHITE, - "Your 'class' determines various intrinsic abilities and bonuses."); - - /* Get a class type */ - for (i = 0; i < max_mc_idx; i++) - c_put_str(meta_class_info[i].color, format("%c) %s", I2A(i), meta_class_info[i].name), 16 + i, 2); - while (1) - { - strnfmt(buf, 200, "Choose a class type (a-%c), * for random, = for options: ", I2A(max_mc_idx - 1)); - put_str(buf, 15, 2); - c = inkey(); - if (c == 'Q') quit(NULL); - if (c == 'S') return (FALSE); - if (c == '*') - { - k = rand_int(max_mc_idx); - break; - } - k = (islower(c) ? A2I(c) : (D2I(c) + 26)); - if ((k >= 0) && (k < max_mc_idx)) break; - if (c == '?') do_cmd_help(); - else if (c == '=') - { - screen_save(); - do_cmd_options_aux(6, "Startup Options", FALSE); - screen_load(); - } - else bell(); - } - } - else - { - k = 0; - } - class_types = meta_class_info[k].classes; - clear_from(15); - - /* Count classes */ - n = 0; - while (class_types[n] != -1) n++; - - /* Only one choice = instant choice */ - if (n == 1) - k = 0; - else - { - /* Dump classes */ - sel = 0; - n = dump_classes(class_types, sel, restrictions); - - /* Get a class */ - while (1) - { - strnfmt(buf, 200, "Choose a class (%c-%c), * for random, = for options, 8/2/4 for up/down/back: ", I2A(0), (n <= 25) ? I2A(n - 1) : I2D(n - 26-1)); - put_str(buf, 15, 2); - c = inkey(); - if (c == 'Q') quit(NULL); - if (c == 'S') return (FALSE); - if (c == '*') - { - k = randint(n) - 1; - break; - } - k = (islower(c) ? A2I(c) : (D2I(c) + 26)); - if ((k >= 0) && (k < n)) break; - if (c == '?') - { - help_class(class_info[class_types[sel]].title + c_name); - } - else if (c == '=') - { - screen_save(); - do_cmd_options_aux(6, "Startup Options", FALSE); - screen_load(); - } - else if (c == '2') - { - sel += 4; - if (sel >= n) sel %= 4; - dump_classes(class_types, sel, restrictions); - } - else if (c == '8') - { - sel -= 4; - if (sel < 0) sel = n - 1 -( ( -sel) % 4); - /* C's modulus operator does not have defined - results for negative first values. Damn. */ - dump_classes(class_types, sel, restrictions); - } - else if (c == '6') - { - sel++; - if (sel >= n) sel = 0; - dump_classes(class_types, sel, restrictions); - } - else if (c == '4') - { - sel--; - if (sel < 0) sel = n - 1; - dump_classes(class_types, sel, restrictions); - } - else if (c == '\r') - { - k = sel; - break; - } - else bell(); - } - } - - /* Set class */ - p_ptr->pclass = class_types[k]; - - /* Choose class spec */ - clear_from(15); - - /* Count choices */ - for (n = 0; n < MAX_SPEC; n++) - { - /* Found the last one ? */ - if (!class_info[p_ptr->pclass].spec[n].title) break; - } - - /* Only one choice = auto choice */ - if (n == 1) - k = 0; - else - { - /* Dump classes spec */ - sel = 0; - n = dump_specs(sel); - - /* Get a class */ - while (1) - { - strnfmt(buf, 200, "Choose a class specialisation (%c-%c), * for random, = for options, 8/2/4/6 for up/down/left/right: ", I2A(0), (n <= 25) ? I2A(n - 1) : I2D(n - 26-1)); - put_str(buf, 15, 2); - c = inkey(); - if (c == 'Q') quit(NULL); - if (c == 'S') return (FALSE); - if (c == '*') - { - k = randint(n) - 1; - break; - } - k = (islower(c) ? A2I(c) : (D2I(c) + 26)); - if ((k >= 0) && (k < n)) break; - if (c == '?') - { - help_class(class_info[p_ptr->pclass].spec[sel].title + c_name); - } - else if (c == '=') - { - screen_save(); - do_cmd_options_aux(6, "Startup Options", FALSE); - screen_load(); - } - else if (c == '2') - { - sel += 4; - if (sel >= n) sel = sel - n + 1; - dump_specs(sel); - } - else if (c == '8') - { - sel -= 4; - if (sel < 0) sel = n - 1 + sel; - dump_specs(sel); - } - else if (c == '6') - { - sel++; - if (sel >= n) sel = 0; - dump_specs(sel); - } - else if (c == '4') - { - sel--; - if (sel < 0) sel = n - 1; - dump_specs(sel); - } - else if (c == '\r') - { - k = sel; - break; - } - else bell(); - } - } - - /* Set class spec */ - p_ptr->pspec = k; - } - cp_ptr = &class_info[p_ptr->pclass]; - spp_ptr = &class_info[p_ptr->pclass].spec[p_ptr->pspec]; - str = spp_ptr->title + c_name; - - /* Display */ - c_put_str(TERM_L_BLUE, str, 5, 9); - - /* Clean up */ - clear_from(15); - - /*** Player god ***/ - if (do_quick_start) - { - k = previous_char.god; - p_ptr->pgod = k; - set_grace(previous_char.grace); - } - else if (PRACE_FLAG(PR1_NO_GOD)) - { - p_ptr->pgod = GOD_NONE; - } - else - { - int choice[MAX_GODS]; - int max = 0; - - /* Get the list of possible gods */ - for (n = 0; n < MAX_GODS; n++) - { - if (god_enabled(&deity_info[n]) && - ((cp_ptr->gods | spp_ptr->gods) & BIT(n))) - { - choice[max++] = n; - } - } - - if (!max) - { - p_ptr->pgod = GOD_NONE; - } - else if (max == 1) - { - p_ptr->pgod = choice[0]; - } - else if (max > 1) - { - sel = 0; - n = dump_gods(sel, choice, max); - - /* Choose */ - while (1) - { - strnfmt(buf, 200, "Choose a god (%c-%c), * for a random choice, " - "= for options, 8/2/4/6 for movement: ", - I2A(0), I2A(max - 1)); - put_str(buf, 19, 2); - - c = inkey(); - if (c == 'Q') quit(NULL); - if (c == 'S') - { - return (FALSE); - } - if (c == '*') - { - k = choice[randint(max) - 1]; - break; - } - k = (islower(c) ? A2I(c) : -1); - if ((k >= 0) && (k < max)) - { - k = choice[k]; - break; - } - if (c == '?') - { - help_god(deity_info[choice[sel]].name); - } - else if (c == '=') - { - screen_save(); - do_cmd_options_aux(6, "Startup Options", FALSE); - screen_load(); - } - else if (c == '2') - { - sel += 4; - if (sel >= n) sel %= 4; - dump_gods(sel, choice, max); - } - else if (c == '8') - { - sel -= 4; - /* C's modulus operator does not have defined - results for negative first values. Damn. */ - if (sel < 0) sel = n - 1 -( ( -sel) % 4); - dump_gods(sel, choice, max); - } - else if (c == '6') - { - sel++; - if (sel >= n) sel = 0; - dump_gods(sel, choice, max); - } - else if (c == '4') - { - sel--; - if (sel < 0) sel = n - 1; - dump_gods(sel, choice, max); - } - else if (c == '\r') - { - k = choice[sel]; - break; - } - else bell(); - } - - /* Set god */ - p_ptr->pgod = k; - p_ptr->grace = 0; - } - - /* A god that like us ? more grace ! */ - if (PRACE_FLAGS(PR1_GOD_FRIEND)) - { - set_grace(200); - } - else - { - set_grace(100); - } - } - - /* Clean up */ - clear_from(12); - - if (!do_quick_start) - { - /* Clear */ - clear_from(15); - - /* */ - if (get_check("Do you want to modify the options")) - { - screen_save(); - do_cmd_options_aux(6, "Startup Options", FALSE); - screen_load(); - } - } - - /* Set birth options: maximize, preserve, sepcial levels and astral */ - p_ptr->maximize = maximize; - p_ptr->preserve = preserve; - p_ptr->special = special_lvls; - p_ptr->astral = (PRACE_FLAG2(PR2_ASTRAL)) ? TRUE : FALSE; - - /* - * A note by pelpel. (remove this please) - * Be it the new Vanilla way (adult vs. birth options) or - * the old one (player_type members), it would be less confusing - * to handle birth-only options in a uniform fashion,the above and - * the following: - * ironman_rooms, - * joke_monsters, - * always_small_level, and - * fate_option - */ - - - /* Set the recall dungeon accordingly */ - dungeon_type = DUNGEON_BASE; - p_ptr->recall_dungeon = dungeon_type; - max_dlv[dungeon_type] = d_info[dungeon_type].mindepth; - - if (p_ptr->astral) - { - /* Somewhere in the misty mountains */ - dungeon_type = DUNGEON_ASTRAL; - p_ptr->wilderness_x = DUNGEON_ASTRAL_WILD_X; - p_ptr->wilderness_y = DUNGEON_ASTRAL_WILD_Y; - } - - /* Clean up */ - clear_from(10); - - /*** User enters number of quests ***/ - /* Heino Vander Sanden and Jimmy De Laet */ - - if (!ironman_rooms) - { - if (do_quick_start) - { - v = previous_char.quests; - } - else - { - /* Extra info */ - Term_putstr(5, 15, -1, TERM_WHITE, - "Select the number of optional random quests you'd like to receive."); - Term_putstr(5, 16, -1, TERM_WHITE, - "If you do not want any optional quests, enter 0."); - - /* Ask the number of additional quests */ - while (TRUE) - { - put_str(format("Number of quests? (0-%u) ", - MAX_RANDOM_QUEST - 1), 20, 2); - - /* Get a the number of additional quest */ - while (TRUE) - { - /* Move the cursor */ - put_str("", 20, 27); - - /* Default */ - strcpy(inp, "20"); - - /* Get a response (or escape) */ - if (!askfor_aux(inp, 2)) inp[0] = '\0'; - if (inp[0] == '*') v = rand_int(MAX_RANDOM_QUEST); - else v = atoi(inp); - - /* Break on valid input */ - if ((v < MAX_RANDOM_QUEST) && ( v >= 0 )) break; - } - break; - } - - /* Clear */ - clear_from(15); - } - } - else - { - /* NO quests for ironman rooms or persistent levels, since they - don't work */ - v = 0; - } - - /* Set the quest monster hook */ - get_mon_num_hook = monster_quest; - - /* Prepare allocation table */ - get_mon_num_prep(); - - /* Generate quests */ - for (i = 0; i < MAX_RANDOM_QUEST; i++) random_quests[i].type = 0; - if (v) gen_random_quests(v); - max_quests = v; - - p_ptr->inside_quest = 0; - - /* Init the plots */ - { - plots[PLOT_MAIN] = QUEST_NECRO; - quest[plots[PLOT_MAIN]].status = QUEST_STATUS_TAKEN; - - plots[PLOT_BREE] = QUEST_THIEVES; - quest[plots[PLOT_BREE]].status = QUEST_STATUS_UNTAKEN; - - plots[PLOT_LORIEN] = QUEST_WOLVES; - quest[plots[PLOT_LORIEN]].status = QUEST_STATUS_UNTAKEN; - - plots[PLOT_GONDOLIN] = QUEST_DRAGONS; - quest[plots[PLOT_GONDOLIN]].status = QUEST_STATUS_UNTAKEN; - - plots[PLOT_MINAS] = QUEST_HAUNTED; - quest[plots[PLOT_MINAS]].status = QUEST_STATUS_UNTAKEN; - - plots[PLOT_KHAZAD] = QUEST_EVIL; - quest[plots[PLOT_KHAZAD]].status = QUEST_STATUS_UNTAKEN; - - plots[PLOT_OTHER] = QUEST_NULL; - } - - quest_random_init_hook(QUEST_RANDOM); - - /* Ok */ - return (TRUE); -} - - - - -/* - * Initial stat costs (initial stats always range from 10 to 18 inclusive). - */ -static const int birth_stat_costs[(18-10) + 1] = -{ - 0, 1, 2, 4, 7, 11, 16, 22, 30 -}; - - -/* - * Helper function for 'player_birth()'. - * - * This function handles "point-based" character creation. - * - * The player selects, for each stat, a value from 10 to 18 (inclusive), - * each costing a certain amount of points (as above), from a pool of 48 - * available points, to which race/class modifiers are then applied. - * - * Each unused point is converted into 100 gold pieces, with a maximum of - * 600 gp at birth. - * - * Taken from V 2.9.0 - */ -static bool_ player_birth_aux_point(void) -{ - int i; - - int row = 3; - - int col = 42; - - int stat = 0; - - int stats[6]; - - int cost; - - char ch; - - char buf[80]; - - int mode = 0; - - - /* Initialize stats */ - for (i = 0; i < 6; i++) - { - /* Initial stats */ - stats[i] = 10; - } - - - /* Roll for base hitpoints */ - get_extra(); - - /* Roll for age/height/weight */ - get_ahw(); - - /* Roll for social class */ - get_history(); - - /*** Generate ***/ - process_hooks(HOOK_BIRTH, "()"); - - /* Get luck */ - p_ptr->luck_base = rp_ptr->luck + rmp_ptr->luck + rand_range( -5, 5); - p_ptr->luck_max = p_ptr->luck_base; - - /* Interact */ - while (1) - { - /* Reset cost */ - cost = 0; - - /* Process stats */ - for (i = 0; i < 6; i++) - { - /* Variable stat maxes */ - if (p_ptr->maximize) - { - /* Reset stats */ - p_ptr->stat_cur[i] = p_ptr->stat_max[i] = stats[i]; - - } - - /* Fixed stat maxes */ - else - { - /* Obtain a "bonus" for "race" and "class" */ - int bonus = rp_ptr->r_adj[i] + cp_ptr->c_adj[i]; - - /* Apply the racial/class bonuses */ - p_ptr->stat_cur[i] = p_ptr->stat_max[i] = - modify_stat_value(stats[i], bonus); - } - - /* Total cost */ - cost += birth_stat_costs[stats[i] - 10]; - } - - /* Restrict cost */ - if (cost > 48) - { - /* Warning */ - bell(); - - /* Reduce stat */ - stats[stat]--; - - /* Recompute costs */ - continue; - } - - /* Gold is inversely proportional to cost */ - p_ptr->au = (100 * (48 - cost)) + 100; - - /* Maximum of 600 gold */ - if (p_ptr->au > 600) p_ptr->au = 600; - - /* Calculate the bonuses and hitpoints */ - p_ptr->update |= (PU_BONUS | PU_HP); - - /* Update stuff */ - update_stuff(); - - /* Fully healed */ - p_ptr->chp = p_ptr->mhp; - - /* Fully rested */ - p_ptr->csp = p_ptr->msp; - - /* Display the player */ - display_player(mode); - - /* Display the costs header */ - put_str("Cost", row - 2, col + 32); - - /* Display the costs */ - for (i = 0; i < 6; i++) - { - /* Display cost */ - strnfmt(buf, 80, "%4d", birth_stat_costs[stats[i] - 10]); - put_str(buf, row + (i - 1), col + 32); - } - - - /* Prompt XXX XXX XXX */ - strnfmt(buf, 80, "Total Cost %2d/48. Use 2/8 to move, 4/6 to modify, ESC to accept.", cost); - prt(buf, 0, 0); - - /* Place cursor just after cost of current stat */ - Term_gotoxy(col + 36, row + stat - 1); - - /* Get key */ - ch = inkey(); - - /* Quit */ - if (ch == 'Q') quit(NULL); - - /* Start over */ - if (ch == 'S') return (FALSE); - - /* Done */ - if (ch == ESCAPE) break; - - /* Prev stat */ - if (ch == '8') - { - stat = (stat + 6 - 1) % 6; - } - - /* Next stat */ - if (ch == '2') - { - stat = (stat + 1) % 6; - } - - /* Decrease stat */ - if ((ch == '4') && (stats[stat] > 10)) - { - stats[stat]--; - } - - /* Increase stat */ - if ((ch == '6') && (stats[stat] < 18)) - { - stats[stat]++; - } - } - - - /* Done */ - return (TRUE); -} - -/* - * Use the autoroller or not to generate a char - */ -static bool_ player_birth_aux_auto() -{ - int i, j, m, v; - - int mode = 0; - - bool_ flag = FALSE; - - bool_ prev = FALSE; - - char c; - - char b1 = '['; - - char b2 = ']'; - - char buf[80]; - - char inp[80]; - - - /* Initialize */ - if (autoroll) - { - int mval[6]; - - - /* Clear fields */ - auto_round = 0L; - last_round = 0L; - - /* Clean up */ - clear_from(10); - - /* Prompt for the minimum stats */ - put_str("Enter minimum attribute for: ", 15, 2); - - /* Output the maximum stats */ - for (i = 0; i < 6; i++) - { - char stat_buf[15]; - - /* Reset the "success" counter */ - stat_match[i] = 0; - - /* Race/Class bonus */ - j = rp_ptr->r_adj[i] + rmp_ptr->r_adj[i] + cp_ptr->c_adj[i]; - - /* Obtain the "maximal" stat */ - m = adjust_stat(17, j, TRUE); - - - /* Save the maximum */ - mval[i] = m; - - /* Extract a textual format */ - cnv_stat(m, stat_buf); - - strnfmt(inp, 80, "(Max of %s):", stat_buf); - - /* Prepare a prompt */ - strnfmt(buf, 80, "%-5s: %-20s", stat_names[i], inp); - - /* Dump the prompt */ - put_str(buf, 16 + i, 5); - } - - /* Input the minimum stats */ - for (i = 0; i < 6; i++) - { - /* Get a minimum stat */ - while (TRUE) - { - char *s; - - /* Move the cursor */ - put_str("", 16 + i, 30); - - /* Default */ - strcpy(inp, ""); - - /* Get a response (or escape) */ - if (!askfor_aux(inp, 8)) inp[0] = '\0'; - - /* Weirdos stat display .. erm .. I mean, original stat display */ - if (!linear_stats) - { - /* Hack -- add a fake slash */ - strcat(inp, "/"); - - /* Hack -- look for the "slash" */ - s = strchr(inp, '/'); - - /* Hack -- Nuke the slash */ - *s++ = '\0'; - - /* Hack -- Extract an input */ - v = atoi(inp) + atoi(s); - } - else - { - int z = atoi(inp); - - if (z <= 18) - v = z; - else - { - int extra = z - 18; - v = 18 + (extra * 10); - } - } - - /* Break on valid input */ - if (v <= mval[i]) break; - } - - /* Save the minimum stat */ - stat_limit[i] = (v > 0) ? v : 0; - } - } - - /* Roll */ - while (TRUE) - { - /* Feedback */ - if (autoroll) - { - Term_clear(); - - put_str("Name :", 2, 1); - put_str("Sex :", 3, 1); - put_str("Race :", 4, 1); - put_str("Class:", 5, 1); - - c_put_str(TERM_L_BLUE, player_name, 2, 9); - c_put_str(TERM_L_BLUE, sp_ptr->title, 3, 9); - strnfmt(buf, 80, "%s", get_player_race_name(p_ptr->prace, p_ptr->pracem)); - c_put_str(TERM_L_BLUE, buf, 4, 9); - c_put_str(TERM_L_BLUE, spp_ptr->title + c_name, 5, 9); - - /* Label stats */ - put_str("STR:", 2 + A_STR, 61); - put_str("INT:", 2 + A_INT, 61); - put_str("WIS:", 2 + A_WIS, 61); - put_str("DEX:", 2 + A_DEX, 61); - put_str("CON:", 2 + A_CON, 61); - put_str("CHR:", 2 + A_CHR, 61); - - /* Note when we started */ - last_round = auto_round; - - /* Indicate the state */ - put_str("(Hit ESC to abort)", 11, 61); - - /* Label count */ - put_str("Round:", 9, 61); - } - - /* Otherwise just get a character */ - else - { - /* Get a new character */ - get_stats(); - } - - /* Auto-roll */ - while (autoroll) - { - bool_ accept = TRUE; - - /* Get a new character */ - get_stats(); - - /* Advance the round */ - auto_round++; - - /* Hack -- Prevent overflow */ - if (auto_round >= 1000000L) break; - - /* Check and count acceptable stats */ - for (i = 0; i < 6; i++) - { - /* This stat is okay */ - if (stat_use[i] >= stat_limit[i]) - { - stat_match[i]++; - } - - /* This stat is not okay */ - else - { - accept = FALSE; - } - } - - /* Break if "happy" */ - if (accept) break; - - /* Take note every 25 rolls */ - flag = (!(auto_round % AUTOROLLER_STEP)); - - /* Update display occasionally */ - if (flag || (auto_round < last_round + 100)) - { - /* Dump data */ - birth_put_stats(); - - /* Dump round */ - put_str(format("%6ld", auto_round), 9, 73); - - /* Make sure they see everything */ - Term_fresh(); - - /* Do not wait for a key */ - inkey_scan = TRUE; - - /* Check for a keypress */ - if (inkey()) break; - } - } - - /* Flush input */ - flush(); - - - /*** Display ***/ - - /* Mode */ - mode = 0; - - /* Roll for base hitpoints */ - get_extra(); - - /* Roll for age/height/weight */ - get_ahw(); - - /* Roll for social class */ - get_history(); - - /* Roll for gold */ - get_money(); - - /*** Generate ***/ - process_hooks(HOOK_BIRTH, "()"); - - /* Input loop */ - while (TRUE) - { - /* Calculate the bonuses and hitpoints */ - p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_BODY); - - /* Update stuff */ - update_stuff(); - - /* Fully healed */ - p_ptr->chp = p_ptr->mhp; - - /* Fully rested */ - p_ptr->csp = p_ptr->msp; - - /* Display the player */ - display_player(mode); - - /* Prepare a prompt (must squeeze everything in) */ - Term_gotoxy(2, 23); - Term_addch(TERM_WHITE, b1); - Term_addstr( -1, TERM_WHITE, "'r' to reroll"); - if (prev) Term_addstr( -1, TERM_WHITE, ", 'p' for prev"); - if (mode) Term_addstr( -1, TERM_WHITE, ", 'h' for Misc."); - else Term_addstr( -1, TERM_WHITE, ", 'h' for History"); - Term_addstr( -1, TERM_WHITE, ", or ESC to accept"); - Term_addch(TERM_WHITE, b2); - - /* Prompt and get a command */ - c = inkey(); - - /* Quit */ - if (c == 'Q') quit(NULL); - - /* Start over */ - if (c == 'S') return (FALSE); - - /* Escape accepts the roll */ - if (c == ESCAPE) break; - - /* Reroll this character */ - if ((c == ' ') || (c == 'r')) break; - - /* Previous character */ - if (prev && (c == 'p')) - { - load_prev_data(TRUE); - continue; - } - - /* Toggle the display */ - if ((c == 'H') || (c == 'h')) - { - mode = ((mode != 0) ? 0 : 1); - continue; - } - - /* Help */ - if (c == '?') - { - do_cmd_help(); - continue; - } - - /* Warning */ - bell(); - } - - /* Are we done? */ - if (c == ESCAPE) break; - - /* Save this for the "previous" character */ - save_prev_data(); - - /* Note that a previous roll exists */ - prev = TRUE; - } - - /* Clear prompt */ - clear_from(23); - - return (TRUE); -} - - -/* - * Helper function for 'player_birth()' - * - * The delay may be reduced, but is recommended to keep players - * from continuously rolling up characters, which can be VERY - * expensive CPU wise. And it cuts down on player stupidity. - */ -static bool_ player_birth_aux() -{ - char c; - - int i, j; - - int y = 0, x = 0; - - char old_history[4][60]; - - /* Ask */ - if (!player_birth_aux_ask()) return (FALSE); - - for (i = 1; i < max_s_idx; i++) - s_info[i].dev = FALSE; - for (i = 1; i < max_s_idx; i++) - { - s32b value = 0, mod = 0; - - compute_skills(&value, &mod, i); - - init_skill(value, mod, i); - - /* Develop only revelant branches */ - if (s_info[i].value || s_info[i].mod) - { - int z = s_info[i].father; - - while (z != -1) - { - s_info[z].dev = TRUE; - z = s_info[z].father; - if (z == 0) - break; - } - } - } - - if (do_quick_start) - { - load_prev_data(FALSE); - - /* Roll for base hitpoints */ - get_extra(); - - /* Calculate the bonuses and hitpoints */ - p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_BODY); - - /* Update stuff */ - update_stuff(); - - /* Fully healed */ - p_ptr->chp = p_ptr->mhp; - - /* Fully rested */ - p_ptr->csp = p_ptr->msp; - } - else - { - /* Point based */ - if (point_based) - { - if (!player_birth_aux_point()) return FALSE; - } - /* Auto-roll */ - else - { - if (!player_birth_aux_auto()) return FALSE; - } - - /* Edit character background */ - for (i = 0; i < 4; i++) - { - strnfmt(old_history[i], 60, "%s", history[i]); - } - /* Turn 0 to space */ - for (i = 0; i < 4; i++) - { - for (j = 0; history[i][j]; j++) /* loop */; - - for (; j < 59; j++) history[i][j] = ' '; - } - display_player(1); - c_put_str(TERM_L_GREEN, "(Character Background - Edit Mode)", 15, 20); - while (TRUE) - { - for (i = 0; i < 4; i++) - { - put_str(history[i], i + 16, 10); - } - c_put_str(TERM_L_BLUE, format("%c", history[y][x]), y + 16, x + 10); - - /* Place cursor just after cost of current stat */ - Term_gotoxy(x + 10, y + 16); - - c = inkey(); - - if (c == '8') - { - y--; - if (y < 0) y = 3; - } - else if (c == '2') - { - y++; - if (y > 3) y = 0; - } - else if (c == '6') - { - x++; - if (x > 59) x = 0; - } - else if (c == '4') - { - x--; - if (x < 0) x = 59; - } - else if (c == '\r') - { - break; - } - else if (c == ESCAPE) - { - for (i = 0; i < 4; i++) - { - strnfmt(history[i], 60, "%s", old_history[i]); - put_str(history[i], i + 16, 10); - } - break; - } - else - { - history[y][x++] = c; - if (x > 58) - { - x = 0; - y++; - if (y > 3) y = 0; - } - } - } - - - /*** Finish up ***/ - - /* Get a name, recolor it, prepare savefile */ - - get_name(); - - - /* Prompt for it */ - prt("['Q' to suicide, 'S' to start over, or ESC to continue]", 23, 10); - - /* Get a key */ - c = inkey(); - - /* Quit */ - if (c == 'Q') quit(NULL); - - /* Start over */ - if (c == 'S') return (FALSE); - } - - /* Save this for the next character */ - previous_char.quick_ok = TRUE; - save_prev_data(); - - /* Accept */ - return (TRUE); -} - - -/* - * Helper function for validate_bg(). - */ -static void validate_bg_aux(int chart, bool_ chart_checked[], char *buf) -{ - char *s; - - int i; - - - /* Assume the chart does not exist */ - bool_ chart_exists = FALSE; - - /* Assume the chart is not complete */ - bool_ chart_complete = FALSE; - - int bg_max = max_bg_idx; - - /* No chart */ - if (!chart) return; - - /* Already saw this chart */ - if (chart_checked[chart]) return; - - /* Build a debug message */ - s = buf + strlen(buf); - - /* XXX XXX XXX */ - (void) strnfmt(s, -1, "%d --> ", chart); - - /* Check each chart */ - for (i = 0; i < bg_max; i++) - { - /* Require same chart */ - if (bg[i].chart != chart) continue; - - /* The chart exists */ - chart_exists = TRUE; - - /* Validate the "next" chart recursively */ - validate_bg_aux(bg[i].next, chart_checked, buf); - - /* Require a terminator */ - if (bg[i].roll != 100) continue; - - /* The chart is complete */ - chart_complete = TRUE; - } - - /* Failed: The chart does not exist */ - if (!chart_exists) - { - quit_fmt("birth.c: bg[] chart %d does not exist\n%s", chart, buf); - } - - /* Failed: The chart is not complete */ - if (!chart_complete) - { - quit_fmt("birth.c: bg[] chart %d is not complete", chart); - } - - /* Remember we saw this chart */ - chart_checked[chart] = TRUE; - - /* Build a debug message */ - *s = 0; -} - - -/* - * Verify that the bg[] table is valid. - */ -static void validate_bg(void) -{ - int i, race; - - bool_ chart_checked[512]; - - char buf[1024]; - - - for (i = 0; i < 512; i++) chart_checked[i] = FALSE; - - /* Check each race */ - for (race = 0; race < max_rp_idx; race++) - { - /* Get the first chart for this race */ - int chart = race_info[race].chart; - - (void) strcpy(buf, ""); - - /* Validate the chart recursively */ - validate_bg_aux(chart, chart_checked, buf); - } -} - -/* - * Initialize a random town - */ -void init_town(int t_idx, int level) -{ - town_type *t_ptr = &town_info[t_idx]; - - /* Mark it as existent */ - t_ptr->flags |= (TOWN_REAL); - - /* Mark it as not found */ - t_ptr->flags &= ~(TOWN_KNOWN); - - /* Generation seed for the town */ - t_ptr->seed = randint(0x10000000); - - /* Total hack and not even used */ - t_ptr->numstores = 8; -} - -/* - * Create a new character. - * - * Note that we may be called with "junk" leftover in the various - * fields, so we must be sure to clear them first. - */ -void player_birth(void) -{ - int i, j, rtown = TOWN_RANDOM; - - /* Validate the bg[] table */ - validate_bg(); - - /* Create a new character */ - while (1) - { - /* Wipe the player */ - player_wipe(); - - /* Roll up a new character */ - if (player_birth_aux()) break; - } - - /* Finish skills */ - p_ptr->skill_points = 0; - p_ptr->skill_last_level = 1; - - recalc_skills(FALSE); - - /* grab level 1 abilities */ - for (i = 0; i < max_ab_idx; i++) - ab_info[i].acquired = FALSE; - apply_level_abilities(1); - - /* Complete the god */ - i = p_ptr->pgod; - p_ptr->pgod = 0; - follow_god(i, TRUE); - - /* Select the default melee type */ - select_default_melee(); - - /* Make a note file if that option is set */ - add_note_type(NOTE_BIRTH); - - /* Note player birth in the message recall */ - message_add(" ", TERM_L_BLUE); - message_add(" ", TERM_L_BLUE); - message_add("====================", TERM_L_BLUE); - message_add(" ", TERM_L_BLUE); - message_add(" ", TERM_L_BLUE); - - /* Hack -- outfit the player */ - player_outfit(); - - /* Initialize random towns in the dungeons */ - for (i = 0; i < max_d_idx; i++) - { - dungeon_info_type *d_ptr = &d_info[i]; - int num = 0, z; - - d_ptr->t_num = 0; - for (z = 0; z < TOWN_DUNGEON; z++) - { - d_ptr->t_idx[z] = 0; - d_ptr->t_level[z] = 0; - } - if (!(d_ptr->flags1 & DF1_RANDOM_TOWNS)) continue; - - /* Can we add a town ? */ - while (magik(TOWN_CHANCE - (num * 10))) - { - int lev; - - d_ptr->t_idx[num] = rtown; - rtown++; - - while (TRUE) - { - int j; - bool_ ok = TRUE; - - lev = rand_range(d_ptr->mindepth, d_ptr->maxdepth - 1); - - /* Be sure it wasnt already used */ - for (j = 0; j < num; j++) - { - if (d_ptr->t_level[j] == lev) ok = FALSE; - } - - /* Ok found one */ - if (ok) break; - } - d_ptr->t_level[num] = lev; - - if (wizard) - { - message_add(format("Random dungeon town: d_idx:%d, lev:%d", i, lev), TERM_WHITE); - } - - /* Create the town */ - init_town(d_ptr->t_idx[num], d_ptr->t_level[num]); - - num++; - - /* No free slots left */ - if (num >= TOWN_DUNGEON) break; - } - - d_ptr->t_num = num; - } - - /* Init the towns */ - for (i = 1; i < max_towns; i++) - { - /* Not destroyed ! yet .. ;) */ - town_info[i].destroyed = FALSE; - - /* Ignore non-existent towns */ - if (!(town_info[i].flags & (TOWN_REAL))) continue; - - create_stores_stock(i); - - /* Init the stores */ - for (j = 0; j < max_st_idx; j++) - { - /* Initialize */ - store_init(i, j); - } - } - - /* Init wilderness seeds */ - for (i = 0; i < max_wild_x; i++) - { - for (j = 0; j < max_wild_y; j++) - { - wild_map[j][i].seed = rand_int(0x10000000); - wild_map[j][i].entrance = 0; - wild_map[j][i].known = FALSE; - } - } - - /* Select bounty monsters. */ - select_bounties(); -} - - - - -char savefile_module[46][80]; -char savefile_names[46][30]; -char savefile_desc[46][80]; -bool_ savefile_alive[46]; -int savefile_idx[46]; - -/* - * Grab all the names from an index - */ -int load_savefile_names() -{ - FILE *fff; - char buf[1024]; - char tmp[50]; - char player_base_save[32]; - int max = 0, fd; - - - /* Build the filename */ - strcpy(tmp, "global.svg"); - path_build(buf, 1024, ANGBAND_DIR_SAVE, tmp); - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - /* Read the file */ - fff = my_fopen(buf, "r"); - - /* Failure */ - if (!fff) return (0); - - - /* Save the current 'player_base' */ - strncpy(player_base_save, player_base, 32); - - - /* - * Parse, use '@' intead of ':' as a separator because it cannot exists - * in savefiles - */ - while (0 == my_fgets(fff, buf, 1024)) - { - int i = 0, start, count; - - /* Check for pre-ToME 2.1.2 file */ - count = 0; - i = 0; - while (buf[i] && buf[i] != '\n') - { - if (buf[i] == '@') - ++count; - ++i; - } - - /* Check module if a current svg file */ - start = 0; - i = 0; - if (count > 1) - { - while (buf[i] != '@') - { - savefile_module[max][i - start] = buf[i]; - i++; - } - savefile_module[max][i] = '\0'; - i++; - } - /* Default to ToME for old files */ - else - { - savefile_module[max][0] = 'T'; - savefile_module[max][1] = 'o'; - savefile_module[max][2] = 'M'; - savefile_module[max][3] = 'E'; - savefile_module[max][4] = '\0'; - } - - if (buf[i] == '0') savefile_alive[max] = FALSE; - else if (buf[i] == '1') savefile_alive[max] = TRUE; - - i++; - start = i; - while (buf[i] != '@') - { - savefile_names[max][i - start] = buf[i]; - i++; - } - savefile_names[max][i - start] = '\0'; - i++; - strcpy(savefile_desc[max], buf + i); - - /* Build platform-dependent savefile name */ - strncpy(player_base, savefile_names[max], 32); - process_player_name(TRUE); - - /* File type is 'SAVE' */ - FILE_TYPE(FILE_TYPE_SAVE); - - /* Try to open the savefile */ - fd = fd_open(savefile, O_RDONLY); - - /* Still existing ? */ - if (fd >= 0) - { - fd_close(fd); - max++; - } - } - - my_fclose(fff); - - /* Restore the values of 'player_base' and 'savefile' */ - strncpy(player_base, player_base_save, 32); - process_player_name(TRUE); - - return (max); -} - - -/* - * Save all the names from an index - */ -void save_savefile_names() -{ - FILE *fff; - char buf[1024]; - char tmp[50]; - int max = load_savefile_names(), i; - - - /* Build the filename */ - strcpy(tmp, "global.svg"); - path_build(buf, 1024, ANGBAND_DIR_SAVE, tmp); - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - /* Read the file */ - fff = my_fopen(buf, "w"); - - /* Failure */ - if (!fff) return; - - /* - * Save, use '@' intead of ':' as a separator because it cannot exists - * in savefiles - */ - fprintf(fff, "%s@%c%s@%s, the %s %s is %s\n", game_module, - (death) ? '0' : '1', player_base, player_name, - get_player_race_name(p_ptr->prace, p_ptr->pracem), - spp_ptr->title + c_name, - (!death) ? "alive" : "dead"); - - for (i = 0; i < max; i++) - { - if (!strcmp(savefile_names[i], player_base)) continue; - fprintf(fff, "%s@%c%s@%s\n", savefile_module[i], - (savefile_alive[i]) ? '1' : '0', savefile_names[i], savefile_desc[i]); - } - - my_fclose(fff); -} - - -static void dump_savefiles(int sel, int max) -{ - int i; - - char buf[40], pre = ' ', post = ')'; - - char ind; - - - for (i = 0; i < max; i++) - { - ind = I2A(i % 26); - if (i >= 26) ind = toupper(ind); - - if (sel == i) - { - pre = '['; - post = ']'; - } - else - { - pre = ' '; - post = ')'; - } - - if (i == 0) strnfmt(buf, 40, "%c%c%c New Character", pre, ind, post); - else if (i == 1) strnfmt(buf, 40, "%c%c%c Load Savefile", pre, ind, post); - else strnfmt(buf, 40, "%c%c%c %s", pre, ind, post, savefile_names[savefile_idx[i - 2]]); - - if (sel == i) - { - if (i >= 2) - { - if (savefile_alive[i - 2]) c_put_str(TERM_L_GREEN, savefile_desc[savefile_idx[i - 2]], 5, 0); - else c_put_str(TERM_L_RED, savefile_desc[savefile_idx[i - 2]], 5, 0); - } - else if (i == 1) c_put_str(TERM_YELLOW, "Load an existing savefile that is not in the list", 5, 0); - else c_put_str(TERM_YELLOW, "Create a new character", 5, 0); - c_put_str(TERM_L_BLUE, buf, 6 + (i / 4), 20 * (i % 4)); - } - else - put_str(buf, 6 + (i / 4), 20 * (i % 4)); - } -} - - -/* Asks for new game or load game */ -bool_ no_begin_screen = FALSE; - -bool_ begin_screen() -{ - int m, k, sel, max; - -savefile_try_again: - sel = 0; - - /* Grab the savefiles */ - max = load_savefile_names(); - - /* Get only the usable savefiles */ - for (k = 0, m = 0; k < max; k++) - { - s32b can_use; - - can_use = module_savefile_loadable(savefile_module[k]); - if (can_use) - { - savefile_idx[m++] = k; - } - } - max = m + 2; - if (max > 2) sel = 2; - - while (TRUE) - { - /* Clear screen */ - Term_clear(); - - /* Let the user choose */ - c_put_str(TERM_YELLOW, format("Welcome to %s! To play you will need a character.", game_module), 1, 10); - put_str("Press 8/2/4/6 to move, Return to select, Backspace to delete a savefile.", 3, 3); - put_str("and Esc to quit.", 4, 32); - - dump_savefiles(sel, max); - - k = inkey(); - - if (k == ESCAPE) - { - quit(NULL); - } - if (k == '6') - { - sel++; - if (sel >= max) sel = 0; - continue; - } - else if (k == '4') - { - sel--; - if (sel < 0) sel = max - 1; - continue; - } - else if (k == '2') - { - sel += 4; - if (sel >= max) sel = sel % max; - continue; - } - else if (k == '8') - { - sel -= 4; - if (sel < 0) sel = (sel + max - 1) % max; - continue; - } - else if (k == '\r') - { - if (sel < 26) k = I2A(sel); - else k = toupper(I2A(sel)); - } - else if (((k == 0x7F) || (k == '\010')) && (sel >= 2)) - { - char player_base_save[32]; - - if (!get_check(format("Really delete '%s'?", savefile_names[savefile_idx[sel - 2]]))) continue; - - /* Save current 'player_base' */ - strncpy(player_base_save, player_base, 32); - - /* Build platform-dependent save file name */ - strncpy(player_base, savefile_names[savefile_idx[sel - 2]], 32); - process_player_name(TRUE); - - /* Remove the savefile */ - fd_kill(savefile); - - /* Restore 'player_base' and 'savefile' */ - strncpy(player_base, player_base_save, 32); - process_player_name(TRUE); - - /* Reload, gods I hate using goto .. */ - goto savefile_try_again; - - continue; - } - - if (k == 'a') - { - /* Display prompt */ - prt("Enter the name of the savefile that will hold this character: ", 23, 0); - - /* Ask the user for a string */ - if (!askfor_aux(player_base, 15)) continue; - - /* Process the player name */ - process_player_name(TRUE); - - return (TRUE); - } - if (k == 'b') - { - /* Display prompt */ - prt("Enter the name of a savefile: ", 23, 0); - - /* Ask the user for a string */ - if (!askfor_aux(player_base, 15)) continue; - - /* Process the player name */ - process_player_name(TRUE); - - return (FALSE); - } - else - { - int x; - - if (islower(k)) x = A2I(k); - else x = A2I(tolower(k)) + 26; - - if ((x < 2) || (x >= max)) continue; - - strnfmt(player_base, 32, "%s", savefile_names[savefile_idx[x - 2]]); - - /* Process the player name */ - process_player_name(TRUE); - - return (FALSE); - } - } - - /* Shouldnt happen */ - return (FALSE); -} diff --git a/src/birth.cc b/src/birth.cc new file mode 100644 index 00000000..8b6ef896 --- /dev/null +++ b/src/birth.cc @@ -0,0 +1,3949 @@ +/* File: birth.c */ + +/* Purpose: create a player character */ + +/* + * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke + * + * This software may be copied and distributed for educational, research, and + * not for profit purposes provided that this copyright and statement are + * included in all such copies. + */ + +#include "angband.h" + +#include "messages.h" +#include "hooks.h" +#include "q_rand.h" + +#include + +/* + * How often the autoroller will update the display and pause + * to check for user interuptions. + * Bigger values will make the autoroller faster, but slower + * system may have problems because the user can't stop the + * autoroller for this number of rolls. + */ +#define AUTOROLLER_STEP 25L + +/* + * Maximum number of tries for selection of a proper quest monster + */ +#define MAX_TRIES 100 + +/* Max quests */ +static byte max_quests = 0; + +/* + * Current stats + */ +static s16b stat_use[6]; + +/* + * Autoroll limit + */ +static s16b stat_limit[6]; + +/* + * Autoroll matches + */ +static s32b stat_match[6]; + +/* + * Autoroll round + */ +static s32b auto_round; + +/* + * Last round + */ +static s32b last_round; + +/* Human */ +static const char *human_syllable1[] = +{ + "Ab", "Ac", "Ad", "Af", "Agr", "Ast", "As", "Al", "Adw", "Adr", "Ar", + "B", "Br", "C", "Cr", "Ch", "Cad", "D", "Dr", "Dw", "Ed", "Eth", "Et", + "Er", "El", "Eow", "F", "Fr", "G", "Gr", "Gw", "Gal", "Gl", "H", "Ha", + "Ib", "Jer", "K", "Ka", "Ked", "L", "Loth", "Lar", "Leg", "M", "Mir", + "N", "Nyd", "Ol", "Oc", "On", "P", "Pr", "R", "Rh", "S", "Sev", "T", + "Tr", "Th", "V", "Y", "Z", "W", "Wic", +}; + +static const char *human_syllable2[] = +{ + "a", "ae", "au", "ao", "are", "ale", "ali", "ay", "ardo", "e", "ei", + "ea", "eri", "era", "ela", "eli", "enda", "erra", "i", "ia", "ie", + "ire", "ira", "ila", "ili", "ira", "igo", "o", "oa", "oi", "oe", + "ore", "u", "y", +}; + +static const char *human_syllable3[] = +{ + "a", "and", "b", "bwyn", "baen", "bard", "c", "ctred", "cred", "ch", + "can", "d", "dan", "don", "der", "dric", "dfrid", "dus", "f", "g", + "gord", "gan", "l", "li", "lgrin", "lin", "lith", "lath", "loth", + "ld", "ldric", "ldan", "m", "mas", "mos", "mar", "mond", "n", + "nydd", "nidd", "nnon", "nwan", "nyth", "nad", "nn", "nnor", "nd", + "p", "r", "ron", "rd", "s", "sh", "seth", "sean", "t", "th", "tha", + "tlan", "trem", "tram", "v", "vudd", "w", "wan", "win", "wyn", "wyr", + "wyr", "wyth", +}; + +/* + * Random Name Generator + * based on a Javascript by Michael Hensley + * "http://geocities.com/timessquare/castle/6274/" + */ +static void create_random_name(int race, char *name) +{ + const char *syl1, *syl2, *syl3; + + int idx; + + + /* Paranoia */ + if (!name) return; + + /* Select the monster type */ + switch (race) + { + /* Create the monster name */ + + /* Use human ones */ + default: + { + idx = rand_int(sizeof(human_syllable1) / sizeof(char *)); + syl1 = human_syllable1[idx]; + idx = rand_int(sizeof(human_syllable2) / sizeof(char *)); + syl2 = human_syllable2[idx]; + idx = rand_int(sizeof(human_syllable3) / sizeof(char *)); + syl3 = human_syllable3[idx]; + + break; + } + } + + /* Concatenate selected syllables */ + strnfmt(name, 32, "%s%s%s", syl1, syl2, syl3); +} + + +void print_desc_aux(cptr txt, int y, int xx) +{ + int i = -1, x = xx; + + + while (txt[++i] != 0) + { + if (txt[i] == '\n') + { + x = xx; + y++; + } + else + { + Term_putch(x++, y, TERM_YELLOW, txt[i]); + } + } +} + +void print_desc(cptr txt) +{ + print_desc_aux(txt, 12, 1); +} + +/* + * Save the current data for later + */ +static void save_prev_data(void) +{ + int i; + + + /*** Save the current data ***/ + + /* Save the data */ + previous_char.sex = p_ptr->psex; + previous_char.race = p_ptr->prace; + previous_char.rmod = p_ptr->pracem; + previous_char.pclass = p_ptr->pclass; + previous_char.spec = p_ptr->pspec; + + previous_char.quests = max_quests; + + previous_char.god = p_ptr->pgod; + previous_char.grace = p_ptr->grace; + + previous_char.age = p_ptr->age; + previous_char.wt = p_ptr->wt; + previous_char.ht = p_ptr->ht; + previous_char.sc = p_ptr->sc; + previous_char.au = p_ptr->au; + + /* Save the stats */ + for (i = 0; i < 6; i++) + { + previous_char.stat[i] = p_ptr->stat_max[i]; + } + previous_char.luck = p_ptr->luck_base; + + /* Save the weapon specialty */ + previous_char.weapon = 0; + + /* Save the history */ + for (i = 0; i < 4; i++) + { + strcpy(previous_char.history[i], history[i]); + } +} + + +/* + * Load the previous data + */ +static void load_prev_data(bool_ save) +{ + int i; + + birther temp; + + + /*** Save the current data ***/ + + /* Save the data */ + temp.age = p_ptr->age; + temp.wt = p_ptr->wt; + temp.ht = p_ptr->ht; + temp.sc = p_ptr->sc; + temp.au = p_ptr->au; + + /* Save the stats */ + for (i = 0; i < 6; i++) + { + temp.stat[i] = p_ptr->stat_max[i]; + } + temp.luck = p_ptr->luck_base; + + /* Save the weapon specialty */ + temp.weapon = 0; + + /* Save the history */ + for (i = 0; i < 4; i++) + { + strcpy(temp.history[i], history[i]); + } + + + /*** Load the previous data ***/ + + /* Load the data */ + p_ptr->age = previous_char.age; + p_ptr->wt = previous_char.wt; + p_ptr->ht = previous_char.ht; + p_ptr->sc = previous_char.sc; + p_ptr->au = previous_char.au; + + /* Load the stats */ + for (i = 0; i < 6; i++) + { + p_ptr->stat_max[i] = previous_char.stat[i]; + p_ptr->stat_cur[i] = previous_char.stat[i]; + } + p_ptr->luck_base = previous_char.luck; + p_ptr->luck_max = previous_char.luck; + + /* Load the history */ + for (i = 0; i < 4; i++) + { + strcpy(history[i], previous_char.history[i]); + } + + + /*** Save the current data ***/ + if (!save) return; + + /* Save the data */ + previous_char.age = temp.age; + previous_char.wt = temp.wt; + previous_char.ht = temp.ht; + previous_char.sc = temp.sc; + previous_char.au = temp.au; + + /* Save the stats */ + for (i = 0; i < 6; i++) + { + previous_char.stat[i] = temp.stat[i]; + } + previous_char.luck = temp.luck; + + /* Save the chaos patron */ + previous_char.chaos_patron = temp.chaos_patron; + + /* Save the weapon specialty */ + previous_char.weapon = temp.weapon; + + /* Save the history */ + for (i = 0; i < 4; i++) + { + strcpy(previous_char.history[i], temp.history[i]); + } +} + + + + +/* + * Returns adjusted stat -JK- Algorithm by -JWT- + * + * auto_roll is boolean and states maximum changes should be used rather + * than random ones to allow specification of higher values to wait for + * + * The "p_ptr->maximize" code is important -BEN- + */ +static int adjust_stat(int value, int amount, int auto_roll) +{ + int i; + + + /* Negative amounts */ + if (amount < 0) + { + /* Apply penalty */ + for (i = 0; i < (0 - amount); i++) + { + if (value >= 18 + 10) + { + value -= 10; + } + else if (value > 18) + { + value = 18; + } + else if (value > 3) + { + value--; + } + } + } + + /* Positive amounts */ + else if (amount > 0) + { + /* Apply reward */ + for (i = 0; i < amount; i++) + { + if (value < 18) + { + value++; + } + else if (p_ptr->maximize) + { + value += 10; + } + else if (value < 18 + 70) + { + value += ((auto_roll ? 15 : randint(15)) + 5); + } + else if (value < 18 + 90) + { + value += ((auto_roll ? 6 : randint(6)) + 2); + } + else if (value < 18 + 100) + { + value++; + } + } + } + + /* Return the result */ + return (value); +} + + + + +/* + * Roll for a characters stats + * + * For efficiency, we include a chunk of "calc_bonuses()". + */ +static void get_stats(void) +{ + int i, j; + + int bonus; + + int dice[18]; + + + /* Roll and verify some stats */ + while (TRUE) + { + /* Roll some dice */ + for (j = i = 0; i < 18; i++) + { + /* Roll the dice */ + dice[i] = randint(3 + i % 3); + + /* Collect the maximum */ + j += dice[i]; + } + + /* + * Verify totals + * + * 57 was 54... I hate 'magic numbers' :< TY + * + * (d3 + d4 + d5) ~= 7.5 (+- 4.5) + * with 5 makes avg. stat value of 12.5 (min 8, max 17) + * + * (d3 + d4 + d5) x 6 ~= 45 (+- 18) + * + * So the original value (still used by Vanilla as of 2.9.3) + * allows (avg - 2)..(avg + 8), while this Z version + * (avg - 2)..(avg + 11). I don't understand what TY meant + * by "magic numbers", but I like big stats :) -- pelpel + * + */ + if ((j > 42) && (j < 57)) break; + } + + /* Acquire the stats */ + for (i = 0; i < 6; i++) + { + /* Extract 5 + 1d3 + 1d4 + 1d5 */ + j = 5 + dice[3 * i] + dice[3 * i + 1] + dice[3 * i + 2]; + + /* Save that value */ + p_ptr->stat_max[i] = j; + + /* Obtain a "bonus" for "race" and "class" */ + bonus = rp_ptr->r_adj[i] + rmp_ptr->r_adj[i] + cp_ptr->c_adj[i]; + + /* Variable stat maxes */ + if (p_ptr->maximize) + { + /* Start fully healed */ + p_ptr->stat_cur[i] = p_ptr->stat_max[i]; + + /* Efficiency -- Apply the racial/class bonuses */ + stat_use[i] = modify_stat_value(p_ptr->stat_max[i], bonus); + } + + /* Fixed stat maxes */ + else + { + /* Apply the bonus to the stat (somewhat randomly) */ + stat_use[i] = adjust_stat(p_ptr->stat_max[i], bonus, FALSE); + + /* Save the resulting stat maximum */ + p_ptr->stat_cur[i] = p_ptr->stat_max[i] = stat_use[i]; + } + + /* No temporary drain (yet...) */ + p_ptr->stat_cnt[i] = 0; + p_ptr->stat_los[i] = 0; + } + + /* Get luck */ + p_ptr->luck_base = rp_ptr->luck + rmp_ptr->luck + rand_range( -5, 5); + p_ptr->luck_max = p_ptr->luck_base; +} + + +/* + * Roll for some info that the auto-roller ignores + */ +static void get_extra(void) +{ + int i, j, min_value, max_value; + + + /* Level one */ + p_ptr->max_plv = p_ptr->lev = 1; + + /* Experience factor */ + p_ptr->expfact = rp_ptr->r_exp + rmp_ptr->r_exp + cp_ptr->c_exp; + + /* Initialize arena and rewards information -KMW- */ + p_ptr->arena_number = 0; + p_ptr->inside_arena = 0; + p_ptr->inside_quest = 0; + p_ptr->exit_bldg = TRUE; /* only used for arena now -KMW- */ + + /* Hitdice */ + p_ptr->hitdie = rp_ptr->r_mhp + rmp_ptr->r_mhp + cp_ptr->c_mhp; + + /* Initial hitpoints */ + p_ptr->mhp = p_ptr->hitdie; + + /* Minimum hitpoints at highest level */ + min_value = (PY_MAX_LEVEL * (p_ptr->hitdie - 1) * 3) / 8; + min_value += PY_MAX_LEVEL; + + /* Maximum hitpoints at highest level */ + max_value = (PY_MAX_LEVEL * (p_ptr->hitdie - 1) * 5) / 8; + max_value += PY_MAX_LEVEL; + + /* Pre-calculate level 1 hitdice */ + player_hp[0] = p_ptr->hitdie; + + /* Roll out the hitpoints */ + while (TRUE) + { + /* Roll the hitpoint values */ + for (i = 1; i < PY_MAX_LEVEL; i++) + { + j = randint(p_ptr->hitdie); + player_hp[i] = player_hp[i - 1] + j; + } + + /* XXX Could also require acceptable "mid-level" hitpoints */ + + /* Require "valid" hitpoints at highest level */ + if (player_hp[PY_MAX_LEVEL - 1] < min_value) continue; + if (player_hp[PY_MAX_LEVEL - 1] > max_value) continue; + + /* Acceptable */ + break; + } + + p_ptr->tactic = 4; + p_ptr->movement = 4; +} + + +/* + * Get the racial history, and social class, using the "history charts". + */ +static void get_history(void) +{ + int i, n, chart, roll, social_class; + + char *s, *t; + + char buf[240]; + + + /* Clear the previous history strings */ + for (i = 0; i < 4; i++) history[i][0] = '\0'; + + /* Clear the history text */ + buf[0] = '\0'; + + /* Initial social class */ + social_class = randint(4); + + /* Starting place */ + chart = rp_ptr->chart; + + /* Process the history */ + while (chart) + { + /* Start over */ + i = 0; + + /* Roll for nobility */ + roll = randint(100); + + + /* Access the proper entry in the table */ + while ((chart != bg[i].chart) || (roll > bg[i].roll)) i++; + + /* Acquire the textual history */ + (void)strcat(buf, bg[i].info + rp_text); + + /* Add in the social class */ + social_class += (int)(bg[i].bonus) - 50; + + /* Enter the next chart */ + chart = bg[i].next; + } + + + + /* Verify social class */ + if (social_class > 100) social_class = 100; + else if (social_class < 1) social_class = 1; + + /* Save the social class */ + p_ptr->sc = social_class; + + + /* Skip leading spaces */ + for (s = buf; *s == ' '; s++) /* loop */; + + /* Get apparent length */ + n = strlen(s); + + /* Kill trailing spaces */ + while ((n > 0) && (s[n - 1] == ' ')) s[--n] = '\0'; + + + /* Start at first line */ + i = 0; + + /* Collect the history */ + while (TRUE) + { + /* Extract remaining length */ + n = strlen(s); + + /* All done */ + if (n < 60) + { + /* Save one line of history */ + strcpy(history[i++], s); + + /* All done */ + break; + } + + /* Find a reasonable break-point */ + for (n = 60; ((n > 0) && (s[n - 1] != ' ')); n--) /* loop */; + + /* Save next location */ + t = s + n; + + /* Wipe trailing spaces */ + while ((n > 0) && (s[n - 1] == ' ')) s[--n] = '\0'; + + /* Save one line of history */ + strcpy(history[i++], s); + + /* Start next line */ + for (s = t; *s == ' '; s++) /* loop */; + } +} + + +/* + * Fill the random_artifacts array with relevant info. + */ +errr init_randart(void) +{ + int i; + + long cost; + + random_artifact* ra_ptr; + + char buf[80]; + + + for (i = 0; i < MAX_RANDARTS; i++) + { + ra_ptr = &random_artifacts[i]; + + strcpy(ra_ptr->name_short, + get_line("rart_s.txt", ANGBAND_DIR_FILE, buf, i)); + strcpy(ra_ptr->name_full, + get_line("rart_f.txt", ANGBAND_DIR_FILE, buf, i)); + + ra_ptr->attr = randint(15); + ra_ptr->activation = rand_int(MAX_T_ACT); + ra_ptr->generated = FALSE; + + cost = randnor(0, 250); + + if (cost < 0) cost = 0; + + ra_ptr->cost = cost; + } + + return 0; +} + + +/* + * A helper function for get_ahw(), also called by polymorph code + */ +void get_height_weight(void) +{ + int h_mean, h_stddev; + + int w_mean, w_stddev; + + + /* Extract mean and standard deviation -- Male */ + if (p_ptr->psex == SEX_MALE) + { + h_mean = rp_ptr->m_b_ht + rmp_ptr->m_b_ht; + h_stddev = rp_ptr->m_m_ht + rmp_ptr->m_m_ht; + + w_mean = rp_ptr->m_b_wt + rmp_ptr->m_b_wt; + w_stddev = rp_ptr->m_m_wt + rmp_ptr->m_m_wt; + } + + /* Female */ + else if (p_ptr->psex == SEX_FEMALE) + { + h_mean = rp_ptr->f_b_ht + rmp_ptr->f_b_ht; + h_stddev = rp_ptr->f_m_ht + rmp_ptr->f_m_ht; + + w_mean = rp_ptr->f_b_wt + rmp_ptr->f_b_wt; + w_stddev = rp_ptr->f_m_wt + rmp_ptr->f_m_wt; + } + + /* Neuter XXX */ + else + { + h_mean = (rp_ptr->m_b_ht + rmp_ptr->m_b_ht + + rp_ptr->f_b_ht + rmp_ptr->f_b_ht) / 2, + h_stddev = (rp_ptr->m_m_ht + rmp_ptr->m_m_ht + + rp_ptr->f_m_ht + rmp_ptr->f_m_ht) / 2; + + w_mean = (rp_ptr->m_b_wt + rmp_ptr->m_b_wt + + rp_ptr->f_b_wt + rmp_ptr->f_b_wt) / 2, + w_stddev = (rp_ptr->m_m_wt + rmp_ptr->m_m_wt + + rp_ptr->f_m_wt + rmp_ptr->f_m_wt) / 2; + } + + /* Calculate height/weight */ + p_ptr->ht = randnor(h_mean, h_stddev); + p_ptr->wt = randnor(w_mean, w_stddev); + + /* Weight/height shouldn't be negative */ + if (p_ptr->ht < 1) p_ptr->ht = 1; + if (p_ptr->wt < 1) p_ptr->wt = 1; +} + + +/* + * Computes character's age, height, and weight + */ +static void get_ahw(void) +{ + /* Calculate the age */ + p_ptr->age = rp_ptr->b_age + rmp_ptr->b_age + + randint(rp_ptr->m_age + rmp_ptr->m_age); + + /* Calculate the height/weight */ + get_height_weight(); +} + + + + +/* + * Get the player's starting money + */ +static void get_money(void) +{ + int i, gold; + + + /* Social Class determines starting gold */ + gold = (p_ptr->sc * 6) + randint(100) + 300; + + /* Process the stats */ + for (i = 0; i < 6; i++) + { + /* Mega-Hack -- reduce gold for high stats */ + if (stat_use[i] >= 18 + 50) gold -= 300; + else if (stat_use[i] >= 18 + 20) gold -= 200; + else if (stat_use[i] > 18) gold -= 150; + else gold -= (stat_use[i] - 8) * 10; + } + + /* Minimum 100 gold */ + if (gold < 100) gold = 100; + + /* Save the gold */ + p_ptr->au = gold; +} + + + +/* + * Display stat values, subset of "put_stats()" + * + * See 'display_player()' for basic method. + */ +static void birth_put_stats(void) +{ + int i, p; + + byte attr; + + char buf[80]; + + + /* Put the stats (and percents) */ + for (i = 0; i < 6; i++) + { + /* Put the stat */ + cnv_stat(p_ptr->stat_use[i], buf); + c_put_str(TERM_L_GREEN, buf, 2 + i, 66); + + /* Put the percent */ + if (stat_match[i]) + { + p = 1000L * stat_match[i] / auto_round; + attr = (p < 100) ? TERM_YELLOW : TERM_L_GREEN; + strnfmt(buf, 80, "%3d.%d%%", p / 10, p % 10); + c_put_str(attr, buf, 2 + i, 73); + } + + /* Never happened */ + else + { + c_put_str(TERM_RED, "(NONE)", 2 + i, 73); + } + } +} + + +/* + * Clear all the global "character" data + */ +static void player_wipe(void) +{ + int i, j; + + + /* Wipe special levels */ + wipe_saved(); + + /* Hack -- zero the struct */ + WIPE(p_ptr, player_type); + + /* Not dead yet */ + p_ptr->lives = 0; + + /* Wipe the history */ + for (i = 0; i < 4; i++) + { + for (j = 0; j < 60; j++) + { + if (j < 59) history[i][j] = ' '; + else history[i][j] = '\0'; + } + } + + /* Wipe the towns */ + for (i = 0; i < max_d_idx; i++) + { + for (j = 0; j < MAX_DUNGEON_DEPTH; j++) + { + special_lvl[j][i] = 0; + } + } + + /* Wipe the towns */ + for (i = max_real_towns + 1; i < max_towns; i++) + { + town_info[i].flags = 0; + } + + /* Wipe the quests */ + for (i = 0; i < MAX_Q_IDX; i++) + { + quest[i].status = QUEST_STATUS_UNTAKEN; + for (j = 0; j < sizeof(quest[i].data)/sizeof(quest[i].data[0]); j++) + { + quest[i].data[j] = 0; + } + } + + /* Wipe the rune spells */ + rune_num = 0; + for (i = 0; i < MAX_RUNES; i++) + { + strcpy(rune_spells[i].name, ""); + rune_spells[i].type = 0; + rune_spells[i].rune2 = 0; + rune_spells[i].mana = 0; + } + + /* No items */ + inven_cnt = 0; + equip_cnt = 0; + + /* Clear the inventory */ + for (i = 0; i < INVEN_TOTAL; i++) + { + object_wipe(&p_ptr->inventory[i]); + } + + /* Generate random artifacts */ + init_randart(); + + /* Start with no artifacts made yet */ + for (i = 0; i < max_a_idx; i++) + { + artifact_type *a_ptr = &a_info[i]; + a_ptr->cur_num = 0; + } + + /* Reset the "objects" */ + for (i = 1; i < max_k_idx; i++) + { + object_kind *k_ptr = &k_info[i]; + + /* Reset "tried" */ + k_ptr->tried = FALSE; + + /* Reset "aware" */ + k_ptr->aware = FALSE; + + /* Reset "know" */ + k_ptr->know = FALSE; + + /* Reset "artifact" */ + k_ptr->artifact = 0; + } + + + /* Reset the "monsters" */ + for (i = 1; i < max_r_idx; i++) + { + monster_race *r_ptr = &r_info[i]; + + /* Hack -- Reset the counter */ + r_ptr->cur_num = 0; + + /* Hack -- Reset the max counter */ + r_ptr->max_num = 100; + + /* Hack -- Reset the max counter */ + if (r_ptr->flags1 & RF1_UNIQUE) r_ptr->max_num = 1; + if (r_ptr->flags3 & RF3_UNIQUE_4) r_ptr->max_num = 4; + + /* Clear player kills */ + r_ptr->r_pkills = 0; + + /* Clear saved flag */ + r_ptr->on_saved = FALSE; + } + + + /* Hack -- Well fed player */ + p_ptr->food = PY_FOOD_FULL - 1; + + /* Wipe the alchemists' recipes */ + for ( i = 0 ; i < 32 ; i++) + alchemist_known_egos[i] = 0; + for ( i = 0 ; i < 6 ; i++) + alchemist_known_artifacts[i] = 0; + alchemist_gained = 0; + + /* Clear "cheat" options */ + cheat_peek = FALSE; + cheat_hear = FALSE; + cheat_room = FALSE; + cheat_xtra = FALSE; + cheat_know = FALSE; + cheat_live = FALSE; + + /* Assume no winning game */ + total_winner = 0; + has_won = FALSE; + + /* Assume no cheating */ + noscore = 0; + wizard = 0; + + /* Assume no innate spells */ + spell_num = 0; + + /* Clear the fate */ + for (i = 0; i < MAX_FATES; i++) + { + fates[i].fate = 0; + } + p_ptr->no_mortal = FALSE; + + /* Player don't have the black breath from the beginning !*/ + p_ptr->black_breath = FALSE; + + /* Default pet command settings */ + p_ptr->pet_follow_distance = 6; + p_ptr->pet_open_doors = FALSE; + p_ptr->pet_pickup_items = FALSE; + + /* Body changing initialisation */ + p_ptr->body_monster = 0; + p_ptr->disembodied = FALSE; + + /* Wipe the bounties */ + total_bounties = 0; + + /* Wipe spells */ + p_ptr->xtra_spells = 0; + + /* Wipe xtra hp */ + p_ptr->hp_mod = 0; + + /* Wipe the monsters */ + wipe_m_list(); + + /* Wipe the doppleganger */ + doppleganger = 0; + + /* Wipe the recall depths */ + for (i = 0; i < max_d_idx; i++) + { + max_dlv[i] = 0; + } + + /* Wipe the known inscription list */ + for (i = 0; i < MAX_INSCRIPTIONS; i++) + { + inscription_info[i].know = FALSE; + } + + /* Wipe the known traps list */ + for (i = 0; i < max_t_idx; i++) + { + t_info[i].known = 0; + t_info[i].ident = FALSE; + } + + /* Reset wild_mode to FALSE */ + p_ptr->wild_mode = FALSE; + p_ptr->old_wild_mode = FALSE; + + /* Initialize allow_one_death */ + p_ptr->allow_one_death = 0; + + p_ptr->loan = p_ptr->loan_time = 0; + + /* Wipe the power list */ + for (i = 0; i < POWER_MAX; i++) + { + p_ptr->powers_mod[i] = 0; + } + + /* No companions killed */ + p_ptr->companion_killed = 0; + + /* Inertia control */ + p_ptr->inertia_controlled_spell = -1; + + /* Automatic stat-gain */ + p_ptr->last_rewarded_level = 1; +} + + +/* Create an object */ +void outfit_obj(int tv, int sv, int pval, int dd, int ds) +{ + object_type forge; + object_type *q_ptr; + + /* Get local object */ + q_ptr = &forge; + q_ptr->pval = 0; + q_ptr->pval2 = 0; + + /* Hack -- Give the player an object */ + object_prep(q_ptr, lookup_kind(tv, sv)); + + if (pval) + q_ptr->pval = pval; + + /* These objects are "storebought" */ + q_ptr->ident |= IDENT_MENTAL; + q_ptr->number = damroll(dd, ds); + + object_aware(q_ptr); + object_known(q_ptr); + (void)inven_carry(q_ptr, FALSE); +} + + +/* + * Give the player an object. + */ +static void player_outfit_object(int qty, int tval, int sval) +{ + object_type forge; + object_type *q_ptr = &forge; + object_prep(q_ptr, lookup_kind(tval, sval)); + q_ptr->number = qty; + object_aware(q_ptr); + object_known(q_ptr); + (void)inven_carry(q_ptr, FALSE); +} + + +/* + * Give player a spell book. + */ +static void player_outfit_spellbook(cptr spell_name) +{ + object_type forge; + object_type *q_ptr = &forge; + object_prep(q_ptr, lookup_kind(TV_BOOK, 255)); + q_ptr->pval = find_spell(spell_name); + q_ptr->ident |= IDENT_MENTAL | IDENT_KNOWN; + inven_carry(q_ptr, FALSE); +} + + +/* + * Init players with some belongings + * + * Having an item makes the player "aware" of its purpose. + */ +static void player_outfit(void) +{ + int i; + cptr class_name = spp_ptr->title + c_name; + cptr subrace_name = rmp_ptr->title + rmp_name; + + /* + * Get an adventurer guide describing a bit of the + * wilderness. + */ + { + /* Hack -- Give the player an adventurer guide */ + player_outfit_object(1, TV_PARCHMENT, 20); + } + + /* + * Provide spell books + */ + if (game_module_idx == MODULE_TOME) + { + if (streq(class_name, "Ranger")) + { + player_outfit_spellbook("Phase Door"); + } + } + if (streq(class_name, "Geomancer")) + { + player_outfit_spellbook("Geyser"); + } + if (streq(class_name, "Priest(Eru)")) + { + player_outfit_spellbook("See the Music"); + } + if (streq(class_name, "Priest(Manwe)")) + { + player_outfit_spellbook("Manwe's Blessing"); + } + if (streq(class_name, "Druid")) + { + player_outfit_spellbook("Charm Animal"); + } + if (streq(class_name, "Dark-Priest")) + { + player_outfit_spellbook("Curse"); + } + if (streq(class_name, "Paladin")) + { + player_outfit_spellbook("Divine Aim"); + } + if (game_module_idx == MODULE_THEME) + { + /* Priests */ + if (streq(class_name, "Stonewright")) + { + player_outfit_spellbook("Firebrand"); + } + if (streq(class_name, "Priest(Varda)")) + { + player_outfit_spellbook("Light of Valinor"); + } + if (streq(class_name, "Priest(Ulmo)")) + { + player_outfit_spellbook("Song of Belegaer"); + } + if (streq(class_name, "Priest(Mandos)")) + { + player_outfit_spellbook("Tears of Luthien"); + } + + /* Dragons */ + if (streq(subrace_name, "Red")) + { + player_outfit_spellbook("Globe of Light"); + } + if (streq(subrace_name, "Black")) + { + player_outfit_spellbook("Geyser"); + } + if (streq(subrace_name, "Green")) + { + player_outfit_spellbook("Noxious Cloud"); + } + if (streq(subrace_name, "Blue")) + { + player_outfit_spellbook("Stone Skin"); + } + if (streq(subrace_name, "White")) + { + player_outfit_spellbook("Sense Monsters"); + } + if (streq(subrace_name, "Ethereal")) + { + player_outfit_spellbook("Recharge"); + } + + /* Demons */ + if (streq(subrace_name, "(Aewrog)")) + { + player_outfit_spellbook("Charm"); + } + if (streq(subrace_name, "(Narrog)")) + { + player_outfit_spellbook("Phase Door"); + } + + /* Peace-mages */ + if (streq(class_name, "Peace-mage")) + { + player_outfit_spellbook("Phase Door"); + } + + /* Wainriders */ + if (streq(class_name, "Wainrider")) + { + player_outfit_spellbook("Curse"); + } + } + + if (streq(class_name, "Mimic")) + { + object_type forge; + object_type *q_ptr = &forge; + + object_prep(q_ptr, lookup_kind(TV_CLOAK, SV_MIMIC_CLOAK)); + q_ptr->pval2 = resolve_mimic_name("Mouse"); + q_ptr->ident |= IDENT_MENTAL | IDENT_KNOWN; + inven_carry(q_ptr, FALSE); + } + + if (game_module_idx == MODULE_THEME) + { + /* Give everyone a scroll of WoR. */ + player_outfit_object(1, TV_SCROLL, SV_SCROLL_WORD_OF_RECALL); + + /* Identify everything in pack. */ + identify_pack_fully(); + } + + if (streq(rmp_ptr->title + rmp_name, "Vampire")) + { + player_gain_corruption(CORRUPT_VAMPIRE_TEETH); + player_gain_corruption(CORRUPT_VAMPIRE_STRENGTH); + player_gain_corruption(CORRUPT_VAMPIRE_VAMPIRE); + } + + process_hooks(HOOK_BIRTH_OBJECTS, "()"); + meta_inertia_control_hook_birth_objects(); + + { + /* Hack -- Give the player some food */ + int qty = (byte)rand_range(3, 7); + player_outfit_object(qty, TV_FOOD, SV_FOOD_RATION); + } + + { + object_type forge; + object_type *q_ptr = &forge; + /* Hack -- Give the player some torches */ + object_prep(q_ptr, lookup_kind(TV_LITE, SV_LITE_TORCH)); + q_ptr->number = (byte)rand_range(3, 7); + q_ptr->timeout = rand_range(3, 7) * 500; + object_aware(q_ptr); + object_known(q_ptr); + (void)inven_carry(q_ptr, FALSE); + } + + /* Rogues have a better knowledge of traps */ + if (has_ability(AB_TRAPPING)) + { + t_info[TRAP_OF_DAGGER_I].known = randint(50) + 50; + t_info[TRAP_OF_POISON_NEEDLE].known = randint(50) + 50; + t_info[TRAP_OF_FIRE_BOLT].known = randint(50) + 50; + t_info[TRAP_OF_DAGGER_I].ident = TRUE; + t_info[TRAP_OF_POISON_NEEDLE].ident = TRUE; + t_info[TRAP_OF_FIRE_BOLT].ident = TRUE; + + /* Hack -- Give the player a some ammo for the traps */ + object_type forge; + object_type *q_ptr = &forge; + object_prep(q_ptr, lookup_kind(TV_SHOT, SV_AMMO_NORMAL)); + q_ptr->number = (byte)rand_range(5, 15); + object_aware(q_ptr); + object_known(q_ptr); + + /* These objects are "storebought" */ + q_ptr->ident |= IDENT_MENTAL; + + (void)inven_carry(q_ptr, FALSE); + } + + /* Hack -- Give the player some useful objects */ + for (i = 0; i < rp_ptr->obj_num; i++) + outfit_obj(rp_ptr->obj_tval[i], rp_ptr->obj_sval[i], rp_ptr->obj_pval[i], rp_ptr->obj_dd[i], rp_ptr->obj_ds[i]); + for (i = 0; i < rmp_ptr->obj_num; i++) + outfit_obj(rmp_ptr->obj_tval[i], rmp_ptr->obj_sval[i], rmp_ptr->obj_pval[i], rmp_ptr->obj_dd[i], rmp_ptr->obj_ds[i]); + for (i = 0; i < cp_ptr->obj_num; i++) + outfit_obj(cp_ptr->obj_tval[i], cp_ptr->obj_sval[i], cp_ptr->obj_pval[i], cp_ptr->obj_dd[i], cp_ptr->obj_ds[i]); + for (i = 0; i < cp_ptr->spec[p_ptr->pspec].obj_num; i++) + outfit_obj(cp_ptr->spec[p_ptr->pspec].obj_tval[i], cp_ptr->spec[p_ptr->pspec].obj_sval[i], cp_ptr->spec[p_ptr->pspec].obj_pval[i], cp_ptr->spec[p_ptr->pspec].obj_dd[i], cp_ptr->spec[p_ptr->pspec].obj_ds[i]); +} + + +/* Possible number(and layout) or random quests */ +#define MAX_RANDOM_QUESTS_TYPES ((8 * 3) + (8 * 1)) +int random_quests_types[MAX_RANDOM_QUESTS_TYPES] = +{ + 1, 5, 6, 7, 10, 11, 12, 14, /* Princess type */ + 1, 5, 6, 7, 10, 11, 12, 14, /* Princess type */ + 1, 5, 6, 7, 10, 11, 12, 14, /* Princess type */ + 20, 13, 15, 16, 9, 17, 18, 8, /* Hero Sword Quest */ +}; + +/* Enforce OoD monsters until this level */ +#define RQ_LEVEL_CAP 49 + +static void gen_random_quests(int n) +{ + int step, lvl, i, k; + int old_type = dungeon_type; + + /* Factor dlev value by 1000 to keep precision */ + step = (98 * 1000) / n; + + lvl = step / 2; + + quest[QUEST_RANDOM].status = QUEST_STATUS_TAKEN; + + for (i = 0; i < n; i++) + { + monster_race *r_ptr = &r_info[2]; + + int rl = (lvl / 1000) + 1; + + int min_level; + + int tries = 5000; + + random_quest *q_ptr = &random_quests[rl]; + + int j; + + /* Find the appropriate dungeon */ + for (j = 0; j < max_d_idx; j++) + { + dungeon_info_type *d_ptr = &d_info[j]; + + if (!(d_ptr->flags1 & DF1_PRINCIPAL)) continue; + + if ((d_ptr->mindepth <= rl) && (rl <= d_ptr->maxdepth)) + { + dungeon_type = j; + break; + } + } + + q_ptr->type = random_quests_types[rand_int(MAX_RANDOM_QUESTS_TYPES)]; + + /* XXX XXX XXX Try until valid choice is found */ + while (tries) + { + bool_ ok; + + tries--; + + /* Random monster 5 - 10 levels out of depth */ + q_ptr->r_idx = get_mon_num(rl + 4 + randint(6)); + + if (!q_ptr->r_idx) continue; + + r_ptr = &r_info[q_ptr->r_idx]; + + /* Accept only monsters that can be generated */ + if (r_ptr->flags9 & RF9_SPECIAL_GENE) continue; + if (r_ptr->flags9 & RF9_NEVER_GENE) continue; + + /* Accept only monsters that are not breeders */ + if (r_ptr->flags4 & RF4_MULTIPLY) continue; + + /* Forbid joke monsters */ + if (r_ptr->flags8 & RF8_JOKEANGBAND) continue; + + /* Accept only monsters that are not friends */ + if (r_ptr->flags7 & RF7_PET) continue; + + /* Refuse nazguls */ + if (r_ptr->flags7 & RF7_NAZGUL) continue; + + /* Accept only monsters that are not good */ + if (r_ptr->flags3 & RF3_GOOD) continue; + + /* If module says a monster race is friendly, then skip */ + if (modules[game_module_idx].race_status != NULL) + { + s16b *status = (*modules[game_module_idx].race_status)(q_ptr->r_idx); + if ((status != NULL) && (*status >= 0)) + { + continue; + } + } + + /* Assume no explosion attacks */ + ok = TRUE; + + /* Reject monsters with exploding attacks */ + for (k = 0; k < 4; k++) + { + if (r_ptr->blow[k].method == RBM_EXPLODE) ok = FALSE; + } + if (!ok) continue; + + /* No mutliple uniques */ + if ((r_ptr->flags1 & RF1_UNIQUE) && + ((q_ptr->type != 1) || (r_ptr->max_num == -1))) continue; + + /* No single non uniques */ + if ((!(r_ptr->flags1 & RF1_UNIQUE)) && (q_ptr->type == 1)) continue; + + /* Level restriction */ + min_level = (rl > RQ_LEVEL_CAP) ? RQ_LEVEL_CAP : rl; + + /* Accept monsters matching the level restriction */ + if (r_ptr->level > min_level) break; + } + + /* Arg could not find anything ??? */ + if (!tries) + { + if (wizard) + { + message_add(format("Could not find quest monster on lvl %d", rl), TERM_RED); + } + q_ptr->type = 0; + } + else + { + if (r_ptr->flags1 & RF1_UNIQUE) + { + r_ptr->max_num = -1; + } + + q_ptr->done = FALSE; + + if (wizard) + { + message_add(format("Quest for %d on lvl %d", + q_ptr->r_idx, rl), TERM_RED); + } + } + + lvl += step; + } + + dungeon_type = old_type; +} + +int dump_classes(s16b *classes, int sel, u32b *restrictions) +{ + int n = 0; + + char buf[80]; + + cptr str; + + /* Clean up */ + clear_from(12); + + while (classes[n] != -1) + { + cptr mod = ""; + char p2 = ')', p1 = ' '; + + /* Analyze */ + p_ptr->pclass = classes[n]; + cp_ptr = &class_info[p_ptr->pclass]; + str = cp_ptr->title + c_name; + + if (sel == n) + { + p1 = '['; + p2 = ']'; + } + + /* Display */ + strnfmt(buf, 80, "%c%c%c %s%s", p1, + (n <= 25) ? I2A(n) : I2D(n - 26), p2, str, mod); + + /* Print some more info */ + if (sel == n) + { + std::string desc; + + desc += (cp_ptr->desc + c_text); + if (cp_ptr->flags1 & PR1_EXPERIMENTAL) + { + desc += "\nEXPERIMENTAL"; + } + + print_desc(desc.c_str()); + + if (!(restrictions[classes[n] / 32] & BIT(classes[n])) || + cp_ptr->flags1 & PR1_EXPERIMENTAL) + c_put_str(TERM_BLUE, buf, 18 + (n / 4), 1 + 20 * (n % 4)); + else + c_put_str(TERM_L_BLUE, buf, 18 + (n / 4), 1 + 20 * (n % 4)); + } + else + { + if (!(restrictions[classes[n] / 32] & BIT(classes[n])) || + cp_ptr->flags1 & PR1_EXPERIMENTAL) + c_put_str(TERM_SLATE, buf, 18 + (n / 4), 1 + 20 * (n % 4)); + else + put_str(buf, 18 + (n / 4), 1 + 20 * (n % 4)); + } + n++; + } + + return (n); +} + +int dump_specs(int sel) +{ + int n = 0; + + char buf[80]; + + cptr str; + + /* Clean up */ + clear_from(12); + + for (n = 0; n < MAX_SPEC; n++) + { + char p2 = ')', p1 = ' '; + + /* Found the last one ? */ + if (!class_info[p_ptr->pclass].spec[n].title) break; + + /* Analyze */ + p_ptr->pspec = n; + spp_ptr = &class_info[p_ptr->pclass].spec[p_ptr->pspec]; + str = spp_ptr->title + c_name; + + if (sel == n) + { + p1 = '['; + p2 = ']'; + } + + /* Display */ + strnfmt(buf, 80, "%c%c%c %s", p1, I2A(n), p2, str); + + /* Print some more info */ + if (sel == n) + { + std::string desc; + + desc += (spp_ptr->desc + c_text); + if (spp_ptr->flags1 & PR1_EXPERIMENTAL) + { + desc += "\nEXPERIMENTAL"; + } + + print_desc(desc.c_str()); + + if (spp_ptr->flags1 & PR1_EXPERIMENTAL) + c_put_str(TERM_BLUE, buf, 18 + (n / 4), 1 + 20 * (n % 4)); + else + c_put_str(TERM_L_BLUE, buf, 18 + (n / 4), 1 + 20 * (n % 4)); + } + else + { + if (spp_ptr->flags1 & PR1_EXPERIMENTAL) + c_put_str(TERM_SLATE, buf, 18 + (n / 4), 1 + 20 * (n % 4)); + else + put_str(buf, 18 + (n / 4), 1 + 20 * (n % 4)); + } + } + + return (n); +} + +int dump_races(int sel) +{ + int n = 0; + + char buf[80]; + + cptr str; + + /* Clean up */ + clear_from(12); + + for (n = 0; n < max_rp_idx; n++) + { + char p2 = ')', p1 = ' '; + + /* Analyze */ + p_ptr->prace = n; + rp_ptr = &race_info[p_ptr->prace]; + str = rp_ptr->title + rp_name; + + if (sel == n) + { + p1 = '['; + p2 = ']'; + } + + /* Display */ + strnfmt(buf, 80, "%c%c%c %s", p1, I2A(n), p2, str); + + /* Print some more info */ + if (sel == n) + { + std::string desc; + + desc += (rp_ptr->desc + rp_text); + if (rp_ptr->flags1 & PR1_EXPERIMENTAL) + { + desc += "\nEXPERIMENTAL"; + } + + print_desc(desc.c_str()); + + if (rp_ptr->flags1 & PR1_EXPERIMENTAL) + c_put_str(TERM_BLUE, buf, 18 + (n / 5), 1 + 15 * (n % 5)); + else + c_put_str(TERM_L_BLUE, buf, 18 + (n / 5), 1 + 15 * (n % 5)); + } + else + { + if (rp_ptr->flags1 & PR1_EXPERIMENTAL) + c_put_str(TERM_SLATE, buf, 18 + (n / 5), 1 + 15 * (n % 5)); + else + put_str(buf, 18 + (n / 5), 1 + 15 * (n % 5)); + } + } + + return (n); +} + + +int dump_rmods(int sel, int *racem, int max) +{ + int n = 0; + + char buf[80]; + + cptr str; + + /* Clean up */ + clear_from(12); + + /* Dump races */ + for (n = 0; n < max; n++) + { + char p2 = ')', p1 = ' '; + + /* Analyze */ + p_ptr->pracem = racem[n]; + rmp_ptr = &race_mod_info[p_ptr->pracem]; + str = rmp_ptr->title + rmp_name; + + if (sel == n) + { + p1 = '['; + p2 = ']'; + } + + /* Display */ + if (racem[n]) + strnfmt(buf, 80, "%c%c%c %s", p1, I2A(n), p2, str); + else + strnfmt(buf, 80, "%c%c%c Classical", p1, I2A(n), p2); + + /* Print some more info */ + if (sel == n) + { + std::string desc; + + desc += (rmp_ptr->desc + rmp_text); + if (rmp_ptr->flags1 & PR1_EXPERIMENTAL) + { + desc += "\nEXPERIMENTAL"; + } + + print_desc(desc.c_str()); + + if (rmp_ptr->flags1 & PR1_EXPERIMENTAL) + c_put_str(TERM_BLUE, buf, 18 + (n / 5), 1 + 15 * (n % 5)); + else + c_put_str(TERM_L_BLUE, buf, 18 + (n / 5), 1 + 15 * (n % 5)); + } + else + { + if (rmp_ptr->flags1 & PR1_EXPERIMENTAL) + c_put_str(TERM_SLATE, buf, 18 + (n / 5), 1 + 15 * (n % 5)); + else + put_str(buf, 18 + (n / 5), 1 + 15 * (n % 5)); + } + } + + return (n); +} + +int dump_gods(int sel, int *choice, int max) +{ + int i, j; + char buf[80]; + cptr str; + + /* Clean up */ + clear_from(12); + + Term_putstr(5, 17, -1, TERM_WHITE, + "You can choose to worship a god, some class must start with a god."); + + for (i = 0; i < max; i++) + { + char p2 = ')', p1 = ' '; + int n = choice[i]; + deity_type *g_ptr = &deity_info[0]; + + if (!n) str = "No God"; + else + { + g_ptr = &deity_info[n]; + str = g_ptr->name; + } + + if (sel == i) + { + p1 = '['; + p2 = ']'; + } + + /* Display */ + strnfmt(buf, 80, "%c%c%c %s", p1, I2A(i), p2, str); + + /* Print some more info */ + if (sel == i) + { + if (n) + { + /* Display the first four lines of the god description */ + for (j = 0; j < 4; j++) + if (strcmp(g_ptr->desc[j], "")) + print_desc_aux(g_ptr->desc[j], 12 + j, 1); + } + else print_desc("You can begin as an atheist and still convert to a god later."); + + c_put_str(TERM_L_BLUE, buf, 20 + (i / 4), 1 + 20 * (i % 4)); + } + else + { + put_str(buf, 20 + (i / 4), 1 + 20 * (i % 4)); + } + } + + return (max); +} + + +/* Ask questions */ +static bool_ do_quick_start = FALSE; + +static bool_ player_birth_aux_ask() +{ + int i, k, n, v, sel; + + int racem[100], max_racem = 0; + + u32b restrictions[2]; + + cptr str; + + char c; + + char p2 = ')'; + + char buf[200]; + char inp[200]; + + s16b *class_types; + + /*** Intro ***/ + + /* Clear screen */ + Term_clear(); + + /* Title everything */ + put_str("Name :", 2, 1); + put_str("Sex :", 3, 1); + put_str("Race :", 4, 1); + put_str("Class :", 5, 1); + + /* Dump the default name */ + c_put_str(TERM_L_BLUE, player_name, 2, 9); + + + /*** Instructions ***/ + + /* Display some helpful information */ + Term_putstr(5, 8, -1, TERM_WHITE, + "Please answer the following questions. Most of the questions"); + Term_putstr(5, 9, -1, TERM_WHITE, + "display a set of standard answers, and many will also accept"); + Term_putstr(5, 10, -1, TERM_WHITE, + "some special responses, including 'Q' to quit, 'S' to restart,"); + Term_putstr(5, 11, -1, TERM_WHITE, + "and '?' for help. Note that 'Q' and 'S' must be capitalized."); + + + /*** Quick Start ***/ + + if (previous_char.quick_ok) + { + /* Extra info */ + Term_putstr(1, 15, -1, TERM_WHITE, + "Do you want to use the quick start function(same character as your last one)."); + + /* Choose */ + while (1) + { + put_str("Use quick start (y/n)?", 20, 2); + c = inkey(); + if (c == 'Q') quit(NULL); + else if (c == 'S') return (FALSE); + else if ((c == 'y') || (c == 'Y')) + { + do_quick_start = TRUE; + break; + } + else + { + do_quick_start = FALSE; + break; + } + } + } + + /* Clean up */ + clear_from(15); + + /*** Player sex ***/ + + if (do_quick_start) + { + k = previous_char.sex; + } + else + { + /* Extra info */ + Term_putstr(5, 15, -1, TERM_WHITE, + "Your 'sex' does not have any significant gameplay effects."); + + /* Prompt for "Sex" */ + for (n = 0; n < MAX_SEXES; n++) + { + /* Analyze */ + p_ptr->psex = n; + sp_ptr = &sex_info[p_ptr->psex]; + str = sp_ptr->title; + + /* Display */ + strnfmt(buf, 200, "%c%c %s", I2A(n), p2, str); + put_str(buf, 21 + (n / 5), 2 + 15 * (n % 5)); + } + + /* Choose */ + while (1) + { + strnfmt(buf, 200, "Choose a sex (%c-%c), * for random, = for options: ", I2A(0), I2A(n - 1)); + put_str(buf, 20, 2); + c = inkey(); + if (c == 'Q') quit(NULL); + if (c == 'S') return (FALSE); + if (c == '*') + { + k = rand_int(MAX_SEXES); + break; + } + k = (islower(c) ? A2I(c) : -1); + if ((k >= 0) && (k < n)) break; + if (c == '?') do_cmd_help(); + else if (c == '=') + { + screen_save(); + do_cmd_options_aux(6, "Startup Options", FALSE); + screen_load(); + } + else bell(); + } + } + + /* Set sex */ + p_ptr->psex = k; + sp_ptr = &sex_info[p_ptr->psex]; + str = sp_ptr->title; + + /* Display */ + c_put_str(TERM_L_BLUE, str, 3, 9); + + /* Clean up */ + clear_from(15); + + + /*** Player race ***/ + + if (do_quick_start) + { + k = previous_char.race; + } + else + { + /* Only one choice = instant choice */ + if (max_rp_idx == 1) + k = 0; + else + { + /* Extra info */ + Term_putstr(5, 16, -1, TERM_WHITE, + "Your 'race' determines various intrinsic factors and bonuses."); + + /* Dump races */ + sel = 0; + n = dump_races(sel); + + /* Choose */ + while (1) + { + strnfmt(buf, 200, "Choose a race (%c-%c), * for a random choice, = for options, 8/2/4/6 for movement: ", + I2A(0), I2A(max_rp_idx - 1)); + put_str(buf, 17, 2); + + c = inkey(); + if (c == 'Q') quit(NULL); + if (c == 'S') return (FALSE); + if (c == '*') + { + k = rand_int(max_rp_idx); + break; + } + k = (islower(c) ? A2I(c) : -1); + if ((k >= 0) && (k < n)) break; + if (c == '?') + { + help_race(race_info[sel].title + rp_name); + } + else if (c == '=') + { + screen_save(); + do_cmd_options_aux(6, "Startup Options", FALSE); + screen_load(); + } + else if (c == '2') + { + sel += 5; + if (sel >= n) sel %= 5; + dump_races(sel); + } + else if (c == '8') + { + sel -= 5; + if (sel < 0) sel = n - 1 -( ( -sel) % 5); + /* C's modulus operator does not have defined + results for negative first values. Damn. */ + dump_races(sel); + } + else if (c == '6') + { + sel++; + if (sel >= n) sel = 0; + dump_races(sel); + } + else if (c == '4') + { + sel--; + if (sel < 0) sel = n - 1; + dump_races(sel); + } + else if (c == '\r') + { + k = sel; + break; + } + else bell(); + } + } + } + /* Set race */ + p_ptr->prace = k; + rp_ptr = &race_info[p_ptr->prace]; + str = rp_ptr->title + rp_name; + + /* Display */ + c_put_str(TERM_L_BLUE, str, 4, 9); + + /* Get a random name */ + if (!do_quick_start) create_random_name(p_ptr->prace, player_name); + + /* Display */ + c_put_str(TERM_L_BLUE, player_name, 2, 9); + + /* Clean up */ + clear_from(12); + + + /*** Player race mod ***/ + if (do_quick_start) + { + k = previous_char.rmod; + p_ptr->pracem = k; + rmp_ptr = &race_mod_info[p_ptr->pracem]; + } + else + { + /* Only one choice = instant choice */ + if (max_rmp_idx == 1) + k = 0; + else + { + for (n = 0; n < 100; n++) racem[n] = 0; + + max_racem = 0; + for (n = 0; n < max_rmp_idx; n++) + { + /* Analyze */ + p_ptr->pracem = n; + rmp_ptr = &race_mod_info[p_ptr->pracem]; + + /* Must be an ok choice */ + if (!(BIT(p_ptr->prace) & rmp_ptr->choice[p_ptr->prace / 32])) continue; + + /* Ok thats a possibility */ + racem[max_racem++] = n; + } + + /* Ah ! nothing found, lets use the default */ + if (!max_racem) p_ptr->pracem = 0; + /* Only one ? use it */ + else if (max_racem == 1) p_ptr->pracem = racem[0]; + /* We got to ask the player */ + else + { + /* Extra info */ + Term_putstr(5, 15, -1, TERM_WHITE, + "Your 'race modifier' determines various intrinsic factors and bonuses."); + + /* Dump races */ + sel = 0; + n = dump_rmods(sel, racem, max_racem); + + /* Choose */ + while (1) + { + strnfmt(buf, 200, "Choose a race modifier (%c-%c), * for a random choice, = for options: ", + I2A(0), I2A(max_racem - 1)); + put_str(buf, 17, 2); + c = inkey(); + if (c == 'Q') quit(NULL); + if (c == 'S') return (FALSE); + if (c == '*') + { + do + { + k = rand_int(max_racem); + } + while (!(BIT(racem[k]) & rmp_ptr->choice[racem[k] / 32])); + break; + } + else if (c == '?') + { + help_subrace(race_mod_info[racem[sel]].title + rmp_name); + } + + k = (islower(c) ? A2I(c) : -1); + if ((k >= 0) && (k < max_racem) && + (BIT(p_ptr->prace) & race_mod_info[racem[k]].choice[p_ptr->prace / 32])) break; + + else if (c == '=') + { + screen_save(); + do_cmd_options_aux(6, "Startup Options", FALSE); + screen_load(); + } + else if (c == '2') + { + sel += 5; + if (sel >= n) sel = sel - n + 1; + dump_rmods(sel, racem, max_racem); + } + else if (c == '8') + { + sel -= 5; + if (sel < 0) sel = n - 1 + sel; + dump_rmods(sel, racem, max_racem); + } + else if (c == '6') + { + sel++; + if (sel >= n) sel = 0; + dump_rmods(sel, racem, max_racem); + } + else if (c == '4') + { + sel--; + if (sel < 0) sel = n - 1; + dump_rmods(sel, racem, max_racem); + } + else if (c == '\r') + { + k = sel; + break; + } + else bell(); + } + + /* Set race */ + p_ptr->pracem = racem[k]; + } + rmp_ptr = &race_mod_info[p_ptr->pracem]; + + /* Display */ + c_put_str(TERM_L_BLUE, get_player_race_name(p_ptr->prace, p_ptr->pracem), 4, 9); + } + } + + /* Clean up */ + clear_from(12); + + + /*** Player class ***/ + if (do_quick_start) + { + k = previous_char.pclass; + p_ptr->pclass = k; + cp_ptr = &class_info[p_ptr->pclass]; + k = previous_char.spec; + p_ptr->pspec = k; + spp_ptr = &class_info[p_ptr->pclass].spec[p_ptr->pspec]; + } + else + { + int z; + + for (z = 0; z < 2; z++) + restrictions[z] = (rp_ptr->choice[z] | rmp_ptr->pclass[z]) & (~rmp_ptr->mclass[z]); + + if (max_mc_idx > 1) + { + /* Extra info */ + Term_putstr(5, 13, -1, TERM_WHITE, + "Your 'class' determines various intrinsic abilities and bonuses."); + + /* Get a class type */ + for (i = 0; i < max_mc_idx; i++) + c_put_str(meta_class_info[i].color, format("%c) %s", I2A(i), meta_class_info[i].name), 16 + i, 2); + while (1) + { + strnfmt(buf, 200, "Choose a class type (a-%c), * for random, = for options: ", I2A(max_mc_idx - 1)); + put_str(buf, 15, 2); + c = inkey(); + if (c == 'Q') quit(NULL); + if (c == 'S') return (FALSE); + if (c == '*') + { + k = rand_int(max_mc_idx); + break; + } + k = (islower(c) ? A2I(c) : (D2I(c) + 26)); + if ((k >= 0) && (k < max_mc_idx)) break; + if (c == '?') do_cmd_help(); + else if (c == '=') + { + screen_save(); + do_cmd_options_aux(6, "Startup Options", FALSE); + screen_load(); + } + else bell(); + } + } + else + { + k = 0; + } + class_types = meta_class_info[k].classes; + clear_from(15); + + /* Count classes */ + n = 0; + while (class_types[n] != -1) n++; + + /* Only one choice = instant choice */ + if (n == 1) + k = 0; + else + { + /* Dump classes */ + sel = 0; + n = dump_classes(class_types, sel, restrictions); + + /* Get a class */ + while (1) + { + strnfmt(buf, 200, "Choose a class (%c-%c), * for random, = for options, 8/2/4 for up/down/back: ", I2A(0), (n <= 25) ? I2A(n - 1) : I2D(n - 26-1)); + put_str(buf, 15, 2); + c = inkey(); + if (c == 'Q') quit(NULL); + if (c == 'S') return (FALSE); + if (c == '*') + { + k = randint(n) - 1; + break; + } + k = (islower(c) ? A2I(c) : (D2I(c) + 26)); + if ((k >= 0) && (k < n)) break; + if (c == '?') + { + help_class(class_info[class_types[sel]].title + c_name); + } + else if (c == '=') + { + screen_save(); + do_cmd_options_aux(6, "Startup Options", FALSE); + screen_load(); + } + else if (c == '2') + { + sel += 4; + if (sel >= n) sel %= 4; + dump_classes(class_types, sel, restrictions); + } + else if (c == '8') + { + sel -= 4; + if (sel < 0) sel = n - 1 -( ( -sel) % 4); + /* C's modulus operator does not have defined + results for negative first values. Damn. */ + dump_classes(class_types, sel, restrictions); + } + else if (c == '6') + { + sel++; + if (sel >= n) sel = 0; + dump_classes(class_types, sel, restrictions); + } + else if (c == '4') + { + sel--; + if (sel < 0) sel = n - 1; + dump_classes(class_types, sel, restrictions); + } + else if (c == '\r') + { + k = sel; + break; + } + else bell(); + } + } + + /* Set class */ + p_ptr->pclass = class_types[k]; + + /* Choose class spec */ + clear_from(15); + + /* Count choices */ + for (n = 0; n < MAX_SPEC; n++) + { + /* Found the last one ? */ + if (!class_info[p_ptr->pclass].spec[n].title) break; + } + + /* Only one choice = auto choice */ + if (n == 1) + k = 0; + else + { + /* Dump classes spec */ + sel = 0; + n = dump_specs(sel); + + /* Get a class */ + while (1) + { + strnfmt(buf, 200, "Choose a class specialisation (%c-%c), * for random, = for options, 8/2/4/6 for up/down/left/right: ", I2A(0), (n <= 25) ? I2A(n - 1) : I2D(n - 26-1)); + put_str(buf, 15, 2); + c = inkey(); + if (c == 'Q') quit(NULL); + if (c == 'S') return (FALSE); + if (c == '*') + { + k = randint(n) - 1; + break; + } + k = (islower(c) ? A2I(c) : (D2I(c) + 26)); + if ((k >= 0) && (k < n)) break; + if (c == '?') + { + help_class(class_info[p_ptr->pclass].spec[sel].title + c_name); + } + else if (c == '=') + { + screen_save(); + do_cmd_options_aux(6, "Startup Options", FALSE); + screen_load(); + } + else if (c == '2') + { + sel += 4; + if (sel >= n) sel = sel - n + 1; + dump_specs(sel); + } + else if (c == '8') + { + sel -= 4; + if (sel < 0) sel = n - 1 + sel; + dump_specs(sel); + } + else if (c == '6') + { + sel++; + if (sel >= n) sel = 0; + dump_specs(sel); + } + else if (c == '4') + { + sel--; + if (sel < 0) sel = n - 1; + dump_specs(sel); + } + else if (c == '\r') + { + k = sel; + break; + } + else bell(); + } + } + + /* Set class spec */ + p_ptr->pspec = k; + } + cp_ptr = &class_info[p_ptr->pclass]; + spp_ptr = &class_info[p_ptr->pclass].spec[p_ptr->pspec]; + str = spp_ptr->title + c_name; + + /* Display */ + c_put_str(TERM_L_BLUE, str, 5, 9); + + /* Clean up */ + clear_from(15); + + /*** Player god ***/ + if (do_quick_start) + { + k = previous_char.god; + p_ptr->pgod = k; + set_grace(previous_char.grace); + } + else if (PRACE_FLAG(PR1_NO_GOD)) + { + p_ptr->pgod = GOD_NONE; + } + else + { + int choice[MAX_GODS]; + int max = 0; + + /* Get the list of possible gods */ + for (n = 0; n < MAX_GODS; n++) + { + if (god_enabled(&deity_info[n]) && + ((cp_ptr->gods | spp_ptr->gods) & BIT(n))) + { + choice[max++] = n; + } + } + + if (!max) + { + p_ptr->pgod = GOD_NONE; + } + else if (max == 1) + { + p_ptr->pgod = choice[0]; + } + else if (max > 1) + { + sel = 0; + n = dump_gods(sel, choice, max); + + /* Choose */ + while (1) + { + strnfmt(buf, 200, "Choose a god (%c-%c), * for a random choice, " + "= for options, 8/2/4/6 for movement: ", + I2A(0), I2A(max - 1)); + put_str(buf, 19, 2); + + c = inkey(); + if (c == 'Q') quit(NULL); + if (c == 'S') + { + return (FALSE); + } + if (c == '*') + { + k = choice[randint(max) - 1]; + break; + } + k = (islower(c) ? A2I(c) : -1); + if ((k >= 0) && (k < max)) + { + k = choice[k]; + break; + } + if (c == '?') + { + help_god(deity_info[choice[sel]].name); + } + else if (c == '=') + { + screen_save(); + do_cmd_options_aux(6, "Startup Options", FALSE); + screen_load(); + } + else if (c == '2') + { + sel += 4; + if (sel >= n) sel %= 4; + dump_gods(sel, choice, max); + } + else if (c == '8') + { + sel -= 4; + /* C's modulus operator does not have defined + results for negative first values. Damn. */ + if (sel < 0) sel = n - 1 -( ( -sel) % 4); + dump_gods(sel, choice, max); + } + else if (c == '6') + { + sel++; + if (sel >= n) sel = 0; + dump_gods(sel, choice, max); + } + else if (c == '4') + { + sel--; + if (sel < 0) sel = n - 1; + dump_gods(sel, choice, max); + } + else if (c == '\r') + { + k = choice[sel]; + break; + } + else bell(); + } + + /* Set god */ + p_ptr->pgod = k; + p_ptr->grace = 0; + } + + /* A god that like us ? more grace ! */ + if (PRACE_FLAGS(PR1_GOD_FRIEND)) + { + set_grace(200); + } + else + { + set_grace(100); + } + } + + /* Clean up */ + clear_from(12); + + if (!do_quick_start) + { + /* Clear */ + clear_from(15); + + /* */ + if (get_check("Do you want to modify the options")) + { + screen_save(); + do_cmd_options_aux(6, "Startup Options", FALSE); + screen_load(); + } + } + + /* Set birth options: maximize, preserve, sepcial levels and astral */ + p_ptr->maximize = maximize; + p_ptr->preserve = preserve; + p_ptr->special = special_lvls; + p_ptr->astral = (PRACE_FLAG2(PR2_ASTRAL)) ? TRUE : FALSE; + + /* + * A note by pelpel. (remove this please) + * Be it the new Vanilla way (adult vs. birth options) or + * the old one (player_type members), it would be less confusing + * to handle birth-only options in a uniform fashion,the above and + * the following: + * ironman_rooms, + * joke_monsters, + * always_small_level, and + * fate_option + */ + + + /* Set the recall dungeon accordingly */ + dungeon_type = DUNGEON_BASE; + p_ptr->recall_dungeon = dungeon_type; + max_dlv[dungeon_type] = d_info[dungeon_type].mindepth; + + if (p_ptr->astral) + { + /* Somewhere in the misty mountains */ + dungeon_type = DUNGEON_ASTRAL; + p_ptr->wilderness_x = DUNGEON_ASTRAL_WILD_X; + p_ptr->wilderness_y = DUNGEON_ASTRAL_WILD_Y; + } + + /* Clean up */ + clear_from(10); + + /*** User enters number of quests ***/ + /* Heino Vander Sanden and Jimmy De Laet */ + + if (!ironman_rooms) + { + if (do_quick_start) + { + v = previous_char.quests; + } + else + { + /* Extra info */ + Term_putstr(5, 15, -1, TERM_WHITE, + "Select the number of optional random quests you'd like to receive."); + Term_putstr(5, 16, -1, TERM_WHITE, + "If you do not want any optional quests, enter 0."); + + /* Ask the number of additional quests */ + while (TRUE) + { + put_str(format("Number of quests? (0-%u) ", + MAX_RANDOM_QUEST - 1), 20, 2); + + /* Get a the number of additional quest */ + while (TRUE) + { + /* Move the cursor */ + put_str("", 20, 27); + + /* Default */ + strcpy(inp, "20"); + + /* Get a response (or escape) */ + if (!askfor_aux(inp, 2)) inp[0] = '\0'; + if (inp[0] == '*') v = rand_int(MAX_RANDOM_QUEST); + else v = atoi(inp); + + /* Break on valid input */ + if ((v < MAX_RANDOM_QUEST) && ( v >= 0 )) break; + } + break; + } + + /* Clear */ + clear_from(15); + } + } + else + { + /* NO quests for ironman rooms or persistent levels, since they + don't work */ + v = 0; + } + + /* Set the quest monster hook */ + get_mon_num_hook = monster_quest; + + /* Prepare allocation table */ + get_mon_num_prep(); + + /* Generate quests */ + for (i = 0; i < MAX_RANDOM_QUEST; i++) random_quests[i].type = 0; + if (v) gen_random_quests(v); + max_quests = v; + + p_ptr->inside_quest = 0; + + /* Init the plots */ + { + plots[PLOT_MAIN] = QUEST_NECRO; + quest[plots[PLOT_MAIN]].status = QUEST_STATUS_TAKEN; + + plots[PLOT_BREE] = QUEST_THIEVES; + quest[plots[PLOT_BREE]].status = QUEST_STATUS_UNTAKEN; + + plots[PLOT_LORIEN] = QUEST_WOLVES; + quest[plots[PLOT_LORIEN]].status = QUEST_STATUS_UNTAKEN; + + plots[PLOT_GONDOLIN] = QUEST_DRAGONS; + quest[plots[PLOT_GONDOLIN]].status = QUEST_STATUS_UNTAKEN; + + plots[PLOT_MINAS] = QUEST_HAUNTED; + quest[plots[PLOT_MINAS]].status = QUEST_STATUS_UNTAKEN; + + plots[PLOT_KHAZAD] = QUEST_EVIL; + quest[plots[PLOT_KHAZAD]].status = QUEST_STATUS_UNTAKEN; + + plots[PLOT_OTHER] = QUEST_NULL; + } + + quest_random_init_hook(QUEST_RANDOM); + + /* Ok */ + return (TRUE); +} + + + + +/* + * Initial stat costs (initial stats always range from 10 to 18 inclusive). + */ +static const int birth_stat_costs[(18-10) + 1] = +{ + 0, 1, 2, 4, 7, 11, 16, 22, 30 +}; + + +/* + * Helper function for 'player_birth()'. + * + * This function handles "point-based" character creation. + * + * The player selects, for each stat, a value from 10 to 18 (inclusive), + * each costing a certain amount of points (as above), from a pool of 48 + * available points, to which race/class modifiers are then applied. + * + * Each unused point is converted into 100 gold pieces, with a maximum of + * 600 gp at birth. + * + * Taken from V 2.9.0 + */ +static bool_ player_birth_aux_point(void) +{ + int i; + + int row = 3; + + int col = 42; + + int stat = 0; + + int stats[6]; + + int cost; + + char ch; + + char buf[80]; + + int mode = 0; + + + /* Initialize stats */ + for (i = 0; i < 6; i++) + { + /* Initial stats */ + stats[i] = 10; + } + + + /* Roll for base hitpoints */ + get_extra(); + + /* Roll for age/height/weight */ + get_ahw(); + + /* Roll for social class */ + get_history(); + + /*** Generate ***/ + process_hooks(HOOK_BIRTH, "()"); + + /* Get luck */ + p_ptr->luck_base = rp_ptr->luck + rmp_ptr->luck + rand_range( -5, 5); + p_ptr->luck_max = p_ptr->luck_base; + + /* Interact */ + while (1) + { + /* Reset cost */ + cost = 0; + + /* Process stats */ + for (i = 0; i < 6; i++) + { + /* Variable stat maxes */ + if (p_ptr->maximize) + { + /* Reset stats */ + p_ptr->stat_cur[i] = p_ptr->stat_max[i] = stats[i]; + + } + + /* Fixed stat maxes */ + else + { + /* Obtain a "bonus" for "race" and "class" */ + int bonus = rp_ptr->r_adj[i] + cp_ptr->c_adj[i]; + + /* Apply the racial/class bonuses */ + p_ptr->stat_cur[i] = p_ptr->stat_max[i] = + modify_stat_value(stats[i], bonus); + } + + /* Total cost */ + cost += birth_stat_costs[stats[i] - 10]; + } + + /* Restrict cost */ + if (cost > 48) + { + /* Warning */ + bell(); + + /* Reduce stat */ + stats[stat]--; + + /* Recompute costs */ + continue; + } + + /* Gold is inversely proportional to cost */ + p_ptr->au = (100 * (48 - cost)) + 100; + + /* Maximum of 600 gold */ + if (p_ptr->au > 600) p_ptr->au = 600; + + /* Calculate the bonuses and hitpoints */ + p_ptr->update |= (PU_BONUS | PU_HP); + + /* Update stuff */ + update_stuff(); + + /* Fully healed */ + p_ptr->chp = p_ptr->mhp; + + /* Fully rested */ + p_ptr->csp = p_ptr->msp; + + /* Display the player */ + display_player(mode); + + /* Display the costs header */ + put_str("Cost", row - 2, col + 32); + + /* Display the costs */ + for (i = 0; i < 6; i++) + { + /* Display cost */ + strnfmt(buf, 80, "%4d", birth_stat_costs[stats[i] - 10]); + put_str(buf, row + (i - 1), col + 32); + } + + + /* Prompt XXX XXX XXX */ + strnfmt(buf, 80, "Total Cost %2d/48. Use 2/8 to move, 4/6 to modify, ESC to accept.", cost); + prt(buf, 0, 0); + + /* Place cursor just after cost of current stat */ + Term_gotoxy(col + 36, row + stat - 1); + + /* Get key */ + ch = inkey(); + + /* Quit */ + if (ch == 'Q') quit(NULL); + + /* Start over */ + if (ch == 'S') return (FALSE); + + /* Done */ + if (ch == ESCAPE) break; + + /* Prev stat */ + if (ch == '8') + { + stat = (stat + 6 - 1) % 6; + } + + /* Next stat */ + if (ch == '2') + { + stat = (stat + 1) % 6; + } + + /* Decrease stat */ + if ((ch == '4') && (stats[stat] > 10)) + { + stats[stat]--; + } + + /* Increase stat */ + if ((ch == '6') && (stats[stat] < 18)) + { + stats[stat]++; + } + } + + + /* Done */ + return (TRUE); +} + +/* + * Use the autoroller or not to generate a char + */ +static bool_ player_birth_aux_auto() +{ + int i, j, m, v; + + int mode = 0; + + bool_ flag = FALSE; + + bool_ prev = FALSE; + + char c; + + char b1 = '['; + + char b2 = ']'; + + char buf[80]; + + char inp[80]; + + + /* Initialize */ + if (autoroll) + { + int mval[6]; + + + /* Clear fields */ + auto_round = 0L; + last_round = 0L; + + /* Clean up */ + clear_from(10); + + /* Prompt for the minimum stats */ + put_str("Enter minimum attribute for: ", 15, 2); + + /* Output the maximum stats */ + for (i = 0; i < 6; i++) + { + char stat_buf[15]; + + /* Reset the "success" counter */ + stat_match[i] = 0; + + /* Race/Class bonus */ + j = rp_ptr->r_adj[i] + rmp_ptr->r_adj[i] + cp_ptr->c_adj[i]; + + /* Obtain the "maximal" stat */ + m = adjust_stat(17, j, TRUE); + + + /* Save the maximum */ + mval[i] = m; + + /* Extract a textual format */ + cnv_stat(m, stat_buf); + + strnfmt(inp, 80, "(Max of %s):", stat_buf); + + /* Prepare a prompt */ + strnfmt(buf, 80, "%-5s: %-20s", stat_names[i], inp); + + /* Dump the prompt */ + put_str(buf, 16 + i, 5); + } + + /* Input the minimum stats */ + for (i = 0; i < 6; i++) + { + /* Get a minimum stat */ + while (TRUE) + { + char *s; + + /* Move the cursor */ + put_str("", 16 + i, 30); + + /* Default */ + strcpy(inp, ""); + + /* Get a response (or escape) */ + if (!askfor_aux(inp, 8)) inp[0] = '\0'; + + /* Weirdos stat display .. erm .. I mean, original stat display */ + if (!linear_stats) + { + /* Hack -- add a fake slash */ + strcat(inp, "/"); + + /* Hack -- look for the "slash" */ + s = strchr(inp, '/'); + + /* Hack -- Nuke the slash */ + *s++ = '\0'; + + /* Hack -- Extract an input */ + v = atoi(inp) + atoi(s); + } + else + { + int z = atoi(inp); + + if (z <= 18) + v = z; + else + { + int extra = z - 18; + v = 18 + (extra * 10); + } + } + + /* Break on valid input */ + if (v <= mval[i]) break; + } + + /* Save the minimum stat */ + stat_limit[i] = (v > 0) ? v : 0; + } + } + + /* Roll */ + while (TRUE) + { + /* Feedback */ + if (autoroll) + { + Term_clear(); + + put_str("Name :", 2, 1); + put_str("Sex :", 3, 1); + put_str("Race :", 4, 1); + put_str("Class:", 5, 1); + + c_put_str(TERM_L_BLUE, player_name, 2, 9); + c_put_str(TERM_L_BLUE, sp_ptr->title, 3, 9); + strnfmt(buf, 80, "%s", get_player_race_name(p_ptr->prace, p_ptr->pracem)); + c_put_str(TERM_L_BLUE, buf, 4, 9); + c_put_str(TERM_L_BLUE, spp_ptr->title + c_name, 5, 9); + + /* Label stats */ + put_str("STR:", 2 + A_STR, 61); + put_str("INT:", 2 + A_INT, 61); + put_str("WIS:", 2 + A_WIS, 61); + put_str("DEX:", 2 + A_DEX, 61); + put_str("CON:", 2 + A_CON, 61); + put_str("CHR:", 2 + A_CHR, 61); + + /* Note when we started */ + last_round = auto_round; + + /* Indicate the state */ + put_str("(Hit ESC to abort)", 11, 61); + + /* Label count */ + put_str("Round:", 9, 61); + } + + /* Otherwise just get a character */ + else + { + /* Get a new character */ + get_stats(); + } + + /* Auto-roll */ + while (autoroll) + { + bool_ accept = TRUE; + + /* Get a new character */ + get_stats(); + + /* Advance the round */ + auto_round++; + + /* Hack -- Prevent overflow */ + if (auto_round >= 1000000L) break; + + /* Check and count acceptable stats */ + for (i = 0; i < 6; i++) + { + /* This stat is okay */ + if (stat_use[i] >= stat_limit[i]) + { + stat_match[i]++; + } + + /* This stat is not okay */ + else + { + accept = FALSE; + } + } + + /* Break if "happy" */ + if (accept) break; + + /* Take note every 25 rolls */ + flag = (!(auto_round % AUTOROLLER_STEP)); + + /* Update display occasionally */ + if (flag || (auto_round < last_round + 100)) + { + /* Dump data */ + birth_put_stats(); + + /* Dump round */ + put_str(format("%6ld", auto_round), 9, 73); + + /* Make sure they see everything */ + Term_fresh(); + + /* Do not wait for a key */ + inkey_scan = TRUE; + + /* Check for a keypress */ + if (inkey()) break; + } + } + + /* Flush input */ + flush(); + + + /*** Display ***/ + + /* Mode */ + mode = 0; + + /* Roll for base hitpoints */ + get_extra(); + + /* Roll for age/height/weight */ + get_ahw(); + + /* Roll for social class */ + get_history(); + + /* Roll for gold */ + get_money(); + + /*** Generate ***/ + process_hooks(HOOK_BIRTH, "()"); + + /* Input loop */ + while (TRUE) + { + /* Calculate the bonuses and hitpoints */ + p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_BODY); + + /* Update stuff */ + update_stuff(); + + /* Fully healed */ + p_ptr->chp = p_ptr->mhp; + + /* Fully rested */ + p_ptr->csp = p_ptr->msp; + + /* Display the player */ + display_player(mode); + + /* Prepare a prompt (must squeeze everything in) */ + Term_gotoxy(2, 23); + Term_addch(TERM_WHITE, b1); + Term_addstr( -1, TERM_WHITE, "'r' to reroll"); + if (prev) Term_addstr( -1, TERM_WHITE, ", 'p' for prev"); + if (mode) Term_addstr( -1, TERM_WHITE, ", 'h' for Misc."); + else Term_addstr( -1, TERM_WHITE, ", 'h' for History"); + Term_addstr( -1, TERM_WHITE, ", or ESC to accept"); + Term_addch(TERM_WHITE, b2); + + /* Prompt and get a command */ + c = inkey(); + + /* Quit */ + if (c == 'Q') quit(NULL); + + /* Start over */ + if (c == 'S') return (FALSE); + + /* Escape accepts the roll */ + if (c == ESCAPE) break; + + /* Reroll this character */ + if ((c == ' ') || (c == 'r')) break; + + /* Previous character */ + if (prev && (c == 'p')) + { + load_prev_data(TRUE); + continue; + } + + /* Toggle the display */ + if ((c == 'H') || (c == 'h')) + { + mode = ((mode != 0) ? 0 : 1); + continue; + } + + /* Help */ + if (c == '?') + { + do_cmd_help(); + continue; + } + + /* Warning */ + bell(); + } + + /* Are we done? */ + if (c == ESCAPE) break; + + /* Save this for the "previous" character */ + save_prev_data(); + + /* Note that a previous roll exists */ + prev = TRUE; + } + + /* Clear prompt */ + clear_from(23); + + return (TRUE); +} + + +/* + * Helper function for 'player_birth()' + * + * The delay may be reduced, but is recommended to keep players + * from continuously rolling up characters, which can be VERY + * expensive CPU wise. And it cuts down on player stupidity. + */ +static bool_ player_birth_aux() +{ + char c; + + int i, j; + + int y = 0, x = 0; + + char old_history[4][60]; + + /* Ask */ + if (!player_birth_aux_ask()) return (FALSE); + + for (i = 1; i < max_s_idx; i++) + s_info[i].dev = FALSE; + for (i = 1; i < max_s_idx; i++) + { + s32b value = 0, mod = 0; + + compute_skills(&value, &mod, i); + + init_skill(value, mod, i); + + /* Develop only revelant branches */ + if (s_info[i].value || s_info[i].mod) + { + int z = s_info[i].father; + + while (z != -1) + { + s_info[z].dev = TRUE; + z = s_info[z].father; + if (z == 0) + break; + } + } + } + + if (do_quick_start) + { + load_prev_data(FALSE); + + /* Roll for base hitpoints */ + get_extra(); + + /* Calculate the bonuses and hitpoints */ + p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_BODY); + + /* Update stuff */ + update_stuff(); + + /* Fully healed */ + p_ptr->chp = p_ptr->mhp; + + /* Fully rested */ + p_ptr->csp = p_ptr->msp; + } + else + { + /* Point based */ + if (point_based) + { + if (!player_birth_aux_point()) return FALSE; + } + /* Auto-roll */ + else + { + if (!player_birth_aux_auto()) return FALSE; + } + + /* Edit character background */ + for (i = 0; i < 4; i++) + { + strnfmt(old_history[i], 60, "%s", history[i]); + } + /* Turn 0 to space */ + for (i = 0; i < 4; i++) + { + for (j = 0; history[i][j]; j++) /* loop */; + + for (; j < 59; j++) history[i][j] = ' '; + } + display_player(1); + c_put_str(TERM_L_GREEN, "(Character Background - Edit Mode)", 15, 20); + while (TRUE) + { + for (i = 0; i < 4; i++) + { + put_str(history[i], i + 16, 10); + } + c_put_str(TERM_L_BLUE, format("%c", history[y][x]), y + 16, x + 10); + + /* Place cursor just after cost of current stat */ + Term_gotoxy(x + 10, y + 16); + + c = inkey(); + + if (c == '8') + { + y--; + if (y < 0) y = 3; + } + else if (c == '2') + { + y++; + if (y > 3) y = 0; + } + else if (c == '6') + { + x++; + if (x > 59) x = 0; + } + else if (c == '4') + { + x--; + if (x < 0) x = 59; + } + else if (c == '\r') + { + break; + } + else if (c == ESCAPE) + { + for (i = 0; i < 4; i++) + { + strnfmt(history[i], 60, "%s", old_history[i]); + put_str(history[i], i + 16, 10); + } + break; + } + else + { + history[y][x++] = c; + if (x > 58) + { + x = 0; + y++; + if (y > 3) y = 0; + } + } + } + + + /*** Finish up ***/ + + /* Get a name, recolor it, prepare savefile */ + + get_name(); + + + /* Prompt for it */ + prt("['Q' to suicide, 'S' to start over, or ESC to continue]", 23, 10); + + /* Get a key */ + c = inkey(); + + /* Quit */ + if (c == 'Q') quit(NULL); + + /* Start over */ + if (c == 'S') return (FALSE); + } + + /* Save this for the next character */ + previous_char.quick_ok = TRUE; + save_prev_data(); + + /* Accept */ + return (TRUE); +} + + +/* + * Helper function for validate_bg(). + */ +static void validate_bg_aux(int chart, bool_ chart_checked[], char *buf) +{ + char *s; + + int i; + + + /* Assume the chart does not exist */ + bool_ chart_exists = FALSE; + + /* Assume the chart is not complete */ + bool_ chart_complete = FALSE; + + int bg_max = max_bg_idx; + + /* No chart */ + if (!chart) return; + + /* Already saw this chart */ + if (chart_checked[chart]) return; + + /* Build a debug message */ + s = buf + strlen(buf); + + /* XXX XXX XXX */ + (void) strnfmt(s, -1, "%d --> ", chart); + + /* Check each chart */ + for (i = 0; i < bg_max; i++) + { + /* Require same chart */ + if (bg[i].chart != chart) continue; + + /* The chart exists */ + chart_exists = TRUE; + + /* Validate the "next" chart recursively */ + validate_bg_aux(bg[i].next, chart_checked, buf); + + /* Require a terminator */ + if (bg[i].roll != 100) continue; + + /* The chart is complete */ + chart_complete = TRUE; + } + + /* Failed: The chart does not exist */ + if (!chart_exists) + { + quit_fmt("birth.c: bg[] chart %d does not exist\n%s", chart, buf); + } + + /* Failed: The chart is not complete */ + if (!chart_complete) + { + quit_fmt("birth.c: bg[] chart %d is not complete", chart); + } + + /* Remember we saw this chart */ + chart_checked[chart] = TRUE; + + /* Build a debug message */ + *s = 0; +} + + +/* + * Verify that the bg[] table is valid. + */ +static void validate_bg(void) +{ + int i, race; + + bool_ chart_checked[512]; + + char buf[1024]; + + + for (i = 0; i < 512; i++) chart_checked[i] = FALSE; + + /* Check each race */ + for (race = 0; race < max_rp_idx; race++) + { + /* Get the first chart for this race */ + int chart = race_info[race].chart; + + (void) strcpy(buf, ""); + + /* Validate the chart recursively */ + validate_bg_aux(chart, chart_checked, buf); + } +} + +/* + * Initialize a random town + */ +void init_town(int t_idx, int level) +{ + town_type *t_ptr = &town_info[t_idx]; + + /* Mark it as existent */ + t_ptr->flags |= (TOWN_REAL); + + /* Mark it as not found */ + t_ptr->flags &= ~(TOWN_KNOWN); + + /* Generation seed for the town */ + t_ptr->seed = randint(0x10000000); + + /* Total hack and not even used */ + t_ptr->numstores = 8; +} + +/* + * Create a new character. + * + * Note that we may be called with "junk" leftover in the various + * fields, so we must be sure to clear them first. + */ +void player_birth(void) +{ + int i, j, rtown = TOWN_RANDOM; + + /* Validate the bg[] table */ + validate_bg(); + + /* Create a new character */ + while (1) + { + /* Wipe the player */ + player_wipe(); + + /* Roll up a new character */ + if (player_birth_aux()) break; + } + + /* Finish skills */ + p_ptr->skill_points = 0; + p_ptr->skill_last_level = 1; + + recalc_skills(FALSE); + + /* grab level 1 abilities */ + for (i = 0; i < max_ab_idx; i++) + ab_info[i].acquired = FALSE; + apply_level_abilities(1); + + /* Complete the god */ + i = p_ptr->pgod; + p_ptr->pgod = 0; + follow_god(i, TRUE); + + /* Select the default melee type */ + select_default_melee(); + + /* Make a note file if that option is set */ + add_note_type(NOTE_BIRTH); + + /* Note player birth in the message recall */ + message_add(" ", TERM_L_BLUE); + message_add(" ", TERM_L_BLUE); + message_add("====================", TERM_L_BLUE); + message_add(" ", TERM_L_BLUE); + message_add(" ", TERM_L_BLUE); + + /* Hack -- outfit the player */ + player_outfit(); + + /* Initialize random towns in the dungeons */ + for (i = 0; i < max_d_idx; i++) + { + dungeon_info_type *d_ptr = &d_info[i]; + int num = 0, z; + + d_ptr->t_num = 0; + for (z = 0; z < TOWN_DUNGEON; z++) + { + d_ptr->t_idx[z] = 0; + d_ptr->t_level[z] = 0; + } + if (!(d_ptr->flags1 & DF1_RANDOM_TOWNS)) continue; + + /* Can we add a town ? */ + while (magik(TOWN_CHANCE - (num * 10))) + { + int lev; + + d_ptr->t_idx[num] = rtown; + rtown++; + + while (TRUE) + { + int j; + bool_ ok = TRUE; + + lev = rand_range(d_ptr->mindepth, d_ptr->maxdepth - 1); + + /* Be sure it wasnt already used */ + for (j = 0; j < num; j++) + { + if (d_ptr->t_level[j] == lev) ok = FALSE; + } + + /* Ok found one */ + if (ok) break; + } + d_ptr->t_level[num] = lev; + + if (wizard) + { + message_add(format("Random dungeon town: d_idx:%d, lev:%d", i, lev), TERM_WHITE); + } + + /* Create the town */ + init_town(d_ptr->t_idx[num], d_ptr->t_level[num]); + + num++; + + /* No free slots left */ + if (num >= TOWN_DUNGEON) break; + } + + d_ptr->t_num = num; + } + + /* Init the towns */ + for (i = 1; i < max_towns; i++) + { + /* Not destroyed ! yet .. ;) */ + town_info[i].destroyed = FALSE; + + /* Ignore non-existent towns */ + if (!(town_info[i].flags & (TOWN_REAL))) continue; + + create_stores_stock(i); + + /* Init the stores */ + for (j = 0; j < max_st_idx; j++) + { + /* Initialize */ + store_init(i, j); + } + } + + /* Init wilderness seeds */ + for (i = 0; i < max_wild_x; i++) + { + for (j = 0; j < max_wild_y; j++) + { + wild_map[j][i].seed = rand_int(0x10000000); + wild_map[j][i].entrance = 0; + wild_map[j][i].known = FALSE; + } + } + + /* Select bounty monsters. */ + select_bounties(); +} + + + + +char savefile_module[46][80]; +char savefile_names[46][30]; +char savefile_desc[46][80]; +bool_ savefile_alive[46]; +int savefile_idx[46]; + +/* + * Grab all the names from an index + */ +int load_savefile_names() +{ + FILE *fff; + char buf[1024]; + char tmp[50]; + char player_base_save[32]; + int max = 0, fd; + + + /* Build the filename */ + strcpy(tmp, "global.svg"); + path_build(buf, 1024, ANGBAND_DIR_SAVE, tmp); + + /* File type is "TEXT" */ + FILE_TYPE(FILE_TYPE_TEXT); + + /* Read the file */ + fff = my_fopen(buf, "r"); + + /* Failure */ + if (!fff) return (0); + + + /* Save the current 'player_base' */ + strncpy(player_base_save, player_base, 32); + + + /* + * Parse, use '@' intead of ':' as a separator because it cannot exists + * in savefiles + */ + while (0 == my_fgets(fff, buf, 1024)) + { + int i = 0, start, count; + + /* Check for pre-ToME 2.1.2 file */ + count = 0; + i = 0; + while (buf[i] && buf[i] != '\n') + { + if (buf[i] == '@') + ++count; + ++i; + } + + /* Check module if a current svg file */ + start = 0; + i = 0; + if (count > 1) + { + while (buf[i] != '@') + { + savefile_module[max][i - start] = buf[i]; + i++; + } + savefile_module[max][i] = '\0'; + i++; + } + /* Default to ToME for old files */ + else + { + savefile_module[max][0] = 'T'; + savefile_module[max][1] = 'o'; + savefile_module[max][2] = 'M'; + savefile_module[max][3] = 'E'; + savefile_module[max][4] = '\0'; + } + + if (buf[i] == '0') savefile_alive[max] = FALSE; + else if (buf[i] == '1') savefile_alive[max] = TRUE; + + i++; + start = i; + while (buf[i] != '@') + { + savefile_names[max][i - start] = buf[i]; + i++; + } + savefile_names[max][i - start] = '\0'; + i++; + strcpy(savefile_desc[max], buf + i); + + /* Build platform-dependent savefile name */ + strncpy(player_base, savefile_names[max], 32); + process_player_name(TRUE); + + /* File type is 'SAVE' */ + FILE_TYPE(FILE_TYPE_SAVE); + + /* Try to open the savefile */ + fd = fd_open(savefile, O_RDONLY); + + /* Still existing ? */ + if (fd >= 0) + { + fd_close(fd); + max++; + } + } + + my_fclose(fff); + + /* Restore the values of 'player_base' and 'savefile' */ + strncpy(player_base, player_base_save, 32); + process_player_name(TRUE); + + return (max); +} + + +/* + * Save all the names from an index + */ +void save_savefile_names() +{ + FILE *fff; + char buf[1024]; + char tmp[50]; + int max = load_savefile_names(), i; + + + /* Build the filename */ + strcpy(tmp, "global.svg"); + path_build(buf, 1024, ANGBAND_DIR_SAVE, tmp); + + /* File type is "TEXT" */ + FILE_TYPE(FILE_TYPE_TEXT); + + /* Read the file */ + fff = my_fopen(buf, "w"); + + /* Failure */ + if (!fff) return; + + /* + * Save, use '@' intead of ':' as a separator because it cannot exists + * in savefiles + */ + fprintf(fff, "%s@%c%s@%s, the %s %s is %s\n", game_module, + (death) ? '0' : '1', player_base, player_name, + get_player_race_name(p_ptr->prace, p_ptr->pracem), + spp_ptr->title + c_name, + (!death) ? "alive" : "dead"); + + for (i = 0; i < max; i++) + { + if (!strcmp(savefile_names[i], player_base)) continue; + fprintf(fff, "%s@%c%s@%s\n", savefile_module[i], + (savefile_alive[i]) ? '1' : '0', savefile_names[i], savefile_desc[i]); + } + + my_fclose(fff); +} + + +static void dump_savefiles(int sel, int max) +{ + int i; + + char buf[40], pre = ' ', post = ')'; + + char ind; + + + for (i = 0; i < max; i++) + { + ind = I2A(i % 26); + if (i >= 26) ind = toupper(ind); + + if (sel == i) + { + pre = '['; + post = ']'; + } + else + { + pre = ' '; + post = ')'; + } + + if (i == 0) strnfmt(buf, 40, "%c%c%c New Character", pre, ind, post); + else if (i == 1) strnfmt(buf, 40, "%c%c%c Load Savefile", pre, ind, post); + else strnfmt(buf, 40, "%c%c%c %s", pre, ind, post, savefile_names[savefile_idx[i - 2]]); + + if (sel == i) + { + if (i >= 2) + { + if (savefile_alive[i - 2]) c_put_str(TERM_L_GREEN, savefile_desc[savefile_idx[i - 2]], 5, 0); + else c_put_str(TERM_L_RED, savefile_desc[savefile_idx[i - 2]], 5, 0); + } + else if (i == 1) c_put_str(TERM_YELLOW, "Load an existing savefile that is not in the list", 5, 0); + else c_put_str(TERM_YELLOW, "Create a new character", 5, 0); + c_put_str(TERM_L_BLUE, buf, 6 + (i / 4), 20 * (i % 4)); + } + else + put_str(buf, 6 + (i / 4), 20 * (i % 4)); + } +} + + +/* Asks for new game or load game */ +bool_ no_begin_screen = FALSE; + +bool_ begin_screen() +{ + int m, k, sel, max; + +savefile_try_again: + sel = 0; + + /* Grab the savefiles */ + max = load_savefile_names(); + + /* Get only the usable savefiles */ + for (k = 0, m = 0; k < max; k++) + { + s32b can_use; + + can_use = module_savefile_loadable(savefile_module[k]); + if (can_use) + { + savefile_idx[m++] = k; + } + } + max = m + 2; + if (max > 2) sel = 2; + + while (TRUE) + { + /* Clear screen */ + Term_clear(); + + /* Let the user choose */ + c_put_str(TERM_YELLOW, format("Welcome to %s! To play you will need a character.", game_module), 1, 10); + put_str("Press 8/2/4/6 to move, Return to select, Backspace to delete a savefile.", 3, 3); + put_str("and Esc to quit.", 4, 32); + + dump_savefiles(sel, max); + + k = inkey(); + + if (k == ESCAPE) + { + quit(NULL); + } + if (k == '6') + { + sel++; + if (sel >= max) sel = 0; + continue; + } + else if (k == '4') + { + sel--; + if (sel < 0) sel = max - 1; + continue; + } + else if (k == '2') + { + sel += 4; + if (sel >= max) sel = sel % max; + continue; + } + else if (k == '8') + { + sel -= 4; + if (sel < 0) sel = (sel + max - 1) % max; + continue; + } + else if (k == '\r') + { + if (sel < 26) k = I2A(sel); + else k = toupper(I2A(sel)); + } + else if (((k == 0x7F) || (k == '\010')) && (sel >= 2)) + { + char player_base_save[32]; + + if (!get_check(format("Really delete '%s'?", savefile_names[savefile_idx[sel - 2]]))) continue; + + /* Save current 'player_base' */ + strncpy(player_base_save, player_base, 32); + + /* Build platform-dependent save file name */ + strncpy(player_base, savefile_names[savefile_idx[sel - 2]], 32); + process_player_name(TRUE); + + /* Remove the savefile */ + fd_kill(savefile); + + /* Restore 'player_base' and 'savefile' */ + strncpy(player_base, player_base_save, 32); + process_player_name(TRUE); + + /* Reload, gods I hate using goto .. */ + goto savefile_try_again; + + continue; + } + + if (k == 'a') + { + /* Display prompt */ + prt("Enter the name of the savefile that will hold this character: ", 23, 0); + + /* Ask the user for a string */ + if (!askfor_aux(player_base, 15)) continue; + + /* Process the player name */ + process_player_name(TRUE); + + return (TRUE); + } + if (k == 'b') + { + /* Display prompt */ + prt("Enter the name of a savefile: ", 23, 0); + + /* Ask the user for a string */ + if (!askfor_aux(player_base, 15)) continue; + + /* Process the player name */ + process_player_name(TRUE); + + return (FALSE); + } + else + { + int x; + + if (islower(k)) x = A2I(k); + else x = A2I(tolower(k)) + 26; + + if ((x < 2) || (x >= max)) continue; + + strnfmt(player_base, 32, "%s", savefile_names[savefile_idx[x - 2]]); + + /* Process the player name */ + process_player_name(TRUE); + + return (FALSE); + } + } + + /* Shouldnt happen */ + return (FALSE); +} diff --git a/src/bldg.c b/src/bldg.c deleted file mode 100644 index 468e3c1d..00000000 --- a/src/bldg.c +++ /dev/null @@ -1,2234 +0,0 @@ -/* File: bldg.c */ - -/* - * Purpose: Building commands - * Created by Ken Wigle for Kangband - a variant of Angband 2.8.3 - * -KMW- - * - * Rewritten for Kangband 2.8.3i using Kamband's version of - * bldg.c as written by Ivan Tkatchev - * - * Changed for ZAngband by Robert Ruehlmann - * - * Heavily modified for ToME by DarkGod - */ - -#include "angband.h" -#include "hooks.h" -#include "q_library.h" -#include "q_fireprof.h" -#include "q_bounty.h" - -/* hack as in leave_store in store.c */ -static bool_ leave_bldg = FALSE; - -/* remember building location */ -static int building_loc = 0; - - -/* - * A helper function for is_state - */ -bool_ is_state_aux(store_type *s_ptr, int state) -{ - owner_type *ow_ptr = &ow_info[s_ptr->owner]; - - - /* Check race */ - if (ow_ptr->races[state][p_ptr->prace / 32] & (1 << p_ptr->prace)) - { - return (TRUE); - } - - /* Check class */ - if (ow_ptr->classes[state][p_ptr->prace / 32] & (1 << p_ptr->pclass)) - { - return (TRUE); - } - - /* All failed */ - return (FALSE); -} - - -/* - * Test if the state accords with the player - */ -bool_ is_state(store_type *s_ptr, int state) -{ - if (state == STORE_NORMAL) - { - if (is_state_aux(s_ptr, STORE_LIKED)) return (FALSE); - if (is_state_aux(s_ptr, STORE_HATED)) return (FALSE); - return (TRUE); - } - - else - { - return (is_state_aux(s_ptr, state)); - } -} - - -/* - * Clear the building information - */ -static void clear_bldg(int min_row, int max_row) -{ - int i; - - - for (i = min_row; i <= max_row; i++) - { - prt("", i, 0); - } -} - - -/* - * Display a building. - */ -void show_building(store_type *s_ptr) -{ - char buff[20]; - - int i; - - byte action_color; - - char tmp_str[80]; - - store_info_type *st_ptr = &st_info[s_ptr->st_idx]; - - store_action_type *ba_ptr; - - - for (i = 0; i < 6; i++) - { - ba_ptr = &ba_info[st_ptr->actions[i]]; - - if (ba_ptr->letter != '.') - { - if (ba_ptr->action_restr == 0) - { - if ((is_state(s_ptr, STORE_LIKED) && (ba_ptr->costs[STORE_LIKED] == 0)) || - (is_state(s_ptr, STORE_HATED) && (ba_ptr->costs[STORE_HATED] == 0)) || - (is_state(s_ptr, STORE_NORMAL) && (ba_ptr->costs[STORE_NORMAL] == 0))) - { - action_color = TERM_WHITE; - buff[0] = '\0'; - } - else if (is_state(s_ptr, STORE_LIKED)) - { - action_color = TERM_L_GREEN; - strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_LIKED]); - } - else if (is_state(s_ptr, STORE_HATED)) - { - action_color = TERM_RED; - strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_HATED]); - } - else - { - action_color = TERM_YELLOW; - strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_NORMAL]); - } - } - else if (ba_ptr->action_restr == 1) - { - if ((is_state(s_ptr, STORE_LIKED) && (ba_ptr->costs[STORE_LIKED] == 0)) || - (is_state(s_ptr, STORE_NORMAL) && (ba_ptr->costs[STORE_NORMAL] == 0))) - { - action_color = TERM_WHITE; - buff[0] = '\0'; - } - else if (is_state(s_ptr, STORE_LIKED)) - { - action_color = TERM_L_GREEN; - strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_LIKED]); - } - else if (is_state(s_ptr, STORE_HATED)) - { - action_color = TERM_L_DARK; - strnfmt(buff, 20, "(closed)"); - } - else - { - action_color = TERM_YELLOW; - strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_NORMAL]); - } - } - else - { - if (is_state(s_ptr, STORE_LIKED) && (ba_ptr->costs[STORE_LIKED] == 0)) - { - action_color = TERM_WHITE; - buff[0] = '\0'; - } - else if (is_state(s_ptr, STORE_LIKED)) - { - action_color = TERM_L_GREEN; - strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_LIKED]); - } - else - { - action_color = TERM_L_DARK; - strnfmt(buff, 20, "(closed)"); - } - } - - strnfmt(tmp_str, 80, " %c", ba_ptr->letter); - c_put_str(TERM_YELLOW, tmp_str, 21 + (i / 2), 17 + (30 * (i % 2))); - - strnfmt(tmp_str, 80, ") %s %s", ba_ptr->name + ba_name, buff); - c_put_str(action_color, tmp_str, 21 + (i / 2), 2 + 17 + (30 * (i % 2))); - } - } -} - - -/* reset timed flags */ -static void reset_tim_flags() -{ - p_ptr->fast = 0; /* Timed -- Fast */ - p_ptr->slow = 0; /* Timed -- Slow */ - p_ptr->blind = 0; /* Timed -- Blindness */ - p_ptr->paralyzed = 0; /* Timed -- Paralysis */ - p_ptr->confused = 0; /* Timed -- Confusion */ - p_ptr->afraid = 0; /* Timed -- Fear */ - p_ptr->image = 0; /* Timed -- Hallucination */ - p_ptr->poisoned = 0; /* Timed -- Poisoned */ - p_ptr->cut = 0; /* Timed -- Cut */ - p_ptr->stun = 0; /* Timed -- Stun */ - - p_ptr->protevil = 0; /* Timed -- Protection */ - p_ptr->protgood = 0; /* Timed -- Protection */ - p_ptr->invuln = 0; /* Timed -- Invulnerable */ - p_ptr->hero = 0; /* Timed -- Heroism */ - p_ptr->shero = 0; /* Timed -- Super Heroism */ - p_ptr->shield = 0; /* Timed -- Shield Spell */ - p_ptr->blessed = 0; /* Timed -- Blessed */ - p_ptr->tim_invis = 0; /* Timed -- Invisibility */ - p_ptr->tim_infra = 0; /* Timed -- Infra Vision */ - - p_ptr->oppose_acid = 0; /* Timed -- oppose acid */ - p_ptr->oppose_elec = 0; /* Timed -- oppose lightning */ - p_ptr->oppose_fire = 0; /* Timed -- oppose heat */ - p_ptr->oppose_cold = 0; /* Timed -- oppose cold */ - p_ptr->oppose_pois = 0; /* Timed -- oppose poison */ - - p_ptr->confusing = 0; /* Touch of Confusion */ -} - - -/* - * arena commands - */ -static void arena_comm(int cmd) -{ - char tmp_str[80]; - - monster_race *r_ptr; - - cptr name; - - - switch (cmd) - { - case BACT_ARENA: - { - if (p_ptr->arena_number == MAX_ARENA_MONS) - { - clear_bldg(5, 19); - prt(" Arena Victor!", 5, 0); - prt("Congratulations! You have defeated all before you.", 7, 0); - prt("For that, receive the prize: 10,000 gold pieces", 8, 0); - prt("", 10, 0); - prt("", 11, 0); - p_ptr->au += 10000; - msg_print("Press the space bar to continue"); - msg_print(NULL); - p_ptr->arena_number++; - } - else if (p_ptr->arena_number > MAX_ARENA_MONS) - { - msg_print("You enter the arena briefly and bask in your glory."); - msg_print(NULL); - } - else - { - p_ptr->inside_arena = TRUE; - p_ptr->exit_bldg = FALSE; - reset_tim_flags(); - p_ptr->leaving = TRUE; - p_ptr->oldpx = p_ptr->px; - p_ptr->oldpy = p_ptr->py; - leave_bldg = TRUE; - } - - break; - } - - case BACT_POSTER: - { - if (p_ptr->arena_number == MAX_ARENA_MONS) - msg_print("You are victorious. Enter the arena for the ceremony."); - else if (p_ptr->arena_number > MAX_ARENA_MONS) - msg_print("You have won against all foes."); - else - { - r_ptr = &r_info[arena_monsters[p_ptr->arena_number]]; - name = (r_name + r_ptr->name); - strnfmt(tmp_str, 80, "Do I hear any challenges against: %s", name); - msg_print(tmp_str); - msg_print(NULL); - } - - break; - } - - case BACT_ARENA_RULES: - { - /* Save screen */ - screen_save(); - - /* Peruse the arena help file */ - (void)show_file("arena.txt", NULL, 0, 0); - - /* Load screen */ - screen_load(); - - break; - } - } -} - - -/* - * display fruit for dice slots - */ -static void display_fruit(int row, int col, int fruit) -{ - switch (fruit) - { - case 0: /* lemon */ - { - c_put_str(TERM_YELLOW, " ####.", row, col); - c_put_str(TERM_YELLOW, " # #", row + 1, col); - c_put_str(TERM_YELLOW, " # #", row + 2, col); - c_put_str(TERM_YELLOW, "# #", row + 3, col); - c_put_str(TERM_YELLOW, "# #", row + 4, col); - c_put_str(TERM_YELLOW, "# # ", row + 5, col); - c_put_str(TERM_YELLOW, "# # ", row + 6, col); - c_put_str(TERM_YELLOW, ".#### ", row + 7, col); - prt(" Lemon ", row + 8, col); - - break; - } - - case 1: /* orange */ - { - c_put_str(TERM_ORANGE, " ## ", row, col); - c_put_str(TERM_ORANGE, " #..# ", row + 1, col); - c_put_str(TERM_ORANGE, " #....# ", row + 2, col); - c_put_str(TERM_ORANGE, "#......#", row + 3, col); - c_put_str(TERM_ORANGE, "#......#", row + 4, col); - c_put_str(TERM_ORANGE, " #....# ", row + 5, col); - c_put_str(TERM_ORANGE, " #..# ", row + 6, col); - c_put_str(TERM_ORANGE, " ## ", row + 7, col); - prt(" Orange ", row + 8, col); - - break; - } - - case 2: /* sword */ - { - c_put_str(TERM_SLATE, " /\\ ", row, col); - c_put_str(TERM_SLATE, " ## ", row + 1, col); - c_put_str(TERM_SLATE, " ## ", row + 2, col); - c_put_str(TERM_SLATE, " ## ", row + 3, col); - c_put_str(TERM_SLATE, " ## ", row + 4, col); - c_put_str(TERM_SLATE, " ## ", row + 5, col); - c_put_str(TERM_UMBER, " ###### ", row + 6, col); - c_put_str(TERM_UMBER, " ## ", row + 7, col); - prt(" Sword ", row + 8, col); - - break; - } - - case 3: /* shield */ - { - c_put_str(TERM_SLATE, " ###### ", row, col); - c_put_str(TERM_SLATE, "# #", row + 1, col); - c_put_str(TERM_SLATE, "# ++++ #", row + 2, col); - c_put_str(TERM_SLATE, "# +==+ #", row + 3, col); - c_put_str(TERM_SLATE, "# ++ #", row + 4, col); - c_put_str(TERM_SLATE, " # # ", row + 5, col); - c_put_str(TERM_SLATE, " # # ", row + 6, col); - c_put_str(TERM_SLATE, " ## ", row + 7, col); - prt(" Shield ", row + 8, col); - - break; - } - - case 4: /* plum */ - { - c_put_str(TERM_VIOLET, " ## ", row, col); - c_put_str(TERM_VIOLET, " ###### ", row + 1, col); - c_put_str(TERM_VIOLET, "########", row + 2, col); - c_put_str(TERM_VIOLET, "########", row + 3, col); - c_put_str(TERM_VIOLET, "########", row + 4, col); - c_put_str(TERM_VIOLET, " ###### ", row + 5, col); - c_put_str(TERM_VIOLET, " #### ", row + 6, col); - c_put_str(TERM_VIOLET, " ## ", row + 7, col); - prt(" Plum ", row + 8, col); - - break; - } - - case 5: /* cherry */ - { - c_put_str(TERM_RED, " ##", row, col); - c_put_str(TERM_RED, " ### ", row + 1, col); - c_put_str(TERM_RED, " #..# ", row + 2, col); - c_put_str(TERM_RED, " #..# ", row + 3, col); - c_put_str(TERM_RED, " ###### ", row + 4, col); - c_put_str(TERM_RED, "#..##..#", row + 5, col); - c_put_str(TERM_RED, "#..##..#", row + 6, col); - c_put_str(TERM_RED, " ## ## ", row + 7, col); - prt(" Cherry ", row + 8, col); - - break; - } - } -} - - -/* - * gamble_comm - */ -static bool_ gamble_comm(int cmd) -{ - int roll1, roll2, roll3, choice, odds, win; - - s32b wager; - - s32b maxbet; - - s32b oldgold; - - static const char *fruit[6] = - {"Lemon", "Orange", "Sword", "Shield", "Plum", "Cherry" - }; - - char out_val[160], tmp_str[80], again; - - cptr p; - - - screen_save(); - - if (cmd == BACT_GAMBLE_RULES) - { - /* Peruse the gambling help file */ - (void)show_file("gambling.txt", NULL, 0, 0); - } - else - { - clear_bldg(5, 23); - - /* Set maximum bet */ - if (p_ptr->lev < 10) - maxbet = (p_ptr->lev * 100); - else - maxbet = (p_ptr->lev * 1000); - - /* Get the wager */ - strcpy(out_val, ""); - strnfmt(tmp_str, 80, "Your wager (1-%ld) ? ", maxbet); - get_string(tmp_str, out_val, 32); - - /* Strip spaces */ - for (p = out_val; *p == ' '; p++); - - wager = atol(p); - - if (wager > p_ptr->au) - { - msg_print("Hey! You don't have the gold - get out of here!"); - msg_print(NULL); - screen_load(); - return (FALSE); - } - else if (wager > maxbet) - { - msg_format("I'll take $%ld of that. Keep the rest.", maxbet); - wager = maxbet; - } - else if (wager < 1) - { - msg_print("Ok, we'll start with $1."); - - wager = 1; - } - msg_print(NULL); - win = FALSE; - odds = 0; - oldgold = p_ptr->au; - - strnfmt(tmp_str, 80, "Gold before game: %9ld", oldgold); - prt(tmp_str, 20, 2); - - strnfmt(tmp_str, 80, "Current Wager: %9ld", wager); - prt(tmp_str, 21, 2); - - do - { - switch (cmd) - { - case BACT_IN_BETWEEN: /* Game of In-Between */ - { - c_put_str(TERM_GREEN, "In Between", 5, 2); - odds = 3; - win = FALSE; - roll1 = randint(10); - roll2 = randint(10); - choice = randint(10); - strnfmt(tmp_str, 80, "Black die: %d Black Die: %d", - roll1, roll2); - prt(tmp_str, 8, 3); - strnfmt(tmp_str, 80, "Red die: %d", choice); - prt(tmp_str, 11, 14); - if (((choice > roll1) && (choice < roll2)) || - ((choice < roll1) && (choice > roll2))) - win = TRUE; - - break; - } - case BACT_CRAPS: /* Game of Craps */ - { - c_put_str(TERM_GREEN, "Craps", 5, 2); - win = 3; - odds = 1; - roll1 = randint(6); - roll2 = randint(6); - roll3 = roll1 + roll2; - choice = roll3; - strnfmt(tmp_str, 80, "First roll: %d %d Total: %d", roll1, - roll2, roll3); - prt(tmp_str, 7, 5); - if ((roll3 == 7) || (roll3 == 11)) - win = TRUE; - else if ((roll3 == 2) || (roll3 == 3) || (roll3 == 12)) - win = FALSE; - else - { - do - { - msg_print("Hit any key to roll again"); - msg_print(NULL); - roll1 = randint(6); - roll2 = randint(6); - roll3 = roll1 + roll2; - - strnfmt(tmp_str, 80, "Roll result: %d %d Total: %d", - roll1, roll2, roll3); - prt(tmp_str, 8, 5); - if (roll3 == choice) - win = TRUE; - else if (roll3 == 7) - win = FALSE; - } - while ((win != TRUE) && (win != FALSE)); - } - - break; - } - - case BACT_SPIN_WHEEL: /* Spin the Wheel Game */ - { - win = FALSE; - odds = 10; - c_put_str(TERM_GREEN, "Wheel", 5, 2); - prt("0 1 2 3 4 5 6 7 8 9", 7, 5); - prt("--------------------------------", 8, 3); - strcpy(out_val, ""); - get_string ("Pick a number (1-9): ", out_val, 32); - for (p = out_val; *p == ' '; p++); - choice = atol(p); - if (choice < 0) - { - msg_print("I'll put you down for 0."); - choice = 0; - } - else if (choice > 9) - { - msg_print("Ok, I'll put you down for 9."); - choice = 9; - } - msg_print(NULL); - roll1 = randint(10) - 1; - strnfmt(tmp_str, 80, "The wheel spins to a stop and the winner is %d", - roll1); - prt(tmp_str, 13, 3); - prt("", 9, 0); - prt("*", 9, (3 * roll1 + 5)); - if (roll1 == choice) - win = TRUE; - - break; - } - - case BACT_DICE_SLOTS: /* The Dice Slots */ - { - c_put_str(TERM_GREEN, "Dice Slots", 5, 2); - win = FALSE; - roll1 = randint(6); - roll2 = randint(6); - choice = randint(6); - strnfmt(tmp_str, 80, "%s %s %s", - fruit[roll1 - 1], fruit[roll2 - 1], - fruit[choice - 1]); - prt(tmp_str, 15, 37); - prt("/--------------------------\\", 7, 2); - prt("\\--------------------------/", 17, 2); - display_fruit(8, 3, roll1 - 1); - display_fruit(8, 12, roll2 - 1); - display_fruit(8, 21, choice - 1); - if ((roll1 == roll2) && (roll2 == choice)) - { - win = TRUE; - if (roll1 == 1) - odds = 4; - else if (roll1 == 2) - odds = 6; - else - odds = roll1 * roll1; - } - else if ((roll1 == 6) && (roll2 == 6)) - { - win = TRUE; - odds = choice + 1; - } - - break; - } - } - - if (win) - { - prt("YOU WON", 16, 37); - p_ptr->au = p_ptr->au + (odds * wager); - strnfmt(tmp_str, 80, "Payoff: %d", odds); - prt(tmp_str, 17, 37); - } - else - { - prt("You Lost", 16, 37); - p_ptr->au = p_ptr->au - wager; - prt("", 17, 37); - } - strnfmt(tmp_str, 80, "Current Gold: %9ld", p_ptr->au); - prt(tmp_str, 22, 2); - prt("Again(Y/N)?", 18, 37); - move_cursor(18, 49); - again = inkey(); - if (wager > p_ptr->au) - { - msg_print("Hey! You don't have the gold - get out of here!"); - msg_print(NULL); - screen_load(); - return (FALSE); - /* strnfmt(tmp_str, 80, "Current Wager: %9ld",wager); - prt(tmp_str, 17, 2); */ - } - } - while ((again == 'y') || (again == 'Y')); - - prt("", 18, 37); - if (p_ptr->au >= oldgold) - msg_print("You came out a winner! We'll win next time, I'm sure."); - else - msg_print("You lost gold! Haha, better head home."); - msg_print(NULL); - } - - screen_load(); - - return (TRUE); -} - - -/* - * inn commands - * Note that resting for the night was a perfect way to avoid player - * ghosts in the town *if* you could only make it to the inn in time (-: - * Now that the ghosts are temporarily disabled in 2.8.X, this function - * will not be that useful. I will keep it in the hopes the player - * ghost code does become a reality again. Does help to avoid filthy urchins. - * Resting at night is also a quick way to restock stores -KMW- - */ -static bool_ inn_comm(int cmd) -{ - bool_ vampire; - - - /* Extract race info */ - vampire = ((PRACE_FLAG(PR1_VAMPIRE)) || (p_ptr->mimic_form == resolve_mimic_name("Vampire"))); - - switch (cmd) - { - case BACT_FOOD: /* Buy food & drink */ - { - if (!vampire) - { - msg_print("The barkeep gives you some gruel and a beer."); - msg_print(NULL); - (void) set_food(PY_FOOD_MAX - 1); - } - else - msg_print("You're a vampire and I don't have any food for you!"); - - break; - } - - /* - * I revamped this... Don't know why normal races didn't get - * mana regenerated. It is the grand tradition of p&p games -- pelpel - */ - case BACT_REST: /* Rest for the night */ - { - bool_ nighttime; - - /* Extract the current time */ - nighttime = ((bst(HOUR, turn) < 6) || (bst(HOUR, turn) >= 18)); - - /* Normal races rest at night */ - if (!vampire && !nighttime) - { - msg_print("The rooms are available only at night."); - msg_print(NULL); - return (FALSE); - } - - /* Vampires rest during daytime */ - if (vampire && nighttime) - { - msg_print("The rooms are available only during daylight for your kind."); - msg_print(NULL); - return (FALSE); - } - - /* Must cure HP draining status first */ - if ((p_ptr->poisoned > 0) || (p_ptr->cut > 0)) - { - msg_print("You need a healer, not a room."); - msg_print(NULL); - msg_print("Sorry, but I don't want anyone dying in here."); - return (FALSE); - } - - /* Let the time pass XXX XXX XXX */ - if (vampire) - { - /* Wait for sunset */ - while ((bst(HOUR, turn) >= 6) && (bst(HOUR, turn) < 18)) - { - turn += (10L * MINUTE); - } - } - else - { - /* Wait for sunrise */ - while ((bst(HOUR, turn) < 6) || (bst(HOUR, turn) >= 18)) - { - turn += (10L * MINUTE); - } - } - - /* Regen */ - p_ptr->chp = p_ptr->mhp; - p_ptr->csp = p_ptr->msp; - - /* Restore status */ - set_blind(0); - set_confused(0); - p_ptr->stun = 0; - - /* Message */ - if (vampire) msg_print("You awake refreshed for the new night."); - else msg_print("You awake refreshed for the new day."); - - /* Dungeon stuff */ - p_ptr->leaving = TRUE; - p_ptr->oldpx = p_ptr->px; - p_ptr->oldpy = p_ptr->py; - - /* Select new bounties. */ - select_bounties(); - - break; - } - - case BACT_RUMORS: /* Listen for rumors */ - { - char rumor[80]; - - get_rnd_line("rumors.txt", rumor); - msg_format("%s", rumor); - msg_print(NULL); - - break; - } - } - - return (TRUE); -} - - -/* - * Display quest information - */ -static void get_questinfo(int questnum) -{ - int i; - - - /* Print the quest info */ - prt(format("Quest Information (Danger level: %d)", quest[questnum].level), 5, 0); - - prt(quest[questnum].name, 7, 0); - - i = 0; - while ((i < 10) && (quest[questnum].desc[i][0] != '\0')) - { - c_put_str(TERM_YELLOW, quest[questnum].desc[i], i + 8, 0); - i++; - } -} - - -/* - * Request a quest from the Lord. - */ -static bool_ castle_quest(int y, int x) -{ - int plot = 0; - - quest_type *q_ptr; - - - clear_bldg(7, 18); - - /* Current plot of the building */ - plot = cave[y][x].special; - - /* Is there a quest available at the building? */ - if ((!plot) || (plots[plot] == QUEST_NULL)) - { - put_str("I don't have a quest for you at the moment.", 8, 0); - return FALSE; - } - - q_ptr = &quest[plots[plot]]; - - /* Quest is completed */ - if (q_ptr->status == QUEST_STATUS_COMPLETED) - { - /* Rewarded quest */ - q_ptr->status = QUEST_STATUS_FINISHED; - - process_hooks(HOOK_QUEST_FINISH, "(d)", plots[plot]); - - return (TRUE); - } - - /* Quest is still unfinished */ - else if (q_ptr->status == QUEST_STATUS_TAKEN) - { - put_str("You have not completed your current quest yet!", 8, 0); - put_str("Use CTRL-Q to check the status of your quest.", 9, 0); - put_str("Return when you have completed your quest.", 12, 0); - - return (FALSE); - } - /* Failed quest */ - else if (q_ptr->status == QUEST_STATUS_FAILED) - { - /* Mark quest as done (but failed) */ - q_ptr->status = QUEST_STATUS_FAILED_DONE; - - process_hooks(HOOK_QUEST_FAIL, "(d)", plots[plot]); - - return (FALSE); - } - /* No quest yet */ - else if (q_ptr->status == QUEST_STATUS_UNTAKEN) - { - if (process_hooks(HOOK_INIT_QUEST, "(d)", plots[plot])) return (FALSE); - - q_ptr->status = QUEST_STATUS_TAKEN; - - /* Assign a new quest */ - get_questinfo(plots[plot]); - - /* Add the hooks */ - quest[plots[plot]].init(plots[plot]); - - return (TRUE); - } - - return FALSE; -} - -/* - * Displaying town history -KMW- - */ -static void town_history(void) -{ - /* Save screen */ - screen_save(); - - /* Peruse the building help file */ - (void)show_file("bldg.txt", NULL, 0, 0); - - /* Load screen */ - screen_load(); -} - - -/* - * compare_weapon_aux2 -KMW- - */ -static void compare_weapon_aux2(object_type *o_ptr, int numblows, int r, int c, int mult, char attr[80], u32b f1, u32b f2, u32b f3, byte color) -{ - char tmp_str[80]; - - c_put_str(color, attr, r, c); - strnfmt(tmp_str, 80, "Attack: %d-%d damage", - numblows * ((o_ptr->dd * mult) + o_ptr->to_d), - numblows * ((o_ptr->ds * o_ptr->dd * mult) + o_ptr->to_d)); - put_str(tmp_str, r, c + 8); - r++; -} - - -/* - * compare_weapon_aux1 -KMW- - */ -static void compare_weapon_aux1(object_type *o_ptr, int col, int r) -{ - u32b f1, f2, f3, f4, f5, esp; - - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - - if (f1 & (TR1_SLAY_ANIMAL)) - { - compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 2, "Animals:", - f1, f2, f3, TERM_YELLOW); - } - if (f1 & (TR1_SLAY_EVIL)) - { - compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 2, "Evil:", - f1, f2, f3, TERM_YELLOW); - } - if (f1 & (TR1_SLAY_UNDEAD)) - { - compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Undead:", - f1, f2, f3, TERM_YELLOW); - } - if (f1 & (TR1_SLAY_DEMON)) - { - compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Demons:", - f1, f2, f3, TERM_YELLOW); - } - if (f1 & (TR1_SLAY_ORC)) - { - compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Orcs:", - f1, f2, f3, TERM_YELLOW); - } - if (f1 & (TR1_SLAY_TROLL)) - { - compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Trolls:", - f1, f2, f3, TERM_YELLOW); - } - if (f1 & (TR1_SLAY_GIANT)) - { - compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Giants:", - f1, f2, f3, TERM_YELLOW); - } - if (f1 & (TR1_SLAY_DRAGON)) - { - compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Dragons:", - f1, f2, f3, TERM_YELLOW); - } - if (f1 & (TR1_KILL_DRAGON)) - { - compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 5, "Dragons:", - f1, f2, f3, TERM_YELLOW); - } - if (f1 & (TR1_BRAND_ACID)) - { - compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Acid:", - f1, f2, f3, TERM_RED); - } - if (f1 & (TR1_BRAND_ELEC)) - { - compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Elec:", - f1, f2, f3, TERM_RED); - } - if (f1 & (TR1_BRAND_FIRE)) - { - compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Fire:", - f1, f2, f3, TERM_RED); - } - if (f1 & (TR1_BRAND_COLD)) - { - compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Cold:", - f1, f2, f3, TERM_RED); - } - if (f1 & (TR1_BRAND_POIS)) - { - compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Poison:", - f1, f2, f3, TERM_RED); - } -} - - -/* - * list_weapon -KMW- - */ -static void list_weapon(object_type *o_ptr, int row, int col) -{ - char o_name[80]; - - char tmp_str[80]; - - - object_desc(o_name, o_ptr, TRUE, 0); - c_put_str(TERM_YELLOW, o_name, row, col); - strnfmt(tmp_str, 80, "To Hit: %d To Damage: %d", o_ptr->to_h, o_ptr->to_d); - put_str(tmp_str, row + 1, col); - strnfmt(tmp_str, 80, "Dice: %d Sides: %d", o_ptr->dd, o_ptr->ds); - put_str(tmp_str, row + 2, col); - strnfmt(tmp_str, 80, "Number of Blows: %d", p_ptr->num_blow); - put_str(tmp_str, row + 3, col); - c_put_str(TERM_YELLOW, "Possible Damage:", row + 5, col); - strnfmt(tmp_str, 80, "One Strike: %d-%d damage", o_ptr->dd + o_ptr->to_d, - (o_ptr->ds*o_ptr->dd) + o_ptr->to_d); - put_str(tmp_str, row + 6, col + 1); - strnfmt(tmp_str, 80, "One Attack: %d-%d damage", p_ptr->num_blow*(o_ptr->dd + o_ptr->to_d), - p_ptr->num_blow*(o_ptr->ds*o_ptr->dd + o_ptr->to_d)); - put_str(tmp_str, row + 7, col + 1); -} - - -/* - * Select melee weapons - */ -static bool_ item_tester_hook_melee_weapon(object_type *o_ptr) -{ - return (wield_slot(o_ptr) == INVEN_WIELD); -} - -/* - * compare_weapons -KMW- - */ -static bool_ compare_weapons(void) -{ - int item, item2, i; - - object_type *o1_ptr, *o2_ptr, *orig_ptr; - - object_type *i_ptr; - - cptr q, s; - - - clear_bldg(6, 18); - - o1_ptr = NULL; - o2_ptr = NULL; - i_ptr = NULL; - - /* Store copy of original wielded weapon in pack slot */ - i_ptr = &p_ptr->inventory[INVEN_WIELD]; - orig_ptr = &p_ptr->inventory[INVEN_PACK]; - object_copy(orig_ptr, i_ptr); - - i = 6; - /* Get first weapon */ - /* Restrict choices to meele weapons */ - item_tester_hook = item_tester_hook_melee_weapon; - - q = "What is your first melee weapon? "; - s = "You have nothing to compare."; - if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN))) - { - object_wipe(orig_ptr); - return (FALSE); - } - - /* Get the item (in the pack) */ - if (item >= 0) - o1_ptr = &p_ptr->inventory[item]; - - /* Get second weapon */ - /* Restrict choices to melee weapons */ - item_tester_hook = item_tester_hook_melee_weapon; - - q = "What is your second melee weapon? "; - s = "You have nothing to compare."; - if (!get_item(&item2, q, s, (USE_EQUIP | USE_INVEN))) - { - object_wipe(orig_ptr); - return (FALSE); - } - - /* Get the item (in the pack) */ - if (item2 >= 0) o2_ptr = &p_ptr->inventory[item2]; - - put_str("Based on your current abilities, here is what your weapons will do", 4, 2); - - i_ptr = &p_ptr->inventory[INVEN_WIELD]; - object_copy(i_ptr, o1_ptr); - calc_bonuses(TRUE); - - list_weapon(o1_ptr, i, 2); - compare_weapon_aux1(o1_ptr, 2, i + 8); - - i_ptr = &p_ptr->inventory[INVEN_WIELD]; - if (item2 == INVEN_WIELD) - object_copy(i_ptr, orig_ptr); - else - object_copy(i_ptr, o2_ptr); - calc_bonuses(TRUE); - - list_weapon(o2_ptr, i, 40); - compare_weapon_aux1(o2_ptr, 40, i + 8); - - i_ptr = &p_ptr->inventory[INVEN_WIELD]; - object_copy(i_ptr, orig_ptr); - calc_bonuses(TRUE); - - object_wipe(orig_ptr); - - put_str("(Only highest damage applies per monster. Special damage not cumulative)", 20, 0); - - return (TRUE); -} - - -/* - * general all-purpose fixing routine for items from building personnel - * sharpen arrows, repair armor, repair weapon - * -KMW- - */ -static bool_ fix_item(int istart, int iend, int ispecific, bool_ iac, - int ireward, bool_ set_reward) -{ - int i; - - int j = 9; - - int maxenchant = (p_ptr->lev / 5); - - object_type *o_ptr; - - char out_val[80], tmp_str[80]; - - bool_ repaired = FALSE; - - clear_bldg(5, 18); - strnfmt(tmp_str, 80, " Based on your skill, we can improve up to +%d", maxenchant); - prt(tmp_str, 5, 0); - prt("Status", 7, 30); - - for (i = istart; i <= iend; i++) - { - o_ptr = &p_ptr->inventory[i]; - if (ispecific > 0) - { - if (o_ptr->tval != ispecific) - continue; - } - - if (o_ptr->tval) - { - object_desc(tmp_str, o_ptr, FALSE, 1); - - if ((o_ptr->name1 && (o_ptr->ident & 0x08))) - strnfmt(out_val, 80, "%-40s: beyond our skills!", tmp_str); - else if (o_ptr->name1) - strnfmt(out_val, 80, "%-40s: in fine condition", tmp_str); - else - { - if ((iac) && (o_ptr->to_a <= -3)) - { - strnfmt(out_val, 80, "%-40s: beyond repair, buy a new one", tmp_str); - } - else if ((iac) && (o_ptr->to_a < maxenchant)) - { - o_ptr->to_a++; - strnfmt(out_val, 80, "%-40s: polished -> (%d)", tmp_str, o_ptr->to_a); - repaired = TRUE; - } - else if ((!iac) && ((o_ptr->to_h <= -3) || (o_ptr->to_d <= -3))) - { - strnfmt(out_val, 80, "%-40s: beyond repair, buy a new one", tmp_str); - } - /* Sharpen a weapon */ - else if ((!iac) && ((o_ptr->to_h < maxenchant) || - (o_ptr->to_d < maxenchant))) - { - if (o_ptr->to_h < maxenchant) - o_ptr->to_h++; - if (o_ptr->to_d < maxenchant) - o_ptr->to_d++; - strnfmt(out_val, 80, "%-40s: sharpened -> (%d,%d)", tmp_str, - o_ptr->to_h, o_ptr->to_d); - repaired = TRUE; - } - else - strnfmt(out_val, 80, "%-40s: in fine condition", tmp_str); - } - prt(out_val, j++, 0); - } - } - - if (!repaired) - { - msg_print("You don't have anything appropriate."); - msg_print(NULL); - } - else - { - msg_print("Press the spacebar to continue"); - msg_print(NULL); - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - p_ptr->update |= (PU_BONUS); - } - clear_bldg(5, 18); - - return (repaired); -} - - -/* - * Research Item - */ -static bool_ research_item(void) -{ - clear_bldg(5, 18); - return (identify_fully()); -} - - -/* - * Show the current quest monster. - */ -static void show_quest_monster(void) -{ - monster_race* r_ptr = &r_info[bounties[0][0]]; - - - msg_format("Quest monster: %s. " - "Need to turn in %d corpse%s to receive reward.", - r_name + r_ptr->name, bounties[0][1], - (bounties[0][1] > 1 ? "s" : "")); - msg_print(NULL); -} - - -/* - * Show the current bounties. - */ -static void show_bounties(void) -{ - int i, j = 6; - - monster_race* r_ptr; - - char buff[80]; - - - clear_bldg(7, 18); - - c_prt(TERM_YELLOW, "Currently active bounties:", 4, 2); - - for (i = 1; i < MAX_BOUNTIES; i++, j++) - { - r_ptr = &r_info[bounties[i][0]]; - - strnfmt(buff, 80, "%-30s (%d gp)", r_name + r_ptr->name, bounties[i][1]); - - prt(buff, j, 2); - - if (j >= 17) - { - msg_print("Press space for more."); - msg_print(NULL); - - clear_bldg(7, 18); - j = 5; - } - } -} - - -/* - * Filter for corpses that currently have a bounty on them. - */ -static bool_ item_tester_hook_bounty(object_type* o_ptr) -{ - int i; - - - if (o_ptr->tval == TV_CORPSE) - { - for (i = 1; i < MAX_BOUNTIES; i++) - { - if (bounties[i][0] == o_ptr->pval2) return (TRUE); - } - } - - return (FALSE); -} - -/* Filter to match the quest monster's corpse. */ -static bool_ item_tester_hook_quest_monster(object_type* o_ptr) -{ - if ((o_ptr->tval == TV_CORPSE) && - (o_ptr->pval2 == bounties[0][0])) return (TRUE); - return (FALSE); -} - - -/* - * Return the boost in the corpse's value depending on how rare the body - * part is. - */ -static int corpse_value_boost(int sval) -{ - switch (sval) - { - case SV_CORPSE_HEAD: - case SV_CORPSE_SKULL: - { - return (1); - } - - /* Default to no boost. */ - default: - { - return (0); - } - } -} - -/* - * Sell a corpse, if there's currently a bounty on it. - */ -static void sell_corpses(void) -{ - object_type* o_ptr; - - int i, boost = 0; - - s16b value; - - int item; - - - /* Set the hook. */ - item_tester_hook = item_tester_hook_bounty; - - /* Select a corpse to sell. */ - if (!get_item(&item, "Sell which corpse", - "You have no corpses you can sell.", USE_INVEN)) return; - - o_ptr = &p_ptr->inventory[item]; - - /* Exotic body parts are worth more. */ - boost = corpse_value_boost(o_ptr->sval); - - /* Try to find a match. */ - for (i = 1; i < MAX_BOUNTIES; i++) - { - if (o_ptr->pval2 == bounties[i][0]) - { - value = bounties[i][1] + boost * (r_info[o_ptr->pval2].level); - - msg_format("Sold for %ld gold pieces.", value); - msg_print(NULL); - p_ptr->au += value; - - /* Increase the number of collected bounties */ - total_bounties++; - - inc_stack_size(item, -1); - - return; - } - } - - msg_print("Sorry, but that monster does not have a bounty on it."); - msg_print(NULL); -} - - - -/* - * Hook for bounty monster selection. - */ -static bool_ mon_hook_bounty(int r_idx) -{ - monster_race* r_ptr = &r_info[r_idx]; - - - /* Reject uniques */ - if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE); - - /* Reject those who cannot leave anything */ - if (!(r_ptr->flags9 & RF9_DROP_CORPSE) && - !(r_ptr->flags9 & RF9_DROP_SKELETON)) return (FALSE); - - /* Reject pets */ - if (r_ptr->flags7 & RF7_PET) return (FALSE); - - /* Reject friendly creatures */ - if (r_ptr->flags7 & RF7_FRIENDLY) return (FALSE); - - /* The rest are acceptable */ - return (TRUE); -} - - -static void select_quest_monster(void) -{ - monster_race* r_ptr; - - int amt; - - - /* - * Set up the hooks -- no bounties on uniques or monsters - * with no corpses - */ - get_mon_num_hook = mon_hook_bounty; - get_mon_num_prep(); - - /* Set up the quest monster. */ - bounties[0][0] = get_mon_num(p_ptr->lev); - - r_ptr = &r_info[bounties[0][0]]; - - /* - * Select the number of monsters needed to kill. Groups and - * breeders require more - */ - amt = randnor(5, 3); - - if (amt < 2) amt = 2; - - if (r_ptr->flags1 & RF1_FRIEND) amt *= 3; amt /= 2; - if (r_ptr->flags1 & RF1_FRIENDS) amt *= 2; - if (r_ptr->flags4 & RF4_MULTIPLY) amt *= 3; - - if (r_ptr->flags7 & RF7_AQUATIC) amt /= 2; - - bounties[0][1] = amt; - - /* Undo the filters */ - get_mon_num_hook = NULL; - get_mon_num_prep(); -} - - - -/* - * Sell a corpse for a reward. - */ -static void sell_quest_monster(void) -{ - object_type* o_ptr; - - int item; - - - /* Set the hook. */ - item_tester_hook = item_tester_hook_quest_monster; - - /* Select a corpse to sell. */ - if (!get_item(&item, "Sell which corpse", - "You have no corpses you can sell.", USE_INVEN)) return; - - o_ptr = &p_ptr->inventory[item]; - - bounties[0][1] -= o_ptr->number; - - /* Completed the quest. */ - if (bounties[0][1] <= 0) - { - int m; - monster_race *r_ptr; - - cmsg_print(TERM_YELLOW, "You have completed your quest!"); - msg_print(NULL); - - /* Give full knowledge */ - - /* Hack -- Maximal info */ - r_ptr = &r_info[bounties[0][0]]; - - msg_print(format("Well done! As a reward I'll teach you everything " - "about the %s, (check your recall)", - r_name + r_ptr->name)); - - r_ptr->r_wake = r_ptr->r_ignore = MAX_UCHAR; - - /* Observe "maximal" attacks */ - for (m = 0; m < 4; m++) - { - /* Examine "actual" blows */ - if (r_ptr->blow[m].effect || r_ptr->blow[m].method) - { - /* Hack -- maximal observations */ - r_ptr->r_blows[m] = MAX_UCHAR; - } - } - - /* Hack -- maximal drops */ - r_ptr->r_drop_gold = r_ptr->r_drop_item = - (((r_ptr->flags1 & (RF1_DROP_4D2)) ? 8 : 0) + - ((r_ptr->flags1 & (RF1_DROP_3D2)) ? 6 : 0) + - ((r_ptr->flags1 & (RF1_DROP_2D2)) ? 4 : 0) + - ((r_ptr->flags1 & (RF1_DROP_1D2)) ? 2 : 0) + - ((r_ptr->flags1 & (RF1_DROP_90)) ? 1 : 0) + - ((r_ptr->flags1 & (RF1_DROP_60)) ? 1 : 0)); - - /* Hack -- but only "valid" drops */ - if (r_ptr->flags1 & (RF1_ONLY_GOLD)) r_ptr->r_drop_item = 0; - if (r_ptr->flags1 & (RF1_ONLY_ITEM)) r_ptr->r_drop_gold = 0; - - /* Hack -- observe many spells */ - r_ptr->r_cast_inate = MAX_UCHAR; - r_ptr->r_cast_spell = MAX_UCHAR; - - /* Hack -- know all the flags */ - r_ptr->r_flags1 = r_ptr->flags1; - r_ptr->r_flags2 = r_ptr->flags2; - r_ptr->r_flags3 = r_ptr->flags3; - r_ptr->r_flags4 = r_ptr->flags4; - r_ptr->r_flags5 = r_ptr->flags5; - r_ptr->r_flags6 = r_ptr->flags6; - r_ptr->r_flags4 = r_ptr->flags7; - r_ptr->r_flags5 = r_ptr->flags8; - r_ptr->r_flags6 = r_ptr->flags9; - - msg_print(NULL); - - select_quest_monster(); - - } - else - { - msg_format("Well done, only %d more to go.", bounties[0][1]); - msg_print(NULL); - } - - inc_stack_size(item, -1); -} - - - -/* - * Fill the bounty list with monsters. - */ -void select_bounties(void) -{ - int i, j; - - - select_quest_monster(); - - /* - * Set up the hooks -- no bounties on uniques or monsters - * with no corpses - */ - get_mon_num_hook = mon_hook_bounty; - get_mon_num_prep(); - - for (i = 1; i < MAX_BOUNTIES; i++) - { - int lev = i * 5 + randnor(0, 2); - monster_race* r_ptr; - s16b r_idx; - s16b val; - - if (lev < 1) lev = 1; - - if (lev >= MAX_DEPTH) lev = MAX_DEPTH - 1; - - /* We don't want to duplicate entries in the list */ - while (TRUE) - { - r_idx = get_mon_num(lev); - - for (j = 0; j < i; j++) - { - if (bounties[j][0] == r_idx) continue; - } - - break; - } - - bounties[i][0] = r_idx; - - r_ptr = &r_info[r_idx]; - - val = r_ptr->mexp + r_ptr->level * 20 + randnor(0, r_ptr->level * 2); - - if (val < 1) val = 1; - - bounties[i][1] = val; - } - - /* Undo the filters. */ - get_mon_num_hook = NULL; - get_mon_num_prep(); -} - -/* - * Execute a building command - */ -bool_ bldg_process_command(store_type *s_ptr, int i) -{ - store_action_type *ba_ptr = &ba_info[st_info[s_ptr->st_idx].actions[i]]; - - int bact = ba_ptr->action; - - int bcost; - - bool_ paid = FALSE; - - bool_ set_reward = FALSE; - - bool_ recreate = FALSE; - - - if (is_state(s_ptr, STORE_LIKED)) - { - bcost = ba_ptr->costs[STORE_LIKED]; - } - else if (is_state(s_ptr, STORE_HATED)) - { - bcost = ba_ptr->costs[STORE_HATED]; - } - else - { - bcost = ba_ptr->costs[STORE_NORMAL]; - } - - /* action restrictions */ - if (((ba_ptr->action_restr == 1) && (is_state(s_ptr, STORE_LIKED))) || - ((ba_ptr->action_restr == 2) && (!is_state(s_ptr, STORE_LIKED)))) - { - msg_print("You have no right to choose that!"); - msg_print(NULL); - return FALSE; - } - - /* If player has loan and the time is out, few things work in stores */ - if (p_ptr->loan && !p_ptr->loan_time) - { - if ((bact != BACT_SELL) && (bact != BACT_VIEW_BOUNTIES) && - (bact != BACT_SELL_CORPSES) && - (bact != BACT_VIEW_QUEST_MON) && - (bact != BACT_SELL_QUEST_MON) && - (bact != BACT_EXAMINE) && (bact != BACT_STEAL) && - (bact != BACT_PAY_BACK_LOAN)) - { - msg_print("You are not allowed to do that until you have paid back your loan."); - msg_print(NULL); - return FALSE; - } - } - - /* check gold */ - if (bcost > p_ptr->au) - { - msg_print("You do not have the gold!"); - msg_print(NULL); - return FALSE; - } - - if (!bcost) set_reward = TRUE; - - switch (bact) - { - case BACT_RESEARCH_ITEM: - { - paid = research_item(); - break; - } - - case BACT_TOWN_HISTORY: - { - town_history(); - break; - } - - case BACT_RACE_LEGENDS: - { - race_legends(); - break; - } - - case BACT_QUEST1: - case BACT_QUEST2: - case BACT_QUEST3: - case BACT_QUEST4: - { - int y = 1, x = 1; - bool_ ok = FALSE; - - while ((x < cur_wid - 1) && !ok) - { - y = 1; - while ((y < cur_hgt - 1) && !ok) - { - /* Found the location of the quest info ? */ - if (bact - BACT_QUEST1 + FEAT_QUEST1 == cave[y][x].feat) - { - /* Stop the loop */ - ok = TRUE; - } - y++; - } - x++; - } - - if (ok) - { - recreate = castle_quest(y - 1, x - 1); - ; - } - else - { - msg_format("ERROR: no quest info feature found: %d", bact - BACT_QUEST1 + FEAT_QUEST1); - } - break; - } - - case BACT_KING_LEGENDS: - case BACT_ARENA_LEGENDS: - case BACT_LEGENDS: - { - show_highclass(building_loc); - break; - } - - case BACT_POSTER: - case BACT_ARENA_RULES: - case BACT_ARENA: - { - arena_comm(bact); - break; - } - - case BACT_IN_BETWEEN: - case BACT_CRAPS: - case BACT_SPIN_WHEEL: - case BACT_DICE_SLOTS: - case BACT_GAMBLE_RULES: - { - gamble_comm(bact); - break; - } - - case BACT_REST: - case BACT_RUMORS: - case BACT_FOOD: - { - paid = inn_comm(bact); - break; - } - - case BACT_RESEARCH_MONSTER: - { - paid = !research_mon(); - break; - } - - case BACT_COMPARE_WEAPONS: - { - paid = compare_weapons(); - break; - } - - case BACT_ENCHANT_WEAPON: - { - paid = fix_item(INVEN_WIELD, INVEN_WIELD, 0, FALSE, - BACT_ENCHANT_WEAPON, set_reward); - break; - } - - case BACT_ENCHANT_ARMOR: - { - paid = fix_item(INVEN_BODY, INVEN_FEET, 0, TRUE, - BACT_ENCHANT_ARMOR, set_reward); - break; - } - - /* needs work */ - case BACT_RECHARGE: - { - if (recharge(80)) paid = TRUE; - break; - } - - /* needs work */ - case BACT_IDENTS: - { - identify_pack(); - msg_print("Your possessions have been identified."); - msg_print(NULL); - paid = TRUE; - break; - } - - /* needs work */ - case BACT_STAR_HEAL: - { - hp_player(200); - set_poisoned(0); - set_blind(0); - set_confused(0); - set_cut(0); - set_stun(0); - if (p_ptr->black_breath) - { - msg_print("The hold of the Black Breath on you is broken!"); - p_ptr->black_breath = FALSE; - } - paid = TRUE; - break; - } - - /* needs work */ - case BACT_HEALING: - { - hp_player(200); - set_poisoned(0); - set_blind(0); - set_confused(0); - set_cut(0); - set_stun(0); - paid = TRUE; - break; - } - - /* needs work */ - case BACT_RESTORE: - { - if (do_res_stat(A_STR, TRUE)) paid = TRUE; - if (do_res_stat(A_INT, TRUE)) paid = TRUE; - if (do_res_stat(A_WIS, TRUE)) paid = TRUE; - if (do_res_stat(A_DEX, TRUE)) paid = TRUE; - if (do_res_stat(A_CON, TRUE)) paid = TRUE; - if (do_res_stat(A_CHR, TRUE)) paid = TRUE; - break; - } - - case BACT_ENCHANT_ARROWS: - { - paid = fix_item(0, INVEN_WIELD, TV_ARROW, FALSE, - BACT_ENCHANT_ARROWS, set_reward); - break; - } - - case BACT_ENCHANT_BOW: - { - paid = fix_item(INVEN_BOW, INVEN_BOW, TV_BOW, FALSE, - BACT_ENCHANT_BOW, set_reward); - break; - } - - case BACT_RECALL: - { - p_ptr->word_recall = 1; - msg_print("The air about you becomes charged..."); - paid = TRUE; - break; - } - - case BACT_TELEPORT_LEVEL: - { - if (reset_recall(FALSE)) - { - p_ptr->word_recall = 1; - msg_print("The air about you becomes charged..."); - paid = TRUE; - } - break; - } - - case BACT_MIMIC_NORMAL: - { - set_mimic(0, 0, 0); - paid = TRUE; - break; - } - - case BACT_VIEW_BOUNTIES: - { - show_bounties(); - break; - } - - case BACT_VIEW_QUEST_MON: - { - show_quest_monster(); - break; - } - - case BACT_SELL_QUEST_MON: - { - sell_quest_monster(); - break; - } - - case BACT_SELL_CORPSES: - { - sell_corpses(); - break; - } - - case BACT_DIVINATION: - { - int i, count = 0; - bool_ something = FALSE; - - while (count < 1000) - { - count++; - i = rand_int(MAX_FATES); - if (!fates[i].fate) continue; - if (fates[i].know) continue; - msg_print("You know a little more of your fate."); - - fates[i].know = TRUE; - something = TRUE; - break; - } - - if (!something) msg_print("Well, you have no fate, but I'll keep your money anyway!"); - - paid = TRUE; - break; - - } - - case BACT_BUY: - { - store_purchase(); - break; - } - - case BACT_SELL: - { - store_sell(); - break; - } - - case BACT_EXAMINE: - { - store_examine(); - break; - } - - case BACT_STEAL: - { - store_stole(); - break; - } - - case BACT_REQUEST_ITEM: - { - store_request_item(); - paid = TRUE; - break; - } - - case BACT_GET_LOAN: - { - s32b i, req; - char prompt[80]; - - if (p_ptr->loan) - { - msg_print("You already have a loan!"); - break; - } - - req = p_ptr->au; - - for (i = 0; i < INVEN_TOTAL; i++) - req += object_value_real(&p_ptr->inventory[i]); - - if (req > 100000) req = 100000; - if ((req + p_ptr->au) > PY_MAX_GOLD) req = PY_MAX_GOLD - p_ptr->au; - - strnfmt(prompt, sizeof (prompt), - "How much would you like to get (0-%ld) ?", req); - - req = get_quantity(prompt, req); - - if (req) - { - p_ptr->loan += req; - p_ptr->au += req; - p_ptr->loan_time += req; - - msg_format("You receive %i gold pieces", req); - - paid = TRUE; - } - else - msg_format("You did not request any money!"); - - break; - } - - case BACT_PAY_BACK_LOAN: - { - s32b req; - char prompt[80]; - - if (p_ptr->loan) - { - msg_format("You have nothing to payback!"); - break; - } - - msg_format("You have a loan of %i.", p_ptr->loan); - - req = ((p_ptr->loan + bcost) > p_ptr->au) ? p_ptr->au - bcost : p_ptr->loan; - - strnfmt(prompt, sizeof (prompt), - "How much would you like to pay back (0-%ld) ?", req); - - req = get_quantity(prompt, req); - - p_ptr->loan -= req; - p_ptr->au -= req; - - if (!p_ptr->loan) p_ptr->loan_time = 0; - - msg_format("You pay back %i gold pieces", req); - paid = TRUE; - break; - } - - case BACT_DROP_ITEM: - { - quest_bounty_drop_item(); - break; - } - - case BACT_GET_ITEM: - { - quest_bounty_get_item(); - break; - } - - case BACT_LIBRARY_QUEST: - { - quest_library_building(&paid, &recreate); - break; - } - - case BACT_FIREPROOF_QUEST: - { - quest_fireproof_building(&paid, &recreate); - break; - } - - case BACT_EREBOR_KEY: - { - msg_print("You will need Thorin's Key and Thrain's Map" - " to get anywhere in Erebor. One may be found" - " in the Barrow-Downs. The other, in Mirkwood."); - break; - } - - default: - { - if (process_hooks_ret(HOOK_BUILDING_ACTION, "dd", "(d)", bact)) - { - paid = process_hooks_return[0].num; - recreate = process_hooks_return[1].num; - } - break; - } - } - - if (paid) - { - p_ptr->au -= bcost; - - /* Display the current gold */ - store_prt_gold(); - } - - return (recreate); -} - - -/* - * Enter quest level - */ -void enter_quest(void) -{ - if (!(cave[p_ptr->py][p_ptr->px].feat == FEAT_QUEST_ENTER)) - { - msg_print("You see no quest level here."); - return; - } - else - { - /* Player enters a new quest */ - p_ptr->oldpy = p_ptr->py; - p_ptr->oldpx = p_ptr->px; - - leaving_quest = p_ptr->inside_quest; - - p_ptr->inside_quest = cave[p_ptr->py][p_ptr->px].special; - dun_level = 1; - p_ptr->leaving = TRUE; - p_ptr->oldpx = p_ptr->px; - p_ptr->oldpy = p_ptr->py; - } -} - - -/* - * Do building commands - */ -void do_cmd_bldg(void) -{ - int i, which, x = p_ptr->px, y = p_ptr->py; - - char command; - - bool_ validcmd; - - store_type *s_ptr; - - store_action_type *ba_ptr; - - - if (cave[p_ptr->py][p_ptr->px].feat != FEAT_SHOP) - { - msg_print("You see no building here."); - return; - } - - which = cave[p_ptr->py][p_ptr->px].special; - building_loc = which; - - s_ptr = &town_info[p_ptr->town_num].store[which]; - - p_ptr->oldpy = p_ptr->py; - p_ptr->oldpx = p_ptr->px; - - /* Forget the lite */ - /* forget_lite(); */ - - /* Forget the view */ - forget_view(); - - /* Hack -- Increase "icky" depth */ - character_icky++; - - command_arg = 0; - command_rep = 0; - command_new = 0; - - show_building(s_ptr); - leave_bldg = FALSE; - - while (!leave_bldg) - { - validcmd = FALSE; - prt("", 1, 0); - command = inkey(); - - if (command == ESCAPE) - { - leave_bldg = TRUE; - p_ptr->inside_arena = FALSE; - break; - } - - for (i = 0; i < 6; i++) - { - ba_ptr = &ba_info[st_info->actions[i]]; - - if (ba_ptr->letter) - { - if (ba_ptr->letter == command) - { - validcmd = TRUE; - break; - } - } - if (ba_ptr->letter_aux) - { - if (ba_ptr->letter_aux == command) - { - validcmd = TRUE; - break; - } - } - } - - if (validcmd) - bldg_process_command(s_ptr, i); - - /* Notice stuff */ - notice_stuff(); - - /* Handle stuff */ - handle_stuff(); - } - - /* Flush messages XXX XXX XXX */ - msg_print(NULL); - - /* Reinit wilderness to activate quests ... */ - wilderness_gen(TRUE); - p_ptr->py = y; - p_ptr->px = x; - - /* Hack -- Decrease "icky" depth */ - character_icky--; - - /* Clear the screen */ - Term_clear(); - - /* Update the visuals */ - p_ptr->update |= (PU_VIEW | PU_MON_LITE | PU_MONSTERS | PU_BONUS); - - /* Redraw entire screen */ - p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP); - - /* Window stuff */ - p_ptr->window |= (PW_OVERHEAD); -} - - diff --git a/src/bldg.cc b/src/bldg.cc new file mode 100644 index 00000000..2a87f035 --- /dev/null +++ b/src/bldg.cc @@ -0,0 +1,2234 @@ +/* File: bldg.c */ + +/* + * Purpose: Building commands + * Created by Ken Wigle for Kangband - a variant of Angband 2.8.3 + * -KMW- + * + * Rewritten for Kangband 2.8.3i using Kamband's version of + * bldg.c as written by Ivan Tkatchev + * + * Changed for ZAngband by Robert Ruehlmann + * + * Heavily modified for ToME by DarkGod + */ + +#include "angband.h" +#include "hooks.h" +#include "q_library.h" +#include "q_fireprof.h" +#include "q_bounty.h" + +/* hack as in leave_store in store.c */ +static bool_ leave_bldg = FALSE; + +/* remember building location */ +static int building_loc = 0; + + +/* + * A helper function for is_state + */ +bool_ is_state_aux(store_type *s_ptr, int state) +{ + owner_type *ow_ptr = &ow_info[s_ptr->owner]; + + + /* Check race */ + if (ow_ptr->races[state][p_ptr->prace / 32] & (1 << p_ptr->prace)) + { + return (TRUE); + } + + /* Check class */ + if (ow_ptr->classes[state][p_ptr->prace / 32] & (1 << p_ptr->pclass)) + { + return (TRUE); + } + + /* All failed */ + return (FALSE); +} + + +/* + * Test if the state accords with the player + */ +bool_ is_state(store_type *s_ptr, int state) +{ + if (state == STORE_NORMAL) + { + if (is_state_aux(s_ptr, STORE_LIKED)) return (FALSE); + if (is_state_aux(s_ptr, STORE_HATED)) return (FALSE); + return (TRUE); + } + + else + { + return (is_state_aux(s_ptr, state)); + } +} + + +/* + * Clear the building information + */ +static void clear_bldg(int min_row, int max_row) +{ + int i; + + + for (i = min_row; i <= max_row; i++) + { + prt("", i, 0); + } +} + + +/* + * Display a building. + */ +void show_building(store_type *s_ptr) +{ + char buff[20]; + + int i; + + byte action_color; + + char tmp_str[80]; + + store_info_type *st_ptr = &st_info[s_ptr->st_idx]; + + store_action_type *ba_ptr; + + + for (i = 0; i < 6; i++) + { + ba_ptr = &ba_info[st_ptr->actions[i]]; + + if (ba_ptr->letter != '.') + { + if (ba_ptr->action_restr == 0) + { + if ((is_state(s_ptr, STORE_LIKED) && (ba_ptr->costs[STORE_LIKED] == 0)) || + (is_state(s_ptr, STORE_HATED) && (ba_ptr->costs[STORE_HATED] == 0)) || + (is_state(s_ptr, STORE_NORMAL) && (ba_ptr->costs[STORE_NORMAL] == 0))) + { + action_color = TERM_WHITE; + buff[0] = '\0'; + } + else if (is_state(s_ptr, STORE_LIKED)) + { + action_color = TERM_L_GREEN; + strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_LIKED]); + } + else if (is_state(s_ptr, STORE_HATED)) + { + action_color = TERM_RED; + strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_HATED]); + } + else + { + action_color = TERM_YELLOW; + strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_NORMAL]); + } + } + else if (ba_ptr->action_restr == 1) + { + if ((is_state(s_ptr, STORE_LIKED) && (ba_ptr->costs[STORE_LIKED] == 0)) || + (is_state(s_ptr, STORE_NORMAL) && (ba_ptr->costs[STORE_NORMAL] == 0))) + { + action_color = TERM_WHITE; + buff[0] = '\0'; + } + else if (is_state(s_ptr, STORE_LIKED)) + { + action_color = TERM_L_GREEN; + strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_LIKED]); + } + else if (is_state(s_ptr, STORE_HATED)) + { + action_color = TERM_L_DARK; + strnfmt(buff, 20, "(closed)"); + } + else + { + action_color = TERM_YELLOW; + strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_NORMAL]); + } + } + else + { + if (is_state(s_ptr, STORE_LIKED) && (ba_ptr->costs[STORE_LIKED] == 0)) + { + action_color = TERM_WHITE; + buff[0] = '\0'; + } + else if (is_state(s_ptr, STORE_LIKED)) + { + action_color = TERM_L_GREEN; + strnfmt(buff, 20, "(%dgp)", ba_ptr->costs[STORE_LIKED]); + } + else + { + action_color = TERM_L_DARK; + strnfmt(buff, 20, "(closed)"); + } + } + + strnfmt(tmp_str, 80, " %c", ba_ptr->letter); + c_put_str(TERM_YELLOW, tmp_str, 21 + (i / 2), 17 + (30 * (i % 2))); + + strnfmt(tmp_str, 80, ") %s %s", ba_ptr->name + ba_name, buff); + c_put_str(action_color, tmp_str, 21 + (i / 2), 2 + 17 + (30 * (i % 2))); + } + } +} + + +/* reset timed flags */ +static void reset_tim_flags() +{ + p_ptr->fast = 0; /* Timed -- Fast */ + p_ptr->slow = 0; /* Timed -- Slow */ + p_ptr->blind = 0; /* Timed -- Blindness */ + p_ptr->paralyzed = 0; /* Timed -- Paralysis */ + p_ptr->confused = 0; /* Timed -- Confusion */ + p_ptr->afraid = 0; /* Timed -- Fear */ + p_ptr->image = 0; /* Timed -- Hallucination */ + p_ptr->poisoned = 0; /* Timed -- Poisoned */ + p_ptr->cut = 0; /* Timed -- Cut */ + p_ptr->stun = 0; /* Timed -- Stun */ + + p_ptr->protevil = 0; /* Timed -- Protection */ + p_ptr->protgood = 0; /* Timed -- Protection */ + p_ptr->invuln = 0; /* Timed -- Invulnerable */ + p_ptr->hero = 0; /* Timed -- Heroism */ + p_ptr->shero = 0; /* Timed -- Super Heroism */ + p_ptr->shield = 0; /* Timed -- Shield Spell */ + p_ptr->blessed = 0; /* Timed -- Blessed */ + p_ptr->tim_invis = 0; /* Timed -- Invisibility */ + p_ptr->tim_infra = 0; /* Timed -- Infra Vision */ + + p_ptr->oppose_acid = 0; /* Timed -- oppose acid */ + p_ptr->oppose_elec = 0; /* Timed -- oppose lightning */ + p_ptr->oppose_fire = 0; /* Timed -- oppose heat */ + p_ptr->oppose_cold = 0; /* Timed -- oppose cold */ + p_ptr->oppose_pois = 0; /* Timed -- oppose poison */ + + p_ptr->confusing = 0; /* Touch of Confusion */ +} + + +/* + * arena commands + */ +static void arena_comm(int cmd) +{ + char tmp_str[80]; + + monster_race *r_ptr; + + cptr name; + + + switch (cmd) + { + case BACT_ARENA: + { + if (p_ptr->arena_number == MAX_ARENA_MONS) + { + clear_bldg(5, 19); + prt(" Arena Victor!", 5, 0); + prt("Congratulations! You have defeated all before you.", 7, 0); + prt("For that, receive the prize: 10,000 gold pieces", 8, 0); + prt("", 10, 0); + prt("", 11, 0); + p_ptr->au += 10000; + msg_print("Press the space bar to continue"); + msg_print(NULL); + p_ptr->arena_number++; + } + else if (p_ptr->arena_number > MAX_ARENA_MONS) + { + msg_print("You enter the arena briefly and bask in your glory."); + msg_print(NULL); + } + else + { + p_ptr->inside_arena = TRUE; + p_ptr->exit_bldg = FALSE; + reset_tim_flags(); + p_ptr->leaving = TRUE; + p_ptr->oldpx = p_ptr->px; + p_ptr->oldpy = p_ptr->py; + leave_bldg = TRUE; + } + + break; + } + + case BACT_POSTER: + { + if (p_ptr->arena_number == MAX_ARENA_MONS) + msg_print("You are victorious. Enter the arena for the ceremony."); + else if (p_ptr->arena_number > MAX_ARENA_MONS) + msg_print("You have won against all foes."); + else + { + r_ptr = &r_info[arena_monsters[p_ptr->arena_number]]; + name = (r_name + r_ptr->name); + strnfmt(tmp_str, 80, "Do I hear any challenges against: %s", name); + msg_print(tmp_str); + msg_print(NULL); + } + + break; + } + + case BACT_ARENA_RULES: + { + /* Save screen */ + screen_save(); + + /* Peruse the arena help file */ + (void)show_file("arena.txt", NULL, 0, 0); + + /* Load screen */ + screen_load(); + + break; + } + } +} + + +/* + * display fruit for dice slots + */ +static void display_fruit(int row, int col, int fruit) +{ + switch (fruit) + { + case 0: /* lemon */ + { + c_put_str(TERM_YELLOW, " ####.", row, col); + c_put_str(TERM_YELLOW, " # #", row + 1, col); + c_put_str(TERM_YELLOW, " # #", row + 2, col); + c_put_str(TERM_YELLOW, "# #", row + 3, col); + c_put_str(TERM_YELLOW, "# #", row + 4, col); + c_put_str(TERM_YELLOW, "# # ", row + 5, col); + c_put_str(TERM_YELLOW, "# # ", row + 6, col); + c_put_str(TERM_YELLOW, ".#### ", row + 7, col); + prt(" Lemon ", row + 8, col); + + break; + } + + case 1: /* orange */ + { + c_put_str(TERM_ORANGE, " ## ", row, col); + c_put_str(TERM_ORANGE, " #..# ", row + 1, col); + c_put_str(TERM_ORANGE, " #....# ", row + 2, col); + c_put_str(TERM_ORANGE, "#......#", row + 3, col); + c_put_str(TERM_ORANGE, "#......#", row + 4, col); + c_put_str(TERM_ORANGE, " #....# ", row + 5, col); + c_put_str(TERM_ORANGE, " #..# ", row + 6, col); + c_put_str(TERM_ORANGE, " ## ", row + 7, col); + prt(" Orange ", row + 8, col); + + break; + } + + case 2: /* sword */ + { + c_put_str(TERM_SLATE, " /\\ ", row, col); + c_put_str(TERM_SLATE, " ## ", row + 1, col); + c_put_str(TERM_SLATE, " ## ", row + 2, col); + c_put_str(TERM_SLATE, " ## ", row + 3, col); + c_put_str(TERM_SLATE, " ## ", row + 4, col); + c_put_str(TERM_SLATE, " ## ", row + 5, col); + c_put_str(TERM_UMBER, " ###### ", row + 6, col); + c_put_str(TERM_UMBER, " ## ", row + 7, col); + prt(" Sword ", row + 8, col); + + break; + } + + case 3: /* shield */ + { + c_put_str(TERM_SLATE, " ###### ", row, col); + c_put_str(TERM_SLATE, "# #", row + 1, col); + c_put_str(TERM_SLATE, "# ++++ #", row + 2, col); + c_put_str(TERM_SLATE, "# +==+ #", row + 3, col); + c_put_str(TERM_SLATE, "# ++ #", row + 4, col); + c_put_str(TERM_SLATE, " # # ", row + 5, col); + c_put_str(TERM_SLATE, " # # ", row + 6, col); + c_put_str(TERM_SLATE, " ## ", row + 7, col); + prt(" Shield ", row + 8, col); + + break; + } + + case 4: /* plum */ + { + c_put_str(TERM_VIOLET, " ## ", row, col); + c_put_str(TERM_VIOLET, " ###### ", row + 1, col); + c_put_str(TERM_VIOLET, "########", row + 2, col); + c_put_str(TERM_VIOLET, "########", row + 3, col); + c_put_str(TERM_VIOLET, "########", row + 4, col); + c_put_str(TERM_VIOLET, " ###### ", row + 5, col); + c_put_str(TERM_VIOLET, " #### ", row + 6, col); + c_put_str(TERM_VIOLET, " ## ", row + 7, col); + prt(" Plum ", row + 8, col); + + break; + } + + case 5: /* cherry */ + { + c_put_str(TERM_RED, " ##", row, col); + c_put_str(TERM_RED, " ### ", row + 1, col); + c_put_str(TERM_RED, " #..# ", row + 2, col); + c_put_str(TERM_RED, " #..# ", row + 3, col); + c_put_str(TERM_RED, " ###### ", row + 4, col); + c_put_str(TERM_RED, "#..##..#", row + 5, col); + c_put_str(TERM_RED, "#..##..#", row + 6, col); + c_put_str(TERM_RED, " ## ## ", row + 7, col); + prt(" Cherry ", row + 8, col); + + break; + } + } +} + + +/* + * gamble_comm + */ +static bool_ gamble_comm(int cmd) +{ + int roll1, roll2, roll3, choice, odds, win; + + s32b wager; + + s32b maxbet; + + s32b oldgold; + + static const char *fruit[6] = + {"Lemon", "Orange", "Sword", "Shield", "Plum", "Cherry" + }; + + char out_val[160], tmp_str[80], again; + + cptr p; + + + screen_save(); + + if (cmd == BACT_GAMBLE_RULES) + { + /* Peruse the gambling help file */ + (void)show_file("gambling.txt", NULL, 0, 0); + } + else + { + clear_bldg(5, 23); + + /* Set maximum bet */ + if (p_ptr->lev < 10) + maxbet = (p_ptr->lev * 100); + else + maxbet = (p_ptr->lev * 1000); + + /* Get the wager */ + strcpy(out_val, ""); + strnfmt(tmp_str, 80, "Your wager (1-%ld) ? ", maxbet); + get_string(tmp_str, out_val, 32); + + /* Strip spaces */ + for (p = out_val; *p == ' '; p++); + + wager = atol(p); + + if (wager > p_ptr->au) + { + msg_print("Hey! You don't have the gold - get out of here!"); + msg_print(NULL); + screen_load(); + return (FALSE); + } + else if (wager > maxbet) + { + msg_format("I'll take $%ld of that. Keep the rest.", maxbet); + wager = maxbet; + } + else if (wager < 1) + { + msg_print("Ok, we'll start with $1."); + + wager = 1; + } + msg_print(NULL); + win = FALSE; + odds = 0; + oldgold = p_ptr->au; + + strnfmt(tmp_str, 80, "Gold before game: %9ld", oldgold); + prt(tmp_str, 20, 2); + + strnfmt(tmp_str, 80, "Current Wager: %9ld", wager); + prt(tmp_str, 21, 2); + + do + { + switch (cmd) + { + case BACT_IN_BETWEEN: /* Game of In-Between */ + { + c_put_str(TERM_GREEN, "In Between", 5, 2); + odds = 3; + win = FALSE; + roll1 = randint(10); + roll2 = randint(10); + choice = randint(10); + strnfmt(tmp_str, 80, "Black die: %d Black Die: %d", + roll1, roll2); + prt(tmp_str, 8, 3); + strnfmt(tmp_str, 80, "Red die: %d", choice); + prt(tmp_str, 11, 14); + if (((choice > roll1) && (choice < roll2)) || + ((choice < roll1) && (choice > roll2))) + win = TRUE; + + break; + } + case BACT_CRAPS: /* Game of Craps */ + { + c_put_str(TERM_GREEN, "Craps", 5, 2); + win = 3; + odds = 1; + roll1 = randint(6); + roll2 = randint(6); + roll3 = roll1 + roll2; + choice = roll3; + strnfmt(tmp_str, 80, "First roll: %d %d Total: %d", roll1, + roll2, roll3); + prt(tmp_str, 7, 5); + if ((roll3 == 7) || (roll3 == 11)) + win = TRUE; + else if ((roll3 == 2) || (roll3 == 3) || (roll3 == 12)) + win = FALSE; + else + { + do + { + msg_print("Hit any key to roll again"); + msg_print(NULL); + roll1 = randint(6); + roll2 = randint(6); + roll3 = roll1 + roll2; + + strnfmt(tmp_str, 80, "Roll result: %d %d Total: %d", + roll1, roll2, roll3); + prt(tmp_str, 8, 5); + if (roll3 == choice) + win = TRUE; + else if (roll3 == 7) + win = FALSE; + } + while ((win != TRUE) && (win != FALSE)); + } + + break; + } + + case BACT_SPIN_WHEEL: /* Spin the Wheel Game */ + { + win = FALSE; + odds = 10; + c_put_str(TERM_GREEN, "Wheel", 5, 2); + prt("0 1 2 3 4 5 6 7 8 9", 7, 5); + prt("--------------------------------", 8, 3); + strcpy(out_val, ""); + get_string ("Pick a number (1-9): ", out_val, 32); + for (p = out_val; *p == ' '; p++); + choice = atol(p); + if (choice < 0) + { + msg_print("I'll put you down for 0."); + choice = 0; + } + else if (choice > 9) + { + msg_print("Ok, I'll put you down for 9."); + choice = 9; + } + msg_print(NULL); + roll1 = randint(10) - 1; + strnfmt(tmp_str, 80, "The wheel spins to a stop and the winner is %d", + roll1); + prt(tmp_str, 13, 3); + prt("", 9, 0); + prt("*", 9, (3 * roll1 + 5)); + if (roll1 == choice) + win = TRUE; + + break; + } + + case BACT_DICE_SLOTS: /* The Dice Slots */ + { + c_put_str(TERM_GREEN, "Dice Slots", 5, 2); + win = FALSE; + roll1 = randint(6); + roll2 = randint(6); + choice = randint(6); + strnfmt(tmp_str, 80, "%s %s %s", + fruit[roll1 - 1], fruit[roll2 - 1], + fruit[choice - 1]); + prt(tmp_str, 15, 37); + prt("/--------------------------\\", 7, 2); + prt("\\--------------------------/", 17, 2); + display_fruit(8, 3, roll1 - 1); + display_fruit(8, 12, roll2 - 1); + display_fruit(8, 21, choice - 1); + if ((roll1 == roll2) && (roll2 == choice)) + { + win = TRUE; + if (roll1 == 1) + odds = 4; + else if (roll1 == 2) + odds = 6; + else + odds = roll1 * roll1; + } + else if ((roll1 == 6) && (roll2 == 6)) + { + win = TRUE; + odds = choice + 1; + } + + break; + } + } + + if (win) + { + prt("YOU WON", 16, 37); + p_ptr->au = p_ptr->au + (odds * wager); + strnfmt(tmp_str, 80, "Payoff: %d", odds); + prt(tmp_str, 17, 37); + } + else + { + prt("You Lost", 16, 37); + p_ptr->au = p_ptr->au - wager; + prt("", 17, 37); + } + strnfmt(tmp_str, 80, "Current Gold: %9ld", p_ptr->au); + prt(tmp_str, 22, 2); + prt("Again(Y/N)?", 18, 37); + move_cursor(18, 49); + again = inkey(); + if (wager > p_ptr->au) + { + msg_print("Hey! You don't have the gold - get out of here!"); + msg_print(NULL); + screen_load(); + return (FALSE); + /* strnfmt(tmp_str, 80, "Current Wager: %9ld",wager); + prt(tmp_str, 17, 2); */ + } + } + while ((again == 'y') || (again == 'Y')); + + prt("", 18, 37); + if (p_ptr->au >= oldgold) + msg_print("You came out a winner! We'll win next time, I'm sure."); + else + msg_print("You lost gold! Haha, better head home."); + msg_print(NULL); + } + + screen_load(); + + return (TRUE); +} + + +/* + * inn commands + * Note that resting for the night was a perfect way to avoid player + * ghosts in the town *if* you could only make it to the inn in time (-: + * Now that the ghosts are temporarily disabled in 2.8.X, this function + * will not be that useful. I will keep it in the hopes the player + * ghost code does become a reality again. Does help to avoid filthy urchins. + * Resting at night is also a quick way to restock stores -KMW- + */ +static bool_ inn_comm(int cmd) +{ + bool_ vampire; + + + /* Extract race info */ + vampire = ((PRACE_FLAG(PR1_VAMPIRE)) || (p_ptr->mimic_form == resolve_mimic_name("Vampire"))); + + switch (cmd) + { + case BACT_FOOD: /* Buy food & drink */ + { + if (!vampire) + { + msg_print("The barkeep gives you some gruel and a beer."); + msg_print(NULL); + (void) set_food(PY_FOOD_MAX - 1); + } + else + msg_print("You're a vampire and I don't have any food for you!"); + + break; + } + + /* + * I revamped this... Don't know why normal races didn't get + * mana regenerated. It is the grand tradition of p&p games -- pelpel + */ + case BACT_REST: /* Rest for the night */ + { + bool_ nighttime; + + /* Extract the current time */ + nighttime = ((bst(HOUR, turn) < 6) || (bst(HOUR, turn) >= 18)); + + /* Normal races rest at night */ + if (!vampire && !nighttime) + { + msg_print("The rooms are available only at night."); + msg_print(NULL); + return (FALSE); + } + + /* Vampires rest during daytime */ + if (vampire && nighttime) + { + msg_print("The rooms are available only during daylight for your kind."); + msg_print(NULL); + return (FALSE); + } + + /* Must cure HP draining status first */ + if ((p_ptr->poisoned > 0) || (p_ptr->cut > 0)) + { + msg_print("You need a healer, not a room."); + msg_print(NULL); + msg_print("Sorry, but I don't want anyone dying in here."); + return (FALSE); + } + + /* Let the time pass XXX XXX XXX */ + if (vampire) + { + /* Wait for sunset */ + while ((bst(HOUR, turn) >= 6) && (bst(HOUR, turn) < 18)) + { + turn += (10L * MINUTE); + } + } + else + { + /* Wait for sunrise */ + while ((bst(HOUR, turn) < 6) || (bst(HOUR, turn) >= 18)) + { + turn += (10L * MINUTE); + } + } + + /* Regen */ + p_ptr->chp = p_ptr->mhp; + p_ptr->csp = p_ptr->msp; + + /* Restore status */ + set_blind(0); + set_confused(0); + p_ptr->stun = 0; + + /* Message */ + if (vampire) msg_print("You awake refreshed for the new night."); + else msg_print("You awake refreshed for the new day."); + + /* Dungeon stuff */ + p_ptr->leaving = TRUE; + p_ptr->oldpx = p_ptr->px; + p_ptr->oldpy = p_ptr->py; + + /* Select new bounties. */ + select_bounties(); + + break; + } + + case BACT_RUMORS: /* Listen for rumors */ + { + char rumor[80]; + + get_rnd_line("rumors.txt", rumor); + msg_format("%s", rumor); + msg_print(NULL); + + break; + } + } + + return (TRUE); +} + + +/* + * Display quest information + */ +static void get_questinfo(int questnum) +{ + int i; + + + /* Print the quest info */ + prt(format("Quest Information (Danger level: %d)", quest[questnum].level), 5, 0); + + prt(quest[questnum].name, 7, 0); + + i = 0; + while ((i < 10) && (quest[questnum].desc[i][0] != '\0')) + { + c_put_str(TERM_YELLOW, quest[questnum].desc[i], i + 8, 0); + i++; + } +} + + +/* + * Request a quest from the Lord. + */ +static bool_ castle_quest(int y, int x) +{ + int plot = 0; + + quest_type *q_ptr; + + + clear_bldg(7, 18); + + /* Current plot of the building */ + plot = cave[y][x].special; + + /* Is there a quest available at the building? */ + if ((!plot) || (plots[plot] == QUEST_NULL)) + { + put_str("I don't have a quest for you at the moment.", 8, 0); + return FALSE; + } + + q_ptr = &quest[plots[plot]]; + + /* Quest is completed */ + if (q_ptr->status == QUEST_STATUS_COMPLETED) + { + /* Rewarded quest */ + q_ptr->status = QUEST_STATUS_FINISHED; + + process_hooks(HOOK_QUEST_FINISH, "(d)", plots[plot]); + + return (TRUE); + } + + /* Quest is still unfinished */ + else if (q_ptr->status == QUEST_STATUS_TAKEN) + { + put_str("You have not completed your current quest yet!", 8, 0); + put_str("Use CTRL-Q to check the status of your quest.", 9, 0); + put_str("Return when you have completed your quest.", 12, 0); + + return (FALSE); + } + /* Failed quest */ + else if (q_ptr->status == QUEST_STATUS_FAILED) + { + /* Mark quest as done (but failed) */ + q_ptr->status = QUEST_STATUS_FAILED_DONE; + + process_hooks(HOOK_QUEST_FAIL, "(d)", plots[plot]); + + return (FALSE); + } + /* No quest yet */ + else if (q_ptr->status == QUEST_STATUS_UNTAKEN) + { + if (process_hooks(HOOK_INIT_QUEST, "(d)", plots[plot])) return (FALSE); + + q_ptr->status = QUEST_STATUS_TAKEN; + + /* Assign a new quest */ + get_questinfo(plots[plot]); + + /* Add the hooks */ + quest[plots[plot]].init(plots[plot]); + + return (TRUE); + } + + return FALSE; +} + +/* + * Displaying town history -KMW- + */ +static void town_history(void) +{ + /* Save screen */ + screen_save(); + + /* Peruse the building help file */ + (void)show_file("bldg.txt", NULL, 0, 0); + + /* Load screen */ + screen_load(); +} + + +/* + * compare_weapon_aux2 -KMW- + */ +static void compare_weapon_aux2(object_type *o_ptr, int numblows, int r, int c, int mult, const char *attr, u32b f1, u32b f2, u32b f3, byte color) +{ + char tmp_str[80]; + + c_put_str(color, attr, r, c); + strnfmt(tmp_str, 80, "Attack: %d-%d damage", + numblows * ((o_ptr->dd * mult) + o_ptr->to_d), + numblows * ((o_ptr->ds * o_ptr->dd * mult) + o_ptr->to_d)); + put_str(tmp_str, r, c + 8); + r++; +} + + +/* + * compare_weapon_aux1 -KMW- + */ +static void compare_weapon_aux1(object_type *o_ptr, int col, int r) +{ + u32b f1, f2, f3, f4, f5, esp; + + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + + if (f1 & (TR1_SLAY_ANIMAL)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 2, "Animals:", + f1, f2, f3, TERM_YELLOW); + } + if (f1 & (TR1_SLAY_EVIL)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 2, "Evil:", + f1, f2, f3, TERM_YELLOW); + } + if (f1 & (TR1_SLAY_UNDEAD)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Undead:", + f1, f2, f3, TERM_YELLOW); + } + if (f1 & (TR1_SLAY_DEMON)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Demons:", + f1, f2, f3, TERM_YELLOW); + } + if (f1 & (TR1_SLAY_ORC)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Orcs:", + f1, f2, f3, TERM_YELLOW); + } + if (f1 & (TR1_SLAY_TROLL)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Trolls:", + f1, f2, f3, TERM_YELLOW); + } + if (f1 & (TR1_SLAY_GIANT)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Giants:", + f1, f2, f3, TERM_YELLOW); + } + if (f1 & (TR1_SLAY_DRAGON)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Dragons:", + f1, f2, f3, TERM_YELLOW); + } + if (f1 & (TR1_KILL_DRAGON)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 5, "Dragons:", + f1, f2, f3, TERM_YELLOW); + } + if (f1 & (TR1_BRAND_ACID)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Acid:", + f1, f2, f3, TERM_RED); + } + if (f1 & (TR1_BRAND_ELEC)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Elec:", + f1, f2, f3, TERM_RED); + } + if (f1 & (TR1_BRAND_FIRE)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Fire:", + f1, f2, f3, TERM_RED); + } + if (f1 & (TR1_BRAND_COLD)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Cold:", + f1, f2, f3, TERM_RED); + } + if (f1 & (TR1_BRAND_POIS)) + { + compare_weapon_aux2(o_ptr, p_ptr->num_blow, r++, col, 3, "Poison:", + f1, f2, f3, TERM_RED); + } +} + + +/* + * list_weapon -KMW- + */ +static void list_weapon(object_type *o_ptr, int row, int col) +{ + char o_name[80]; + + char tmp_str[80]; + + + object_desc(o_name, o_ptr, TRUE, 0); + c_put_str(TERM_YELLOW, o_name, row, col); + strnfmt(tmp_str, 80, "To Hit: %d To Damage: %d", o_ptr->to_h, o_ptr->to_d); + put_str(tmp_str, row + 1, col); + strnfmt(tmp_str, 80, "Dice: %d Sides: %d", o_ptr->dd, o_ptr->ds); + put_str(tmp_str, row + 2, col); + strnfmt(tmp_str, 80, "Number of Blows: %d", p_ptr->num_blow); + put_str(tmp_str, row + 3, col); + c_put_str(TERM_YELLOW, "Possible Damage:", row + 5, col); + strnfmt(tmp_str, 80, "One Strike: %d-%d damage", o_ptr->dd + o_ptr->to_d, + (o_ptr->ds*o_ptr->dd) + o_ptr->to_d); + put_str(tmp_str, row + 6, col + 1); + strnfmt(tmp_str, 80, "One Attack: %d-%d damage", p_ptr->num_blow*(o_ptr->dd + o_ptr->to_d), + p_ptr->num_blow*(o_ptr->ds*o_ptr->dd + o_ptr->to_d)); + put_str(tmp_str, row + 7, col + 1); +} + + +/* + * Select melee weapons + */ +static bool_ item_tester_hook_melee_weapon(object_type *o_ptr) +{ + return (wield_slot(o_ptr) == INVEN_WIELD); +} + +/* + * compare_weapons -KMW- + */ +static bool_ compare_weapons(void) +{ + int item, item2, i; + + object_type *o1_ptr, *o2_ptr, *orig_ptr; + + object_type *i_ptr; + + cptr q, s; + + + clear_bldg(6, 18); + + o1_ptr = NULL; + o2_ptr = NULL; + i_ptr = NULL; + + /* Store copy of original wielded weapon in pack slot */ + i_ptr = &p_ptr->inventory[INVEN_WIELD]; + orig_ptr = &p_ptr->inventory[INVEN_PACK]; + object_copy(orig_ptr, i_ptr); + + i = 6; + /* Get first weapon */ + /* Restrict choices to meele weapons */ + item_tester_hook = item_tester_hook_melee_weapon; + + q = "What is your first melee weapon? "; + s = "You have nothing to compare."; + if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN))) + { + object_wipe(orig_ptr); + return (FALSE); + } + + /* Get the item (in the pack) */ + if (item >= 0) + o1_ptr = &p_ptr->inventory[item]; + + /* Get second weapon */ + /* Restrict choices to melee weapons */ + item_tester_hook = item_tester_hook_melee_weapon; + + q = "What is your second melee weapon? "; + s = "You have nothing to compare."; + if (!get_item(&item2, q, s, (USE_EQUIP | USE_INVEN))) + { + object_wipe(orig_ptr); + return (FALSE); + } + + /* Get the item (in the pack) */ + if (item2 >= 0) o2_ptr = &p_ptr->inventory[item2]; + + put_str("Based on your current abilities, here is what your weapons will do", 4, 2); + + i_ptr = &p_ptr->inventory[INVEN_WIELD]; + object_copy(i_ptr, o1_ptr); + calc_bonuses(TRUE); + + list_weapon(o1_ptr, i, 2); + compare_weapon_aux1(o1_ptr, 2, i + 8); + + i_ptr = &p_ptr->inventory[INVEN_WIELD]; + if (item2 == INVEN_WIELD) + object_copy(i_ptr, orig_ptr); + else + object_copy(i_ptr, o2_ptr); + calc_bonuses(TRUE); + + list_weapon(o2_ptr, i, 40); + compare_weapon_aux1(o2_ptr, 40, i + 8); + + i_ptr = &p_ptr->inventory[INVEN_WIELD]; + object_copy(i_ptr, orig_ptr); + calc_bonuses(TRUE); + + object_wipe(orig_ptr); + + put_str("(Only highest damage applies per monster. Special damage not cumulative)", 20, 0); + + return (TRUE); +} + + +/* + * general all-purpose fixing routine for items from building personnel + * sharpen arrows, repair armor, repair weapon + * -KMW- + */ +static bool_ fix_item(int istart, int iend, int ispecific, bool_ iac, + int ireward, bool_ set_reward) +{ + int i; + + int j = 9; + + int maxenchant = (p_ptr->lev / 5); + + object_type *o_ptr; + + char out_val[80], tmp_str[80]; + + bool_ repaired = FALSE; + + clear_bldg(5, 18); + strnfmt(tmp_str, 80, " Based on your skill, we can improve up to +%d", maxenchant); + prt(tmp_str, 5, 0); + prt("Status", 7, 30); + + for (i = istart; i <= iend; i++) + { + o_ptr = &p_ptr->inventory[i]; + if (ispecific > 0) + { + if (o_ptr->tval != ispecific) + continue; + } + + if (o_ptr->tval) + { + object_desc(tmp_str, o_ptr, FALSE, 1); + + if ((o_ptr->name1 && (o_ptr->ident & 0x08))) + strnfmt(out_val, 80, "%-40s: beyond our skills!", tmp_str); + else if (o_ptr->name1) + strnfmt(out_val, 80, "%-40s: in fine condition", tmp_str); + else + { + if ((iac) && (o_ptr->to_a <= -3)) + { + strnfmt(out_val, 80, "%-40s: beyond repair, buy a new one", tmp_str); + } + else if ((iac) && (o_ptr->to_a < maxenchant)) + { + o_ptr->to_a++; + strnfmt(out_val, 80, "%-40s: polished -> (%d)", tmp_str, o_ptr->to_a); + repaired = TRUE; + } + else if ((!iac) && ((o_ptr->to_h <= -3) || (o_ptr->to_d <= -3))) + { + strnfmt(out_val, 80, "%-40s: beyond repair, buy a new one", tmp_str); + } + /* Sharpen a weapon */ + else if ((!iac) && ((o_ptr->to_h < maxenchant) || + (o_ptr->to_d < maxenchant))) + { + if (o_ptr->to_h < maxenchant) + o_ptr->to_h++; + if (o_ptr->to_d < maxenchant) + o_ptr->to_d++; + strnfmt(out_val, 80, "%-40s: sharpened -> (%d,%d)", tmp_str, + o_ptr->to_h, o_ptr->to_d); + repaired = TRUE; + } + else + strnfmt(out_val, 80, "%-40s: in fine condition", tmp_str); + } + prt(out_val, j++, 0); + } + } + + if (!repaired) + { + msg_print("You don't have anything appropriate."); + msg_print(NULL); + } + else + { + msg_print("Press the spacebar to continue"); + msg_print(NULL); + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + p_ptr->update |= (PU_BONUS); + } + clear_bldg(5, 18); + + return (repaired); +} + + +/* + * Research Item + */ +static bool_ research_item(void) +{ + clear_bldg(5, 18); + return (identify_fully()); +} + + +/* + * Show the current quest monster. + */ +static void show_quest_monster(void) +{ + monster_race* r_ptr = &r_info[bounties[0][0]]; + + + msg_format("Quest monster: %s. " + "Need to turn in %d corpse%s to receive reward.", + r_name + r_ptr->name, bounties[0][1], + (bounties[0][1] > 1 ? "s" : "")); + msg_print(NULL); +} + + +/* + * Show the current bounties. + */ +static void show_bounties(void) +{ + int i, j = 6; + + monster_race* r_ptr; + + char buff[80]; + + + clear_bldg(7, 18); + + c_prt(TERM_YELLOW, "Currently active bounties:", 4, 2); + + for (i = 1; i < MAX_BOUNTIES; i++, j++) + { + r_ptr = &r_info[bounties[i][0]]; + + strnfmt(buff, 80, "%-30s (%d gp)", r_name + r_ptr->name, bounties[i][1]); + + prt(buff, j, 2); + + if (j >= 17) + { + msg_print("Press space for more."); + msg_print(NULL); + + clear_bldg(7, 18); + j = 5; + } + } +} + + +/* + * Filter for corpses that currently have a bounty on them. + */ +static bool_ item_tester_hook_bounty(object_type* o_ptr) +{ + int i; + + + if (o_ptr->tval == TV_CORPSE) + { + for (i = 1; i < MAX_BOUNTIES; i++) + { + if (bounties[i][0] == o_ptr->pval2) return (TRUE); + } + } + + return (FALSE); +} + +/* Filter to match the quest monster's corpse. */ +static bool_ item_tester_hook_quest_monster(object_type* o_ptr) +{ + if ((o_ptr->tval == TV_CORPSE) && + (o_ptr->pval2 == bounties[0][0])) return (TRUE); + return (FALSE); +} + + +/* + * Return the boost in the corpse's value depending on how rare the body + * part is. + */ +static int corpse_value_boost(int sval) +{ + switch (sval) + { + case SV_CORPSE_HEAD: + case SV_CORPSE_SKULL: + { + return (1); + } + + /* Default to no boost. */ + default: + { + return (0); + } + } +} + +/* + * Sell a corpse, if there's currently a bounty on it. + */ +static void sell_corpses(void) +{ + object_type* o_ptr; + + int i, boost = 0; + + s16b value; + + int item; + + + /* Set the hook. */ + item_tester_hook = item_tester_hook_bounty; + + /* Select a corpse to sell. */ + if (!get_item(&item, "Sell which corpse", + "You have no corpses you can sell.", USE_INVEN)) return; + + o_ptr = &p_ptr->inventory[item]; + + /* Exotic body parts are worth more. */ + boost = corpse_value_boost(o_ptr->sval); + + /* Try to find a match. */ + for (i = 1; i < MAX_BOUNTIES; i++) + { + if (o_ptr->pval2 == bounties[i][0]) + { + value = bounties[i][1] + boost * (r_info[o_ptr->pval2].level); + + msg_format("Sold for %ld gold pieces.", value); + msg_print(NULL); + p_ptr->au += value; + + /* Increase the number of collected bounties */ + total_bounties++; + + inc_stack_size(item, -1); + + return; + } + } + + msg_print("Sorry, but that monster does not have a bounty on it."); + msg_print(NULL); +} + + + +/* + * Hook for bounty monster selection. + */ +static bool_ mon_hook_bounty(int r_idx) +{ + monster_race* r_ptr = &r_info[r_idx]; + + + /* Reject uniques */ + if (r_ptr->flags1 & RF1_UNIQUE) return (FALSE); + + /* Reject those who cannot leave anything */ + if (!(r_ptr->flags9 & RF9_DROP_CORPSE) && + !(r_ptr->flags9 & RF9_DROP_SKELETON)) return (FALSE); + + /* Reject pets */ + if (r_ptr->flags7 & RF7_PET) return (FALSE); + + /* Reject friendly creatures */ + if (r_ptr->flags7 & RF7_FRIENDLY) return (FALSE); + + /* The rest are acceptable */ + return (TRUE); +} + + +static void select_quest_monster(void) +{ + monster_race* r_ptr; + + int amt; + + + /* + * Set up the hooks -- no bounties on uniques or monsters + * with no corpses + */ + get_mon_num_hook = mon_hook_bounty; + get_mon_num_prep(); + + /* Set up the quest monster. */ + bounties[0][0] = get_mon_num(p_ptr->lev); + + r_ptr = &r_info[bounties[0][0]]; + + /* + * Select the number of monsters needed to kill. Groups and + * breeders require more + */ + amt = randnor(5, 3); + + if (amt < 2) amt = 2; + + if (r_ptr->flags1 & RF1_FRIEND) amt *= 3; amt /= 2; + if (r_ptr->flags1 & RF1_FRIENDS) amt *= 2; + if (r_ptr->flags4 & RF4_MULTIPLY) amt *= 3; + + if (r_ptr->flags7 & RF7_AQUATIC) amt /= 2; + + bounties[0][1] = amt; + + /* Undo the filters */ + get_mon_num_hook = NULL; + get_mon_num_prep(); +} + + + +/* + * Sell a corpse for a reward. + */ +static void sell_quest_monster(void) +{ + object_type* o_ptr; + + int item; + + + /* Set the hook. */ + item_tester_hook = item_tester_hook_quest_monster; + + /* Select a corpse to sell. */ + if (!get_item(&item, "Sell which corpse", + "You have no corpses you can sell.", USE_INVEN)) return; + + o_ptr = &p_ptr->inventory[item]; + + bounties[0][1] -= o_ptr->number; + + /* Completed the quest. */ + if (bounties[0][1] <= 0) + { + int m; + monster_race *r_ptr; + + cmsg_print(TERM_YELLOW, "You have completed your quest!"); + msg_print(NULL); + + /* Give full knowledge */ + + /* Hack -- Maximal info */ + r_ptr = &r_info[bounties[0][0]]; + + msg_print(format("Well done! As a reward I'll teach you everything " + "about the %s, (check your recall)", + r_name + r_ptr->name)); + + r_ptr->r_wake = r_ptr->r_ignore = MAX_UCHAR; + + /* Observe "maximal" attacks */ + for (m = 0; m < 4; m++) + { + /* Examine "actual" blows */ + if (r_ptr->blow[m].effect || r_ptr->blow[m].method) + { + /* Hack -- maximal observations */ + r_ptr->r_blows[m] = MAX_UCHAR; + } + } + + /* Hack -- maximal drops */ + r_ptr->r_drop_gold = r_ptr->r_drop_item = + (((r_ptr->flags1 & (RF1_DROP_4D2)) ? 8 : 0) + + ((r_ptr->flags1 & (RF1_DROP_3D2)) ? 6 : 0) + + ((r_ptr->flags1 & (RF1_DROP_2D2)) ? 4 : 0) + + ((r_ptr->flags1 & (RF1_DROP_1D2)) ? 2 : 0) + + ((r_ptr->flags1 & (RF1_DROP_90)) ? 1 : 0) + + ((r_ptr->flags1 & (RF1_DROP_60)) ? 1 : 0)); + + /* Hack -- but only "valid" drops */ + if (r_ptr->flags1 & (RF1_ONLY_GOLD)) r_ptr->r_drop_item = 0; + if (r_ptr->flags1 & (RF1_ONLY_ITEM)) r_ptr->r_drop_gold = 0; + + /* Hack -- observe many spells */ + r_ptr->r_cast_inate = MAX_UCHAR; + r_ptr->r_cast_spell = MAX_UCHAR; + + /* Hack -- know all the flags */ + r_ptr->r_flags1 = r_ptr->flags1; + r_ptr->r_flags2 = r_ptr->flags2; + r_ptr->r_flags3 = r_ptr->flags3; + r_ptr->r_flags4 = r_ptr->flags4; + r_ptr->r_flags5 = r_ptr->flags5; + r_ptr->r_flags6 = r_ptr->flags6; + r_ptr->r_flags4 = r_ptr->flags7; + r_ptr->r_flags5 = r_ptr->flags8; + r_ptr->r_flags6 = r_ptr->flags9; + + msg_print(NULL); + + select_quest_monster(); + + } + else + { + msg_format("Well done, only %d more to go.", bounties[0][1]); + msg_print(NULL); + } + + inc_stack_size(item, -1); +} + + + +/* + * Fill the bounty list with monsters. + */ +void select_bounties(void) +{ + int i, j; + + + select_quest_monster(); + + /* + * Set up the hooks -- no bounties on uniques or monsters + * with no corpses + */ + get_mon_num_hook = mon_hook_bounty; + get_mon_num_prep(); + + for (i = 1; i < MAX_BOUNTIES; i++) + { + int lev = i * 5 + randnor(0, 2); + monster_race* r_ptr; + s16b r_idx; + s16b val; + + if (lev < 1) lev = 1; + + if (lev >= MAX_DEPTH) lev = MAX_DEPTH - 1; + + /* We don't want to duplicate entries in the list */ + while (TRUE) + { + r_idx = get_mon_num(lev); + + for (j = 0; j < i; j++) + { + if (bounties[j][0] == r_idx) continue; + } + + break; + } + + bounties[i][0] = r_idx; + + r_ptr = &r_info[r_idx]; + + val = r_ptr->mexp + r_ptr->level * 20 + randnor(0, r_ptr->level * 2); + + if (val < 1) val = 1; + + bounties[i][1] = val; + } + + /* Undo the filters. */ + get_mon_num_hook = NULL; + get_mon_num_prep(); +} + +/* + * Execute a building command + */ +bool_ bldg_process_command(store_type *s_ptr, int i) +{ + store_action_type *ba_ptr = &ba_info[st_info[s_ptr->st_idx].actions[i]]; + + int bact = ba_ptr->action; + + int bcost; + + bool_ paid = FALSE; + + bool_ set_reward = FALSE; + + bool_ recreate = FALSE; + + + if (is_state(s_ptr, STORE_LIKED)) + { + bcost = ba_ptr->costs[STORE_LIKED]; + } + else if (is_state(s_ptr, STORE_HATED)) + { + bcost = ba_ptr->costs[STORE_HATED]; + } + else + { + bcost = ba_ptr->costs[STORE_NORMAL]; + } + + /* action restrictions */ + if (((ba_ptr->action_restr == 1) && (is_state(s_ptr, STORE_LIKED))) || + ((ba_ptr->action_restr == 2) && (!is_state(s_ptr, STORE_LIKED)))) + { + msg_print("You have no right to choose that!"); + msg_print(NULL); + return FALSE; + } + + /* If player has loan and the time is out, few things work in stores */ + if (p_ptr->loan && !p_ptr->loan_time) + { + if ((bact != BACT_SELL) && (bact != BACT_VIEW_BOUNTIES) && + (bact != BACT_SELL_CORPSES) && + (bact != BACT_VIEW_QUEST_MON) && + (bact != BACT_SELL_QUEST_MON) && + (bact != BACT_EXAMINE) && (bact != BACT_STEAL) && + (bact != BACT_PAY_BACK_LOAN)) + { + msg_print("You are not allowed to do that until you have paid back your loan."); + msg_print(NULL); + return FALSE; + } + } + + /* check gold */ + if (bcost > p_ptr->au) + { + msg_print("You do not have the gold!"); + msg_print(NULL); + return FALSE; + } + + if (!bcost) set_reward = TRUE; + + switch (bact) + { + case BACT_RESEARCH_ITEM: + { + paid = research_item(); + break; + } + + case BACT_TOWN_HISTORY: + { + town_history(); + break; + } + + case BACT_RACE_LEGENDS: + { + race_legends(); + break; + } + + case BACT_QUEST1: + case BACT_QUEST2: + case BACT_QUEST3: + case BACT_QUEST4: + { + int y = 1, x = 1; + bool_ ok = FALSE; + + while ((x < cur_wid - 1) && !ok) + { + y = 1; + while ((y < cur_hgt - 1) && !ok) + { + /* Found the location of the quest info ? */ + if (bact - BACT_QUEST1 + FEAT_QUEST1 == cave[y][x].feat) + { + /* Stop the loop */ + ok = TRUE; + } + y++; + } + x++; + } + + if (ok) + { + recreate = castle_quest(y - 1, x - 1); + ; + } + else + { + msg_format("ERROR: no quest info feature found: %d", bact - BACT_QUEST1 + FEAT_QUEST1); + } + break; + } + + case BACT_KING_LEGENDS: + case BACT_ARENA_LEGENDS: + case BACT_LEGENDS: + { + show_highclass(building_loc); + break; + } + + case BACT_POSTER: + case BACT_ARENA_RULES: + case BACT_ARENA: + { + arena_comm(bact); + break; + } + + case BACT_IN_BETWEEN: + case BACT_CRAPS: + case BACT_SPIN_WHEEL: + case BACT_DICE_SLOTS: + case BACT_GAMBLE_RULES: + { + gamble_comm(bact); + break; + } + + case BACT_REST: + case BACT_RUMORS: + case BACT_FOOD: + { + paid = inn_comm(bact); + break; + } + + case BACT_RESEARCH_MONSTER: + { + paid = !research_mon(); + break; + } + + case BACT_COMPARE_WEAPONS: + { + paid = compare_weapons(); + break; + } + + case BACT_ENCHANT_WEAPON: + { + paid = fix_item(INVEN_WIELD, INVEN_WIELD, 0, FALSE, + BACT_ENCHANT_WEAPON, set_reward); + break; + } + + case BACT_ENCHANT_ARMOR: + { + paid = fix_item(INVEN_BODY, INVEN_FEET, 0, TRUE, + BACT_ENCHANT_ARMOR, set_reward); + break; + } + + /* needs work */ + case BACT_RECHARGE: + { + if (recharge(80)) paid = TRUE; + break; + } + + /* needs work */ + case BACT_IDENTS: + { + identify_pack(); + msg_print("Your possessions have been identified."); + msg_print(NULL); + paid = TRUE; + break; + } + + /* needs work */ + case BACT_STAR_HEAL: + { + hp_player(200); + set_poisoned(0); + set_blind(0); + set_confused(0); + set_cut(0); + set_stun(0); + if (p_ptr->black_breath) + { + msg_print("The hold of the Black Breath on you is broken!"); + p_ptr->black_breath = FALSE; + } + paid = TRUE; + break; + } + + /* needs work */ + case BACT_HEALING: + { + hp_player(200); + set_poisoned(0); + set_blind(0); + set_confused(0); + set_cut(0); + set_stun(0); + paid = TRUE; + break; + } + + /* needs work */ + case BACT_RESTORE: + { + if (do_res_stat(A_STR, TRUE)) paid = TRUE; + if (do_res_stat(A_INT, TRUE)) paid = TRUE; + if (do_res_stat(A_WIS, TRUE)) paid = TRUE; + if (do_res_stat(A_DEX, TRUE)) paid = TRUE; + if (do_res_stat(A_CON, TRUE)) paid = TRUE; + if (do_res_stat(A_CHR, TRUE)) paid = TRUE; + break; + } + + case BACT_ENCHANT_ARROWS: + { + paid = fix_item(0, INVEN_WIELD, TV_ARROW, FALSE, + BACT_ENCHANT_ARROWS, set_reward); + break; + } + + case BACT_ENCHANT_BOW: + { + paid = fix_item(INVEN_BOW, INVEN_BOW, TV_BOW, FALSE, + BACT_ENCHANT_BOW, set_reward); + break; + } + + case BACT_RECALL: + { + p_ptr->word_recall = 1; + msg_print("The air about you becomes charged..."); + paid = TRUE; + break; + } + + case BACT_TELEPORT_LEVEL: + { + if (reset_recall(FALSE)) + { + p_ptr->word_recall = 1; + msg_print("The air about you becomes charged..."); + paid = TRUE; + } + break; + } + + case BACT_MIMIC_NORMAL: + { + set_mimic(0, 0, 0); + paid = TRUE; + break; + } + + case BACT_VIEW_BOUNTIES: + { + show_bounties(); + break; + } + + case BACT_VIEW_QUEST_MON: + { + show_quest_monster(); + break; + } + + case BACT_SELL_QUEST_MON: + { + sell_quest_monster(); + break; + } + + case BACT_SELL_CORPSES: + { + sell_corpses(); + break; + } + + case BACT_DIVINATION: + { + int i, count = 0; + bool_ something = FALSE; + + while (count < 1000) + { + count++; + i = rand_int(MAX_FATES); + if (!fates[i].fate) continue; + if (fates[i].know) continue; + msg_print("You know a little more of your fate."); + + fates[i].know = TRUE; + something = TRUE; + break; + } + + if (!something) msg_print("Well, you have no fate, but I'll keep your money anyway!"); + + paid = TRUE; + break; + + } + + case BACT_BUY: + { + store_purchase(); + break; + } + + case BACT_SELL: + { + store_sell(); + break; + } + + case BACT_EXAMINE: + { + store_examine(); + break; + } + + case BACT_STEAL: + { + store_stole(); + break; + } + + case BACT_REQUEST_ITEM: + { + store_request_item(); + paid = TRUE; + break; + } + + case BACT_GET_LOAN: + { + s32b i, req; + char prompt[80]; + + if (p_ptr->loan) + { + msg_print("You already have a loan!"); + break; + } + + req = p_ptr->au; + + for (i = 0; i < INVEN_TOTAL; i++) + req += object_value_real(&p_ptr->inventory[i]); + + if (req > 100000) req = 100000; + if ((req + p_ptr->au) > PY_MAX_GOLD) req = PY_MAX_GOLD - p_ptr->au; + + strnfmt(prompt, sizeof (prompt), + "How much would you like to get (0-%ld) ?", req); + + req = get_quantity(prompt, req); + + if (req) + { + p_ptr->loan += req; + p_ptr->au += req; + p_ptr->loan_time += req; + + msg_format("You receive %i gold pieces", req); + + paid = TRUE; + } + else + msg_format("You did not request any money!"); + + break; + } + + case BACT_PAY_BACK_LOAN: + { + s32b req; + char prompt[80]; + + if (p_ptr->loan) + { + msg_format("You have nothing to payback!"); + break; + } + + msg_format("You have a loan of %i.", p_ptr->loan); + + req = ((p_ptr->loan + bcost) > p_ptr->au) ? p_ptr->au - bcost : p_ptr->loan; + + strnfmt(prompt, sizeof (prompt), + "How much would you like to pay back (0-%ld) ?", req); + + req = get_quantity(prompt, req); + + p_ptr->loan -= req; + p_ptr->au -= req; + + if (!p_ptr->loan) p_ptr->loan_time = 0; + + msg_format("You pay back %i gold pieces", req); + paid = TRUE; + break; + } + + case BACT_DROP_ITEM: + { + quest_bounty_drop_item(); + break; + } + + case BACT_GET_ITEM: + { + quest_bounty_get_item(); + break; + } + + case BACT_LIBRARY_QUEST: + { + quest_library_building(&paid, &recreate); + break; + } + + case BACT_FIREPROOF_QUEST: + { + quest_fireproof_building(&paid, &recreate); + break; + } + + case BACT_EREBOR_KEY: + { + msg_print("You will need Thorin's Key and Thrain's Map" + " to get anywhere in Erebor. One may be found" + " in the Barrow-Downs. The other, in Mirkwood."); + break; + } + + default: + { + if (process_hooks_ret(HOOK_BUILDING_ACTION, "dd", "(d)", bact)) + { + paid = process_hooks_return[0].num; + recreate = process_hooks_return[1].num; + } + break; + } + } + + if (paid) + { + p_ptr->au -= bcost; + + /* Display the current gold */ + store_prt_gold(); + } + + return (recreate); +} + + +/* + * Enter quest level + */ +void enter_quest(void) +{ + if (!(cave[p_ptr->py][p_ptr->px].feat == FEAT_QUEST_ENTER)) + { + msg_print("You see no quest level here."); + return; + } + else + { + /* Player enters a new quest */ + p_ptr->oldpy = p_ptr->py; + p_ptr->oldpx = p_ptr->px; + + leaving_quest = p_ptr->inside_quest; + + p_ptr->inside_quest = cave[p_ptr->py][p_ptr->px].special; + dun_level = 1; + p_ptr->leaving = TRUE; + p_ptr->oldpx = p_ptr->px; + p_ptr->oldpy = p_ptr->py; + } +} + + +/* + * Do building commands + */ +void do_cmd_bldg(void) +{ + int i, which, x = p_ptr->px, y = p_ptr->py; + + char command; + + bool_ validcmd; + + store_type *s_ptr; + + store_action_type *ba_ptr; + + + if (cave[p_ptr->py][p_ptr->px].feat != FEAT_SHOP) + { + msg_print("You see no building here."); + return; + } + + which = cave[p_ptr->py][p_ptr->px].special; + building_loc = which; + + s_ptr = &town_info[p_ptr->town_num].store[which]; + + p_ptr->oldpy = p_ptr->py; + p_ptr->oldpx = p_ptr->px; + + /* Forget the lite */ + /* forget_lite(); */ + + /* Forget the view */ + forget_view(); + + /* Hack -- Increase "icky" depth */ + character_icky++; + + command_arg = 0; + command_rep = 0; + command_new = 0; + + show_building(s_ptr); + leave_bldg = FALSE; + + while (!leave_bldg) + { + validcmd = FALSE; + prt("", 1, 0); + command = inkey(); + + if (command == ESCAPE) + { + leave_bldg = TRUE; + p_ptr->inside_arena = FALSE; + break; + } + + for (i = 0; i < 6; i++) + { + ba_ptr = &ba_info[st_info->actions[i]]; + + if (ba_ptr->letter) + { + if (ba_ptr->letter == command) + { + validcmd = TRUE; + break; + } + } + if (ba_ptr->letter_aux) + { + if (ba_ptr->letter_aux == command) + { + validcmd = TRUE; + break; + } + } + } + + if (validcmd) + bldg_process_command(s_ptr, i); + + /* Notice stuff */ + notice_stuff(); + + /* Handle stuff */ + handle_stuff(); + } + + /* Flush messages XXX XXX XXX */ + msg_print(NULL); + + /* Reinit wilderness to activate quests ... */ + wilderness_gen(TRUE); + p_ptr->py = y; + p_ptr->px = x; + + /* Hack -- Decrease "icky" depth */ + character_icky--; + + /* Clear the screen */ + Term_clear(); + + /* Update the visuals */ + p_ptr->update |= (PU_VIEW | PU_MON_LITE | PU_MONSTERS | PU_BONUS); + + /* Redraw entire screen */ + p_ptr->redraw |= (PR_BASIC | PR_EXTRA | PR_MAP); + + /* Window stuff */ + p_ptr->window |= (PW_OVERHEAD); +} + + diff --git a/src/cave.c b/src/cave.c deleted file mode 100644 index 2a02f017..00000000 --- a/src/cave.c +++ /dev/null @@ -1,5022 +0,0 @@ -/* File: cave.c */ - -/* Purpose: low level dungeon routines -BEN- */ - - -#include "angband.h" -#include "q_rand.h" - - -/* - * Support for Adam Bolt's tileset, lighting and transparency effects - * by Robert Ruehlmann (rr9@angband.org) - */ - - -/* - * Approximate Distance between two points. - * - * When either the X or Y component dwarfs the other component, - * this function is almost perfect, and otherwise, it tends to - * over-estimate about one grid per fifteen grids of distance. - * - * Algorithm: hypot(dy,dx) = max(dy,dx) + min(dy,dx) / 2 - */ -int distance(int y1, int x1, int y2, int x2) -{ - int dy, dx, d; - - - /* Find the absolute y/x distance components */ - dy = (y1 > y2) ? (y1 - y2) : (y2 - y1); - dx = (x1 > x2) ? (x1 - x2) : (x2 - x1); - - /* Hack -- approximate the distance */ - d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1)); - - /* Return the distance */ - return (d); -} - - -/* - * Returns TRUE if a grid is considered to be a wall for the purpose - * of magic mapping / clairvoyance - */ -static bool_ is_wall(cave_type *c_ptr) -{ - byte feat; - - - /* Handle feature mimics */ - if (c_ptr->mimic) feat = c_ptr->mimic; - else feat = c_ptr->feat; - - /* Paranoia */ - if (feat >= max_f_idx) return FALSE; - - /* Vanilla floors and doors aren't considered to be walls */ - if (feat < FEAT_SECRET) return FALSE; - - /* Exception #1: a glass wall is a wall but doesn't prevent LOS */ - if (feat == FEAT_GLASS_WALL) return FALSE; - - /* Exception #2: an illusion wall is not a wall but obstructs view */ - if (feat == FEAT_ILLUS_WALL) return TRUE; - - /* Exception #3: a small tree is a floor but obstructs view */ - if (feat == FEAT_SMALL_TREES) return TRUE; - - /* Normal cases: use the WALL flag in f_info.txt */ - return (f_info[feat].flags1 & FF1_WALL) ? TRUE : FALSE; -} - - -/* - * A simple, fast, integer-based line-of-sight algorithm. By Joseph Hall, - * 4116 Brewster Drive, Raleigh NC 27606. Email to jnh@ecemwl.ncsu.edu. - * - * Returns TRUE if a line of sight can be traced from (x1,y1) to (x2,y2). - * - * The LOS begins at the center of the tile (x1,y1) and ends at the center of - * the tile (x2,y2). If los() is to return TRUE, all of the tiles this line - * passes through must be floor tiles, except for (x1,y1) and (x2,y2). - * - * We assume that the "mathematical corner" of a non-floor tile does not - * block line of sight. - * - * Because this function uses (short) ints for all calculations, overflow may - * occur if dx and dy exceed 90. - * - * Once all the degenerate cases are eliminated, the values "qx", "qy", and - * "m" are multiplied by a scale factor "f1 = abs(dx * dy * 2)", so that - * we can use integer arithmetic. - * - * We travel from start to finish along the longer axis, starting at the border - * between the first and second tiles, where the y offset = .5 * slope, taking - * into account the scale factor. See below. - * - * Also note that this function and the "move towards target" code do NOT - * share the same properties. Thus, you can see someone, target them, and - * then fire a bolt at them, but the bolt may hit a wall, not them. However, - * by clever choice of target locations, you can sometimes throw a "curve". - * - * Note that "line of sight" is not "reflexive" in all cases. - * - * Use the "projectable()" routine to test "spell/missile line of sight". - * - * Use the "update_view()" function to determine player line-of-sight. - */ -bool_ los(int y1, int x1, int y2, int x2) -{ - /* Delta */ - int dx, dy; - - /* Absolute */ - int ax, ay; - - /* Signs */ - int sx, sy; - - /* Fractions */ - int qx, qy; - - /* Scanners */ - int tx, ty; - - /* Scale factors */ - int f1, f2; - - /* Slope, or 1/Slope, of LOS */ - int m; - - - /* Extract the offset */ - dy = y2 - y1; - dx = x2 - x1; - - /* Extract the absolute offset */ - ay = ABS(dy); - ax = ABS(dx); - - - /* Handle adjacent (or identical) grids */ - if ((ax < 2) && (ay < 2)) return (TRUE); - - - /* Paranoia -- require "safe" origin */ - /* if (!in_bounds(y1, x1)) return (FALSE); */ - - - /* Directly South/North */ - if (!dx) - { - /* South -- check for walls */ - if (dy > 0) - { - for (ty = y1 + 1; ty < y2; ty++) - { - if (!cave_sight_bold(ty, x1)) return (FALSE); - } - } - - /* North -- check for walls */ - else - { - for (ty = y1 - 1; ty > y2; ty--) - { - if (!cave_sight_bold(ty, x1)) return (FALSE); - } - } - - /* Assume los */ - return (TRUE); - } - - /* Directly East/West */ - if (!dy) - { - /* East -- check for walls */ - if (dx > 0) - { - for (tx = x1 + 1; tx < x2; tx++) - { - if (!cave_sight_bold(y1, tx)) return (FALSE); - } - } - - /* West -- check for walls */ - else - { - for (tx = x1 - 1; tx > x2; tx--) - { - if (!cave_sight_bold(y1, tx)) return (FALSE); - } - } - - /* Assume los */ - return (TRUE); - } - - - /* Extract some signs */ - sx = (dx < 0) ? -1 : 1; - sy = (dy < 0) ? -1 : 1; - - - /* Vertical "knights" */ - if (ax == 1) - { - if (ay == 2) - { - if (cave_sight_bold(y1 + sy, x1)) return (TRUE); - } - } - - /* Horizontal "knights" */ - else if (ay == 1) - { - if (ax == 2) - { - if (cave_sight_bold(y1, x1 + sx)) return (TRUE); - } - } - - - /* Calculate scale factor div 2 */ - f2 = (ax * ay); - - /* Calculate scale factor */ - f1 = f2 << 1; - - - /* Travel horizontally */ - if (ax >= ay) - { - /* Let m = dy / dx * 2 * (dy * dx) = 2 * dy * dy */ - qy = ay * ay; - m = qy << 1; - - tx = x1 + sx; - - /* Consider the special case where slope == 1. */ - if (qy == f2) - { - ty = y1 + sy; - qy -= f1; - } - else - { - ty = y1; - } - - /* Note (below) the case (qy == f2), where */ - /* the LOS exactly meets the corner of a tile. */ - while (x2 - tx) - { - if (!cave_sight_bold(ty, tx)) return (FALSE); - - qy += m; - - if (qy < f2) - { - tx += sx; - } - else if (qy > f2) - { - ty += sy; - if (!cave_sight_bold(ty, tx)) return (FALSE); - qy -= f1; - tx += sx; - } - else - { - ty += sy; - qy -= f1; - tx += sx; - } - } - } - - /* Travel vertically */ - else - { - /* Let m = dx / dy * 2 * (dx * dy) = 2 * dx * dx */ - qx = ax * ax; - m = qx << 1; - - ty = y1 + sy; - - if (qx == f2) - { - tx = x1 + sx; - qx -= f1; - } - else - { - tx = x1; - } - - /* Note (below) the case (qx == f2), where */ - /* the LOS exactly meets the corner of a tile. */ - while (y2 - ty) - { - if (!cave_sight_bold(ty, tx)) return (FALSE); - - qx += m; - - if (qx < f2) - { - ty += sy; - } - else if (qx > f2) - { - tx += sx; - if (!cave_sight_bold(ty, tx)) return (FALSE); - qx -= f1; - ty += sy; - } - else - { - tx += sx; - qx -= f1; - ty += sy; - } - } - } - - /* Assume los */ - return (TRUE); -} - - - -/* - * Returns true if the player's grid is dark - */ -bool_ no_lite(void) -{ - return (!player_can_see_bold(p_ptr->py, p_ptr->px)); -} - - - -/* - * Determine if a given location may be "destroyed" - * - * Used by destruction spells, and for placing stairs, etc. - */ -bool_ cave_valid_bold(int y, int x) -{ - cave_type *c_ptr = &cave[y][x]; - - s16b this_o_idx, next_o_idx = 0; - - - /* Forbid perma-grids */ - if (cave_perma_grid(c_ptr)) return (FALSE); - - /* Check objects */ - for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) - { - object_type * o_ptr; - - /* Acquire object */ - o_ptr = &o_list[this_o_idx]; - - /* Acquire next object */ - next_o_idx = o_ptr->next_o_idx; - - /* Forbid artifact grids */ - if ((o_ptr->art_name) || artifact_p(o_ptr)) return (FALSE); - } - - /* Accept */ - return (TRUE); -} - - - - -/* - * Hack -- Legal monster codes - */ -static cptr image_monster_hack = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - -/* - * Hack -- Legal monster codes for IBM pseudo-graphics - * - * Dropped. Although this option has long left unmaintained, hardcoding - * code points makes it impossible to update the font and prf files - * flexibly. And the normal graphics code still works with it -- pelpel - */ - -/* - * Mega-Hack -- Hallucinatory monster - */ -static void image_monster(byte *ap, char *cp) -{ - int n; - - switch (graphics_mode) - { - /* Text mode */ - case GRAPHICS_NONE: - { - n = strlen(image_monster_hack); - - /* Random symbol from set above */ - *cp = (image_monster_hack[rand_int(n)]); - - /* Random color */ - *ap = randint(15); - - break; - } - - /* Normal graphics */ - default: - { - /* Avoid player ghost */ - n = randint(max_r_idx); - - *cp = r_info[n].x_char; - - *ap = r_info[n].x_attr; - - break; - } - } -} - - - - -/* - * Hack -- Legal object codes - */ -static cptr image_object_hack = "?/|\\\"!$()_-=[]{},~"; - -/* - * Hardcoded IBM pseudo-graphics code points have been removed - * for the same reason as stated above -- pelpel - */ - -/* - * Mega-Hack -- Hallucinatory object - */ -static void image_object(byte *ap, char *cp) -{ - int n; - - switch (graphics_mode) - { - /* Text mode */ - case GRAPHICS_NONE: - { - n = strlen(image_object_hack); - - /* Random symbol from set above */ - *cp = (image_object_hack[rand_int(n)]); - - /* Random color */ - *ap = randint(15); - - /* Done */ - break; - } - - /* Normal graphics */ - default: - { - n = randint(max_k_idx - 1); - - *cp = k_info[n].x_char; - *ap = k_info[n].x_attr; - - break; - } - } -} - - -/* - * Hack -- Random hallucination - */ -static void image_random(byte *ap, char *cp) -{ - /* Normally, assume monsters */ - if (rand_int(100) < 75) - { - image_monster(ap, cp); - } - - /* Otherwise, assume objects */ - else - { - image_object(ap, cp); - } -} - - -/* - * The 16x16 tile of the terrain supports lighting - */ -static bool_ feat_supports_lighting(byte feat) -{ - return (f_info[feat].flags1 & FF1_SUPPORT_LIGHT) != 0; -} - - -char get_shimmer_color() -{ - switch (randint(7)) - { - case 1: - return (TERM_RED); - case 2: - return (TERM_L_RED); - case 3: - return (TERM_WHITE); - case 4: - return (TERM_L_GREEN); - case 5: - return (TERM_BLUE); - case 6: - return (TERM_L_DARK); - case 7: - return (TERM_GREEN); - } - - return (TERM_VIOLET); -} - - -/* - * Table of breath colors. Must match listings in a single set of - * monster spell flags. - * - * The value "255" is special. Monsters with that kind of breath - * may be any color. - */ -static byte breath_to_attr[32][2] = -{ - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { 0, 0 }, - { TERM_SLATE, TERM_L_DARK }, /* RF4_BRTH_ACID */ - { TERM_BLUE, TERM_L_BLUE }, /* RF4_BRTH_ELEC */ - { TERM_RED, TERM_L_RED }, /* RF4_BRTH_FIRE */ - { TERM_WHITE, TERM_L_WHITE }, /* RF4_BRTH_COLD */ - { TERM_GREEN, TERM_L_GREEN }, /* RF4_BRTH_POIS */ - { TERM_L_GREEN, TERM_GREEN }, /* RF4_BRTH_NETHR */ - { TERM_YELLOW, TERM_ORANGE }, /* RF4_BRTH_LITE */ - { TERM_L_DARK, TERM_SLATE }, /* RF4_BRTH_DARK */ - { TERM_L_UMBER, TERM_UMBER }, /* RF4_BRTH_CONFU */ - { TERM_YELLOW, TERM_L_UMBER }, /* RF4_BRTH_SOUND */ - { 255, 255 }, /* (any color) */ /* RF4_BRTH_CHAOS */ - { TERM_VIOLET, TERM_VIOLET }, /* RF4_BRTH_DISEN */ - { TERM_L_RED, TERM_VIOLET }, /* RF4_BRTH_NEXUS */ - { TERM_L_BLUE, TERM_L_BLUE }, /* RF4_BRTH_TIME */ - { TERM_L_WHITE, TERM_SLATE }, /* RF4_BRTH_INER */ - { TERM_L_WHITE, TERM_SLATE }, /* RF4_BRTH_GRAV */ - { TERM_UMBER, TERM_L_UMBER }, /* RF4_BRTH_SHARD */ - { TERM_ORANGE, TERM_RED }, /* RF4_BRTH_PLAS */ - { TERM_UMBER, TERM_L_UMBER }, /* RF4_BRTH_FORCE */ - { TERM_L_BLUE, TERM_WHITE }, /* RF4_BRTH_MANA */ - { 0, 0 }, /* */ - { TERM_GREEN, TERM_L_GREEN }, /* RF4_BRTH_NUKE */ - { 0, 0 }, /* */ - { TERM_WHITE, TERM_L_RED }, /* RF4_BRTH_DISINT */ -}; - - -/* - * Multi-hued monsters shimmer acording to their breaths. - * - * If a monster has only one kind of breath, it uses both colors - * associated with that breath. Otherwise, it just uses the first - * color for any of its breaths. - * - * If a monster does not breath anything, it can be any color. - */ -static byte multi_hued_attr(monster_race *r_ptr) -{ - byte allowed_attrs[15]; - - int i, j; - - int stored_colors = 0; - - int breaths = 0; - - int first_color = 0; - - int second_color = 0; - - - /* Monsters with no ranged attacks can be any color */ - if (!r_ptr->freq_inate) return (get_shimmer_color()); - - /* Check breaths */ - for (i = 0; i < 32; i++) - { - bool_ stored = FALSE; - - /* Don't have that breath */ - if (!(r_ptr->flags4 & (1L << i))) continue; - - /* Get the first color of this breath */ - first_color = breath_to_attr[i][0]; - - /* Breath has no color associated with it */ - if (first_color == 0) continue; - - /* Monster can be of any color */ - if (first_color == 255) return (randint(15)); - - - /* Increment the number of breaths */ - breaths++; - - /* Monsters with lots of breaths may be any color. */ - if (breaths == 6) return (randint(15)); - - - /* Always store the first color */ - for (j = 0; j < stored_colors; j++) - { - /* Already stored */ - if (allowed_attrs[j] == first_color) stored = TRUE; - } - if (!stored) - { - allowed_attrs[stored_colors] = first_color; - stored_colors++; - } - - /* - * Remember (but do not immediately store) the second color - * of the first breath. - */ - if (breaths == 1) - { - second_color = breath_to_attr[i][1]; - } - } - - /* Monsters with no breaths may be of any color. */ - if (breaths == 0) return (get_shimmer_color()); - - /* If monster has one breath, store the second color too. */ - if (breaths == 1) - { - allowed_attrs[stored_colors] = second_color; - stored_colors++; - } - - /* Pick a color at random */ - return (allowed_attrs[rand_int(stored_colors)]); -} - - -/* - * Extract the attr/char to display at the given (legal) map location - * - * Note that this function, since it is called by "lite_spot()" which - * is called by "update_view()", is a major efficiency concern. - * - * Basically, we examine each "layer" of the world (terrain, objects, - * monsters/players), from the bottom up, extracting a new attr/char - * if necessary at each layer, and defaulting to "darkness". This is - * not the fastest method, but it is very simple, and it is about as - * fast as it could be for grids which contain no "marked" objects or - * "visible" monsters. - * - * We apply the effects of hallucination during each layer. Objects will - * always appear as random "objects", monsters will always appear as random - * "monsters", and normal grids occasionally appear as random "monsters" or - * "objects", but note that these random "monsters" and "objects" are really - * just "colored ascii symbols" (which may look silly on some machines). - * - * The hallucination functions avoid taking any pointers to local variables - * because some compilers refuse to use registers for any local variables - * whose address is taken anywhere in the function. - * - * As an optimization, we can handle the "player" grid as a special case. - * - * Note that the memorization of "objects" and "monsters" is not related - * to the memorization of "terrain". This allows the player to memorize - * the terrain of a grid without memorizing any objects in that grid, and - * to detect monsters without detecting anything about the terrain of the - * grid containing the monster. - * - * The fact that all interesting "objects" and "terrain features" are - * memorized as soon as they become visible for the first time means - * that we only have to check the "CAVE_SEEN" flag for "boring" grids. - * - * Note that bizarre things must be done when the "attr" and/or "char" - * codes have the "high-bit" set, since these values are used to encode - * various "special" pictures in some versions, and certain situations, - * such as "multi-hued" or "clear" monsters, cause the attr/char codes - * to be "scrambled" in various ways. - * - * Note that the "zero" entry in the feature/object/monster arrays are - * used to provide "special" attr/char codes, with "monster zero" being - * used for the player attr/char, "object zero" being used for the "stack" - * attr/char, and "feature zero" being used for the "nothing" attr/char. - * - * Note that eventually we may want to use the "&" symbol for embedded - * treasure, and use the "*" symbol to indicate multiple objects, but - * currently, we simply use the attr/char of the first "marked" object - * in the stack, if any, and so "object zero" is unused. XXX XXX XXX - * - * Note the assumption that doing "x_ptr = &x_info[x]" plus a few of - * "x_ptr->xxx", is quicker than "x_info[x].xxx", even if "x" is a fixed - * constant. If this is incorrect then a lot of code should be changed. - * - * - * Some comments on the "terrain" layer... - * - * Note that "boring" grids (floors, invisible traps, and any illegal grids) - * are very different from "interesting" grids (all other terrain features), - * and the two types of grids are handled completely separately. The most - * important distinction is that "boring" grids may or may not be memorized - * when they are first encountered, and so we must use the "CAVE_SEEN" flag - * to see if they are "see-able". - * - * - * Some comments on the "terrain" layer (boring grids)... - * - * Note that "boring" grids are always drawn using the picture for "empty - * floors", which is stored in "f_info[FEAT_FLOOR]". Sometimes, special - * lighting effects may cause this picture to be modified. - * - * Note that "invisible traps" are always displayes exactly like "empty - * floors", which prevents various forms of "cheating", with no loss of - * efficiency. There are still a few ways to "guess" where traps may be - * located, for example, objects will never fall into a grid containing - * an invisible trap. XXX XXX - * - * To determine if a "boring" grid should be displayed, we simply check to - * see if it is either memorized ("CAVE_MARK"), or currently "see-able" by - * the player ("CAVE_SEEN"). Note that "CAVE_SEEN" is now maintained by the - * "update_view()" function. - * - * Note the "special lighting effects" which can be activated for "boring" - * grids using the "view_special_lite" option, causing certain such grids - * to be displayed using special colors. If the grid is "see-able" by - * the player, we will use the normal (except that, if the "view_yellow_lite" - * option is set, and the grid is *only* "see-able" because of the player's - * torch, then we will use "yellow"), else if the player is "blind", we will - * use greyscale, else if the grid is not "illuminated", we will use "dark - * gray", if the "view_bright_lite" option is set, we will use "darker" colour - * else we will use the normal colour. - * - * - * Some comments on the "terrain" layer (non-boring grids)... - * - * Note the use of the "mimic" field in the "terrain feature" processing, - * which allows any feature to "pretend" to be another feature. This is - * used to "hide" secret doors, and to make all "doors" appear the same, - * and all "walls" appear the same, and "hidden" treasure stay hidden. - * Note that it is possible to use this field to make a feature "look" - * like a floor, but the "view_special_lite" flag only affects actual - * "boring" grids. - * - * Since "interesting" grids are always memorized as soon as they become - * "see-able" by the player ("CAVE_SEEN"), such a grid only needs to be - * displayed if it is memorized ("CAVE_MARK"). Most "interesting" grids - * are in fact non-memorized, non-see-able, wall grids, so the fact that - * we do not have to check the "CAVE_SEEN" flag adds some efficiency, at - * the cost of *forcing* the memorization of all "interesting" grids when - * they are first seen. Since the "CAVE_SEEN" flag is now maintained by - * the "update_view()" function, this efficiency is not as significant as - * it was in previous versions, and could perhaps be removed. - * (so I removed this to simplify the terrain feature handling -- pelpel) - * - * Note the "special lighting effects" which can be activated for "wall" - * grids using the "view_granite_lite" option, causing certain such grids - * to be displayed using special colors. - * If the grid is "see-able" by the player, we will use the normal colour - * else if the player is "blind", we will use grey scale, else if the - * "view_bright_lite" option is set, we will use reduced colour, else we - * will use the normal one. - * - * Note that "wall" grids are more complicated than "boring" grids, due to - * the fact that "CAVE_GLOW" for a "wall" grid means that the grid *might* - * be glowing, depending on where the player is standing in relation to the - * wall. In particular, the wall of an illuminated room should look just - * like any other (dark) wall unless the player is actually inside the room. - * - * Thus, we do not support as many visual special effects for "wall" grids - * as we do for "boring" grids, since many of them would give the player - * information about the "CAVE_GLOW" flag of the wall grid, in particular, - * it would allow the player to notice the walls of illuminated rooms from - * a dark hallway that happened to run beside the room. - * - * - * Some comments on the "object" layer... - * - * Currently, we do nothing with multi-hued objects, because there are - * not any. If there were, they would have to set "shimmer_objects" - * when they were created, and then new "shimmer" code in "dungeon.c" - * would have to be created handle the "shimmer" effect, and the code - * in "cave.c" would have to be updated to create the shimmer effect. - * This did not seem worth the effort. XXX XXX - * - * - * Some comments on the "monster"/"player" layer... - * - * Note that monsters can have some "special" flags, including "ATTR_MULTI", - * which means their color changes, and "ATTR_CLEAR", which means they take - * the color of whatever is under them, and "CHAR_CLEAR", which means that - * they take the symbol of whatever is under them. Technically, the flag - * "CHAR_MULTI" is supposed to indicate that a monster looks strange when - * examined, but this flag is currently ignored. All of these flags are - * ignored if the "avoid_other" option is set, since checking for these - * conditions is expensive (and annoying) on some systems. - * - * Normally, players could be handled just like monsters, except that the - * concept of the "torch lite" of others player would add complications. - * For efficiency, however, we handle the (only) player first, since the - * "player" symbol always "pre-empts" any other facts about the grid. - * - * The "hidden_player" efficiency option, which only makes sense with a - * single player, allows the player symbol to be hidden while running. - */ - -/* - * Alternative colours for unseen grids - * - * Reduced colours - remembered interesting grids and perma-lit floors - * B&W - currently only used by blindness effect - */ - -/* Colour */ -static byte dark_attrs[16] = -{ - TERM_DARK, TERM_L_WHITE, TERM_L_DARK, TERM_ORANGE, - TERM_RED, TERM_GREEN, TERM_BLUE, TERM_UMBER, - TERM_L_DARK, TERM_SLATE, TERM_VIOLET, TERM_YELLOW, - TERM_RED, TERM_GREEN, TERM_BLUE, TERM_UMBER -}; - -/* B&W */ -static byte darker_attrs[16] = -{ - TERM_DARK, TERM_L_WHITE, TERM_L_DARK, TERM_SLATE, - TERM_L_DARK, TERM_L_DARK, TERM_L_DARK, TERM_L_DARK, - TERM_L_DARK, TERM_SLATE, TERM_L_DARK, TERM_SLATE, - TERM_SLATE, TERM_SLATE, TERM_SLATE, TERM_SLATE -}; - - -void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp, - byte *eap, char *ecp) -{ - cave_type *c_ptr; - - feature_type *f_ptr; - - s16b this_o_idx, next_o_idx = 0; - - u16b info; - - s16b t_idx; - - byte feat; - - byte a; - - byte c; - - /* - * This means that a port supports graphics overlay as well as lighting - * effects. See the step 3 below for the detailed information about - * lighting. Basically, it requires "darker" tiles for those terrain - * features with SUPPORT_LIGHT flag set, and they must be arranged - * this way: - * col col+1 col+2 - * row base darker brighter - */ - bool_ graf_new = ((graphics_mode == GRAPHICS_ISO) || - (graphics_mode == GRAPHICS_NEW)); - - /* - * I never understand why some coders like shimmering so much. - * It just serves to hurt my eyes, IMHO. If one feels like to show off, - * go for better graphics support... Anyway this means a port allows - * changing attr independently from its char -- pelpel - */ - bool_ attr_mutable = (!use_graphics || - (graphics_mode == GRAPHICS_IBM)); - - - /**** Preparation ****/ - - /* Access the grid */ - c_ptr = &cave[y][x]; - - - /* Cache some frequently used values */ - - /* Grid info */ - info = c_ptr->info; - - /* Feature code */ - feat = c_ptr->feat; - - /* Apply "mimic" field */ - if (c_ptr->mimic) - { - feat = c_ptr->mimic; - } - else - { - feat = f_info[feat].mimic; - } - - /* Access floor */ - f_ptr = &f_info[feat]; - - - /* Reset attr/char */ - *eap = 0; - *ecp = 0; - - - /**** Layer 1 -- Terrain feature ****/ - - /* Only memorised or visible grids are displayed */ - if (info & (CAVE_MARK | CAVE_SEEN)) - { - /**** Step 1 -- Retrieve base attr/char ****/ - - /* 'Sane' terrain features */ - if (feat != FEAT_SHOP) - { - /* Normal char */ - c = f_ptr->x_char; - - /* Normal attr */ - a = f_ptr->x_attr; - } - - /* Mega-Hack 1 -- Building don't conform to f_info */ - else - { - c = st_info[c_ptr->special].x_char; - a = st_info[c_ptr->special].x_attr; - } - - /* Mega-Hack 2 -- stair to dungeon branch are purple */ - if (c_ptr->special && attr_mutable && - ((feat == FEAT_MORE) || (feat == FEAT_LESS))) - { - a = TERM_VIOLET; - } - - /* Mega-Hack 3 -- Traps don't have f_info entries either */ - if ((info & (CAVE_TRDT)) && (feat != FEAT_ILLUS_WALL)) - { - /* Trap index */ - t_idx = c_ptr->t_idx; - - if (use_graphics && - (t_info[t_idx].g_attr != 0) && - (t_info[t_idx].g_char != 0)) - { - - if (graf_new) - { - *eap = t_info[t_idx].g_attr; - *ecp = t_info[t_idx].g_char; - } - else - { - a = t_info[t_idx].g_attr; - c = t_info[t_idx].g_char; - } - - } - else - { - /* - * If trap is set on a floor grid that is not - * one of "interesting" features, use a special - * symbol to display it. Check for doors is no longer - * necessary because they have REMEMBER flag now. - * - * Cave macros cannot be used safely here, because of - * c_ptr->mimic XXX XXX - */ - if (!attr_mutable) - { - a = f_info[FEAT_TRAP].x_attr; - c = f_info[FEAT_TRAP].x_char; - } - else - { - if ((f_ptr->flags1 & (FF1_FLOOR | FF1_REMEMBER)) == FF1_FLOOR) - { - c = f_info[FEAT_TRAP].x_char; - } - - /* Add attr XXX XXX XXX */ - a = t_info[t_idx].color; - - /* Get a new color with a strange formula :) XXX XXX XXX */ - if (t_info[t_idx].flags & FTRAP_CHANGE) - { - s32b tmp; - - tmp = dun_level + dungeon_type + feat; - - a = tmp % 16; - } - } - } - } - - - /**** Step 2 -- Apply special random effects ****/ - if (!avoid_other && !avoid_shimmer && attr_mutable) - { - /* Special terrain effect */ - if (c_ptr->effect) - { - a = spell_color(effects[c_ptr->effect].type); - } - - /* Multi-hued attr */ - else if (f_ptr->flags1 & FF1_ATTR_MULTI) - { - a = f_ptr->shimmer[rand_int(7)]; - } - } - - - /* - * Step 3 - * - * Special lighting effects, if specified and applicable - * This will never happen for - * - any grids in the overhead map - * - traps - * - (graphics modes) terrain features without corresponding - * "darker" tiles. - * - * Note the use of f_ptr->flags1 to avoid problems with - * c_ptr->mimic. - */ - - /* view_special_lite: lighting effects for boring features */ - if (view_special_lite && - ((f_ptr->flags1 & (FF1_FLOOR | FF1_REMEMBER)) == FF1_FLOOR)) - { - if (!p_ptr->wild_mode && !(info & (CAVE_TRDT)) && - (attr_mutable || (graf_new && feat_supports_lighting(feat)))) - { - /* Handle "seen" grids */ - if (info & (CAVE_SEEN)) - { - /* Only lit by "torch" light */ - if (view_yellow_lite && !(info & (CAVE_GLOW))) - { - if (graf_new) - { - /* Use a brightly lit tile */ - c += 2; - } - else - { - /* Use "yellow" */ - a = TERM_YELLOW; - } - } - } - - /* Handle "blind" */ - else if (p_ptr->blind) - { - if (graf_new) - { - /* Use a dark tile */ - c++; - } - else - { - /* Use darker colour */ - a = darker_attrs[a & 0xF]; - } - } - - /* Handle "dark" grids */ - else if (!(info & (CAVE_GLOW))) - { - if (graf_new) - { - /* Use a dark tile */ - c++; - } - else - { - /* Use darkest colour */ - a = TERM_L_DARK; - } - } - - /* "Out-of-sight" glowing grids -- handle "view_bright_lite" */ - else if (view_bright_lite) - { - if (graf_new) - { - /* Use a dark tile */ - c++; - } - else - { - /* Use darker colour */ - a = dark_attrs[a & 0xF]; - } - } - } - } - - /* view_granite_lite: lighting effects for walls and doors */ - else if (view_granite_lite && - (f_ptr->flags1 & (FF1_NO_VISION | FF1_DOOR))) - { - if (!p_ptr->wild_mode && !(info & (CAVE_TRDT)) && - (attr_mutable || (graf_new && feat_supports_lighting(feat)))) - { - /* Handle "seen" grids */ - if (info & (CAVE_SEEN)) - { - /* Do nothing */ - } - - /* Handle "blind" */ - else if (p_ptr->blind) - { - if (graf_new) - { - /* Use a dark tile */ - c++; - } - else - { - /* Use darker colour */ - a = darker_attrs[a & 0xF]; - } - } - - /* Handle "view_bright_lite" */ - else if (view_bright_lite) - { - if (graf_new) - { - /* Use a dark tile */ - c++; - } - else - { - /* Use darker colour */ - a = dark_attrs[a & 0xF]; - } - } - - else - { - if (graf_new) - { - /* Use a brightly lit tile */ - c += 2; - } - else - { - /* Use normal colour */ - } - } - } - } - } - - /* Unknown grids */ - else - { - /* Access darkness */ - f_ptr = &f_info[FEAT_NONE]; - - /* Normal attr */ - a = f_ptr->x_attr; - - /* Normal char */ - c = f_ptr->x_char; - } - - /* - * Hack -- rare random hallucination - * Because we cannot be sure which is outer dungeon walls, - * the check for 'feat' has been removed - */ - if (p_ptr->image && (rand_int(256) == 0)) - { - /* Hallucinate */ - image_random(ap, cp); - } - - /* Save the terrain info for the transparency effects */ - *tap = a; - *tcp = c; - - /* Save the info */ - *ap = a; - *cp = c; - - - /**** Layer 2 -- Objects ****/ - - if (feat != FEAT_MON_TRAP) - { - for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) - { - object_type * o_ptr; - - /* Acquire object */ - o_ptr = &o_list[this_o_idx]; - - /* Acquire next object */ - next_o_idx = o_ptr->next_o_idx; - - /* Memorized objects */ - if (o_ptr->marked) - { - /* Normal char */ - *cp = object_char(o_ptr); - - /* Normal attr */ - *ap = object_attr(o_ptr); - - /* Multi-hued attr */ - if (!avoid_other && attr_mutable && - (k_info[o_ptr->k_idx].flags5 & TR5_ATTR_MULTI)) - { - *ap = get_shimmer_color(); - } - - /* Hack -- hallucination */ - if (p_ptr->image) image_object(ap, cp); - - /* Done */ - break; - } - } - } - - - /**** Layer 3 -- Handle monsters ****/ - - if (c_ptr->m_idx) - { - monster_type *m_ptr = &m_list[c_ptr->m_idx]; - monster_race *r_ptr = race_inf(m_ptr); - - if (r_ptr->flags9 & RF9_MIMIC) - { - object_type *o_ptr; - - /* Acquire object */ - o_ptr = &o_list[m_ptr->hold_o_idx]; - - /* Memorized objects */ - if (o_ptr->marked) - { - /* Normal char */ - *cp = object_char(o_ptr); - - /* Normal attr */ - *ap = object_attr(o_ptr); - - /* Multi-hued attr */ - if (!avoid_other && attr_mutable && - (k_info[o_ptr->k_idx].flags5 & TR5_ATTR_MULTI)) - { - *ap = get_shimmer_color(); - } - - /* Hack -- hallucination */ - if (p_ptr->image) image_object(ap, cp); - } - } - else - { - /* Visible monster */ - if (m_ptr->ml) - { - monster_race *r_ptr = race_inf(m_ptr); - - /* Reset attr/char */ - *eap = 0; - *ecp = 0; - - if (use_graphics) - { - - if (graf_new) - { - monster_ego *re_ptr = &re_info[m_ptr->ego]; - - /* Desired attr */ - *eap = re_ptr->g_attr; - - /* Desired char */ - *ecp = re_ptr->g_char; - } - - /* Use base monster */ - r_ptr = &r_info[m_ptr->r_idx]; - } - - /* Desired attr/char */ - c = r_ptr->x_char; - a = r_ptr->x_attr; - - /* Ignore weird codes */ - if (avoid_other) - { - /* Use char */ - *cp = c; - - /* Use attr */ - *ap = a; - } - - /* Special attr/char codes */ - else if (!attr_mutable) - { - /* Use char */ - *cp = c; - - /* Use attr */ - *ap = a; - } - - /* Multi-hued monster */ - else if (r_ptr->flags1 & (RF1_ATTR_MULTI)) - { - /* Is it a shapechanger? */ - if (r_ptr->flags2 & (RF2_SHAPECHANGER)) - { - image_random(ap, cp); - } - else - *cp = c; - - /* Multi-hued attr */ - if (r_ptr->flags2 & (RF2_ATTR_ANY)) - { - *ap = randint(15); - } - else - { - *ap = multi_hued_attr(r_ptr); - } - } - - /* Normal monster (not "clear" in any way) */ - else if (!(r_ptr->flags1 & (RF1_ATTR_CLEAR | RF1_CHAR_CLEAR))) - { - /* Use char */ - *cp = c; - - /* Use attr */ - *ap = a; - } - - /* - * Hack -- Bizarre grid under monster - * WAS: else if (*ap & 0x80) || (*cp & 0x80) -- pelpel - */ - else if (*ap & 0x80) - { - /* Use char */ - *cp = c; - - /* Use attr */ - *ap = a; - } - - /* Normal */ - else - { - /* Normal (non-clear char) monster */ - if (!(r_ptr->flags1 & (RF1_CHAR_CLEAR))) - { - /* Normal char */ - *cp = c; - } - - /* Normal (non-clear attr) monster */ - else if (!(r_ptr->flags1 & (RF1_ATTR_CLEAR))) - { - /* Normal attr */ - *ap = a; - } - } - - /* Hack -- hallucination */ - if (p_ptr->image) - { - /* Hallucinatory monster */ - image_monster(ap, cp); - } - } - } - } - - /* Handle "player" */ - if ((y == p_ptr->py) && (x == p_ptr->px) && - (!p_ptr->invis || p_ptr->see_inv)) - { - monster_race *r_ptr = &r_info[p_ptr->body_monster]; - - /* Reset attr/char */ - *eap = 0; - *ecp = 0; - - /* Get the "player" attr */ - if (!avoid_other && attr_mutable && (r_ptr->flags1 & RF1_ATTR_MULTI)) - { - a = get_shimmer_color(); - } - else - { - a = r_ptr->x_attr; - } - - /* Get the "player" char */ - c = r_ptr->x_char; - - - /* Mega-Hack -- Apply modifications to player graphics XXX XXX XXX */ - switch (graphics_mode) - { - case GRAPHICS_NONE: - case GRAPHICS_IBM: - { - if (player_char_health) - { - int percent = p_ptr->chp * 10 / p_ptr->mhp; - - if (percent < 7) - { - c = I2D(percent); - if (percent < 3) a = TERM_L_RED; - } - } - - break; - } - - case GRAPHICS_OLD: - { - if (player_symbols) - { - a = BMP_FIRST_PC_CLASS + p_ptr->pclass; - c = BMP_FIRST_PC_RACE + p_ptr->prace; - } - - break; - } - - case GRAPHICS_ISO: - case GRAPHICS_NEW: - { - if (p_ptr->pracem) - { - player_race_mod *rmp_ptr = &race_mod_info[p_ptr->pracem]; - - /* Desired attr */ - *eap = rmp_ptr->g_attr; - - /* Desired char */ - *ecp = rmp_ptr->g_char; - } - - /* +AKH 20020421 - Health dispay for graphics, too */ - if (player_char_health && (graphics_mode == GRAPHICS_NEW)) - { - int percent = p_ptr->chp * 14 / p_ptr->mhp; - - if (percent < 10) - { - *eap = 10; - *ecp = 32 + 14 - percent; - } - } - - break; - } - - } - - /* Save the info */ - *ap = a; - *cp = c; - - } -} - - -/* - * Special version of map_info, for use by cmovie and HTML converter - * to obtain pure-ASCII image of dungeon map - */ -void map_info_default(int y, int x, byte *ap, char *cp) -{ - cave_type *c_ptr; - - feature_type *f_ptr; - - s16b this_o_idx, next_o_idx = 0; - - u16b info; - - s16b t_idx; - - byte feat; - - byte a; - - byte c; - - bool_ use_graphics_hack = use_graphics; - byte graphics_mode_hack = graphics_mode; - - - /* Temporarily disable graphics mode -- for some random effects XXX */ - use_graphics = FALSE; - graphics_mode = GRAPHICS_NONE; - - /**** Preparation ****/ - - /* Access the grid */ - c_ptr = &cave[y][x]; - - - /* Cache some frequently used values */ - - /* Grid info */ - info = c_ptr->info; - - /* Feature code */ - feat = c_ptr->feat; - - /* Apply "mimic" field */ - if (c_ptr->mimic) - { - feat = c_ptr->mimic; - } - else - { - feat = f_info[feat].mimic; - } - - /* Access floor */ - f_ptr = &f_info[feat]; - - - /**** Layer 1 -- Terrain feature ****/ - - /* Only memorised or visible grids are displayed */ - if (info & (CAVE_MARK | CAVE_SEEN)) - { - /**** Step 1 -- Retrieve base attr/char ****/ - - /* 'Sane' terrain features */ - if (feat != FEAT_SHOP) - { - /* Default char */ - c = f_ptr->d_char; - - /* Default attr */ - a = f_ptr->d_attr; - } - - /* Mega-Hack 1 -- Building don't conform to f_info */ - else - { - c = st_info[c_ptr->special].d_char; - a = st_info[c_ptr->special].d_attr; - } - - /* Mega-Hack 2 -- stair to dungeon branch are purple */ - if (c_ptr->special && - ((feat == FEAT_MORE) || (feat == FEAT_LESS))) - { - a = TERM_VIOLET; - } - - /* Mega-Hack 3 -- Traps don't have f_info entries either */ - if ((info & (CAVE_TRDT)) && (feat != FEAT_ILLUS_WALL)) - { - /* Trap index */ - t_idx = c_ptr->t_idx; - - /* - * If trap is set on a floor grid that is not - * one of "interesting" features, use a special - * symbol to display it. Check for doors is no longer - * necessary because they have REMEMBER flag now. - * - * Cave macros cannot be used safely here, because of - * c_ptr->mimic XXX XXX - */ - if ((f_ptr->flags1 & (FF1_FLOOR | FF1_REMEMBER)) == FF1_FLOOR) - { - c = f_info[FEAT_TRAP].d_char; - } - - /* Add attr */ - a = t_info[t_idx].color; - - /* Get a new color with a strange formula :) */ - if (t_info[t_idx].flags & FTRAP_CHANGE) - { - s32b tmp; - - tmp = dun_level + dungeon_type + feat; - - a = tmp % 16; - } - } - - - /**** Step 2 -- Apply special random effects ****/ - if (!avoid_other) - { - /* Special terrain effect */ - if (c_ptr->effect) - { - a = spell_color(effects[c_ptr->effect].type); - } - - /* Multi-hued attr */ - else if (f_ptr->flags1 & FF1_ATTR_MULTI) - { - a = f_ptr->shimmer[rand_int(7)]; - } - } - - - /* - * Step 3 - * - * Special lighting effects, if specified and applicable - * This will never happen for - * - any grids in the overhead map - * - traps - * - (graphics modes) terrain features without corresponding - * "darker" tiles. - * - * All the if's here are flag checks, so changed order shouldn't - * affect performance a lot, I hope... - */ - - /* view_special_lite: lighting effects for boring features */ - if (view_special_lite && - ((f_ptr->flags1 & (FF1_FLOOR | FF1_REMEMBER)) == FF1_FLOOR)) - { - if (!p_ptr->wild_mode && !(info & (CAVE_TRDT))) - { - /* Handle "seen" grids */ - if (info & (CAVE_SEEN)) - { - /* Only lit by "torch" light */ - if (view_yellow_lite && !(info & (CAVE_GLOW))) - { - /* Use "yellow" */ - a = TERM_YELLOW; - } - } - - /* Handle "blind" */ - else if (p_ptr->blind) - { - /* Use darker colour */ - a = darker_attrs[a & 0xF]; - } - - /* Handle "dark" grids */ - else if (!(info & (CAVE_GLOW))) - { - /* Use darkest colour */ - a = TERM_L_DARK; - } - - /* "Out-of-sight" glowing grids -- handle "view_bright_lite" */ - else if (view_bright_lite) - { - /* Use darker colour */ - a = dark_attrs[a & 0xF]; - } - } - } - - /* view_granite_lite: lighting effects for walls and doors */ - else if (view_granite_lite && - (f_ptr->flags1 & (FF1_NO_VISION | FF1_DOOR))) - { - if (!p_ptr->wild_mode && !(info & (CAVE_TRDT))) - { - /* Handle "seen" grids */ - if (info & (CAVE_SEEN)) - { - /* Do nothing */ - } - - /* Handle "blind" */ - else if (p_ptr->blind) - { - /* Use darker colour */ - a = darker_attrs[a & 0xF]; - } - - /* Handle "view_bright_lite" */ - else if (view_bright_lite) - { - /* Use darker colour */ - a = dark_attrs[a & 0xF]; - } - } - } - } - - /* Unknown grids */ - else - { - /* Access darkness */ - f_ptr = &f_info[FEAT_NONE]; - - /* Default attr */ - a = f_ptr->d_attr; - - /* Default char */ - c = f_ptr->d_char; - } - - /* - * Hack -- rare random hallucination - * Because we cannot be sure which is outer dungeon walls, - * the check for 'feat' has been removed - */ - if (p_ptr->image && (rand_int(256) == 0)) - { - /* Hallucinate */ - image_random(ap, cp); - } - - /* Save the info */ - *ap = a; - *cp = c; - - - /**** Layer 2 -- Objects ****/ - - if (feat != FEAT_MON_TRAP) - { - for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) - { - object_type * o_ptr; - - /* Acquire object */ - o_ptr = &o_list[this_o_idx]; - - /* Acquire next object */ - next_o_idx = o_ptr->next_o_idx; - - /* Memorized objects */ - if (o_ptr->marked) - { - /* Normal char */ - *cp = object_char_default(o_ptr); - - /* Normal attr */ - *ap = object_attr_default(o_ptr); - - /* Multi-hued attr */ - if (!avoid_other && - (k_info[o_ptr->k_idx].flags5 & TR5_ATTR_MULTI)) - { - *ap = get_shimmer_color(); - } - - /* Hack -- hallucination */ - if (p_ptr->image) image_object(ap, cp); - - /* Done */ - break; - } - } - } - - - /**** Layer 3 -- Handle monsters ****/ - - if (c_ptr->m_idx) - { - monster_type *m_ptr = &m_list[c_ptr->m_idx]; - monster_race *r_ptr = race_inf(m_ptr); - - if (r_ptr->flags9 & RF9_MIMIC) - { - object_type *o_ptr; - - /* Acquire object */ - o_ptr = &o_list[m_ptr->hold_o_idx]; - - /* Memorized objects */ - if (o_ptr->marked) - { - /* Normal char */ - *cp = object_char_default(o_ptr); - - /* Normal attr */ - *ap = object_attr_default(o_ptr); - - /* Multi-hued attr */ - if (!avoid_other && !use_graphics && - (k_info[o_ptr->k_idx].flags5 & TR5_ATTR_MULTI)) - { - *ap = get_shimmer_color(); - } - - /* Hack -- hallucination */ - if (p_ptr->image) image_object(ap, cp); - } - } - else - { - /* Visible monster */ - if (m_ptr->ml) - { - monster_race *r_ptr = race_inf(m_ptr); - - /* Default attr/char */ - c = r_ptr->d_char; - a = r_ptr->d_attr; - - /* Ignore weird codes */ - if (avoid_other) - { - /* Use char */ - *cp = c; - - /* Use attr */ - *ap = a; - } - - /* Multi-hued monster */ - else if (r_ptr->flags1 & (RF1_ATTR_MULTI)) - { - /* Is it a shapechanger? */ - if (r_ptr->flags2 & (RF2_SHAPECHANGER)) - { - image_random(ap, cp); - } - else - *cp = c; - - /* Multi-hued attr */ - if (r_ptr->flags2 & (RF2_ATTR_ANY)) - { - *ap = randint(15); - } - else - { - *ap = multi_hued_attr(r_ptr); - } - } - - /* Normal monster (not "clear" in any way) */ - else if (!(r_ptr->flags1 & (RF1_ATTR_CLEAR | RF1_CHAR_CLEAR))) - { - /* Use char */ - *cp = c; - - /* Use attr */ - *ap = a; - } - - /* Hack -- Bizarre grid under monster */ - else if ((*ap & 0x80) || (*cp & 0x80)) - { - /* Use char */ - *cp = c; - - /* Use attr */ - *ap = a; - } - - /* Normal */ - else - { - /* Normal (non-clear char) monster */ - if (!(r_ptr->flags1 & (RF1_CHAR_CLEAR))) - { - /* Normal char */ - *cp = c; - } - - /* Normal (non-clear attr) monster */ - else if (!(r_ptr->flags1 & (RF1_ATTR_CLEAR))) - { - /* Normal attr */ - *ap = a; - } - } - - /* Hack -- hallucination */ - if (p_ptr->image) - { - /* Hallucinatory monster */ - image_monster(ap, cp); - } - } - } - } - - - /* Handle "player" */ - if ((y == p_ptr->py) && (x == p_ptr->px) && - (!p_ptr->invis || - (p_ptr->invis && p_ptr->see_inv))) - { - monster_race *r_ptr = &r_info[p_ptr->body_monster]; - - /* Get the "player" attr */ - if (!avoid_other && (r_ptr->flags1 & RF1_ATTR_MULTI)) - { - a = get_shimmer_color(); - } - else - { - a = r_ptr->d_attr; - } - - /* Get the "player" char */ - c = r_ptr->d_char; - - /* Save the info */ - *ap = a; - *cp = c; - - } - - /* XXX Restore the graphics mode */ - use_graphics = use_graphics_hack; - graphics_mode = graphics_mode_hack; -} - - -/* - * Calculate panel colum of a location in the map - */ -static int panel_col_of(int col) -{ - col -= panel_col_min; - if (use_bigtile) col *= 2; - return col + COL_MAP; -} - - - -/* - * Moves the cursor to a given MAP (y,x) location - */ -void move_cursor_relative(int row, int col) -{ - /* Real co-ords convert to screen positions */ - row -= panel_row_prt; - - /* Go there */ - Term_gotoxy(panel_col_of(col), row); -} - - - -/* - * Place an attr/char pair at the given map coordinate, if legal. - */ -void print_rel(char c, byte a, int y, int x) -{ - /* Paranoia -- Only do "legal" locations */ - if (!panel_contains(y, x)) return; - - /* Draw the char using the attr */ - Term_draw(panel_col_of(x), y - panel_row_prt, a, c); - - if (use_bigtile) - { - char c2; - byte a2; - - if (a & 0x80) - { - a2 = 255; - c2 = 255; - } - else - { - a2 = TERM_WHITE; - c2 = ' '; - } - Term_draw(panel_col_of(x) + 1, y - panel_row_prt, a2, c2); - } -} - - - - - -/* - * Memorize interesting viewable object/features in the given grid - * - * This function should only be called on "legal" grids. - * - * This function will memorize the object and/or feature in the given - * grid, if they are (1) viewable and (2) interesting. Note that all - * objects are interesting, all terrain features except floors (and - * invisible traps) are interesting, and floors (and invisible traps) - * are interesting sometimes (depending on various options involving - * the illumination of floor grids). - * - * The automatic memorization of all objects and non-floor terrain - * features as soon as they are displayed allows incredible amounts - * of optimization in various places, especially "map_info()". - * - * Note that the memorization of objects is completely separate from - * the memorization of terrain features, preventing annoying floor - * memorization when a detected object is picked up from a dark floor, - * and object memorization when an object is dropped into a floor grid - * which is memorized but out-of-sight. - * - * This function should be called every time the "memorization" of - * a grid (or the object in a grid) is called into question, such - * as when an object is created in a grid, when a terrain feature - * "changes" from "floor" to "non-floor", when any grid becomes - * "illuminated" or "viewable", and when a "floor" grid becomes - * "torch-lit". - * - * Note the relatively efficient use of this function by the various - * "update_view()" and "update_lite()" calls, to allow objects and - * terrain features to be memorized (and drawn) whenever they become - * viewable or illuminated in any way, but not when they "maintain" - * or "lose" their previous viewability or illumination. - * - * Note the butchered "internal" version of "player_can_see_bold()", - * optimized primarily for the most common cases, that is, for the - * non-marked floor grids. - */ -void note_spot(int y, int x) -{ - cave_type *c_ptr = &cave[y][x]; - - u16b info = c_ptr->info; - - s16b this_o_idx, next_o_idx = 0; - - - /* Require "seen" flag */ - if (!(info & (CAVE_SEEN))) return; - - - /* Hack -- memorize objects */ - for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) - { - object_type * o_ptr = &o_list[this_o_idx]; - - /* Acquire next object */ - next_o_idx = o_ptr->next_o_idx; - - /* Memorize objects */ - o_ptr->marked = TRUE; - } - - if (c_ptr->m_idx) - { - monster_type *m_ptr = &m_list[c_ptr->m_idx]; - monster_race *r_ptr = race_inf(m_ptr); - - if (r_ptr->flags9 & RF9_MIMIC) - { - object_type *o_ptr = &o_list[m_ptr->hold_o_idx]; - - o_ptr->marked = TRUE; - } - } - - - /* Hack -- memorize grids */ - if (!(info & (CAVE_MARK))) - { - /* Memorise some "boring" grids */ - if (cave_plain_floor_grid(c_ptr)) - { - /* Option -- memorise certain floors */ - if ((info & (CAVE_TRDT)) || - ((info & (CAVE_GLOW)) && view_perma_grids ) || - view_torch_grids) - { - /* Memorize */ - c_ptr->info |= (CAVE_MARK); - } - } - - /* Memorise all "interesting" grids */ - else - { - /* Memorize */ - c_ptr->info |= (CAVE_MARK); - } - } -} - - -/* - * Redraw (on the screen) a given MAP location - * - * This function should only be called on "legal" grids - */ -void lite_spot(int y, int x) -{ - byte a, a2; - byte c, c2; - - byte ta; - char tc; - - byte ea; - char ec; - - - /* Redraw if on screen */ - if (panel_contains(y, x)) - { - /* Examine the grid */ - map_info(y, x, &a, (char*)&c, &ta, &tc, &ea, &ec); - - /* Hack -- Queue it */ - Term_queue_char(panel_col_of(x), y - panel_row_prt, a, c, ta, tc, ea, ec); - if (use_bigtile) - { - if (a & 0x80) - { - a2 = 255; - c2 = 255; - } - else - { - a2 = TERM_WHITE; - c2 = ' '; - } - Term_queue_char(panel_col_of(x) + 1, y - panel_row_prt, a2, c2, 0, 0, 0, 0); - } - - } -} - - - - -/* - * Prints the map of the dungeon - * - * Note that, for efficiency, we contain an "optimized" version - * of both "lite_spot()" and "print_rel()", and that we use the - * "lite_spot()" function to display the player grid, if needed. - */ -void prt_map(void) -{ - int x, y; - - int v; - - /* Access the cursor state */ - (void)Term_get_cursor(&v); - - /* Hide the cursor */ - (void)Term_set_cursor(0); - - /* Dump the map */ - for (y = panel_row_min; y <= panel_row_max; y++) - { - /* Scan the columns of row "y" */ - for (x = panel_col_min; x <= panel_col_max; x++) - { - byte a, a2; - char c, c2; - - byte ta; - char tc; - byte ea; - char ec; - - /* Determine what is there */ - map_info(y, x, &a, &c, &ta, &tc, &ea, &ec); - - /* Efficiency -- Redraw that grid of the map */ - Term_queue_char(panel_col_of(x), y - panel_row_prt, a, c, ta, tc, ea, ec); - if (use_bigtile) - { - if (a & 0x80) - { - a2 = 255; - c2 = 255; - } - else - { - a2 = TERM_WHITE; - c2 = ' '; - } - Term_queue_char(panel_col_of(x) + 1, y - panel_row_prt, a2, c2, 0, 0, 0, 0); - } - } - } - - /* Display player */ - lite_spot(p_ptr->py, p_ptr->px); - - /* Restore the cursor */ - (void)Term_set_cursor(v); -} - - - - - -/* - * Display highest priority object in the RATIO by RATIO area - */ - -/* - * Display the entire map - */ -#define MAP_HGT (MAX_HGT / RATIO) -#define MAP_WID (MAX_WID / RATIO) - -/* - * Hack -- priority array (see below) - * - * Note that all "walls" always look like "secret doors" (see "map_info()"). - */ -static byte priority_table[][2] = -{ - /* Dark */ - { FEAT_NONE, 2 }, - - /* Floors */ - { FEAT_FLOOR, 5 }, - - /* Walls */ - { FEAT_SECRET, 10 }, - - /* Quartz */ - { FEAT_QUARTZ, 11 }, - - /* Magma */ - { FEAT_MAGMA, 12 }, - - /* Rubble */ - { FEAT_RUBBLE, 13 }, - - /* Sandwall */ - { FEAT_SANDWALL, 14 }, - - /* Open doors */ - { FEAT_OPEN, 15 }, - { FEAT_BROKEN, 15 }, - - /* Closed doors */ - { FEAT_DOOR_HEAD + 0x00, 17 }, - - /* Hidden gold */ - { FEAT_QUARTZ_K, 19 }, - { FEAT_MAGMA_K, 19 }, - { FEAT_SANDWALL_K, 19 }, - - /* water, lava, & trees oh my! -KMW- */ - { FEAT_DEEP_WATER, 20 }, - { FEAT_SHAL_WATER, 20 }, - { FEAT_DEEP_LAVA, 20 }, - { FEAT_SHAL_LAVA, 20 }, - { FEAT_DIRT, 20 }, - { FEAT_GRASS, 20 }, - { FEAT_DARK_PIT, 20 }, - { FEAT_TREES, 20 }, - { FEAT_MOUNTAIN, 20 }, - { FEAT_ICE, 20}, - { FEAT_SAND, 20}, - { FEAT_DEAD_TREE, 20}, - { FEAT_ASH, 20}, - { FEAT_MUD, 20}, - - /* Fountain */ - { FEAT_FOUNTAIN, 22 }, - { FEAT_EMPTY_FOUNTAIN, 22 }, - - /* Stairs */ - { FEAT_LESS, 25 }, - { FEAT_MORE, 25 }, - - /* Stairs */ - { FEAT_WAY_LESS, 25 }, - { FEAT_WAY_MORE, 25 }, - - { FEAT_SHAFT_UP, 25 }, - { FEAT_SHAFT_DOWN, 25 }, - - /* End */ - { 0, 0 } -}; - - -/* - * Hack -- a priority function (see below) - */ -static byte priority(byte a, char c) -{ - int i, p0, p1; - - feature_type *f_ptr; - - /* Scan the table */ - for (i = 0; TRUE; i++) - { - /* Priority level */ - p1 = priority_table[i][1]; - - /* End of table */ - if (!p1) break; - - /* Feature index */ - p0 = priority_table[i][0]; - - /* Access the feature */ - f_ptr = &f_info[p0]; - - /* Check character and attribute, accept matches */ - if ((f_ptr->x_char == c) && (f_ptr->x_attr == a)) return (p1); - } - - /* Default */ - return (20); -} - - -/* - * Display a "small-scale" map of the dungeon in the active Term - * - * Note that the "map_info()" function must return fully colorized - * data or this function will not work correctly. - * - * Note that this function must "disable" the special lighting - * effects so that the "priority" function will work. - * - * Note the use of a specialized "priority" function to allow this - * function to work with any graphic attr/char mappings, and the - * attempts to optimize this function where possible. - */ -void display_map(int *cy, int *cx) -{ - int i, j, x, y; - - byte ta; - char tc; - - byte tp; - - byte **ma; - char **mc; - - byte **mp; - - bool_ old_view_special_lite; - bool_ old_view_granite_lite; - - int hgt, wid, yrat, xrat, yfactor, xfactor; - - - /* Obtain current size of the Angband window */ - Term_get_size(&wid, &hgt); - - /* Use two characters as one tile in Bigtile mode */ - if (use_bigtile) wid /= 2; - - /* - * Calculate the size of the dungeon map area - */ - hgt -= ROW_MAP + 2; - wid -= COL_MAP + 1; - - /* Paranoia */ - if ((hgt < 3) || (wid < 3)) - { - /* Map is too small, but place the player anyway */ - *cy = ROW_MAP; - *cx = COL_MAP; - - return; - } - - - /* Save lighting effects */ - old_view_special_lite = view_special_lite; - old_view_granite_lite = view_granite_lite; - - /* Disable lighting effects */ - view_special_lite = FALSE; - view_granite_lite = FALSE; - - - /* Allocate temporary memory for the maps */ - C_MAKE(ma, hgt + 2, byte *); - C_MAKE(mc, hgt + 2, char *); - C_MAKE(mp, hgt + 2, byte *); - - /* Allocate each line in the maps */ - for (i = 0; i < hgt + 2; i++) - { - C_MAKE(ma[i], wid + 2, byte); - C_MAKE(mc[i], wid + 2, char); - C_MAKE(mp[i], wid + 2, byte); - } - - /* Clear the chars and attributes */ - for (y = 0; y < hgt + 2; ++y) - { - for (x = 0; x < wid + 2; ++x) - { - /* Nothing here */ - ma[y][x] = TERM_WHITE; - mc[y][x] = ' '; - - /* No priority */ - mp[y][x] = 0; - } - } - - /* Calculate scaling factors */ - yfactor = ((cur_hgt / hgt < 4) && (cur_hgt > hgt)) ? 10 : 1; - xfactor = ((cur_wid / wid < 4) && (cur_wid > wid)) ? 10 : 1; - - yrat = (cur_hgt * yfactor + (hgt - 1)) / hgt; - xrat = (cur_wid * xfactor + (wid - 1)) / wid; - - /* Fill in the map */ - for (j = 0; j < cur_hgt; ++j) - { - for (i = 0; i < cur_wid; ++i) - { - /* Location */ - y = j * yfactor / yrat + 1; - x = i * xfactor / xrat + 1; - - /* Extract the current attr/char at that map location */ - map_info(j, i, &ta, &tc, &ta, &tc, &ta, &tc); - - /* Extract the priority of that attr/char */ - tp = priority(ta, tc); - - /* Player location has the highest priority */ - if ((p_ptr->py == j) && (p_ptr->px == i)) tp = 255; - - /* Save "best" */ - if (mp[y][x] < tp) - { - /* Save the char */ - mc[y][x] = tc; - - /* Save the attr */ - ma[y][x] = ta; - - /* Save priority */ - mp[y][x] = tp; - } - } - } - - - /* Corners */ - y = hgt + 1; - x = wid + 1; - - /* Draw the corners */ - mc[0][0] = mc[0][x] = mc[y][0] = mc[y][x] = '+'; - - /* Draw the horizontal edges */ - for (x = 1; x <= wid; x++) mc[0][x] = mc[y][x] = '-'; - - /* Draw the vertical edges */ - for (y = 1; y <= hgt; y++) mc[y][0] = mc[y][x] = '|'; - - - /* Display each map line in order */ - for (y = 0; y < hgt + 2; ++y) - { - /* Start a new line */ - Term_gotoxy(COL_MAP - 1, y); - - /* Display the line */ - for (x = 0; x < wid + 2; ++x) - { - ta = ma[y][x]; - tc = mc[y][x]; - - /* Add the character */ - Term_addch(ta, tc); - - /* Double width tile mode requires filler */ - if (use_bigtile) - { - byte a2; - char c2; - - if (ta & 0x80) - { - /* Mega-Hack */ - a2 = 255; - c2 = 255; - } - else - { - a2 = TERM_WHITE; - c2 = ' '; - } - - Term_addch(a2, c2); - } - } - } - - /* Player location in dungeon */ - *cy = p_ptr->py * yfactor / yrat + ROW_MAP; - if (!use_bigtile) - { - *cx = p_ptr->px * xfactor / xrat + COL_MAP; - } - else - { - *cx = (p_ptr->px * xfactor / xrat + 1) * 2 - 1 + COL_MAP; - } - - /* Free each line in the maps */ - for (i = 0; i < hgt + 2; i++) - { - C_FREE(ma[i], wid + 2, byte); - C_FREE(mc[i], wid + 2, char); - C_FREE(mp[i], wid + 2, byte); - } - - /* Allocate temporary memory for the maps */ - C_FREE(ma, hgt + 2, byte *); - C_FREE(mc, hgt + 2, char *); - C_FREE(mp, hgt + 2, byte *); - - - /* Restore lighting effects */ - view_special_lite = old_view_special_lite; - view_granite_lite = old_view_granite_lite; -} - - -/* - * Display a "small-scale" map of the dungeon for the player - * - * Currently, the "player" is displayed on the map. XXX XXX XXX - */ -void do_cmd_view_map(void) -{ - int cy, cx; - int wid, hgt; - - /* Retrive current screen size */ - Term_get_size(&wid, &hgt); - - /* Enter "icky" mode */ - character_icky = TRUE; - - /* Save the screen */ - Term_save(); - - /* Note */ - prt("Please wait...", 0, 0); - - /* Flush */ - Term_fresh(); - - /* Clear the screen */ - Term_clear(); - - /* Display the map */ - display_map(&cy, &cx); - - /* Wait for it */ - put_str("Hit any key to continue", hgt - 1, (wid - COL_MAP) / 2); - - /* Hilite the player */ - move_cursor(cy, cx); - - /* Get any key */ - inkey(); - - /* Restore the screen */ - Term_load(); - - /* Leave "icky" mode */ - character_icky = FALSE; -} - - - - - - -/* - * Some comments on the dungeon related data structures and functions... - * - * Angband is primarily a dungeon exploration game, and it should come as - * no surprise that the internal representation of the dungeon has evolved - * over time in much the same way as the game itself, to provide semantic - * changes to the game itself, to make the code simpler to understand, and - * to make the executable itself faster or more efficient in various ways. - * - * There are a variety of dungeon related data structures, and associated - * functions, which store information about the dungeon, and provide methods - * by which this information can be accessed or modified. - * - * Some of this information applies to the dungeon as a whole, such as the - * list of unique monsters which are still alive. Some of this information - * only applies to the current dungeon level, such as the current depth, or - * the list of monsters currently inhabiting the level. And some of the - * information only applies to a single grid of the current dungeon level, - * such as whether the grid is illuminated, or whether the grid contains a - * monster, or whether the grid can be seen by the player. If Angband was - * to be turned into a multi-player game, some of the information currently - * associated with the dungeon should really be associated with the player, - * such as whether a given grid is viewable by a given player. - * - * One of the major bottlenecks in ancient versions of Angband was in the - * calculation of "line of sight" from the player to various grids, such - * as those containing monsters, using the relatively expensive "los()" - * function. This was such a nasty bottleneck that a lot of silly things - * were done to reduce the dependancy on "line of sight", for example, you - * could not "see" any grids in a lit room until you actually entered the - * room, at which point every grid in the room became "illuminated" and - * all of the grids in the room were "memorized" forever. Other major - * bottlenecks involved the determination of whether a grid was lit by the - * player's torch, and whether a grid blocked the player's line of sight. - * These bottlenecks led to the development of special new functions to - * optimize issues involved with "line of sight" and "torch lit grids". - * These optimizations led to entirely new additions to the game, such as - * the ability to display the player's entire field of view using different - * colors than were used for the "memorized" portions of the dungeon, and - * the ability to memorize dark floor grids, but to indicate by the way in - * which they are displayed that they are not actually illuminated. And - * of course many of them simply made the game itself faster or more fun. - * Also, over time, the definition of "line of sight" has been relaxed to - * allow the player to see a wider "field of view", which is slightly more - * realistic, and only slightly more expensive to maintain. - * - * Currently, a lot of the information about the dungeon is stored in ways - * that make it very efficient to access or modify the information, while - * still attempting to be relatively conservative about memory usage, even - * if this means that some information is stored in multiple places, or in - * ways which require the use of special code idioms. For example, each - * monster record in the monster array contains the location of the monster, - * and each cave grid has an index into the monster array, or a zero if no - * monster is in the grid. This allows the monster code to efficiently see - * where the monster is located, while allowing the dungeon code to quickly - * determine not only if a monster is present in a given grid, but also to - * find out which monster. The extra space used to store the information - * twice is inconsequential compared to the speed increase. - * - * Some of the information about the dungeon is used by functions which can - * constitute the "critical efficiency path" of the game itself, and so the - * way in which they are stored and accessed has been optimized in order to - * optimize the game itself. For example, the "update_view()" function was - * originally created to speed up the game itself (when the player was not - * running), but then it took on extra responsibility as the provider of the - * new "special effects lighting code", and became one of the most important - * bottlenecks when the player was running. So many rounds of optimization - * were performed on both the function itself, and the data structures which - * it uses, resulting eventually in a function which not only made the game - * faster than before, but which was responsible for even more calculations - * (including the determination of which grids are "viewable" by the player, - * which grids are illuminated by the player's torch, and which grids can be - * "seen" in some way by the player), as well as for providing the guts of - * the special effects lighting code, and for the efficient redisplay of any - * grids whose visual representation may have changed. - * - * Several pieces of information about each cave grid are stored in various - * two dimensional arrays, with one unit of information for each grid in the - * dungeon. Some of these arrays have been intentionally expanded by a small - * factor to make the two dimensional array accesses faster by allowing the - * use of shifting instead of multiplication. - * - * Several pieces of information about each cave grid are stored in the - * "cave_info" array, which is a special two dimensional array of bytes, - * one for each cave grid, each containing eight separate "flags" which - * describe some property of the cave grid. These flags can be checked and - * modified extremely quickly, especially when special idioms are used to - * force the compiler to keep a local register pointing to the base of the - * array. Special location offset macros can be used to minimize the number - * of computations which must be performed at runtime. Note that using a - * byte for each flag set may be slightly more efficient than using a larger - * unit, so if another flag (or two) is needed later, and it must be fast, - * then the two existing flags which do not have to be fast should be moved - * out into some other data structure and the new flags should take their - * place. This may require a few minor changes in the savefile code. - * - * The "CAVE_ROOM" flag is saved in the savefile and is used to determine - * which grids are part of "rooms", and thus which grids are affected by - * "illumination" spells. This flag does not have to be very fast. - * - * The "CAVE_ICKY" flag is saved in the savefile and is used to determine - * which grids are part of "vaults", and thus which grids cannot serve as - * the destinations of player teleportation. This flag does not have to - * be very fast. - * - * The "CAVE_MARK" flag is saved in the savefile and is used to determine - * which grids have been "memorized" by the player. This flag is used by - * the "map_info()" function to determine if a grid should be displayed. - * This flag is used in a few other places to determine if the player can - * "know" about a given grid. This flag must be very fast. - * - * The "CAVE_GLOW" flag is saved in the savefile and is used to determine - * which grids are "permanently illuminated". This flag is used by the - * "update_view()" function to help determine which viewable flags may - * be "seen" by the player. This flag is used by the "map_info" function - * to determine if a grid is only lit by the player's torch. This flag - * has special semantics for wall grids (see "update_view()"). This flag - * must be very fast. - * - * The "CAVE_WALL" flag is used to determine which grids block the player's - * line of sight. This flag is used by the "update_view()" function to - * determine which grids block line of sight, and to help determine which - * grids can be "seen" by the player. This flag must be very fast. - * - * The "CAVE_VIEW" flag is used to determine which grids are currently in - * line of sight of the player. This flag is set by (and used by) the - * "update_view()" function. This flag is used by any code which needs to - * know if the player can "view" a given grid. This flag is used by the - * "map_info()" function for some optional special lighting effects. The - * "player_has_los_bold()" macro wraps an abstraction around this flag, but - * certain code idioms are much more efficient. This flag is used to check - * if a modification to a terrain feature might affect the player's field of - * view. This flag is used to see if certain monsters are "visible" to the - * player. This flag is used to allow any monster in the player's field of - * view to "sense" the presence of the player. This flag must be very fast. - * - * The "CAVE_SEEN" flag is used to determine which grids are currently in - * line of sight of the player and also illuminated in some way. This flag - * is set by the "update_view()" function, using computations based on the - * "CAVE_VIEW" and "CAVE_WALL" and "CAVE_GLOW" flags of various grids. This - * flag is used by any code which needs to know if the player can "see" a - * given grid. This flag is used by the "map_info()" function both to see - * if a given "boring" grid can be seen by the player, and for some optional - * special lighting effects. The "player_can_see_bold()" macro wraps an - * abstraction around this flag, but certain code idioms are much more - * efficient. This flag is used to see if certain monsters are "visible" to - * the player. This flag is never set for a grid unless "CAVE_VIEW" is also - * set for the grid. Whenever the "CAVE_WALL" or "CAVE_GLOW" flag changes - * for a grid which has the "CAVE_VIEW" flag set, the "CAVE_SEEN" flag must - * be recalculated. The simplest way to do this is to call "forget_view()" - * and "update_view()" whenever the "CAVE_WALL" or "CAVE_GLOW" flags change - * for a grid which has "CAVE_VIEW" set. This flag must be very fast. - * - * The "CAVE_TEMP" flag is used for a variety of temporary purposes. This - * flag is used to determine if the "CAVE_SEEN" flag for a grid has changed - * during the "update_view()" function. This flag is used to "spread" light - * or darkness through a room. This flag is used by the "monster flow code". - * This flag must always be cleared by any code which sets it, often, this - * can be optimized by the use of the special "temp_g", "temp_y", "temp_x" - * arrays (and the special "temp_n" global). This flag must be very fast. - * - * Note that the "CAVE_MARK" flag is used for many reasons, some of which - * are strictly for optimization purposes. The "CAVE_MARK" flag means that - * even if the player cannot "see" the grid, he "knows" about the terrain in - * that grid. This is used to "memorize" grids when they are first "seen" by - * the player, and to allow certain grids to be "detected" by certain magic. - * Note that most grids are always memorized when they are first "seen", but - * "boring" grids (floor grids) are only memorized if the "view_torch_grids" - * option is set, or if the "view_perma_grids" option is set, and the grid - * in question has the "CAVE_GLOW" flag set. - * - * Objects are "memorized" in a different way, using a special "marked" flag - * on the object itself, which is set when an object is observed or detected. - * This allows objects to be "memorized" independant of the terrain features. - * - * The "update_view()" function is an extremely important function. It is - * called only when the player moves, significant terrain changes, or the - * player's blindness or torch radius changes. Note that when the player - * is resting, or performing any repeated actions (like digging, disarming, - * farming, etc), there is no need to call the "update_view()" function, so - * even if it was not very efficient, this would really only matter when the - * player was "running" through the dungeon. It sets the "CAVE_VIEW" flag - * on every cave grid in the player's field of view, and maintains an array - * of all such grids in the global "view_g" array. It also checks the torch - * radius of the player, and sets the "CAVE_SEEN" flag for every grid which - * is in the "field of view" of the player and which is also "illuminated", - * either by the players torch (if any) or by any permanent light source. - * It could use and help maintain information about multiple light sources, - * which would be helpful in a multi-player version of Angband. - * - * The "update_view()" function maintains the special "view_g" array, which - * contains exactly those grids which have the "CAVE_VIEW" flag set. This - * array is used by "update_view()" to (only) memorize grids which become - * newly "seen", and to (only) redraw grids whose "seen" value changes, which - * allows the use of some interesting (and very efficient) "special lighting - * effects". In addition, this array could be used elsewhere to quickly scan - * through all the grids which are in the player's field of view. - * - * Note that the "update_view()" function allows, among other things, a room - * to be "partially" seen as the player approaches it, with a growing cone - * of floor appearing as the player gets closer to the door. Also, by not - * turning on the "memorize perma-lit grids" option, the player will only - * "see" those floor grids which are actually in line of sight. And best - * of all, you can now activate the special lighting effects to indicate - * which grids are actually in the player's field of view by using dimmer - * colors for grids which are not in the player's field of view, and/or to - * indicate which grids are illuminated only by the player's torch by using - * the color yellow for those grids. - * - * The old "update_view()" algorithm uses the special "CAVE_EASY" flag as a - * temporary internal flag to mark those grids which are not only in view, - * but which are also "easily" in line of sight of the player. This flag - * is actually just the "CAVE_SEEN" flag, and the "update_view()" function - * makes sure to clear it for all old "CAVE_SEEN" grids, and then use it in - * the algorithm as "CAVE_EASY", and then clear it for all "CAVE_EASY" grids, - * and then reset it as appropriate for all new "CAVE_SEEN" grids. This is - * kind of messy, but it works. The old algorithm may disappear eventually. - * - * The new "update_view()" algorithm uses a faster and more mathematically - * correct algorithm, assisted by a large machine generated static array, to - * determine the "CAVE_VIEW" and "CAVE_SEEN" flags simultaneously. See below. - * - * It seems as though slight modifications to the "update_view()" functions - * would allow us to determine "reverse" line-of-sight as well as "normal" - * line-of-sight", which would allow monsters to have a more "correct" way - * to determine if they can "see" the player, since right now, they "cheat" - * somewhat and assume that if the player has "line of sight" to them, then - * they can "pretend" that they have "line of sight" to the player. But if - * such a change was attempted, the monsters would actually start to exhibit - * some undesirable behavior, such as "freezing" near the entrances to long - * hallways containing the player, and code would have to be added to make - * the monsters move around even if the player was not detectable, and to - * "remember" where the player was last seen, to avoid looking stupid. - * - * Note that the "CAVE_GLOW" flag means that a grid is permanently lit in - * some way. However, for the player to "see" the grid, as determined by - * the "CAVE_SEEN" flag, the player must not be blind, the grid must have - * the "CAVE_VIEW" flag set, and if the grid is a "wall" grid, and it is - * not lit by the player's torch, then it must touch a grid which does not - * have the "CAVE_WALL" flag set, but which does have both the "CAVE_GLOW" - * and "CAVE_VIEW" flags set. This last part about wall grids is induced - * by the semantics of "CAVE_GLOW" as applied to wall grids, and checking - * the technical requirements can be very expensive, especially since the - * grid may be touching some "illegal" grids. Luckily, it is more or less - * correct to restrict the "touching" grids from the eight "possible" grids - * to the (at most) three grids which are touching the grid, and which are - * closer to the player than the grid itself, which eliminates more than - * half of the work, including all of the potentially "illegal" grids, if - * at most one of the three grids is a "diagonal" grid. In addition, in - * almost every situation, it is possible to ignore the "CAVE_VIEW" flag - * on these three "touching" grids, for a variety of technical reasons. - * Finally, note that in most situations, it is only necessary to check - * a single "touching" grid, in fact, the grid which is strictly closest - * to the player of all the touching grids, and in fact, it is normally - * only necessary to check the "CAVE_GLOW" flag of that grid, again, for - * various technical reasons. However, one of the situations which does - * not work with this last reduction is the very common one in which the - * player approaches an illuminated room from a dark hallway, in which the - * two wall grids which form the "entrance" to the room would not be marked - * as "CAVE_SEEN", since of the three "touching" grids nearer to the player - * than each wall grid, only the farthest of these grids is itself marked - * "CAVE_GLOW". - * - * - * Here are some pictures of the legal "light source" radius values, in - * which the numbers indicate the "order" in which the grids could have - * been calculated, if desired. Note that the code will work with larger - * radiuses, though currently yields such a radius, and the game would - * become slower in some situations if it did. - * - * Rad=0 Rad=1 Rad=2 Rad=3 - * No-Lite Torch,etc Lantern Artifacts - * - * 333 - * 333 43334 - * 212 32123 3321233 - * @ 1@1 31@13 331@133 - * 212 32123 3321233 - * 333 43334 - * 333 - * - * - * Here is an illustration of the two different "update_view()" algorithms, - * in which the grids marked "%" are pillars, and the grids marked "?" are - * not in line of sight of the player. - * - * - * Sample situation - * - * ##################### - * ############.%.%.%.%# - * #...@..#####........# - * #............%.%.%.%# - * #......#####........# - * ############........# - * ##################### - * - * - * New Algorithm Old Algorithm - * - * ########????????????? ########????????????? - * #...@..#????????????? #...@..#????????????? - * #...........????????? #.........??????????? - * #......#####.....???? #......####?????????? - * ########?????????...# ########????????????? - * - * ########????????????? ########????????????? - * #.@....#????????????? #.@....#????????????? - * #............%??????? #...........????????? - * #......#####........? #......#####????????? - * ########??????????..# ########????????????? - * - * ########????????????? ########?????%??????? - * #......#####........# #......#####..??????? - * #.@..........%??????? #.@..........%??????? - * #......#####........# #......#####..??????? - * ########????????????? ########????????????? - * - * ########??????????..# ########????????????? - * #......#####........? #......#####????????? - * #............%??????? #...........????????? - * #.@....#????????????? #.@....#????????????? - * ########????????????? ########????????????? - * - * ########?????????%??? ########????????????? - * #......#####.....???? #......####?????????? - * #...........????????? #.........??????????? - * #...@..#????????????? #...@..#????????????? - * ########????????????? ########????????????? - */ - - - - -/* - * Maximum number of grids in a single octant - */ -#define VINFO_MAX_GRIDS 161 - - -/* - * Maximum number of slopes in a single octant - */ -#define VINFO_MAX_SLOPES 126 - - -/* - * Mask of bits used in a single octant - */ -#define VINFO_BITS_3 0x3FFFFFFF -#define VINFO_BITS_2 0xFFFFFFFF -#define VINFO_BITS_1 0xFFFFFFFF -#define VINFO_BITS_0 0xFFFFFFFF - - -/* - * Forward declare - */ -typedef struct vinfo_type vinfo_type; - - -/* - * The 'vinfo_type' structure - */ -struct vinfo_type -{ - s16b grid_y[8]; - s16b grid_x[8]; - - u32b bits_3; - u32b bits_2; - u32b bits_1; - u32b bits_0; - - vinfo_type *next_0; - vinfo_type *next_1; - - byte y; - byte x; - byte d; - byte r; -}; - - - -/* - * The array of "vinfo" objects, initialized by "vinfo_init()" - */ -static vinfo_type vinfo[VINFO_MAX_GRIDS]; - - - - -/* - * Slope scale factor - */ -#define SCALE 100000L - - -/* - * The actual slopes (for reference) - */ - -/* Bit : Slope Grids */ -/* --- : ----- ----- */ -/* 0 : 2439 21 */ -/* 1 : 2564 21 */ -/* 2 : 2702 21 */ -/* 3 : 2857 21 */ -/* 4 : 3030 21 */ -/* 5 : 3225 21 */ -/* 6 : 3448 21 */ -/* 7 : 3703 21 */ -/* 8 : 4000 21 */ -/* 9 : 4347 21 */ -/* 10 : 4761 21 */ -/* 11 : 5263 21 */ -/* 12 : 5882 21 */ -/* 13 : 6666 21 */ -/* 14 : 7317 22 */ -/* 15 : 7692 20 */ -/* 16 : 8108 21 */ -/* 17 : 8571 21 */ -/* 18 : 9090 20 */ -/* 19 : 9677 21 */ -/* 20 : 10344 21 */ -/* 21 : 11111 20 */ -/* 22 : 12000 21 */ -/* 23 : 12820 22 */ -/* 24 : 13043 22 */ -/* 25 : 13513 22 */ -/* 26 : 14285 20 */ -/* 27 : 15151 22 */ -/* 28 : 15789 22 */ -/* 29 : 16129 22 */ -/* 30 : 17241 22 */ -/* 31 : 17647 22 */ -/* 32 : 17948 23 */ -/* 33 : 18518 22 */ -/* 34 : 18918 22 */ -/* 35 : 20000 19 */ -/* 36 : 21212 22 */ -/* 37 : 21739 22 */ -/* 38 : 22580 22 */ -/* 39 : 23076 22 */ -/* 40 : 23809 22 */ -/* 41 : 24137 22 */ -/* 42 : 24324 23 */ -/* 43 : 25714 23 */ -/* 44 : 25925 23 */ -/* 45 : 26315 23 */ -/* 46 : 27272 22 */ -/* 47 : 28000 23 */ -/* 48 : 29032 23 */ -/* 49 : 29411 23 */ -/* 50 : 29729 24 */ -/* 51 : 30434 23 */ -/* 52 : 31034 23 */ -/* 53 : 31428 23 */ -/* 54 : 33333 18 */ -/* 55 : 35483 23 */ -/* 56 : 36000 23 */ -/* 57 : 36842 23 */ -/* 58 : 37142 24 */ -/* 59 : 37931 24 */ -/* 60 : 38461 24 */ -/* 61 : 39130 24 */ -/* 62 : 39393 24 */ -/* 63 : 40740 24 */ -/* 64 : 41176 24 */ -/* 65 : 41935 24 */ -/* 66 : 42857 23 */ -/* 67 : 44000 24 */ -/* 68 : 44827 24 */ -/* 69 : 45454 23 */ -/* 70 : 46666 24 */ -/* 71 : 47368 24 */ -/* 72 : 47826 24 */ -/* 73 : 48148 24 */ -/* 74 : 48387 24 */ -/* 75 : 51515 25 */ -/* 76 : 51724 25 */ -/* 77 : 52000 25 */ -/* 78 : 52380 25 */ -/* 79 : 52941 25 */ -/* 80 : 53846 25 */ -/* 81 : 54838 25 */ -/* 82 : 55555 24 */ -/* 83 : 56521 25 */ -/* 84 : 57575 26 */ -/* 85 : 57894 25 */ -/* 86 : 58620 25 */ -/* 87 : 60000 23 */ -/* 88 : 61290 25 */ -/* 89 : 61904 25 */ -/* 90 : 62962 25 */ -/* 91 : 63636 25 */ -/* 92 : 64705 25 */ -/* 93 : 65217 25 */ -/* 94 : 65517 25 */ -/* 95 : 67741 26 */ -/* 96 : 68000 26 */ -/* 97 : 68421 26 */ -/* 98 : 69230 26 */ -/* 99 : 70370 26 */ -/* 100 : 71428 25 */ -/* 101 : 72413 26 */ -/* 102 : 73333 26 */ -/* 103 : 73913 26 */ -/* 104 : 74193 27 */ -/* 105 : 76000 26 */ -/* 106 : 76470 26 */ -/* 107 : 77777 25 */ -/* 108 : 78947 26 */ -/* 109 : 79310 26 */ -/* 110 : 80952 26 */ -/* 111 : 81818 26 */ -/* 112 : 82608 26 */ -/* 113 : 84000 26 */ -/* 114 : 84615 26 */ -/* 115 : 85185 26 */ -/* 116 : 86206 27 */ -/* 117 : 86666 27 */ -/* 118 : 88235 27 */ -/* 119 : 89473 27 */ -/* 120 : 90476 27 */ -/* 121 : 91304 27 */ -/* 122 : 92000 27 */ -/* 123 : 92592 27 */ -/* 124 : 93103 28 */ -/* 125 : 100000 13 */ - - - -/* - * Forward declare - */ -typedef struct vinfo_hack vinfo_hack; - - -/* - * Temporary data used by "vinfo_init()" - * - * - Number of grids - * - * - Number of slopes - * - * - Slope values - * - * - Slope range per grid - */ -struct vinfo_hack -{ - - int num_slopes; - - long slopes[VINFO_MAX_SLOPES]; - - long slopes_min[MAX_SIGHT + 1][MAX_SIGHT + 1]; - long slopes_max[MAX_SIGHT + 1][MAX_SIGHT + 1]; -}; - - - -/* - * Sorting hook -- comp function -- array of long's (see below) - * - * We use "u" to point to an array of long integers. - */ -static bool_ ang_sort_comp_hook_longs(vptr u, vptr v, int a, int b) -{ - long *x = (long*)(u); - - return (x[a] <= x[b]); -} - - -/* - * Sorting hook -- comp function -- array of long's (see below) - * - * We use "u" to point to an array of long integers. - */ -static void ang_sort_swap_hook_longs(vptr u, vptr v, int a, int b) -{ - long *x = (long*)(u); - - long temp; - - /* Swap */ - temp = x[a]; - x[a] = x[b]; - x[b] = temp; -} - - - -/* - * Save a slope - */ -static void vinfo_init_aux(vinfo_hack *hack, int y, int x, long m) -{ - int i; - - /* Handle "legal" slopes */ - if ((m > 0) && (m <= SCALE)) - { - /* Look for that slope */ - for (i = 0; i < hack->num_slopes; i++) - { - if (hack->slopes[i] == m) break; - } - - /* New slope */ - if (i == hack->num_slopes) - { - /* Paranoia */ - if (hack->num_slopes >= VINFO_MAX_SLOPES) - { - quit_fmt("Too many slopes (%d)!", - VINFO_MAX_SLOPES); - } - - /* Save the slope, and advance */ - hack->slopes[hack->num_slopes++] = m; - } - } - - /* Track slope range */ - if (hack->slopes_min[y][x] > m) hack->slopes_min[y][x] = m; - if (hack->slopes_max[y][x] < m) hack->slopes_max[y][x] = m; -} - - - -/* - * Initialize the "vinfo" array - * - * Full Octagon (radius 20), Grids=1149 - * - * Quadrant (south east), Grids=308, Slopes=251 - * - * Octant (east then south), Grids=161, Slopes=126 - * - * This function assumes that VINFO_MAX_GRIDS and VINFO_MAX_SLOPES - * have the correct values, which can be derived by setting them to - * a number which is too high, running this function, and using the - * error messages to obtain the correct values. - */ -errr vinfo_init(void) -{ - int i, y, x; - - long m; - - vinfo_hack *hack; - - int num_grids = 0; - - int queue_head = 0; - int queue_tail = 0; - vinfo_type *queue[VINFO_MAX_GRIDS*2]; - - - /* Make hack */ - MAKE(hack, vinfo_hack); - - - /* Analyze grids */ - for (y = 0; y <= MAX_SIGHT; ++y) - { - for (x = y; x <= MAX_SIGHT; ++x) - { - /* Skip grids which are out of sight range */ - if (distance(0, 0, y, x) > MAX_SIGHT) continue; - - /* Default slope range */ - hack->slopes_min[y][x] = 999999999; - hack->slopes_max[y][x] = 0; - - /* Paranoia */ - if (num_grids >= VINFO_MAX_GRIDS) - { - quit_fmt("Too many grids (%d >= %d)!", - num_grids, VINFO_MAX_GRIDS); - } - - /* Count grids */ - num_grids++; - - /* Slope to the top right corner */ - m = SCALE * (1000L * y - 500) / (1000L * x + 500); - - /* Handle "legal" slopes */ - vinfo_init_aux(hack, y, x, m); - - /* Slope to top left corner */ - m = SCALE * (1000L * y - 500) / (1000L * x - 500); - - /* Handle "legal" slopes */ - vinfo_init_aux(hack, y, x, m); - - /* Slope to bottom right corner */ - m = SCALE * (1000L * y + 500) / (1000L * x + 500); - - /* Handle "legal" slopes */ - vinfo_init_aux(hack, y, x, m); - - /* Slope to bottom left corner */ - m = SCALE * (1000L * y + 500) / (1000L * x - 500); - - /* Handle "legal" slopes */ - vinfo_init_aux(hack, y, x, m); - } - } - - - /* Enforce maximal efficiency */ - if (num_grids < VINFO_MAX_GRIDS) - { - quit_fmt("Too few grids (%d < %d)!", - num_grids, VINFO_MAX_GRIDS); - } - - /* Enforce maximal efficiency */ - if (hack->num_slopes < VINFO_MAX_SLOPES) - { - quit_fmt("Too few slopes (%d < %d)!", - hack->num_slopes, VINFO_MAX_SLOPES); - } - - - /* Sort slopes numerically */ - ang_sort_comp = ang_sort_comp_hook_longs; - - /* Sort slopes numerically */ - ang_sort_swap = ang_sort_swap_hook_longs; - - /* Sort the (unique) slopes */ - ang_sort(hack->slopes, NULL, hack->num_slopes); - - - - /* Enqueue player grid */ - queue[queue_tail++] = &vinfo[0]; - - /* Process queue */ - while (queue_head < queue_tail) - { - int e; - - /* Index */ - e = queue_head; - - /* Dequeue next grid */ - queue_head++; - - /* Location of main grid */ - y = vinfo[e].grid_y[0]; - x = vinfo[e].grid_x[0]; - - - /* Compute grid offsets */ - vinfo[e].grid_y[0] = + y; - vinfo[e].grid_x[0] = + x; - vinfo[e].grid_y[1] = + x; - vinfo[e].grid_x[1] = + y; - vinfo[e].grid_y[2] = + x; - vinfo[e].grid_x[2] = -y; - vinfo[e].grid_y[3] = + y; - vinfo[e].grid_x[3] = -x; - vinfo[e].grid_y[4] = -y; - vinfo[e].grid_x[4] = -x; - vinfo[e].grid_y[5] = -x; - vinfo[e].grid_x[5] = -y; - vinfo[e].grid_y[6] = -x; - vinfo[e].grid_x[6] = + y; - vinfo[e].grid_y[7] = -y; - vinfo[e].grid_x[7] = + x; - - - /* Analyze slopes */ - for (i = 0; i < hack->num_slopes; ++i) - { - m = hack->slopes[i]; - - /* Memorize intersection slopes (for non-player-grids) */ - if ((e > 0) && - (hack->slopes_min[y][x] < m) && - (m < hack->slopes_max[y][x])) - { - switch (i / 32) - { - case 3: - vinfo[e].bits_3 |= (1L << (i % 32)); - break; - case 2: - vinfo[e].bits_2 |= (1L << (i % 32)); - break; - case 1: - vinfo[e].bits_1 |= (1L << (i % 32)); - break; - case 0: - vinfo[e].bits_0 |= (1L << (i % 32)); - break; - } - } - } - - - /* Default */ - vinfo[e].next_0 = &vinfo[0]; - - /* Grid next child */ - if (distance(0, 0, y, x + 1) <= MAX_SIGHT) - { - if ((queue[queue_tail - 1]->grid_y[0] != y) || - (queue[queue_tail - 1]->grid_x[0] != x + 1)) - { - vinfo[queue_tail].grid_y[0] = y; - vinfo[queue_tail].grid_x[0] = x + 1; - queue[queue_tail] = &vinfo[queue_tail]; - queue_tail++; - } - - vinfo[e].next_0 = &vinfo[queue_tail - 1]; - } - - - /* Default */ - vinfo[e].next_1 = &vinfo[0]; - - /* Grid diag child */ - if (distance(0, 0, y + 1, x + 1) <= MAX_SIGHT) - { - if ((queue[queue_tail - 1]->grid_y[0] != y + 1) || - (queue[queue_tail - 1]->grid_x[0] != x + 1)) - { - vinfo[queue_tail].grid_y[0] = y + 1; - vinfo[queue_tail].grid_x[0] = x + 1; - queue[queue_tail] = &vinfo[queue_tail]; - queue_tail++; - } - - vinfo[e].next_1 = &vinfo[queue_tail - 1]; - } - - - /* Hack -- main diagonal has special children */ - if (y == x) vinfo[e].next_0 = vinfo[e].next_1; - - - /* Extra values */ - vinfo[e].y = y; - vinfo[e].x = x; - vinfo[e].d = ((y > x) ? (y + x / 2) : (x + y / 2)); - vinfo[e].r = ((!y) ? x : (!x) ? y : (y == x) ? y : 0); - } - - - /* Verify maximal bits XXX XXX XXX */ - if (((vinfo[1].bits_3 | vinfo[2].bits_3) != VINFO_BITS_3) || - ((vinfo[1].bits_2 | vinfo[2].bits_2) != VINFO_BITS_2) || - ((vinfo[1].bits_1 | vinfo[2].bits_1) != VINFO_BITS_1) || - ((vinfo[1].bits_0 | vinfo[2].bits_0) != VINFO_BITS_0)) - { - quit("Incorrect bit masks!"); - } - - - /* Kill hack */ - KILL(hack, vinfo_hack); - - - /* Success */ - return (0); -} - - - -/* - * Forget the "CAVE_VIEW" grids, redrawing as needed - */ -void forget_view(void) -{ - int i; - - int fast_view_n = view_n; - - cave_type *c_ptr; - - - /* None to forget */ - if (!fast_view_n) return; - - /* Clear them all */ - for (i = 0; i < fast_view_n; i++) - { - int y = view_y[i]; - int x = view_x[i]; - - /* Access the grid */ - c_ptr = &cave[y][x]; - - /* Clear "CAVE_VIEW", "CAVE_SEEN" and player torch flags */ - c_ptr->info &= ~(CAVE_VIEW | CAVE_SEEN | CAVE_PLIT); - - /* Redraw */ - lite_spot(y, x); - } - - /* None left */ - view_n = 0; -} - - - -/* - * Calculate the complete field of view using a new algorithm - * - * If "view_y/x" and "temp_y/x" were global pointers to arrays of grids, as - * opposed to actual arrays of grids, then we could be more efficient by - * using "pointer swapping". - * - * Normally, vision along the major axes is more likely than vision - * along the diagonal axes, so we check the bits corresponding to - * the lines of sight near the major axes first. - * - * We use the "temp_y/x" array (and the "CAVE_TEMP" flag) to keep track of - * which grids were previously marked "CAVE_SEEN", since only those grids - * whose "CAVE_SEEN" value changes during this routine must be redrawn. - * - * This function is now responsible for maintaining the "CAVE_SEEN" - * flags as well as the "CAVE_VIEW" flags, which is good, because - * the only grids which normally need to be memorized and/or redrawn - * are the ones whose "CAVE_SEEN" flag changes during this routine. - * - * Basically, this function divides the "octagon of view" into octants of - * grids (where grids on the main axes and diagonal axes are "shared" by - * two octants), and processes each octant one at a time, processing each - * octant one grid at a time, processing only those grids which "might" be - * viewable, and setting the "CAVE_VIEW" flag for each grid for which there - * is an (unobstructed) line of sight from the center of the player grid to - * any internal point in the grid (and collecting these "CAVE_VIEW" grids - * into the "view_y/x" array), and setting the "CAVE_SEEN" flag for the grid - * if, in addition, the grid is "illuminated" in some way. - * - * This function relies on a theorem (suggested and proven by Mat Hostetter) - * which states that in each octant of a field of view, a given grid will - * be "intersected" by one or more unobstructed "lines of sight" from the - * center of the player grid if and only if it is "intersected" by at least - * one such unobstructed "line of sight" which passes directly through some - * corner of some grid in the octant which is not shared by any other octant. - * The proof is based on the fact that there are at least three significant - * lines of sight involving any non-shared grid in any octant, one which - * intersects the grid and passes though the corner of the grid closest to - * the player, and two which "brush" the grid, passing through the "outer" - * corners of the grid, and that any line of sight which intersects a grid - * without passing through the corner of a grid in the octant can be "slid" - * slowly towards the corner of the grid closest to the player, until it - * either reaches it or until it brushes the corner of another grid which - * is closer to the player, and in either case, the existanc of a suitable - * line of sight is thus demonstrated. - * - * It turns out that in each octant of the radius 20 "octagon of view", - * there are 161 grids (with 128 not shared by any other octant), and there - * are exactly 126 distinct "lines of sight" passing from the center of the - * player grid through any corner of any non-shared grid in the octant. To - * determine if a grid is "viewable" by the player, therefore, you need to - * simply show that one of these 126 lines of sight intersects the grid but - * does not intersect any wall grid closer to the player. So we simply use - * a bit vector with 126 bits to represent the set of interesting lines of - * sight which have not yet been obstructed by wall grids, and then we scan - * all the grids in the octant, moving outwards from the player grid. For - * each grid, if any of the lines of sight which intersect that grid have not - * yet been obstructed, then the grid is viewable. Furthermore, if the grid - * is a wall grid, then all of the lines of sight which intersect the grid - * should be marked as obstructed for future reference. Also, we only need - * to check those grids for whom at least one of the "parents" was a viewable - * non-wall grid, where the parents include the two grids touching the grid - * but closer to the player grid (one adjacent, and one diagonal). For the - * bit vector, we simply use 4 32-bit integers. All of the static values - * which are needed by this function are stored in the large "vinfo" array - * (above), which is machine generated by another program. XXX XXX XXX - * - * Hack -- The queue must be able to hold more than VINFO_MAX_GRIDS grids - * because the grids at the edge of the field of view use "grid zero" as - * their children, and the queue must be able to hold several of these - * special grids. Because the actual number of required grids is bizarre, - * we simply allocate twice as many as we would normally need. XXX XXX XXX - */ -void update_view(void) -{ - int i, o; - int y, x; - - int radius; - - int fast_view_n = view_n; - - int fast_temp_n = 0; - - cave_type *c_ptr; - - u16b info; - - - /*** Step 0 -- Begin ***/ - - /* Save the old "view" grids for later */ - for (i = 0; i < fast_view_n; i++) - { - /* Location */ - y = view_y[i]; - x = view_x[i]; - - /* Grid */ - c_ptr = &cave[y][x]; - - /* Get grid info */ - info = c_ptr->info; - ; - - /* Save "CAVE_SEEN" grids */ - if (info & (CAVE_SEEN)) - { - /* Set "CAVE_TEMP" flag */ - info |= (CAVE_TEMP); - - /* Save grid for later */ - temp_y[fast_temp_n] = y; - temp_x[fast_temp_n++] = x; - } - - /* Clear "CAVE_VIEW", "CAVE_SEEN" and player torch flags */ - info &= ~(CAVE_VIEW | CAVE_SEEN | CAVE_PLIT); - - /* Save cave info */ - c_ptr->info = info; - } - - /* Reset the "view" array */ - fast_view_n = 0; - - /* Extract "radius" value */ - radius = p_ptr->cur_lite; - - /* Handle real light */ - if (radius > 0) ++radius; - - - /*** Step 1 -- player grid ***/ - - /* Player grid */ - c_ptr = &cave[p_ptr->py][p_ptr->px]; - - /* Get grid info */ - info = c_ptr->info; - - /* Assume viewable */ - info |= (CAVE_VIEW); - - /* Torch-lit grid */ - if (0 < radius) - { - /* Mark as "CAVE_SEEN" and torch-lit */ - info |= (CAVE_SEEN | CAVE_PLIT); - } - - - /* Perma-lit grid */ - else if (info & (CAVE_GLOW)) - { - /* Mark as "CAVE_SEEN" */ - info |= (CAVE_SEEN); - } - - /* Save cave info */ - c_ptr->info = info; - - /* Save in array */ - view_y[fast_view_n] = p_ptr->py; - view_x[fast_view_n++] = p_ptr->px; - - - /*** Step 2 -- octants ***/ - - /* Scan each octant */ - for (o = 0; o < 8; o++) - { - vinfo_type *p; - - /* Last added */ - vinfo_type *last = &vinfo[0]; - - /* Grid queue */ - int queue_head = 0; - int queue_tail = 0; - vinfo_type *queue[VINFO_MAX_GRIDS*2]; - - /* Slope bit vector */ - u32b bits0 = VINFO_BITS_0; - u32b bits1 = VINFO_BITS_1; - u32b bits2 = VINFO_BITS_2; - u32b bits3 = VINFO_BITS_3; - - /* Reset queue */ - queue_head = queue_tail = 0; - - /* Initial grids */ - queue[queue_tail++] = &vinfo[1]; - queue[queue_tail++] = &vinfo[2]; - - /* Process queue */ - while (queue_head < queue_tail) - { - /* Dequeue next grid */ - p = queue[queue_head++]; - - /* Check bits */ - if ((bits0 & (p->bits_0)) || - (bits1 & (p->bits_1)) || - (bits2 & (p->bits_2)) || - (bits3 & (p->bits_3))) - { - /* Extract coordinate value */ - y = p_ptr->py + p->grid_y[o]; - x = p_ptr->px + p->grid_x[o]; - - /* Access the grid */ - c_ptr = &cave[y][x]; - - /* Get grid info */ - info = c_ptr->info; - - /* Handle wall */ - if (info & (CAVE_WALL)) - { - /* Clear bits */ - bits0 &= ~(p->bits_0); - bits1 &= ~(p->bits_1); - bits2 &= ~(p->bits_2); - bits3 &= ~(p->bits_3); - - /* Newly viewable wall */ - if (!(info & (CAVE_VIEW))) - { - /* Mark as viewable */ - info |= (CAVE_VIEW); - - /* Torch-lit grids */ - if (p->d < radius) - { - /* Mark as "CAVE_SEEN" and torch-lit */ - info |= (CAVE_SEEN | CAVE_PLIT); - } - - /* Monster-lit grids */ - else if (info & (CAVE_MLIT)) - { - /* Mark as "CAVE_SEEN" */ - info |= (CAVE_SEEN); - } - - /* Perma-lit grids */ - else if (info & (CAVE_GLOW)) - { - /* Hack -- move towards player */ - int yy = (y < p_ptr->py) ? (y + 1) : (y > p_ptr->py) ? (y - 1) : y; - int xx = (x < p_ptr->px) ? (x + 1) : (x > p_ptr->px) ? (x - 1) : x; - - /* Check for "simple" illumination */ - if (cave[yy][xx].info & (CAVE_GLOW)) - { - /* Mark as seen */ - info |= (CAVE_SEEN); - } - } - - /* Save cave info */ - c_ptr->info = info; - - /* Save in array */ - view_y[fast_view_n] = y; - view_x[fast_view_n++] = x; - } - } - - /* Handle non-wall */ - else - { - /* Enqueue child */ - if (last != p->next_0) - { - queue[queue_tail++] = last = p->next_0; - } - - /* Enqueue child */ - if (last != p->next_1) - { - queue[queue_tail++] = last = p->next_1; - } - - /* Newly viewable non-wall */ - if (!(info & (CAVE_VIEW))) - { - /* Mark as "viewable" */ - info |= (CAVE_VIEW); - - /* Torch-lit grids */ - if (p->d < radius) - { - /* Mark as "CAVE_SEEN" and torch-lit */ - info |= (CAVE_SEEN | CAVE_PLIT); - } - - /* Perma-lit or monster-lit grids */ - else if (info & (CAVE_GLOW | CAVE_MLIT)) - { - /* Mark as "CAVE_SEEN" */ - info |= (CAVE_SEEN); - } - - /* Save cave info */ - c_ptr->info = info; - - /* Save in array */ - view_y[fast_view_n] = y; - view_x[fast_view_n++] = x; - } - } - } - } - } - - - /*** Step 3 -- Complete the algorithm ***/ - - /* Handle blindness */ - if (p_ptr->blind) - { - /* Process "new" grids */ - for (i = 0; i < fast_view_n; i++) - { - /* Location */ - y = view_y[i]; - x = view_x[i]; - - /* Grid cannot be "CAVE_SEEN" */ - cave[y][x].info &= ~(CAVE_SEEN); - } - } - - /* Process "new" grids */ - for (i = 0; i < fast_view_n; i++) - { - /* Location */ - y = view_y[i]; - x = view_x[i]; - - /* Get grid info */ - info = cave[y][x].info; - - /* Was not "CAVE_SEEN", is now "CAVE_SEEN" */ - if ((info & (CAVE_SEEN)) && !(info & (CAVE_TEMP))) - { - /* Note */ - note_spot(y, x); - - /* Redraw */ - lite_spot(y, x); - } - } - - /* Process "old" grids */ - for (i = 0; i < fast_temp_n; i++) - { - /* Location */ - y = temp_y[i]; - x = temp_x[i]; - - /* Grid */ - c_ptr = &cave[y][x]; - - /* Get grid info */ - info = c_ptr->info; - - /* Clear "CAVE_TEMP" flag */ - info &= ~(CAVE_TEMP); - - /* Save cave info */ - c_ptr->info = info; - - /* Was "CAVE_SEEN", is now not "CAVE_SEEN" */ - if (!(info & (CAVE_SEEN))) - { - /* Redraw */ - lite_spot(y, x); - } - } - - - /* Save 'view_n' */ - view_n = fast_view_n; -} - - -/* - * Clear monster light - */ -void forget_mon_lite(void) -{ - int i, y, x; - - /* Process all the monster-lit grids */ - for (i = 0; i < lite_n; i++) - { - /* Access location */ - y = lite_y[i]; - x = lite_x[i]; - - /* Clear monster light flag */ - cave[y][x].info &= ~(CAVE_MLIT); - } - - /* Forget light array */ - lite_n = 0; -} - - -/* - * Update squares illuminated by monsters - * - * Code taken from Steven Fuerst's work for ZAngband, without support - * for multiple lite radii, and with necessary modifications for different - * internal representation of dungeon/wilderness. Other minor changes - * are mine... - * - * I'm not sure if I can handle wide radius well. Consider the following - * example, with p carrying a radius 3 light source: - * - * ##%# - * .x.. - * p##@ - * - * % should be illuminated, although the beam path is entirely out of - * player's los (because of grid-based nature of cave representation)... - * And I'm extremely reluctant to introduce symmetrical los. The current - * asymmetrical system has its own merit, and all the rules of games are - * asymmetrical, in some way or another... - * - * The code below exploits special characteristics of radius one light - * where one can fairly safely use light source's visibility (in terms of los) - * to determine if we can illuminate walls XXX - * - * This function works within the current player's field of view - * calculated by update_view(), so it should normally be called - * whenever FoV is updated (== PU_VIEW | PU_MON_LITE). The other - * case is when RF9_HAS_LITE monsters have moved or dead. Monster - * creation occurs out of LoS, so I chose not to take this into - * consideration. - * - * The CAVE_TEMP flag is used by the function to remember "old" monster-lit - * grids so that it can only redraw squares whose visibility has changed. - * - * Doing this in the update_view() order (update "new" grids, then "old") - * would result in bizarre lighting effects XXX XXX - * - * It has been made possible again to draw torch/monster-lit grids in - * different colours, even when they are in permanently lit locations - * by using (CAVE_PLIT|CAVE_MLIT) as if it were old CAVE_LITE, but I don't - * think it's appropriate for torch lights to be visible under the Sun :) - * or brighter light, and it doesn't work well with PernAngband's already - * colourful terrain features in aesthetically pleasing ways... -- pelpel - */ -void update_mon_lite(void) -{ - int i, y, x, d; - int fy, fx; - - cave_type *c_ptr; - u16b info; - - bool_ invis; - - s16b fast_lite_n = lite_n; - s16b fast_temp_n; - - - /* Mega-Hack -- It's unnecessary there */ - if (p_ptr->wild_mode) return; - - /* Handle special case -- Blindness */ - if (p_ptr->blind) - { - for (i = 0; i < fast_lite_n; i++) - { - /* Light location */ - y = lite_y[i]; - x = lite_x[i]; - - /* Forget monster light and view */ - cave[y][x].info &= ~(CAVE_MLIT | CAVE_SEEN); - - /* Redraw spot */ - /* lite_spot(y, x); */ - } - - /* Clear the light list */ - lite_n = 0; - - /* Done */ - return; - } - - - /* Remember and clear all monster-lit grids */ - for (i = 0; i < fast_lite_n; i++) - { - /* Lit location */ - y = lite_y[i]; - x = lite_x[i]; - - /* Access grid */ - c_ptr = &cave[y][x]; - - /* Access cave info of the grid */ - info = c_ptr->info; - - /* Remember it, by setting the CAVE_TEMP flag */ - info |= (CAVE_TEMP); - - /* Forget monster light */ - info &= ~(CAVE_MLIT); - - /* Unseen unless it's glowing or illuminated by player light source */ - if (!(info & (CAVE_GLOW | CAVE_PLIT))) - { - info &= ~(CAVE_SEEN); - } - - /* Save cave info flags */ - c_ptr->info = info; - } - - - /* Clear the temp list */ - fast_temp_n = 0; - - /* Loop through monsters, adding newly lit grids to changes list */ - for (i = 1; i < m_max; i++) - { - monster_type *m_ptr = &m_list[i]; - monster_race *r_ptr; - - /* Skip dead monsters */ - if (!m_ptr->r_idx) continue; - - /* Skip out-of-sight monsters (MAX_SIGHT + max radius) */ - if (m_ptr->cdis > MAX_SIGHT + 1) continue; - - /* Access monster race info (with possible ego mods) */ - r_ptr = race_info_idx(m_ptr->r_idx, m_ptr->ego); - - /* Skip monsters not carrying light source */ - if (!(r_ptr->flags9 & RF9_HAS_LITE)) continue; - - /* Access the location */ - fy = m_ptr->fy; - fx = m_ptr->fx; - - /* Extract monster grid visibility */ - invis = !player_has_los_bold(fy, fx); - - /* Nested loops may be a bad idea here XXX */ - for (d = 0; d < 9; d++) - { - y = fy + ddy_ddd[d]; - x = fx + ddx_ddd[d]; - - /* Paranoia */ - /* if (!in_bounds(y, x)) continue; */ - - /* Access the grid */ - c_ptr = &cave[y][x]; - - /* Access cave info flags */ - info = c_ptr->info; - - /* Don't care grids out of player's los */ - if (!(info & (CAVE_VIEW))) continue; - - /* - * Avoid processing already monster-lit grids, - * for efficiency and to avoid temp array overflow - */ - if (info & (CAVE_MLIT)) continue; - - /* - * Hack XXX XXX -- light shouldn't penetrate walls - * - * OK NG - * .#. p#. | p. .p. p.. - * p.@ ..@ | .# .#. .#. - * | .@ .@. ..@ - * - * So if a monster carrying light source is out of player LoS, - * walls aren't illuminated. - * - * CAVEAT: % will be illuminated in cases like this: - * - * #%..@ - * p.... - * - * We don't have four sides for a wall grid, so... - */ - if (invis && (f_info[c_ptr->feat].flags1 & FF1_NO_VISION)) continue; - - /* Give monster light to the location */ - c_ptr->info |= (CAVE_MLIT | CAVE_SEEN); - - /* Save the location */ - temp_y[fast_temp_n] = y; - temp_x[fast_temp_n] = x; - fast_temp_n++; - } - } - - /* Process old grids */ - for (i = 0; i < fast_lite_n; i++) - { - /* Access location */ - y = lite_y[i]; - x = lite_x[i]; - - /* Access grid */ - c_ptr = &cave[y][x]; - - /* Was lit, is no longer lit */ - if (!(c_ptr->info & (CAVE_MLIT))) - { - /* Clear the temp flag */ - c_ptr->info &= ~(CAVE_TEMP); - - /* See if there was a visible monster */ - if (player_has_los_bold(y, x) && c_ptr->m_idx) - { - /* Hide the monster */ - update_mon(c_ptr->m_idx, FALSE); - } - else - { - /* Redraw */ - lite_spot(y, x); - } - } - } - - /* Copy the temp array into the light array */ - for (i = 0; i < fast_temp_n; i++) - { - /* Access location */ - y = temp_y[i]; - x = temp_x[i]; - - /* Access grid */ - c_ptr = &cave[y][x]; - - - /* No changes in illumination */ - if (c_ptr->info & (CAVE_TEMP)) - { - /* Clear the temp flag */ - c_ptr->info &= ~(CAVE_TEMP); - } - - /* Was not lit, is now lit */ - else - { - /* Remember the location, if appropriate */ - note_spot(y, x); - - /* See if there is a monster */ - if (c_ptr->m_idx) - { - /* Show it */ - update_mon(c_ptr->m_idx, FALSE); - } - else - { - /* Redraw */ - lite_spot(y, x); - } - } - - - /* Save the location */ - lite_y[i] = y; - lite_x[i] = x; - } - - /* Save lite_n */ - lite_n = fast_temp_n; - - /* Forget temp */ - temp_n = 0; -} - - - - - - -/* - * Hack -- provide some "speed" for the "flow" code - * This entry is the "current index" for the "when" field - * Note that a "when" value of "zero" means "not used". - * - * Note that the "cost" indexes from 1 to 127 are for - * "old" data, and from 128 to 255 are for "new" data. - * - * This means that as long as the player does not "teleport", - * then any monster up to 128 + MONSTER_FLOW_DEPTH will be - * able to track down the player, and in general, will be - * able to track down either the player or a position recently - * occupied by the player. - */ -static int flow_n = 0; - - -/* - * Hack -- forget the "flow" information - */ -void forget_flow(void) -{ - int x, y; - - /* Nothing to forget */ - if (!flow_n) return; - - /* Check the entire dungeon */ - for (y = 0; y < cur_hgt; y++) - { - for (x = 0; x < cur_wid; x++) - { - /* Forget the old data */ - cave[y][x].cost = 0; - cave[y][x].when = 0; - } - } - - /* Start over */ - flow_n = 0; -} - - -/* - * Hack -- Allow us to treat the "seen" array as a queue - */ -static int flow_head = 0; -static int flow_tail = 0; - - -/* - * Take note of a reachable grid. Assume grid is legal. - */ -static void update_flow_aux(int y, int x, int n) -{ - cave_type *c_ptr; - - int old_head = flow_head; - - - /* Get the grid */ - c_ptr = &cave[y][x]; - - /* Ignore "pre-stamped" entries */ - if (c_ptr->when == flow_n) return; - - /* Ignore "walls" and "rubble" */ - if (c_ptr->feat >= FEAT_RUBBLE) return; - - /* Save the time-stamp */ - c_ptr->when = flow_n; - - /* Save the flow cost */ - c_ptr->cost = n; - - /* Hack -- limit flow depth */ - if (n == MONSTER_FLOW_DEPTH) return; - - /* Enqueue that entry */ - temp_y[flow_head] = y; - temp_x[flow_head] = x; - - /* Advance the queue */ - if (++flow_head == TEMP_MAX) flow_head = 0; - - /* Hack -- notice overflow by forgetting new entry */ - if (flow_head == flow_tail) flow_head = old_head; -} - - -/* - * Hack -- fill in the "cost" field of every grid that the player - * can "reach" with the number of steps needed to reach that grid. - * This also yields the "distance" of the player from every grid. - * - * In addition, mark the "when" of the grids that can reach - * the player with the incremented value of "flow_n". - * - * Hack -- use the "seen" array as a "circular queue". - * - * We do not need a priority queue because the cost from grid - * to grid is always "one" and we process them in order. - */ -void update_flow(void) -{ - int x, y, d; - - /* Hack -- disabled */ - if (!flow_by_sound) return; - - /* Paranoia -- make sure the array is empty */ - if (temp_n) return; - - /* Cycle the old entries (once per 128 updates) */ - if (flow_n == 255) - { - /* Rotate the time-stamps */ - for (y = 0; y < cur_hgt; y++) - { - for (x = 0; x < cur_wid; x++) - { - int w = cave[y][x].when; - cave[y][x].when = (w > 128) ? (w - 128) : 0; - } - } - - /* Restart */ - flow_n = 127; - } - - /* Start a new flow (never use "zero") */ - flow_n++; - - - /* Reset the "queue" */ - flow_head = flow_tail = 0; - - /* Add the player's grid to the queue */ - update_flow_aux(p_ptr->py, p_ptr->px, 0); - - /* Now process the queue */ - while (flow_head != flow_tail) - { - /* Extract the next entry */ - y = temp_y[flow_tail]; - x = temp_x[flow_tail]; - - /* Forget that entry */ - if (++flow_tail == TEMP_MAX) flow_tail = 0; - - /* Add the "children" */ - for (d = 0; d < 8; d++) - { - /* Add that child if "legal" */ - update_flow_aux(y + ddy_ddd[d], x + ddx_ddd[d], cave[y][x].cost + 1); - } - } - - /* Forget the flow info */ - flow_head = flow_tail = 0; -} - - - - - - - -/* - * Hack -- map the current panel (plus some) ala "magic mapping" - */ -void map_area(void) -{ - int i, x, y, y1, y2, x1, x2; - - cave_type *c_ptr; - - - /* Pick an area to map */ - y1 = panel_row_min - randint(10); - y2 = panel_row_max + randint(10); - x1 = panel_col_min - randint(20); - x2 = panel_col_max + randint(20); - - /* Speed -- shrink to fit legal bounds */ - if (y1 < 1) y1 = 1; - if (y2 > cur_hgt - 2) y2 = cur_hgt - 2; - if (x1 < 1) x1 = 1; - if (x2 > cur_wid - 2) x2 = cur_wid - 2; - - /* Scan that area */ - for (y = y1; y <= y2; y++) - { - for (x = x1; x <= x2; x++) - { - c_ptr = &cave[y][x]; - - /* All non-walls are "checked" */ - if (!is_wall(c_ptr)) - { - /* Memorize normal features */ - if (!cave_plain_floor_grid(c_ptr)) - { - /* Memorize the object */ - c_ptr->info |= (CAVE_MARK); - } - - /* Memorize known walls */ - for (i = 0; i < 8; i++) - { - c_ptr = &cave[y + ddy_ddd[i]][x + ddx_ddd[i]]; - - /* Memorize walls (etc) */ - if (is_wall(c_ptr)) - { - /* Memorize the walls */ - c_ptr->info |= (CAVE_MARK); - } - } - } - } - } - - /* Redraw map */ - p_ptr->redraw |= (PR_MAP); - - /* Window stuff */ - p_ptr->window |= (PW_OVERHEAD); -} - - - -/* - * Light up the dungeon using "clairvoyance" - * - * This function "illuminates" every grid in the dungeon, memorizes all - * "objects", memorizes all grids as with magic mapping, and, under the - * standard option settings (view_perma_grids but not view_torch_grids) - * memorizes all floor grids too. - * - * Note that if "view_perma_grids" is not set, we do not memorize floor - * grids, since this would defeat the purpose of "view_perma_grids", not - * that anyone seems to play without this option. - * - * Note that if "view_torch_grids" is set, we do not memorize floor grids, - * since this would prevent the use of "view_torch_grids" as a method to - * keep track of what grids have been observed directly. - */ -void wiz_lite(void) -{ - int i, y, x; - - - /* Memorize objects */ - for (i = 1; i < o_max; i++) - { - object_type *o_ptr = &o_list[i]; - - /* Skip dead objects */ - if (!o_ptr->k_idx) continue; - - /* Skip held objects */ - if (o_ptr->held_m_idx) continue; - - /* Memorize */ - o_ptr->marked = TRUE; - } - - /* Scan all normal grids */ - for (y = 1; y < cur_hgt - 1; y++) - { - /* Scan all normal grids */ - for (x = 1; x < cur_wid - 1; x++) - { - cave_type *c_ptr = &cave[y][x]; - - if (c_ptr->m_idx) - { - monster_type *m_ptr = &m_list[c_ptr->m_idx]; - monster_race *r_ptr = race_inf(m_ptr); - - if (r_ptr->flags9 & RF9_MIMIC) - { - object_type *o_ptr = &o_list[m_ptr->hold_o_idx]; - - o_ptr->marked = TRUE; - } - } - - /* Process all non-walls */ - /* if (c_ptr->feat < FEAT_SECRET) */ - { - /* Scan all neighbors */ - for (i = 0; i < 9; i++) - { - int yy = y + ddy_ddd[i]; - int xx = x + ddx_ddd[i]; - - /* Get the grid */ - c_ptr = &cave[yy][xx]; - - /* Perma-lite the grid */ - c_ptr->info |= (CAVE_GLOW); - - /* Memorize normal features */ - if (!cave_plain_floor_grid(c_ptr)) - { - /* Memorize the grid */ - c_ptr->info |= (CAVE_MARK); - } - - /* Normally, memorize floors (see above) */ - if (view_perma_grids && !view_torch_grids) - { - /* Memorize the grid */ - c_ptr->info |= (CAVE_MARK); - } - } - } - } - } - - /* Fully update the visuals */ - p_ptr->update |= (PU_UN_VIEW | PU_VIEW | PU_MONSTERS | PU_MON_LITE); - - /* Redraw map */ - p_ptr->redraw |= (PR_MAP); - - /* Window stuff */ - p_ptr->window |= (PW_OVERHEAD); -} - -void wiz_lite_extra(void) -{ - int y, x; - for (y = 0; y < cur_hgt; y++) - { - for (x = 0; x < cur_wid; x++) - { - cave[y][x].info |= (CAVE_GLOW | CAVE_MARK); - } - } - wiz_lite(); -} - -/* - * Forget the dungeon map (ala "Thinking of Maud..."). - */ -void wiz_dark(void) -{ - int i, y, x; - - - /* Forget every grid */ - for (y = 0; y < cur_hgt; y++) - { - for (x = 0; x < cur_wid; x++) - { - cave_type *c_ptr = &cave[y][x]; - - /* Process the grid */ - c_ptr->info &= ~(CAVE_MARK); - } - } - - /* Forget all objects */ - for (i = 1; i < o_max; i++) - { - object_type *o_ptr = &o_list[i]; - - /* Skip dead objects */ - if (!o_ptr->k_idx) continue; - - /* Skip held objects */ - if (o_ptr->held_m_idx) continue; - - /* Forget the object */ - o_ptr->marked = FALSE; - } - - /* Fully update the visuals */ - p_ptr->update |= (PU_UN_VIEW | PU_VIEW | PU_MONSTERS | PU_MON_LITE); - - /* Redraw map */ - p_ptr->redraw |= (PR_MAP); - - /* Window stuff */ - p_ptr->window |= (PW_OVERHEAD); -} - - - - - -/* - * Change the "feat" flag for a grid, and notice/redraw the grid - */ -void cave_set_feat(int y, int x, int feat) -{ - cave_type *c_ptr = &cave[y][x]; - - /* Change the feature */ - c_ptr->feat = feat; - - /* - * Handle "wall/door" grids - * - * XXX XXX XXX This assumes c_ptr->mimic doesn't mimic terrain - * features whose LoS behaviour is different from its own, in - * most cases. Level boundaries are the most notable exception, - * where "real" terrain is always FEAT_PERM_SOLID, and the fact - * is (ab)used to prevent out-of-range access to the cave array. - * If we were going to implement an evil dungeon type in which - * everything is mimicked, then this function, los(), projectable(), - * project_path() and maybe some functions in melee2.c might - * better use c_ptr->mimic when it's set -- pelpel - */ - if (!cave_sight_grid(c_ptr)) - { - c_ptr->info |= (CAVE_WALL); - } - - /* Handle "floor"/etc grids */ - else - { - c_ptr->info &= ~(CAVE_WALL); - } - - /* Notice & Redraw */ - if (character_dungeon) - { - /* Notice */ - note_spot(y, x); - - /* Redraw */ - lite_spot(y, x); - } -} - - -/* - * Place floor terrain at (y, x) according to dungeon info - */ -void place_floor(int y, int x) -{ - cave_set_feat(y, x, floor_type[rand_int(100)]); -} - -/* - * This routine is used when the current feature gets convert to a floor and - * the possible floor types include glass which is permanent. An unpassable - * feature is undesirable, so the glass gets convert to molten glass which - * is passable. - */ -void place_floor_convert_glass(int y, int x) -{ - place_floor(y, x); - - if (cave[y][x].feat == 188) cave[y][x].feat = 103; -} - -/* - * Place a cave filler at (y, x) - */ -void place_filler(int y, int x) -{ - cave_set_feat(y, x, fill_type[rand_int(100)]); -} - - -/* - * Calculate "incremental motion". Used by project() and shoot(). - * Assumes that (*y,*x) lies on the path from (y1,x1) to (y2,x2). - */ -void mmove2(int *y, int *x, int y1, int x1, int y2, int x2) -{ - int dy, dx, dist, shift; - - /* Extract the distance travelled */ - dy = (*y < y1) ? y1 - *y : *y - y1; - dx = (*x < x1) ? x1 - *x : *x - x1; - - /* Number of steps */ - dist = (dy > dx) ? dy : dx; - - /* We are calculating the next location */ - dist++; - - - /* Calculate the total distance along each axis */ - dy = (y2 < y1) ? (y1 - y2) : (y2 - y1); - dx = (x2 < x1) ? (x1 - x2) : (x2 - x1); - - /* Paranoia -- Hack -- no motion */ - if (!dy && !dx) return; - - - /* Move mostly vertically */ - if (dy > dx) - { - /* Extract a shift factor */ - shift = (dist * dx + (dy - 1) / 2) / dy; - - /* Sometimes move along the minor axis */ - (*x) = (x2 < x1) ? (x1 - shift) : (x1 + shift); - - /* Always move along major axis */ - (*y) = (y2 < y1) ? (y1 - dist) : (y1 + dist); - } - - /* Move mostly horizontally */ - else - { - /* Extract a shift factor */ - shift = (dist * dy + (dx - 1) / 2) / dx; - - /* Sometimes move along the minor axis */ - (*y) = (y2 < y1) ? (y1 - shift) : (y1 + shift); - - /* Always move along major axis */ - (*x) = (x2 < x1) ? (x1 - dist) : (x1 + dist); - } -} - - - -/* - * Determine if a bolt spell cast from (y1,x1) to (y2,x2) will arrive - * at the final destination, assuming no monster gets in the way. - * - * This is slightly (but significantly) different from "los(y1,x1,y2,x2)". - */ -bool_ projectable(int y1, int x1, int y2, int x2) -{ - int dist, y, x; - - /* Start at the initial location */ - y = y1, x = x1; - - /* See "project()" */ - for (dist = 0; dist <= MAX_RANGE; dist++) - { - /* Check for arrival at "final target" */ - /* - * NB: this check was AFTER the 'never pass - * thru walls' clause, below. Switching them - * lets monsters shoot a the player if s/he is - * visible but in a wall - */ - if ((x == x2) && (y == y2)) return (TRUE); - - /* Never pass through walls */ - if (dist && (!cave_sight_bold(y, x) || !cave_floor_bold(y, x))) break; - - /* Calculate the new location */ - mmove2(&y, &x, y1, x1, y2, x2); - } - - - /* Assume obstruction */ - return (FALSE); -} - - - - -/* - * Standard "find me a location" function - * - * Obtains a legal location within the given distance of the initial - * location, and with "los()" from the source to destination location. - * - * This function is often called from inside a loop which searches for - * locations while increasing the "d" distance. - * - * Currently the "m" parameter is unused. - */ -void scatter(int *yp, int *xp, int y, int x, int d) -{ - int nx, ny; - int attempts_left = 5000; - - /* Pick a location */ - while (--attempts_left) - { - /* Pick a new location */ - ny = rand_spread(y, d); - nx = rand_spread(x, d); - - /* Ignore illegal locations and outer walls */ - if (!in_bounds(ny, nx)) continue; - - /* Ignore "excessively distant" locations */ - if ((d > 1) && (distance(y, x, ny, nx) > d)) continue; - - /* Require "line of sight" */ - if (los(y, x, ny, nx)) break; - } - - if (attempts_left > 0) - { - /* Save the location */ - (*yp) = ny; - (*xp) = nx; - } -} - - - - -/* - * Track a new monster - */ -void health_track(int m_idx) -{ - /* Track a new guy */ - health_who = m_idx; - - /* Redraw (later) */ - p_ptr->redraw |= (PR_HEALTH); -} - - - -/* - * Hack -- track the given monster race - */ -void monster_race_track(int r_idx, int ego) -{ - /* Save this monster ID */ - monster_race_idx = r_idx; - monster_ego_idx = ego; - - /* Window stuff */ - p_ptr->window |= (PW_MONSTER); -} - - - -/* - * Hack -- track the given object kind - */ -void object_track(object_type *o_ptr) -{ - /* Save this monster ID */ - tracked_object = o_ptr; - - /* Window stuff */ - p_ptr->window |= (PW_OBJECT); -} - - - -/* - * Something has happened to disturb the player. - * - * The first arg indicates a major disturbance, which affects search. - * - * All disturbance cancels repeated commands, resting, and running. - */ -void disturb(int stop_search) -{ - /* Cancel auto-commands */ - /* command_new = 0; */ - - /* Cancel repeated commands */ - if (command_rep) - { - /* Cancel */ - command_rep = 0; - - /* Redraw the state (later) */ - p_ptr->redraw |= (PR_STATE); - } - - /* Cancel Resting */ - if (resting) - { - /* Cancel */ - resting = 0; - - /* Redraw the state (later) */ - p_ptr->redraw |= (PR_STATE); - } - - /* Cancel running */ - if (running) - { - /* Cancel */ - running = 0; - - /* Calculate torch radius */ - p_ptr->update |= (PU_TORCH); - } - - /* Cancel searching if requested */ - if (stop_search && p_ptr->searching) - { - /* Cancel */ - p_ptr->searching = FALSE; - - /* Recalculate bonuses */ - p_ptr->update |= (PU_BONUS); - - /* Redraw the state */ - p_ptr->redraw |= (PR_STATE); - } - - /* Flush the input if requested */ - if (flush_disturb) flush(); -} - - -/* - * Hack -- Check if a level is a "quest" level - */ -int is_quest(int level) -{ - int i = random_quest_number(); - - /* Check quests */ - if (p_ptr->inside_quest) - return (p_ptr->inside_quest); - - if (i) return (QUEST_RANDOM); - - /* Nope */ - return (0); -} - - -/* - * Return the index of the random quest on this level - * (or zero) - */ -int random_quest_number() -{ - if ((dun_level >= 1) && (dun_level < MAX_RANDOM_QUEST) && - (dungeon_flags1 & DF1_PRINCIPAL) && - (random_quests[dun_level].type) && - (!random_quests[dun_level].done) && - (!is_randhero(dun_level))) - { - return dun_level; - } - - /* Nope */ - return 0; -} - - -/* - * handle spell effects - */ -int effect_pop() -{ - int i; - - for (i = 1; i < MAX_EFFECTS; i++) - if (!effects[i].time) - return i; - return -1; -} - -int new_effect(int type, int dam, int time, int cy, int cx, int rad, s32b flags) -{ - int i; - - if ((i = effect_pop()) == -1) return -1; - - effects[i].type = type; - effects[i].dam = dam; - effects[i].time = time; - effects[i].flags = flags; - effects[i].cx = cx; - effects[i].cy = cy; - effects[i].rad = rad; - return i; -} diff --git a/src/cave.cc b/src/cave.cc new file mode 100644 index 00000000..a0b8c7fc --- /dev/null +++ b/src/cave.cc @@ -0,0 +1,4952 @@ +/* File: cave.c */ + +/* Purpose: low level dungeon routines -BEN- */ + + +#include "angband.h" +#include "q_rand.h" + +#include +#include +#include + +/* + * Support for Adam Bolt's tileset, lighting and transparency effects + * by Robert Ruehlmann (rr9@angband.org) + */ + + +/* + * Approximate Distance between two points. + * + * When either the X or Y component dwarfs the other component, + * this function is almost perfect, and otherwise, it tends to + * over-estimate about one grid per fifteen grids of distance. + * + * Algorithm: hypot(dy,dx) = max(dy,dx) + min(dy,dx) / 2 + */ +int distance(int y1, int x1, int y2, int x2) +{ + int dy, dx, d; + + + /* Find the absolute y/x distance components */ + dy = (y1 > y2) ? (y1 - y2) : (y2 - y1); + dx = (x1 > x2) ? (x1 - x2) : (x2 - x1); + + /* Hack -- approximate the distance */ + d = (dy > dx) ? (dy + (dx >> 1)) : (dx + (dy >> 1)); + + /* Return the distance */ + return (d); +} + + +/* + * Returns TRUE if a grid is considered to be a wall for the purpose + * of magic mapping / clairvoyance + */ +static bool_ is_wall(cave_type *c_ptr) +{ + byte feat; + + + /* Handle feature mimics */ + if (c_ptr->mimic) feat = c_ptr->mimic; + else feat = c_ptr->feat; + + /* Paranoia */ + if (feat >= max_f_idx) return FALSE; + + /* Vanilla floors and doors aren't considered to be walls */ + if (feat < FEAT_SECRET) return FALSE; + + /* Exception #1: a glass wall is a wall but doesn't prevent LOS */ + if (feat == FEAT_GLASS_WALL) return FALSE; + + /* Exception #2: an illusion wall is not a wall but obstructs view */ + if (feat == FEAT_ILLUS_WALL) return TRUE; + + /* Exception #3: a small tree is a floor but obstructs view */ + if (feat == FEAT_SMALL_TREES) return TRUE; + + /* Normal cases: use the WALL flag in f_info.txt */ + return (f_info[feat].flags1 & FF1_WALL) ? TRUE : FALSE; +} + + +/* + * A simple, fast, integer-based line-of-sight algorithm. By Joseph Hall, + * 4116 Brewster Drive, Raleigh NC 27606. Email to jnh@ecemwl.ncsu.edu. + * + * Returns TRUE if a line of sight can be traced from (x1,y1) to (x2,y2). + * + * The LOS begins at the center of the tile (x1,y1) and ends at the center of + * the tile (x2,y2). If los() is to return TRUE, all of the tiles this line + * passes through must be floor tiles, except for (x1,y1) and (x2,y2). + * + * We assume that the "mathematical corner" of a non-floor tile does not + * block line of sight. + * + * Because this function uses (short) ints for all calculations, overflow may + * occur if dx and dy exceed 90. + * + * Once all the degenerate cases are eliminated, the values "qx", "qy", and + * "m" are multiplied by a scale factor "f1 = abs(dx * dy * 2)", so that + * we can use integer arithmetic. + * + * We travel from start to finish along the longer axis, starting at the border + * between the first and second tiles, where the y offset = .5 * slope, taking + * into account the scale factor. See below. + * + * Also note that this function and the "move towards target" code do NOT + * share the same properties. Thus, you can see someone, target them, and + * then fire a bolt at them, but the bolt may hit a wall, not them. However, + * by clever choice of target locations, you can sometimes throw a "curve". + * + * Note that "line of sight" is not "reflexive" in all cases. + * + * Use the "projectable()" routine to test "spell/missile line of sight". + * + * Use the "update_view()" function to determine player line-of-sight. + */ +bool_ los(int y1, int x1, int y2, int x2) +{ + /* Delta */ + int dx, dy; + + /* Absolute */ + int ax, ay; + + /* Signs */ + int sx, sy; + + /* Fractions */ + int qx, qy; + + /* Scanners */ + int tx, ty; + + /* Scale factors */ + int f1, f2; + + /* Slope, or 1/Slope, of LOS */ + int m; + + + /* Extract the offset */ + dy = y2 - y1; + dx = x2 - x1; + + /* Extract the absolute offset */ + ay = ABS(dy); + ax = ABS(dx); + + + /* Handle adjacent (or identical) grids */ + if ((ax < 2) && (ay < 2)) return (TRUE); + + + /* Paranoia -- require "safe" origin */ + /* if (!in_bounds(y1, x1)) return (FALSE); */ + + + /* Directly South/North */ + if (!dx) + { + /* South -- check for walls */ + if (dy > 0) + { + for (ty = y1 + 1; ty < y2; ty++) + { + if (!cave_sight_bold(ty, x1)) return (FALSE); + } + } + + /* North -- check for walls */ + else + { + for (ty = y1 - 1; ty > y2; ty--) + { + if (!cave_sight_bold(ty, x1)) return (FALSE); + } + } + + /* Assume los */ + return (TRUE); + } + + /* Directly East/West */ + if (!dy) + { + /* East -- check for walls */ + if (dx > 0) + { + for (tx = x1 + 1; tx < x2; tx++) + { + if (!cave_sight_bold(y1, tx)) return (FALSE); + } + } + + /* West -- check for walls */ + else + { + for (tx = x1 - 1; tx > x2; tx--) + { + if (!cave_sight_bold(y1, tx)) return (FALSE); + } + } + + /* Assume los */ + return (TRUE); + } + + + /* Extract some signs */ + sx = (dx < 0) ? -1 : 1; + sy = (dy < 0) ? -1 : 1; + + + /* Vertical "knights" */ + if (ax == 1) + { + if (ay == 2) + { + if (cave_sight_bold(y1 + sy, x1)) return (TRUE); + } + } + + /* Horizontal "knights" */ + else if (ay == 1) + { + if (ax == 2) + { + if (cave_sight_bold(y1, x1 + sx)) return (TRUE); + } + } + + + /* Calculate scale factor div 2 */ + f2 = (ax * ay); + + /* Calculate scale factor */ + f1 = f2 << 1; + + + /* Travel horizontally */ + if (ax >= ay) + { + /* Let m = dy / dx * 2 * (dy * dx) = 2 * dy * dy */ + qy = ay * ay; + m = qy << 1; + + tx = x1 + sx; + + /* Consider the special case where slope == 1. */ + if (qy == f2) + { + ty = y1 + sy; + qy -= f1; + } + else + { + ty = y1; + } + + /* Note (below) the case (qy == f2), where */ + /* the LOS exactly meets the corner of a tile. */ + while (x2 - tx) + { + if (!cave_sight_bold(ty, tx)) return (FALSE); + + qy += m; + + if (qy < f2) + { + tx += sx; + } + else if (qy > f2) + { + ty += sy; + if (!cave_sight_bold(ty, tx)) return (FALSE); + qy -= f1; + tx += sx; + } + else + { + ty += sy; + qy -= f1; + tx += sx; + } + } + } + + /* Travel vertically */ + else + { + /* Let m = dx / dy * 2 * (dx * dy) = 2 * dx * dx */ + qx = ax * ax; + m = qx << 1; + + ty = y1 + sy; + + if (qx == f2) + { + tx = x1 + sx; + qx -= f1; + } + else + { + tx = x1; + } + + /* Note (below) the case (qx == f2), where */ + /* the LOS exactly meets the corner of a tile. */ + while (y2 - ty) + { + if (!cave_sight_bold(ty, tx)) return (FALSE); + + qx += m; + + if (qx < f2) + { + ty += sy; + } + else if (qx > f2) + { + tx += sx; + if (!cave_sight_bold(ty, tx)) return (FALSE); + qx -= f1; + ty += sy; + } + else + { + tx += sx; + qx -= f1; + ty += sy; + } + } + } + + /* Assume los */ + return (TRUE); +} + + + +/* + * Returns true if the player's grid is dark + */ +bool_ no_lite(void) +{ + return (!player_can_see_bold(p_ptr->py, p_ptr->px)); +} + + + +/* + * Determine if a given location may be "destroyed" + * + * Used by destruction spells, and for placing stairs, etc. + */ +bool_ cave_valid_bold(int y, int x) +{ + cave_type *c_ptr = &cave[y][x]; + + s16b this_o_idx, next_o_idx = 0; + + + /* Forbid perma-grids */ + if (cave_perma_grid(c_ptr)) return (FALSE); + + /* Check objects */ + for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) + { + object_type * o_ptr; + + /* Acquire object */ + o_ptr = &o_list[this_o_idx]; + + /* Acquire next object */ + next_o_idx = o_ptr->next_o_idx; + + /* Forbid artifact grids */ + if ((o_ptr->art_name) || artifact_p(o_ptr)) return (FALSE); + } + + /* Accept */ + return (TRUE); +} + + + + +/* + * Hack -- Legal monster codes + */ +static cptr image_monster_hack = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + +/* + * Hack -- Legal monster codes for IBM pseudo-graphics + * + * Dropped. Although this option has long left unmaintained, hardcoding + * code points makes it impossible to update the font and prf files + * flexibly. And the normal graphics code still works with it -- pelpel + */ + +/* + * Mega-Hack -- Hallucinatory monster + */ +static void image_monster(byte *ap, char *cp) +{ + int n; + + switch (graphics_mode) + { + /* Text mode */ + case GRAPHICS_NONE: + { + n = strlen(image_monster_hack); + + /* Random symbol from set above */ + *cp = (image_monster_hack[rand_int(n)]); + + /* Random color */ + *ap = randint(15); + + break; + } + + /* Normal graphics */ + default: + { + /* Avoid player ghost */ + n = randint(max_r_idx); + + *cp = r_info[n].x_char; + + *ap = r_info[n].x_attr; + + break; + } + } +} + + + + +/* + * Hack -- Legal object codes + */ +static cptr image_object_hack = "?/|\\\"!$()_-=[]{},~"; + +/* + * Hardcoded IBM pseudo-graphics code points have been removed + * for the same reason as stated above -- pelpel + */ + +/* + * Mega-Hack -- Hallucinatory object + */ +static void image_object(byte *ap, char *cp) +{ + int n; + + switch (graphics_mode) + { + /* Text mode */ + case GRAPHICS_NONE: + { + n = strlen(image_object_hack); + + /* Random symbol from set above */ + *cp = (image_object_hack[rand_int(n)]); + + /* Random color */ + *ap = randint(15); + + /* Done */ + break; + } + + /* Normal graphics */ + default: + { + n = randint(max_k_idx - 1); + + *cp = k_info[n].x_char; + *ap = k_info[n].x_attr; + + break; + } + } +} + + +/* + * Hack -- Random hallucination + */ +static void image_random(byte *ap, char *cp) +{ + /* Normally, assume monsters */ + if (rand_int(100) < 75) + { + image_monster(ap, cp); + } + + /* Otherwise, assume objects */ + else + { + image_object(ap, cp); + } +} + + +/* + * The 16x16 tile of the terrain supports lighting + */ +static bool_ feat_supports_lighting(byte feat) +{ + return (f_info[feat].flags1 & FF1_SUPPORT_LIGHT) != 0; +} + + +char get_shimmer_color() +{ + switch (randint(7)) + { + case 1: + return (TERM_RED); + case 2: + return (TERM_L_RED); + case 3: + return (TERM_WHITE); + case 4: + return (TERM_L_GREEN); + case 5: + return (TERM_BLUE); + case 6: + return (TERM_L_DARK); + case 7: + return (TERM_GREEN); + } + + return (TERM_VIOLET); +} + + +/* + * Table of breath colors. Must match listings in a single set of + * monster spell flags. + * + * The value "255" is special. Monsters with that kind of breath + * may be any color. + */ +static byte breath_to_attr[32][2] = +{ + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { 0, 0 }, + { TERM_SLATE, TERM_L_DARK }, /* RF4_BRTH_ACID */ + { TERM_BLUE, TERM_L_BLUE }, /* RF4_BRTH_ELEC */ + { TERM_RED, TERM_L_RED }, /* RF4_BRTH_FIRE */ + { TERM_WHITE, TERM_L_WHITE }, /* RF4_BRTH_COLD */ + { TERM_GREEN, TERM_L_GREEN }, /* RF4_BRTH_POIS */ + { TERM_L_GREEN, TERM_GREEN }, /* RF4_BRTH_NETHR */ + { TERM_YELLOW, TERM_ORANGE }, /* RF4_BRTH_LITE */ + { TERM_L_DARK, TERM_SLATE }, /* RF4_BRTH_DARK */ + { TERM_L_UMBER, TERM_UMBER }, /* RF4_BRTH_CONFU */ + { TERM_YELLOW, TERM_L_UMBER }, /* RF4_BRTH_SOUND */ + { 255, 255 }, /* (any color) */ /* RF4_BRTH_CHAOS */ + { TERM_VIOLET, TERM_VIOLET }, /* RF4_BRTH_DISEN */ + { TERM_L_RED, TERM_VIOLET }, /* RF4_BRTH_NEXUS */ + { TERM_L_BLUE, TERM_L_BLUE }, /* RF4_BRTH_TIME */ + { TERM_L_WHITE, TERM_SLATE }, /* RF4_BRTH_INER */ + { TERM_L_WHITE, TERM_SLATE }, /* RF4_BRTH_GRAV */ + { TERM_UMBER, TERM_L_UMBER }, /* RF4_BRTH_SHARD */ + { TERM_ORANGE, TERM_RED }, /* RF4_BRTH_PLAS */ + { TERM_UMBER, TERM_L_UMBER }, /* RF4_BRTH_FORCE */ + { TERM_L_BLUE, TERM_WHITE }, /* RF4_BRTH_MANA */ + { 0, 0 }, /* */ + { TERM_GREEN, TERM_L_GREEN }, /* RF4_BRTH_NUKE */ + { 0, 0 }, /* */ + { TERM_WHITE, TERM_L_RED }, /* RF4_BRTH_DISINT */ +}; + + +/* + * Multi-hued monsters shimmer acording to their breaths. + * + * If a monster has only one kind of breath, it uses both colors + * associated with that breath. Otherwise, it just uses the first + * color for any of its breaths. + * + * If a monster does not breath anything, it can be any color. + */ +static byte multi_hued_attr(monster_race *r_ptr) +{ + byte allowed_attrs[15]; + + int i, j; + + int stored_colors = 0; + + int breaths = 0; + + int first_color = 0; + + int second_color = 0; + + + /* Monsters with no ranged attacks can be any color */ + if (!r_ptr->freq_inate) return (get_shimmer_color()); + + /* Check breaths */ + for (i = 0; i < 32; i++) + { + bool_ stored = FALSE; + + /* Don't have that breath */ + if (!(r_ptr->flags4 & (1L << i))) continue; + + /* Get the first color of this breath */ + first_color = breath_to_attr[i][0]; + + /* Breath has no color associated with it */ + if (first_color == 0) continue; + + /* Monster can be of any color */ + if (first_color == 255) return (randint(15)); + + + /* Increment the number of breaths */ + breaths++; + + /* Monsters with lots of breaths may be any color. */ + if (breaths == 6) return (randint(15)); + + + /* Always store the first color */ + for (j = 0; j < stored_colors; j++) + { + /* Already stored */ + if (allowed_attrs[j] == first_color) stored = TRUE; + } + if (!stored) + { + allowed_attrs[stored_colors] = first_color; + stored_colors++; + } + + /* + * Remember (but do not immediately store) the second color + * of the first breath. + */ + if (breaths == 1) + { + second_color = breath_to_attr[i][1]; + } + } + + /* Monsters with no breaths may be of any color. */ + if (breaths == 0) return (get_shimmer_color()); + + /* If monster has one breath, store the second color too. */ + if (breaths == 1) + { + allowed_attrs[stored_colors] = second_color; + stored_colors++; + } + + /* Pick a color at random */ + return (allowed_attrs[rand_int(stored_colors)]); +} + + +/* + * Extract the attr/char to display at the given (legal) map location + * + * Note that this function, since it is called by "lite_spot()" which + * is called by "update_view()", is a major efficiency concern. + * + * Basically, we examine each "layer" of the world (terrain, objects, + * monsters/players), from the bottom up, extracting a new attr/char + * if necessary at each layer, and defaulting to "darkness". This is + * not the fastest method, but it is very simple, and it is about as + * fast as it could be for grids which contain no "marked" objects or + * "visible" monsters. + * + * We apply the effects of hallucination during each layer. Objects will + * always appear as random "objects", monsters will always appear as random + * "monsters", and normal grids occasionally appear as random "monsters" or + * "objects", but note that these random "monsters" and "objects" are really + * just "colored ascii symbols" (which may look silly on some machines). + * + * The hallucination functions avoid taking any pointers to local variables + * because some compilers refuse to use registers for any local variables + * whose address is taken anywhere in the function. + * + * As an optimization, we can handle the "player" grid as a special case. + * + * Note that the memorization of "objects" and "monsters" is not related + * to the memorization of "terrain". This allows the player to memorize + * the terrain of a grid without memorizing any objects in that grid, and + * to detect monsters without detecting anything about the terrain of the + * grid containing the monster. + * + * The fact that all interesting "objects" and "terrain features" are + * memorized as soon as they become visible for the first time means + * that we only have to check the "CAVE_SEEN" flag for "boring" grids. + * + * Note that bizarre things must be done when the "attr" and/or "char" + * codes have the "high-bit" set, since these values are used to encode + * various "special" pictures in some versions, and certain situations, + * such as "multi-hued" or "clear" monsters, cause the attr/char codes + * to be "scrambled" in various ways. + * + * Note that the "zero" entry in the feature/object/monster arrays are + * used to provide "special" attr/char codes, with "monster zero" being + * used for the player attr/char, "object zero" being used for the "stack" + * attr/char, and "feature zero" being used for the "nothing" attr/char. + * + * Note that eventually we may want to use the "&" symbol for embedded + * treasure, and use the "*" symbol to indicate multiple objects, but + * currently, we simply use the attr/char of the first "marked" object + * in the stack, if any, and so "object zero" is unused. XXX XXX XXX + * + * Note the assumption that doing "x_ptr = &x_info[x]" plus a few of + * "x_ptr->xxx", is quicker than "x_info[x].xxx", even if "x" is a fixed + * constant. If this is incorrect then a lot of code should be changed. + * + * + * Some comments on the "terrain" layer... + * + * Note that "boring" grids (floors, invisible traps, and any illegal grids) + * are very different from "interesting" grids (all other terrain features), + * and the two types of grids are handled completely separately. The most + * important distinction is that "boring" grids may or may not be memorized + * when they are first encountered, and so we must use the "CAVE_SEEN" flag + * to see if they are "see-able". + * + * + * Some comments on the "terrain" layer (boring grids)... + * + * Note that "boring" grids are always drawn using the picture for "empty + * floors", which is stored in "f_info[FEAT_FLOOR]". Sometimes, special + * lighting effects may cause this picture to be modified. + * + * Note that "invisible traps" are always displayes exactly like "empty + * floors", which prevents various forms of "cheating", with no loss of + * efficiency. There are still a few ways to "guess" where traps may be + * located, for example, objects will never fall into a grid containing + * an invisible trap. XXX XXX + * + * To determine if a "boring" grid should be displayed, we simply check to + * see if it is either memorized ("CAVE_MARK"), or currently "see-able" by + * the player ("CAVE_SEEN"). Note that "CAVE_SEEN" is now maintained by the + * "update_view()" function. + * + * Note the "special lighting effects" which can be activated for "boring" + * grids using the "view_special_lite" option, causing certain such grids + * to be displayed using special colors. If the grid is "see-able" by + * the player, we will use the normal (except that, if the "view_yellow_lite" + * option is set, and the grid is *only* "see-able" because of the player's + * torch, then we will use "yellow"), else if the player is "blind", we will + * use greyscale, else if the grid is not "illuminated", we will use "dark + * gray", if the "view_bright_lite" option is set, we will use "darker" colour + * else we will use the normal colour. + * + * + * Some comments on the "terrain" layer (non-boring grids)... + * + * Note the use of the "mimic" field in the "terrain feature" processing, + * which allows any feature to "pretend" to be another feature. This is + * used to "hide" secret doors, and to make all "doors" appear the same, + * and all "walls" appear the same, and "hidden" treasure stay hidden. + * Note that it is possible to use this field to make a feature "look" + * like a floor, but the "view_special_lite" flag only affects actual + * "boring" grids. + * + * Since "interesting" grids are always memorized as soon as they become + * "see-able" by the player ("CAVE_SEEN"), such a grid only needs to be + * displayed if it is memorized ("CAVE_MARK"). Most "interesting" grids + * are in fact non-memorized, non-see-able, wall grids, so the fact that + * we do not have to check the "CAVE_SEEN" flag adds some efficiency, at + * the cost of *forcing* the memorization of all "interesting" grids when + * they are first seen. Since the "CAVE_SEEN" flag is now maintained by + * the "update_view()" function, this efficiency is not as significant as + * it was in previous versions, and could perhaps be removed. + * (so I removed this to simplify the terrain feature handling -- pelpel) + * + * Note the "special lighting effects" which can be activated for "wall" + * grids using the "view_granite_lite" option, causing certain such grids + * to be displayed using special colors. + * If the grid is "see-able" by the player, we will use the normal colour + * else if the player is "blind", we will use grey scale, else if the + * "view_bright_lite" option is set, we will use reduced colour, else we + * will use the normal one. + * + * Note that "wall" grids are more complicated than "boring" grids, due to + * the fact that "CAVE_GLOW" for a "wall" grid means that the grid *might* + * be glowing, depending on where the player is standing in relation to the + * wall. In particular, the wall of an illuminated room should look just + * like any other (dark) wall unless the player is actually inside the room. + * + * Thus, we do not support as many visual special effects for "wall" grids + * as we do for "boring" grids, since many of them would give the player + * information about the "CAVE_GLOW" flag of the wall grid, in particular, + * it would allow the player to notice the walls of illuminated rooms from + * a dark hallway that happened to run beside the room. + * + * + * Some comments on the "object" layer... + * + * Currently, we do nothing with multi-hued objects, because there are + * not any. If there were, they would have to set "shimmer_objects" + * when they were created, and then new "shimmer" code in "dungeon.c" + * would have to be created handle the "shimmer" effect, and the code + * in "cave.c" would have to be updated to create the shimmer effect. + * This did not seem worth the effort. XXX XXX + * + * + * Some comments on the "monster"/"player" layer... + * + * Note that monsters can have some "special" flags, including "ATTR_MULTI", + * which means their color changes, and "ATTR_CLEAR", which means they take + * the color of whatever is under them, and "CHAR_CLEAR", which means that + * they take the symbol of whatever is under them. Technically, the flag + * "CHAR_MULTI" is supposed to indicate that a monster looks strange when + * examined, but this flag is currently ignored. All of these flags are + * ignored if the "avoid_other" option is set, since checking for these + * conditions is expensive (and annoying) on some systems. + * + * Normally, players could be handled just like monsters, except that the + * concept of the "torch lite" of others player would add complications. + * For efficiency, however, we handle the (only) player first, since the + * "player" symbol always "pre-empts" any other facts about the grid. + * + * The "hidden_player" efficiency option, which only makes sense with a + * single player, allows the player symbol to be hidden while running. + */ + +/* + * Alternative colours for unseen grids + * + * Reduced colours - remembered interesting grids and perma-lit floors + * B&W - currently only used by blindness effect + */ + +/* Colour */ +static byte dark_attrs[16] = +{ + TERM_DARK, TERM_L_WHITE, TERM_L_DARK, TERM_ORANGE, + TERM_RED, TERM_GREEN, TERM_BLUE, TERM_UMBER, + TERM_L_DARK, TERM_SLATE, TERM_VIOLET, TERM_YELLOW, + TERM_RED, TERM_GREEN, TERM_BLUE, TERM_UMBER +}; + +/* B&W */ +static byte darker_attrs[16] = +{ + TERM_DARK, TERM_L_WHITE, TERM_L_DARK, TERM_SLATE, + TERM_L_DARK, TERM_L_DARK, TERM_L_DARK, TERM_L_DARK, + TERM_L_DARK, TERM_SLATE, TERM_L_DARK, TERM_SLATE, + TERM_SLATE, TERM_SLATE, TERM_SLATE, TERM_SLATE +}; + + +void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp, + byte *eap, char *ecp) +{ + cave_type *c_ptr; + + feature_type *f_ptr; + + s16b this_o_idx, next_o_idx = 0; + + u16b info; + + s16b t_idx; + + byte feat; + + byte a; + + byte c; + + /* + * This means that a port supports graphics overlay as well as lighting + * effects. See the step 3 below for the detailed information about + * lighting. Basically, it requires "darker" tiles for those terrain + * features with SUPPORT_LIGHT flag set, and they must be arranged + * this way: + * col col+1 col+2 + * row base darker brighter + */ + bool_ graf_new = ((graphics_mode == GRAPHICS_ISO) || + (graphics_mode == GRAPHICS_NEW)); + + /* + * I never understand why some coders like shimmering so much. + * It just serves to hurt my eyes, IMHO. If one feels like to show off, + * go for better graphics support... Anyway this means a port allows + * changing attr independently from its char -- pelpel + */ + bool_ attr_mutable = (!use_graphics || + (graphics_mode == GRAPHICS_IBM)); + + + /**** Preparation ****/ + + /* Access the grid */ + c_ptr = &cave[y][x]; + + + /* Cache some frequently used values */ + + /* Grid info */ + info = c_ptr->info; + + /* Feature code */ + feat = c_ptr->feat; + + /* Apply "mimic" field */ + if (c_ptr->mimic) + { + feat = c_ptr->mimic; + } + else + { + feat = f_info[feat].mimic; + } + + /* Access floor */ + f_ptr = &f_info[feat]; + + + /* Reset attr/char */ + *eap = 0; + *ecp = 0; + + + /**** Layer 1 -- Terrain feature ****/ + + /* Only memorised or visible grids are displayed */ + if (info & (CAVE_MARK | CAVE_SEEN)) + { + /**** Step 1 -- Retrieve base attr/char ****/ + + /* 'Sane' terrain features */ + if (feat != FEAT_SHOP) + { + /* Normal char */ + c = f_ptr->x_char; + + /* Normal attr */ + a = f_ptr->x_attr; + } + + /* Mega-Hack 1 -- Building don't conform to f_info */ + else + { + c = st_info[c_ptr->special].x_char; + a = st_info[c_ptr->special].x_attr; + } + + /* Mega-Hack 2 -- stair to dungeon branch are purple */ + if (c_ptr->special && attr_mutable && + ((feat == FEAT_MORE) || (feat == FEAT_LESS))) + { + a = TERM_VIOLET; + } + + /* Mega-Hack 3 -- Traps don't have f_info entries either */ + if ((info & (CAVE_TRDT)) && (feat != FEAT_ILLUS_WALL)) + { + /* Trap index */ + t_idx = c_ptr->t_idx; + + if (use_graphics && + (t_info[t_idx].g_attr != 0) && + (t_info[t_idx].g_char != 0)) + { + + if (graf_new) + { + *eap = t_info[t_idx].g_attr; + *ecp = t_info[t_idx].g_char; + } + else + { + a = t_info[t_idx].g_attr; + c = t_info[t_idx].g_char; + } + + } + else + { + /* + * If trap is set on a floor grid that is not + * one of "interesting" features, use a special + * symbol to display it. Check for doors is no longer + * necessary because they have REMEMBER flag now. + * + * Cave macros cannot be used safely here, because of + * c_ptr->mimic XXX XXX + */ + if (!attr_mutable) + { + a = f_info[FEAT_TRAP].x_attr; + c = f_info[FEAT_TRAP].x_char; + } + else + { + if ((f_ptr->flags1 & (FF1_FLOOR | FF1_REMEMBER)) == FF1_FLOOR) + { + c = f_info[FEAT_TRAP].x_char; + } + + /* Add attr XXX XXX XXX */ + a = t_info[t_idx].color; + + /* Get a new color with a strange formula :) XXX XXX XXX */ + if (t_info[t_idx].flags & FTRAP_CHANGE) + { + s32b tmp; + + tmp = dun_level + dungeon_type + feat; + + a = tmp % 16; + } + } + } + } + + + /**** Step 2 -- Apply special random effects ****/ + if (!avoid_other && !avoid_shimmer && attr_mutable) + { + /* Special terrain effect */ + if (c_ptr->effect) + { + a = spell_color(effects[c_ptr->effect].type); + } + + /* Multi-hued attr */ + else if (f_ptr->flags1 & FF1_ATTR_MULTI) + { + a = f_ptr->shimmer[rand_int(7)]; + } + } + + + /* + * Step 3 + * + * Special lighting effects, if specified and applicable + * This will never happen for + * - any grids in the overhead map + * - traps + * - (graphics modes) terrain features without corresponding + * "darker" tiles. + * + * Note the use of f_ptr->flags1 to avoid problems with + * c_ptr->mimic. + */ + + /* view_special_lite: lighting effects for boring features */ + if (view_special_lite && + ((f_ptr->flags1 & (FF1_FLOOR | FF1_REMEMBER)) == FF1_FLOOR)) + { + if (!p_ptr->wild_mode && !(info & (CAVE_TRDT)) && + (attr_mutable || (graf_new && feat_supports_lighting(feat)))) + { + /* Handle "seen" grids */ + if (info & (CAVE_SEEN)) + { + /* Only lit by "torch" light */ + if (view_yellow_lite && !(info & (CAVE_GLOW))) + { + if (graf_new) + { + /* Use a brightly lit tile */ + c += 2; + } + else + { + /* Use "yellow" */ + a = TERM_YELLOW; + } + } + } + + /* Handle "blind" */ + else if (p_ptr->blind) + { + if (graf_new) + { + /* Use a dark tile */ + c++; + } + else + { + /* Use darker colour */ + a = darker_attrs[a & 0xF]; + } + } + + /* Handle "dark" grids */ + else if (!(info & (CAVE_GLOW))) + { + if (graf_new) + { + /* Use a dark tile */ + c++; + } + else + { + /* Use darkest colour */ + a = TERM_L_DARK; + } + } + + /* "Out-of-sight" glowing grids -- handle "view_bright_lite" */ + else if (view_bright_lite) + { + if (graf_new) + { + /* Use a dark tile */ + c++; + } + else + { + /* Use darker colour */ + a = dark_attrs[a & 0xF]; + } + } + } + } + + /* view_granite_lite: lighting effects for walls and doors */ + else if (view_granite_lite && + (f_ptr->flags1 & (FF1_NO_VISION | FF1_DOOR))) + { + if (!p_ptr->wild_mode && !(info & (CAVE_TRDT)) && + (attr_mutable || (graf_new && feat_supports_lighting(feat)))) + { + /* Handle "seen" grids */ + if (info & (CAVE_SEEN)) + { + /* Do nothing */ + } + + /* Handle "blind" */ + else if (p_ptr->blind) + { + if (graf_new) + { + /* Use a dark tile */ + c++; + } + else + { + /* Use darker colour */ + a = darker_attrs[a & 0xF]; + } + } + + /* Handle "view_bright_lite" */ + else if (view_bright_lite) + { + if (graf_new) + { + /* Use a dark tile */ + c++; + } + else + { + /* Use darker colour */ + a = dark_attrs[a & 0xF]; + } + } + + else + { + if (graf_new) + { + /* Use a brightly lit tile */ + c += 2; + } + else + { + /* Use normal colour */ + } + } + } + } + } + + /* Unknown grids */ + else + { + /* Access darkness */ + f_ptr = &f_info[FEAT_NONE]; + + /* Normal attr */ + a = f_ptr->x_attr; + + /* Normal char */ + c = f_ptr->x_char; + } + + /* + * Hack -- rare random hallucination + * Because we cannot be sure which is outer dungeon walls, + * the check for 'feat' has been removed + */ + if (p_ptr->image && (rand_int(256) == 0)) + { + /* Hallucinate */ + image_random(ap, cp); + } + + /* Save the terrain info for the transparency effects */ + *tap = a; + *tcp = c; + + /* Save the info */ + *ap = a; + *cp = c; + + + /**** Layer 2 -- Objects ****/ + + if (feat != FEAT_MON_TRAP) + { + for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) + { + object_type * o_ptr; + + /* Acquire object */ + o_ptr = &o_list[this_o_idx]; + + /* Acquire next object */ + next_o_idx = o_ptr->next_o_idx; + + /* Memorized objects */ + if (o_ptr->marked) + { + /* Normal char */ + *cp = object_char(o_ptr); + + /* Normal attr */ + *ap = object_attr(o_ptr); + + /* Multi-hued attr */ + if (!avoid_other && attr_mutable && + (k_info[o_ptr->k_idx].flags5 & TR5_ATTR_MULTI)) + { + *ap = get_shimmer_color(); + } + + /* Hack -- hallucination */ + if (p_ptr->image) image_object(ap, cp); + + /* Done */ + break; + } + } + } + + + /**** Layer 3 -- Handle monsters ****/ + + if (c_ptr->m_idx) + { + monster_type *m_ptr = &m_list[c_ptr->m_idx]; + monster_race *r_ptr = race_inf(m_ptr); + + if (r_ptr->flags9 & RF9_MIMIC) + { + object_type *o_ptr; + + /* Acquire object */ + o_ptr = &o_list[m_ptr->hold_o_idx]; + + /* Memorized objects */ + if (o_ptr->marked) + { + /* Normal char */ + *cp = object_char(o_ptr); + + /* Normal attr */ + *ap = object_attr(o_ptr); + + /* Multi-hued attr */ + if (!avoid_other && attr_mutable && + (k_info[o_ptr->k_idx].flags5 & TR5_ATTR_MULTI)) + { + *ap = get_shimmer_color(); + } + + /* Hack -- hallucination */ + if (p_ptr->image) image_object(ap, cp); + } + } + else + { + /* Visible monster */ + if (m_ptr->ml) + { + monster_race *r_ptr = race_inf(m_ptr); + + /* Reset attr/char */ + *eap = 0; + *ecp = 0; + + if (use_graphics) + { + + if (graf_new) + { + monster_ego *re_ptr = &re_info[m_ptr->ego]; + + /* Desired attr */ + *eap = re_ptr->g_attr; + + /* Desired char */ + *ecp = re_ptr->g_char; + } + + /* Use base monster */ + r_ptr = &r_info[m_ptr->r_idx]; + } + + /* Desired attr/char */ + c = r_ptr->x_char; + a = r_ptr->x_attr; + + /* Ignore weird codes */ + if (avoid_other) + { + /* Use char */ + *cp = c; + + /* Use attr */ + *ap = a; + } + + /* Special attr/char codes */ + else if (!attr_mutable) + { + /* Use char */ + *cp = c; + + /* Use attr */ + *ap = a; + } + + /* Multi-hued monster */ + else if (r_ptr->flags1 & (RF1_ATTR_MULTI)) + { + /* Is it a shapechanger? */ + if (r_ptr->flags2 & (RF2_SHAPECHANGER)) + { + image_random(ap, cp); + } + else + *cp = c; + + /* Multi-hued attr */ + if (r_ptr->flags2 & (RF2_ATTR_ANY)) + { + *ap = randint(15); + } + else + { + *ap = multi_hued_attr(r_ptr); + } + } + + /* Normal monster (not "clear" in any way) */ + else if (!(r_ptr->flags1 & (RF1_ATTR_CLEAR | RF1_CHAR_CLEAR))) + { + /* Use char */ + *cp = c; + + /* Use attr */ + *ap = a; + } + + /* + * Hack -- Bizarre grid under monster + * WAS: else if (*ap & 0x80) || (*cp & 0x80) -- pelpel + */ + else if (*ap & 0x80) + { + /* Use char */ + *cp = c; + + /* Use attr */ + *ap = a; + } + + /* Normal */ + else + { + /* Normal (non-clear char) monster */ + if (!(r_ptr->flags1 & (RF1_CHAR_CLEAR))) + { + /* Normal char */ + *cp = c; + } + + /* Normal (non-clear attr) monster */ + else if (!(r_ptr->flags1 & (RF1_ATTR_CLEAR))) + { + /* Normal attr */ + *ap = a; + } + } + + /* Hack -- hallucination */ + if (p_ptr->image) + { + /* Hallucinatory monster */ + image_monster(ap, cp); + } + } + } + } + + /* Handle "player" */ + if ((y == p_ptr->py) && (x == p_ptr->px) && + (!p_ptr->invis || p_ptr->see_inv)) + { + monster_race *r_ptr = &r_info[p_ptr->body_monster]; + + /* Reset attr/char */ + *eap = 0; + *ecp = 0; + + /* Get the "player" attr */ + if (!avoid_other && attr_mutable && (r_ptr->flags1 & RF1_ATTR_MULTI)) + { + a = get_shimmer_color(); + } + else + { + a = r_ptr->x_attr; + } + + /* Get the "player" char */ + c = r_ptr->x_char; + + + /* Mega-Hack -- Apply modifications to player graphics XXX XXX XXX */ + switch (graphics_mode) + { + case GRAPHICS_NONE: + case GRAPHICS_IBM: + { + if (player_char_health) + { + int percent = p_ptr->chp * 10 / p_ptr->mhp; + + if (percent < 7) + { + c = I2D(percent); + if (percent < 3) a = TERM_L_RED; + } + } + + break; + } + + case GRAPHICS_OLD: + { + if (player_symbols) + { + a = BMP_FIRST_PC_CLASS + p_ptr->pclass; + c = BMP_FIRST_PC_RACE + p_ptr->prace; + } + + break; + } + + case GRAPHICS_ISO: + case GRAPHICS_NEW: + { + if (p_ptr->pracem) + { + player_race_mod *rmp_ptr = &race_mod_info[p_ptr->pracem]; + + /* Desired attr */ + *eap = rmp_ptr->g_attr; + + /* Desired char */ + *ecp = rmp_ptr->g_char; + } + + /* +AKH 20020421 - Health dispay for graphics, too */ + if (player_char_health && (graphics_mode == GRAPHICS_NEW)) + { + int percent = p_ptr->chp * 14 / p_ptr->mhp; + + if (percent < 10) + { + *eap = 10; + *ecp = 32 + 14 - percent; + } + } + + break; + } + + } + + /* Save the info */ + *ap = a; + *cp = c; + + } +} + + +/* + * Special version of map_info, for use by cmovie and HTML converter + * to obtain pure-ASCII image of dungeon map + */ +void map_info_default(int y, int x, byte *ap, char *cp) +{ + cave_type *c_ptr; + + feature_type *f_ptr; + + s16b this_o_idx, next_o_idx = 0; + + u16b info; + + s16b t_idx; + + byte feat; + + byte a; + + byte c; + + bool_ use_graphics_hack = use_graphics; + byte graphics_mode_hack = graphics_mode; + + + /* Temporarily disable graphics mode -- for some random effects XXX */ + use_graphics = FALSE; + graphics_mode = GRAPHICS_NONE; + + /**** Preparation ****/ + + /* Access the grid */ + c_ptr = &cave[y][x]; + + + /* Cache some frequently used values */ + + /* Grid info */ + info = c_ptr->info; + + /* Feature code */ + feat = c_ptr->feat; + + /* Apply "mimic" field */ + if (c_ptr->mimic) + { + feat = c_ptr->mimic; + } + else + { + feat = f_info[feat].mimic; + } + + /* Access floor */ + f_ptr = &f_info[feat]; + + + /**** Layer 1 -- Terrain feature ****/ + + /* Only memorised or visible grids are displayed */ + if (info & (CAVE_MARK | CAVE_SEEN)) + { + /**** Step 1 -- Retrieve base attr/char ****/ + + /* 'Sane' terrain features */ + if (feat != FEAT_SHOP) + { + /* Default char */ + c = f_ptr->d_char; + + /* Default attr */ + a = f_ptr->d_attr; + } + + /* Mega-Hack 1 -- Building don't conform to f_info */ + else + { + c = st_info[c_ptr->special].d_char; + a = st_info[c_ptr->special].d_attr; + } + + /* Mega-Hack 2 -- stair to dungeon branch are purple */ + if (c_ptr->special && + ((feat == FEAT_MORE) || (feat == FEAT_LESS))) + { + a = TERM_VIOLET; + } + + /* Mega-Hack 3 -- Traps don't have f_info entries either */ + if ((info & (CAVE_TRDT)) && (feat != FEAT_ILLUS_WALL)) + { + /* Trap index */ + t_idx = c_ptr->t_idx; + + /* + * If trap is set on a floor grid that is not + * one of "interesting" features, use a special + * symbol to display it. Check for doors is no longer + * necessary because they have REMEMBER flag now. + * + * Cave macros cannot be used safely here, because of + * c_ptr->mimic XXX XXX + */ + if ((f_ptr->flags1 & (FF1_FLOOR | FF1_REMEMBER)) == FF1_FLOOR) + { + c = f_info[FEAT_TRAP].d_char; + } + + /* Add attr */ + a = t_info[t_idx].color; + + /* Get a new color with a strange formula :) */ + if (t_info[t_idx].flags & FTRAP_CHANGE) + { + s32b tmp; + + tmp = dun_level + dungeon_type + feat; + + a = tmp % 16; + } + } + + + /**** Step 2 -- Apply special random effects ****/ + if (!avoid_other) + { + /* Special terrain effect */ + if (c_ptr->effect) + { + a = spell_color(effects[c_ptr->effect].type); + } + + /* Multi-hued attr */ + else if (f_ptr->flags1 & FF1_ATTR_MULTI) + { + a = f_ptr->shimmer[rand_int(7)]; + } + } + + + /* + * Step 3 + * + * Special lighting effects, if specified and applicable + * This will never happen for + * - any grids in the overhead map + * - traps + * - (graphics modes) terrain features without corresponding + * "darker" tiles. + * + * All the if's here are flag checks, so changed order shouldn't + * affect performance a lot, I hope... + */ + + /* view_special_lite: lighting effects for boring features */ + if (view_special_lite && + ((f_ptr->flags1 & (FF1_FLOOR | FF1_REMEMBER)) == FF1_FLOOR)) + { + if (!p_ptr->wild_mode && !(info & (CAVE_TRDT))) + { + /* Handle "seen" grids */ + if (info & (CAVE_SEEN)) + { + /* Only lit by "torch" light */ + if (view_yellow_lite && !(info & (CAVE_GLOW))) + { + /* Use "yellow" */ + a = TERM_YELLOW; + } + } + + /* Handle "blind" */ + else if (p_ptr->blind) + { + /* Use darker colour */ + a = darker_attrs[a & 0xF]; + } + + /* Handle "dark" grids */ + else if (!(info & (CAVE_GLOW))) + { + /* Use darkest colour */ + a = TERM_L_DARK; + } + + /* "Out-of-sight" glowing grids -- handle "view_bright_lite" */ + else if (view_bright_lite) + { + /* Use darker colour */ + a = dark_attrs[a & 0xF]; + } + } + } + + /* view_granite_lite: lighting effects for walls and doors */ + else if (view_granite_lite && + (f_ptr->flags1 & (FF1_NO_VISION | FF1_DOOR))) + { + if (!p_ptr->wild_mode && !(info & (CAVE_TRDT))) + { + /* Handle "seen" grids */ + if (info & (CAVE_SEEN)) + { + /* Do nothing */ + } + + /* Handle "blind" */ + else if (p_ptr->blind) + { + /* Use darker colour */ + a = darker_attrs[a & 0xF]; + } + + /* Handle "view_bright_lite" */ + else if (view_bright_lite) + { + /* Use darker colour */ + a = dark_attrs[a & 0xF]; + } + } + } + } + + /* Unknown grids */ + else + { + /* Access darkness */ + f_ptr = &f_info[FEAT_NONE]; + + /* Default attr */ + a = f_ptr->d_attr; + + /* Default char */ + c = f_ptr->d_char; + } + + /* + * Hack -- rare random hallucination + * Because we cannot be sure which is outer dungeon walls, + * the check for 'feat' has been removed + */ + if (p_ptr->image && (rand_int(256) == 0)) + { + /* Hallucinate */ + image_random(ap, cp); + } + + /* Save the info */ + *ap = a; + *cp = c; + + + /**** Layer 2 -- Objects ****/ + + if (feat != FEAT_MON_TRAP) + { + for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) + { + object_type * o_ptr; + + /* Acquire object */ + o_ptr = &o_list[this_o_idx]; + + /* Acquire next object */ + next_o_idx = o_ptr->next_o_idx; + + /* Memorized objects */ + if (o_ptr->marked) + { + /* Normal char */ + *cp = object_char_default(o_ptr); + + /* Normal attr */ + *ap = object_attr_default(o_ptr); + + /* Multi-hued attr */ + if (!avoid_other && + (k_info[o_ptr->k_idx].flags5 & TR5_ATTR_MULTI)) + { + *ap = get_shimmer_color(); + } + + /* Hack -- hallucination */ + if (p_ptr->image) image_object(ap, cp); + + /* Done */ + break; + } + } + } + + + /**** Layer 3 -- Handle monsters ****/ + + if (c_ptr->m_idx) + { + monster_type *m_ptr = &m_list[c_ptr->m_idx]; + monster_race *r_ptr = race_inf(m_ptr); + + if (r_ptr->flags9 & RF9_MIMIC) + { + object_type *o_ptr; + + /* Acquire object */ + o_ptr = &o_list[m_ptr->hold_o_idx]; + + /* Memorized objects */ + if (o_ptr->marked) + { + /* Normal char */ + *cp = object_char_default(o_ptr); + + /* Normal attr */ + *ap = object_attr_default(o_ptr); + + /* Multi-hued attr */ + if (!avoid_other && !use_graphics && + (k_info[o_ptr->k_idx].flags5 & TR5_ATTR_MULTI)) + { + *ap = get_shimmer_color(); + } + + /* Hack -- hallucination */ + if (p_ptr->image) image_object(ap, cp); + } + } + else + { + /* Visible monster */ + if (m_ptr->ml) + { + monster_race *r_ptr = race_inf(m_ptr); + + /* Default attr/char */ + c = r_ptr->d_char; + a = r_ptr->d_attr; + + /* Ignore weird codes */ + if (avoid_other) + { + /* Use char */ + *cp = c; + + /* Use attr */ + *ap = a; + } + + /* Multi-hued monster */ + else if (r_ptr->flags1 & (RF1_ATTR_MULTI)) + { + /* Is it a shapechanger? */ + if (r_ptr->flags2 & (RF2_SHAPECHANGER)) + { + image_random(ap, cp); + } + else + *cp = c; + + /* Multi-hued attr */ + if (r_ptr->flags2 & (RF2_ATTR_ANY)) + { + *ap = randint(15); + } + else + { + *ap = multi_hued_attr(r_ptr); + } + } + + /* Normal monster (not "clear" in any way) */ + else if (!(r_ptr->flags1 & (RF1_ATTR_CLEAR | RF1_CHAR_CLEAR))) + { + /* Use char */ + *cp = c; + + /* Use attr */ + *ap = a; + } + + /* Hack -- Bizarre grid under monster */ + else if ((*ap & 0x80) || (*cp & 0x80)) + { + /* Use char */ + *cp = c; + + /* Use attr */ + *ap = a; + } + + /* Normal */ + else + { + /* Normal (non-clear char) monster */ + if (!(r_ptr->flags1 & (RF1_CHAR_CLEAR))) + { + /* Normal char */ + *cp = c; + } + + /* Normal (non-clear attr) monster */ + else if (!(r_ptr->flags1 & (RF1_ATTR_CLEAR))) + { + /* Normal attr */ + *ap = a; + } + } + + /* Hack -- hallucination */ + if (p_ptr->image) + { + /* Hallucinatory monster */ + image_monster(ap, cp); + } + } + } + } + + + /* Handle "player" */ + if ((y == p_ptr->py) && (x == p_ptr->px) && + (!p_ptr->invis || + (p_ptr->invis && p_ptr->see_inv))) + { + monster_race *r_ptr = &r_info[p_ptr->body_monster]; + + /* Get the "player" attr */ + if (!avoid_other && (r_ptr->flags1 & RF1_ATTR_MULTI)) + { + a = get_shimmer_color(); + } + else + { + a = r_ptr->d_attr; + } + + /* Get the "player" char */ + c = r_ptr->d_char; + + /* Save the info */ + *ap = a; + *cp = c; + + } + + /* XXX Restore the graphics mode */ + use_graphics = use_graphics_hack; + graphics_mode = graphics_mode_hack; +} + + +/* + * Calculate panel colum of a location in the map + */ +static int panel_col_of(int col) +{ + col -= panel_col_min; + if (use_bigtile) col *= 2; + return col + COL_MAP; +} + + + +/* + * Moves the cursor to a given MAP (y,x) location + */ +void move_cursor_relative(int row, int col) +{ + /* Real co-ords convert to screen positions */ + row -= panel_row_prt; + + /* Go there */ + Term_gotoxy(panel_col_of(col), row); +} + + + +/* + * Place an attr/char pair at the given map coordinate, if legal. + */ +void print_rel(char c, byte a, int y, int x) +{ + /* Paranoia -- Only do "legal" locations */ + if (!panel_contains(y, x)) return; + + /* Draw the char using the attr */ + Term_draw(panel_col_of(x), y - panel_row_prt, a, c); + + if (use_bigtile) + { + char c2; + byte a2; + + if (a & 0x80) + { + a2 = 255; + c2 = 255; + } + else + { + a2 = TERM_WHITE; + c2 = ' '; + } + Term_draw(panel_col_of(x) + 1, y - panel_row_prt, a2, c2); + } +} + + + + + +/* + * Memorize interesting viewable object/features in the given grid + * + * This function should only be called on "legal" grids. + * + * This function will memorize the object and/or feature in the given + * grid, if they are (1) viewable and (2) interesting. Note that all + * objects are interesting, all terrain features except floors (and + * invisible traps) are interesting, and floors (and invisible traps) + * are interesting sometimes (depending on various options involving + * the illumination of floor grids). + * + * The automatic memorization of all objects and non-floor terrain + * features as soon as they are displayed allows incredible amounts + * of optimization in various places, especially "map_info()". + * + * Note that the memorization of objects is completely separate from + * the memorization of terrain features, preventing annoying floor + * memorization when a detected object is picked up from a dark floor, + * and object memorization when an object is dropped into a floor grid + * which is memorized but out-of-sight. + * + * This function should be called every time the "memorization" of + * a grid (or the object in a grid) is called into question, such + * as when an object is created in a grid, when a terrain feature + * "changes" from "floor" to "non-floor", when any grid becomes + * "illuminated" or "viewable", and when a "floor" grid becomes + * "torch-lit". + * + * Note the relatively efficient use of this function by the various + * "update_view()" and "update_lite()" calls, to allow objects and + * terrain features to be memorized (and drawn) whenever they become + * viewable or illuminated in any way, but not when they "maintain" + * or "lose" their previous viewability or illumination. + * + * Note the butchered "internal" version of "player_can_see_bold()", + * optimized primarily for the most common cases, that is, for the + * non-marked floor grids. + */ +void note_spot(int y, int x) +{ + cave_type *c_ptr = &cave[y][x]; + + u16b info = c_ptr->info; + + s16b this_o_idx, next_o_idx = 0; + + + /* Require "seen" flag */ + if (!(info & (CAVE_SEEN))) return; + + + /* Hack -- memorize objects */ + for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) + { + object_type * o_ptr = &o_list[this_o_idx]; + + /* Acquire next object */ + next_o_idx = o_ptr->next_o_idx; + + /* Memorize objects */ + o_ptr->marked = TRUE; + } + + if (c_ptr->m_idx) + { + monster_type *m_ptr = &m_list[c_ptr->m_idx]; + monster_race *r_ptr = race_inf(m_ptr); + + if (r_ptr->flags9 & RF9_MIMIC) + { + object_type *o_ptr = &o_list[m_ptr->hold_o_idx]; + + o_ptr->marked = TRUE; + } + } + + + /* Hack -- memorize grids */ + if (!(info & (CAVE_MARK))) + { + /* Memorise some "boring" grids */ + if (cave_plain_floor_grid(c_ptr)) + { + /* Option -- memorise certain floors */ + if ((info & (CAVE_TRDT)) || + ((info & (CAVE_GLOW)) && view_perma_grids ) || + view_torch_grids) + { + /* Memorize */ + c_ptr->info |= (CAVE_MARK); + } + } + + /* Memorise all "interesting" grids */ + else + { + /* Memorize */ + c_ptr->info |= (CAVE_MARK); + } + } +} + + +/* + * Redraw (on the screen) a given MAP location + * + * This function should only be called on "legal" grids + */ +void lite_spot(int y, int x) +{ + byte a, a2; + byte c, c2; + + byte ta; + char tc; + + byte ea; + char ec; + + + /* Redraw if on screen */ + if (panel_contains(y, x)) + { + /* Examine the grid */ + map_info(y, x, &a, (char*)&c, &ta, &tc, &ea, &ec); + + /* Hack -- Queue it */ + Term_queue_char(panel_col_of(x), y - panel_row_prt, a, c, ta, tc, ea, ec); + if (use_bigtile) + { + if (a & 0x80) + { + a2 = 255; + c2 = 255; + } + else + { + a2 = TERM_WHITE; + c2 = ' '; + } + Term_queue_char(panel_col_of(x) + 1, y - panel_row_prt, a2, c2, 0, 0, 0, 0); + } + + } +} + + + + +/* + * Prints the map of the dungeon + * + * Note that, for efficiency, we contain an "optimized" version + * of both "lite_spot()" and "print_rel()", and that we use the + * "lite_spot()" function to display the player grid, if needed. + */ +void prt_map(void) +{ + int x, y; + + int v; + + /* Access the cursor state */ + (void)Term_get_cursor(&v); + + /* Hide the cursor */ + (void)Term_set_cursor(0); + + /* Dump the map */ + for (y = panel_row_min; y <= panel_row_max; y++) + { + /* Scan the columns of row "y" */ + for (x = panel_col_min; x <= panel_col_max; x++) + { + byte a, a2; + char c, c2; + + byte ta; + char tc; + byte ea; + char ec; + + /* Determine what is there */ + map_info(y, x, &a, &c, &ta, &tc, &ea, &ec); + + /* Efficiency -- Redraw that grid of the map */ + Term_queue_char(panel_col_of(x), y - panel_row_prt, a, c, ta, tc, ea, ec); + if (use_bigtile) + { + if (a & 0x80) + { + a2 = 255; + c2 = 255; + } + else + { + a2 = TERM_WHITE; + c2 = ' '; + } + Term_queue_char(panel_col_of(x) + 1, y - panel_row_prt, a2, c2, 0, 0, 0, 0); + } + } + } + + /* Display player */ + lite_spot(p_ptr->py, p_ptr->px); + + /* Restore the cursor */ + (void)Term_set_cursor(v); +} + + + + + +/* + * Display highest priority object in the RATIO by RATIO area + */ + +/* + * Display the entire map + */ +#define MAP_HGT (MAX_HGT / RATIO) +#define MAP_WID (MAX_WID / RATIO) + +/* + * Hack -- priority array (see below) + * + * Note that all "walls" always look like "secret doors" (see "map_info()"). + */ +static byte priority_table[][2] = +{ + /* Dark */ + { FEAT_NONE, 2 }, + + /* Floors */ + { FEAT_FLOOR, 5 }, + + /* Walls */ + { FEAT_SECRET, 10 }, + + /* Quartz */ + { FEAT_QUARTZ, 11 }, + + /* Magma */ + { FEAT_MAGMA, 12 }, + + /* Rubble */ + { FEAT_RUBBLE, 13 }, + + /* Sandwall */ + { FEAT_SANDWALL, 14 }, + + /* Open doors */ + { FEAT_OPEN, 15 }, + { FEAT_BROKEN, 15 }, + + /* Closed doors */ + { FEAT_DOOR_HEAD + 0x00, 17 }, + + /* Hidden gold */ + { FEAT_QUARTZ_K, 19 }, + { FEAT_MAGMA_K, 19 }, + { FEAT_SANDWALL_K, 19 }, + + /* water, lava, & trees oh my! -KMW- */ + { FEAT_DEEP_WATER, 20 }, + { FEAT_SHAL_WATER, 20 }, + { FEAT_DEEP_LAVA, 20 }, + { FEAT_SHAL_LAVA, 20 }, + { FEAT_DIRT, 20 }, + { FEAT_GRASS, 20 }, + { FEAT_DARK_PIT, 20 }, + { FEAT_TREES, 20 }, + { FEAT_MOUNTAIN, 20 }, + { FEAT_ICE, 20}, + { FEAT_SAND, 20}, + { FEAT_DEAD_TREE, 20}, + { FEAT_ASH, 20}, + { FEAT_MUD, 20}, + + /* Fountain */ + { FEAT_FOUNTAIN, 22 }, + { FEAT_EMPTY_FOUNTAIN, 22 }, + + /* Stairs */ + { FEAT_LESS, 25 }, + { FEAT_MORE, 25 }, + + /* Stairs */ + { FEAT_WAY_LESS, 25 }, + { FEAT_WAY_MORE, 25 }, + + { FEAT_SHAFT_UP, 25 }, + { FEAT_SHAFT_DOWN, 25 }, + + /* End */ + { 0, 0 } +}; + + +/* + * Hack -- a priority function (see below) + */ +static byte priority(byte a, char c) +{ + int i, p0, p1; + + feature_type *f_ptr; + + /* Scan the table */ + for (i = 0; TRUE; i++) + { + /* Priority level */ + p1 = priority_table[i][1]; + + /* End of table */ + if (!p1) break; + + /* Feature index */ + p0 = priority_table[i][0]; + + /* Access the feature */ + f_ptr = &f_info[p0]; + + /* Check character and attribute, accept matches */ + if ((f_ptr->x_char == c) && (f_ptr->x_attr == a)) return (p1); + } + + /* Default */ + return (20); +} + + +/* + * Display a "small-scale" map of the dungeon in the active Term + * + * Note that the "map_info()" function must return fully colorized + * data or this function will not work correctly. + * + * Note that this function must "disable" the special lighting + * effects so that the "priority" function will work. + * + * Note the use of a specialized "priority" function to allow this + * function to work with any graphic attr/char mappings, and the + * attempts to optimize this function where possible. + */ +void display_map(int *cy, int *cx) +{ + int i, j, x, y; + + byte ta; + char tc; + + byte tp; + + bool_ old_view_special_lite; + bool_ old_view_granite_lite; + + int hgt, wid, yrat, xrat, yfactor, xfactor; + + + /* Obtain current size of the Angband window */ + Term_get_size(&wid, &hgt); + + /* Use two characters as one tile in Bigtile mode */ + if (use_bigtile) wid /= 2; + + /* + * Calculate the size of the dungeon map area + */ + hgt -= ROW_MAP + 2; + wid -= COL_MAP + 1; + + /* Paranoia */ + if ((hgt < 3) || (wid < 3)) + { + /* Map is too small, but place the player anyway */ + *cy = ROW_MAP; + *cx = COL_MAP; + + return; + } + + + /* Save lighting effects */ + old_view_special_lite = view_special_lite; + old_view_granite_lite = view_granite_lite; + + /* Disable lighting effects */ + view_special_lite = FALSE; + view_granite_lite = FALSE; + + + /* Set up initial maps */ + std::vector> ma; + std::vector> mc; + std::vector> mp; + for (i = 0; i < hgt + 2; i++) + { + // Nothing there. + ma.push_back(std::vector(wid + 2, TERM_WHITE)); + mc.push_back(std::vector(wid + 2, ' ')); + + // No priority. + mp.push_back(std::vector(wid + 2, 0)); + } + assert(ma.size() == hgt + 2); + assert(mc.size() == hgt + 2); + assert(mp.size() == hgt + 2); + + /* Calculate scaling factors */ + yfactor = ((cur_hgt / hgt < 4) && (cur_hgt > hgt)) ? 10 : 1; + xfactor = ((cur_wid / wid < 4) && (cur_wid > wid)) ? 10 : 1; + + yrat = (cur_hgt * yfactor + (hgt - 1)) / hgt; + xrat = (cur_wid * xfactor + (wid - 1)) / wid; + + /* Fill in the map */ + for (j = 0; j < cur_hgt; ++j) + { + for (i = 0; i < cur_wid; ++i) + { + /* Location */ + y = j * yfactor / yrat + 1; + x = i * xfactor / xrat + 1; + + /* Extract the current attr/char at that map location */ + map_info(j, i, &ta, &tc, &ta, &tc, &ta, &tc); + + /* Extract the priority of that attr/char */ + tp = priority(ta, tc); + + /* Player location has the highest priority */ + if ((p_ptr->py == j) && (p_ptr->px == i)) tp = 255; + + /* Save "best" */ + if (mp[y][x] < tp) + { + /* Save the char */ + mc[y][x] = tc; + + /* Save the attr */ + ma[y][x] = ta; + + /* Save priority */ + mp[y][x] = tp; + } + } + } + + + /* Corners */ + y = hgt + 1; + x = wid + 1; + + /* Draw the corners */ + mc[0][0] = mc[0][x] = mc[y][0] = mc[y][x] = '+'; + + /* Draw the horizontal edges */ + for (x = 1; x <= wid; x++) mc[0][x] = mc[y][x] = '-'; + + /* Draw the vertical edges */ + for (y = 1; y <= hgt; y++) mc[y][0] = mc[y][x] = '|'; + + + /* Display each map line in order */ + for (y = 0; y < hgt + 2; ++y) + { + /* Start a new line */ + Term_gotoxy(COL_MAP - 1, y); + + /* Display the line */ + for (x = 0; x < wid + 2; ++x) + { + ta = ma[y][x]; + tc = mc[y][x]; + + /* Add the character */ + Term_addch(ta, tc); + + /* Double width tile mode requires filler */ + if (use_bigtile) + { + byte a2; + char c2; + + if (ta & 0x80) + { + /* Mega-Hack */ + a2 = 255; + c2 = 255; + } + else + { + a2 = TERM_WHITE; + c2 = ' '; + } + + Term_addch(a2, c2); + } + } + } + + /* Player location in dungeon */ + *cy = p_ptr->py * yfactor / yrat + ROW_MAP; + if (!use_bigtile) + { + *cx = p_ptr->px * xfactor / xrat + COL_MAP; + } + else + { + *cx = (p_ptr->px * xfactor / xrat + 1) * 2 - 1 + COL_MAP; + } + + /* Restore lighting effects */ + view_special_lite = old_view_special_lite; + view_granite_lite = old_view_granite_lite; +} + + +/* + * Display a "small-scale" map of the dungeon for the player + * + * Currently, the "player" is displayed on the map. XXX XXX XXX + */ +void do_cmd_view_map(void) +{ + int cy, cx; + int wid, hgt; + + /* Retrive current screen size */ + Term_get_size(&wid, &hgt); + + /* Enter "icky" mode */ + character_icky = TRUE; + + /* Save the screen */ + Term_save(); + + /* Note */ + prt("Please wait...", 0, 0); + + /* Flush */ + Term_fresh(); + + /* Clear the screen */ + Term_clear(); + + /* Display the map */ + display_map(&cy, &cx); + + /* Wait for it */ + put_str("Hit any key to continue", hgt - 1, (wid - COL_MAP) / 2); + + /* Hilite the player */ + move_cursor(cy, cx); + + /* Get any key */ + inkey(); + + /* Restore the screen */ + Term_load(); + + /* Leave "icky" mode */ + character_icky = FALSE; +} + + + + + + +/* + * Some comments on the dungeon related data structures and functions... + * + * Angband is primarily a dungeon exploration game, and it should come as + * no surprise that the internal representation of the dungeon has evolved + * over time in much the same way as the game itself, to provide semantic + * changes to the game itself, to make the code simpler to understand, and + * to make the executable itself faster or more efficient in various ways. + * + * There are a variety of dungeon related data structures, and associated + * functions, which store information about the dungeon, and provide methods + * by which this information can be accessed or modified. + * + * Some of this information applies to the dungeon as a whole, such as the + * list of unique monsters which are still alive. Some of this information + * only applies to the current dungeon level, such as the current depth, or + * the list of monsters currently inhabiting the level. And some of the + * information only applies to a single grid of the current dungeon level, + * such as whether the grid is illuminated, or whether the grid contains a + * monster, or whether the grid can be seen by the player. If Angband was + * to be turned into a multi-player game, some of the information currently + * associated with the dungeon should really be associated with the player, + * such as whether a given grid is viewable by a given player. + * + * One of the major bottlenecks in ancient versions of Angband was in the + * calculation of "line of sight" from the player to various grids, such + * as those containing monsters, using the relatively expensive "los()" + * function. This was such a nasty bottleneck that a lot of silly things + * were done to reduce the dependancy on "line of sight", for example, you + * could not "see" any grids in a lit room until you actually entered the + * room, at which point every grid in the room became "illuminated" and + * all of the grids in the room were "memorized" forever. Other major + * bottlenecks involved the determination of whether a grid was lit by the + * player's torch, and whether a grid blocked the player's line of sight. + * These bottlenecks led to the development of special new functions to + * optimize issues involved with "line of sight" and "torch lit grids". + * These optimizations led to entirely new additions to the game, such as + * the ability to display the player's entire field of view using different + * colors than were used for the "memorized" portions of the dungeon, and + * the ability to memorize dark floor grids, but to indicate by the way in + * which they are displayed that they are not actually illuminated. And + * of course many of them simply made the game itself faster or more fun. + * Also, over time, the definition of "line of sight" has been relaxed to + * allow the player to see a wider "field of view", which is slightly more + * realistic, and only slightly more expensive to maintain. + * + * Currently, a lot of the information about the dungeon is stored in ways + * that make it very efficient to access or modify the information, while + * still attempting to be relatively conservative about memory usage, even + * if this means that some information is stored in multiple places, or in + * ways which require the use of special code idioms. For example, each + * monster record in the monster array contains the location of the monster, + * and each cave grid has an index into the monster array, or a zero if no + * monster is in the grid. This allows the monster code to efficiently see + * where the monster is located, while allowing the dungeon code to quickly + * determine not only if a monster is present in a given grid, but also to + * find out which monster. The extra space used to store the information + * twice is inconsequential compared to the speed increase. + * + * Some of the information about the dungeon is used by functions which can + * constitute the "critical efficiency path" of the game itself, and so the + * way in which they are stored and accessed has been optimized in order to + * optimize the game itself. For example, the "update_view()" function was + * originally created to speed up the game itself (when the player was not + * running), but then it took on extra responsibility as the provider of the + * new "special effects lighting code", and became one of the most important + * bottlenecks when the player was running. So many rounds of optimization + * were performed on both the function itself, and the data structures which + * it uses, resulting eventually in a function which not only made the game + * faster than before, but which was responsible for even more calculations + * (including the determination of which grids are "viewable" by the player, + * which grids are illuminated by the player's torch, and which grids can be + * "seen" in some way by the player), as well as for providing the guts of + * the special effects lighting code, and for the efficient redisplay of any + * grids whose visual representation may have changed. + * + * Several pieces of information about each cave grid are stored in various + * two dimensional arrays, with one unit of information for each grid in the + * dungeon. Some of these arrays have been intentionally expanded by a small + * factor to make the two dimensional array accesses faster by allowing the + * use of shifting instead of multiplication. + * + * Several pieces of information about each cave grid are stored in the + * "cave_info" array, which is a special two dimensional array of bytes, + * one for each cave grid, each containing eight separate "flags" which + * describe some property of the cave grid. These flags can be checked and + * modified extremely quickly, especially when special idioms are used to + * force the compiler to keep a local register pointing to the base of the + * array. Special location offset macros can be used to minimize the number + * of computations which must be performed at runtime. Note that using a + * byte for each flag set may be slightly more efficient than using a larger + * unit, so if another flag (or two) is needed later, and it must be fast, + * then the two existing flags which do not have to be fast should be moved + * out into some other data structure and the new flags should take their + * place. This may require a few minor changes in the savefile code. + * + * The "CAVE_ROOM" flag is saved in the savefile and is used to determine + * which grids are part of "rooms", and thus which grids are affected by + * "illumination" spells. This flag does not have to be very fast. + * + * The "CAVE_ICKY" flag is saved in the savefile and is used to determine + * which grids are part of "vaults", and thus which grids cannot serve as + * the destinations of player teleportation. This flag does not have to + * be very fast. + * + * The "CAVE_MARK" flag is saved in the savefile and is used to determine + * which grids have been "memorized" by the player. This flag is used by + * the "map_info()" function to determine if a grid should be displayed. + * This flag is used in a few other places to determine if the player can + * "know" about a given grid. This flag must be very fast. + * + * The "CAVE_GLOW" flag is saved in the savefile and is used to determine + * which grids are "permanently illuminated". This flag is used by the + * "update_view()" function to help determine which viewable flags may + * be "seen" by the player. This flag is used by the "map_info" function + * to determine if a grid is only lit by the player's torch. This flag + * has special semantics for wall grids (see "update_view()"). This flag + * must be very fast. + * + * The "CAVE_WALL" flag is used to determine which grids block the player's + * line of sight. This flag is used by the "update_view()" function to + * determine which grids block line of sight, and to help determine which + * grids can be "seen" by the player. This flag must be very fast. + * + * The "CAVE_VIEW" flag is used to determine which grids are currently in + * line of sight of the player. This flag is set by (and used by) the + * "update_view()" function. This flag is used by any code which needs to + * know if the player can "view" a given grid. This flag is used by the + * "map_info()" function for some optional special lighting effects. The + * "player_has_los_bold()" macro wraps an abstraction around this flag, but + * certain code idioms are much more efficient. This flag is used to check + * if a modification to a terrain feature might affect the player's field of + * view. This flag is used to see if certain monsters are "visible" to the + * player. This flag is used to allow any monster in the player's field of + * view to "sense" the presence of the player. This flag must be very fast. + * + * The "CAVE_SEEN" flag is used to determine which grids are currently in + * line of sight of the player and also illuminated in some way. This flag + * is set by the "update_view()" function, using computations based on the + * "CAVE_VIEW" and "CAVE_WALL" and "CAVE_GLOW" flags of various grids. This + * flag is used by any code which needs to know if the player can "see" a + * given grid. This flag is used by the "map_info()" function both to see + * if a given "boring" grid can be seen by the player, and for some optional + * special lighting effects. The "player_can_see_bold()" macro wraps an + * abstraction around this flag, but certain code idioms are much more + * efficient. This flag is used to see if certain monsters are "visible" to + * the player. This flag is never set for a grid unless "CAVE_VIEW" is also + * set for the grid. Whenever the "CAVE_WALL" or "CAVE_GLOW" flag changes + * for a grid which has the "CAVE_VIEW" flag set, the "CAVE_SEEN" flag must + * be recalculated. The simplest way to do this is to call "forget_view()" + * and "update_view()" whenever the "CAVE_WALL" or "CAVE_GLOW" flags change + * for a grid which has "CAVE_VIEW" set. This flag must be very fast. + * + * The "CAVE_TEMP" flag is used for a variety of temporary purposes. This + * flag is used to determine if the "CAVE_SEEN" flag for a grid has changed + * during the "update_view()" function. This flag is used to "spread" light + * or darkness through a room. This flag is used by the "monster flow code". + * This flag must always be cleared by any code which sets it, often, this + * can be optimized by the use of the special "temp_g", "temp_y", "temp_x" + * arrays (and the special "temp_n" global). This flag must be very fast. + * + * Note that the "CAVE_MARK" flag is used for many reasons, some of which + * are strictly for optimization purposes. The "CAVE_MARK" flag means that + * even if the player cannot "see" the grid, he "knows" about the terrain in + * that grid. This is used to "memorize" grids when they are first "seen" by + * the player, and to allow certain grids to be "detected" by certain magic. + * Note that most grids are always memorized when they are first "seen", but + * "boring" grids (floor grids) are only memorized if the "view_torch_grids" + * option is set, or if the "view_perma_grids" option is set, and the grid + * in question has the "CAVE_GLOW" flag set. + * + * Objects are "memorized" in a different way, using a special "marked" flag + * on the object itself, which is set when an object is observed or detected. + * This allows objects to be "memorized" independant of the terrain features. + * + * The "update_view()" function is an extremely important function. It is + * called only when the player moves, significant terrain changes, or the + * player's blindness or torch radius changes. Note that when the player + * is resting, or performing any repeated actions (like digging, disarming, + * farming, etc), there is no need to call the "update_view()" function, so + * even if it was not very efficient, this would really only matter when the + * player was "running" through the dungeon. It sets the "CAVE_VIEW" flag + * on every cave grid in the player's field of view, and maintains an array + * of all such grids in the global "view_g" array. It also checks the torch + * radius of the player, and sets the "CAVE_SEEN" flag for every grid which + * is in the "field of view" of the player and which is also "illuminated", + * either by the players torch (if any) or by any permanent light source. + * It could use and help maintain information about multiple light sources, + * which would be helpful in a multi-player version of Angband. + * + * The "update_view()" function maintains the special "view_g" array, which + * contains exactly those grids which have the "CAVE_VIEW" flag set. This + * array is used by "update_view()" to (only) memorize grids which become + * newly "seen", and to (only) redraw grids whose "seen" value changes, which + * allows the use of some interesting (and very efficient) "special lighting + * effects". In addition, this array could be used elsewhere to quickly scan + * through all the grids which are in the player's field of view. + * + * Note that the "update_view()" function allows, among other things, a room + * to be "partially" seen as the player approaches it, with a growing cone + * of floor appearing as the player gets closer to the door. Also, by not + * turning on the "memorize perma-lit grids" option, the player will only + * "see" those floor grids which are actually in line of sight. And best + * of all, you can now activate the special lighting effects to indicate + * which grids are actually in the player's field of view by using dimmer + * colors for grids which are not in the player's field of view, and/or to + * indicate which grids are illuminated only by the player's torch by using + * the color yellow for those grids. + * + * The old "update_view()" algorithm uses the special "CAVE_EASY" flag as a + * temporary internal flag to mark those grids which are not only in view, + * but which are also "easily" in line of sight of the player. This flag + * is actually just the "CAVE_SEEN" flag, and the "update_view()" function + * makes sure to clear it for all old "CAVE_SEEN" grids, and then use it in + * the algorithm as "CAVE_EASY", and then clear it for all "CAVE_EASY" grids, + * and then reset it as appropriate for all new "CAVE_SEEN" grids. This is + * kind of messy, but it works. The old algorithm may disappear eventually. + * + * The new "update_view()" algorithm uses a faster and more mathematically + * correct algorithm, assisted by a large machine generated static array, to + * determine the "CAVE_VIEW" and "CAVE_SEEN" flags simultaneously. See below. + * + * It seems as though slight modifications to the "update_view()" functions + * would allow us to determine "reverse" line-of-sight as well as "normal" + * line-of-sight", which would allow monsters to have a more "correct" way + * to determine if they can "see" the player, since right now, they "cheat" + * somewhat and assume that if the player has "line of sight" to them, then + * they can "pretend" that they have "line of sight" to the player. But if + * such a change was attempted, the monsters would actually start to exhibit + * some undesirable behavior, such as "freezing" near the entrances to long + * hallways containing the player, and code would have to be added to make + * the monsters move around even if the player was not detectable, and to + * "remember" where the player was last seen, to avoid looking stupid. + * + * Note that the "CAVE_GLOW" flag means that a grid is permanently lit in + * some way. However, for the player to "see" the grid, as determined by + * the "CAVE_SEEN" flag, the player must not be blind, the grid must have + * the "CAVE_VIEW" flag set, and if the grid is a "wall" grid, and it is + * not lit by the player's torch, then it must touch a grid which does not + * have the "CAVE_WALL" flag set, but which does have both the "CAVE_GLOW" + * and "CAVE_VIEW" flags set. This last part about wall grids is induced + * by the semantics of "CAVE_GLOW" as applied to wall grids, and checking + * the technical requirements can be very expensive, especially since the + * grid may be touching some "illegal" grids. Luckily, it is more or less + * correct to restrict the "touching" grids from the eight "possible" grids + * to the (at most) three grids which are touching the grid, and which are + * closer to the player than the grid itself, which eliminates more than + * half of the work, including all of the potentially "illegal" grids, if + * at most one of the three grids is a "diagonal" grid. In addition, in + * almost every situation, it is possible to ignore the "CAVE_VIEW" flag + * on these three "touching" grids, for a variety of technical reasons. + * Finally, note that in most situations, it is only necessary to check + * a single "touching" grid, in fact, the grid which is strictly closest + * to the player of all the touching grids, and in fact, it is normally + * only necessary to check the "CAVE_GLOW" flag of that grid, again, for + * various technical reasons. However, one of the situations which does + * not work with this last reduction is the very common one in which the + * player approaches an illuminated room from a dark hallway, in which the + * two wall grids which form the "entrance" to the room would not be marked + * as "CAVE_SEEN", since of the three "touching" grids nearer to the player + * than each wall grid, only the farthest of these grids is itself marked + * "CAVE_GLOW". + * + * + * Here are some pictures of the legal "light source" radius values, in + * which the numbers indicate the "order" in which the grids could have + * been calculated, if desired. Note that the code will work with larger + * radiuses, though currently yields such a radius, and the game would + * become slower in some situations if it did. + * + * Rad=0 Rad=1 Rad=2 Rad=3 + * No-Lite Torch,etc Lantern Artifacts + * + * 333 + * 333 43334 + * 212 32123 3321233 + * @ 1@1 31@13 331@133 + * 212 32123 3321233 + * 333 43334 + * 333 + * + * + * Here is an illustration of the two different "update_view()" algorithms, + * in which the grids marked "%" are pillars, and the grids marked "?" are + * not in line of sight of the player. + * + * + * Sample situation + * + * ##################### + * ############.%.%.%.%# + * #...@..#####........# + * #............%.%.%.%# + * #......#####........# + * ############........# + * ##################### + * + * + * New Algorithm Old Algorithm + * + * ########????????????? ########????????????? + * #...@..#????????????? #...@..#????????????? + * #...........????????? #.........??????????? + * #......#####.....???? #......####?????????? + * ########?????????...# ########????????????? + * + * ########????????????? ########????????????? + * #.@....#????????????? #.@....#????????????? + * #............%??????? #...........????????? + * #......#####........? #......#####????????? + * ########??????????..# ########????????????? + * + * ########????????????? ########?????%??????? + * #......#####........# #......#####..??????? + * #.@..........%??????? #.@..........%??????? + * #......#####........# #......#####..??????? + * ########????????????? ########????????????? + * + * ########??????????..# ########????????????? + * #......#####........? #......#####????????? + * #............%??????? #...........????????? + * #.@....#????????????? #.@....#????????????? + * ########????????????? ########????????????? + * + * ########?????????%??? ########????????????? + * #......#####.....???? #......####?????????? + * #...........????????? #.........??????????? + * #...@..#????????????? #...@..#????????????? + * ########????????????? ########????????????? + */ + + + + +/* + * Maximum number of grids in a single octant + */ +#define VINFO_MAX_GRIDS 161 + + +/* + * Maximum number of slopes in a single octant + */ +#define VINFO_MAX_SLOPES 126 + + +/* + * Mask of bits used in a single octant + */ +#define VINFO_BITS_3 0x3FFFFFFF +#define VINFO_BITS_2 0xFFFFFFFF +#define VINFO_BITS_1 0xFFFFFFFF +#define VINFO_BITS_0 0xFFFFFFFF + + +/* + * Forward declare + */ +typedef struct vinfo_type vinfo_type; + + +/* + * The 'vinfo_type' structure + */ +struct vinfo_type +{ + s16b grid_y[8]; + s16b grid_x[8]; + + u32b bits_3; + u32b bits_2; + u32b bits_1; + u32b bits_0; + + vinfo_type *next_0; + vinfo_type *next_1; + + byte y; + byte x; + byte d; + byte r; +}; + + + +/* + * The array of "vinfo" objects, initialized by "vinfo_init()" + */ +static vinfo_type vinfo[VINFO_MAX_GRIDS]; + + + + +/* + * Slope scale factor + */ +#define SCALE 100000L + + +/* + * The actual slopes (for reference) + */ + +/* Bit : Slope Grids */ +/* --- : ----- ----- */ +/* 0 : 2439 21 */ +/* 1 : 2564 21 */ +/* 2 : 2702 21 */ +/* 3 : 2857 21 */ +/* 4 : 3030 21 */ +/* 5 : 3225 21 */ +/* 6 : 3448 21 */ +/* 7 : 3703 21 */ +/* 8 : 4000 21 */ +/* 9 : 4347 21 */ +/* 10 : 4761 21 */ +/* 11 : 5263 21 */ +/* 12 : 5882 21 */ +/* 13 : 6666 21 */ +/* 14 : 7317 22 */ +/* 15 : 7692 20 */ +/* 16 : 8108 21 */ +/* 17 : 8571 21 */ +/* 18 : 9090 20 */ +/* 19 : 9677 21 */ +/* 20 : 10344 21 */ +/* 21 : 11111 20 */ +/* 22 : 12000 21 */ +/* 23 : 12820 22 */ +/* 24 : 13043 22 */ +/* 25 : 13513 22 */ +/* 26 : 14285 20 */ +/* 27 : 15151 22 */ +/* 28 : 15789 22 */ +/* 29 : 16129 22 */ +/* 30 : 17241 22 */ +/* 31 : 17647 22 */ +/* 32 : 17948 23 */ +/* 33 : 18518 22 */ +/* 34 : 18918 22 */ +/* 35 : 20000 19 */ +/* 36 : 21212 22 */ +/* 37 : 21739 22 */ +/* 38 : 22580 22 */ +/* 39 : 23076 22 */ +/* 40 : 23809 22 */ +/* 41 : 24137 22 */ +/* 42 : 24324 23 */ +/* 43 : 25714 23 */ +/* 44 : 25925 23 */ +/* 45 : 26315 23 */ +/* 46 : 27272 22 */ +/* 47 : 28000 23 */ +/* 48 : 29032 23 */ +/* 49 : 29411 23 */ +/* 50 : 29729 24 */ +/* 51 : 30434 23 */ +/* 52 : 31034 23 */ +/* 53 : 31428 23 */ +/* 54 : 33333 18 */ +/* 55 : 35483 23 */ +/* 56 : 36000 23 */ +/* 57 : 36842 23 */ +/* 58 : 37142 24 */ +/* 59 : 37931 24 */ +/* 60 : 38461 24 */ +/* 61 : 39130 24 */ +/* 62 : 39393 24 */ +/* 63 : 40740 24 */ +/* 64 : 41176 24 */ +/* 65 : 41935 24 */ +/* 66 : 42857 23 */ +/* 67 : 44000 24 */ +/* 68 : 44827 24 */ +/* 69 : 45454 23 */ +/* 70 : 46666 24 */ +/* 71 : 47368 24 */ +/* 72 : 47826 24 */ +/* 73 : 48148 24 */ +/* 74 : 48387 24 */ +/* 75 : 51515 25 */ +/* 76 : 51724 25 */ +/* 77 : 52000 25 */ +/* 78 : 52380 25 */ +/* 79 : 52941 25 */ +/* 80 : 53846 25 */ +/* 81 : 54838 25 */ +/* 82 : 55555 24 */ +/* 83 : 56521 25 */ +/* 84 : 57575 26 */ +/* 85 : 57894 25 */ +/* 86 : 58620 25 */ +/* 87 : 60000 23 */ +/* 88 : 61290 25 */ +/* 89 : 61904 25 */ +/* 90 : 62962 25 */ +/* 91 : 63636 25 */ +/* 92 : 64705 25 */ +/* 93 : 65217 25 */ +/* 94 : 65517 25 */ +/* 95 : 67741 26 */ +/* 96 : 68000 26 */ +/* 97 : 68421 26 */ +/* 98 : 69230 26 */ +/* 99 : 70370 26 */ +/* 100 : 71428 25 */ +/* 101 : 72413 26 */ +/* 102 : 73333 26 */ +/* 103 : 73913 26 */ +/* 104 : 74193 27 */ +/* 105 : 76000 26 */ +/* 106 : 76470 26 */ +/* 107 : 77777 25 */ +/* 108 : 78947 26 */ +/* 109 : 79310 26 */ +/* 110 : 80952 26 */ +/* 111 : 81818 26 */ +/* 112 : 82608 26 */ +/* 113 : 84000 26 */ +/* 114 : 84615 26 */ +/* 115 : 85185 26 */ +/* 116 : 86206 27 */ +/* 117 : 86666 27 */ +/* 118 : 88235 27 */ +/* 119 : 89473 27 */ +/* 120 : 90476 27 */ +/* 121 : 91304 27 */ +/* 122 : 92000 27 */ +/* 123 : 92592 27 */ +/* 124 : 93103 28 */ +/* 125 : 100000 13 */ + + + +/* + * Forward declare + */ +typedef struct vinfo_hack vinfo_hack; + + +/* + * Temporary data used by "vinfo_init()" + * + * - Number of grids + * + * - Number of slopes + * + * - Slope values + * + * - Slope range per grid + */ +struct vinfo_hack +{ + + int num_slopes; + + long slopes[VINFO_MAX_SLOPES]; + + long slopes_min[MAX_SIGHT + 1][MAX_SIGHT + 1]; + long slopes_max[MAX_SIGHT + 1][MAX_SIGHT + 1]; +}; + + + +/* + * Save a slope + */ +static void vinfo_init_aux(vinfo_hack *hack, int y, int x, long m) +{ + int i; + + /* Handle "legal" slopes */ + if ((m > 0) && (m <= SCALE)) + { + /* Look for that slope */ + for (i = 0; i < hack->num_slopes; i++) + { + if (hack->slopes[i] == m) break; + } + + /* New slope */ + if (i == hack->num_slopes) + { + /* Paranoia */ + if (hack->num_slopes >= VINFO_MAX_SLOPES) + { + quit_fmt("Too many slopes (%d)!", + VINFO_MAX_SLOPES); + } + + /* Save the slope, and advance */ + hack->slopes[hack->num_slopes++] = m; + } + } + + /* Track slope range */ + if (hack->slopes_min[y][x] > m) hack->slopes_min[y][x] = m; + if (hack->slopes_max[y][x] < m) hack->slopes_max[y][x] = m; +} + + + +/* + * Initialize the "vinfo" array + * + * Full Octagon (radius 20), Grids=1149 + * + * Quadrant (south east), Grids=308, Slopes=251 + * + * Octant (east then south), Grids=161, Slopes=126 + * + * This function assumes that VINFO_MAX_GRIDS and VINFO_MAX_SLOPES + * have the correct values, which can be derived by setting them to + * a number which is too high, running this function, and using the + * error messages to obtain the correct values. + */ +errr vinfo_init(void) +{ + int i, y, x; + + long m; + + int num_grids = 0; + + int queue_head = 0; + int queue_tail = 0; + vinfo_type *queue[VINFO_MAX_GRIDS*2]; + + + /* Make hack */ + vinfo_hack hack; + WIPE(&hack, vinfo_hack); + + /* Analyze grids */ + for (y = 0; y <= MAX_SIGHT; ++y) + { + for (x = y; x <= MAX_SIGHT; ++x) + { + /* Skip grids which are out of sight range */ + if (distance(0, 0, y, x) > MAX_SIGHT) continue; + + /* Default slope range */ + hack.slopes_min[y][x] = 999999999; + hack.slopes_max[y][x] = 0; + + /* Paranoia */ + if (num_grids >= VINFO_MAX_GRIDS) + { + quit_fmt("Too many grids (%d >= %d)!", + num_grids, VINFO_MAX_GRIDS); + } + + /* Count grids */ + num_grids++; + + /* Slope to the top right corner */ + m = SCALE * (1000L * y - 500) / (1000L * x + 500); + + /* Handle "legal" slopes */ + vinfo_init_aux(&hack, y, x, m); + + /* Slope to top left corner */ + m = SCALE * (1000L * y - 500) / (1000L * x - 500); + + /* Handle "legal" slopes */ + vinfo_init_aux(&hack, y, x, m); + + /* Slope to bottom right corner */ + m = SCALE * (1000L * y + 500) / (1000L * x + 500); + + /* Handle "legal" slopes */ + vinfo_init_aux(&hack, y, x, m); + + /* Slope to bottom left corner */ + m = SCALE * (1000L * y + 500) / (1000L * x - 500); + + /* Handle "legal" slopes */ + vinfo_init_aux(&hack, y, x, m); + } + } + + + /* Enforce maximal efficiency */ + if (num_grids < VINFO_MAX_GRIDS) + { + quit_fmt("Too few grids (%d < %d)!", + num_grids, VINFO_MAX_GRIDS); + } + + /* Enforce maximal efficiency */ + if (hack.num_slopes < VINFO_MAX_SLOPES) + { + quit_fmt("Too few slopes (%d < %d)!", + hack.num_slopes, VINFO_MAX_SLOPES); + } + + + /* Sort slopes numerically */ + std::sort(std::begin(hack.slopes), std::end(hack.slopes)); + + + + /* Enqueue player grid */ + queue[queue_tail++] = &vinfo[0]; + + /* Process queue */ + while (queue_head < queue_tail) + { + int e; + + /* Index */ + e = queue_head; + + /* Dequeue next grid */ + queue_head++; + + /* Location of main grid */ + y = vinfo[e].grid_y[0]; + x = vinfo[e].grid_x[0]; + + + /* Compute grid offsets */ + vinfo[e].grid_y[0] = + y; + vinfo[e].grid_x[0] = + x; + vinfo[e].grid_y[1] = + x; + vinfo[e].grid_x[1] = + y; + vinfo[e].grid_y[2] = + x; + vinfo[e].grid_x[2] = -y; + vinfo[e].grid_y[3] = + y; + vinfo[e].grid_x[3] = -x; + vinfo[e].grid_y[4] = -y; + vinfo[e].grid_x[4] = -x; + vinfo[e].grid_y[5] = -x; + vinfo[e].grid_x[5] = -y; + vinfo[e].grid_y[6] = -x; + vinfo[e].grid_x[6] = + y; + vinfo[e].grid_y[7] = -y; + vinfo[e].grid_x[7] = + x; + + + /* Analyze slopes */ + for (i = 0; i < hack.num_slopes; ++i) + { + m = hack.slopes[i]; + + /* Memorize intersection slopes (for non-player-grids) */ + if ((e > 0) && + (hack.slopes_min[y][x] < m) && + (m < hack.slopes_max[y][x])) + { + switch (i / 32) + { + case 3: + vinfo[e].bits_3 |= (1L << (i % 32)); + break; + case 2: + vinfo[e].bits_2 |= (1L << (i % 32)); + break; + case 1: + vinfo[e].bits_1 |= (1L << (i % 32)); + break; + case 0: + vinfo[e].bits_0 |= (1L << (i % 32)); + break; + } + } + } + + + /* Default */ + vinfo[e].next_0 = &vinfo[0]; + + /* Grid next child */ + if (distance(0, 0, y, x + 1) <= MAX_SIGHT) + { + if ((queue[queue_tail - 1]->grid_y[0] != y) || + (queue[queue_tail - 1]->grid_x[0] != x + 1)) + { + vinfo[queue_tail].grid_y[0] = y; + vinfo[queue_tail].grid_x[0] = x + 1; + queue[queue_tail] = &vinfo[queue_tail]; + queue_tail++; + } + + vinfo[e].next_0 = &vinfo[queue_tail - 1]; + } + + + /* Default */ + vinfo[e].next_1 = &vinfo[0]; + + /* Grid diag child */ + if (distance(0, 0, y + 1, x + 1) <= MAX_SIGHT) + { + if ((queue[queue_tail - 1]->grid_y[0] != y + 1) || + (queue[queue_tail - 1]->grid_x[0] != x + 1)) + { + vinfo[queue_tail].grid_y[0] = y + 1; + vinfo[queue_tail].grid_x[0] = x + 1; + queue[queue_tail] = &vinfo[queue_tail]; + queue_tail++; + } + + vinfo[e].next_1 = &vinfo[queue_tail - 1]; + } + + + /* Hack -- main diagonal has special children */ + if (y == x) vinfo[e].next_0 = vinfo[e].next_1; + + + /* Extra values */ + vinfo[e].y = y; + vinfo[e].x = x; + vinfo[e].d = ((y > x) ? (y + x / 2) : (x + y / 2)); + vinfo[e].r = ((!y) ? x : (!x) ? y : (y == x) ? y : 0); + } + + + /* Verify maximal bits XXX XXX XXX */ + if (((vinfo[1].bits_3 | vinfo[2].bits_3) != VINFO_BITS_3) || + ((vinfo[1].bits_2 | vinfo[2].bits_2) != VINFO_BITS_2) || + ((vinfo[1].bits_1 | vinfo[2].bits_1) != VINFO_BITS_1) || + ((vinfo[1].bits_0 | vinfo[2].bits_0) != VINFO_BITS_0)) + { + quit("Incorrect bit masks!"); + } + + + /* Success */ + return (0); +} + + + +/* + * Forget the "CAVE_VIEW" grids, redrawing as needed + */ +void forget_view(void) +{ + int i; + + int fast_view_n = view_n; + + cave_type *c_ptr; + + + /* None to forget */ + if (!fast_view_n) return; + + /* Clear them all */ + for (i = 0; i < fast_view_n; i++) + { + int y = view_y[i]; + int x = view_x[i]; + + /* Access the grid */ + c_ptr = &cave[y][x]; + + /* Clear "CAVE_VIEW", "CAVE_SEEN" and player torch flags */ + c_ptr->info &= ~(CAVE_VIEW | CAVE_SEEN | CAVE_PLIT); + + /* Redraw */ + lite_spot(y, x); + } + + /* None left */ + view_n = 0; +} + + + +/* + * Calculate the complete field of view using a new algorithm + * + * If "view_y/x" and "temp_y/x" were global pointers to arrays of grids, as + * opposed to actual arrays of grids, then we could be more efficient by + * using "pointer swapping". + * + * Normally, vision along the major axes is more likely than vision + * along the diagonal axes, so we check the bits corresponding to + * the lines of sight near the major axes first. + * + * We use the "temp_y/x" array (and the "CAVE_TEMP" flag) to keep track of + * which grids were previously marked "CAVE_SEEN", since only those grids + * whose "CAVE_SEEN" value changes during this routine must be redrawn. + * + * This function is now responsible for maintaining the "CAVE_SEEN" + * flags as well as the "CAVE_VIEW" flags, which is good, because + * the only grids which normally need to be memorized and/or redrawn + * are the ones whose "CAVE_SEEN" flag changes during this routine. + * + * Basically, this function divides the "octagon of view" into octants of + * grids (where grids on the main axes and diagonal axes are "shared" by + * two octants), and processes each octant one at a time, processing each + * octant one grid at a time, processing only those grids which "might" be + * viewable, and setting the "CAVE_VIEW" flag for each grid for which there + * is an (unobstructed) line of sight from the center of the player grid to + * any internal point in the grid (and collecting these "CAVE_VIEW" grids + * into the "view_y/x" array), and setting the "CAVE_SEEN" flag for the grid + * if, in addition, the grid is "illuminated" in some way. + * + * This function relies on a theorem (suggested and proven by Mat Hostetter) + * which states that in each octant of a field of view, a given grid will + * be "intersected" by one or more unobstructed "lines of sight" from the + * center of the player grid if and only if it is "intersected" by at least + * one such unobstructed "line of sight" which passes directly through some + * corner of some grid in the octant which is not shared by any other octant. + * The proof is based on the fact that there are at least three significant + * lines of sight involving any non-shared grid in any octant, one which + * intersects the grid and passes though the corner of the grid closest to + * the player, and two which "brush" the grid, passing through the "outer" + * corners of the grid, and that any line of sight which intersects a grid + * without passing through the corner of a grid in the octant can be "slid" + * slowly towards the corner of the grid closest to the player, until it + * either reaches it or until it brushes the corner of another grid which + * is closer to the player, and in either case, the existanc of a suitable + * line of sight is thus demonstrated. + * + * It turns out that in each octant of the radius 20 "octagon of view", + * there are 161 grids (with 128 not shared by any other octant), and there + * are exactly 126 distinct "lines of sight" passing from the center of the + * player grid through any corner of any non-shared grid in the octant. To + * determine if a grid is "viewable" by the player, therefore, you need to + * simply show that one of these 126 lines of sight intersects the grid but + * does not intersect any wall grid closer to the player. So we simply use + * a bit vector with 126 bits to represent the set of interesting lines of + * sight which have not yet been obstructed by wall grids, and then we scan + * all the grids in the octant, moving outwards from the player grid. For + * each grid, if any of the lines of sight which intersect that grid have not + * yet been obstructed, then the grid is viewable. Furthermore, if the grid + * is a wall grid, then all of the lines of sight which intersect the grid + * should be marked as obstructed for future reference. Also, we only need + * to check those grids for whom at least one of the "parents" was a viewable + * non-wall grid, where the parents include the two grids touching the grid + * but closer to the player grid (one adjacent, and one diagonal). For the + * bit vector, we simply use 4 32-bit integers. All of the static values + * which are needed by this function are stored in the large "vinfo" array + * (above), which is machine generated by another program. XXX XXX XXX + * + * Hack -- The queue must be able to hold more than VINFO_MAX_GRIDS grids + * because the grids at the edge of the field of view use "grid zero" as + * their children, and the queue must be able to hold several of these + * special grids. Because the actual number of required grids is bizarre, + * we simply allocate twice as many as we would normally need. XXX XXX XXX + */ +void update_view(void) +{ + int i, o; + int y, x; + + int radius; + + int fast_view_n = view_n; + + int fast_temp_n = 0; + + cave_type *c_ptr; + + u16b info; + + + /*** Step 0 -- Begin ***/ + + /* Save the old "view" grids for later */ + for (i = 0; i < fast_view_n; i++) + { + /* Location */ + y = view_y[i]; + x = view_x[i]; + + /* Grid */ + c_ptr = &cave[y][x]; + + /* Get grid info */ + info = c_ptr->info; + ; + + /* Save "CAVE_SEEN" grids */ + if (info & (CAVE_SEEN)) + { + /* Set "CAVE_TEMP" flag */ + info |= (CAVE_TEMP); + + /* Save grid for later */ + temp_y[fast_temp_n] = y; + temp_x[fast_temp_n++] = x; + } + + /* Clear "CAVE_VIEW", "CAVE_SEEN" and player torch flags */ + info &= ~(CAVE_VIEW | CAVE_SEEN | CAVE_PLIT); + + /* Save cave info */ + c_ptr->info = info; + } + + /* Reset the "view" array */ + fast_view_n = 0; + + /* Extract "radius" value */ + radius = p_ptr->cur_lite; + + /* Handle real light */ + if (radius > 0) ++radius; + + + /*** Step 1 -- player grid ***/ + + /* Player grid */ + c_ptr = &cave[p_ptr->py][p_ptr->px]; + + /* Get grid info */ + info = c_ptr->info; + + /* Assume viewable */ + info |= (CAVE_VIEW); + + /* Torch-lit grid */ + if (0 < radius) + { + /* Mark as "CAVE_SEEN" and torch-lit */ + info |= (CAVE_SEEN | CAVE_PLIT); + } + + + /* Perma-lit grid */ + else if (info & (CAVE_GLOW)) + { + /* Mark as "CAVE_SEEN" */ + info |= (CAVE_SEEN); + } + + /* Save cave info */ + c_ptr->info = info; + + /* Save in array */ + view_y[fast_view_n] = p_ptr->py; + view_x[fast_view_n++] = p_ptr->px; + + + /*** Step 2 -- octants ***/ + + /* Scan each octant */ + for (o = 0; o < 8; o++) + { + vinfo_type *p; + + /* Last added */ + vinfo_type *last = &vinfo[0]; + + /* Grid queue */ + int queue_head = 0; + int queue_tail = 0; + vinfo_type *queue[VINFO_MAX_GRIDS*2]; + + /* Slope bit vector */ + u32b bits0 = VINFO_BITS_0; + u32b bits1 = VINFO_BITS_1; + u32b bits2 = VINFO_BITS_2; + u32b bits3 = VINFO_BITS_3; + + /* Reset queue */ + queue_head = queue_tail = 0; + + /* Initial grids */ + queue[queue_tail++] = &vinfo[1]; + queue[queue_tail++] = &vinfo[2]; + + /* Process queue */ + while (queue_head < queue_tail) + { + /* Dequeue next grid */ + p = queue[queue_head++]; + + /* Check bits */ + if ((bits0 & (p->bits_0)) || + (bits1 & (p->bits_1)) || + (bits2 & (p->bits_2)) || + (bits3 & (p->bits_3))) + { + /* Extract coordinate value */ + y = p_ptr->py + p->grid_y[o]; + x = p_ptr->px + p->grid_x[o]; + + /* Access the grid */ + c_ptr = &cave[y][x]; + + /* Get grid info */ + info = c_ptr->info; + + /* Handle wall */ + if (info & (CAVE_WALL)) + { + /* Clear bits */ + bits0 &= ~(p->bits_0); + bits1 &= ~(p->bits_1); + bits2 &= ~(p->bits_2); + bits3 &= ~(p->bits_3); + + /* Newly viewable wall */ + if (!(info & (CAVE_VIEW))) + { + /* Mark as viewable */ + info |= (CAVE_VIEW); + + /* Torch-lit grids */ + if (p->d < radius) + { + /* Mark as "CAVE_SEEN" and torch-lit */ + info |= (CAVE_SEEN | CAVE_PLIT); + } + + /* Monster-lit grids */ + else if (info & (CAVE_MLIT)) + { + /* Mark as "CAVE_SEEN" */ + info |= (CAVE_SEEN); + } + + /* Perma-lit grids */ + else if (info & (CAVE_GLOW)) + { + /* Hack -- move towards player */ + int yy = (y < p_ptr->py) ? (y + 1) : (y > p_ptr->py) ? (y - 1) : y; + int xx = (x < p_ptr->px) ? (x + 1) : (x > p_ptr->px) ? (x - 1) : x; + + /* Check for "simple" illumination */ + if (cave[yy][xx].info & (CAVE_GLOW)) + { + /* Mark as seen */ + info |= (CAVE_SEEN); + } + } + + /* Save cave info */ + c_ptr->info = info; + + /* Save in array */ + view_y[fast_view_n] = y; + view_x[fast_view_n++] = x; + } + } + + /* Handle non-wall */ + else + { + /* Enqueue child */ + if (last != p->next_0) + { + queue[queue_tail++] = last = p->next_0; + } + + /* Enqueue child */ + if (last != p->next_1) + { + queue[queue_tail++] = last = p->next_1; + } + + /* Newly viewable non-wall */ + if (!(info & (CAVE_VIEW))) + { + /* Mark as "viewable" */ + info |= (CAVE_VIEW); + + /* Torch-lit grids */ + if (p->d < radius) + { + /* Mark as "CAVE_SEEN" and torch-lit */ + info |= (CAVE_SEEN | CAVE_PLIT); + } + + /* Perma-lit or monster-lit grids */ + else if (info & (CAVE_GLOW | CAVE_MLIT)) + { + /* Mark as "CAVE_SEEN" */ + info |= (CAVE_SEEN); + } + + /* Save cave info */ + c_ptr->info = info; + + /* Save in array */ + view_y[fast_view_n] = y; + view_x[fast_view_n++] = x; + } + } + } + } + } + + + /*** Step 3 -- Complete the algorithm ***/ + + /* Handle blindness */ + if (p_ptr->blind) + { + /* Process "new" grids */ + for (i = 0; i < fast_view_n; i++) + { + /* Location */ + y = view_y[i]; + x = view_x[i]; + + /* Grid cannot be "CAVE_SEEN" */ + cave[y][x].info &= ~(CAVE_SEEN); + } + } + + /* Process "new" grids */ + for (i = 0; i < fast_view_n; i++) + { + /* Location */ + y = view_y[i]; + x = view_x[i]; + + /* Get grid info */ + info = cave[y][x].info; + + /* Was not "CAVE_SEEN", is now "CAVE_SEEN" */ + if ((info & (CAVE_SEEN)) && !(info & (CAVE_TEMP))) + { + /* Note */ + note_spot(y, x); + + /* Redraw */ + lite_spot(y, x); + } + } + + /* Process "old" grids */ + for (i = 0; i < fast_temp_n; i++) + { + /* Location */ + y = temp_y[i]; + x = temp_x[i]; + + /* Grid */ + c_ptr = &cave[y][x]; + + /* Get grid info */ + info = c_ptr->info; + + /* Clear "CAVE_TEMP" flag */ + info &= ~(CAVE_TEMP); + + /* Save cave info */ + c_ptr->info = info; + + /* Was "CAVE_SEEN", is now not "CAVE_SEEN" */ + if (!(info & (CAVE_SEEN))) + { + /* Redraw */ + lite_spot(y, x); + } + } + + + /* Save 'view_n' */ + view_n = fast_view_n; +} + + +/* + * Clear monster light + */ +void forget_mon_lite(void) +{ + int i, y, x; + + /* Process all the monster-lit grids */ + for (i = 0; i < lite_n; i++) + { + /* Access location */ + y = lite_y[i]; + x = lite_x[i]; + + /* Clear monster light flag */ + cave[y][x].info &= ~(CAVE_MLIT); + } + + /* Forget light array */ + lite_n = 0; +} + + +/* + * Update squares illuminated by monsters + * + * Code taken from Steven Fuerst's work for ZAngband, without support + * for multiple lite radii, and with necessary modifications for different + * internal representation of dungeon/wilderness. Other minor changes + * are mine... + * + * I'm not sure if I can handle wide radius well. Consider the following + * example, with p carrying a radius 3 light source: + * + * ##%# + * .x.. + * p##@ + * + * % should be illuminated, although the beam path is entirely out of + * player's los (because of grid-based nature of cave representation)... + * And I'm extremely reluctant to introduce symmetrical los. The current + * asymmetrical system has its own merit, and all the rules of games are + * asymmetrical, in some way or another... + * + * The code below exploits special characteristics of radius one light + * where one can fairly safely use light source's visibility (in terms of los) + * to determine if we can illuminate walls XXX + * + * This function works within the current player's field of view + * calculated by update_view(), so it should normally be called + * whenever FoV is updated (== PU_VIEW | PU_MON_LITE). The other + * case is when RF9_HAS_LITE monsters have moved or dead. Monster + * creation occurs out of LoS, so I chose not to take this into + * consideration. + * + * The CAVE_TEMP flag is used by the function to remember "old" monster-lit + * grids so that it can only redraw squares whose visibility has changed. + * + * Doing this in the update_view() order (update "new" grids, then "old") + * would result in bizarre lighting effects XXX XXX + * + * It has been made possible again to draw torch/monster-lit grids in + * different colours, even when they are in permanently lit locations + * by using (CAVE_PLIT|CAVE_MLIT) as if it were old CAVE_LITE, but I don't + * think it's appropriate for torch lights to be visible under the Sun :) + * or brighter light, and it doesn't work well with PernAngband's already + * colourful terrain features in aesthetically pleasing ways... -- pelpel + */ +void update_mon_lite(void) +{ + int i, y, x, d; + int fy, fx; + + cave_type *c_ptr; + u16b info; + + bool_ invis; + + s16b fast_lite_n = lite_n; + s16b fast_temp_n; + + + /* Mega-Hack -- It's unnecessary there */ + if (p_ptr->wild_mode) return; + + /* Handle special case -- Blindness */ + if (p_ptr->blind) + { + for (i = 0; i < fast_lite_n; i++) + { + /* Light location */ + y = lite_y[i]; + x = lite_x[i]; + + /* Forget monster light and view */ + cave[y][x].info &= ~(CAVE_MLIT | CAVE_SEEN); + + /* Redraw spot */ + /* lite_spot(y, x); */ + } + + /* Clear the light list */ + lite_n = 0; + + /* Done */ + return; + } + + + /* Remember and clear all monster-lit grids */ + for (i = 0; i < fast_lite_n; i++) + { + /* Lit location */ + y = lite_y[i]; + x = lite_x[i]; + + /* Access grid */ + c_ptr = &cave[y][x]; + + /* Access cave info of the grid */ + info = c_ptr->info; + + /* Remember it, by setting the CAVE_TEMP flag */ + info |= (CAVE_TEMP); + + /* Forget monster light */ + info &= ~(CAVE_MLIT); + + /* Unseen unless it's glowing or illuminated by player light source */ + if (!(info & (CAVE_GLOW | CAVE_PLIT))) + { + info &= ~(CAVE_SEEN); + } + + /* Save cave info flags */ + c_ptr->info = info; + } + + + /* Clear the temp list */ + fast_temp_n = 0; + + /* Loop through monsters, adding newly lit grids to changes list */ + for (i = 1; i < m_max; i++) + { + monster_type *m_ptr = &m_list[i]; + monster_race *r_ptr; + + /* Skip dead monsters */ + if (!m_ptr->r_idx) continue; + + /* Skip out-of-sight monsters (MAX_SIGHT + max radius) */ + if (m_ptr->cdis > MAX_SIGHT + 1) continue; + + /* Access monster race info (with possible ego mods) */ + r_ptr = race_info_idx(m_ptr->r_idx, m_ptr->ego); + + /* Skip monsters not carrying light source */ + if (!(r_ptr->flags9 & RF9_HAS_LITE)) continue; + + /* Access the location */ + fy = m_ptr->fy; + fx = m_ptr->fx; + + /* Extract monster grid visibility */ + invis = !player_has_los_bold(fy, fx); + + /* Nested loops may be a bad idea here XXX */ + for (d = 0; d < 9; d++) + { + y = fy + ddy_ddd[d]; + x = fx + ddx_ddd[d]; + + /* Paranoia */ + /* if (!in_bounds(y, x)) continue; */ + + /* Access the grid */ + c_ptr = &cave[y][x]; + + /* Access cave info flags */ + info = c_ptr->info; + + /* Don't care grids out of player's los */ + if (!(info & (CAVE_VIEW))) continue; + + /* + * Avoid processing already monster-lit grids, + * for efficiency and to avoid temp array overflow + */ + if (info & (CAVE_MLIT)) continue; + + /* + * Hack XXX XXX -- light shouldn't penetrate walls + * + * OK NG + * .#. p#. | p. .p. p.. + * p.@ ..@ | .# .#. .#. + * | .@ .@. ..@ + * + * So if a monster carrying light source is out of player LoS, + * walls aren't illuminated. + * + * CAVEAT: % will be illuminated in cases like this: + * + * #%..@ + * p.... + * + * We don't have four sides for a wall grid, so... + */ + if (invis && (f_info[c_ptr->feat].flags1 & FF1_NO_VISION)) continue; + + /* Give monster light to the location */ + c_ptr->info |= (CAVE_MLIT | CAVE_SEEN); + + /* Save the location */ + temp_y[fast_temp_n] = y; + temp_x[fast_temp_n] = x; + fast_temp_n++; + } + } + + /* Process old grids */ + for (i = 0; i < fast_lite_n; i++) + { + /* Access location */ + y = lite_y[i]; + x = lite_x[i]; + + /* Access grid */ + c_ptr = &cave[y][x]; + + /* Was lit, is no longer lit */ + if (!(c_ptr->info & (CAVE_MLIT))) + { + /* Clear the temp flag */ + c_ptr->info &= ~(CAVE_TEMP); + + /* See if there was a visible monster */ + if (player_has_los_bold(y, x) && c_ptr->m_idx) + { + /* Hide the monster */ + update_mon(c_ptr->m_idx, FALSE); + } + else + { + /* Redraw */ + lite_spot(y, x); + } + } + } + + /* Copy the temp array into the light array */ + for (i = 0; i < fast_temp_n; i++) + { + /* Access location */ + y = temp_y[i]; + x = temp_x[i]; + + /* Access grid */ + c_ptr = &cave[y][x]; + + + /* No changes in illumination */ + if (c_ptr->info & (CAVE_TEMP)) + { + /* Clear the temp flag */ + c_ptr->info &= ~(CAVE_TEMP); + } + + /* Was not lit, is now lit */ + else + { + /* Remember the location, if appropriate */ + note_spot(y, x); + + /* See if there is a monster */ + if (c_ptr->m_idx) + { + /* Show it */ + update_mon(c_ptr->m_idx, FALSE); + } + else + { + /* Redraw */ + lite_spot(y, x); + } + } + + + /* Save the location */ + lite_y[i] = y; + lite_x[i] = x; + } + + /* Save lite_n */ + lite_n = fast_temp_n; + + /* Forget temp */ + temp_n = 0; +} + + + + + + +/* + * Hack -- provide some "speed" for the "flow" code + * This entry is the "current index" for the "when" field + * Note that a "when" value of "zero" means "not used". + * + * Note that the "cost" indexes from 1 to 127 are for + * "old" data, and from 128 to 255 are for "new" data. + * + * This means that as long as the player does not "teleport", + * then any monster up to 128 + MONSTER_FLOW_DEPTH will be + * able to track down the player, and in general, will be + * able to track down either the player or a position recently + * occupied by the player. + */ +static int flow_n = 0; + + +/* + * Hack -- forget the "flow" information + */ +void forget_flow(void) +{ + int x, y; + + /* Nothing to forget */ + if (!flow_n) return; + + /* Check the entire dungeon */ + for (y = 0; y < cur_hgt; y++) + { + for (x = 0; x < cur_wid; x++) + { + /* Forget the old data */ + cave[y][x].cost = 0; + cave[y][x].when = 0; + } + } + + /* Start over */ + flow_n = 0; +} + + +/* + * Hack -- Allow us to treat the "seen" array as a queue + */ +static int flow_head = 0; +static int flow_tail = 0; + + +/* + * Take note of a reachable grid. Assume grid is legal. + */ +static void update_flow_aux(int y, int x, int n) +{ + cave_type *c_ptr; + + int old_head = flow_head; + + + /* Get the grid */ + c_ptr = &cave[y][x]; + + /* Ignore "pre-stamped" entries */ + if (c_ptr->when == flow_n) return; + + /* Ignore "walls" and "rubble" */ + if (c_ptr->feat >= FEAT_RUBBLE) return; + + /* Save the time-stamp */ + c_ptr->when = flow_n; + + /* Save the flow cost */ + c_ptr->cost = n; + + /* Hack -- limit flow depth */ + if (n == MONSTER_FLOW_DEPTH) return; + + /* Enqueue that entry */ + temp_y[flow_head] = y; + temp_x[flow_head] = x; + + /* Advance the queue */ + if (++flow_head == TEMP_MAX) flow_head = 0; + + /* Hack -- notice overflow by forgetting new entry */ + if (flow_head == flow_tail) flow_head = old_head; +} + + +/* + * Hack -- fill in the "cost" field of every grid that the player + * can "reach" with the number of steps needed to reach that grid. + * This also yields the "distance" of the player from every grid. + * + * In addition, mark the "when" of the grids that can reach + * the player with the incremented value of "flow_n". + * + * Hack -- use the "seen" array as a "circular queue". + * + * We do not need a priority queue because the cost from grid + * to grid is always "one" and we process them in order. + */ +void update_flow(void) +{ + int x, y, d; + + /* Hack -- disabled */ + if (!flow_by_sound) return; + + /* Paranoia -- make sure the array is empty */ + if (temp_n) return; + + /* Cycle the old entries (once per 128 updates) */ + if (flow_n == 255) + { + /* Rotate the time-stamps */ + for (y = 0; y < cur_hgt; y++) + { + for (x = 0; x < cur_wid; x++) + { + int w = cave[y][x].when; + cave[y][x].when = (w > 128) ? (w - 128) : 0; + } + } + + /* Restart */ + flow_n = 127; + } + + /* Start a new flow (never use "zero") */ + flow_n++; + + + /* Reset the "queue" */ + flow_head = flow_tail = 0; + + /* Add the player's grid to the queue */ + update_flow_aux(p_ptr->py, p_ptr->px, 0); + + /* Now process the queue */ + while (flow_head != flow_tail) + { + /* Extract the next entry */ + y = temp_y[flow_tail]; + x = temp_x[flow_tail]; + + /* Forget that entry */ + if (++flow_tail == TEMP_MAX) flow_tail = 0; + + /* Add the "children" */ + for (d = 0; d < 8; d++) + { + /* Add that child if "legal" */ + update_flow_aux(y + ddy_ddd[d], x + ddx_ddd[d], cave[y][x].cost + 1); + } + } + + /* Forget the flow info */ + flow_head = flow_tail = 0; +} + + + + + + + +/* + * Hack -- map the current panel (plus some) ala "magic mapping" + */ +void map_area(void) +{ + int i, x, y, y1, y2, x1, x2; + + cave_type *c_ptr; + + + /* Pick an area to map */ + y1 = panel_row_min - randint(10); + y2 = panel_row_max + randint(10); + x1 = panel_col_min - randint(20); + x2 = panel_col_max + randint(20); + + /* Speed -- shrink to fit legal bounds */ + if (y1 < 1) y1 = 1; + if (y2 > cur_hgt - 2) y2 = cur_hgt - 2; + if (x1 < 1) x1 = 1; + if (x2 > cur_wid - 2) x2 = cur_wid - 2; + + /* Scan that area */ + for (y = y1; y <= y2; y++) + { + for (x = x1; x <= x2; x++) + { + c_ptr = &cave[y][x]; + + /* All non-walls are "checked" */ + if (!is_wall(c_ptr)) + { + /* Memorize normal features */ + if (!cave_plain_floor_grid(c_ptr)) + { + /* Memorize the object */ + c_ptr->info |= (CAVE_MARK); + } + + /* Memorize known walls */ + for (i = 0; i < 8; i++) + { + c_ptr = &cave[y + ddy_ddd[i]][x + ddx_ddd[i]]; + + /* Memorize walls (etc) */ + if (is_wall(c_ptr)) + { + /* Memorize the walls */ + c_ptr->info |= (CAVE_MARK); + } + } + } + } + } + + /* Redraw map */ + p_ptr->redraw |= (PR_MAP); + + /* Window stuff */ + p_ptr->window |= (PW_OVERHEAD); +} + + + +/* + * Light up the dungeon using "clairvoyance" + * + * This function "illuminates" every grid in the dungeon, memorizes all + * "objects", memorizes all grids as with magic mapping, and, under the + * standard option settings (view_perma_grids but not view_torch_grids) + * memorizes all floor grids too. + * + * Note that if "view_perma_grids" is not set, we do not memorize floor + * grids, since this would defeat the purpose of "view_perma_grids", not + * that anyone seems to play without this option. + * + * Note that if "view_torch_grids" is set, we do not memorize floor grids, + * since this would prevent the use of "view_torch_grids" as a method to + * keep track of what grids have been observed directly. + */ +void wiz_lite(void) +{ + int i, y, x; + + + /* Memorize objects */ + for (i = 1; i < o_max; i++) + { + object_type *o_ptr = &o_list[i]; + + /* Skip dead objects */ + if (!o_ptr->k_idx) continue; + + /* Skip held objects */ + if (o_ptr->held_m_idx) continue; + + /* Memorize */ + o_ptr->marked = TRUE; + } + + /* Scan all normal grids */ + for (y = 1; y < cur_hgt - 1; y++) + { + /* Scan all normal grids */ + for (x = 1; x < cur_wid - 1; x++) + { + cave_type *c_ptr = &cave[y][x]; + + if (c_ptr->m_idx) + { + monster_type *m_ptr = &m_list[c_ptr->m_idx]; + monster_race *r_ptr = race_inf(m_ptr); + + if (r_ptr->flags9 & RF9_MIMIC) + { + object_type *o_ptr = &o_list[m_ptr->hold_o_idx]; + + o_ptr->marked = TRUE; + } + } + + /* Process all non-walls */ + /* if (c_ptr->feat < FEAT_SECRET) */ + { + /* Scan all neighbors */ + for (i = 0; i < 9; i++) + { + int yy = y + ddy_ddd[i]; + int xx = x + ddx_ddd[i]; + + /* Get the grid */ + c_ptr = &cave[yy][xx]; + + /* Perma-lite the grid */ + c_ptr->info |= (CAVE_GLOW); + + /* Memorize normal features */ + if (!cave_plain_floor_grid(c_ptr)) + { + /* Memorize the grid */ + c_ptr->info |= (CAVE_MARK); + } + + /* Normally, memorize floors (see above) */ + if (view_perma_grids && !view_torch_grids) + { + /* Memorize the grid */ + c_ptr->info |= (CAVE_MARK); + } + } + } + } + } + + /* Fully update the visuals */ + p_ptr->update |= (PU_UN_VIEW | PU_VIEW | PU_MONSTERS | PU_MON_LITE); + + /* Redraw map */ + p_ptr->redraw |= (PR_MAP); + + /* Window stuff */ + p_ptr->window |= (PW_OVERHEAD); +} + +void wiz_lite_extra(void) +{ + int y, x; + for (y = 0; y < cur_hgt; y++) + { + for (x = 0; x < cur_wid; x++) + { + cave[y][x].info |= (CAVE_GLOW | CAVE_MARK); + } + } + wiz_lite(); +} + +/* + * Forget the dungeon map (ala "Thinking of Maud..."). + */ +void wiz_dark(void) +{ + int i, y, x; + + + /* Forget every grid */ + for (y = 0; y < cur_hgt; y++) + { + for (x = 0; x < cur_wid; x++) + { + cave_type *c_ptr = &cave[y][x]; + + /* Process the grid */ + c_ptr->info &= ~(CAVE_MARK); + } + } + + /* Forget all objects */ + for (i = 1; i < o_max; i++) + { + object_type *o_ptr = &o_list[i]; + + /* Skip dead objects */ + if (!o_ptr->k_idx) continue; + + /* Skip held objects */ + if (o_ptr->held_m_idx) continue; + + /* Forget the object */ + o_ptr->marked = FALSE; + } + + /* Fully update the visuals */ + p_ptr->update |= (PU_UN_VIEW | PU_VIEW | PU_MONSTERS | PU_MON_LITE); + + /* Redraw map */ + p_ptr->redraw |= (PR_MAP); + + /* Window stuff */ + p_ptr->window |= (PW_OVERHEAD); +} + + + + + +/* + * Change the "feat" flag for a grid, and notice/redraw the grid + */ +void cave_set_feat(int y, int x, int feat) +{ + cave_type *c_ptr = &cave[y][x]; + + /* Change the feature */ + c_ptr->feat = feat; + + /* + * Handle "wall/door" grids + * + * XXX XXX XXX This assumes c_ptr->mimic doesn't mimic terrain + * features whose LoS behaviour is different from its own, in + * most cases. Level boundaries are the most notable exception, + * where "real" terrain is always FEAT_PERM_SOLID, and the fact + * is (ab)used to prevent out-of-range access to the cave array. + * If we were going to implement an evil dungeon type in which + * everything is mimicked, then this function, los(), projectable(), + * project_path() and maybe some functions in melee2.c might + * better use c_ptr->mimic when it's set -- pelpel + */ + if (!cave_sight_grid(c_ptr)) + { + c_ptr->info |= (CAVE_WALL); + } + + /* Handle "floor"/etc grids */ + else + { + c_ptr->info &= ~(CAVE_WALL); + } + + /* Notice & Redraw */ + if (character_dungeon) + { + /* Notice */ + note_spot(y, x); + + /* Redraw */ + lite_spot(y, x); + } +} + + +/* + * Place floor terrain at (y, x) according to dungeon info + */ +void place_floor(int y, int x) +{ + cave_set_feat(y, x, floor_type[rand_int(100)]); +} + +/* + * This routine is used when the current feature gets convert to a floor and + * the possible floor types include glass which is permanent. An unpassable + * feature is undesirable, so the glass gets convert to molten glass which + * is passable. + */ +void place_floor_convert_glass(int y, int x) +{ + place_floor(y, x); + + if (cave[y][x].feat == 188) cave[y][x].feat = 103; +} + +/* + * Place a cave filler at (y, x) + */ +void place_filler(int y, int x) +{ + cave_set_feat(y, x, fill_type[rand_int(100)]); +} + + +/* + * Calculate "incremental motion". Used by project() and shoot(). + * Assumes that (*y,*x) lies on the path from (y1,x1) to (y2,x2). + */ +void mmove2(int *y, int *x, int y1, int x1, int y2, int x2) +{ + int dy, dx, dist, shift; + + /* Extract the distance travelled */ + dy = (*y < y1) ? y1 - *y : *y - y1; + dx = (*x < x1) ? x1 - *x : *x - x1; + + /* Number of steps */ + dist = (dy > dx) ? dy : dx; + + /* We are calculating the next location */ + dist++; + + + /* Calculate the total distance along each axis */ + dy = (y2 < y1) ? (y1 - y2) : (y2 - y1); + dx = (x2 < x1) ? (x1 - x2) : (x2 - x1); + + /* Paranoia -- Hack -- no motion */ + if (!dy && !dx) return; + + + /* Move mostly vertically */ + if (dy > dx) + { + /* Extract a shift factor */ + shift = (dist * dx + (dy - 1) / 2) / dy; + + /* Sometimes move along the minor axis */ + (*x) = (x2 < x1) ? (x1 - shift) : (x1 + shift); + + /* Always move along major axis */ + (*y) = (y2 < y1) ? (y1 - dist) : (y1 + dist); + } + + /* Move mostly horizontally */ + else + { + /* Extract a shift factor */ + shift = (dist * dy + (dx - 1) / 2) / dx; + + /* Sometimes move along the minor axis */ + (*y) = (y2 < y1) ? (y1 - shift) : (y1 + shift); + + /* Always move along major axis */ + (*x) = (x2 < x1) ? (x1 - dist) : (x1 + dist); + } +} + + + +/* + * Determine if a bolt spell cast from (y1,x1) to (y2,x2) will arrive + * at the final destination, assuming no monster gets in the way. + * + * This is slightly (but significantly) different from "los(y1,x1,y2,x2)". + */ +bool_ projectable(int y1, int x1, int y2, int x2) +{ + int dist, y, x; + + /* Start at the initial location */ + y = y1, x = x1; + + /* See "project()" */ + for (dist = 0; dist <= MAX_RANGE; dist++) + { + /* Check for arrival at "final target" */ + /* + * NB: this check was AFTER the 'never pass + * thru walls' clause, below. Switching them + * lets monsters shoot a the player if s/he is + * visible but in a wall + */ + if ((x == x2) && (y == y2)) return (TRUE); + + /* Never pass through walls */ + if (dist && (!cave_sight_bold(y, x) || !cave_floor_bold(y, x))) break; + + /* Calculate the new location */ + mmove2(&y, &x, y1, x1, y2, x2); + } + + + /* Assume obstruction */ + return (FALSE); +} + + + + +/* + * Standard "find me a location" function + * + * Obtains a legal location within the given distance of the initial + * location, and with "los()" from the source to destination location. + * + * This function is often called from inside a loop which searches for + * locations while increasing the "d" distance. + * + * Currently the "m" parameter is unused. + */ +void scatter(int *yp, int *xp, int y, int x, int d) +{ + int nx, ny; + int attempts_left = 5000; + + /* Pick a location */ + while (--attempts_left) + { + /* Pick a new location */ + ny = rand_spread(y, d); + nx = rand_spread(x, d); + + /* Ignore illegal locations and outer walls */ + if (!in_bounds(ny, nx)) continue; + + /* Ignore "excessively distant" locations */ + if ((d > 1) && (distance(y, x, ny, nx) > d)) continue; + + /* Require "line of sight" */ + if (los(y, x, ny, nx)) break; + } + + if (attempts_left > 0) + { + /* Save the location */ + (*yp) = ny; + (*xp) = nx; + } +} + + + + +/* + * Track a new monster + */ +void health_track(int m_idx) +{ + /* Track a new guy */ + health_who = m_idx; + + /* Redraw (later) */ + p_ptr->redraw |= (PR_HEALTH); +} + + + +/* + * Hack -- track the given monster race + */ +void monster_race_track(int r_idx, int ego) +{ + /* Save this monster ID */ + monster_race_idx = r_idx; + monster_ego_idx = ego; + + /* Window stuff */ + p_ptr->window |= (PW_MONSTER); +} + + + +/* + * Hack -- track the given object kind + */ +void object_track(object_type *o_ptr) +{ + /* Save this monster ID */ + tracked_object = o_ptr; + + /* Window stuff */ + p_ptr->window |= (PW_OBJECT); +} + + + +/* + * Something has happened to disturb the player. + * + * The first arg indicates a major disturbance, which affects search. + * + * All disturbance cancels repeated commands, resting, and running. + */ +void disturb(int stop_search) +{ + /* Cancel auto-commands */ + /* command_new = 0; */ + + /* Cancel repeated commands */ + if (command_rep) + { + /* Cancel */ + command_rep = 0; + + /* Redraw the state (later) */ + p_ptr->redraw |= (PR_STATE); + } + + /* Cancel Resting */ + if (resting) + { + /* Cancel */ + resting = 0; + + /* Redraw the state (later) */ + p_ptr->redraw |= (PR_STATE); + } + + /* Cancel running */ + if (running) + { + /* Cancel */ + running = 0; + + /* Calculate torch radius */ + p_ptr->update |= (PU_TORCH); + } + + /* Cancel searching if requested */ + if (stop_search && p_ptr->searching) + { + /* Cancel */ + p_ptr->searching = FALSE; + + /* Recalculate bonuses */ + p_ptr->update |= (PU_BONUS); + + /* Redraw the state */ + p_ptr->redraw |= (PR_STATE); + } + + /* Flush the input if requested */ + if (flush_disturb) flush(); +} + + +/* + * Hack -- Check if a level is a "quest" level + */ +int is_quest(int level) +{ + int i = random_quest_number(); + + /* Check quests */ + if (p_ptr->inside_quest) + return (p_ptr->inside_quest); + + if (i) return (QUEST_RANDOM); + + /* Nope */ + return (0); +} + + +/* + * Return the index of the random quest on this level + * (or zero) + */ +int random_quest_number() +{ + if ((dun_level >= 1) && (dun_level < MAX_RANDOM_QUEST) && + (dungeon_flags1 & DF1_PRINCIPAL) && + (random_quests[dun_level].type) && + (!random_quests[dun_level].done) && + (!is_randhero(dun_level))) + { + return dun_level; + } + + /* Nope */ + return 0; +} + + +/* + * handle spell effects + */ +int effect_pop() +{ + int i; + + for (i = 1; i < MAX_EFFECTS; i++) + if (!effects[i].time) + return i; + return -1; +} + +int new_effect(int type, int dam, int time, int cy, int cx, int rad, s32b flags) +{ + int i; + + if ((i = effect_pop()) == -1) return -1; + + effects[i].type = type; + effects[i].dam = dam; + effects[i].time = time; + effects[i].flags = flags; + effects[i].cx = cx; + effects[i].cy = cy; + effects[i].rad = rad; + return i; +} diff --git a/src/cmd1.c b/src/cmd1.c deleted file mode 100644 index ff493174..00000000 --- a/src/cmd1.c +++ /dev/null @@ -1,5147 +0,0 @@ -/* File: cmd1.c */ - -/* Purpose: Movement commands (part 1) */ - -/* - * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke - * - * This software may be copied and distributed for educational, research, and - * not for profit purposes provided that this copyright and statement are - * included in all such copies. - */ - -#include "angband.h" - -#include "quark.h" -#include "hooks.h" - -#define MAX_VAMPIRIC_DRAIN 100 - - -/* - * Determine if the player "hits" a monster (normal combat). - * Note -- Always miss 5%, always hit 5%, otherwise random. - */ -bool_ test_hit_fire(int chance, int ac, int vis) -{ - int k; - - - /* Percentile dice */ - k = rand_int(100); - - /* Hack -- Instant miss or hit */ - if (k < 10) return (k < 5); - - /* Never hit */ - if (chance <= 0) return (FALSE); - - /* Invisible monsters are harder to hit */ - if (!vis) chance = (chance + 1) / 2; - - /* Power competes against armor */ - if (rand_int(chance + luck( -10, 10)) < (ac * 3 / 4)) return (FALSE); - - /* Assume hit */ - return (TRUE); -} - - - -/* - * Determine if the player "hits" a monster (normal combat). - * - * Note -- Always miss 5%, always hit 5%, otherwise random. - */ -bool_ test_hit_norm(int chance, int ac, int vis) -{ - int k; - - - /* Percentile dice */ - k = rand_int(100); - - /* Hack -- Instant miss or hit */ - if (k < 10) return (k < 5); - - /* Wimpy attack never hits */ - if (chance <= 0) return (FALSE); - - /* Penalize invisible targets */ - if (!vis) chance = (chance + 1) / 2; - - /* Power must defeat armor */ - if (rand_int(chance + luck( -10, 10)) < (ac * 3 / 4)) return (FALSE); - - /* Assume hit */ - return (TRUE); -} - - - -/* - * Critical hits (from objects thrown by player) - * Factor in item weight, total plusses, and player level. - */ -s16b critical_shot(int weight, int plus, int dam, int skill) -{ - int i, k; - - - /* Extract "shot" power */ - i = (weight + ((p_ptr->to_h + plus) * 4) + - get_skill_scale(skill, 100)); - i += 50 * p_ptr->xtra_crit; - i += luck( -100, 100); - - /* Critical hit */ - if (randint(5000) <= i) - { - k = weight + randint(500); - - if (k < 500) - { - msg_print("It was a good hit!"); - dam = 2 * dam + 5; - } - else if (k < 1000) - { - msg_print("It was a great hit!"); - dam = 2 * dam + 10; - } - else - { - msg_print("It was a superb hit!"); - dam = 3 * dam + 15; - } - } - - return (dam); -} - -/* - * Critical hits (by player) - * - * Factor in weapon weight, total plusses, player level. - */ -s16b critical_norm(int weight, int plus, int dam, int weapon_tval, bool_ *done_crit) -{ - int i, k, num = randint(5000); - - *done_crit = FALSE; - - /* Extract "blow" power */ - i = (weight + ((p_ptr->to_h + plus) * 5) + - get_skill_scale(p_ptr->melee_style, 150)); - i += 50 * p_ptr->xtra_crit; - if ((weapon_tval == TV_SWORD) && (weight < 50) && get_skill(SKILL_CRITS)) - { - i += get_skill_scale(SKILL_CRITS, 40 * 50); - } - i += luck( -100, 100); - - /* Force good strikes */ - if (p_ptr->tim_deadly) - { - set_tim_deadly(p_ptr->tim_deadly - 1); - msg_print("It was a *GREAT* hit!"); - dam = 3 * dam + 20; - *done_crit = TRUE; - } - - /* Chance */ - else if (num <= i) - { - k = weight + randint(650); - if ((weapon_tval == TV_SWORD) && (weight < 50) && get_skill(SKILL_CRITS)) - { - k += get_skill_scale(SKILL_CRITS, 400); - } - - if (k < 400) - { - msg_print("It was a good hit!"); - dam = 2 * dam + 5; - } - else if (k < 700) - { - msg_print("It was a great hit!"); - dam = 2 * dam + 10; - } - else if (k < 900) - { - msg_print("It was a superb hit!"); - dam = 3 * dam + 15; - } - else if (k < 1300) - { - msg_print("It was a *GREAT* hit!"); - dam = 3 * dam + 20; - } - else - { - msg_print("It was a *SUPERB* hit!"); - dam = ((7 * dam) / 2) + 25; - } - *done_crit = TRUE; - } - - return (dam); -} - - - -/* - * Extract the "total damage" from a given object hitting a given monster. - * - * Note that "flasks of oil" do NOT do fire damage, although they - * certainly could be made to do so. XXX XXX - * - * Note that most brands and slays are x3, except Slay Animal (x2), - * Slay Evil (x2), and Kill dragon (x5). - */ -s16b tot_dam_aux(object_type *o_ptr, int tdam, monster_type *m_ptr, - s32b *special) -{ - int mult = 1; - - monster_race *r_ptr = race_inf(m_ptr); - - u32b f1, f2, f3, f4, f5, esp; - - - /* Extract the flags */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* Some "weapons" and "ammo" do extra damage */ - switch (o_ptr->tval) - { - case TV_SHOT: - case TV_ARROW: - case TV_BOLT: - case TV_BOOMERANG: - case TV_HAFTED: - case TV_POLEARM: - case TV_SWORD: - case TV_AXE: - case TV_DIGGING: - { - /* Slay Animal */ - if ((f1 & (TR1_SLAY_ANIMAL)) && (r_ptr->flags3 & (RF3_ANIMAL))) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_ANIMAL); - } - - if (mult < 2) mult = 2; - } - - /* Slay Evil */ - if ((f1 & (TR1_SLAY_EVIL)) && (r_ptr->flags3 & (RF3_EVIL))) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_EVIL); - } - - if (mult < 2) mult = 2; - } - - /* Slay Undead */ - if ((f1 & (TR1_SLAY_UNDEAD)) && (r_ptr->flags3 & (RF3_UNDEAD))) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_UNDEAD); - } - - if (mult < 3) mult = 3; - } - - /* Slay Demon */ - if ((f1 & (TR1_SLAY_DEMON)) && (r_ptr->flags3 & (RF3_DEMON))) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_DEMON); - } - - if (mult < 3) mult = 3; - } - - /* Slay Orc */ - if ((f1 & (TR1_SLAY_ORC)) && (r_ptr->flags3 & (RF3_ORC))) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_ORC); - } - - if (mult < 3) mult = 3; - } - - /* Slay Troll */ - if ((f1 & (TR1_SLAY_TROLL)) && (r_ptr->flags3 & (RF3_TROLL))) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_TROLL); - } - - if (mult < 3) mult = 3; - } - - /* Slay Giant */ - if ((f1 & (TR1_SLAY_GIANT)) && (r_ptr->flags3 & (RF3_GIANT))) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_GIANT); - } - - if (mult < 3) mult = 3; - } - - /* Slay Dragon */ - if ((f1 & (TR1_SLAY_DRAGON)) && (r_ptr->flags3 & (RF3_DRAGON))) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_DRAGON); - } - - if (mult < 3) mult = 3; - } - - /* Execute Dragon */ - if ((f1 & (TR1_KILL_DRAGON)) && (r_ptr->flags3 & (RF3_DRAGON))) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_DRAGON); - } - - if (mult < 5) mult = 5; - } - - /* Execute Undead */ - if ((f5 & (TR5_KILL_UNDEAD)) && (r_ptr->flags3 & (RF3_UNDEAD))) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_UNDEAD); - } - - if (mult < 5) mult = 5; - } - - /* Execute Demon */ - if ((f5 & (TR5_KILL_DEMON)) && (r_ptr->flags3 & (RF3_DEMON))) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_DEMON); - } - - if (mult < 5) mult = 5; - } - - - /* Brand (Acid) */ - if (f1 & (TR1_BRAND_ACID)) - { - /* Notice immunity */ - if (r_ptr->flags3 & (RF3_IM_ACID)) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_IM_ACID); - } - } - - /* Notice susceptibility */ - else if (r_ptr->flags9 & (RF9_SUSCEP_ACID)) - { - if (m_ptr->ml) - { - r_ptr->r_flags9 |= (RF9_SUSCEP_ACID); - } - if (mult < 6) mult = 6; - } - - /* Otherwise, take the damage */ - else - { - if (mult < 3) mult = 3; - } - } - - /* Brand (Elec) */ - if (f1 & (TR1_BRAND_ELEC)) - { - /* Notice immunity */ - if (r_ptr->flags3 & (RF3_IM_ELEC)) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_IM_ELEC); - } - } - - /* Notice susceptibility */ - else if (r_ptr->flags9 & (RF9_SUSCEP_ELEC)) - { - if (m_ptr->ml) - { - r_ptr->r_flags9 |= (RF9_SUSCEP_ELEC); - } - if (mult < 6) mult = 6; - } - - /* Otherwise, take the damage */ - else - { - if (mult < 3) mult = 3; - } - } - - /* Brand (Fire) */ - if (f1 & (TR1_BRAND_FIRE)) - { - /* Notice immunity */ - if (r_ptr->flags3 & (RF3_IM_FIRE)) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_IM_FIRE); - } - } - - /* Notice susceptibility */ - else if (r_ptr->flags3 & (RF3_SUSCEP_FIRE)) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_SUSCEP_FIRE); - } - if (mult < 6) mult = 6; - } - - /* Otherwise, take the damage */ - else - { - if (mult < 3) mult = 3; - } - } - - /* Brand (Cold) */ - if (f1 & (TR1_BRAND_COLD)) - { - /* Notice immunity */ - if (r_ptr->flags3 & (RF3_IM_COLD)) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_IM_COLD); - } - } - - /* Notice susceptibility */ - else if (r_ptr->flags3 & (RF3_SUSCEP_COLD)) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_SUSCEP_COLD); - } - if (mult < 6) mult = 6; - } - - /* Otherwise, take the damage */ - else - { - if (mult < 3) mult = 3; - } - } - - /* Brand (Poison) */ - if (f1 & (TR1_BRAND_POIS) || (p_ptr->tim_poison)) - { - /* Notice immunity */ - if (r_ptr->flags3 & (RF3_IM_POIS)) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_IM_POIS); - } - } - - /* Notice susceptibility */ - else if (r_ptr->flags9 & (RF9_SUSCEP_POIS)) - { - if (m_ptr->ml) - { - r_ptr->r_flags9 |= (RF9_SUSCEP_POIS); - } - if (mult < 6) mult = 6; - if (magik(95)) *special |= SPEC_POIS; - } - - /* Otherwise, take the damage */ - else - { - if (mult < 3) mult = 3; - if (magik(50)) *special |= SPEC_POIS; - } - } - - /* Wounding */ - if (f5 & (TR5_WOUNDING)) - { - /* Notice immunity */ - if (r_ptr->flags8 & (RF8_NO_CUT)) - { - if (m_ptr->ml) - { - r_info[m_ptr->r_idx].r_flags8 |= (RF8_NO_CUT); - } - } - - /* Otherwise, take the damage */ - else - { - if (magik(50)) *special |= SPEC_CUT; - } - } - break; - } - } - - - /* Return the total damage */ - return (tdam * mult); -} - - -/* - * Search for hidden things - */ -void search(void) -{ - int y, x, chance; - - s16b this_o_idx, next_o_idx = 0; - - cave_type *c_ptr; - - - /* Start with base search ability */ - chance = p_ptr->skill_srh; - - /* Penalize various conditions */ - if (p_ptr->blind || no_lite()) chance = chance / 10; - if (p_ptr->confused || p_ptr->image) chance = chance / 10; - - /* Search the nearby grids, which are always in bounds */ - for (y = (p_ptr->py - 1); y <= (p_ptr->py + 1); y++) - { - for (x = (p_ptr->px - 1); x <= (p_ptr->px + 1); x++) - { - /* Sometimes, notice things */ - if (rand_int(100) < chance) - { - /* Access the grid */ - c_ptr = &cave[y][x]; - - /* Invisible trap */ - if ((c_ptr->t_idx != 0) && !(c_ptr->info & CAVE_TRDT)) - { - /* Pick a trap */ - pick_trap(y, x); - - /* Message */ - msg_print("You have found a trap."); - - /* Disturb */ - disturb(0); - } - - /* Secret door */ - if (c_ptr->feat == FEAT_SECRET) - { - /* Message */ - msg_print("You have found a secret door."); - - /* Pick a door XXX XXX XXX */ - cave_set_feat(y, x, FEAT_DOOR_HEAD + 0x00); - cave[y][x].mimic = 0; - lite_spot(y, x); - - /* Disturb */ - disturb(0); - } - - /* Scan all objects in the grid */ - for (this_o_idx = c_ptr->o_idx; this_o_idx; - this_o_idx = next_o_idx) - { - object_type * o_ptr; - - /* Acquire object */ - o_ptr = &o_list[this_o_idx]; - - /* Acquire next object */ - next_o_idx = o_ptr->next_o_idx; - - /* Skip non-chests */ - if (o_ptr->tval != TV_CHEST) continue; - - /* Skip non-trapped chests */ - if (!o_ptr->pval) continue; - - /* Identify once */ - if (!object_known_p(o_ptr)) - { - /* Message */ - msg_print("You have discovered a trap on the chest!"); - - /* Know the trap */ - object_known(o_ptr); - - /* Notice it */ - disturb(0); - } - } - } - } - } -} - - - - -/* - * Player "wants" to pick up an object or gold. - * Note that we ONLY handle things that can be picked up. - * See "move_player()" for handling of other things. - */ -void carry(int pickup) -{ - if (!p_ptr->disembodied) - { - py_pickup_floor(pickup); - } -} - - -/* - * Handle player hitting a real trap - */ -static void hit_trap(void) -{ - bool_ ident = FALSE; - - cave_type *c_ptr; - - - /* Disturb the player */ - disturb(0); - - /* Get the cave grid */ - c_ptr = &cave[p_ptr->py][p_ptr->px]; - if (c_ptr->t_idx != 0) - { - ident = player_activate_trap_type(p_ptr->py, p_ptr->px, NULL, -1); - if (ident) - { - t_info[c_ptr->t_idx].ident = TRUE; - msg_format("You identified the trap as %s.", - t_name + t_info[c_ptr->t_idx].name); - } - } -} - - -void touch_zap_player(monster_type *m_ptr) -{ - int aura_damage = 0; - - monster_race *r_ptr = race_inf(m_ptr); - - - if (r_ptr->flags2 & (RF2_AURA_FIRE)) - { - if (!(p_ptr->immune_fire)) - { - char aura_dam[80]; - - aura_damage = - damroll(1 + (m_ptr->level / 26), 1 + (m_ptr->level / 17)); - - /* Hack -- Get the "died from" name */ - monster_desc(aura_dam, m_ptr, 0x88); - - msg_print("You are suddenly very hot!"); - - if (p_ptr->oppose_fire) aura_damage = (aura_damage + 2) / 3; - if (p_ptr->resist_fire) aura_damage = (aura_damage + 2) / 3; - if (p_ptr->sensible_fire) aura_damage = (aura_damage + 2) * 2; - - take_hit(aura_damage, aura_dam); - r_ptr->r_flags2 |= RF2_AURA_FIRE; - handle_stuff(); - } - } - - - if (r_ptr->flags2 & (RF2_AURA_ELEC)) - { - if (!(p_ptr->immune_elec)) - { - char aura_dam[80]; - - aura_damage = - damroll(1 + (m_ptr->level / 26), 1 + (m_ptr->level / 17)); - - /* Hack -- Get the "died from" name */ - monster_desc(aura_dam, m_ptr, 0x88); - - if (p_ptr->oppose_elec) aura_damage = (aura_damage + 2) / 3; - if (p_ptr->resist_elec) aura_damage = (aura_damage + 2) / 3; - - msg_print("You get zapped!"); - take_hit(aura_damage, aura_dam); - r_ptr->r_flags2 |= RF2_AURA_ELEC; - handle_stuff(); - } - } -} - - -/* - * Carried monster can attack too. - * Based on monst_attack_monst. - */ -static void carried_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath, - int x, int y) -{ - monster_type *t_ptr = &m_list[m_idx]; - - monster_race *r_ptr; - - monster_race *tr_ptr = race_inf(t_ptr); - - int ap_cnt; - - int ac, rlev, pt; - - char t_name[80]; - - cptr sym_name = symbiote_name(TRUE); - - char temp[80]; - - bool_ blinked = FALSE, touched = FALSE; - - byte y_saver = t_ptr->fy; - - byte x_saver = t_ptr->fx; - - object_type *o_ptr; - - - /* Get the carried monster */ - o_ptr = &p_ptr->inventory[INVEN_CARRY]; - if (!o_ptr->k_idx) return; - - r_ptr = &r_info[o_ptr->pval]; - - /* Not allowed to attack */ - if (r_ptr->flags1 & RF1_NEVER_BLOW) return; - - /* Total armor */ - ac = t_ptr->ac; - - /* Extract the effective monster level */ - rlev = ((o_ptr->elevel >= 1) ? o_ptr->elevel : 1); - - /* Get the monster name (or "it") */ - monster_desc(t_name, t_ptr, 0); - - /* Assume no blink */ - blinked = FALSE; - - if (!t_ptr->ml) - { - msg_print("You hear noise."); - } - - /* Scan through all four blows */ - for (ap_cnt = 0; ap_cnt < 4; ap_cnt++) - { - bool_ visible = FALSE; - bool_ obvious = FALSE; - - int power = 0; - int damage = 0; - - cptr act = NULL; - - /* Extract the attack infomation */ - int effect = r_ptr->blow[ap_cnt].effect; - int method = r_ptr->blow[ap_cnt].method; - int d_dice = r_ptr->blow[ap_cnt].d_dice; - int d_side = r_ptr->blow[ap_cnt].d_side; - - /* Stop attacking if the target dies! */ - if (t_ptr->fx != x_saver || t_ptr->fy != y_saver) - break; - - /* Hack -- no more attacks */ - if (!method) break; - - if (blinked) /* Stop! */ - { - /* break; */ - } - - /* Extract visibility (before blink) */ - visible = TRUE; - - /* Extract the attack "power" */ - power = get_attack_power(effect); - - /* Monster hits */ - if (!effect || check_hit2(power, rlev, ac)) - { - /* Always disturbing */ - disturb(1); - - /* Describe the attack method */ - switch (method) - { - case RBM_HIT: - { - act = "hits %s."; - touched = TRUE; - break; - } - - case RBM_TOUCH: - { - act = "touches %s."; - touched = TRUE; - break; - } - - case RBM_PUNCH: - { - act = "punches %s."; - touched = TRUE; - break; - } - - case RBM_KICK: - { - act = "kicks %s."; - touched = TRUE; - break; - } - - case RBM_CLAW: - { - act = "claws %s."; - touched = TRUE; - break; - } - - case RBM_BITE: - { - act = "bites %s."; - touched = TRUE; - break; - } - - case RBM_STING: - { - act = "stings %s."; - touched = TRUE; - break; - } - - case RBM_XXX1: - { - act = "XXX1's %s."; - break; - } - - case RBM_BUTT: - { - act = "butts %s."; - touched = TRUE; - break; - } - - case RBM_CRUSH: - { - act = "crushes %s."; - touched = TRUE; - break; - } - - case RBM_ENGULF: - { - act = "engulfs %s."; - touched = TRUE; - break; - } - - case RBM_CHARGE: - { - act = "charges %s."; - touched = TRUE; - break; - } - - case RBM_CRAWL: - { - act = "crawls on %s."; - touched = TRUE; - break; - } - - case RBM_DROOL: - { - act = "drools on %s."; - touched = FALSE; - break; - } - - case RBM_SPIT: - { - act = "spits on %s."; - touched = FALSE; - break; - } - - case RBM_GAZE: - { - act = "gazes at %s."; - touched = FALSE; - break; - } - - case RBM_WAIL: - { - act = "wails at %s."; - touched = FALSE; - break; - } - - case RBM_SPORE: - { - act = "releases spores at %s."; - touched = FALSE; - break; - } - - case RBM_XXX4: - { - act = "projects XXX4's at %s."; - touched = FALSE; - break; - } - - case RBM_BEG: - { - act = "begs %s for money."; - touched = FALSE; - t_ptr->csleep = 0; - break; - } - - case RBM_INSULT: - { - act = "insults %s."; - touched = FALSE; - t_ptr->csleep = 0; - break; - } - - case RBM_MOAN: - { - act = "moans at %s."; - touched = FALSE; - t_ptr->csleep = 0; - break; - } - - case RBM_SHOW: - { - act = "sings to %s."; - touched = FALSE; - t_ptr->csleep = 0; - break; - } - } - - /* Message */ - if (act) - { - strfmt(temp, act, t_name); - if (t_ptr->ml) - msg_format("%s %s", sym_name, temp); - - } - - /* Hack -- assume all attacks are obvious */ - obvious = TRUE; - - /* Roll out the damage */ - damage = damroll(d_dice, d_side); - - pt = GF_MISSILE; - - /* Apply appropriate damage */ - switch (effect) - { - case 0: - { - damage = 0; - pt = 0; - break; - } - - case RBE_HURT: - case RBE_SANITY: - { - damage -= (damage * ((ac < 150) ? ac : 150) / 250); - break; - } - - case RBE_POISON: - case RBE_DISEASE: - { - pt = GF_POIS; - break; - } - - case RBE_UN_BONUS: - case RBE_UN_POWER: - case RBE_ABOMINATION: - { - pt = GF_DISENCHANT; - break; - } - - case RBE_EAT_FOOD: - case RBE_EAT_LITE: - { - pt = damage = 0; - break; - } - - case RBE_EAT_ITEM: - case RBE_EAT_GOLD: - { - pt = damage = 0; - if (randint(2) == 1) blinked = TRUE; - break; - } - - case RBE_ACID: - { - pt = GF_ACID; - break; - } - - case RBE_ELEC: - { - pt = GF_ELEC; - break; - } - - case RBE_FIRE: - { - pt = GF_FIRE; - break; - } - - case RBE_COLD: - { - pt = GF_COLD; - break; - } - - case RBE_BLIND: - { - break; - } - - case RBE_CONFUSE: - case RBE_HALLU: - { - pt = GF_CONFUSION; - break; - } - - case RBE_TERRIFY: - { - pt = GF_TURN_ALL; - break; - } - - case RBE_PARALYZE: - { - pt = GF_OLD_SLEEP; /* sort of close... */ - break; - } - - case RBE_LOSE_STR: - case RBE_LOSE_INT: - case RBE_LOSE_WIS: - case RBE_LOSE_DEX: - case RBE_LOSE_CON: - case RBE_LOSE_CHR: - case RBE_LOSE_ALL: - case RBE_PARASITE: - { - break; - } - - case RBE_SHATTER: - { - if (damage > 23) - { - /* Prevent destruction of quest levels and town */ - if (!is_quest(dun_level) && dun_level) - earthquake(p_ptr->py, p_ptr->px, 8); - } - break; - } - - case RBE_EXP_10: - case RBE_EXP_20: - case RBE_EXP_40: - case RBE_EXP_80: - { - pt = GF_NETHER; - break; - } - - case RBE_TIME: - { - pt = GF_TIME; - break; - } - - default: - { - pt = 0; - break; - } - } - - if (pt) - { - /* Do damage if not exploding */ - project(0, 0, t_ptr->fy, t_ptr->fx, - (pt == GF_OLD_SLEEP ? r_ptr->level : damage), pt, - PROJECT_KILL | PROJECT_STOP); - - if (touched) - { - /* Aura fire */ - if ((tr_ptr->flags2 & RF2_AURA_FIRE) && - !(r_ptr->flags3 & RF3_IM_FIRE)) - { - if (t_ptr->ml) - { - blinked = FALSE; - msg_format("You are suddenly very hot!"); - if (t_ptr->ml) - tr_ptr->r_flags2 |= RF2_AURA_FIRE; - } - project(m_idx, 0, p_ptr->py, p_ptr->px, - damroll(1 + ((t_ptr->level) / 26), - 1 + ((t_ptr->level) / 17)), - GF_FIRE, PROJECT_KILL | PROJECT_STOP); - } - - /* Aura elec */ - if ((tr_ptr->flags2 & (RF2_AURA_ELEC)) && - !(r_ptr->flags3 & (RF3_IM_ELEC))) - { - if (t_ptr->ml) - { - blinked = FALSE; - msg_format("You get zapped!"); - if (t_ptr->ml) - tr_ptr->r_flags2 |= RF2_AURA_ELEC; - } - project(m_idx, 0, p_ptr->py, p_ptr->px, - damroll(1 + ((t_ptr->level) / 26), - 1 + ((t_ptr->level) / 17)), - GF_ELEC, PROJECT_KILL | PROJECT_STOP); - } - } - } - } - - /* Monster missed player */ - else - { - /* Analyze failed attacks */ - switch (method) - { - case RBM_HIT: - case RBM_TOUCH: - case RBM_PUNCH: - case RBM_KICK: - case RBM_CLAW: - case RBM_BITE: - case RBM_STING: - case RBM_XXX1: - case RBM_BUTT: - case RBM_CRUSH: - case RBM_ENGULF: - case RBM_CHARGE: - { - /* Disturb */ - disturb(1); - - /* Message */ - msg_format("%s misses %s.", sym_name, t_name); - break; - } - } - } - - - /* Analyze "visible" monsters only */ - if (visible) - { - /* Count "obvious" attacks (and ones that cause damage) */ - if (obvious || damage || (r_ptr->r_blows[ap_cnt] > 10)) - { - /* Count attacks of this type */ - if (r_ptr->r_blows[ap_cnt] < MAX_UCHAR) - { - r_ptr->r_blows[ap_cnt]++; - } - } - } - } - - /* Blink away */ - if (blinked) - { - msg_format("You and %s flee laughing!", symbiote_name(FALSE)); - - teleport_player(MAX_SIGHT * 2 + 5); - } -} - -/* - * Carried monster can attack too. - * Based on monst_attack_monst. - */ -static void incarnate_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath, - int x, int y) -{ - monster_type *t_ptr = &m_list[m_idx]; - - monster_race *r_ptr; - - monster_race *tr_ptr = race_inf(t_ptr); - - int ap_cnt; - - int ac, rlev, pt; - - char t_name[80]; - - char temp[80]; - - bool_ blinked = FALSE, touched = FALSE; - - byte y_saver = t_ptr->fy; - - byte x_saver = t_ptr->fx; - - - if (!p_ptr->body_monster) return; - - r_ptr = race_info_idx(p_ptr->body_monster, 0); - - /* Not allowed to attack */ - if (r_ptr->flags1 & RF1_NEVER_BLOW) return; - - /* Total armor */ - ac = t_ptr->ac; - - /* Extract the effective monster level */ - rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1); - - /* Get the monster name (or "it") */ - monster_desc(t_name, t_ptr, 0); - - /* Assume no blink */ - blinked = FALSE; - - if (!t_ptr->ml) - { - msg_print("You hear noise."); - } - - /* Scan through all four blows */ - for (ap_cnt = 0; ap_cnt < (p_ptr->num_blow > 4) ? 4 : p_ptr->num_blow; - ap_cnt++) - { - bool_ visible = FALSE; - bool_ obvious = FALSE; - - int power = 0; - int damage = 0; - - cptr act = NULL; - - /* Extract the attack infomation */ - int effect = r_ptr->blow[ap_cnt].effect; - int method = r_ptr->blow[ap_cnt].method; - int d_dice = r_ptr->blow[ap_cnt].d_dice; - int d_side = r_ptr->blow[ap_cnt].d_side; - - /* Stop attacking if the target dies! */ - if (t_ptr->fx != x_saver || t_ptr->fy != y_saver) - break; - - /* Hack -- no more attacks */ - if (!method) break; - - if (blinked) /* Stop! */ - { - /* break; */ - } - - /* Extract visibility (before blink) */ - visible = TRUE; - - /* Extract the attack "power" */ - power = get_attack_power(effect); - - /* Monster hits */ - if (!effect || check_hit2(power, rlev, ac)) - { - /* Always disturbing */ - disturb(1); - - /* Describe the attack method */ - switch (method) - { - case RBM_HIT: - { - act = "hit %s."; - touched = TRUE; - break; - } - - case RBM_TOUCH: - { - act = "touch %s."; - touched = TRUE; - break; - } - - case RBM_PUNCH: - { - act = "punch %s."; - touched = TRUE; - break; - } - - case RBM_KICK: - { - act = "kick %s."; - touched = TRUE; - break; - } - - case RBM_CLAW: - { - act = "claw %s."; - touched = TRUE; - break; - } - - case RBM_BITE: - { - act = "bite %s."; - touched = TRUE; - break; - } - - case RBM_STING: - { - act = "sting %s."; - touched = TRUE; - break; - } - - case RBM_XXX1: - { - act = "XXX1's %s."; - break; - } - - case RBM_BUTT: - { - act = "butt %s."; - touched = TRUE; - break; - } - - case RBM_CRUSH: - { - act = "crush %s."; - touched = TRUE; - break; - } - - case RBM_ENGULF: - { - act = "engulf %s."; - touched = TRUE; - break; - } - - case RBM_CHARGE: - { - act = "charge %s."; - touched = TRUE; - break; - } - - case RBM_CRAWL: - { - act = "crawl on %s."; - touched = TRUE; - break; - } - - case RBM_DROOL: - { - act = "drool on %s."; - touched = FALSE; - break; - } - - case RBM_SPIT: - { - act = "spit on %s."; - touched = FALSE; - break; - } - - case RBM_GAZE: - { - act = "gaze at %s."; - touched = FALSE; - break; - } - - case RBM_WAIL: - { - act = "wail at %s."; - touched = FALSE; - break; - } - - case RBM_SPORE: - { - act = "release spores at %s."; - touched = FALSE; - break; - } - - case RBM_XXX4: - { - act = "project XXX4's at %s."; - touched = FALSE; - break; - } - - case RBM_BEG: - { - act = "beg %s for money."; - touched = FALSE; - t_ptr->csleep = 0; - break; - } - - case RBM_INSULT: - { - act = "insult %s."; - touched = FALSE; - t_ptr->csleep = 0; - break; - } - - case RBM_MOAN: - { - act = "moan at %s."; - touched = FALSE; - t_ptr->csleep = 0; - break; - } - - case RBM_SHOW: - { - act = "sing to %s."; - touched = FALSE; - t_ptr->csleep = 0; - break; - } - } - - /* Message */ - if (act) - { - strfmt(temp, act, t_name); - if (t_ptr->ml) - msg_format("You %s", temp); - - } - - /* Hack -- assume all attacks are obvious */ - obvious = TRUE; - - /* Roll out the damage */ - damage = damroll(d_dice, d_side) + p_ptr->to_d; - - pt = GF_MISSILE; - - /* Apply appropriate damage */ - switch (effect) - { - case 0: - { - damage = 0; - pt = 0; - break; - } - - case RBE_HURT: - case RBE_SANITY: - { - damage -= (damage * ((ac < 150) ? ac : 150) / 250); - break; - } - - case RBE_POISON: - case RBE_DISEASE: - { - pt = GF_POIS; - break; - } - - case RBE_UN_BONUS: - case RBE_UN_POWER: - { - pt = GF_DISENCHANT; - break; - } - - case RBE_EAT_FOOD: - case RBE_EAT_LITE: - { - pt = damage = 0; - break; - } - - case RBE_EAT_ITEM: - case RBE_EAT_GOLD: - { - pt = damage = 0; - if (randint(2) == 1) blinked = TRUE; - break; - } - - case RBE_ACID: - { - pt = GF_ACID; - break; - } - - case RBE_ELEC: - { - pt = GF_ELEC; - break; - } - - case RBE_FIRE: - { - pt = GF_FIRE; - break; - } - - case RBE_COLD: - { - pt = GF_COLD; - break; - } - - case RBE_BLIND: - { - break; - } - - case RBE_HALLU: - case RBE_CONFUSE: - { - pt = GF_CONFUSION; - break; - } - - case RBE_TERRIFY: - { - pt = GF_TURN_ALL; - break; - } - - case RBE_PARALYZE: - { - pt = GF_OLD_SLEEP; /* sort of close... */ - break; - } - - case RBE_LOSE_STR: - case RBE_LOSE_INT: - case RBE_LOSE_WIS: - case RBE_LOSE_DEX: - case RBE_LOSE_CON: - case RBE_LOSE_CHR: - case RBE_LOSE_ALL: - case RBE_PARASITE: - { - break; - } - - case RBE_SHATTER: - { - if (damage > 23) - { - /* Prevent destruction of quest levels and town */ - if (!is_quest(dun_level) && dun_level) - earthquake(p_ptr->py, p_ptr->px, 8); - } - break; - } - - case RBE_EXP_10: - case RBE_EXP_20: - case RBE_EXP_40: - case RBE_EXP_80: - { - pt = GF_NETHER; - break; - } - - case RBE_TIME: - { - pt = GF_TIME; - break; - } - - default: - { - pt = 0; - break; - } - } - - if (pt) - { - /* Do damage if not exploding */ - project(0, 0, t_ptr->fy, t_ptr->fx, - (pt == GF_OLD_SLEEP ? p_ptr->lev * 2 : damage), pt, - PROJECT_KILL | PROJECT_STOP); - - if (touched) - { - /* Aura fire */ - if ((tr_ptr->flags2 & RF2_AURA_FIRE) && - !(r_ptr->flags3 & RF3_IM_FIRE)) - { - if (t_ptr->ml) - { - blinked = FALSE; - msg_format("You are suddenly very hot!"); - if (t_ptr->ml) - tr_ptr->r_flags2 |= RF2_AURA_FIRE; - } - project(m_idx, 0, p_ptr->py, p_ptr->px, - damroll(1 + ((t_ptr->level) / 26), - 1 + ((t_ptr->level) / 17)), - GF_FIRE, PROJECT_KILL | PROJECT_STOP); - } - - /* Aura elec */ - if ((tr_ptr->flags2 & (RF2_AURA_ELEC)) && - !(r_ptr->flags3 & (RF3_IM_ELEC))) - { - if (t_ptr->ml) - { - blinked = FALSE; - msg_format("You get zapped!"); - if (t_ptr->ml) - tr_ptr->r_flags2 |= RF2_AURA_ELEC; - } - project(m_idx, 0, p_ptr->py, p_ptr->px, - damroll(1 + ((t_ptr->level) / 26), - 1 + ((t_ptr->level) / 17)), - GF_ELEC, PROJECT_KILL | PROJECT_STOP); - } - - } - } - } - - /* Monster missed player */ - else - { - /* Analyze failed attacks */ - switch (method) - { - case RBM_HIT: - case RBM_TOUCH: - case RBM_PUNCH: - case RBM_KICK: - case RBM_CLAW: - case RBM_BITE: - case RBM_STING: - case RBM_XXX1: - case RBM_BUTT: - case RBM_CRUSH: - case RBM_ENGULF: - case RBM_CHARGE: - { - /* Disturb */ - disturb(1); - - /* Message */ - msg_format("You miss %s.", t_name); - - break; - } - } - } - - - /* Analyze "visible" monsters only */ - if (visible) - { - /* Count "obvious" attacks (and ones that cause damage) */ - if (obvious || damage || (r_ptr->r_blows[ap_cnt] > 10)) - { - /* Count attacks of this type */ - if (r_ptr->r_blows[ap_cnt] < MAX_UCHAR) - { - r_ptr->r_blows[ap_cnt]++; - } - } - } - } - - /* Blink away */ - if (blinked) - { - msg_print("You flee laughing!"); - - teleport_player(MAX_SIGHT * 2 + 5); - } -} - - -/* - * Fetch an attack description from dam_*.txt files. - */ - -static void flavored_attack(int percent, char *output) -{ - int insanity = (p_ptr->msane - p_ptr->csane) * 100 / p_ptr->msane; - bool_ insane = (rand_int(100) < insanity); - - if (percent < 5) - { - if (!insane) - strcpy(output, "You scratch %s."); - else - get_rnd_line("dam_none.txt", output); - - } - else if (percent < 30) - { - if (!insane) - strcpy(output, "You hit %s."); - else - get_rnd_line("dam_med.txt", output); - } - else if (percent < 60) - { - if (!insane) - strcpy(output, "You wound %s."); - else - get_rnd_line("dam_lots.txt", output); - } - else if (percent < 95) - { - if (!insane) - strcpy(output, "You cripple %s."); - else - get_rnd_line("dam_huge.txt", output); - - } - else - { - if (!insane) - strcpy(output, "You demolish %s."); - else - get_rnd_line("dam_xxx.txt", output); - } -} - - -/* - * Apply the special effects of an attack - */ -void attack_special(monster_type *m_ptr, s32b special, int dam) -{ - char m_name[80]; - - monster_race *r_ptr = race_inf(m_ptr); - - - /* Extract monster name (or "it") */ - monster_desc(m_name, m_ptr, 0); - - /* Special - Cut monster */ - if (special & SPEC_CUT) - { - /* Cut the monster */ - if (r_ptr->flags8 & (RF8_NO_CUT)) - { - if (m_ptr->ml) - { - r_info[m_ptr->r_idx].r_flags8 |= (RF8_NO_CUT); - } - } - else if (rand_int(100) >= r_ptr->level) - { - /* Already partially poisoned */ - if (m_ptr->bleeding) msg_format("%^s is bleeding more strongly.", - m_name); - /* Was not poisoned */ - else - msg_format("%^s is bleeding.", m_name); - - m_ptr->bleeding += dam * 2; - } - } - - /* Special - Poison monster */ - if (special & SPEC_POIS) - { - /* Poison the monster */ - if (r_ptr->flags3 & (RF3_IM_POIS)) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_IM_POIS); - } - } - /* Notice susceptibility */ - else if (r_ptr->flags9 & (RF9_SUSCEP_POIS)) - { - if (m_ptr->ml) - { - r_ptr->r_flags9 |= (RF9_SUSCEP_POIS); - } - /* Already partially poisoned */ - if (m_ptr->poisoned) msg_format("%^s is more poisoned.", m_name); - /* Was not poisoned */ - else - msg_format("%^s is poisoned.", m_name); - - m_ptr->poisoned += dam * 2; - } - else if (rand_int(100) >= r_ptr->level) - { - /* Already partially poisoned */ - if (m_ptr->poisoned) msg_format("%^s is more poisoned.", m_name); - /* Was not poisoned */ - else - msg_format("%^s is poisoned.", m_name); - - m_ptr->poisoned += dam; - } - } -} - - -/* - * Bare handed attacks - */ -static void py_attack_hand(int *k, monster_type *m_ptr, s32b *special) -{ - s16b special_effect = 0, stun_effect = 0, times = 0; - martial_arts *ma_ptr, *old_ptr, *blow_table = ma_blows; - int resist_stun = 0, max = MAX_MA; - monster_race *r_ptr = race_inf(m_ptr); - char m_name[80]; - bool_ desc = FALSE; - bool_ done_crit; - int plev = p_ptr->lev; - - if ((!p_ptr->body_monster) && (p_ptr->mimic_form == resolve_mimic_name("Bear")) && - (p_ptr->melee_style == SKILL_BEAR)) - { - blow_table = bear_blows; - max = MAX_BEAR; - plev = get_skill(SKILL_BEAR); - } - if (p_ptr->melee_style == SKILL_HAND) - { - blow_table = ma_blows; - max = MAX_MA; - plev = get_skill(SKILL_HAND); - } - ma_ptr = &blow_table[0]; - old_ptr = &blow_table[0]; - - /* Extract monster name (or "it") */ - monster_desc(m_name, m_ptr, 0); - - if (r_ptr->flags1 & RF1_UNIQUE) resist_stun += 88; - if (r_ptr->flags3 & RF3_NO_CONF) resist_stun += 44; - if (r_ptr->flags3 & RF3_NO_SLEEP) resist_stun += 44; - if ((r_ptr->flags3 & RF3_UNDEAD) || - (r_ptr->flags3 & RF3_NONLIVING)) resist_stun += 88; - - if (plev) - { - for (times = 0; times < (plev < 7 ? 1 : plev / 7); times++) - { - do - { - ma_ptr = &blow_table[(randint(max)) - 1]; - } - while ((ma_ptr->min_level > plev) || (randint(plev) < ma_ptr->chance)); - - /* keep the highest level attack available we found */ - if ((ma_ptr->min_level > old_ptr->min_level) && - !(p_ptr->stun || p_ptr->confused)) - { - old_ptr = ma_ptr; - - if (wizard && cheat_xtra) - { - msg_print("Attack re-selected."); - } - } - else - { - ma_ptr = old_ptr; - } - } - } - - *k = damroll(ma_ptr->dd, ma_ptr->ds); - - if (ma_ptr->effect & MA_KNEE) - { - if (r_ptr->flags1 & RF1_MALE) - { - if (!desc) msg_format("You hit %s in the groin with your knee!", - m_name); - sound(SOUND_PAIN); - special_effect = MA_KNEE; - } - else if (!desc) msg_format(ma_ptr->desc, m_name); - - desc = TRUE; - } - if (ma_ptr->effect & MA_FULL_SLOW) - { - special_effect = MA_SLOW; - if (!desc) msg_format(ma_ptr->desc, m_name); - - desc = TRUE; - } - if (ma_ptr->effect & MA_SLOW) - { - if (! - ((r_ptr->flags1 & RF1_NEVER_MOVE) || - strchr("UjmeEv$,DdsbBFIJQSXclnw!=?", r_ptr->d_char))) - { - if (!desc) msg_format("You kick %s in the ankle.", m_name); - special_effect = MA_SLOW; - } - else if (!desc) msg_format(ma_ptr->desc, m_name); - - desc = TRUE; - } - if (ma_ptr->effect & MA_STUN) - { - if (ma_ptr->power) - { - stun_effect = (ma_ptr->power / 2) + randint(ma_ptr->power / 2); - } - - if (!desc) msg_format(ma_ptr->desc, m_name); - desc = TRUE; - } - if (ma_ptr->effect & MA_WOUND) - { - if (magik(ma_ptr->power)) - { - *special |= SPEC_CUT; - } - if (!desc) msg_format(ma_ptr->desc, m_name); - desc = TRUE; - } - - *k = critical_norm(plev * (randint(10)), ma_ptr->min_level, *k, -1, &done_crit); - - if ((special_effect & MA_KNEE) && ((*k + p_ptr->to_d) < m_ptr->hp)) - { - msg_format("%^s moans in agony!", m_name); - stun_effect = 7 + randint(13); - resist_stun /= 3; - } - if (((special_effect & MA_FULL_SLOW) || (special_effect & MA_SLOW)) && - ((*k + p_ptr->to_d) < m_ptr->hp)) - { - if (!(r_ptr->flags1 & RF1_UNIQUE) && - (randint(plev) > m_ptr->level) && m_ptr->mspeed > 60) - { - msg_format("%^s starts limping slower.", m_name); - m_ptr->mspeed -= 10; - } - } - - if (stun_effect && ((*k + p_ptr->to_d) < m_ptr->hp)) - { - if (plev > randint(m_ptr->level + resist_stun + 10)) - { - if (m_ptr->stunned) - msg_format("%^s is still stunned.", m_name); - else - msg_format("%^s is stunned.", m_name); - - m_ptr->stunned += (stun_effect); - } - } -} - - -/* - * Apply nazgul effects - */ -void do_nazgul(int *k, int *num, int num_blow, int weap, monster_race *r_ptr, - object_type *o_ptr) -{ - u32b f1, f2, f3, f4, f5, esp; - - bool_ mundane; - bool_ allow_shatter = TRUE; - - /* Extract mundane-ness of the current weapon */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* It should be Slay Evil, Slay Undead, or *Slay Undead* */ - mundane = !(f1 & TR1_SLAY_EVIL) && !(f1 & TR1_SLAY_UNDEAD) && - !(f5 & TR5_KILL_UNDEAD); - - /* Some blades can resist shattering */ - if (f5 & TR5_RES_MORGUL) - allow_shatter = FALSE; - - /* Mega Hack -- Hitting Nazgul is REALY dangerous (ideas from Akhronath) */ - if (r_ptr->flags7 & RF7_NAZGUL) - { - if ((!o_ptr->name2) && (!artifact_p(o_ptr)) && allow_shatter) - { - msg_print("Your weapon *DISINTEGRATES*!"); - *k = 0; - - inc_stack_size_ex(INVEN_WIELD + weap, -1, OPTIMIZE, NO_DESCRIBE); - - /* To stop attacking */ - *num = num_blow; - } - else if (o_ptr->name2) - { - if (mundane) - { - msg_print - ("The Ringwraith is IMPERVIOUS to the mundane weapon."); - *k = 0; - } - - /* 25% chance of getting destroyed */ - if (magik(25) && allow_shatter) - { - msg_print("Your weapon is destroyed!"); - - inc_stack_size_ex(INVEN_WIELD + weap, -1, OPTIMIZE, NO_DESCRIBE); - - /* To stop attacking */ - *num = num_blow; - } - } - else if (artifact_p(o_ptr)) - { - if (mundane) - { - msg_print - ("The Ringwraith is IMPERVIOUS to the mundane weapon."); - *k = 0; - } - - apply_disenchant(INVEN_WIELD + weap); - - /* 1/1000 chance of getting destroyed */ - if (!rand_int(1000) && allow_shatter) - { - msg_print("Your weapon is destroyed!"); - - inc_stack_size_ex(INVEN_WIELD + weap, -1, OPTIMIZE, NO_DESCRIBE); - - /* To stop attacking */ - *num = num_blow; - } - } - - /* If any damage is done, then 25% chance of getting the Black Breath */ - if (*k) - { - if (magik(25)) - { - msg_print("Your foe calls upon your soul!"); - msg_print - ("You feel the Black Breath slowly draining you of life..."); - p_ptr->black_breath = TRUE; - } - } - } -} - - -/* - * Player attacks a (poor, defenseless) creature -RAK- - * - * If no "weapon" is available, then "punch" the monster one time. - */ -void py_attack(int y, int x, int max_blow) -{ - int num = 0, k, bonus, chance; - - s32b special = 0; - - cave_type *c_ptr = &cave[y][x]; - - monster_type *m_ptr = &m_list[c_ptr->m_idx]; - - monster_race *r_ptr = race_inf(m_ptr); - - object_type *o_ptr; - - char m_name[80]; - - bool_ fear = FALSE; - - bool_ mdeath = FALSE; - - bool_ backstab = FALSE; - - bool_ vorpal_cut = FALSE; - - int chaos_effect = 0; - - bool_ stab_fleeing = FALSE; - - bool_ do_quake = FALSE; - - bool_ done_crit = FALSE; - - bool_ drain_msg = TRUE; - - int drain_result = 0, drain_heal = 0; - - int drain_left = MAX_VAMPIRIC_DRAIN; - - /* A massive hack -- life-draining weapons */ - u32b f1, f2, f3, f4, f5, esp; - - int weap; - - /* Disturb the player */ - disturb(0); - - if (r_info[p_ptr->body_monster].flags1 & RF1_NEVER_BLOW) - { - msg_print("You cannot attack in this form!"); - return; - } - - if (get_skill(SKILL_BACKSTAB)) - { - if ((m_ptr->csleep) && (m_ptr->ml)) - { - /* Can't backstab creatures that we can't see, right? */ - backstab = TRUE; - } - else if ((m_ptr->monfear) && (m_ptr->ml)) - { - stab_fleeing = TRUE; - } - } - - /* Disturb the monster */ - m_ptr->csleep = 0; - - - /* Extract monster name (or "it") */ - monster_desc(m_name, m_ptr, 0); - - /* Dont even bother */ - if (r_ptr->flags7 & RF7_IM_MELEE) - { - msg_format("%^s is immune to melee attacks."); - return; - } - - /* Auto-Recall if possible and visible */ - if (m_ptr->ml) monster_race_track(m_ptr->r_idx, m_ptr->ego); - - /* Track a new monster */ - if (m_ptr->ml) health_track(c_ptr->m_idx); - - /* Stop if friendly */ - if ((is_friend(m_ptr) >= 0) && - !(p_ptr->stun || p_ptr->confused || p_ptr->image || - !(m_ptr->ml))) - { - if (!(p_ptr->inventory[INVEN_WIELD].art_name)) - { - msg_format("You stop to avoid hitting %s.", m_name); - return; - } - - if (! - (streq - (quark_str(p_ptr->inventory[INVEN_WIELD].art_name), "'Stormbringer'"))) - { - msg_format("You stop to avoid hitting %s.", m_name); - return; - } - - msg_format("Your black blade greedily attacks %s!", m_name); - } - - /* Break goi/manashield */ - if (p_ptr->invuln) - { - set_invuln(0); - } - if (p_ptr->disrupt_shield) - { - set_disrupt_shield(0); - } - - /* Handle player fear */ - if (p_ptr->afraid) - { - /* Message */ - if (m_ptr->ml) - msg_format("You are too afraid to attack %s!", m_name); - else - msg_format("There is something scary in your way!"); - - /* Done */ - return; - } - - /* Monsters can use barehanded combat, but not weapon combat */ - if ((p_ptr->body_monster) && - (!r_info[p_ptr->body_monster].body_parts[BODY_WEAPON]) && - !(p_ptr->melee_style == SKILL_HAND)) - { - incarnate_monster_attack(c_ptr->m_idx, &fear, &mdeath, y, x); - } - /* Otherwise use your weapon(s) */ - else - { - int weapons; - if (p_ptr->melee_style == SKILL_MASTERY) - weapons = r_info[p_ptr->body_monster].body_parts[BODY_WEAPON]; - else /* SKILL_HAND */ - weapons = 1; - - /* Attack with ALL the weapons !!!!! -- ooh that's gonna hurt YOU */ - for (weap = 0; weap < weapons; ++weap) - { - /* Monster is already dead ? oh :( */ - if (mdeath) break; - - /* Reset the blows counter */ - num = 0; - - /* Access the weapon */ - o_ptr = &p_ptr->inventory[INVEN_WIELD + weap]; - - /* Calculate the "attack quality" */ - bonus = p_ptr->to_h + p_ptr->to_h_melee + o_ptr->to_h; - chance = p_ptr->skill_thn + (bonus * BTH_PLUS_ADJ); - - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - if (!(f4 & TR4_NEVER_BLOW)) - { - int num_blow = p_ptr->num_blow; - - /* Restrict to max_blow(if max_blow >= 0) */ - if ((max_blow >= 0) && - (num_blow > max_blow)) num_blow = max_blow; - - /* Attack once for each legal blow */ - while (num++ < num_blow) - { - /* Test for hit */ - if (test_hit_norm(chance, m_ptr->ac, m_ptr->ml)) - { - /* Sound */ - sound(SOUND_HIT); - - /* Hack -- bare hands do one damage */ - k = 1; - - /* Select a chaotic effect (50% chance) */ - if ((f1 & TR1_CHAOTIC) && (rand_int(2) == 0)) - { - if (randint(5) < 3) - { - /* Vampiric (20%) */ - chaos_effect = 1; - } - else if (rand_int(250) == 0) - { - /* Quake (0.12%) */ - chaos_effect = 2; - } - else if (rand_int(10)) - { - /* Confusion (26.892%) */ - chaos_effect = 3; - } - else if (rand_int(2) == 0) - { - /* Teleport away (1.494%) */ - chaos_effect = 4; - } - else - { - /* Polymorph (1.494%) */ - chaos_effect = 5; - } - } - - /* Vampiric drain */ - if ((f1 & TR1_VAMPIRIC) || (chaos_effect == 1)) - { - if (! - ((r_ptr->flags3 & RF3_UNDEAD) || - (r_ptr->flags3 & RF3_NONLIVING))) - drain_result = m_ptr->hp; - else - drain_result = 0; - } - - if (f1 & TR1_VORPAL && (randint(6) == 1)) - vorpal_cut = TRUE; - else - vorpal_cut = FALSE; - - /* Should we attack with hands or not ? */ - if (p_ptr->melee_style != SKILL_MASTERY) - { - py_attack_hand(&k, m_ptr, &special); - } - /* Handle normal weapon */ - else if (o_ptr->k_idx) - { - k = damroll(o_ptr->dd, o_ptr->ds); - k = tot_dam_aux(o_ptr, k, m_ptr, &special); - - if (backstab) - { - k += (k * - get_skill_scale(SKILL_BACKSTAB, - 100)) / 100; - } - else if (stab_fleeing) - { - k += (k * get_skill_scale(SKILL_BACKSTAB, 70)) / - 100; - } - - if ((p_ptr->impact && ((k > 50) || randint(7) == 1)) - || (chaos_effect == 2)) - { - do_quake = TRUE; - } - - k = critical_norm(o_ptr->weight, o_ptr->to_h, k, o_ptr->tval, &done_crit); - - /* Stunning blow */ - if (magik(get_skill(SKILL_STUN)) && (o_ptr->tval == TV_HAFTED) && (o_ptr->weight > 50) && done_crit) - { - if (!(r_ptr->flags4 & (RF4_BR_SOUN)) && !(r_ptr->flags4 & (RF4_BR_WALL)) && k) - { - int tmp; - - /* Get stunned */ - if (m_ptr->stunned) - { - msg_format("%^s is more dazed.", m_name); - tmp = m_ptr->stunned + get_skill_scale(SKILL_STUN, 30) + 10; - } - else - { - msg_format("%^s is dazed.", m_name); - tmp = get_skill_scale(SKILL_STUN, 60) + 20; - } - - /* Apply stun */ - m_ptr->stunned = (tmp < 200) ? tmp : 200; - } - } - - if (vorpal_cut) - { - int step_k = k; - - msg_format("Your weapon cuts deep into %s!", - m_name); - do - { - k += step_k; - } - while (randint(4) == 1); - } - - PRAY_GOD(GOD_TULKAS) - { - if (magik(wisdom_scale(130) - m_ptr->level) && (p_ptr->grace > 1000)) - { - msg_print("You feel the hand of Tulkas helping your blow."); - k += (o_ptr->to_d + p_ptr->to_d_melee) * 2; - } - else k += o_ptr->to_d + p_ptr->to_d_melee; - } - else k += o_ptr->to_d; - - /* Project some more nasty stuff? */ - if (p_ptr->tim_project) - { - project(0, p_ptr->tim_project_rad, y, x, p_ptr->tim_project_dam, p_ptr->tim_project_gf, p_ptr->tim_project_flag | PROJECT_JUMP); - if (!c_ptr->m_idx) - { - mdeath = TRUE; - break; - } - } - - do_nazgul(&k, &num, num_blow, weap, r_ptr, o_ptr); - - } - - /* Melkor can cast curse for you*/ - PRAY_GOD(GOD_MELKOR) - { - int lv = get_level_s(MELKOR_CURSE, 100); - - if (lv >= 10) - { - int chance = (wisdom_scale(30) * lv) / ((m_ptr->level < 1) ? 1 : m_ptr->level); - - if (chance < 1) chance = 1; - if ((p_ptr->grace > 5000) && magik(chance)) - { - do_melkor_curse(c_ptr->m_idx); - } - } - } - - /* May it clone the monster ? */ - if ((f4 & TR4_CLONE) && magik(30)) - { - msg_format("Oh no! Your weapon clones %^s!", - m_name); - multiply_monster(c_ptr->m_idx, FALSE, TRUE); - } - - /* Apply the player damage bonuses */ - k += p_ptr->to_d + p_ptr->to_d_melee; - - /* No negative damage */ - if (k < 0) k = 0; - - /* Message */ - if (!(backstab || stab_fleeing)) - { - /* These monsters never have flavoured combat msgs */ - if (strchr("vwjmelX,.*", r_ptr->d_char)) - { - msg_format("You hit %s.", m_name); - } - - /* Print flavoured messages if requested */ - else - { - char buff[255]; - - flavored_attack((100 * k) / m_ptr->maxhp, buff); - msg_format(buff, m_name); - } - } - else if (backstab) - { - char buf[80]; - - monster_race_desc(buf, m_ptr->r_idx, m_ptr->ego); - - backstab = FALSE; - - msg_format - ("You cruelly stab the helpless, sleeping %s!", - buf); - } - else - { - char buf[80]; - - monster_race_desc(buf, m_ptr->r_idx, m_ptr->ego); - - msg_format("You backstab the fleeing %s!", buf); - } - - /* Complex message */ - if (wizard) - { - msg_format("You do %d (out of %d) damage.", k, - m_ptr->hp); - } - - if (special) attack_special(m_ptr, special, k); - - /* Damage, check for fear and death */ - if (mon_take_hit(c_ptr->m_idx, k, &fear, NULL)) - { - /* Hack -- High-level warriors can spread their attacks out - * among weaker foes. - */ - if ((has_ability(AB_SPREAD_BLOWS)) && (num < num_blow) && - (energy_use)) - { - energy_use = energy_use * num / num_blow; - } - mdeath = TRUE; - break; - } - - switch (is_friend(m_ptr)) - { - case 1: - msg_format("%^s gets angry!", m_name); - change_side(m_ptr); - break; - case 0: - msg_format("%^s gets angry!", m_name); - m_ptr->status = MSTATUS_NEUTRAL_M; - break; - } - - touch_zap_player(m_ptr); - - /* Are we draining it? A little note: If the monster is - dead, the drain does not work... */ - - if (drain_result) - { - drain_result -= m_ptr->hp; /* Calculate the difference */ - - if (drain_result > 0) /* Did we really hurt it? */ - { - drain_heal = damroll(4, (drain_result / 6)); - - if (cheat_xtra) - { - msg_format("Draining left: %d", drain_left); - } - - if (drain_left) - { - if (drain_heal < drain_left) - { - drain_left -= drain_heal; - } - else - { - drain_heal = drain_left; - drain_left = 0; - } - - if (drain_msg) - { - msg_format - ("Your weapon drains life from %s!", - m_name); - drain_msg = FALSE; - } - - hp_player(drain_heal); - /* We get to keep some of it! */ - } - } - } - - /* Confusion attack */ - if ((p_ptr->confusing) || (chaos_effect == 3)) - { - /* Cancel glowing hands */ - if (p_ptr->confusing) - { - p_ptr->confusing = FALSE; - msg_print("Your hands stop glowing."); - } - - /* Confuse the monster */ - if (r_ptr->flags3 & (RF3_NO_CONF)) - { - if (m_ptr->ml) - { - r_ptr->r_flags3 |= (RF3_NO_CONF); - } - - msg_format("%^s is unaffected.", m_name); - } - else if (rand_int(100) < m_ptr->level) - { - msg_format("%^s is unaffected.", m_name); - } - else - { - msg_format("%^s appears confused.", m_name); - m_ptr->confused += - 10 + rand_int(get_skill(SKILL_COMBAT)) / 5; - } - } - - else if (chaos_effect == 4) - { - msg_format("%^s disappears!", m_name); - teleport_away(c_ptr->m_idx, 50); - num = num_blow + 1; /* Can't hit it anymore! */ - } - - else if ((chaos_effect == 5) && cave_floor_bold(y, x) && - (randint(90) > m_ptr->level)) - { - if (!((r_ptr->flags1 & RF1_UNIQUE) || - (r_ptr->flags4 & RF4_BR_CHAO) || - (m_ptr->mflag & MFLAG_QUEST))) - { - /* Handle polymorph */ - if (do_poly_monster(y, x)) - { - /* Polymorph succeeded */ - msg_format("%^s changes!", m_name); - - /* Hack -- Get new monster */ - m_ptr = &m_list[c_ptr->m_idx]; - - /* Oops, we need a different name... */ - monster_desc(m_name, m_ptr, 0); - - /* Hack -- Get new race */ - r_ptr = race_inf(m_ptr); - - fear = FALSE; - } - else - { - msg_format("%^s resists.", m_name); - } - } - else - { - msg_format("%^s is unaffected.", m_name); - } - } - } - - /* Player misses */ - else - { - /* Sound */ - sound(SOUND_MISS); - - backstab = FALSE; /* Clumsy! */ - - /* Message */ - msg_format("You miss %s.", m_name); - } - } - } - else - { - msg_print("You can't attack with that weapon."); - } - } - } - - /* Carried monster can attack too */ - if ((!mdeath) && m_list[c_ptr->m_idx].hp) - carried_monster_attack(c_ptr->m_idx, &fear, &mdeath, y, x); - - /* Hack -- delay fear messages */ - if (fear && m_ptr->ml) - { - /* Sound */ - sound(SOUND_FLEE); - - /* Message */ - msg_format("%^s flees in terror!", m_name); - } - - /* Mega-Hack -- apply earthquake brand */ - if (do_quake) - { - /* Prevent destruction of quest levels and town */ - if (!is_quest(dun_level) && dun_level) - earthquake(p_ptr->py, p_ptr->px, 10); - } -} - - - -static bool_ pattern_tile(int y, int x) -{ - return ((cave[y][x].feat <= FEAT_PATTERN_XTRA2) && - (cave[y][x].feat >= FEAT_PATTERN_START)); -} - - -static bool_ pattern_seq(int c_y, int c_x, int n_y, int n_x) -{ - if (!(pattern_tile(c_y, c_x)) && !(pattern_tile(n_y, n_x))) - return TRUE; - - if (cave[n_y][n_x].feat == FEAT_PATTERN_START) - { - if ((!(pattern_tile(c_y, c_x))) && - !(p_ptr->confused || p_ptr->stun || p_ptr->image)) - { - if (get_check - ("If you start walking the Straight Road, you must walk the whole way. Ok? ")) - return TRUE; - else - return FALSE; - } - else - return TRUE; - } - else if ((cave[n_y][n_x].feat == FEAT_PATTERN_OLD) || - (cave[n_y][n_x].feat == FEAT_PATTERN_END) || - (cave[n_y][n_x].feat == FEAT_PATTERN_XTRA2)) - { - if (pattern_tile(c_y, c_x)) - { - return TRUE; - } - else - { - msg_print - ("You must start walking the Straight Road from the startpoint."); - return FALSE; - } - } - else if ((cave[n_y][n_x].feat == FEAT_PATTERN_XTRA1) || - (cave[c_y][c_x].feat == FEAT_PATTERN_XTRA1)) - { - return TRUE; - } - else if (cave[c_y][c_x].feat == FEAT_PATTERN_START) - { - if (pattern_tile(n_y, n_x)) - return TRUE; - else - { - msg_print("You must walk the Straight Road in correct order."); - return FALSE; - } - } - else if ((cave[c_y][c_x].feat == FEAT_PATTERN_OLD) || - (cave[c_y][c_x].feat == FEAT_PATTERN_END) || - (cave[c_y][c_x].feat == FEAT_PATTERN_XTRA2)) - { - if (!pattern_tile(n_y, n_x)) - { - msg_print("You may not step off from the Straight Road."); - return FALSE; - } - else - { - return TRUE; - } - } - else - { - if (!pattern_tile(c_y, c_x)) - { - msg_print - ("You must start walking the Straight Road from the startpoint."); - return FALSE; - } - else - { - byte ok_move = FEAT_PATTERN_START; - switch (cave[c_y][c_x].feat) - { - case FEAT_PATTERN_1: - ok_move = FEAT_PATTERN_2; - break; - case FEAT_PATTERN_2: - ok_move = FEAT_PATTERN_3; - break; - case FEAT_PATTERN_3: - ok_move = FEAT_PATTERN_4; - break; - case FEAT_PATTERN_4: - ok_move = FEAT_PATTERN_1; - break; - default: - if (wizard) - msg_format("Funny Straight Road walking, %d.", - cave[c_y][c_x]); - return TRUE; /* Goof-up */ - } - - if ((cave[n_y][n_x].feat == ok_move) || - (cave[n_y][n_x].feat == cave[c_y][c_x].feat)) - return TRUE; - else - { - if (!pattern_tile(n_y, n_x)) - msg_print("You may not step off from the Straight Road."); - else - msg_print - ("You must walk the Straight Road in correct order."); - - return FALSE; - } - } - } -} - - - -bool_ player_can_enter(byte feature) -{ - bool_ pass_wall; - - bool_ only_wall = FALSE; - - - /* Player can not walk through "walls" unless in Shadow Form */ - if (p_ptr->wraith_form || (PRACE_FLAG(PR1_SEMI_WRAITH))) - pass_wall = TRUE; - else - pass_wall = FALSE; - - /* Wall mimicry force the player to stay in walls */ - if (p_ptr->mimic_extra & CLASS_WALL) - { - only_wall = TRUE; - } - - /* Don't let the player kill himself with one keystroke */ - if (p_ptr->wild_mode) - { - if (feature == FEAT_DEEP_WATER) - { - int wt = weight_limit() / 2; - - if ((calc_total_weight() >= wt) && !(p_ptr->ffall)) - return (FALSE); - } - else if (feature == FEAT_SHAL_LAVA || - feature == FEAT_DEEP_LAVA) - { - if (!(p_ptr->resist_fire || - p_ptr->immune_fire || - p_ptr->oppose_fire || - p_ptr->ffall)) - return (FALSE); - } - } - - if (feature == FEAT_TREES) - { - if (p_ptr->fly || - pass_wall || - (has_ability(AB_TREE_WALK)) || - (p_ptr->mimic_form == resolve_mimic_name("Ent")) || - ((p_ptr->grace >= 9000) && (p_ptr->praying) && (p_ptr->pgod == GOD_YAVANNA))) - return (TRUE); - } - - if ((p_ptr->climb) && (f_info[feature].flags1 & FF1_CAN_CLIMB)) - return (TRUE); - if ((p_ptr->fly) && - ((f_info[feature].flags1 & FF1_CAN_FLY) || - (f_info[feature].flags1 & FF1_CAN_LEVITATE))) - return (TRUE); - else if (only_wall && (f_info[feature].flags1 & FF1_FLOOR)) - return (FALSE); - else if ((p_ptr->ffall) && - (f_info[feature].flags1 & FF1_CAN_LEVITATE)) - return (TRUE); - else if ((pass_wall || only_wall) && - (f_info[feature].flags1 & FF1_CAN_PASS)) - return (TRUE); - else if (f_info[feature].flags1 & FF1_NO_WALK) - return (FALSE); - else if ((f_info[feature].flags1 & FF1_WEB) && - ((!(r_info[p_ptr->body_monster].flags7 & RF7_SPIDER)) && (p_ptr->mimic_form != resolve_mimic_name("Spider")))) - return (FALSE); - - return (TRUE); -} - -/* - * Move player in the given direction, with the given "pickup" flag. - * - * This routine should (probably) always induce energy expenditure. - * - * Note that moving will *always* take a turn, and will *always* hit - * any monster which might be in the destination grid. Previously, - * moving into walls was "free" and did NOT hit invisible monsters. - */ -void move_player_aux(int dir, int do_pickup, int run, bool_ disarm) -{ - int y, x, tmp; - - cave_type *c_ptr = &cave[p_ptr->py][p_ptr->px]; - - monster_type *m_ptr; - - monster_race *r_ptr = &r_info[p_ptr->body_monster], *mr_ptr; - - char m_name[80]; - - bool_ stormbringer = FALSE; - - bool_ old_dtrap, new_dtrap; - - bool_ oktomove = TRUE; - - - /* Hack - random movement */ - if (p_ptr->disembodied) - tmp = dir; - else if ((r_ptr->flags1 & RF1_RAND_25) && (r_ptr->flags1 & RF1_RAND_50)) - { - if (randint(100) < 75) - tmp = randint(9); - else - tmp = dir; - } - else if (r_ptr->flags1 & RF1_RAND_50) - { - if (randint(100) < 50) - tmp = randint(9); - else - tmp = dir; - } - else if (r_ptr->flags1 & RF1_RAND_25) - { - if (randint(100) < 25) - tmp = randint(9); - else - tmp = dir; - } - else - { - tmp = dir; - } - - if ((c_ptr->feat == FEAT_ICE) && (!p_ptr->ffall && !p_ptr->fly)) - { - if (magik(70 - p_ptr->lev)) - { - tmp = randint(9); - msg_print("You slip on the icy floor."); - } - else - tmp = dir; - } - - /* Find the result of moving */ - y = p_ptr->py + ddy[tmp]; - x = p_ptr->px + ddx[tmp]; - - /* Examine the destination */ - c_ptr = &cave[y][x]; - - /* Change oldpx and oldpy to place the player well when going back to big mode */ - if (p_ptr->wild_mode) - { - if (ddy[tmp] > 0) p_ptr->oldpy = 1; - if (ddy[tmp] < 0) p_ptr->oldpy = MAX_HGT - 2; - if (ddy[tmp] == 0) p_ptr->oldpy = MAX_HGT / 2; - if (ddx[tmp] > 0) p_ptr->oldpx = 1; - if (ddx[tmp] < 0) p_ptr->oldpx = MAX_WID - 2; - if (ddx[tmp] == 0) p_ptr->oldpx = MAX_WID / 2; - } - - /* Exit the area */ - if (!dun_level && !p_ptr->wild_mode && !is_quest(dun_level) && - ((x == 0) || (x == cur_wid - 1) || (y == 0) || (y == cur_hgt - 1))) - { - /* Can the player enter the grid? */ - if (player_can_enter(c_ptr->mimic)) - { - /* Hack: move to new area */ - if ((y == 0) && (x == 0)) - { - p_ptr->wilderness_y--; - p_ptr->wilderness_x--; - p_ptr->oldpy = cur_hgt - 2; - p_ptr->oldpx = cur_wid - 2; - ambush_flag = FALSE; - } - - else if ((y == 0) && (x == MAX_WID - 1)) - { - p_ptr->wilderness_y--; - p_ptr->wilderness_x++; - p_ptr->oldpy = cur_hgt - 2; - p_ptr->oldpx = 1; - ambush_flag = FALSE; - } - - else if ((y == MAX_HGT - 1) && (x == 0)) - { - p_ptr->wilderness_y++; - p_ptr->wilderness_x--; - p_ptr->oldpy = 1; - p_ptr->oldpx = cur_wid - 2; - ambush_flag = FALSE; - } - - else if ((y == MAX_HGT - 1) && (x == MAX_WID - 1)) - { - p_ptr->wilderness_y++; - p_ptr->wilderness_x++; - p_ptr->oldpy = 1; - p_ptr->oldpx = 1; - ambush_flag = FALSE; - } - - else if (y == 0) - { - p_ptr->wilderness_y--; - p_ptr->oldpy = cur_hgt - 2; - p_ptr->oldpx = x; - ambush_flag = FALSE; - } - - else if (y == cur_hgt - 1) - { - p_ptr->wilderness_y++; - p_ptr->oldpy = 1; - p_ptr->oldpx = x; - ambush_flag = FALSE; - } - - else if (x == 0) - { - p_ptr->wilderness_x--; - p_ptr->oldpx = cur_wid - 2; - p_ptr->oldpy = y; - ambush_flag = FALSE; - } - - else if (x == cur_wid - 1) - { - p_ptr->wilderness_x++; - p_ptr->oldpx = 1; - p_ptr->oldpy = y; - ambush_flag = FALSE; - } - - p_ptr->leaving = TRUE; - - return; - } - } - - /* Some hooks */ - if (process_hooks(HOOK_MOVE, "(d,d)", y, x)) return; - - { - hook_move_in in = { y, x }; - if (process_hooks_new(HOOK_MOVE, &in, NULL)) { - return; /* Prevent movement */ - } - } - - if (p_ptr->dripping_tread > 0) - { - geomancy_random_floor(y, x, FALSE); - p_ptr->dripping_tread -= 1; - if (p_ptr->dripping_tread == 0) - { - msg_print("You stop dripping raw elemental energies."); - } - } - - - /* Get the monster */ - m_ptr = &m_list[c_ptr->m_idx]; - mr_ptr = race_inf(m_ptr); - - if (p_ptr->inventory[INVEN_WIELD].art_name) - { - if (streq(quark_str(p_ptr->inventory[INVEN_WIELD].art_name), "'Stormbringer'")) - stormbringer = TRUE; - } - - /* Hack -- attack monsters */ - if (c_ptr->m_idx && (m_ptr->ml || player_can_enter(c_ptr->feat))) - { - - /* Attack -- only if we can see it OR it is not in a wall */ - if ((is_friend(m_ptr) > 0) && - !(p_ptr->confused || p_ptr->image || !(m_ptr->ml) || p_ptr->stun) && - (pattern_seq(p_ptr->py, p_ptr->px, y, x)) && - ((player_can_enter(cave[y][x].feat)))) - { - m_ptr->csleep = 0; - - /* Extract monster name (or "it") */ - monster_desc(m_name, m_ptr, 0); - - /* Auto-Recall if possible and visible */ - if (m_ptr->ml) monster_race_track(m_ptr->r_idx, m_ptr->ego); - - /* Track a new monster */ - if (m_ptr->ml) health_track(c_ptr->m_idx); - - /* displace? */ - if (stormbringer && (randint(1000) > 666)) - { - py_attack(y, x, -1); - } - else if (cave_floor_bold(p_ptr->py, p_ptr->px) || - (mr_ptr->flags2 & RF2_PASS_WALL)) - { - msg_format("You push past %s.", m_name); - m_ptr->fy = p_ptr->py; - m_ptr->fx = p_ptr->px; - cave[p_ptr->py][p_ptr->px].m_idx = c_ptr->m_idx; - c_ptr->m_idx = 0; - update_mon(cave[p_ptr->py][p_ptr->px].m_idx, TRUE); - } - else - { - msg_format("%^s is in your way!", m_name); - energy_use = 0; - oktomove = FALSE; - } - - /* now continue on to 'movement' */ - } - else - { - py_attack(y, x, -1); - oktomove = FALSE; - } - } - - else if ((c_ptr->feat == FEAT_DARK_PIT) && !p_ptr->ffall) - { - msg_print("You can't cross the chasm."); - running = 0; - oktomove = FALSE; - } - - /* Disarm a visible trap */ - else if (easy_disarm && disarm && (c_ptr->info & (CAVE_TRDT))) - { - (void)do_cmd_disarm_aux(y, x, tmp, do_pickup); - return; - } - - /* Don't step on known traps. */ - else if (disarm && (c_ptr->info & (CAVE_TRDT)) && !(p_ptr->confused || p_ptr->stun || p_ptr->image)) - { - msg_print("You stop to avoid triggering the trap."); - energy_use = 0; - oktomove = FALSE; - } - - /* Player can't enter ? soo bad for him/her ... */ - else if (!player_can_enter(c_ptr->feat)) - { - oktomove = FALSE; - - /* Disturb the player */ - disturb(0); - - if (p_ptr->prob_travel) - { - if (passwall(tmp, TRUE)) return; - } - - /* Notice things in the dark */ - if (!(c_ptr->info & (CAVE_MARK)) && !(c_ptr->info & (CAVE_SEEN))) - { - /* Rubble */ - if (c_ptr->feat == FEAT_RUBBLE) - { - msg_print("You feel some rubble blocking your way."); - c_ptr->info |= (CAVE_MARK); - lite_spot(y, x); - } - - /* Closed door */ - else if (c_ptr->feat < FEAT_SECRET) - { - msg_print("You feel a closed door blocking your way."); - c_ptr->info |= (CAVE_MARK); - lite_spot(y, x); - } - - /* Wall (or secret door) */ - else - { - int feat; - - if (c_ptr->mimic) feat = c_ptr->mimic; - else - feat = f_info[c_ptr->feat].mimic; - - msg_format("You feel %s.", f_text + f_info[feat].block); - c_ptr->info |= (CAVE_MARK); - lite_spot(y, x); - } - } - - /* Notice things */ - else - { - /* Rubble */ - if (c_ptr->feat == FEAT_RUBBLE) - { - if (!easy_tunnel) - { - msg_print("There is rubble blocking your way."); - - if (!(p_ptr->confused || p_ptr->stun || p_ptr->image)) - energy_use = 0; - /* - * Well, it makes sense that you lose time bumping into - * a wall _if_ you are confused, stunned or blind; but - * typing mistakes should not cost you a turn... - */ - } - else - { - do_cmd_tunnel_aux(y, x, dir); - return; - } - } - /* Closed doors */ - else if ((c_ptr->feat >= FEAT_DOOR_HEAD) && (c_ptr->feat <= FEAT_DOOR_TAIL)) - { - if (easy_open) - { - if (easy_open_door(y, x)) return; - } - else - { - msg_print("There is a closed door blocking your way."); - - if (!(p_ptr->confused || p_ptr->stun || p_ptr->image)) - energy_use = 0; - } - } - - /* Wall (or secret door) */ - else - { - if (!easy_tunnel) - { - int feat; - - if (c_ptr->mimic) feat = c_ptr->mimic; - else - feat = f_info[c_ptr->feat].mimic; - - msg_format("There is %s.", f_text + f_info[feat].block); - - if (!(p_ptr->confused || p_ptr->stun || p_ptr->image)) - energy_use = 0; - } - else - { - do_cmd_tunnel_aux(y, x, dir); - return; - } - } - } - - /* Sound */ - sound(SOUND_HITWALL); - } - - /* Normal movement */ - if (!pattern_seq(p_ptr->py, p_ptr->px, y, x)) - { - if (!(p_ptr->confused || p_ptr->stun || p_ptr->image)) - { - energy_use = 0; - } - - disturb(0); /* To avoid a loop with running */ - - oktomove = FALSE; - } - - - /* - * Check trap detection status -- retrieve them here - * because they are used by the movement code as well - */ - old_dtrap = ((cave[p_ptr->py][p_ptr->px].info & CAVE_DETECT) != 0); - new_dtrap = ((cave[y][x].info & CAVE_DETECT) != 0); - - /* Normal movement */ - if (oktomove && running && disturb_detect) - { - /* - * Disturb the player when about to leave the trap detected - * area - */ - if (old_dtrap && !new_dtrap) - { - /* Disturb player */ - disturb(0); - - /* but don't take a turn */ - energy_use = 0; - - /* Tell player why */ - cmsg_print(TERM_VIOLET, "You are about to leave a trap detected zone."); - /* Flush */ - /* msg_print(NULL); */ - - oktomove = FALSE; - } - } - - /* Normal movement */ - if (oktomove) - { - int oy, ox; - int feat; - - /* Rooted means no move */ - if (p_ptr->tim_roots) return; - - /* Save old location */ - oy = p_ptr->py; - ox = p_ptr->px; - - /* Move the player */ - p_ptr->py = y; - p_ptr->px = x; - - if (cave[p_ptr->py][p_ptr->px].mimic) feat = cave[p_ptr->py][p_ptr->px].mimic; - else - feat = cave[p_ptr->py][p_ptr->px].feat; - - /* Some hooks */ - if (process_hooks(HOOK_MOVED, "(d,d)", oy, ox)) return; - - /* Redraw new spot */ - lite_spot(p_ptr->py, p_ptr->px); - - /* Redraw old spot */ - lite_spot(oy, ox); - - /* Sound */ - /* sound(SOUND_WALK); */ - - /* Check for new panel (redraw map) */ - verify_panel(); - - /* Check detection status */ - if (old_dtrap && !new_dtrap) - { - cmsg_print(TERM_VIOLET, "You leave a trap detected zone."); - if (running) msg_print(NULL); - p_ptr->redraw |= (PR_DTRAP); - } - else if (!old_dtrap && new_dtrap) - { - cmsg_print(TERM_L_BLUE, "You enter a trap detected zone."); - if (running) msg_print(NULL); - p_ptr->redraw |= (PR_DTRAP); - } - - /* Update stuff */ - p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE); - - /* Update the monsters */ - p_ptr->update |= (PU_DISTANCE); - - /* Window stuff */ - if (!run) p_ptr->window |= (PW_OVERHEAD); - - /* Some feature descs */ - if (f_info[cave[p_ptr->py][p_ptr->px].feat].text > 1) - { - /* Mega-hack for dungeon branches */ - if ((feat == FEAT_MORE) && c_ptr->special) - { - msg_format("There is %s", d_text + d_info[c_ptr->special].text); - } - else - { - msg_print(f_text + f_info[feat].text); - } - - /* Flush message while running */ - if (running) msg_print(NULL); - } - - /* Spontaneous Searching */ - if ((p_ptr->skill_fos >= 50) || (0 == rand_int(50 - p_ptr->skill_fos))) - { - search(); - } - - /* Continuous Searching */ - if (p_ptr->searching) - { - search(); - } - - /* Handle "objects" */ - carry(do_pickup); - - /* Handle "store doors" */ - if (c_ptr->feat == FEAT_SHOP) - { - /* Disturb */ - disturb(0); - - /* Hack -- Enter store */ - command_new = '_'; - } - - else if (cave[y][x].feat >= FEAT_ALTAR_HEAD && - cave[y][x].feat <= FEAT_ALTAR_TAIL) - { - cptr name = f_name + f_info[cave[y][x].feat].name; - cptr pref = (is_a_vowel(name[0])) ? "an" : "a"; - - msg_format("You see %s %s.", pref, name); - - /* Flush message while running */ - if (running) msg_print(NULL); - } - - /* Discover invisible traps */ - else if ((c_ptr->t_idx != 0) && - !(f_info[cave[y][x].feat].flags1 & FF1_DOOR)) - { - /* Disturb */ - disturb(0); - - if (!(c_ptr->info & (CAVE_TRDT))) - { - /* Message */ - msg_print("You found a trap!"); - - /* Pick a trap */ - pick_trap(p_ptr->py, p_ptr->px); - } - - /* Hit the trap */ - hit_trap(); - } - - /* Execute the inscription */ - else if (c_ptr->inscription) - { - /* Disturb */ - disturb(0); - - msg_format("There is an inscription here: %s", - inscription_info[c_ptr->inscription].text); - if (inscription_info[c_ptr->inscription].when & INSCRIP_EXEC_WALK) - { - execute_inscription(c_ptr->inscription, p_ptr->py, p_ptr->px); - } - } - } - - /* Update wilderness knowledge */ - if (p_ptr->wild_mode) - { - if (wizard) msg_format("y:%d, x:%d", p_ptr->py, p_ptr->px); - - /* Update the known wilderness */ - reveal_wilderness_around_player(p_ptr->py, p_ptr->px, 0, WILDERNESS_SEE_RADIUS); - - /* Walking the wild isnt meaningfull */ - p_ptr->did_nothing = TRUE; - } -} - -void move_player(int dir, int do_pickup, bool_ disarm) -{ - move_player_aux(dir, do_pickup, 0, disarm); -} - - -/* - * Hack -- Grid-based version of see_obstacle - */ -static int see_obstacle_grid(cave_type *c_ptr) -{ - /* - * Hack -- Avoid hitting detected traps, because we cannot rely on - * the CAVE_MARK check below, and traps can be set to nearly - * everything the player can move on to XXX XXX XXX - */ - if (c_ptr->info & (CAVE_TRDT)) return (TRUE); - - - /* Hack -- Handle special cases XXX XXX */ - switch (c_ptr->feat) - { - /* Require levitation */ - case FEAT_DARK_PIT: - case FEAT_DEEP_WATER: - case FEAT_ICE: - { - if (p_ptr->ffall || p_ptr->fly) return (FALSE); - } - - /* Require immunity */ - case FEAT_DEEP_LAVA: - case FEAT_SHAL_LAVA: - { - if (p_ptr->invuln || p_ptr->immune_fire) return (FALSE); - } - } - - - /* "Safe" floor grids aren't obstacles */ - if (f_info[c_ptr->feat].flags1 & FF1_CAN_RUN) return (FALSE); - - /* Must be known to the player */ - if (!(c_ptr->info & (CAVE_MARK))) return (FALSE); - - /* Default */ - return (TRUE); -} - - -/* - * Hack -- Check for a "known wall" or "dangerous" feature (see below) - */ -static int see_obstacle(int dir, int y, int x) -{ - /* Get the new location */ - y += ddy[dir]; - x += ddx[dir]; - - /* Illegal grids are not known walls */ - if (!in_bounds2(y, x)) return (FALSE); - - /* Analyse the grid */ - return (see_obstacle_grid(&cave[y][x])); -} - - -/* - * Hack -- Check for an "unknown corner" (see below) - */ -static int see_nothing(int dir, int y, int x) -{ - /* Get the new location */ - y += ddy[dir]; - x += ddx[dir]; - - /* Illegal grids are unknown */ - if (!in_bounds2(y, x)) return (TRUE); - - /* Memorized grids are always known */ - if (cave[y][x].info & (CAVE_MARK)) return (FALSE); - - /* Non-floor grids are unknown */ - if (!cave_floor_bold(y, x)) return (TRUE); - - /* Viewable door/wall grids are known */ - if (player_can_see_bold(y, x)) return (FALSE); - - /* Default */ - return (TRUE); -} - - - - - -/* - * The running algorithm: -CJS- - * - * In the diagrams below, the player has just arrived in the - * grid marked as '@', and he has just come from a grid marked - * as 'o', and he is about to enter the grid marked as 'x'. - * - * Of course, if the "requested" move was impossible, then you - * will of course be blocked, and will stop. - * - * Overview: You keep moving until something interesting happens. - * If you are in an enclosed space, you follow corners. This is - * the usual corridor scheme. If you are in an open space, you go - * straight, but stop before entering enclosed space. This is - * analogous to reaching doorways. If you have enclosed space on - * one side only (that is, running along side a wall) stop if - * your wall opens out, or your open space closes in. Either case - * corresponds to a doorway. - * - * What happens depends on what you can really SEE. (i.e. if you - * have no light, then running along a dark corridor is JUST like - * running in a dark room.) The algorithm works equally well in - * corridors, rooms, mine tailings, earthquake rubble, etc, etc. - * - * These conditions are kept in static memory: - * find_openarea You are in the open on at least one - * side. - * find_breakleft You have a wall on the left, and will - * stop if it opens - * find_breakright You have a wall on the right, and will - * stop if it opens - * - * To initialize these conditions, we examine the grids adjacent - * to the grid marked 'x', two on each side (marked 'L' and 'R'). - * If either one of the two grids on a given side is seen to be - * closed, then that side is considered to be closed. If both - * sides are closed, then it is an enclosed (corridor) run. - * - * LL L - * @x LxR - * RR @R - * - * Looking at more than just the immediate squares is - * significant. Consider the following case. A run along the - * corridor will stop just before entering the center point, - * because a choice is clearly established. Running in any of - * three available directions will be defined as a corridor run. - * Note that a minor hack is inserted to make the angled corridor - * entry (with one side blocked near and the other side blocked - * further away from the runner) work correctly. The runner moves - * diagonally, but then saves the previous direction as being - * straight into the gap. Otherwise, the tail end of the other - * entry would be perceived as an alternative on the next move. - * - * #.# - * ##.## - * .@x.. - * ##.## - * #.# - * - * Likewise, a run along a wall, and then into a doorway (two - * runs) will work correctly. A single run rightwards from @ will - * stop at 1. Another run right and down will enter the corridor - * and make the corner, stopping at the 2. - * - * #@x 1 - * ########### ###### - * 2 # - * ############# - * # - * - * After any move, the function area_affect is called to - * determine the new surroundings, and the direction of - * subsequent moves. It examines the current player location - * (at which the runner has just arrived) and the previous - * direction (from which the runner is considered to have come). - * - * Moving one square in some direction places you adjacent to - * three or five new squares (for straight and diagonal moves - * respectively) to which you were not previously adjacent, - * marked as '!' in the diagrams below. - * - * ...! ... - * .o@! .o.! - * ...! ..@! - * !!! - * - * You STOP if any of the new squares are interesting in any way: - * for example, if they contain visible monsters or treasure. - * - * You STOP if any of the newly adjacent squares seem to be open, - * and you are also looking for a break on that side. (that is, - * find_openarea AND find_break). - * - * You STOP if any of the newly adjacent squares do NOT seem to be - * open and you are in an open area, and that side was previously - * entirely open. - * - * Corners: If you are not in the open (i.e. you are in a corridor) - * and there is only one way to go in the new squares, then turn in - * that direction. If there are more than two new ways to go, STOP. - * If there are two ways to go, and those ways are separated by a - * square which does not seem to be open, then STOP. - * - * Otherwise, we have a potential corner. There are two new open - * squares, which are also adjacent. One of the new squares is - * diagonally located, the other is straight on (as in the diagram). - * We consider two more squares further out (marked below as ?). - * - * We assign "option" to the straight-on grid, and "option2" to the - * diagonal grid, and "check_dir" to the grid marked 's'. - * - * .s - * @x? - * #? - * - * If they are both seen to be closed, then it is seen that no - * benefit is gained from moving straight. It is a known corner. - * To cut the corner, go diagonally, otherwise go straight, but - * pretend you stepped diagonally into that next location for a - * full view next time. Conversely, if one of the ? squares is - * not seen to be closed, then there is a potential choice. We check - * to see whether it is a potential corner or an intersection/room entrance. - * If the square two spaces straight ahead, and the space marked with 's' - * are both blank, then it is a potential corner and enter if find_examine - * is set, otherwise must stop because it is not a corner. - */ - - - - -/* - * Hack -- allow quick "cycling" through the legal directions - */ -static byte cycle[] = { 1, 2, 3, 6, 9, 8, 7, 4, 1, 2, 3, 6, 9, 8, 7, 4, 1 }; - -/* - * Hack -- map each direction into the "middle" of the "cycle[]" array - */ -static byte chome[] = { 0, 8, 9, 10, 7, 0, 11, 6, 5, 4 }; - -/* - * The direction we are running - */ -static byte find_current; - -/* - * The direction we came from - */ -static byte find_prevdir; - -/* - * We are looking for open area - */ -static bool_ find_openarea; - -/* - * We are looking for a break - */ -static bool_ find_breakright; -static bool_ find_breakleft; - - - -/* - * Initialize the running algorithm for a new direction. - * - * Diagonal Corridor -- allow diaginal entry into corridors. - * - * Blunt Corridor -- If there is a wall two spaces ahead and - * we seem to be in a corridor, then force a turn into the side - * corridor, must be moving straight into a corridor here. ??? - * - * Diagonal Corridor Blunt Corridor (?) - * # # # - * #x# @x# - * @p. p - */ -static void run_init(int dir) -{ - int row, col, deepleft, deepright; - - int i, shortleft, shortright; - - - /* Save the direction */ - find_current = dir; - - /* Assume running straight */ - find_prevdir = dir; - - /* Assume looking for open area */ - find_openarea = TRUE; - - /* Assume not looking for breaks */ - find_breakright = find_breakleft = FALSE; - - /* Assume no nearby walls */ - deepleft = deepright = FALSE; - shortright = shortleft = FALSE; - - /* Find the destination grid */ - row = p_ptr->py + ddy[dir]; - col = p_ptr->px + ddx[dir]; - - /* Extract cycle index */ - i = chome[dir]; - - /* Check for walls */ - if (see_obstacle(cycle[i + 1], p_ptr->py, p_ptr->px)) - { - find_breakleft = TRUE; - shortleft = TRUE; - } - else if (see_obstacle(cycle[i + 1], row, col)) - { - find_breakleft = TRUE; - deepleft = TRUE; - } - - /* Check for walls */ - if (see_obstacle(cycle[i - 1], p_ptr->py, p_ptr->px)) - { - find_breakright = TRUE; - shortright = TRUE; - } - else if (see_obstacle(cycle[i - 1], row, col)) - { - find_breakright = TRUE; - deepright = TRUE; - } - - /* Looking for a break */ - if (find_breakleft && find_breakright) - { - /* Not looking for open area */ - find_openarea = FALSE; - - /* Hack -- allow angled corridor entry */ - if (dir & 0x01) - { - if (deepleft && !deepright) - { - find_prevdir = cycle[i - 1]; - } - else if (deepright && !deepleft) - { - find_prevdir = cycle[i + 1]; - } - } - - /* Hack -- allow blunt corridor entry */ - else if (see_obstacle(cycle[i], row, col)) - { - if (shortleft && !shortright) - { - find_prevdir = cycle[i - 2]; - } - else if (shortright && !shortleft) - { - find_prevdir = cycle[i + 2]; - } - } - } -} - - -/* - * Update the current "run" path - * - * Return TRUE if the running should be stopped - */ -static bool_ run_test(void) -{ - int prev_dir, new_dir, check_dir = 0; - - int row, col; - - int i, max, inv; - - int option = 0, option2 = 0; - - cave_type *c_ptr; - - - /* Where we came from */ - prev_dir = find_prevdir; - - - /* Range of newly adjacent grids */ - max = (prev_dir & 0x01) + 1; - - - /* Look at every newly adjacent square. */ - for (i = -max; i <= max; i++) - { - s16b this_o_idx, next_o_idx = 0; - - - /* New direction */ - new_dir = cycle[chome[prev_dir] + i]; - - /* New location */ - row = p_ptr->py + ddy[new_dir]; - col = p_ptr->px + ddx[new_dir]; - - /* Access grid */ - c_ptr = &cave[row][col]; - - - /* Visible monsters abort running */ - if (c_ptr->m_idx) - { - monster_type *m_ptr = &m_list[c_ptr->m_idx]; - - /* Visible monster */ - if (m_ptr->ml) return (TRUE); - } - - /* Visible objects abort running */ - for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) - { - object_type * o_ptr; - - /* Acquire object */ - o_ptr = &o_list[this_o_idx]; - - /* Acquire next object */ - next_o_idx = o_ptr->next_o_idx; - - /* Visible object */ - if (o_ptr->marked) return (TRUE); - } - - - /* Assume unknown */ - inv = TRUE; - - /* Check memorized grids */ - if (c_ptr->info & (CAVE_MARK)) - { - bool_ notice = TRUE; - - /* - * Examine the terrain -- conditional disturbance - * If we had more flags, we could make these customisable too - */ - switch (c_ptr->feat) - { - case FEAT_DEEP_LAVA: - case FEAT_SHAL_LAVA: - { - /* Ignore */ - if (p_ptr->invuln || p_ptr->immune_fire) notice = FALSE; - - /* Done */ - break; - } - - case FEAT_DEEP_WATER: - case FEAT_ICE: - { - /* Ignore */ - if (p_ptr->ffall || p_ptr->fly) notice = FALSE; - - /* Done */ - break; - } - - /* Open doors */ - case FEAT_OPEN: - case FEAT_BROKEN: - { - /* Option -- ignore */ - if (find_ignore_doors) notice = FALSE; - - /* Done */ - break; - } - - /* - * Stairs - too many of them, should find better ways to - * handle them (not scripting!, because it can be called - * from within the running algo) XXX XXX XXX - */ - case FEAT_LESS: - case FEAT_MORE: - case FEAT_QUEST_ENTER: - case FEAT_QUEST_EXIT: - case FEAT_QUEST_DOWN: - case FEAT_QUEST_UP: - case FEAT_SHAFT_UP: - case FEAT_SHAFT_DOWN: - case FEAT_WAY_LESS: - case FEAT_WAY_MORE: - /* XXX */ - case FEAT_BETWEEN: - case FEAT_BETWEEN2: - { - /* Option -- ignore */ - if (find_ignore_stairs) notice = FALSE; - - /* Done */ - break; - } - } - - /* Check the "don't notice running" flag */ - if (f_info[c_ptr->feat].flags1 & FF1_DONT_NOTICE_RUNNING) - { - notice = FALSE; - } - - /* A detected trap is interesting */ - if (c_ptr->info & (CAVE_TRDT)) notice = TRUE; - - /* Interesting feature */ - if (notice) return (TRUE); - - /* The grid is "visible" */ - inv = FALSE; - } - - /* Mega-Hack -- Maze code removes CAVE_MARK XXX XXX XXX */ - if (c_ptr->info & (CAVE_TRDT)) return (TRUE); - - /* Analyze unknown grids and floors */ - if (inv || cave_floor_bold(row, col)) - { - /* Looking for open area */ - if (find_openarea) - { - /* Nothing */ - } - - /* The first new direction. */ - else if (!option) - { - option = new_dir; - } - - /* Three new directions. Stop running. */ - else if (option2) - { - return (TRUE); - } - - /* Two non-adjacent new directions. Stop running. */ - else if (option != cycle[chome[prev_dir] + i - 1]) - { - return (TRUE); - } - - /* Two new (adjacent) directions (case 1) */ - else if (new_dir & 0x01) - { - check_dir = cycle[chome[prev_dir] + i - 2]; - option2 = new_dir; - } - - /* Two new (adjacent) directions (case 2) */ - else - { - check_dir = cycle[chome[prev_dir] + i + 1]; - option2 = option; - option = new_dir; - } - } - - /* Obstacle, while looking for open area */ - else - { - if (find_openarea) - { - if (i < 0) - { - /* Break to the right */ - find_breakright = TRUE; - } - - else if (i > 0) - { - /* Break to the left */ - find_breakleft = TRUE; - } - } - } - } - - - /* Looking for open area */ - if (find_openarea) - { - /* Hack -- look again */ - for (i = -max; i < 0; i++) - { - new_dir = cycle[chome[prev_dir] + i]; - - row = p_ptr->py + ddy[new_dir]; - col = p_ptr->px + ddx[new_dir]; - - /* Access grid */ - c_ptr = &cave[row][col]; - - /* Unknown grids or non-obstacle */ - if (!see_obstacle_grid(c_ptr)) - { - /* Looking to break right */ - if (find_breakright) - { - return (TRUE); - } - } - - /* Obstacle */ - else - { - /* Looking to break left */ - if (find_breakleft) - { - return (TRUE); - } - } - } - - /* Hack -- look again */ - for (i = max; i > 0; i--) - { - new_dir = cycle[chome[prev_dir] + i]; - - row = p_ptr->py + ddy[new_dir]; - col = p_ptr->px + ddx[new_dir]; - - /* Access grid */ - c_ptr = &cave[row][col]; - - /* Unknown grid or non-obstacle */ - if (!see_obstacle_grid(c_ptr)) - { - /* Looking to break left */ - if (find_breakleft) - { - return (TRUE); - } - } - - /* Obstacle */ - else - { - /* Looking to break right */ - if (find_breakright) - { - return (TRUE); - } - } - } - } - - - /* Not looking for open area */ - else - { - /* No options */ - if (!option) - { - return (TRUE); - } - - /* One option */ - else if (!option2) - { - /* Primary option */ - find_current = option; - - /* No other options */ - find_prevdir = option; - } - - /* Two options, examining corners */ - else if (find_examine && !find_cut) - { - /* Primary option */ - find_current = option; - - /* Hack -- allow curving */ - find_prevdir = option2; - } - - /* Two options, pick one */ - else - { - /* Get next location */ - row = p_ptr->py + ddy[option]; - col = p_ptr->px + ddx[option]; - - /* Don't see that it is closed off. */ - /* This could be a potential corner or an intersection. */ - if (!see_obstacle(option, row, col) || !see_obstacle(check_dir, row, col)) - { - /* Can not see anything ahead and in the direction we */ - /* are turning, assume that it is a potential corner. */ - if (find_examine && - see_nothing(option, row, col) && - see_nothing(option2, row, col)) - { - find_current = option; - find_prevdir = option2; - } - - /* STOP: we are next to an intersection or a room */ - else - { - return (TRUE); - } - } - - /* This corner is seen to be enclosed; we cut the corner. */ - else if (find_cut) - { - find_current = option2; - find_prevdir = option2; - } - - /* This corner is seen to be enclosed, and we */ - /* deliberately go the long way. */ - else - { - find_current = option; - find_prevdir = option2; - } - } - } - - - /* About to hit a known wall, stop */ - if (see_obstacle(find_current, p_ptr->py, p_ptr->px)) - { - return (TRUE); - } - - - /* Failure */ - return (FALSE); -} - - - -/* - * Take one step along the current "run" path - */ -void run_step(int dir) -{ - /* Start running */ - if (dir) - { - /* Hack -- do not start silly run */ - if (see_obstacle(dir, p_ptr->py, p_ptr->px) && - (cave[p_ptr->py + ddy[dir]][p_ptr->px + ddx[dir]].feat != FEAT_TREES)) - { - /* Message */ - msg_print("You cannot run in that direction."); - - /* Disturb */ - disturb(0); - - /* Done */ - return; - } - - /* Calculate torch radius */ - p_ptr->update |= (PU_TORCH); - - /* Initialize */ - run_init(dir); - } - - /* Keep running */ - else - { - /* Update run */ - if (run_test()) - { - /* Disturb */ - disturb(0); - - /* Done */ - return; - } - } - - /* Decrease the run counter */ - if (--running <= 0) return; - - /* Take time */ - energy_use = 100; - - - /* Move the player, using the "pickup" flag */ - move_player_aux(find_current, always_pickup, 1, TRUE); -} - - -/* - * Take care of the various things that can happen when you step - * into a space. (Objects, traps, and stores.) - */ -void step_effects(int y, int x, int do_pickup) -{ - /* Handle "objects" */ - py_pickup_floor(do_pickup); - - /* Handle "store doors" */ - if (cave[y][x].feat == FEAT_SHOP) - { - /* Disturb */ - disturb(0); - - /* Hack -- Enter store */ - command_new = KTRL('V'); - } - - /* Discover/set off traps */ - else if (cave[y][x].t_idx != 0) - { - /* Disturb */ - disturb(0); - - if (!(cave[y][x].info & CAVE_TRDT)) - { - /* Message */ - msg_print("You found a trap!"); - - /* Pick a trap */ - pick_trap(y, x); - } - - /* Hit the trap */ - hit_trap(); - } -} - -/* - * Issue a pet command - */ -void do_cmd_pet(void) -{ - int i = 0; - - int num = 0; - - int powers[36]; - - char power_desc[36][80]; - - bool_ flag, redraw; - - int ask; - - char choice; - - char out_val[160]; - - int pets = 0, pet_ctr = 0; - - bool_ all_pets = FALSE; - - monster_type *m_ptr; - - - for (num = 0; num < 36; num++) - { - powers[num] = 0; - strcpy(power_desc[num], ""); - } - - num = 0; - - if (p_ptr->confused) - { - msg_print("You are too confused to command your pets."); - energy_use = 0; - return; - } - - /* Calculate pets */ - /* Process the monsters (backwards) */ - for (pet_ctr = m_max - 1; pet_ctr >= 1; pet_ctr--) - { - /* Access the monster */ - m_ptr = &m_list[pet_ctr]; - - if (m_ptr->status >= MSTATUS_FRIEND) pets++; - } - - if (pets == 0) - { - msg_print("You have no pets/companions."); - energy_use = 0; - return; - } - else - { - strcpy(power_desc[num], "dismiss pets"); - powers[num++] = 1; - strcpy(power_desc[num], "dismiss companions"); - powers[num++] = 10; - strcpy(power_desc[num], "call pets"); - powers[num++] = 2; - strcpy(power_desc[num], "follow me"); - powers[num++] = 6; - strcpy(power_desc[num], "seek and destroy"); - powers[num++] = 3; - if (p_ptr->pet_open_doors) - strcpy(power_desc[num], "disallow open doors"); - else - strcpy(power_desc[num], "allow open doors"); - powers[num++] = 4; - if (p_ptr->pet_pickup_items) - strcpy(power_desc[num], "disallow pickup items"); - else - strcpy(power_desc[num], "allow pickup items"); - powers[num++] = 5; - strcpy(power_desc[num], "give target to a friend"); - powers[num++] = 7; - strcpy(power_desc[num], "give target to all friends"); - powers[num++] = 8; - strcpy(power_desc[num], "friend forget target"); - powers[num++] = 9; - } - - /* Nothing chosen yet */ - flag = FALSE; - - /* No redraw yet */ - redraw = FALSE; - - /* Build a prompt (accept all spells) */ - if (num <= 26) - { - /* Build a prompt (accept all spells) */ - strnfmt(out_val, 78, - "(Command %c-%c, *=List, ESC=exit) Select a command: ", I2A(0), - I2A(num - 1)); - } - else - { - strnfmt(out_val, 78, - "(Command %c-%c, *=List, ESC=exit) Select a command: ", I2A(0), - '0' + num - 27); - } - - /* Get a command from the user */ - while (!flag && get_com(out_val, &choice)) - { - /* Request redraw */ - if ((choice == ' ') || (choice == '*') || (choice == '?')) - { - /* Show the list */ - if (!redraw) - { - byte y = 1, x = 0; - int ctr = 0; - char dummy[80]; - - strcpy(dummy, ""); - - /* Show list */ - redraw = TRUE; - - /* Save the screen */ - character_icky = TRUE; - Term_save(); - - prt("", y++, x); - - while (ctr < num) - { - strnfmt(dummy, 80, "%c) %s", I2A(ctr), power_desc[ctr]); - prt(dummy, y + ctr, x); - ctr++; - } - - if (ctr < 17) - { - prt("", y + ctr, x); - } - else - { - prt("", y + 17, x); - } - } - - /* Hide the list */ - else - { - /* Hide list */ - redraw = FALSE; - - /* Restore the screen */ - Term_load(); - character_icky = FALSE; - } - - /* Redo asking */ - continue; - } - - if (choice == '\r' && num == 1) - { - choice = 'a'; - } - - if (isalpha(choice)) - { - /* Note verify */ - ask = (isupper(choice)); - - /* Lowercase */ - if (ask) choice = tolower(choice); - - /* Extract request */ - i = (islower(choice) ? A2I(choice) : -1); - } - else - { - ask = FALSE; /* Can't uppercase digits */ - - i = choice - '0' + 26; - } - - /* Totally Illegal */ - if ((i < 0) || (i >= num)) - { - bell(); - continue; - } - - /* Verify it */ - if (ask) - { - char tmp_val[160]; - - /* Prompt */ - strnfmt(tmp_val, 78, "Use %s? ", power_desc[i]); - - /* Belay that order */ - if (!get_check(tmp_val)) continue; - } - - /* Stop the loop */ - flag = TRUE; - } - - /* Restore the screen */ - if (redraw) - { - Term_load(); - character_icky = FALSE; - } - - /* Abort if needed */ - if (!flag) - { - energy_use = 0; - return; - } - - switch (powers[i]) - { - /* forget target */ - case 9: - { - monster_type *m_ptr; - int ii, jj; - - msg_print("Select the friendly monster:"); - if (!tgt_pt(&ii, &jj)) return; - - if (cave[jj][ii].m_idx) - { - m_ptr = &m_list[cave[jj][ii].m_idx]; - - if (m_ptr->status < MSTATUS_PET) - { - msg_print("You cannot give orders to this monster."); - return; - } - - m_ptr->target = -1; - } - break; - } - /* Give target to all */ - case 8: - { - monster_type *m_ptr; - int ii, jj, i; - - - msg_print("Select the target monster:"); - if (!tgt_pt(&ii, &jj)) return; - - if (cave[jj][ii].m_idx) - { - msg_print("Target selected."); - - for (i = m_max - 1; i >= 1; i--) - { - /* Access the monster */ - m_ptr = &m_list[i]; - - if (!m_ptr->r_idx) continue; - - if (m_ptr->status < MSTATUS_PET) continue; - - m_ptr->target = cave[jj][ii].m_idx; - } - } - else - { - msg_print("This is not a correct target."); - return; - } - break; - } - case 1: /* Dismiss pets */ - { - int Dismissed = 0; - - if (get_check("Dismiss all pets? ")) all_pets = TRUE; - - /* Process the monsters (backwards) */ - for (pet_ctr = m_max - 1; pet_ctr >= 1; pet_ctr--) - { - monster_race *r_ptr; - - /* Access the monster */ - m_ptr = &m_list[pet_ctr]; - r_ptr = &r_info[m_ptr->r_idx]; - - if ((!(r_ptr->flags7 & RF7_NO_DEATH)) && ((m_ptr->status == MSTATUS_PET) || (m_ptr->status == MSTATUS_FRIEND))) /* Get rid of it! */ - { - bool_ checked = FALSE; - char command; - bool_ delete_this = FALSE; - - if (all_pets) - { - delete_this = TRUE; - } - else - { - char friend_name[80], check_friend[80]; - monster_desc(friend_name, m_ptr, 0x80); - strnfmt(check_friend, 80, "Dismiss %s? (Escape to cancel)", friend_name); - - while (!checked) - { - if (!get_com(check_friend, &command)) - { - /* get out of loop */ - checked = TRUE; - pet_ctr = 0; - } - else switch (command) - { - case 'Y': - case 'y': - delete_this = TRUE; - checked = TRUE; - break; - case 'n': - case 'N': - checked = TRUE; - break; - default: - bell(); - break; - } - } - } - - if (delete_this) - { - delete_monster_idx(pet_ctr); - Dismissed++; - } - } - } - - msg_format("You have dismissed %d pet%s.", Dismissed, - (Dismissed == 1 ? "" : "s")); - break; - } - case 10: /* Dismiss companions */ - { - int Dismissed = 0; - - if (get_check("Dismiss all companions? ")) all_pets = TRUE; - - /* Process the monsters (backwards) */ - for (pet_ctr = m_max - 1; pet_ctr >= 1; pet_ctr--) - { - monster_race *r_ptr; - - /* Access the monster */ - m_ptr = &m_list[pet_ctr]; - r_ptr = &r_info[m_ptr->r_idx]; - - if ((!(r_ptr->flags7 & RF7_NO_DEATH)) && ((m_ptr->status == MSTATUS_COMPANION))) /* Get rid of it! */ - { - bool_ delete_this = FALSE; - - if (all_pets) - delete_this = TRUE; - else - { - char friend_name[80], check_friend[80]; - monster_desc(friend_name, m_ptr, 0x80); - strnfmt(check_friend, 80, "Dismiss %s? ", friend_name); - - if (get_check(check_friend)) - delete_this = TRUE; - } - - if (delete_this) - { - delete_monster_idx(pet_ctr); - Dismissed++; - } - } - } - - msg_format("You have dismissed %d companion%s.", Dismissed, - (Dismissed == 1 ? "" : "s")); - break; - } - /* Call pets */ - case 2: - { - p_ptr->pet_follow_distance = 1; - break; - } - /* "Seek and destroy" */ - case 3: - { - p_ptr->pet_follow_distance = 255; - break; - } - /* flag - allow pets to open doors */ - case 4: - { - p_ptr->pet_open_doors = !p_ptr->pet_open_doors; - break; - } - /* flag - allow pets to pickup items */ - case 5: - { - p_ptr->pet_pickup_items = !p_ptr->pet_pickup_items; - - /* Drop objects being carried by pets */ - if (!p_ptr->pet_pickup_items) - { - for (pet_ctr = m_max - 1; pet_ctr >= 1; pet_ctr--) - { - /* Access the monster */ - m_ptr = &m_list[pet_ctr]; - - if (m_ptr->status >= MSTATUS_PET) - { - monster_drop_carried_objects(m_ptr); - } - } - } - - break; - } - /* "Follow Me" */ - case 6: - { - p_ptr->pet_follow_distance = 6; - break; - } - } -} - -/* - * Incarnate into a body - */ -bool_ do_cmd_integrate_body() -{ - cptr q, s; - - int item; - - object_type *o_ptr; - - - if (!p_ptr->disembodied) - { - msg_print("You are already in a body."); - return FALSE; - } - - /* Restrict choices to monsters */ - item_tester_tval = TV_CORPSE; - - /* Get an item */ - q = "Incarnate in which body? "; - s = "You have no corpse to incarnate in."; - if (!get_item(&item, q, s, (USE_FLOOR))) return FALSE; - - o_ptr = &o_list[0 - item]; - - if (o_ptr->sval != SV_CORPSE_CORPSE) - { - msg_print("You must select a corpse."); - return FALSE; - } - - p_ptr->body_monster = o_ptr->pval2; - p_ptr->chp = o_ptr->pval3; - - floor_item_increase(0 - item, -1); - floor_item_describe(0 - item); - floor_item_optimize(0 - item); - - msg_print("Your spirit is incarnated in your new body."); - p_ptr->wraith_form = FALSE; - p_ptr->disembodied = FALSE; - do_cmd_redraw(); - - return TRUE; -} - -/* - * Leave a body - */ -bool_ do_cmd_leave_body(bool_ drop_body) -{ - object_type *o_ptr, forge; - - monster_race *r_ptr = &r_info[p_ptr->body_monster]; - - int i; - - - if (p_ptr->disembodied) - { - msg_print("You are already disembodied."); - return FALSE; - } - - for (i = INVEN_WIELD; i < INVEN_TOTAL; i++) - { - if (p_ptr->body_parts[i - INVEN_WIELD] && p_ptr->inventory[i].k_idx && - cursed_p(&p_ptr->inventory[i])) - { - msg_print("A cursed object is preventing you from leaving your body."); - return FALSE; - } - } - - if (drop_body) - { - if (magik(25 + get_skill_scale(SKILL_POSSESSION, 25) + get_skill(SKILL_PRESERVATION))) - { - o_ptr = &forge; - object_prep(o_ptr, lookup_kind(TV_CORPSE, SV_CORPSE_CORPSE)); - o_ptr->number = 1; - o_ptr->pval = 0; - o_ptr->pval2 = p_ptr->body_monster; - o_ptr->pval3 = p_ptr->chp; - o_ptr->weight = (r_ptr->weight + rand_int(r_ptr->weight) / 10) + 1; - object_aware(o_ptr); - object_known(o_ptr); - o_ptr->ident |= IDENT_STOREB; - - /* Unique corpses are unique */ - if (r_ptr->flags1 & RF1_UNIQUE) - { - o_ptr->name1 = 201; - } - - drop_near(o_ptr, -1, p_ptr->py, p_ptr->px); - } - else - msg_print - ("You do not manage to keep the corpse from rotting away."); - } - - msg_print("Your spirit leaves your body."); - p_ptr->disembodied = TRUE; - - /* Turn into a lost soul(just for the picture) */ - p_ptr->body_monster = test_monster_name("Lost soul"); - do_cmd_redraw(); - - return (TRUE); -} - - -bool_ execute_inscription(byte i, byte y, byte x) -{ - cave_type *c_ptr = &cave[y][x]; - - - /* Not enough mana in the current grid */ - if (c_ptr->mana < inscription_info[i].mana) return (TRUE); - - - /* Reduce the grid mana -- note: it can't be restored */ - c_ptr->mana -= inscription_info[i].mana; - - /* Analyse inscription type */ - switch (i) - { - case INSCRIP_LIGHT: - { - msg_print("The inscription shines in a bright light!"); - lite_room(y, x); - - break; - } - - case INSCRIP_DARK: - { - msg_print("The inscription is enveloped in a dark aura!"); - unlite_room(y, x); - - break; - } - - case INSCRIP_STORM: - { - msg_print("The inscription releases a powerful storm!"); - project(0, 3, y, x, damroll(10, 10), - GF_ELEC, PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | - PROJECT_KILL | PROJECT_JUMP); - - break; - } - - case INSCRIP_PROTECTION: - { - return (FALSE); - - break; - } - - case INSCRIP_DWARF_SUMMON: - { - int yy = y, xx = x; - - scatter(&yy, &xx, y, x, 3); - place_monster_one(yy, xx, test_monster_name("Dwarven Warrior"), - 0, FALSE, MSTATUS_FRIEND); - - break; - } - - case INSCRIP_CHASM: - { - monster_type *m_ptr; - monster_race *r_ptr; - cave_type *c_ptr; - int ii = x, ij = y; - - cave_set_feat(ij, ii, FEAT_DARK_PIT); - msg_print("A chasm appears in the floor!"); - - if (cave[ij][ii].m_idx) - { - m_ptr = &m_list[cave[ij][ii].m_idx]; - r_ptr = race_inf(m_ptr); - - if (r_ptr->flags7 & RF7_CAN_FLY) - { - msg_print("The monster simply flies over the chasm."); - } - else - { - if (!(r_ptr->flags1 & RF1_UNIQUE)) - { - msg_print("The monster falls in the chasm!"); - delete_monster_idx(cave[ij][ii].m_idx); - } - } - } - - if (cave[ij][ii].o_idx) - { - s16b this_o_idx, next_o_idx = 0; - - c_ptr = &cave[ij][ii]; - - /* Scan all objects in the grid */ - for (this_o_idx = c_ptr->o_idx; this_o_idx; - this_o_idx = next_o_idx) - { - object_type * o_ptr; - bool_ plural = FALSE; - - char o_name[80]; - - /* Acquire object */ - o_ptr = &o_list[this_o_idx]; - - if (o_ptr->number > 1) plural = TRUE; - - /* Acquire next object */ - next_o_idx = o_ptr->next_o_idx; - - /* Effect "observed" */ - if (o_ptr->marked) - { - object_desc(o_name, o_ptr, FALSE, 0); - } - - /* Artifacts get to resist */ - if (o_ptr->name1) - { - /* Observe the resist */ - if (o_ptr->marked) - { - msg_format("The %s %s simply fly over the chasm!", - o_name, (plural ? "are" : "is")); - } - } - - /* Kill it */ - else - { - /* Delete the object */ - delete_object_idx(this_o_idx); - - /* Redraw */ - lite_spot(ij, ii); - } - } - } - - break; - } - - case INSCRIP_BLACK_FIRE: - { - msg_print("The inscription releases a blast of hellfire!"); - project(0, 3, y, x, 200, - GF_HELL_FIRE, PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | - PROJECT_KILL | PROJECT_JUMP); - - break; - } - } - - return (TRUE); -} - - -/* - * Choose an inscription and engrave it - */ -void do_cmd_engrave() -{ - char buf[41] = ""; - - byte i; - - strnfmt(buf, 41, "%s", inscription_info[cave[p_ptr->py][p_ptr->px].inscription].text); - - get_string("Engrave what? ", buf, 40); - - /* Silently do nothing when player his escape or enters an empty string */ - if (!buf[0]) return; - - for (i = 0; i < MAX_INSCRIPTIONS; i++) - { - if (!strcmp(inscription_info[i].text, buf)) - { - if (inscription_info[i].know) - { - /* Save the inscription */ - cave[p_ptr->py][p_ptr->px].inscription = i; - } - else - msg_print("You can't use this inscription for now."); - } - } - - /* Execute the inscription */ - if (inscription_info[cave[p_ptr->py][p_ptr->px].inscription].when & INSCRIP_EXEC_ENGRAVE) - { - execute_inscription(cave[p_ptr->py][p_ptr->px].inscription, p_ptr->py, p_ptr->px); - } - - energy_use += 300; -} - - -/* - * Let's do a spinning around attack: -- DG -- - * aDb - * y@k - * ooT - * Ah ... all of those will get hit. - */ -void do_spin() -{ - int i, j; - - - msg_print("You start spinning around..."); - - for (j = p_ptr->py - 1; j <= p_ptr->py + 1; j++) - { - for (i = p_ptr->px - 1; i <= p_ptr->px + 1; i++) - { - /* Avoid stupid bugs */ - if (in_bounds(j, i) && cave[j][i].m_idx) - py_attack(j, i, 1); - } - } -} diff --git a/src/cmd1.cc b/src/cmd1.cc new file mode 100644 index 00000000..ff493174 --- /dev/null +++ b/src/cmd1.cc @@ -0,0 +1,5147 @@ +/* File: cmd1.c */ + +/* Purpose: Movement commands (part 1) */ + +/* + * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke + * + * This software may be copied and distributed for educational, research, and + * not for profit purposes provided that this copyright and statement are + * included in all such copies. + */ + +#include "angband.h" + +#include "quark.h" +#include "hooks.h" + +#define MAX_VAMPIRIC_DRAIN 100 + + +/* + * Determine if the player "hits" a monster (normal combat). + * Note -- Always miss 5%, always hit 5%, otherwise random. + */ +bool_ test_hit_fire(int chance, int ac, int vis) +{ + int k; + + + /* Percentile dice */ + k = rand_int(100); + + /* Hack -- Instant miss or hit */ + if (k < 10) return (k < 5); + + /* Never hit */ + if (chance <= 0) return (FALSE); + + /* Invisible monsters are harder to hit */ + if (!vis) chance = (chance + 1) / 2; + + /* Power competes against armor */ + if (rand_int(chance + luck( -10, 10)) < (ac * 3 / 4)) return (FALSE); + + /* Assume hit */ + return (TRUE); +} + + + +/* + * Determine if the player "hits" a monster (normal combat). + * + * Note -- Always miss 5%, always hit 5%, otherwise random. + */ +bool_ test_hit_norm(int chance, int ac, int vis) +{ + int k; + + + /* Percentile dice */ + k = rand_int(100); + + /* Hack -- Instant miss or hit */ + if (k < 10) return (k < 5); + + /* Wimpy attack never hits */ + if (chance <= 0) return (FALSE); + + /* Penalize invisible targets */ + if (!vis) chance = (chance + 1) / 2; + + /* Power must defeat armor */ + if (rand_int(chance + luck( -10, 10)) < (ac * 3 / 4)) return (FALSE); + + /* Assume hit */ + return (TRUE); +} + + + +/* + * Critical hits (from objects thrown by player) + * Factor in item weight, total plusses, and player level. + */ +s16b critical_shot(int weight, int plus, int dam, int skill) +{ + int i, k; + + + /* Extract "shot" power */ + i = (weight + ((p_ptr->to_h + plus) * 4) + + get_skill_scale(skill, 100)); + i += 50 * p_ptr->xtra_crit; + i += luck( -100, 100); + + /* Critical hit */ + if (randint(5000) <= i) + { + k = weight + randint(500); + + if (k < 500) + { + msg_print("It was a good hit!"); + dam = 2 * dam + 5; + } + else if (k < 1000) + { + msg_print("It was a great hit!"); + dam = 2 * dam + 10; + } + else + { + msg_print("It was a superb hit!"); + dam = 3 * dam + 15; + } + } + + return (dam); +} + +/* + * Critical hits (by player) + * + * Factor in weapon weight, total plusses, player level. + */ +s16b critical_norm(int weight, int plus, int dam, int weapon_tval, bool_ *done_crit) +{ + int i, k, num = randint(5000); + + *done_crit = FALSE; + + /* Extract "blow" power */ + i = (weight + ((p_ptr->to_h + plus) * 5) + + get_skill_scale(p_ptr->melee_style, 150)); + i += 50 * p_ptr->xtra_crit; + if ((weapon_tval == TV_SWORD) && (weight < 50) && get_skill(SKILL_CRITS)) + { + i += get_skill_scale(SKILL_CRITS, 40 * 50); + } + i += luck( -100, 100); + + /* Force good strikes */ + if (p_ptr->tim_deadly) + { + set_tim_deadly(p_ptr->tim_deadly - 1); + msg_print("It was a *GREAT* hit!"); + dam = 3 * dam + 20; + *done_crit = TRUE; + } + + /* Chance */ + else if (num <= i) + { + k = weight + randint(650); + if ((weapon_tval == TV_SWORD) && (weight < 50) && get_skill(SKILL_CRITS)) + { + k += get_skill_scale(SKILL_CRITS, 400); + } + + if (k < 400) + { + msg_print("It was a good hit!"); + dam = 2 * dam + 5; + } + else if (k < 700) + { + msg_print("It was a great hit!"); + dam = 2 * dam + 10; + } + else if (k < 900) + { + msg_print("It was a superb hit!"); + dam = 3 * dam + 15; + } + else if (k < 1300) + { + msg_print("It was a *GREAT* hit!"); + dam = 3 * dam + 20; + } + else + { + msg_print("It was a *SUPERB* hit!"); + dam = ((7 * dam) / 2) + 25; + } + *done_crit = TRUE; + } + + return (dam); +} + + + +/* + * Extract the "total damage" from a given object hitting a given monster. + * + * Note that "flasks of oil" do NOT do fire damage, although they + * certainly could be made to do so. XXX XXX + * + * Note that most brands and slays are x3, except Slay Animal (x2), + * Slay Evil (x2), and Kill dragon (x5). + */ +s16b tot_dam_aux(object_type *o_ptr, int tdam, monster_type *m_ptr, + s32b *special) +{ + int mult = 1; + + monster_race *r_ptr = race_inf(m_ptr); + + u32b f1, f2, f3, f4, f5, esp; + + + /* Extract the flags */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* Some "weapons" and "ammo" do extra damage */ + switch (o_ptr->tval) + { + case TV_SHOT: + case TV_ARROW: + case TV_BOLT: + case TV_BOOMERANG: + case TV_HAFTED: + case TV_POLEARM: + case TV_SWORD: + case TV_AXE: + case TV_DIGGING: + { + /* Slay Animal */ + if ((f1 & (TR1_SLAY_ANIMAL)) && (r_ptr->flags3 & (RF3_ANIMAL))) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_ANIMAL); + } + + if (mult < 2) mult = 2; + } + + /* Slay Evil */ + if ((f1 & (TR1_SLAY_EVIL)) && (r_ptr->flags3 & (RF3_EVIL))) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_EVIL); + } + + if (mult < 2) mult = 2; + } + + /* Slay Undead */ + if ((f1 & (TR1_SLAY_UNDEAD)) && (r_ptr->flags3 & (RF3_UNDEAD))) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_UNDEAD); + } + + if (mult < 3) mult = 3; + } + + /* Slay Demon */ + if ((f1 & (TR1_SLAY_DEMON)) && (r_ptr->flags3 & (RF3_DEMON))) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_DEMON); + } + + if (mult < 3) mult = 3; + } + + /* Slay Orc */ + if ((f1 & (TR1_SLAY_ORC)) && (r_ptr->flags3 & (RF3_ORC))) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_ORC); + } + + if (mult < 3) mult = 3; + } + + /* Slay Troll */ + if ((f1 & (TR1_SLAY_TROLL)) && (r_ptr->flags3 & (RF3_TROLL))) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_TROLL); + } + + if (mult < 3) mult = 3; + } + + /* Slay Giant */ + if ((f1 & (TR1_SLAY_GIANT)) && (r_ptr->flags3 & (RF3_GIANT))) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_GIANT); + } + + if (mult < 3) mult = 3; + } + + /* Slay Dragon */ + if ((f1 & (TR1_SLAY_DRAGON)) && (r_ptr->flags3 & (RF3_DRAGON))) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_DRAGON); + } + + if (mult < 3) mult = 3; + } + + /* Execute Dragon */ + if ((f1 & (TR1_KILL_DRAGON)) && (r_ptr->flags3 & (RF3_DRAGON))) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_DRAGON); + } + + if (mult < 5) mult = 5; + } + + /* Execute Undead */ + if ((f5 & (TR5_KILL_UNDEAD)) && (r_ptr->flags3 & (RF3_UNDEAD))) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_UNDEAD); + } + + if (mult < 5) mult = 5; + } + + /* Execute Demon */ + if ((f5 & (TR5_KILL_DEMON)) && (r_ptr->flags3 & (RF3_DEMON))) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_DEMON); + } + + if (mult < 5) mult = 5; + } + + + /* Brand (Acid) */ + if (f1 & (TR1_BRAND_ACID)) + { + /* Notice immunity */ + if (r_ptr->flags3 & (RF3_IM_ACID)) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_IM_ACID); + } + } + + /* Notice susceptibility */ + else if (r_ptr->flags9 & (RF9_SUSCEP_ACID)) + { + if (m_ptr->ml) + { + r_ptr->r_flags9 |= (RF9_SUSCEP_ACID); + } + if (mult < 6) mult = 6; + } + + /* Otherwise, take the damage */ + else + { + if (mult < 3) mult = 3; + } + } + + /* Brand (Elec) */ + if (f1 & (TR1_BRAND_ELEC)) + { + /* Notice immunity */ + if (r_ptr->flags3 & (RF3_IM_ELEC)) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_IM_ELEC); + } + } + + /* Notice susceptibility */ + else if (r_ptr->flags9 & (RF9_SUSCEP_ELEC)) + { + if (m_ptr->ml) + { + r_ptr->r_flags9 |= (RF9_SUSCEP_ELEC); + } + if (mult < 6) mult = 6; + } + + /* Otherwise, take the damage */ + else + { + if (mult < 3) mult = 3; + } + } + + /* Brand (Fire) */ + if (f1 & (TR1_BRAND_FIRE)) + { + /* Notice immunity */ + if (r_ptr->flags3 & (RF3_IM_FIRE)) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_IM_FIRE); + } + } + + /* Notice susceptibility */ + else if (r_ptr->flags3 & (RF3_SUSCEP_FIRE)) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_SUSCEP_FIRE); + } + if (mult < 6) mult = 6; + } + + /* Otherwise, take the damage */ + else + { + if (mult < 3) mult = 3; + } + } + + /* Brand (Cold) */ + if (f1 & (TR1_BRAND_COLD)) + { + /* Notice immunity */ + if (r_ptr->flags3 & (RF3_IM_COLD)) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_IM_COLD); + } + } + + /* Notice susceptibility */ + else if (r_ptr->flags3 & (RF3_SUSCEP_COLD)) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_SUSCEP_COLD); + } + if (mult < 6) mult = 6; + } + + /* Otherwise, take the damage */ + else + { + if (mult < 3) mult = 3; + } + } + + /* Brand (Poison) */ + if (f1 & (TR1_BRAND_POIS) || (p_ptr->tim_poison)) + { + /* Notice immunity */ + if (r_ptr->flags3 & (RF3_IM_POIS)) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_IM_POIS); + } + } + + /* Notice susceptibility */ + else if (r_ptr->flags9 & (RF9_SUSCEP_POIS)) + { + if (m_ptr->ml) + { + r_ptr->r_flags9 |= (RF9_SUSCEP_POIS); + } + if (mult < 6) mult = 6; + if (magik(95)) *special |= SPEC_POIS; + } + + /* Otherwise, take the damage */ + else + { + if (mult < 3) mult = 3; + if (magik(50)) *special |= SPEC_POIS; + } + } + + /* Wounding */ + if (f5 & (TR5_WOUNDING)) + { + /* Notice immunity */ + if (r_ptr->flags8 & (RF8_NO_CUT)) + { + if (m_ptr->ml) + { + r_info[m_ptr->r_idx].r_flags8 |= (RF8_NO_CUT); + } + } + + /* Otherwise, take the damage */ + else + { + if (magik(50)) *special |= SPEC_CUT; + } + } + break; + } + } + + + /* Return the total damage */ + return (tdam * mult); +} + + +/* + * Search for hidden things + */ +void search(void) +{ + int y, x, chance; + + s16b this_o_idx, next_o_idx = 0; + + cave_type *c_ptr; + + + /* Start with base search ability */ + chance = p_ptr->skill_srh; + + /* Penalize various conditions */ + if (p_ptr->blind || no_lite()) chance = chance / 10; + if (p_ptr->confused || p_ptr->image) chance = chance / 10; + + /* Search the nearby grids, which are always in bounds */ + for (y = (p_ptr->py - 1); y <= (p_ptr->py + 1); y++) + { + for (x = (p_ptr->px - 1); x <= (p_ptr->px + 1); x++) + { + /* Sometimes, notice things */ + if (rand_int(100) < chance) + { + /* Access the grid */ + c_ptr = &cave[y][x]; + + /* Invisible trap */ + if ((c_ptr->t_idx != 0) && !(c_ptr->info & CAVE_TRDT)) + { + /* Pick a trap */ + pick_trap(y, x); + + /* Message */ + msg_print("You have found a trap."); + + /* Disturb */ + disturb(0); + } + + /* Secret door */ + if (c_ptr->feat == FEAT_SECRET) + { + /* Message */ + msg_print("You have found a secret door."); + + /* Pick a door XXX XXX XXX */ + cave_set_feat(y, x, FEAT_DOOR_HEAD + 0x00); + cave[y][x].mimic = 0; + lite_spot(y, x); + + /* Disturb */ + disturb(0); + } + + /* Scan all objects in the grid */ + for (this_o_idx = c_ptr->o_idx; this_o_idx; + this_o_idx = next_o_idx) + { + object_type * o_ptr; + + /* Acquire object */ + o_ptr = &o_list[this_o_idx]; + + /* Acquire next object */ + next_o_idx = o_ptr->next_o_idx; + + /* Skip non-chests */ + if (o_ptr->tval != TV_CHEST) continue; + + /* Skip non-trapped chests */ + if (!o_ptr->pval) continue; + + /* Identify once */ + if (!object_known_p(o_ptr)) + { + /* Message */ + msg_print("You have discovered a trap on the chest!"); + + /* Know the trap */ + object_known(o_ptr); + + /* Notice it */ + disturb(0); + } + } + } + } + } +} + + + + +/* + * Player "wants" to pick up an object or gold. + * Note that we ONLY handle things that can be picked up. + * See "move_player()" for handling of other things. + */ +void carry(int pickup) +{ + if (!p_ptr->disembodied) + { + py_pickup_floor(pickup); + } +} + + +/* + * Handle player hitting a real trap + */ +static void hit_trap(void) +{ + bool_ ident = FALSE; + + cave_type *c_ptr; + + + /* Disturb the player */ + disturb(0); + + /* Get the cave grid */ + c_ptr = &cave[p_ptr->py][p_ptr->px]; + if (c_ptr->t_idx != 0) + { + ident = player_activate_trap_type(p_ptr->py, p_ptr->px, NULL, -1); + if (ident) + { + t_info[c_ptr->t_idx].ident = TRUE; + msg_format("You identified the trap as %s.", + t_name + t_info[c_ptr->t_idx].name); + } + } +} + + +void touch_zap_player(monster_type *m_ptr) +{ + int aura_damage = 0; + + monster_race *r_ptr = race_inf(m_ptr); + + + if (r_ptr->flags2 & (RF2_AURA_FIRE)) + { + if (!(p_ptr->immune_fire)) + { + char aura_dam[80]; + + aura_damage = + damroll(1 + (m_ptr->level / 26), 1 + (m_ptr->level / 17)); + + /* Hack -- Get the "died from" name */ + monster_desc(aura_dam, m_ptr, 0x88); + + msg_print("You are suddenly very hot!"); + + if (p_ptr->oppose_fire) aura_damage = (aura_damage + 2) / 3; + if (p_ptr->resist_fire) aura_damage = (aura_damage + 2) / 3; + if (p_ptr->sensible_fire) aura_damage = (aura_damage + 2) * 2; + + take_hit(aura_damage, aura_dam); + r_ptr->r_flags2 |= RF2_AURA_FIRE; + handle_stuff(); + } + } + + + if (r_ptr->flags2 & (RF2_AURA_ELEC)) + { + if (!(p_ptr->immune_elec)) + { + char aura_dam[80]; + + aura_damage = + damroll(1 + (m_ptr->level / 26), 1 + (m_ptr->level / 17)); + + /* Hack -- Get the "died from" name */ + monster_desc(aura_dam, m_ptr, 0x88); + + if (p_ptr->oppose_elec) aura_damage = (aura_damage + 2) / 3; + if (p_ptr->resist_elec) aura_damage = (aura_damage + 2) / 3; + + msg_print("You get zapped!"); + take_hit(aura_damage, aura_dam); + r_ptr->r_flags2 |= RF2_AURA_ELEC; + handle_stuff(); + } + } +} + + +/* + * Carried monster can attack too. + * Based on monst_attack_monst. + */ +static void carried_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath, + int x, int y) +{ + monster_type *t_ptr = &m_list[m_idx]; + + monster_race *r_ptr; + + monster_race *tr_ptr = race_inf(t_ptr); + + int ap_cnt; + + int ac, rlev, pt; + + char t_name[80]; + + cptr sym_name = symbiote_name(TRUE); + + char temp[80]; + + bool_ blinked = FALSE, touched = FALSE; + + byte y_saver = t_ptr->fy; + + byte x_saver = t_ptr->fx; + + object_type *o_ptr; + + + /* Get the carried monster */ + o_ptr = &p_ptr->inventory[INVEN_CARRY]; + if (!o_ptr->k_idx) return; + + r_ptr = &r_info[o_ptr->pval]; + + /* Not allowed to attack */ + if (r_ptr->flags1 & RF1_NEVER_BLOW) return; + + /* Total armor */ + ac = t_ptr->ac; + + /* Extract the effective monster level */ + rlev = ((o_ptr->elevel >= 1) ? o_ptr->elevel : 1); + + /* Get the monster name (or "it") */ + monster_desc(t_name, t_ptr, 0); + + /* Assume no blink */ + blinked = FALSE; + + if (!t_ptr->ml) + { + msg_print("You hear noise."); + } + + /* Scan through all four blows */ + for (ap_cnt = 0; ap_cnt < 4; ap_cnt++) + { + bool_ visible = FALSE; + bool_ obvious = FALSE; + + int power = 0; + int damage = 0; + + cptr act = NULL; + + /* Extract the attack infomation */ + int effect = r_ptr->blow[ap_cnt].effect; + int method = r_ptr->blow[ap_cnt].method; + int d_dice = r_ptr->blow[ap_cnt].d_dice; + int d_side = r_ptr->blow[ap_cnt].d_side; + + /* Stop attacking if the target dies! */ + if (t_ptr->fx != x_saver || t_ptr->fy != y_saver) + break; + + /* Hack -- no more attacks */ + if (!method) break; + + if (blinked) /* Stop! */ + { + /* break; */ + } + + /* Extract visibility (before blink) */ + visible = TRUE; + + /* Extract the attack "power" */ + power = get_attack_power(effect); + + /* Monster hits */ + if (!effect || check_hit2(power, rlev, ac)) + { + /* Always disturbing */ + disturb(1); + + /* Describe the attack method */ + switch (method) + { + case RBM_HIT: + { + act = "hits %s."; + touched = TRUE; + break; + } + + case RBM_TOUCH: + { + act = "touches %s."; + touched = TRUE; + break; + } + + case RBM_PUNCH: + { + act = "punches %s."; + touched = TRUE; + break; + } + + case RBM_KICK: + { + act = "kicks %s."; + touched = TRUE; + break; + } + + case RBM_CLAW: + { + act = "claws %s."; + touched = TRUE; + break; + } + + case RBM_BITE: + { + act = "bites %s."; + touched = TRUE; + break; + } + + case RBM_STING: + { + act = "stings %s."; + touched = TRUE; + break; + } + + case RBM_XXX1: + { + act = "XXX1's %s."; + break; + } + + case RBM_BUTT: + { + act = "butts %s."; + touched = TRUE; + break; + } + + case RBM_CRUSH: + { + act = "crushes %s."; + touched = TRUE; + break; + } + + case RBM_ENGULF: + { + act = "engulfs %s."; + touched = TRUE; + break; + } + + case RBM_CHARGE: + { + act = "charges %s."; + touched = TRUE; + break; + } + + case RBM_CRAWL: + { + act = "crawls on %s."; + touched = TRUE; + break; + } + + case RBM_DROOL: + { + act = "drools on %s."; + touched = FALSE; + break; + } + + case RBM_SPIT: + { + act = "spits on %s."; + touched = FALSE; + break; + } + + case RBM_GAZE: + { + act = "gazes at %s."; + touched = FALSE; + break; + } + + case RBM_WAIL: + { + act = "wails at %s."; + touched = FALSE; + break; + } + + case RBM_SPORE: + { + act = "releases spores at %s."; + touched = FALSE; + break; + } + + case RBM_XXX4: + { + act = "projects XXX4's at %s."; + touched = FALSE; + break; + } + + case RBM_BEG: + { + act = "begs %s for money."; + touched = FALSE; + t_ptr->csleep = 0; + break; + } + + case RBM_INSULT: + { + act = "insults %s."; + touched = FALSE; + t_ptr->csleep = 0; + break; + } + + case RBM_MOAN: + { + act = "moans at %s."; + touched = FALSE; + t_ptr->csleep = 0; + break; + } + + case RBM_SHOW: + { + act = "sings to %s."; + touched = FALSE; + t_ptr->csleep = 0; + break; + } + } + + /* Message */ + if (act) + { + strfmt(temp, act, t_name); + if (t_ptr->ml) + msg_format("%s %s", sym_name, temp); + + } + + /* Hack -- assume all attacks are obvious */ + obvious = TRUE; + + /* Roll out the damage */ + damage = damroll(d_dice, d_side); + + pt = GF_MISSILE; + + /* Apply appropriate damage */ + switch (effect) + { + case 0: + { + damage = 0; + pt = 0; + break; + } + + case RBE_HURT: + case RBE_SANITY: + { + damage -= (damage * ((ac < 150) ? ac : 150) / 250); + break; + } + + case RBE_POISON: + case RBE_DISEASE: + { + pt = GF_POIS; + break; + } + + case RBE_UN_BONUS: + case RBE_UN_POWER: + case RBE_ABOMINATION: + { + pt = GF_DISENCHANT; + break; + } + + case RBE_EAT_FOOD: + case RBE_EAT_LITE: + { + pt = damage = 0; + break; + } + + case RBE_EAT_ITEM: + case RBE_EAT_GOLD: + { + pt = damage = 0; + if (randint(2) == 1) blinked = TRUE; + break; + } + + case RBE_ACID: + { + pt = GF_ACID; + break; + } + + case RBE_ELEC: + { + pt = GF_ELEC; + break; + } + + case RBE_FIRE: + { + pt = GF_FIRE; + break; + } + + case RBE_COLD: + { + pt = GF_COLD; + break; + } + + case RBE_BLIND: + { + break; + } + + case RBE_CONFUSE: + case RBE_HALLU: + { + pt = GF_CONFUSION; + break; + } + + case RBE_TERRIFY: + { + pt = GF_TURN_ALL; + break; + } + + case RBE_PARALYZE: + { + pt = GF_OLD_SLEEP; /* sort of close... */ + break; + } + + case RBE_LOSE_STR: + case RBE_LOSE_INT: + case RBE_LOSE_WIS: + case RBE_LOSE_DEX: + case RBE_LOSE_CON: + case RBE_LOSE_CHR: + case RBE_LOSE_ALL: + case RBE_PARASITE: + { + break; + } + + case RBE_SHATTER: + { + if (damage > 23) + { + /* Prevent destruction of quest levels and town */ + if (!is_quest(dun_level) && dun_level) + earthquake(p_ptr->py, p_ptr->px, 8); + } + break; + } + + case RBE_EXP_10: + case RBE_EXP_20: + case RBE_EXP_40: + case RBE_EXP_80: + { + pt = GF_NETHER; + break; + } + + case RBE_TIME: + { + pt = GF_TIME; + break; + } + + default: + { + pt = 0; + break; + } + } + + if (pt) + { + /* Do damage if not exploding */ + project(0, 0, t_ptr->fy, t_ptr->fx, + (pt == GF_OLD_SLEEP ? r_ptr->level : damage), pt, + PROJECT_KILL | PROJECT_STOP); + + if (touched) + { + /* Aura fire */ + if ((tr_ptr->flags2 & RF2_AURA_FIRE) && + !(r_ptr->flags3 & RF3_IM_FIRE)) + { + if (t_ptr->ml) + { + blinked = FALSE; + msg_format("You are suddenly very hot!"); + if (t_ptr->ml) + tr_ptr->r_flags2 |= RF2_AURA_FIRE; + } + project(m_idx, 0, p_ptr->py, p_ptr->px, + damroll(1 + ((t_ptr->level) / 26), + 1 + ((t_ptr->level) / 17)), + GF_FIRE, PROJECT_KILL | PROJECT_STOP); + } + + /* Aura elec */ + if ((tr_ptr->flags2 & (RF2_AURA_ELEC)) && + !(r_ptr->flags3 & (RF3_IM_ELEC))) + { + if (t_ptr->ml) + { + blinked = FALSE; + msg_format("You get zapped!"); + if (t_ptr->ml) + tr_ptr->r_flags2 |= RF2_AURA_ELEC; + } + project(m_idx, 0, p_ptr->py, p_ptr->px, + damroll(1 + ((t_ptr->level) / 26), + 1 + ((t_ptr->level) / 17)), + GF_ELEC, PROJECT_KILL | PROJECT_STOP); + } + } + } + } + + /* Monster missed player */ + else + { + /* Analyze failed attacks */ + switch (method) + { + case RBM_HIT: + case RBM_TOUCH: + case RBM_PUNCH: + case RBM_KICK: + case RBM_CLAW: + case RBM_BITE: + case RBM_STING: + case RBM_XXX1: + case RBM_BUTT: + case RBM_CRUSH: + case RBM_ENGULF: + case RBM_CHARGE: + { + /* Disturb */ + disturb(1); + + /* Message */ + msg_format("%s misses %s.", sym_name, t_name); + break; + } + } + } + + + /* Analyze "visible" monsters only */ + if (visible) + { + /* Count "obvious" attacks (and ones that cause damage) */ + if (obvious || damage || (r_ptr->r_blows[ap_cnt] > 10)) + { + /* Count attacks of this type */ + if (r_ptr->r_blows[ap_cnt] < MAX_UCHAR) + { + r_ptr->r_blows[ap_cnt]++; + } + } + } + } + + /* Blink away */ + if (blinked) + { + msg_format("You and %s flee laughing!", symbiote_name(FALSE)); + + teleport_player(MAX_SIGHT * 2 + 5); + } +} + +/* + * Carried monster can attack too. + * Based on monst_attack_monst. + */ +static void incarnate_monster_attack(s16b m_idx, bool_ *fear, bool_ *mdeath, + int x, int y) +{ + monster_type *t_ptr = &m_list[m_idx]; + + monster_race *r_ptr; + + monster_race *tr_ptr = race_inf(t_ptr); + + int ap_cnt; + + int ac, rlev, pt; + + char t_name[80]; + + char temp[80]; + + bool_ blinked = FALSE, touched = FALSE; + + byte y_saver = t_ptr->fy; + + byte x_saver = t_ptr->fx; + + + if (!p_ptr->body_monster) return; + + r_ptr = race_info_idx(p_ptr->body_monster, 0); + + /* Not allowed to attack */ + if (r_ptr->flags1 & RF1_NEVER_BLOW) return; + + /* Total armor */ + ac = t_ptr->ac; + + /* Extract the effective monster level */ + rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1); + + /* Get the monster name (or "it") */ + monster_desc(t_name, t_ptr, 0); + + /* Assume no blink */ + blinked = FALSE; + + if (!t_ptr->ml) + { + msg_print("You hear noise."); + } + + /* Scan through all four blows */ + for (ap_cnt = 0; ap_cnt < (p_ptr->num_blow > 4) ? 4 : p_ptr->num_blow; + ap_cnt++) + { + bool_ visible = FALSE; + bool_ obvious = FALSE; + + int power = 0; + int damage = 0; + + cptr act = NULL; + + /* Extract the attack infomation */ + int effect = r_ptr->blow[ap_cnt].effect; + int method = r_ptr->blow[ap_cnt].method; + int d_dice = r_ptr->blow[ap_cnt].d_dice; + int d_side = r_ptr->blow[ap_cnt].d_side; + + /* Stop attacking if the target dies! */ + if (t_ptr->fx != x_saver || t_ptr->fy != y_saver) + break; + + /* Hack -- no more attacks */ + if (!method) break; + + if (blinked) /* Stop! */ + { + /* break; */ + } + + /* Extract visibility (before blink) */ + visible = TRUE; + + /* Extract the attack "power" */ + power = get_attack_power(effect); + + /* Monster hits */ + if (!effect || check_hit2(power, rlev, ac)) + { + /* Always disturbing */ + disturb(1); + + /* Describe the attack method */ + switch (method) + { + case RBM_HIT: + { + act = "hit %s."; + touched = TRUE; + break; + } + + case RBM_TOUCH: + { + act = "touch %s."; + touched = TRUE; + break; + } + + case RBM_PUNCH: + { + act = "punch %s."; + touched = TRUE; + break; + } + + case RBM_KICK: + { + act = "kick %s."; + touched = TRUE; + break; + } + + case RBM_CLAW: + { + act = "claw %s."; + touched = TRUE; + break; + } + + case RBM_BITE: + { + act = "bite %s."; + touched = TRUE; + break; + } + + case RBM_STING: + { + act = "sting %s."; + touched = TRUE; + break; + } + + case RBM_XXX1: + { + act = "XXX1's %s."; + break; + } + + case RBM_BUTT: + { + act = "butt %s."; + touched = TRUE; + break; + } + + case RBM_CRUSH: + { + act = "crush %s."; + touched = TRUE; + break; + } + + case RBM_ENGULF: + { + act = "engulf %s."; + touched = TRUE; + break; + } + + case RBM_CHARGE: + { + act = "charge %s."; + touched = TRUE; + break; + } + + case RBM_CRAWL: + { + act = "crawl on %s."; + touched = TRUE; + break; + } + + case RBM_DROOL: + { + act = "drool on %s."; + touched = FALSE; + break; + } + + case RBM_SPIT: + { + act = "spit on %s."; + touched = FALSE; + break; + } + + case RBM_GAZE: + { + act = "gaze at %s."; + touched = FALSE; + break; + } + + case RBM_WAIL: + { + act = "wail at %s."; + touched = FALSE; + break; + } + + case RBM_SPORE: + { + act = "release spores at %s."; + touched = FALSE; + break; + } + + case RBM_XXX4: + { + act = "project XXX4's at %s."; + touched = FALSE; + break; + } + + case RBM_BEG: + { + act = "beg %s for money."; + touched = FALSE; + t_ptr->csleep = 0; + break; + } + + case RBM_INSULT: + { + act = "insult %s."; + touched = FALSE; + t_ptr->csleep = 0; + break; + } + + case RBM_MOAN: + { + act = "moan at %s."; + touched = FALSE; + t_ptr->csleep = 0; + break; + } + + case RBM_SHOW: + { + act = "sing to %s."; + touched = FALSE; + t_ptr->csleep = 0; + break; + } + } + + /* Message */ + if (act) + { + strfmt(temp, act, t_name); + if (t_ptr->ml) + msg_format("You %s", temp); + + } + + /* Hack -- assume all attacks are obvious */ + obvious = TRUE; + + /* Roll out the damage */ + damage = damroll(d_dice, d_side) + p_ptr->to_d; + + pt = GF_MISSILE; + + /* Apply appropriate damage */ + switch (effect) + { + case 0: + { + damage = 0; + pt = 0; + break; + } + + case RBE_HURT: + case RBE_SANITY: + { + damage -= (damage * ((ac < 150) ? ac : 150) / 250); + break; + } + + case RBE_POISON: + case RBE_DISEASE: + { + pt = GF_POIS; + break; + } + + case RBE_UN_BONUS: + case RBE_UN_POWER: + { + pt = GF_DISENCHANT; + break; + } + + case RBE_EAT_FOOD: + case RBE_EAT_LITE: + { + pt = damage = 0; + break; + } + + case RBE_EAT_ITEM: + case RBE_EAT_GOLD: + { + pt = damage = 0; + if (randint(2) == 1) blinked = TRUE; + break; + } + + case RBE_ACID: + { + pt = GF_ACID; + break; + } + + case RBE_ELEC: + { + pt = GF_ELEC; + break; + } + + case RBE_FIRE: + { + pt = GF_FIRE; + break; + } + + case RBE_COLD: + { + pt = GF_COLD; + break; + } + + case RBE_BLIND: + { + break; + } + + case RBE_HALLU: + case RBE_CONFUSE: + { + pt = GF_CONFUSION; + break; + } + + case RBE_TERRIFY: + { + pt = GF_TURN_ALL; + break; + } + + case RBE_PARALYZE: + { + pt = GF_OLD_SLEEP; /* sort of close... */ + break; + } + + case RBE_LOSE_STR: + case RBE_LOSE_INT: + case RBE_LOSE_WIS: + case RBE_LOSE_DEX: + case RBE_LOSE_CON: + case RBE_LOSE_CHR: + case RBE_LOSE_ALL: + case RBE_PARASITE: + { + break; + } + + case RBE_SHATTER: + { + if (damage > 23) + { + /* Prevent destruction of quest levels and town */ + if (!is_quest(dun_level) && dun_level) + earthquake(p_ptr->py, p_ptr->px, 8); + } + break; + } + + case RBE_EXP_10: + case RBE_EXP_20: + case RBE_EXP_40: + case RBE_EXP_80: + { + pt = GF_NETHER; + break; + } + + case RBE_TIME: + { + pt = GF_TIME; + break; + } + + default: + { + pt = 0; + break; + } + } + + if (pt) + { + /* Do damage if not exploding */ + project(0, 0, t_ptr->fy, t_ptr->fx, + (pt == GF_OLD_SLEEP ? p_ptr->lev * 2 : damage), pt, + PROJECT_KILL | PROJECT_STOP); + + if (touched) + { + /* Aura fire */ + if ((tr_ptr->flags2 & RF2_AURA_FIRE) && + !(r_ptr->flags3 & RF3_IM_FIRE)) + { + if (t_ptr->ml) + { + blinked = FALSE; + msg_format("You are suddenly very hot!"); + if (t_ptr->ml) + tr_ptr->r_flags2 |= RF2_AURA_FIRE; + } + project(m_idx, 0, p_ptr->py, p_ptr->px, + damroll(1 + ((t_ptr->level) / 26), + 1 + ((t_ptr->level) / 17)), + GF_FIRE, PROJECT_KILL | PROJECT_STOP); + } + + /* Aura elec */ + if ((tr_ptr->flags2 & (RF2_AURA_ELEC)) && + !(r_ptr->flags3 & (RF3_IM_ELEC))) + { + if (t_ptr->ml) + { + blinked = FALSE; + msg_format("You get zapped!"); + if (t_ptr->ml) + tr_ptr->r_flags2 |= RF2_AURA_ELEC; + } + project(m_idx, 0, p_ptr->py, p_ptr->px, + damroll(1 + ((t_ptr->level) / 26), + 1 + ((t_ptr->level) / 17)), + GF_ELEC, PROJECT_KILL | PROJECT_STOP); + } + + } + } + } + + /* Monster missed player */ + else + { + /* Analyze failed attacks */ + switch (method) + { + case RBM_HIT: + case RBM_TOUCH: + case RBM_PUNCH: + case RBM_KICK: + case RBM_CLAW: + case RBM_BITE: + case RBM_STING: + case RBM_XXX1: + case RBM_BUTT: + case RBM_CRUSH: + case RBM_ENGULF: + case RBM_CHARGE: + { + /* Disturb */ + disturb(1); + + /* Message */ + msg_format("You miss %s.", t_name); + + break; + } + } + } + + + /* Analyze "visible" monsters only */ + if (visible) + { + /* Count "obvious" attacks (and ones that cause damage) */ + if (obvious || damage || (r_ptr->r_blows[ap_cnt] > 10)) + { + /* Count attacks of this type */ + if (r_ptr->r_blows[ap_cnt] < MAX_UCHAR) + { + r_ptr->r_blows[ap_cnt]++; + } + } + } + } + + /* Blink away */ + if (blinked) + { + msg_print("You flee laughing!"); + + teleport_player(MAX_SIGHT * 2 + 5); + } +} + + +/* + * Fetch an attack description from dam_*.txt files. + */ + +static void flavored_attack(int percent, char *output) +{ + int insanity = (p_ptr->msane - p_ptr->csane) * 100 / p_ptr->msane; + bool_ insane = (rand_int(100) < insanity); + + if (percent < 5) + { + if (!insane) + strcpy(output, "You scratch %s."); + else + get_rnd_line("dam_none.txt", output); + + } + else if (percent < 30) + { + if (!insane) + strcpy(output, "You hit %s."); + else + get_rnd_line("dam_med.txt", output); + } + else if (percent < 60) + { + if (!insane) + strcpy(output, "You wound %s."); + else + get_rnd_line("dam_lots.txt", output); + } + else if (percent < 95) + { + if (!insane) + strcpy(output, "You cripple %s."); + else + get_rnd_line("dam_huge.txt", output); + + } + else + { + if (!insane) + strcpy(output, "You demolish %s."); + else + get_rnd_line("dam_xxx.txt", output); + } +} + + +/* + * Apply the special effects of an attack + */ +void attack_special(monster_type *m_ptr, s32b special, int dam) +{ + char m_name[80]; + + monster_race *r_ptr = race_inf(m_ptr); + + + /* Extract monster name (or "it") */ + monster_desc(m_name, m_ptr, 0); + + /* Special - Cut monster */ + if (special & SPEC_CUT) + { + /* Cut the monster */ + if (r_ptr->flags8 & (RF8_NO_CUT)) + { + if (m_ptr->ml) + { + r_info[m_ptr->r_idx].r_flags8 |= (RF8_NO_CUT); + } + } + else if (rand_int(100) >= r_ptr->level) + { + /* Already partially poisoned */ + if (m_ptr->bleeding) msg_format("%^s is bleeding more strongly.", + m_name); + /* Was not poisoned */ + else + msg_format("%^s is bleeding.", m_name); + + m_ptr->bleeding += dam * 2; + } + } + + /* Special - Poison monster */ + if (special & SPEC_POIS) + { + /* Poison the monster */ + if (r_ptr->flags3 & (RF3_IM_POIS)) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_IM_POIS); + } + } + /* Notice susceptibility */ + else if (r_ptr->flags9 & (RF9_SUSCEP_POIS)) + { + if (m_ptr->ml) + { + r_ptr->r_flags9 |= (RF9_SUSCEP_POIS); + } + /* Already partially poisoned */ + if (m_ptr->poisoned) msg_format("%^s is more poisoned.", m_name); + /* Was not poisoned */ + else + msg_format("%^s is poisoned.", m_name); + + m_ptr->poisoned += dam * 2; + } + else if (rand_int(100) >= r_ptr->level) + { + /* Already partially poisoned */ + if (m_ptr->poisoned) msg_format("%^s is more poisoned.", m_name); + /* Was not poisoned */ + else + msg_format("%^s is poisoned.", m_name); + + m_ptr->poisoned += dam; + } + } +} + + +/* + * Bare handed attacks + */ +static void py_attack_hand(int *k, monster_type *m_ptr, s32b *special) +{ + s16b special_effect = 0, stun_effect = 0, times = 0; + martial_arts *ma_ptr, *old_ptr, *blow_table = ma_blows; + int resist_stun = 0, max = MAX_MA; + monster_race *r_ptr = race_inf(m_ptr); + char m_name[80]; + bool_ desc = FALSE; + bool_ done_crit; + int plev = p_ptr->lev; + + if ((!p_ptr->body_monster) && (p_ptr->mimic_form == resolve_mimic_name("Bear")) && + (p_ptr->melee_style == SKILL_BEAR)) + { + blow_table = bear_blows; + max = MAX_BEAR; + plev = get_skill(SKILL_BEAR); + } + if (p_ptr->melee_style == SKILL_HAND) + { + blow_table = ma_blows; + max = MAX_MA; + plev = get_skill(SKILL_HAND); + } + ma_ptr = &blow_table[0]; + old_ptr = &blow_table[0]; + + /* Extract monster name (or "it") */ + monster_desc(m_name, m_ptr, 0); + + if (r_ptr->flags1 & RF1_UNIQUE) resist_stun += 88; + if (r_ptr->flags3 & RF3_NO_CONF) resist_stun += 44; + if (r_ptr->flags3 & RF3_NO_SLEEP) resist_stun += 44; + if ((r_ptr->flags3 & RF3_UNDEAD) || + (r_ptr->flags3 & RF3_NONLIVING)) resist_stun += 88; + + if (plev) + { + for (times = 0; times < (plev < 7 ? 1 : plev / 7); times++) + { + do + { + ma_ptr = &blow_table[(randint(max)) - 1]; + } + while ((ma_ptr->min_level > plev) || (randint(plev) < ma_ptr->chance)); + + /* keep the highest level attack available we found */ + if ((ma_ptr->min_level > old_ptr->min_level) && + !(p_ptr->stun || p_ptr->confused)) + { + old_ptr = ma_ptr; + + if (wizard && cheat_xtra) + { + msg_print("Attack re-selected."); + } + } + else + { + ma_ptr = old_ptr; + } + } + } + + *k = damroll(ma_ptr->dd, ma_ptr->ds); + + if (ma_ptr->effect & MA_KNEE) + { + if (r_ptr->flags1 & RF1_MALE) + { + if (!desc) msg_format("You hit %s in the groin with your knee!", + m_name); + sound(SOUND_PAIN); + special_effect = MA_KNEE; + } + else if (!desc) msg_format(ma_ptr->desc, m_name); + + desc = TRUE; + } + if (ma_ptr->effect & MA_FULL_SLOW) + { + special_effect = MA_SLOW; + if (!desc) msg_format(ma_ptr->desc, m_name); + + desc = TRUE; + } + if (ma_ptr->effect & MA_SLOW) + { + if (! + ((r_ptr->flags1 & RF1_NEVER_MOVE) || + strchr("UjmeEv$,DdsbBFIJQSXclnw!=?", r_ptr->d_char))) + { + if (!desc) msg_format("You kick %s in the ankle.", m_name); + special_effect = MA_SLOW; + } + else if (!desc) msg_format(ma_ptr->desc, m_name); + + desc = TRUE; + } + if (ma_ptr->effect & MA_STUN) + { + if (ma_ptr->power) + { + stun_effect = (ma_ptr->power / 2) + randint(ma_ptr->power / 2); + } + + if (!desc) msg_format(ma_ptr->desc, m_name); + desc = TRUE; + } + if (ma_ptr->effect & MA_WOUND) + { + if (magik(ma_ptr->power)) + { + *special |= SPEC_CUT; + } + if (!desc) msg_format(ma_ptr->desc, m_name); + desc = TRUE; + } + + *k = critical_norm(plev * (randint(10)), ma_ptr->min_level, *k, -1, &done_crit); + + if ((special_effect & MA_KNEE) && ((*k + p_ptr->to_d) < m_ptr->hp)) + { + msg_format("%^s moans in agony!", m_name); + stun_effect = 7 + randint(13); + resist_stun /= 3; + } + if (((special_effect & MA_FULL_SLOW) || (special_effect & MA_SLOW)) && + ((*k + p_ptr->to_d) < m_ptr->hp)) + { + if (!(r_ptr->flags1 & RF1_UNIQUE) && + (randint(plev) > m_ptr->level) && m_ptr->mspeed > 60) + { + msg_format("%^s starts limping slower.", m_name); + m_ptr->mspeed -= 10; + } + } + + if (stun_effect && ((*k + p_ptr->to_d) < m_ptr->hp)) + { + if (plev > randint(m_ptr->level + resist_stun + 10)) + { + if (m_ptr->stunned) + msg_format("%^s is still stunned.", m_name); + else + msg_format("%^s is stunned.", m_name); + + m_ptr->stunned += (stun_effect); + } + } +} + + +/* + * Apply nazgul effects + */ +void do_nazgul(int *k, int *num, int num_blow, int weap, monster_race *r_ptr, + object_type *o_ptr) +{ + u32b f1, f2, f3, f4, f5, esp; + + bool_ mundane; + bool_ allow_shatter = TRUE; + + /* Extract mundane-ness of the current weapon */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* It should be Slay Evil, Slay Undead, or *Slay Undead* */ + mundane = !(f1 & TR1_SLAY_EVIL) && !(f1 & TR1_SLAY_UNDEAD) && + !(f5 & TR5_KILL_UNDEAD); + + /* Some blades can resist shattering */ + if (f5 & TR5_RES_MORGUL) + allow_shatter = FALSE; + + /* Mega Hack -- Hitting Nazgul is REALY dangerous (ideas from Akhronath) */ + if (r_ptr->flags7 & RF7_NAZGUL) + { + if ((!o_ptr->name2) && (!artifact_p(o_ptr)) && allow_shatter) + { + msg_print("Your weapon *DISINTEGRATES*!"); + *k = 0; + + inc_stack_size_ex(INVEN_WIELD + weap, -1, OPTIMIZE, NO_DESCRIBE); + + /* To stop attacking */ + *num = num_blow; + } + else if (o_ptr->name2) + { + if (mundane) + { + msg_print + ("The Ringwraith is IMPERVIOUS to the mundane weapon."); + *k = 0; + } + + /* 25% chance of getting destroyed */ + if (magik(25) && allow_shatter) + { + msg_print("Your weapon is destroyed!"); + + inc_stack_size_ex(INVEN_WIELD + weap, -1, OPTIMIZE, NO_DESCRIBE); + + /* To stop attacking */ + *num = num_blow; + } + } + else if (artifact_p(o_ptr)) + { + if (mundane) + { + msg_print + ("The Ringwraith is IMPERVIOUS to the mundane weapon."); + *k = 0; + } + + apply_disenchant(INVEN_WIELD + weap); + + /* 1/1000 chance of getting destroyed */ + if (!rand_int(1000) && allow_shatter) + { + msg_print("Your weapon is destroyed!"); + + inc_stack_size_ex(INVEN_WIELD + weap, -1, OPTIMIZE, NO_DESCRIBE); + + /* To stop attacking */ + *num = num_blow; + } + } + + /* If any damage is done, then 25% chance of getting the Black Breath */ + if (*k) + { + if (magik(25)) + { + msg_print("Your foe calls upon your soul!"); + msg_print + ("You feel the Black Breath slowly draining you of life..."); + p_ptr->black_breath = TRUE; + } + } + } +} + + +/* + * Player attacks a (poor, defenseless) creature -RAK- + * + * If no "weapon" is available, then "punch" the monster one time. + */ +void py_attack(int y, int x, int max_blow) +{ + int num = 0, k, bonus, chance; + + s32b special = 0; + + cave_type *c_ptr = &cave[y][x]; + + monster_type *m_ptr = &m_list[c_ptr->m_idx]; + + monster_race *r_ptr = race_inf(m_ptr); + + object_type *o_ptr; + + char m_name[80]; + + bool_ fear = FALSE; + + bool_ mdeath = FALSE; + + bool_ backstab = FALSE; + + bool_ vorpal_cut = FALSE; + + int chaos_effect = 0; + + bool_ stab_fleeing = FALSE; + + bool_ do_quake = FALSE; + + bool_ done_crit = FALSE; + + bool_ drain_msg = TRUE; + + int drain_result = 0, drain_heal = 0; + + int drain_left = MAX_VAMPIRIC_DRAIN; + + /* A massive hack -- life-draining weapons */ + u32b f1, f2, f3, f4, f5, esp; + + int weap; + + /* Disturb the player */ + disturb(0); + + if (r_info[p_ptr->body_monster].flags1 & RF1_NEVER_BLOW) + { + msg_print("You cannot attack in this form!"); + return; + } + + if (get_skill(SKILL_BACKSTAB)) + { + if ((m_ptr->csleep) && (m_ptr->ml)) + { + /* Can't backstab creatures that we can't see, right? */ + backstab = TRUE; + } + else if ((m_ptr->monfear) && (m_ptr->ml)) + { + stab_fleeing = TRUE; + } + } + + /* Disturb the monster */ + m_ptr->csleep = 0; + + + /* Extract monster name (or "it") */ + monster_desc(m_name, m_ptr, 0); + + /* Dont even bother */ + if (r_ptr->flags7 & RF7_IM_MELEE) + { + msg_format("%^s is immune to melee attacks."); + return; + } + + /* Auto-Recall if possible and visible */ + if (m_ptr->ml) monster_race_track(m_ptr->r_idx, m_ptr->ego); + + /* Track a new monster */ + if (m_ptr->ml) health_track(c_ptr->m_idx); + + /* Stop if friendly */ + if ((is_friend(m_ptr) >= 0) && + !(p_ptr->stun || p_ptr->confused || p_ptr->image || + !(m_ptr->ml))) + { + if (!(p_ptr->inventory[INVEN_WIELD].art_name)) + { + msg_format("You stop to avoid hitting %s.", m_name); + return; + } + + if (! + (streq + (quark_str(p_ptr->inventory[INVEN_WIELD].art_name), "'Stormbringer'"))) + { + msg_format("You stop to avoid hitting %s.", m_name); + return; + } + + msg_format("Your black blade greedily attacks %s!", m_name); + } + + /* Break goi/manashield */ + if (p_ptr->invuln) + { + set_invuln(0); + } + if (p_ptr->disrupt_shield) + { + set_disrupt_shield(0); + } + + /* Handle player fear */ + if (p_ptr->afraid) + { + /* Message */ + if (m_ptr->ml) + msg_format("You are too afraid to attack %s!", m_name); + else + msg_format("There is something scary in your way!"); + + /* Done */ + return; + } + + /* Monsters can use barehanded combat, but not weapon combat */ + if ((p_ptr->body_monster) && + (!r_info[p_ptr->body_monster].body_parts[BODY_WEAPON]) && + !(p_ptr->melee_style == SKILL_HAND)) + { + incarnate_monster_attack(c_ptr->m_idx, &fear, &mdeath, y, x); + } + /* Otherwise use your weapon(s) */ + else + { + int weapons; + if (p_ptr->melee_style == SKILL_MASTERY) + weapons = r_info[p_ptr->body_monster].body_parts[BODY_WEAPON]; + else /* SKILL_HAND */ + weapons = 1; + + /* Attack with ALL the weapons !!!!! -- ooh that's gonna hurt YOU */ + for (weap = 0; weap < weapons; ++weap) + { + /* Monster is already dead ? oh :( */ + if (mdeath) break; + + /* Reset the blows counter */ + num = 0; + + /* Access the weapon */ + o_ptr = &p_ptr->inventory[INVEN_WIELD + weap]; + + /* Calculate the "attack quality" */ + bonus = p_ptr->to_h + p_ptr->to_h_melee + o_ptr->to_h; + chance = p_ptr->skill_thn + (bonus * BTH_PLUS_ADJ); + + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + if (!(f4 & TR4_NEVER_BLOW)) + { + int num_blow = p_ptr->num_blow; + + /* Restrict to max_blow(if max_blow >= 0) */ + if ((max_blow >= 0) && + (num_blow > max_blow)) num_blow = max_blow; + + /* Attack once for each legal blow */ + while (num++ < num_blow) + { + /* Test for hit */ + if (test_hit_norm(chance, m_ptr->ac, m_ptr->ml)) + { + /* Sound */ + sound(SOUND_HIT); + + /* Hack -- bare hands do one damage */ + k = 1; + + /* Select a chaotic effect (50% chance) */ + if ((f1 & TR1_CHAOTIC) && (rand_int(2) == 0)) + { + if (randint(5) < 3) + { + /* Vampiric (20%) */ + chaos_effect = 1; + } + else if (rand_int(250) == 0) + { + /* Quake (0.12%) */ + chaos_effect = 2; + } + else if (rand_int(10)) + { + /* Confusion (26.892%) */ + chaos_effect = 3; + } + else if (rand_int(2) == 0) + { + /* Teleport away (1.494%) */ + chaos_effect = 4; + } + else + { + /* Polymorph (1.494%) */ + chaos_effect = 5; + } + } + + /* Vampiric drain */ + if ((f1 & TR1_VAMPIRIC) || (chaos_effect == 1)) + { + if (! + ((r_ptr->flags3 & RF3_UNDEAD) || + (r_ptr->flags3 & RF3_NONLIVING))) + drain_result = m_ptr->hp; + else + drain_result = 0; + } + + if (f1 & TR1_VORPAL && (randint(6) == 1)) + vorpal_cut = TRUE; + else + vorpal_cut = FALSE; + + /* Should we attack with hands or not ? */ + if (p_ptr->melee_style != SKILL_MASTERY) + { + py_attack_hand(&k, m_ptr, &special); + } + /* Handle normal weapon */ + else if (o_ptr->k_idx) + { + k = damroll(o_ptr->dd, o_ptr->ds); + k = tot_dam_aux(o_ptr, k, m_ptr, &special); + + if (backstab) + { + k += (k * + get_skill_scale(SKILL_BACKSTAB, + 100)) / 100; + } + else if (stab_fleeing) + { + k += (k * get_skill_scale(SKILL_BACKSTAB, 70)) / + 100; + } + + if ((p_ptr->impact && ((k > 50) || randint(7) == 1)) + || (chaos_effect == 2)) + { + do_quake = TRUE; + } + + k = critical_norm(o_ptr->weight, o_ptr->to_h, k, o_ptr->tval, &done_crit); + + /* Stunning blow */ + if (magik(get_skill(SKILL_STUN)) && (o_ptr->tval == TV_HAFTED) && (o_ptr->weight > 50) && done_crit) + { + if (!(r_ptr->flags4 & (RF4_BR_SOUN)) && !(r_ptr->flags4 & (RF4_BR_WALL)) && k) + { + int tmp; + + /* Get stunned */ + if (m_ptr->stunned) + { + msg_format("%^s is more dazed.", m_name); + tmp = m_ptr->stunned + get_skill_scale(SKILL_STUN, 30) + 10; + } + else + { + msg_format("%^s is dazed.", m_name); + tmp = get_skill_scale(SKILL_STUN, 60) + 20; + } + + /* Apply stun */ + m_ptr->stunned = (tmp < 200) ? tmp : 200; + } + } + + if (vorpal_cut) + { + int step_k = k; + + msg_format("Your weapon cuts deep into %s!", + m_name); + do + { + k += step_k; + } + while (randint(4) == 1); + } + + PRAY_GOD(GOD_TULKAS) + { + if (magik(wisdom_scale(130) - m_ptr->level) && (p_ptr->grace > 1000)) + { + msg_print("You feel the hand of Tulkas helping your blow."); + k += (o_ptr->to_d + p_ptr->to_d_melee) * 2; + } + else k += o_ptr->to_d + p_ptr->to_d_melee; + } + else k += o_ptr->to_d; + + /* Project some more nasty stuff? */ + if (p_ptr->tim_project) + { + project(0, p_ptr->tim_project_rad, y, x, p_ptr->tim_project_dam, p_ptr->tim_project_gf, p_ptr->tim_project_flag | PROJECT_JUMP); + if (!c_ptr->m_idx) + { + mdeath = TRUE; + break; + } + } + + do_nazgul(&k, &num, num_blow, weap, r_ptr, o_ptr); + + } + + /* Melkor can cast curse for you*/ + PRAY_GOD(GOD_MELKOR) + { + int lv = get_level_s(MELKOR_CURSE, 100); + + if (lv >= 10) + { + int chance = (wisdom_scale(30) * lv) / ((m_ptr->level < 1) ? 1 : m_ptr->level); + + if (chance < 1) chance = 1; + if ((p_ptr->grace > 5000) && magik(chance)) + { + do_melkor_curse(c_ptr->m_idx); + } + } + } + + /* May it clone the monster ? */ + if ((f4 & TR4_CLONE) && magik(30)) + { + msg_format("Oh no! Your weapon clones %^s!", + m_name); + multiply_monster(c_ptr->m_idx, FALSE, TRUE); + } + + /* Apply the player damage bonuses */ + k += p_ptr->to_d + p_ptr->to_d_melee; + + /* No negative damage */ + if (k < 0) k = 0; + + /* Message */ + if (!(backstab || stab_fleeing)) + { + /* These monsters never have flavoured combat msgs */ + if (strchr("vwjmelX,.*", r_ptr->d_char)) + { + msg_format("You hit %s.", m_name); + } + + /* Print flavoured messages if requested */ + else + { + char buff[255]; + + flavored_attack((100 * k) / m_ptr->maxhp, buff); + msg_format(buff, m_name); + } + } + else if (backstab) + { + char buf[80]; + + monster_race_desc(buf, m_ptr->r_idx, m_ptr->ego); + + backstab = FALSE; + + msg_format + ("You cruelly stab the helpless, sleeping %s!", + buf); + } + else + { + char buf[80]; + + monster_race_desc(buf, m_ptr->r_idx, m_ptr->ego); + + msg_format("You backstab the fleeing %s!", buf); + } + + /* Complex message */ + if (wizard) + { + msg_format("You do %d (out of %d) damage.", k, + m_ptr->hp); + } + + if (special) attack_special(m_ptr, special, k); + + /* Damage, check for fear and death */ + if (mon_take_hit(c_ptr->m_idx, k, &fear, NULL)) + { + /* Hack -- High-level warriors can spread their attacks out + * among weaker foes. + */ + if ((has_ability(AB_SPREAD_BLOWS)) && (num < num_blow) && + (energy_use)) + { + energy_use = energy_use * num / num_blow; + } + mdeath = TRUE; + break; + } + + switch (is_friend(m_ptr)) + { + case 1: + msg_format("%^s gets angry!", m_name); + change_side(m_ptr); + break; + case 0: + msg_format("%^s gets angry!", m_name); + m_ptr->status = MSTATUS_NEUTRAL_M; + break; + } + + touch_zap_player(m_ptr); + + /* Are we draining it? A little note: If the monster is + dead, the drain does not work... */ + + if (drain_result) + { + drain_result -= m_ptr->hp; /* Calculate the difference */ + + if (drain_result > 0) /* Did we really hurt it? */ + { + drain_heal = damroll(4, (drain_result / 6)); + + if (cheat_xtra) + { + msg_format("Draining left: %d", drain_left); + } + + if (drain_left) + { + if (drain_heal < drain_left) + { + drain_left -= drain_heal; + } + else + { + drain_heal = drain_left; + drain_left = 0; + } + + if (drain_msg) + { + msg_format + ("Your weapon drains life from %s!", + m_name); + drain_msg = FALSE; + } + + hp_player(drain_heal); + /* We get to keep some of it! */ + } + } + } + + /* Confusion attack */ + if ((p_ptr->confusing) || (chaos_effect == 3)) + { + /* Cancel glowing hands */ + if (p_ptr->confusing) + { + p_ptr->confusing = FALSE; + msg_print("Your hands stop glowing."); + } + + /* Confuse the monster */ + if (r_ptr->flags3 & (RF3_NO_CONF)) + { + if (m_ptr->ml) + { + r_ptr->r_flags3 |= (RF3_NO_CONF); + } + + msg_format("%^s is unaffected.", m_name); + } + else if (rand_int(100) < m_ptr->level) + { + msg_format("%^s is unaffected.", m_name); + } + else + { + msg_format("%^s appears confused.", m_name); + m_ptr->confused += + 10 + rand_int(get_skill(SKILL_COMBAT)) / 5; + } + } + + else if (chaos_effect == 4) + { + msg_format("%^s disappears!", m_name); + teleport_away(c_ptr->m_idx, 50); + num = num_blow + 1; /* Can't hit it anymore! */ + } + + else if ((chaos_effect == 5) && cave_floor_bold(y, x) && + (randint(90) > m_ptr->level)) + { + if (!((r_ptr->flags1 & RF1_UNIQUE) || + (r_ptr->flags4 & RF4_BR_CHAO) || + (m_ptr->mflag & MFLAG_QUEST))) + { + /* Handle polymorph */ + if (do_poly_monster(y, x)) + { + /* Polymorph succeeded */ + msg_format("%^s changes!", m_name); + + /* Hack -- Get new monster */ + m_ptr = &m_list[c_ptr->m_idx]; + + /* Oops, we need a different name... */ + monster_desc(m_name, m_ptr, 0); + + /* Hack -- Get new race */ + r_ptr = race_inf(m_ptr); + + fear = FALSE; + } + else + { + msg_format("%^s resists.", m_name); + } + } + else + { + msg_format("%^s is unaffected.", m_name); + } + } + } + + /* Player misses */ + else + { + /* Sound */ + sound(SOUND_MISS); + + backstab = FALSE; /* Clumsy! */ + + /* Message */ + msg_format("You miss %s.", m_name); + } + } + } + else + { + msg_print("You can't attack with that weapon."); + } + } + } + + /* Carried monster can attack too */ + if ((!mdeath) && m_list[c_ptr->m_idx].hp) + carried_monster_attack(c_ptr->m_idx, &fear, &mdeath, y, x); + + /* Hack -- delay fear messages */ + if (fear && m_ptr->ml) + { + /* Sound */ + sound(SOUND_FLEE); + + /* Message */ + msg_format("%^s flees in terror!", m_name); + } + + /* Mega-Hack -- apply earthquake brand */ + if (do_quake) + { + /* Prevent destruction of quest levels and town */ + if (!is_quest(dun_level) && dun_level) + earthquake(p_ptr->py, p_ptr->px, 10); + } +} + + + +static bool_ pattern_tile(int y, int x) +{ + return ((cave[y][x].feat <= FEAT_PATTERN_XTRA2) && + (cave[y][x].feat >= FEAT_PATTERN_START)); +} + + +static bool_ pattern_seq(int c_y, int c_x, int n_y, int n_x) +{ + if (!(pattern_tile(c_y, c_x)) && !(pattern_tile(n_y, n_x))) + return TRUE; + + if (cave[n_y][n_x].feat == FEAT_PATTERN_START) + { + if ((!(pattern_tile(c_y, c_x))) && + !(p_ptr->confused || p_ptr->stun || p_ptr->image)) + { + if (get_check + ("If you start walking the Straight Road, you must walk the whole way. Ok? ")) + return TRUE; + else + return FALSE; + } + else + return TRUE; + } + else if ((cave[n_y][n_x].feat == FEAT_PATTERN_OLD) || + (cave[n_y][n_x].feat == FEAT_PATTERN_END) || + (cave[n_y][n_x].feat == FEAT_PATTERN_XTRA2)) + { + if (pattern_tile(c_y, c_x)) + { + return TRUE; + } + else + { + msg_print + ("You must start walking the Straight Road from the startpoint."); + return FALSE; + } + } + else if ((cave[n_y][n_x].feat == FEAT_PATTERN_XTRA1) || + (cave[c_y][c_x].feat == FEAT_PATTERN_XTRA1)) + { + return TRUE; + } + else if (cave[c_y][c_x].feat == FEAT_PATTERN_START) + { + if (pattern_tile(n_y, n_x)) + return TRUE; + else + { + msg_print("You must walk the Straight Road in correct order."); + return FALSE; + } + } + else if ((cave[c_y][c_x].feat == FEAT_PATTERN_OLD) || + (cave[c_y][c_x].feat == FEAT_PATTERN_END) || + (cave[c_y][c_x].feat == FEAT_PATTERN_XTRA2)) + { + if (!pattern_tile(n_y, n_x)) + { + msg_print("You may not step off from the Straight Road."); + return FALSE; + } + else + { + return TRUE; + } + } + else + { + if (!pattern_tile(c_y, c_x)) + { + msg_print + ("You must start walking the Straight Road from the startpoint."); + return FALSE; + } + else + { + byte ok_move = FEAT_PATTERN_START; + switch (cave[c_y][c_x].feat) + { + case FEAT_PATTERN_1: + ok_move = FEAT_PATTERN_2; + break; + case FEAT_PATTERN_2: + ok_move = FEAT_PATTERN_3; + break; + case FEAT_PATTERN_3: + ok_move = FEAT_PATTERN_4; + break; + case FEAT_PATTERN_4: + ok_move = FEAT_PATTERN_1; + break; + default: + if (wizard) + msg_format("Funny Straight Road walking, %d.", + cave[c_y][c_x]); + return TRUE; /* Goof-up */ + } + + if ((cave[n_y][n_x].feat == ok_move) || + (cave[n_y][n_x].feat == cave[c_y][c_x].feat)) + return TRUE; + else + { + if (!pattern_tile(n_y, n_x)) + msg_print("You may not step off from the Straight Road."); + else + msg_print + ("You must walk the Straight Road in correct order."); + + return FALSE; + } + } + } +} + + + +bool_ player_can_enter(byte feature) +{ + bool_ pass_wall; + + bool_ only_wall = FALSE; + + + /* Player can not walk through "walls" unless in Shadow Form */ + if (p_ptr->wraith_form || (PRACE_FLAG(PR1_SEMI_WRAITH))) + pass_wall = TRUE; + else + pass_wall = FALSE; + + /* Wall mimicry force the player to stay in walls */ + if (p_ptr->mimic_extra & CLASS_WALL) + { + only_wall = TRUE; + } + + /* Don't let the player kill himself with one keystroke */ + if (p_ptr->wild_mode) + { + if (feature == FEAT_DEEP_WATER) + { + int wt = weight_limit() / 2; + + if ((calc_total_weight() >= wt) && !(p_ptr->ffall)) + return (FALSE); + } + else if (feature == FEAT_SHAL_LAVA || + feature == FEAT_DEEP_LAVA) + { + if (!(p_ptr->resist_fire || + p_ptr->immune_fire || + p_ptr->oppose_fire || + p_ptr->ffall)) + return (FALSE); + } + } + + if (feature == FEAT_TREES) + { + if (p_ptr->fly || + pass_wall || + (has_ability(AB_TREE_WALK)) || + (p_ptr->mimic_form == resolve_mimic_name("Ent")) || + ((p_ptr->grace >= 9000) && (p_ptr->praying) && (p_ptr->pgod == GOD_YAVANNA))) + return (TRUE); + } + + if ((p_ptr->climb) && (f_info[feature].flags1 & FF1_CAN_CLIMB)) + return (TRUE); + if ((p_ptr->fly) && + ((f_info[feature].flags1 & FF1_CAN_FLY) || + (f_info[feature].flags1 & FF1_CAN_LEVITATE))) + return (TRUE); + else if (only_wall && (f_info[feature].flags1 & FF1_FLOOR)) + return (FALSE); + else if ((p_ptr->ffall) && + (f_info[feature].flags1 & FF1_CAN_LEVITATE)) + return (TRUE); + else if ((pass_wall || only_wall) && + (f_info[feature].flags1 & FF1_CAN_PASS)) + return (TRUE); + else if (f_info[feature].flags1 & FF1_NO_WALK) + return (FALSE); + else if ((f_info[feature].flags1 & FF1_WEB) && + ((!(r_info[p_ptr->body_monster].flags7 & RF7_SPIDER)) && (p_ptr->mimic_form != resolve_mimic_name("Spider")))) + return (FALSE); + + return (TRUE); +} + +/* + * Move player in the given direction, with the given "pickup" flag. + * + * This routine should (probably) always induce energy expenditure. + * + * Note that moving will *always* take a turn, and will *always* hit + * any monster which might be in the destination grid. Previously, + * moving into walls was "free" and did NOT hit invisible monsters. + */ +void move_player_aux(int dir, int do_pickup, int run, bool_ disarm) +{ + int y, x, tmp; + + cave_type *c_ptr = &cave[p_ptr->py][p_ptr->px]; + + monster_type *m_ptr; + + monster_race *r_ptr = &r_info[p_ptr->body_monster], *mr_ptr; + + char m_name[80]; + + bool_ stormbringer = FALSE; + + bool_ old_dtrap, new_dtrap; + + bool_ oktomove = TRUE; + + + /* Hack - random movement */ + if (p_ptr->disembodied) + tmp = dir; + else if ((r_ptr->flags1 & RF1_RAND_25) && (r_ptr->flags1 & RF1_RAND_50)) + { + if (randint(100) < 75) + tmp = randint(9); + else + tmp = dir; + } + else if (r_ptr->flags1 & RF1_RAND_50) + { + if (randint(100) < 50) + tmp = randint(9); + else + tmp = dir; + } + else if (r_ptr->flags1 & RF1_RAND_25) + { + if (randint(100) < 25) + tmp = randint(9); + else + tmp = dir; + } + else + { + tmp = dir; + } + + if ((c_ptr->feat == FEAT_ICE) && (!p_ptr->ffall && !p_ptr->fly)) + { + if (magik(70 - p_ptr->lev)) + { + tmp = randint(9); + msg_print("You slip on the icy floor."); + } + else + tmp = dir; + } + + /* Find the result of moving */ + y = p_ptr->py + ddy[tmp]; + x = p_ptr->px + ddx[tmp]; + + /* Examine the destination */ + c_ptr = &cave[y][x]; + + /* Change oldpx and oldpy to place the player well when going back to big mode */ + if (p_ptr->wild_mode) + { + if (ddy[tmp] > 0) p_ptr->oldpy = 1; + if (ddy[tmp] < 0) p_ptr->oldpy = MAX_HGT - 2; + if (ddy[tmp] == 0) p_ptr->oldpy = MAX_HGT / 2; + if (ddx[tmp] > 0) p_ptr->oldpx = 1; + if (ddx[tmp] < 0) p_ptr->oldpx = MAX_WID - 2; + if (ddx[tmp] == 0) p_ptr->oldpx = MAX_WID / 2; + } + + /* Exit the area */ + if (!dun_level && !p_ptr->wild_mode && !is_quest(dun_level) && + ((x == 0) || (x == cur_wid - 1) || (y == 0) || (y == cur_hgt - 1))) + { + /* Can the player enter the grid? */ + if (player_can_enter(c_ptr->mimic)) + { + /* Hack: move to new area */ + if ((y == 0) && (x == 0)) + { + p_ptr->wilderness_y--; + p_ptr->wilderness_x--; + p_ptr->oldpy = cur_hgt - 2; + p_ptr->oldpx = cur_wid - 2; + ambush_flag = FALSE; + } + + else if ((y == 0) && (x == MAX_WID - 1)) + { + p_ptr->wilderness_y--; + p_ptr->wilderness_x++; + p_ptr->oldpy = cur_hgt - 2; + p_ptr->oldpx = 1; + ambush_flag = FALSE; + } + + else if ((y == MAX_HGT - 1) && (x == 0)) + { + p_ptr->wilderness_y++; + p_ptr->wilderness_x--; + p_ptr->oldpy = 1; + p_ptr->oldpx = cur_wid - 2; + ambush_flag = FALSE; + } + + else if ((y == MAX_HGT - 1) && (x == MAX_WID - 1)) + { + p_ptr->wilderness_y++; + p_ptr->wilderness_x++; + p_ptr->oldpy = 1; + p_ptr->oldpx = 1; + ambush_flag = FALSE; + } + + else if (y == 0) + { + p_ptr->wilderness_y--; + p_ptr->oldpy = cur_hgt - 2; + p_ptr->oldpx = x; + ambush_flag = FALSE; + } + + else if (y == cur_hgt - 1) + { + p_ptr->wilderness_y++; + p_ptr->oldpy = 1; + p_ptr->oldpx = x; + ambush_flag = FALSE; + } + + else if (x == 0) + { + p_ptr->wilderness_x--; + p_ptr->oldpx = cur_wid - 2; + p_ptr->oldpy = y; + ambush_flag = FALSE; + } + + else if (x == cur_wid - 1) + { + p_ptr->wilderness_x++; + p_ptr->oldpx = 1; + p_ptr->oldpy = y; + ambush_flag = FALSE; + } + + p_ptr->leaving = TRUE; + + return; + } + } + + /* Some hooks */ + if (process_hooks(HOOK_MOVE, "(d,d)", y, x)) return; + + { + hook_move_in in = { y, x }; + if (process_hooks_new(HOOK_MOVE, &in, NULL)) { + return; /* Prevent movement */ + } + } + + if (p_ptr->dripping_tread > 0) + { + geomancy_random_floor(y, x, FALSE); + p_ptr->dripping_tread -= 1; + if (p_ptr->dripping_tread == 0) + { + msg_print("You stop dripping raw elemental energies."); + } + } + + + /* Get the monster */ + m_ptr = &m_list[c_ptr->m_idx]; + mr_ptr = race_inf(m_ptr); + + if (p_ptr->inventory[INVEN_WIELD].art_name) + { + if (streq(quark_str(p_ptr->inventory[INVEN_WIELD].art_name), "'Stormbringer'")) + stormbringer = TRUE; + } + + /* Hack -- attack monsters */ + if (c_ptr->m_idx && (m_ptr->ml || player_can_enter(c_ptr->feat))) + { + + /* Attack -- only if we can see it OR it is not in a wall */ + if ((is_friend(m_ptr) > 0) && + !(p_ptr->confused || p_ptr->image || !(m_ptr->ml) || p_ptr->stun) && + (pattern_seq(p_ptr->py, p_ptr->px, y, x)) && + ((player_can_enter(cave[y][x].feat)))) + { + m_ptr->csleep = 0; + + /* Extract monster name (or "it") */ + monster_desc(m_name, m_ptr, 0); + + /* Auto-Recall if possible and visible */ + if (m_ptr->ml) monster_race_track(m_ptr->r_idx, m_ptr->ego); + + /* Track a new monster */ + if (m_ptr->ml) health_track(c_ptr->m_idx); + + /* displace? */ + if (stormbringer && (randint(1000) > 666)) + { + py_attack(y, x, -1); + } + else if (cave_floor_bold(p_ptr->py, p_ptr->px) || + (mr_ptr->flags2 & RF2_PASS_WALL)) + { + msg_format("You push past %s.", m_name); + m_ptr->fy = p_ptr->py; + m_ptr->fx = p_ptr->px; + cave[p_ptr->py][p_ptr->px].m_idx = c_ptr->m_idx; + c_ptr->m_idx = 0; + update_mon(cave[p_ptr->py][p_ptr->px].m_idx, TRUE); + } + else + { + msg_format("%^s is in your way!", m_name); + energy_use = 0; + oktomove = FALSE; + } + + /* now continue on to 'movement' */ + } + else + { + py_attack(y, x, -1); + oktomove = FALSE; + } + } + + else if ((c_ptr->feat == FEAT_DARK_PIT) && !p_ptr->ffall) + { + msg_print("You can't cross the chasm."); + running = 0; + oktomove = FALSE; + } + + /* Disarm a visible trap */ + else if (easy_disarm && disarm && (c_ptr->info & (CAVE_TRDT))) + { + (void)do_cmd_disarm_aux(y, x, tmp, do_pickup); + return; + } + + /* Don't step on known traps. */ + else if (disarm && (c_ptr->info & (CAVE_TRDT)) && !(p_ptr->confused || p_ptr->stun || p_ptr->image)) + { + msg_print("You stop to avoid triggering the trap."); + energy_use = 0; + oktomove = FALSE; + } + + /* Player can't enter ? soo bad for him/her ... */ + else if (!player_can_enter(c_ptr->feat)) + { + oktomove = FALSE; + + /* Disturb the player */ + disturb(0); + + if (p_ptr->prob_travel) + { + if (passwall(tmp, TRUE)) return; + } + + /* Notice things in the dark */ + if (!(c_ptr->info & (CAVE_MARK)) && !(c_ptr->info & (CAVE_SEEN))) + { + /* Rubble */ + if (c_ptr->feat == FEAT_RUBBLE) + { + msg_print("You feel some rubble blocking your way."); + c_ptr->info |= (CAVE_MARK); + lite_spot(y, x); + } + + /* Closed door */ + else if (c_ptr->feat < FEAT_SECRET) + { + msg_print("You feel a closed door blocking your way."); + c_ptr->info |= (CAVE_MARK); + lite_spot(y, x); + } + + /* Wall (or secret door) */ + else + { + int feat; + + if (c_ptr->mimic) feat = c_ptr->mimic; + else + feat = f_info[c_ptr->feat].mimic; + + msg_format("You feel %s.", f_text + f_info[feat].block); + c_ptr->info |= (CAVE_MARK); + lite_spot(y, x); + } + } + + /* Notice things */ + else + { + /* Rubble */ + if (c_ptr->feat == FEAT_RUBBLE) + { + if (!easy_tunnel) + { + msg_print("There is rubble blocking your way."); + + if (!(p_ptr->confused || p_ptr->stun || p_ptr->image)) + energy_use = 0; + /* + * Well, it makes sense that you lose time bumping into + * a wall _if_ you are confused, stunned or blind; but + * typing mistakes should not cost you a turn... + */ + } + else + { + do_cmd_tunnel_aux(y, x, dir); + return; + } + } + /* Closed doors */ + else if ((c_ptr->feat >= FEAT_DOOR_HEAD) && (c_ptr->feat <= FEAT_DOOR_TAIL)) + { + if (easy_open) + { + if (easy_open_door(y, x)) return; + } + else + { + msg_print("There is a closed door blocking your way."); + + if (!(p_ptr->confused || p_ptr->stun || p_ptr->image)) + energy_use = 0; + } + } + + /* Wall (or secret door) */ + else + { + if (!easy_tunnel) + { + int feat; + + if (c_ptr->mimic) feat = c_ptr->mimic; + else + feat = f_info[c_ptr->feat].mimic; + + msg_format("There is %s.", f_text + f_info[feat].block); + + if (!(p_ptr->confused || p_ptr->stun || p_ptr->image)) + energy_use = 0; + } + else + { + do_cmd_tunnel_aux(y, x, dir); + return; + } + } + } + + /* Sound */ + sound(SOUND_HITWALL); + } + + /* Normal movement */ + if (!pattern_seq(p_ptr->py, p_ptr->px, y, x)) + { + if (!(p_ptr->confused || p_ptr->stun || p_ptr->image)) + { + energy_use = 0; + } + + disturb(0); /* To avoid a loop with running */ + + oktomove = FALSE; + } + + + /* + * Check trap detection status -- retrieve them here + * because they are used by the movement code as well + */ + old_dtrap = ((cave[p_ptr->py][p_ptr->px].info & CAVE_DETECT) != 0); + new_dtrap = ((cave[y][x].info & CAVE_DETECT) != 0); + + /* Normal movement */ + if (oktomove && running && disturb_detect) + { + /* + * Disturb the player when about to leave the trap detected + * area + */ + if (old_dtrap && !new_dtrap) + { + /* Disturb player */ + disturb(0); + + /* but don't take a turn */ + energy_use = 0; + + /* Tell player why */ + cmsg_print(TERM_VIOLET, "You are about to leave a trap detected zone."); + /* Flush */ + /* msg_print(NULL); */ + + oktomove = FALSE; + } + } + + /* Normal movement */ + if (oktomove) + { + int oy, ox; + int feat; + + /* Rooted means no move */ + if (p_ptr->tim_roots) return; + + /* Save old location */ + oy = p_ptr->py; + ox = p_ptr->px; + + /* Move the player */ + p_ptr->py = y; + p_ptr->px = x; + + if (cave[p_ptr->py][p_ptr->px].mimic) feat = cave[p_ptr->py][p_ptr->px].mimic; + else + feat = cave[p_ptr->py][p_ptr->px].feat; + + /* Some hooks */ + if (process_hooks(HOOK_MOVED, "(d,d)", oy, ox)) return; + + /* Redraw new spot */ + lite_spot(p_ptr->py, p_ptr->px); + + /* Redraw old spot */ + lite_spot(oy, ox); + + /* Sound */ + /* sound(SOUND_WALK); */ + + /* Check for new panel (redraw map) */ + verify_panel(); + + /* Check detection status */ + if (old_dtrap && !new_dtrap) + { + cmsg_print(TERM_VIOLET, "You leave a trap detected zone."); + if (running) msg_print(NULL); + p_ptr->redraw |= (PR_DTRAP); + } + else if (!old_dtrap && new_dtrap) + { + cmsg_print(TERM_L_BLUE, "You enter a trap detected zone."); + if (running) msg_print(NULL); + p_ptr->redraw |= (PR_DTRAP); + } + + /* Update stuff */ + p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE); + + /* Update the monsters */ + p_ptr->update |= (PU_DISTANCE); + + /* Window stuff */ + if (!run) p_ptr->window |= (PW_OVERHEAD); + + /* Some feature descs */ + if (f_info[cave[p_ptr->py][p_ptr->px].feat].text > 1) + { + /* Mega-hack for dungeon branches */ + if ((feat == FEAT_MORE) && c_ptr->special) + { + msg_format("There is %s", d_text + d_info[c_ptr->special].text); + } + else + { + msg_print(f_text + f_info[feat].text); + } + + /* Flush message while running */ + if (running) msg_print(NULL); + } + + /* Spontaneous Searching */ + if ((p_ptr->skill_fos >= 50) || (0 == rand_int(50 - p_ptr->skill_fos))) + { + search(); + } + + /* Continuous Searching */ + if (p_ptr->searching) + { + search(); + } + + /* Handle "objects" */ + carry(do_pickup); + + /* Handle "store doors" */ + if (c_ptr->feat == FEAT_SHOP) + { + /* Disturb */ + disturb(0); + + /* Hack -- Enter store */ + command_new = '_'; + } + + else if (cave[y][x].feat >= FEAT_ALTAR_HEAD && + cave[y][x].feat <= FEAT_ALTAR_TAIL) + { + cptr name = f_name + f_info[cave[y][x].feat].name; + cptr pref = (is_a_vowel(name[0])) ? "an" : "a"; + + msg_format("You see %s %s.", pref, name); + + /* Flush message while running */ + if (running) msg_print(NULL); + } + + /* Discover invisible traps */ + else if ((c_ptr->t_idx != 0) && + !(f_info[cave[y][x].feat].flags1 & FF1_DOOR)) + { + /* Disturb */ + disturb(0); + + if (!(c_ptr->info & (CAVE_TRDT))) + { + /* Message */ + msg_print("You found a trap!"); + + /* Pick a trap */ + pick_trap(p_ptr->py, p_ptr->px); + } + + /* Hit the trap */ + hit_trap(); + } + + /* Execute the inscription */ + else if (c_ptr->inscription) + { + /* Disturb */ + disturb(0); + + msg_format("There is an inscription here: %s", + inscription_info[c_ptr->inscription].text); + if (inscription_info[c_ptr->inscription].when & INSCRIP_EXEC_WALK) + { + execute_inscription(c_ptr->inscription, p_ptr->py, p_ptr->px); + } + } + } + + /* Update wilderness knowledge */ + if (p_ptr->wild_mode) + { + if (wizard) msg_format("y:%d, x:%d", p_ptr->py, p_ptr->px); + + /* Update the known wilderness */ + reveal_wilderness_around_player(p_ptr->py, p_ptr->px, 0, WILDERNESS_SEE_RADIUS); + + /* Walking the wild isnt meaningfull */ + p_ptr->did_nothing = TRUE; + } +} + +void move_player(int dir, int do_pickup, bool_ disarm) +{ + move_player_aux(dir, do_pickup, 0, disarm); +} + + +/* + * Hack -- Grid-based version of see_obstacle + */ +static int see_obstacle_grid(cave_type *c_ptr) +{ + /* + * Hack -- Avoid hitting detected traps, because we cannot rely on + * the CAVE_MARK check below, and traps can be set to nearly + * everything the player can move on to XXX XXX XXX + */ + if (c_ptr->info & (CAVE_TRDT)) return (TRUE); + + + /* Hack -- Handle special cases XXX XXX */ + switch (c_ptr->feat) + { + /* Require levitation */ + case FEAT_DARK_PIT: + case FEAT_DEEP_WATER: + case FEAT_ICE: + { + if (p_ptr->ffall || p_ptr->fly) return (FALSE); + } + + /* Require immunity */ + case FEAT_DEEP_LAVA: + case FEAT_SHAL_LAVA: + { + if (p_ptr->invuln || p_ptr->immune_fire) return (FALSE); + } + } + + + /* "Safe" floor grids aren't obstacles */ + if (f_info[c_ptr->feat].flags1 & FF1_CAN_RUN) return (FALSE); + + /* Must be known to the player */ + if (!(c_ptr->info & (CAVE_MARK))) return (FALSE); + + /* Default */ + return (TRUE); +} + + +/* + * Hack -- Check for a "known wall" or "dangerous" feature (see below) + */ +static int see_obstacle(int dir, int y, int x) +{ + /* Get the new location */ + y += ddy[dir]; + x += ddx[dir]; + + /* Illegal grids are not known walls */ + if (!in_bounds2(y, x)) return (FALSE); + + /* Analyse the grid */ + return (see_obstacle_grid(&cave[y][x])); +} + + +/* + * Hack -- Check for an "unknown corner" (see below) + */ +static int see_nothing(int dir, int y, int x) +{ + /* Get the new location */ + y += ddy[dir]; + x += ddx[dir]; + + /* Illegal grids are unknown */ + if (!in_bounds2(y, x)) return (TRUE); + + /* Memorized grids are always known */ + if (cave[y][x].info & (CAVE_MARK)) return (FALSE); + + /* Non-floor grids are unknown */ + if (!cave_floor_bold(y, x)) return (TRUE); + + /* Viewable door/wall grids are known */ + if (player_can_see_bold(y, x)) return (FALSE); + + /* Default */ + return (TRUE); +} + + + + + +/* + * The running algorithm: -CJS- + * + * In the diagrams below, the player has just arrived in the + * grid marked as '@', and he has just come from a grid marked + * as 'o', and he is about to enter the grid marked as 'x'. + * + * Of course, if the "requested" move was impossible, then you + * will of course be blocked, and will stop. + * + * Overview: You keep moving until something interesting happens. + * If you are in an enclosed space, you follow corners. This is + * the usual corridor scheme. If you are in an open space, you go + * straight, but stop before entering enclosed space. This is + * analogous to reaching doorways. If you have enclosed space on + * one side only (that is, running along side a wall) stop if + * your wall opens out, or your open space closes in. Either case + * corresponds to a doorway. + * + * What happens depends on what you can really SEE. (i.e. if you + * have no light, then running along a dark corridor is JUST like + * running in a dark room.) The algorithm works equally well in + * corridors, rooms, mine tailings, earthquake rubble, etc, etc. + * + * These conditions are kept in static memory: + * find_openarea You are in the open on at least one + * side. + * find_breakleft You have a wall on the left, and will + * stop if it opens + * find_breakright You have a wall on the right, and will + * stop if it opens + * + * To initialize these conditions, we examine the grids adjacent + * to the grid marked 'x', two on each side (marked 'L' and 'R'). + * If either one of the two grids on a given side is seen to be + * closed, then that side is considered to be closed. If both + * sides are closed, then it is an enclosed (corridor) run. + * + * LL L + * @x LxR + * RR @R + * + * Looking at more than just the immediate squares is + * significant. Consider the following case. A run along the + * corridor will stop just before entering the center point, + * because a choice is clearly established. Running in any of + * three available directions will be defined as a corridor run. + * Note that a minor hack is inserted to make the angled corridor + * entry (with one side blocked near and the other side blocked + * further away from the runner) work correctly. The runner moves + * diagonally, but then saves the previous direction as being + * straight into the gap. Otherwise, the tail end of the other + * entry would be perceived as an alternative on the next move. + * + * #.# + * ##.## + * .@x.. + * ##.## + * #.# + * + * Likewise, a run along a wall, and then into a doorway (two + * runs) will work correctly. A single run rightwards from @ will + * stop at 1. Another run right and down will enter the corridor + * and make the corner, stopping at the 2. + * + * #@x 1 + * ########### ###### + * 2 # + * ############# + * # + * + * After any move, the function area_affect is called to + * determine the new surroundings, and the direction of + * subsequent moves. It examines the current player location + * (at which the runner has just arrived) and the previous + * direction (from which the runner is considered to have come). + * + * Moving one square in some direction places you adjacent to + * three or five new squares (for straight and diagonal moves + * respectively) to which you were not previously adjacent, + * marked as '!' in the diagrams below. + * + * ...! ... + * .o@! .o.! + * ...! ..@! + * !!! + * + * You STOP if any of the new squares are interesting in any way: + * for example, if they contain visible monsters or treasure. + * + * You STOP if any of the newly adjacent squares seem to be open, + * and you are also looking for a break on that side. (that is, + * find_openarea AND find_break). + * + * You STOP if any of the newly adjacent squares do NOT seem to be + * open and you are in an open area, and that side was previously + * entirely open. + * + * Corners: If you are not in the open (i.e. you are in a corridor) + * and there is only one way to go in the new squares, then turn in + * that direction. If there are more than two new ways to go, STOP. + * If there are two ways to go, and those ways are separated by a + * square which does not seem to be open, then STOP. + * + * Otherwise, we have a potential corner. There are two new open + * squares, which are also adjacent. One of the new squares is + * diagonally located, the other is straight on (as in the diagram). + * We consider two more squares further out (marked below as ?). + * + * We assign "option" to the straight-on grid, and "option2" to the + * diagonal grid, and "check_dir" to the grid marked 's'. + * + * .s + * @x? + * #? + * + * If they are both seen to be closed, then it is seen that no + * benefit is gained from moving straight. It is a known corner. + * To cut the corner, go diagonally, otherwise go straight, but + * pretend you stepped diagonally into that next location for a + * full view next time. Conversely, if one of the ? squares is + * not seen to be closed, then there is a potential choice. We check + * to see whether it is a potential corner or an intersection/room entrance. + * If the square two spaces straight ahead, and the space marked with 's' + * are both blank, then it is a potential corner and enter if find_examine + * is set, otherwise must stop because it is not a corner. + */ + + + + +/* + * Hack -- allow quick "cycling" through the legal directions + */ +static byte cycle[] = { 1, 2, 3, 6, 9, 8, 7, 4, 1, 2, 3, 6, 9, 8, 7, 4, 1 }; + +/* + * Hack -- map each direction into the "middle" of the "cycle[]" array + */ +static byte chome[] = { 0, 8, 9, 10, 7, 0, 11, 6, 5, 4 }; + +/* + * The direction we are running + */ +static byte find_current; + +/* + * The direction we came from + */ +static byte find_prevdir; + +/* + * We are looking for open area + */ +static bool_ find_openarea; + +/* + * We are looking for a break + */ +static bool_ find_breakright; +static bool_ find_breakleft; + + + +/* + * Initialize the running algorithm for a new direction. + * + * Diagonal Corridor -- allow diaginal entry into corridors. + * + * Blunt Corridor -- If there is a wall two spaces ahead and + * we seem to be in a corridor, then force a turn into the side + * corridor, must be moving straight into a corridor here. ??? + * + * Diagonal Corridor Blunt Corridor (?) + * # # # + * #x# @x# + * @p. p + */ +static void run_init(int dir) +{ + int row, col, deepleft, deepright; + + int i, shortleft, shortright; + + + /* Save the direction */ + find_current = dir; + + /* Assume running straight */ + find_prevdir = dir; + + /* Assume looking for open area */ + find_openarea = TRUE; + + /* Assume not looking for breaks */ + find_breakright = find_breakleft = FALSE; + + /* Assume no nearby walls */ + deepleft = deepright = FALSE; + shortright = shortleft = FALSE; + + /* Find the destination grid */ + row = p_ptr->py + ddy[dir]; + col = p_ptr->px + ddx[dir]; + + /* Extract cycle index */ + i = chome[dir]; + + /* Check for walls */ + if (see_obstacle(cycle[i + 1], p_ptr->py, p_ptr->px)) + { + find_breakleft = TRUE; + shortleft = TRUE; + } + else if (see_obstacle(cycle[i + 1], row, col)) + { + find_breakleft = TRUE; + deepleft = TRUE; + } + + /* Check for walls */ + if (see_obstacle(cycle[i - 1], p_ptr->py, p_ptr->px)) + { + find_breakright = TRUE; + shortright = TRUE; + } + else if (see_obstacle(cycle[i - 1], row, col)) + { + find_breakright = TRUE; + deepright = TRUE; + } + + /* Looking for a break */ + if (find_breakleft && find_breakright) + { + /* Not looking for open area */ + find_openarea = FALSE; + + /* Hack -- allow angled corridor entry */ + if (dir & 0x01) + { + if (deepleft && !deepright) + { + find_prevdir = cycle[i - 1]; + } + else if (deepright && !deepleft) + { + find_prevdir = cycle[i + 1]; + } + } + + /* Hack -- allow blunt corridor entry */ + else if (see_obstacle(cycle[i], row, col)) + { + if (shortleft && !shortright) + { + find_prevdir = cycle[i - 2]; + } + else if (shortright && !shortleft) + { + find_prevdir = cycle[i + 2]; + } + } + } +} + + +/* + * Update the current "run" path + * + * Return TRUE if the running should be stopped + */ +static bool_ run_test(void) +{ + int prev_dir, new_dir, check_dir = 0; + + int row, col; + + int i, max, inv; + + int option = 0, option2 = 0; + + cave_type *c_ptr; + + + /* Where we came from */ + prev_dir = find_prevdir; + + + /* Range of newly adjacent grids */ + max = (prev_dir & 0x01) + 1; + + + /* Look at every newly adjacent square. */ + for (i = -max; i <= max; i++) + { + s16b this_o_idx, next_o_idx = 0; + + + /* New direction */ + new_dir = cycle[chome[prev_dir] + i]; + + /* New location */ + row = p_ptr->py + ddy[new_dir]; + col = p_ptr->px + ddx[new_dir]; + + /* Access grid */ + c_ptr = &cave[row][col]; + + + /* Visible monsters abort running */ + if (c_ptr->m_idx) + { + monster_type *m_ptr = &m_list[c_ptr->m_idx]; + + /* Visible monster */ + if (m_ptr->ml) return (TRUE); + } + + /* Visible objects abort running */ + for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) + { + object_type * o_ptr; + + /* Acquire object */ + o_ptr = &o_list[this_o_idx]; + + /* Acquire next object */ + next_o_idx = o_ptr->next_o_idx; + + /* Visible object */ + if (o_ptr->marked) return (TRUE); + } + + + /* Assume unknown */ + inv = TRUE; + + /* Check memorized grids */ + if (c_ptr->info & (CAVE_MARK)) + { + bool_ notice = TRUE; + + /* + * Examine the terrain -- conditional disturbance + * If we had more flags, we could make these customisable too + */ + switch (c_ptr->feat) + { + case FEAT_DEEP_LAVA: + case FEAT_SHAL_LAVA: + { + /* Ignore */ + if (p_ptr->invuln || p_ptr->immune_fire) notice = FALSE; + + /* Done */ + break; + } + + case FEAT_DEEP_WATER: + case FEAT_ICE: + { + /* Ignore */ + if (p_ptr->ffall || p_ptr->fly) notice = FALSE; + + /* Done */ + break; + } + + /* Open doors */ + case FEAT_OPEN: + case FEAT_BROKEN: + { + /* Option -- ignore */ + if (find_ignore_doors) notice = FALSE; + + /* Done */ + break; + } + + /* + * Stairs - too many of them, should find better ways to + * handle them (not scripting!, because it can be called + * from within the running algo) XXX XXX XXX + */ + case FEAT_LESS: + case FEAT_MORE: + case FEAT_QUEST_ENTER: + case FEAT_QUEST_EXIT: + case FEAT_QUEST_DOWN: + case FEAT_QUEST_UP: + case FEAT_SHAFT_UP: + case FEAT_SHAFT_DOWN: + case FEAT_WAY_LESS: + case FEAT_WAY_MORE: + /* XXX */ + case FEAT_BETWEEN: + case FEAT_BETWEEN2: + { + /* Option -- ignore */ + if (find_ignore_stairs) notice = FALSE; + + /* Done */ + break; + } + } + + /* Check the "don't notice running" flag */ + if (f_info[c_ptr->feat].flags1 & FF1_DONT_NOTICE_RUNNING) + { + notice = FALSE; + } + + /* A detected trap is interesting */ + if (c_ptr->info & (CAVE_TRDT)) notice = TRUE; + + /* Interesting feature */ + if (notice) return (TRUE); + + /* The grid is "visible" */ + inv = FALSE; + } + + /* Mega-Hack -- Maze code removes CAVE_MARK XXX XXX XXX */ + if (c_ptr->info & (CAVE_TRDT)) return (TRUE); + + /* Analyze unknown grids and floors */ + if (inv || cave_floor_bold(row, col)) + { + /* Looking for open area */ + if (find_openarea) + { + /* Nothing */ + } + + /* The first new direction. */ + else if (!option) + { + option = new_dir; + } + + /* Three new directions. Stop running. */ + else if (option2) + { + return (TRUE); + } + + /* Two non-adjacent new directions. Stop running. */ + else if (option != cycle[chome[prev_dir] + i - 1]) + { + return (TRUE); + } + + /* Two new (adjacent) directions (case 1) */ + else if (new_dir & 0x01) + { + check_dir = cycle[chome[prev_dir] + i - 2]; + option2 = new_dir; + } + + /* Two new (adjacent) directions (case 2) */ + else + { + check_dir = cycle[chome[prev_dir] + i + 1]; + option2 = option; + option = new_dir; + } + } + + /* Obstacle, while looking for open area */ + else + { + if (find_openarea) + { + if (i < 0) + { + /* Break to the right */ + find_breakright = TRUE; + } + + else if (i > 0) + { + /* Break to the left */ + find_breakleft = TRUE; + } + } + } + } + + + /* Looking for open area */ + if (find_openarea) + { + /* Hack -- look again */ + for (i = -max; i < 0; i++) + { + new_dir = cycle[chome[prev_dir] + i]; + + row = p_ptr->py + ddy[new_dir]; + col = p_ptr->px + ddx[new_dir]; + + /* Access grid */ + c_ptr = &cave[row][col]; + + /* Unknown grids or non-obstacle */ + if (!see_obstacle_grid(c_ptr)) + { + /* Looking to break right */ + if (find_breakright) + { + return (TRUE); + } + } + + /* Obstacle */ + else + { + /* Looking to break left */ + if (find_breakleft) + { + return (TRUE); + } + } + } + + /* Hack -- look again */ + for (i = max; i > 0; i--) + { + new_dir = cycle[chome[prev_dir] + i]; + + row = p_ptr->py + ddy[new_dir]; + col = p_ptr->px + ddx[new_dir]; + + /* Access grid */ + c_ptr = &cave[row][col]; + + /* Unknown grid or non-obstacle */ + if (!see_obstacle_grid(c_ptr)) + { + /* Looking to break left */ + if (find_breakleft) + { + return (TRUE); + } + } + + /* Obstacle */ + else + { + /* Looking to break right */ + if (find_breakright) + { + return (TRUE); + } + } + } + } + + + /* Not looking for open area */ + else + { + /* No options */ + if (!option) + { + return (TRUE); + } + + /* One option */ + else if (!option2) + { + /* Primary option */ + find_current = option; + + /* No other options */ + find_prevdir = option; + } + + /* Two options, examining corners */ + else if (find_examine && !find_cut) + { + /* Primary option */ + find_current = option; + + /* Hack -- allow curving */ + find_prevdir = option2; + } + + /* Two options, pick one */ + else + { + /* Get next location */ + row = p_ptr->py + ddy[option]; + col = p_ptr->px + ddx[option]; + + /* Don't see that it is closed off. */ + /* This could be a potential corner or an intersection. */ + if (!see_obstacle(option, row, col) || !see_obstacle(check_dir, row, col)) + { + /* Can not see anything ahead and in the direction we */ + /* are turning, assume that it is a potential corner. */ + if (find_examine && + see_nothing(option, row, col) && + see_nothing(option2, row, col)) + { + find_current = option; + find_prevdir = option2; + } + + /* STOP: we are next to an intersection or a room */ + else + { + return (TRUE); + } + } + + /* This corner is seen to be enclosed; we cut the corner. */ + else if (find_cut) + { + find_current = option2; + find_prevdir = option2; + } + + /* This corner is seen to be enclosed, and we */ + /* deliberately go the long way. */ + else + { + find_current = option; + find_prevdir = option2; + } + } + } + + + /* About to hit a known wall, stop */ + if (see_obstacle(find_current, p_ptr->py, p_ptr->px)) + { + return (TRUE); + } + + + /* Failure */ + return (FALSE); +} + + + +/* + * Take one step along the current "run" path + */ +void run_step(int dir) +{ + /* Start running */ + if (dir) + { + /* Hack -- do not start silly run */ + if (see_obstacle(dir, p_ptr->py, p_ptr->px) && + (cave[p_ptr->py + ddy[dir]][p_ptr->px + ddx[dir]].feat != FEAT_TREES)) + { + /* Message */ + msg_print("You cannot run in that direction."); + + /* Disturb */ + disturb(0); + + /* Done */ + return; + } + + /* Calculate torch radius */ + p_ptr->update |= (PU_TORCH); + + /* Initialize */ + run_init(dir); + } + + /* Keep running */ + else + { + /* Update run */ + if (run_test()) + { + /* Disturb */ + disturb(0); + + /* Done */ + return; + } + } + + /* Decrease the run counter */ + if (--running <= 0) return; + + /* Take time */ + energy_use = 100; + + + /* Move the player, using the "pickup" flag */ + move_player_aux(find_current, always_pickup, 1, TRUE); +} + + +/* + * Take care of the various things that can happen when you step + * into a space. (Objects, traps, and stores.) + */ +void step_effects(int y, int x, int do_pickup) +{ + /* Handle "objects" */ + py_pickup_floor(do_pickup); + + /* Handle "store doors" */ + if (cave[y][x].feat == FEAT_SHOP) + { + /* Disturb */ + disturb(0); + + /* Hack -- Enter store */ + command_new = KTRL('V'); + } + + /* Discover/set off traps */ + else if (cave[y][x].t_idx != 0) + { + /* Disturb */ + disturb(0); + + if (!(cave[y][x].info & CAVE_TRDT)) + { + /* Message */ + msg_print("You found a trap!"); + + /* Pick a trap */ + pick_trap(y, x); + } + + /* Hit the trap */ + hit_trap(); + } +} + +/* + * Issue a pet command + */ +void do_cmd_pet(void) +{ + int i = 0; + + int num = 0; + + int powers[36]; + + char power_desc[36][80]; + + bool_ flag, redraw; + + int ask; + + char choice; + + char out_val[160]; + + int pets = 0, pet_ctr = 0; + + bool_ all_pets = FALSE; + + monster_type *m_ptr; + + + for (num = 0; num < 36; num++) + { + powers[num] = 0; + strcpy(power_desc[num], ""); + } + + num = 0; + + if (p_ptr->confused) + { + msg_print("You are too confused to command your pets."); + energy_use = 0; + return; + } + + /* Calculate pets */ + /* Process the monsters (backwards) */ + for (pet_ctr = m_max - 1; pet_ctr >= 1; pet_ctr--) + { + /* Access the monster */ + m_ptr = &m_list[pet_ctr]; + + if (m_ptr->status >= MSTATUS_FRIEND) pets++; + } + + if (pets == 0) + { + msg_print("You have no pets/companions."); + energy_use = 0; + return; + } + else + { + strcpy(power_desc[num], "dismiss pets"); + powers[num++] = 1; + strcpy(power_desc[num], "dismiss companions"); + powers[num++] = 10; + strcpy(power_desc[num], "call pets"); + powers[num++] = 2; + strcpy(power_desc[num], "follow me"); + powers[num++] = 6; + strcpy(power_desc[num], "seek and destroy"); + powers[num++] = 3; + if (p_ptr->pet_open_doors) + strcpy(power_desc[num], "disallow open doors"); + else + strcpy(power_desc[num], "allow open doors"); + powers[num++] = 4; + if (p_ptr->pet_pickup_items) + strcpy(power_desc[num], "disallow pickup items"); + else + strcpy(power_desc[num], "allow pickup items"); + powers[num++] = 5; + strcpy(power_desc[num], "give target to a friend"); + powers[num++] = 7; + strcpy(power_desc[num], "give target to all friends"); + powers[num++] = 8; + strcpy(power_desc[num], "friend forget target"); + powers[num++] = 9; + } + + /* Nothing chosen yet */ + flag = FALSE; + + /* No redraw yet */ + redraw = FALSE; + + /* Build a prompt (accept all spells) */ + if (num <= 26) + { + /* Build a prompt (accept all spells) */ + strnfmt(out_val, 78, + "(Command %c-%c, *=List, ESC=exit) Select a command: ", I2A(0), + I2A(num - 1)); + } + else + { + strnfmt(out_val, 78, + "(Command %c-%c, *=List, ESC=exit) Select a command: ", I2A(0), + '0' + num - 27); + } + + /* Get a command from the user */ + while (!flag && get_com(out_val, &choice)) + { + /* Request redraw */ + if ((choice == ' ') || (choice == '*') || (choice == '?')) + { + /* Show the list */ + if (!redraw) + { + byte y = 1, x = 0; + int ctr = 0; + char dummy[80]; + + strcpy(dummy, ""); + + /* Show list */ + redraw = TRUE; + + /* Save the screen */ + character_icky = TRUE; + Term_save(); + + prt("", y++, x); + + while (ctr < num) + { + strnfmt(dummy, 80, "%c) %s", I2A(ctr), power_desc[ctr]); + prt(dummy, y + ctr, x); + ctr++; + } + + if (ctr < 17) + { + prt("", y + ctr, x); + } + else + { + prt("", y + 17, x); + } + } + + /* Hide the list */ + else + { + /* Hide list */ + redraw = FALSE; + + /* Restore the screen */ + Term_load(); + character_icky = FALSE; + } + + /* Redo asking */ + continue; + } + + if (choice == '\r' && num == 1) + { + choice = 'a'; + } + + if (isalpha(choice)) + { + /* Note verify */ + ask = (isupper(choice)); + + /* Lowercase */ + if (ask) choice = tolower(choice); + + /* Extract request */ + i = (islower(choice) ? A2I(choice) : -1); + } + else + { + ask = FALSE; /* Can't uppercase digits */ + + i = choice - '0' + 26; + } + + /* Totally Illegal */ + if ((i < 0) || (i >= num)) + { + bell(); + continue; + } + + /* Verify it */ + if (ask) + { + char tmp_val[160]; + + /* Prompt */ + strnfmt(tmp_val, 78, "Use %s? ", power_desc[i]); + + /* Belay that order */ + if (!get_check(tmp_val)) continue; + } + + /* Stop the loop */ + flag = TRUE; + } + + /* Restore the screen */ + if (redraw) + { + Term_load(); + character_icky = FALSE; + } + + /* Abort if needed */ + if (!flag) + { + energy_use = 0; + return; + } + + switch (powers[i]) + { + /* forget target */ + case 9: + { + monster_type *m_ptr; + int ii, jj; + + msg_print("Select the friendly monster:"); + if (!tgt_pt(&ii, &jj)) return; + + if (cave[jj][ii].m_idx) + { + m_ptr = &m_list[cave[jj][ii].m_idx]; + + if (m_ptr->status < MSTATUS_PET) + { + msg_print("You cannot give orders to this monster."); + return; + } + + m_ptr->target = -1; + } + break; + } + /* Give target to all */ + case 8: + { + monster_type *m_ptr; + int ii, jj, i; + + + msg_print("Select the target monster:"); + if (!tgt_pt(&ii, &jj)) return; + + if (cave[jj][ii].m_idx) + { + msg_print("Target selected."); + + for (i = m_max - 1; i >= 1; i--) + { + /* Access the monster */ + m_ptr = &m_list[i]; + + if (!m_ptr->r_idx) continue; + + if (m_ptr->status < MSTATUS_PET) continue; + + m_ptr->target = cave[jj][ii].m_idx; + } + } + else + { + msg_print("This is not a correct target."); + return; + } + break; + } + case 1: /* Dismiss pets */ + { + int Dismissed = 0; + + if (get_check("Dismiss all pets? ")) all_pets = TRUE; + + /* Process the monsters (backwards) */ + for (pet_ctr = m_max - 1; pet_ctr >= 1; pet_ctr--) + { + monster_race *r_ptr; + + /* Access the monster */ + m_ptr = &m_list[pet_ctr]; + r_ptr = &r_info[m_ptr->r_idx]; + + if ((!(r_ptr->flags7 & RF7_NO_DEATH)) && ((m_ptr->status == MSTATUS_PET) || (m_ptr->status == MSTATUS_FRIEND))) /* Get rid of it! */ + { + bool_ checked = FALSE; + char command; + bool_ delete_this = FALSE; + + if (all_pets) + { + delete_this = TRUE; + } + else + { + char friend_name[80], check_friend[80]; + monster_desc(friend_name, m_ptr, 0x80); + strnfmt(check_friend, 80, "Dismiss %s? (Escape to cancel)", friend_name); + + while (!checked) + { + if (!get_com(check_friend, &command)) + { + /* get out of loop */ + checked = TRUE; + pet_ctr = 0; + } + else switch (command) + { + case 'Y': + case 'y': + delete_this = TRUE; + checked = TRUE; + break; + case 'n': + case 'N': + checked = TRUE; + break; + default: + bell(); + break; + } + } + } + + if (delete_this) + { + delete_monster_idx(pet_ctr); + Dismissed++; + } + } + } + + msg_format("You have dismissed %d pet%s.", Dismissed, + (Dismissed == 1 ? "" : "s")); + break; + } + case 10: /* Dismiss companions */ + { + int Dismissed = 0; + + if (get_check("Dismiss all companions? ")) all_pets = TRUE; + + /* Process the monsters (backwards) */ + for (pet_ctr = m_max - 1; pet_ctr >= 1; pet_ctr--) + { + monster_race *r_ptr; + + /* Access the monster */ + m_ptr = &m_list[pet_ctr]; + r_ptr = &r_info[m_ptr->r_idx]; + + if ((!(r_ptr->flags7 & RF7_NO_DEATH)) && ((m_ptr->status == MSTATUS_COMPANION))) /* Get rid of it! */ + { + bool_ delete_this = FALSE; + + if (all_pets) + delete_this = TRUE; + else + { + char friend_name[80], check_friend[80]; + monster_desc(friend_name, m_ptr, 0x80); + strnfmt(check_friend, 80, "Dismiss %s? ", friend_name); + + if (get_check(check_friend)) + delete_this = TRUE; + } + + if (delete_this) + { + delete_monster_idx(pet_ctr); + Dismissed++; + } + } + } + + msg_format("You have dismissed %d companion%s.", Dismissed, + (Dismissed == 1 ? "" : "s")); + break; + } + /* Call pets */ + case 2: + { + p_ptr->pet_follow_distance = 1; + break; + } + /* "Seek and destroy" */ + case 3: + { + p_ptr->pet_follow_distance = 255; + break; + } + /* flag - allow pets to open doors */ + case 4: + { + p_ptr->pet_open_doors = !p_ptr->pet_open_doors; + break; + } + /* flag - allow pets to pickup items */ + case 5: + { + p_ptr->pet_pickup_items = !p_ptr->pet_pickup_items; + + /* Drop objects being carried by pets */ + if (!p_ptr->pet_pickup_items) + { + for (pet_ctr = m_max - 1; pet_ctr >= 1; pet_ctr--) + { + /* Access the monster */ + m_ptr = &m_list[pet_ctr]; + + if (m_ptr->status >= MSTATUS_PET) + { + monster_drop_carried_objects(m_ptr); + } + } + } + + break; + } + /* "Follow Me" */ + case 6: + { + p_ptr->pet_follow_distance = 6; + break; + } + } +} + +/* + * Incarnate into a body + */ +bool_ do_cmd_integrate_body() +{ + cptr q, s; + + int item; + + object_type *o_ptr; + + + if (!p_ptr->disembodied) + { + msg_print("You are already in a body."); + return FALSE; + } + + /* Restrict choices to monsters */ + item_tester_tval = TV_CORPSE; + + /* Get an item */ + q = "Incarnate in which body? "; + s = "You have no corpse to incarnate in."; + if (!get_item(&item, q, s, (USE_FLOOR))) return FALSE; + + o_ptr = &o_list[0 - item]; + + if (o_ptr->sval != SV_CORPSE_CORPSE) + { + msg_print("You must select a corpse."); + return FALSE; + } + + p_ptr->body_monster = o_ptr->pval2; + p_ptr->chp = o_ptr->pval3; + + floor_item_increase(0 - item, -1); + floor_item_describe(0 - item); + floor_item_optimize(0 - item); + + msg_print("Your spirit is incarnated in your new body."); + p_ptr->wraith_form = FALSE; + p_ptr->disembodied = FALSE; + do_cmd_redraw(); + + return TRUE; +} + +/* + * Leave a body + */ +bool_ do_cmd_leave_body(bool_ drop_body) +{ + object_type *o_ptr, forge; + + monster_race *r_ptr = &r_info[p_ptr->body_monster]; + + int i; + + + if (p_ptr->disembodied) + { + msg_print("You are already disembodied."); + return FALSE; + } + + for (i = INVEN_WIELD; i < INVEN_TOTAL; i++) + { + if (p_ptr->body_parts[i - INVEN_WIELD] && p_ptr->inventory[i].k_idx && + cursed_p(&p_ptr->inventory[i])) + { + msg_print("A cursed object is preventing you from leaving your body."); + return FALSE; + } + } + + if (drop_body) + { + if (magik(25 + get_skill_scale(SKILL_POSSESSION, 25) + get_skill(SKILL_PRESERVATION))) + { + o_ptr = &forge; + object_prep(o_ptr, lookup_kind(TV_CORPSE, SV_CORPSE_CORPSE)); + o_ptr->number = 1; + o_ptr->pval = 0; + o_ptr->pval2 = p_ptr->body_monster; + o_ptr->pval3 = p_ptr->chp; + o_ptr->weight = (r_ptr->weight + rand_int(r_ptr->weight) / 10) + 1; + object_aware(o_ptr); + object_known(o_ptr); + o_ptr->ident |= IDENT_STOREB; + + /* Unique corpses are unique */ + if (r_ptr->flags1 & RF1_UNIQUE) + { + o_ptr->name1 = 201; + } + + drop_near(o_ptr, -1, p_ptr->py, p_ptr->px); + } + else + msg_print + ("You do not manage to keep the corpse from rotting away."); + } + + msg_print("Your spirit leaves your body."); + p_ptr->disembodied = TRUE; + + /* Turn into a lost soul(just for the picture) */ + p_ptr->body_monster = test_monster_name("Lost soul"); + do_cmd_redraw(); + + return (TRUE); +} + + +bool_ execute_inscription(byte i, byte y, byte x) +{ + cave_type *c_ptr = &cave[y][x]; + + + /* Not enough mana in the current grid */ + if (c_ptr->mana < inscription_info[i].mana) return (TRUE); + + + /* Reduce the grid mana -- note: it can't be restored */ + c_ptr->mana -= inscription_info[i].mana; + + /* Analyse inscription type */ + switch (i) + { + case INSCRIP_LIGHT: + { + msg_print("The inscription shines in a bright light!"); + lite_room(y, x); + + break; + } + + case INSCRIP_DARK: + { + msg_print("The inscription is enveloped in a dark aura!"); + unlite_room(y, x); + + break; + } + + case INSCRIP_STORM: + { + msg_print("The inscription releases a powerful storm!"); + project(0, 3, y, x, damroll(10, 10), + GF_ELEC, PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | + PROJECT_KILL | PROJECT_JUMP); + + break; + } + + case INSCRIP_PROTECTION: + { + return (FALSE); + + break; + } + + case INSCRIP_DWARF_SUMMON: + { + int yy = y, xx = x; + + scatter(&yy, &xx, y, x, 3); + place_monster_one(yy, xx, test_monster_name("Dwarven Warrior"), + 0, FALSE, MSTATUS_FRIEND); + + break; + } + + case INSCRIP_CHASM: + { + monster_type *m_ptr; + monster_race *r_ptr; + cave_type *c_ptr; + int ii = x, ij = y; + + cave_set_feat(ij, ii, FEAT_DARK_PIT); + msg_print("A chasm appears in the floor!"); + + if (cave[ij][ii].m_idx) + { + m_ptr = &m_list[cave[ij][ii].m_idx]; + r_ptr = race_inf(m_ptr); + + if (r_ptr->flags7 & RF7_CAN_FLY) + { + msg_print("The monster simply flies over the chasm."); + } + else + { + if (!(r_ptr->flags1 & RF1_UNIQUE)) + { + msg_print("The monster falls in the chasm!"); + delete_monster_idx(cave[ij][ii].m_idx); + } + } + } + + if (cave[ij][ii].o_idx) + { + s16b this_o_idx, next_o_idx = 0; + + c_ptr = &cave[ij][ii]; + + /* Scan all objects in the grid */ + for (this_o_idx = c_ptr->o_idx; this_o_idx; + this_o_idx = next_o_idx) + { + object_type * o_ptr; + bool_ plural = FALSE; + + char o_name[80]; + + /* Acquire object */ + o_ptr = &o_list[this_o_idx]; + + if (o_ptr->number > 1) plural = TRUE; + + /* Acquire next object */ + next_o_idx = o_ptr->next_o_idx; + + /* Effect "observed" */ + if (o_ptr->marked) + { + object_desc(o_name, o_ptr, FALSE, 0); + } + + /* Artifacts get to resist */ + if (o_ptr->name1) + { + /* Observe the resist */ + if (o_ptr->marked) + { + msg_format("The %s %s simply fly over the chasm!", + o_name, (plural ? "are" : "is")); + } + } + + /* Kill it */ + else + { + /* Delete the object */ + delete_object_idx(this_o_idx); + + /* Redraw */ + lite_spot(ij, ii); + } + } + } + + break; + } + + case INSCRIP_BLACK_FIRE: + { + msg_print("The inscription releases a blast of hellfire!"); + project(0, 3, y, x, 200, + GF_HELL_FIRE, PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | + PROJECT_KILL | PROJECT_JUMP); + + break; + } + } + + return (TRUE); +} + + +/* + * Choose an inscription and engrave it + */ +void do_cmd_engrave() +{ + char buf[41] = ""; + + byte i; + + strnfmt(buf, 41, "%s", inscription_info[cave[p_ptr->py][p_ptr->px].inscription].text); + + get_string("Engrave what? ", buf, 40); + + /* Silently do nothing when player his escape or enters an empty string */ + if (!buf[0]) return; + + for (i = 0; i < MAX_INSCRIPTIONS; i++) + { + if (!strcmp(inscription_info[i].text, buf)) + { + if (inscription_info[i].know) + { + /* Save the inscription */ + cave[p_ptr->py][p_ptr->px].inscription = i; + } + else + msg_print("You can't use this inscription for now."); + } + } + + /* Execute the inscription */ + if (inscription_info[cave[p_ptr->py][p_ptr->px].inscription].when & INSCRIP_EXEC_ENGRAVE) + { + execute_inscription(cave[p_ptr->py][p_ptr->px].inscription, p_ptr->py, p_ptr->px); + } + + energy_use += 300; +} + + +/* + * Let's do a spinning around attack: -- DG -- + * aDb + * y@k + * ooT + * Ah ... all of those will get hit. + */ +void do_spin() +{ + int i, j; + + + msg_print("You start spinning around..."); + + for (j = p_ptr->py - 1; j <= p_ptr->py + 1; j++) + { + for (i = p_ptr->px - 1; i <= p_ptr->px + 1; i++) + { + /* Avoid stupid bugs */ + if (in_bounds(j, i) && cave[j][i].m_idx) + py_attack(j, i, 1); + } + } +} diff --git a/src/cmd2.c b/src/cmd2.c deleted file mode 100644 index 67f25098..00000000 --- a/src/cmd2.c +++ /dev/null @@ -1,5182 +0,0 @@ -/* File: cmd2.c */ - -/* Purpose: Movement commands (part 2) */ - -/* - * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke - * - * This software may be copied and distributed for educational, research, and - * not for profit purposes provided that this copyright and statement are - * included in all such copies. - */ - -#include "angband.h" -#include "hooks.h" - -void do_cmd_immovable_special(void); - -/* - * Try to bash an altar - */ -static bool_ do_cmd_bash_altar(int y, int x) -{ - msg_print("Are you mad? You want to anger the gods?"); - return (FALSE); -} - - -/* - * Try to bash a fountain - */ -static bool_ do_cmd_bash_fountain(int y, int x) -{ - int bash, temp; - - bool_ more = TRUE; - - monster_race *r_ptr = &r_info[p_ptr->body_monster]; - - - if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_BASH_DOOR)) - { - msg_print("You cannot do that."); - - return (FALSE); - } - - /* Take a turn */ - energy_use = 100; - - /* Message */ - msg_print("You smash into the fountain!"); - - /* Hack -- Bash power based on strength */ - /* (Ranges from 3 to 20 to 100 to 200) */ - bash = adj_str_blow[p_ptr->stat_ind[A_STR]]; - - /* Compare bash power to door power XXX XXX XXX */ - temp = (bash - 50); - - /* Hack -- always have a chance */ - if (temp < 1) temp = 1; - - /* Hack -- attempt to bash down the door */ - if (rand_int(200) < temp) - { - /* Message */ - msg_print("The fountain breaks!"); - - fire_ball(GF_WATER, 5, damroll(6, 8), 2); - - cave_set_feat(y, x, FEAT_DEEP_WATER); - more = FALSE; - } - - return (more); -} - -/* - * Stair hooks - */ -static bool_ stair_hooks(stairs_direction direction) -{ - cptr direction_s = (direction == STAIRS_UP) ? "up" : "down"; - - /* Old-style hooks */ - if (process_hooks(HOOK_STAIR, "(s)", direction_s)) - { - return TRUE; /* Prevent movement */ - } - - /* New-style hooks */ - { - hook_stair_in in = { direction }; - hook_stair_out out = { TRUE }; /* Allow by default */ - - process_hooks_new(HOOK_STAIR, &in, &out); - - return (!out.allow); - } -} - - -/* - * Go up one level - */ -void do_cmd_go_up(void) -{ - bool_ go_up = FALSE, go_up_many = FALSE, prob_traveling = FALSE; - - cave_type *c_ptr; - - int oldl = dun_level; - - dungeon_info_type *d_ptr = &d_info[dungeon_type]; - - - /* Player grid */ - c_ptr = &cave[p_ptr->py][p_ptr->px]; - - /* Can we ? */ - if (stair_hooks(STAIRS_UP)) - { - return; - } - - /* Normal up stairs */ - if ((c_ptr->feat == FEAT_LESS) || (c_ptr->feat == FEAT_WAY_LESS)) - { - if (!dun_level) - { - go_up = TRUE; - } - else if ((dungeon_flags2 & DF2_ASK_LEAVE)) - { - go_up = get_check("Leave this unique level forever? "); - } - else if (confirm_stairs) - { - go_up = get_check("Really leave the level? "); - } - else - { - go_up = TRUE; - } - } - - /* Shaft up */ - else if (c_ptr->feat == FEAT_SHAFT_UP) - { - if (dun_level == 1) - { - go_up = TRUE; - } - else if ((dungeon_flags2 & DF2_ASK_LEAVE)) - { - go_up = get_check("Leave this unique level forever? "); - } - else if (confirm_stairs) - { - go_up_many = get_check("Really leave the level? "); - } - else - { - go_up_many = TRUE; - } - } - - /* Quest exit */ - else if (c_ptr->feat == FEAT_QUEST_EXIT) - { - leaving_quest = p_ptr->inside_quest; - - if ((dungeon_flags2 & DF2_ASK_LEAVE) && - !get_check("Leave this unique level forever? ")) - return; - - p_ptr->inside_quest = c_ptr->special; - dun_level = 0; - p_ptr->oldpx = 0; - p_ptr->oldpy = 0; - p_ptr->leaving = TRUE; - - return; - } - - /* Exits to previous area in flat terrains */ - else if (!(dungeon_flags1 & DF1_FLAT) && - p_ptr->prob_travel && !p_ptr->inside_quest) - { - if (d_ptr->mindepth == dun_level) return; - - if (dungeon_flags2 & DF2_NO_EASY_MOVE) - { - msg_print("Some powerful force prevents your from teleporting."); - return; - } - - prob_traveling = TRUE; - - if (confirm_stairs) - { - if (get_check("Really leave the level? ")) - go_up = TRUE; - } - else - { - go_up = TRUE; - } - } - else - { - msg_print("I see no up staircase here."); - return; - } - - if (go_up || go_up_many) - { - - energy_use = 0; - - /* Success */ - if (c_ptr->feat == FEAT_WAY_LESS) - msg_print("You enter the previous area."); - else - msg_print("You enter a maze of up staircases."); - - autosave_checkpoint(); - - if (p_ptr->inside_quest) - { - dun_level = 1; - leaving_quest = p_ptr->inside_quest; - - p_ptr->inside_quest = c_ptr->special; - } - - /* Create a way back */ - if (go_up_many) - create_down_shaft = TRUE; - else - create_down_stair = TRUE; - - /* New depth */ - if (go_up) - dun_level--; - else - { - dun_level -= randint(3) + 1; - if (dun_level <= 0) dun_level = 0; - } - - if (c_ptr->special && (!prob_traveling)) - { - dun_level = oldl; - dun_level = get_flevel(); - dungeon_type = c_ptr->special; - dun_level += d_info[dungeon_type].mindepth; - } - - /* Leaving */ - p_ptr->leaving = TRUE; - } -} - - -/* - * Returns TRUE if we are in the Between... - */ -static bool_ between_effect(void) -{ - byte bx, by; - - - if (cave[p_ptr->py][p_ptr->px].feat == FEAT_BETWEEN) - { - - bx = cave[p_ptr->py][p_ptr->px].special & 255; - by = cave[p_ptr->py][p_ptr->px].special >> 8; - - msg_print("You fall into the void."); - msg_print("Brrrr! It's deadly cold."); - - swap_position(by, bx); - - /* To avoid being teleported back */ - energy_use = 100; - - return (TRUE); - } - - else if (cave[p_ptr->py][p_ptr->px].feat == FEAT_BETWEEN2) - { - between_exit *be_ptr = &between_exits[cave[p_ptr->py][p_ptr->px].special]; - - p_ptr->wild_mode = FALSE; - p_ptr->wilderness_x = be_ptr->wild_x; - p_ptr->wilderness_y = be_ptr->wild_y; - p_ptr->oldpx = p_ptr->px = be_ptr->px; - p_ptr->oldpy = p_ptr->py = be_ptr->py; - dungeon_type = be_ptr->d_idx; - dun_level = be_ptr->level; - p_ptr->leaving = TRUE; - - return (TRUE); - } - else - return (FALSE); -} - -/* - * Go down one level - */ -void do_cmd_go_down(void) -{ - cave_type *c_ptr; - - bool_ go_down = FALSE, go_down_many = FALSE, prob_traveling = FALSE; - - bool_ fall_trap = FALSE; - - char i; - - int old_dun = dun_level; - - dungeon_info_type *d_ptr = &d_info[dungeon_type]; - - - /* MUST be actived now */ - if (between_effect()) return; - - /* Player grid */ - c_ptr = &cave[p_ptr->py][p_ptr->px]; - - if (p_ptr->astral && (dun_level == 98)) return; - - if (c_ptr->t_idx == TRAP_OF_SINKING) fall_trap = TRUE; - - /* test if on special level */ - if ((dungeon_flags2 & DF2_ASK_LEAVE)) - { - prt("Leave this unique level forever (y/n) ? ", 0, 0); - flush(); - i = inkey(); - prt("", 0, 0); - if (i != 'y') return; - } - - /* Can we ? */ - if (stair_hooks(STAIRS_DOWN)) - { - return; - } - - /* Normal up stairs */ - if (c_ptr->feat == FEAT_SHAFT_DOWN) - { - if (!dun_level) - { - go_down = TRUE; - - /* Save old player position */ - p_ptr->oldpx = p_ptr->px; - p_ptr->oldpy = p_ptr->py; - } - else - { - if (confirm_stairs) - { - if (get_check("Really leave the level? ")) - go_down_many = TRUE; - } - else - { - go_down_many = TRUE; - } - } - } - - /* Normal stairs */ - else if ((c_ptr->feat == FEAT_MORE) || (c_ptr->feat == FEAT_WAY_MORE)) - { - if (p_ptr->prob_travel) - { - if (d_ptr->maxdepth == dun_level) return; - } - if (!dun_level) - { - go_down = TRUE; - - /* Save old player position */ - p_ptr->oldpx = p_ptr->px; - p_ptr->oldpy = p_ptr->py; - } - else - { - if (confirm_stairs) - { - if (get_check("Really leave the level? ")) - go_down = TRUE; - } - else - { - go_down = TRUE; - } - } - } - - /* Handle quest areas -KMW- */ - else if (c_ptr->feat == FEAT_QUEST_ENTER) - { - /* Enter quest level */ - enter_quest(); - - return; - } - - else if (!(dungeon_flags1 & DF1_FLAT) && - p_ptr->prob_travel && !p_ptr->inside_quest) - { - if (d_ptr->maxdepth == dun_level) return; - - if (dungeon_flags2 & DF2_NO_EASY_MOVE) - { - msg_print("Some powerfull force prevents your from teleporting."); - return; - } - - prob_traveling = TRUE; - - if (confirm_stairs) - { - if (get_check("Really leave the level? ")) - go_down = TRUE; - } - else - { - go_down = TRUE; - } - } - - else if (!(fall_trap)) - { - msg_print("I see no down staircase here."); - return; - } - - if (go_down || go_down_many) - { - energy_use = 0; - - if (fall_trap) - msg_print("You deliberately jump through the trap door."); - else - { - if (c_ptr->feat == FEAT_WAY_MORE) - msg_print("You enter the next area."); - else - msg_print("You enter a maze of down staircases."); - } - - autosave_checkpoint(); - - /* Go down */ - if (go_down) - { - dun_level++; - } - else if (go_down_many) - { - int i = randint(3) + 1, j; - - for (j = 1; j < i; j++) - { - dun_level++; - if (is_quest(dun_level + i - 1)) break; - if (d_ptr->maxdepth == dun_level) break; - } - } - - /* We change place */ - if (c_ptr->special && (!prob_traveling)) - { - if (d_info[c_ptr->special].min_plev <= p_ptr->lev) - { - dungeon_info_type *d_ptr = &d_info[c_ptr->special]; - - /* Do the lua scripts refuse ? ;) */ - if (process_hooks(HOOK_ENTER_DUNGEON, "(d)", c_ptr->special)) - { - dun_level = old_dun; - return; - } - - /* Ok go in the new dungeon */ - dungeon_type = c_ptr->special; - d_ptr = &d_info[dungeon_type]; - - if ((p_ptr->wilderness_x == d_ptr->ix) && - (p_ptr->wilderness_y == d_ptr->iy)) - { - dun_level = d_ptr->mindepth; - } - else if ((p_ptr->wilderness_x == d_ptr->ox) && - (p_ptr->wilderness_y == d_ptr->oy)) - { - dun_level = d_ptr->maxdepth; - } - else - { - dun_level = d_ptr->mindepth; - } - - msg_format("You go into %s", - d_text + d_info[dungeon_type].text); - } - else - { - msg_print - ("You don't feel yourself experienced enough to go there..."); - dun_level = old_dun; - return; - } - } - - /* Leaving */ - p_ptr->leaving = TRUE; - - if (!fall_trap) - { - /* Create a way back */ - if (go_down_many) - create_up_shaft = TRUE; - else - create_up_stair = TRUE; - } - } -} - - - -/* - * Simple command to "search" for one turn - */ -void do_cmd_search(void) -{ - /* Allow repeated command */ - if (command_arg) - { - /* Set repeat count */ - command_rep = command_arg - 1; - - /* Redraw the state */ - p_ptr->redraw |= (PR_STATE); - - /* Cancel the arg */ - command_arg = 0; - } - - /* Take a turn */ - energy_use = 100; - - /* Search */ - search(); -} - - -/* - * Hack -- toggle search mode - */ -void do_cmd_toggle_search(void) -{ - /* Stop searching */ - if (p_ptr->searching) - { - /* Clear the searching flag */ - p_ptr->searching = FALSE; - - /* Recalculate bonuses */ - p_ptr->update |= (PU_BONUS); - - /* Redraw the state */ - p_ptr->redraw |= (PR_STATE); - } - - /* Start searching */ - else - { - /* Set the searching flag */ - p_ptr->searching = TRUE; - - /* Update stuff */ - p_ptr->update |= (PU_BONUS); - - /* Redraw stuff */ - p_ptr->redraw |= (PR_STATE | PR_SPEED); - } -} - - - -/* - * Determine if a grid contains a chest - */ -static s16b chest_check(int y, int x) -{ - cave_type *c_ptr = &cave[y][x]; - - s16b this_o_idx, next_o_idx = 0; - - - /* Scan all objects in the grid */ - for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) - { - object_type * o_ptr; - - /* Acquire object */ - o_ptr = &o_list[this_o_idx]; - - /* Acquire next object */ - next_o_idx = o_ptr->next_o_idx; - - /* Skip unknown chests XXX XXX */ - /* if (!o_ptr->marked) continue; */ - - /* Check for chest */ - if (o_ptr->tval == TV_CHEST) return (this_o_idx); - } - - /* No chest */ - return (0); -} - - -/* - * Allocates objects upon opening a chest -BEN- - * - * Disperse treasures from the given chest, centered at (x,y). - * - * Small chests often contain "gold", while Large chests always contain - * items. Wooden chests contain 2 items, Iron chests contain 4 items, - * and Steel chests contain 6 items. The "value" of the items in a - * chest is based on the "power" of the chest, which is in turn based - * on the level on which the chest is generated. - */ -static void chest_death(int y, int x, s16b o_idx) -{ - int number; - - bool_ small; - - object_type forge; - object_type *q_ptr; - - object_type *o_ptr = &o_list[o_idx]; - - - /* Small chests often hold "gold" */ - small = (o_ptr->sval < SV_CHEST_MIN_LARGE); - - /* Determine how much to drop (see above) */ - number = (o_ptr->sval % SV_CHEST_MIN_LARGE) * 2; - - /* Zero pval means empty chest */ - if (!o_ptr->pval) number = 0; - - /* Opening a chest */ - opening_chest = TRUE; - - /* Determine the "value" of the items */ - object_level = ABS(o_ptr->pval) + 10; - - /* Drop some objects (non-chests) */ - for (; number > 0; --number) - { - /* Get local object */ - q_ptr = &forge; - - /* Wipe the object */ - object_wipe(q_ptr); - - /* Small chests often drop gold */ - if (small && (rand_int(100) < 75)) - { - /* Make some gold */ - if (!make_gold(q_ptr)) continue; - } - - /* Otherwise drop an item */ - else - { - /* Make an object */ - if (!make_object(q_ptr, FALSE, FALSE, d_info[dungeon_type].objs)) - continue; - } - - /* Drop it in the dungeon */ - drop_near(q_ptr, -1, y, x); - } - - /* Reset the object level */ - object_level = dun_level; - - /* No longer opening a chest */ - opening_chest = FALSE; - - /* Empty */ - o_ptr->pval = 0; - o_ptr->pval2 = 0; - - /* Known */ - object_known(o_ptr); -} - - -/* - * Chests have traps too. - * - * Exploding chest destroys contents (and traps). - * Note that the chest itself is never destroyed. - */ -static void chest_trap(int y, int x, s16b o_idx) -{ - int trap; - - object_type *o_ptr = &o_list[o_idx]; - - bool_ ident = FALSE; - - - /* Ignore disarmed chests */ - if (o_ptr->pval <= 0) return; - - /* Obtain the trap */ - trap = o_ptr->pval; - - /* Message */ - msg_print("You found a trap!"); - - /* Set off trap */ - ident = player_activate_trap_type(y, x, o_ptr, o_idx); - if (ident) - { - t_info[o_ptr->pval].ident = TRUE; - msg_format("You identified the trap as %s.", - t_name + t_info[trap].name); - } -} - - -/* - * Attempt to open the given chest at the given location - * - * Assume there is no monster blocking the destination - * - * Returns TRUE if repeated commands may continue - */ -static bool_ do_cmd_open_chest(int y, int x, s16b o_idx) -{ - int i, j; - - bool_ flag = TRUE; - - bool_ more = FALSE; - - object_type *o_ptr = &o_list[o_idx]; - - monster_race *r_ptr = &r_info[p_ptr->body_monster]; - - - if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_OPEN_DOOR)) - { - msg_print("You cannot open chests."); - - return (FALSE); - } - - /* Take a turn */ - energy_use = 100; - - /* Attempt to unlock it */ - if (o_ptr->pval > 0) - { - /* Assume locked, and thus not open */ - flag = FALSE; - - /* Get the "disarm" factor */ - i = p_ptr->skill_dis; - - /* Penalize some conditions */ - if (p_ptr->blind || no_lite()) i = i / 10; - if (p_ptr->confused || p_ptr->image) i = i / 10; - - /* Extract the difficulty */ - j = i - o_ptr->pval; - - /* Always have a small chance of success */ - if (j < 2) j = 2; - - /* Success -- May still have traps */ - if (rand_int(100) < j) - { - msg_print("You have picked the lock."); - gain_exp(1); - flag = TRUE; - } - - /* Failure -- Keep trying */ - else - { - /* We may continue repeating */ - more = TRUE; - - if (flush_failure) flush(); - - msg_print("You failed to pick the lock."); - } - } - - /* Allowed to open */ - if (flag) - { - /* Apply chest traps, if any */ - chest_trap(y, x, o_idx); - - /* Let the Chest drop items */ - chest_death(y, x, o_idx); - } - - /* Result */ - return (more); -} - - -/* - * Original code by TNB, improvement for Angband 2.9.3 by rr9 - * Slightly modified for ToME because of its trap implementation - */ - -/* - * Return TRUE if the given grid is an open door - */ -static bool_ is_open(cave_type *c_ptr) -{ - return (c_ptr->feat == FEAT_OPEN); -} - - -/* - * Return TRUE if the given grid is a closed door - */ -static bool_ is_closed(cave_type *c_ptr) -{ - byte feat; - - if (c_ptr->mimic) feat = c_ptr->mimic; - else feat = c_ptr->feat; - - return ((feat >= FEAT_DOOR_HEAD) && (feat <= FEAT_DOOR_TAIL)); -} - - -/* - * Return TRUE if the given grid has a trap - */ -static bool_ is_trap(cave_type *c_ptr) -{ - return ((c_ptr->info & (CAVE_TRDT)) != 0); -} - - -/* - * Return the number of doors/traps around (or under) - * the character using the filter function 'test' - */ -static int count_feats(int *y, int *x, bool_ (*test) (cave_type *c_ptr), - bool_ under) -{ - int d; - - int xx, yy; - - int count; - - - /* Clear match counter */ - count = 0; - - /* Check around (and under) the character */ - for (d = 0; d < 9; d++) - { - /* Ignore current grid if told so -- See tables.c */ - if ((d == 8) && !under) continue; - - /* Extract adjacent (legal) location */ - yy = p_ptr->py + ddy_ddd[d]; - xx = p_ptr->px + ddx_ddd[d]; - - /* Paranoia */ - if (!in_bounds(yy, xx)) continue; - - /* Must have knowledge */ - if (!(cave[yy][xx].info & (CAVE_MARK))) continue; - - /* Not looking for this feature */ - if (!(*test) (&cave[yy][xx])) continue; - - /* Count it */ - count++; - - /* Remember the location. Only meaningful if there's - exactly one match */ - *y = yy; - *x = xx; - } - - /* All done */ - return (count); -} - - -/* - * Return the number of chests around (or under) the character. - * If requested, count only trapped chests. - */ -static int count_chests(int *y, int *x, bool_ trapped) -{ - int d, count, o_idx; - - object_type *o_ptr; - - - /* Count how many matches */ - count = 0; - - /* Check around (and under) the character */ - for (d = 0; d < 9; d++) - { - - /* Extract adjacent (legal) location */ - int yy = p_ptr->py + ddy_ddd[d]; - int xx = p_ptr->px + ddx_ddd[d]; - - /* No (visible) chest is there */ - if ((o_idx = chest_check(yy, xx)) == 0) continue; - - /* Grab the object */ - o_ptr = &o_list[o_idx]; - - /* Already open */ - if (o_ptr->pval == 0) continue; - - /* No (known) traps here */ - if (trapped && (!object_known_p(o_ptr) || !o_ptr->pval)) continue; - - /* OK */ - ++count; - - /* Remember the location. Only useful if only one match */ - *y = yy; - *x = xx; - } - - /* All done */ - return (count); -} - - -/* - * Convert an adjacent location to a direction. - */ -static int coords_to_dir(int y, int x) -{ - int d[3][3] = - { - {7, 4, 1}, - {8, 5, 2}, - {9, 6, 3} }; - - int dy, dx; - - - dy = y - p_ptr->py; - dx = x - p_ptr->px; - - /* Paranoia */ - if (ABS(dx) > 1 || ABS(dy) > 1) return (0); - - return d[dx + 1][dy + 1]; -} - - -/* - * Perform the basic "open" command on doors - * - * Assume destination is a closed/locked/jammed door - * - * Assume there is no monster blocking the destination - * - * Returns TRUE if repeated commands may continue - */ -static bool_ do_cmd_open_aux(int y, int x, int dir) -{ - int i, j; - - cave_type *c_ptr; - - bool_ more = FALSE; - - monster_race *r_ptr = &r_info[p_ptr->body_monster]; - - - if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_OPEN_DOOR)) - { - msg_print("You cannot open doors."); - - return (FALSE); - } - - /* Take a turn */ - energy_use = 100; - - /* Get requested grid */ - c_ptr = &cave[y][x]; - - /* Jammed door */ - if (c_ptr->feat >= FEAT_DOOR_HEAD + 0x08) - { - /* Stuck */ - msg_print("The door appears to be stuck."); - } - - /* Locked door */ - else if (c_ptr->feat >= FEAT_DOOR_HEAD + 0x01) - { - /* Disarm factor */ - i = p_ptr->skill_dis; - - /* Penalize some conditions */ - if (p_ptr->blind || no_lite()) i = i / 10; - if (p_ptr->confused || p_ptr->image) i = i / 10; - - /* Extract the lock power */ - j = c_ptr->feat - FEAT_DOOR_HEAD; - - /* Extract the difficulty XXX XXX XXX */ - j = i - (j * 4); - - /* Always have a small chance of success */ - if (j < 2) j = 2; - - /* Success */ - if (rand_int(100) < j) - { - /* Message */ - msg_print("You have picked the lock."); - - /* Set off trap */ - if (c_ptr->t_idx != 0) player_activate_door_trap(y, x); - - /* Open the door */ - cave_set_feat(y, x, FEAT_OPEN); - - /* Update some things */ - p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_MON_LITE); - - /* Sound */ - sound(SOUND_OPENDOOR); - - /* Experience */ - gain_exp(1); - } - - /* Failure */ - else - { - /* Failure */ - if (flush_failure) flush(); - - /* Message */ - msg_print("You failed to pick the lock."); - - /* We may keep trying */ - more = TRUE; - } - } - - /* Closed door */ - else - { - /* Set off trap */ - if (c_ptr->t_idx != 0) player_activate_door_trap(y, x); - - /* Open the door */ - cave_set_feat(y, x, FEAT_OPEN); - - /* Update some things */ - p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_MON_LITE); - - /* Sound */ - sound(SOUND_OPENDOOR); - } - - /* Result */ - return (more); -} - - - -/* - * Open a closed/locked/jammed door or a closed/locked chest. - * - * Unlocking a locked door/chest is worth one experience point. - */ -void do_cmd_open(void) -{ - int y, x, dir; - - s16b o_idx; - - cave_type *c_ptr; - - bool_ more = FALSE; - - monster_race *r_ptr = &r_info[p_ptr->body_monster]; - - - if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_OPEN_DOOR)) - { - msg_print("You cannot open doors."); - - return; - } - - /* Option: Pick a direction */ - if (easy_open) - { - int num_doors, num_chests; - - /* Count closed doors (locked or jammed) */ - num_doors = count_feats(&y, &x, is_closed, FALSE); - - /* Count chests (locked) */ - num_chests = count_chests(&y, &x, FALSE); - - /* There is nothing the player can open */ - if ((num_doors + num_chests) == 0) - { - /* Message */ - msg_print("You see nothing there to open."); - - /* Done */ - return; - } - - /* Set direction if there is only one target */ - else if ((num_doors + num_chests) == 1) - { - command_dir = coords_to_dir(y, x); - } - } - - /* Allow repeated command */ - if (command_arg) - { - /* Set repeat count */ - command_rep = command_arg - 1; - - /* Redraw the state */ - p_ptr->redraw |= (PR_STATE); - - /* Cancel the arg */ - command_arg = 0; - } - - /* Get a "repeated" direction */ - if (get_rep_dir(&dir)) - { - /* Get requested location */ - y = p_ptr->py + ddy[dir]; - x = p_ptr->px + ddx[dir]; - - /* Get requested grid */ - c_ptr = &cave[y][x]; - - /* Check for chest */ - o_idx = chest_check(y, x); - - /* Nothing useful */ - if (!((c_ptr->feat >= FEAT_DOOR_HEAD) && - (c_ptr->feat <= FEAT_DOOR_TAIL)) && !o_idx) - { - /* Message */ - msg_print("You see nothing there to open."); - } - - /* Monster in the way */ - else if (c_ptr->m_idx) - { - /* Take a turn */ - energy_use = 100; - - /* Message */ - msg_print("There is a monster in the way!"); - - /* Attack */ - py_attack(y, x, -1); - } - - /* Handle chests */ - else if (o_idx) - { - /* Open the chest */ - more = do_cmd_open_chest(y, x, o_idx); - } - - /* Handle doors */ - else - { - /* Open the door */ - more = do_cmd_open_aux(y, x, dir); - } - } - - /* Process the appropriate hooks */ - process_hooks(HOOK_OPEN, "(d)", is_quest(dun_level)); - - /* Cancel repeat unless we may continue */ - if (!more) disturb(0); -} - - - -/* - * Perform the basic "close" command - * - * Assume destination is an open/broken door - * - * Assume there is no monster blocking the destination - * - * Returns TRUE if repeated commands may continue - */ -static bool_ do_cmd_close_aux(int y, int x, int dir) -{ - cave_type *c_ptr; - - bool_ more = FALSE; - - monster_race *r_ptr = &r_info[p_ptr->body_monster]; - - - if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_OPEN_DOOR)) - { - msg_print("You cannot close doors."); - - return (FALSE); - } - - /* Take a turn */ - energy_use = 100; - - /* Get grid and contents */ - c_ptr = &cave[y][x]; - - /* Set off trap */ - if (c_ptr->t_idx != 0) player_activate_door_trap(y, x); - - /* Broken door */ - if (c_ptr->feat == FEAT_BROKEN) - { - /* Message */ - msg_print("The door appears to be broken."); - } - - /* Open door */ - else - { - /* Close the door */ - cave_set_feat(y, x, FEAT_DOOR_HEAD + 0x00); - - /* Update some things */ - p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_MON_LITE); - - /* Sound */ - sound(SOUND_SHUTDOOR); - } - - /* Result */ - return (more); -} - - -/* - * Close an open door. - */ -void do_cmd_close(void) -{ - int y, x, dir; - - cave_type *c_ptr; - - bool_ more = FALSE; - - - /* Option: Pick a direction */ - if (easy_open) - { - int num_doors; - - /* Count open doors */ - num_doors = count_feats(&y, &x, is_open, FALSE); - - /* There are no doors the player can close */ - if (num_doors == 0) - { - /* Message */ - msg_print("You see nothing there to close."); - - /* Done */ - return; - } - - /* Exactly one closeable door */ - else if (num_doors == 1) - { - command_dir = coords_to_dir(y, x); - } - } - - /* Allow repeated command */ - if (command_arg) - { - /* Set repeat count */ - command_rep = command_arg - 1; - - /* Redraw the state */ - p_ptr->redraw |= (PR_STATE); - - /* Cancel the arg */ - command_arg = 0; - } - - /* Get a "repeated" direction */ - if (get_rep_dir(&dir)) - { - /* Get requested location */ - y = p_ptr->py + ddy[dir]; - x = p_ptr->px + ddx[dir]; - - /* Get grid and contents */ - c_ptr = &cave[y][x]; - - /* Require open/broken door */ - if ((c_ptr->feat != FEAT_OPEN) && (c_ptr->feat != FEAT_BROKEN)) - { - /* Message */ - msg_print("You see nothing there to close."); - } - - /* Monster in the way */ - else if (c_ptr->m_idx) - { - /* Take a turn */ - energy_use = 100; - - /* Message */ - msg_print("There is a monster in the way!"); - - /* Attack */ - py_attack(y, x, -1); - } - - /* Close the door */ - else - { - /* Close the door */ - more = do_cmd_close_aux(y, x, dir); - } - } - - /* Cancel repeat unless we may continue */ - if (!more) disturb(0); -} - - -/* - * Determine if a given grid may be "tunneled" - */ -static bool_ do_cmd_tunnel_test(int y, int x) -{ - /* Must have knowledge(execpt on "forget" levels) */ - if (!(cave[y][x].info & (CAVE_MARK))) - { - /* Message */ - msg_print("You see nothing there."); - - /* Nope */ - return (FALSE); - } - - /* Must be a wall/door/etc */ - if (cave_floor_bold(y, x)) - { - /* Message */ - msg_print("You see nothing there to tunnel."); - - /* Nope */ - return (FALSE); - } - - /* Must be tunnelable */ - if (!(f_info[cave[y][x].feat].flags1 & FF1_TUNNELABLE)) - { - /* Message */ - msg_print(f_text + f_info[cave[y][x].feat].tunnel); - - /* Nope */ - return (FALSE); - } - - /* Okay */ - return (TRUE); -} - - - -/* - * Tunnel through wall. Assumes valid location. - * - * Note that it is impossible to "extend" rooms past their - * outer walls (which are actually part of the room). - * - * This will, however, produce grids which are NOT illuminated - * (or darkened) along with the rest of the room. - */ -static bool_ twall(int y, int x, byte feat) -{ - cave_type *c_ptr = &cave[y][x]; - - - /* Paranoia -- Require a wall or door or some such */ - if (cave_floor_bold(y, x)) return (FALSE); - - /* Forget the wall */ - c_ptr->info &= ~(CAVE_MARK); - - /* Remove the feature */ - cave_set_feat(y, x, feat); - - /* Update some things */ - p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MONSTERS | PU_MON_LITE); - - /* Result */ - return (TRUE); -} - - - -/* - * Perform the basic "tunnel" command - * - * Assumes that the destination is a wall, a vein, a secret - * door, or rubble. - * - * Assumes that no monster is blocking the destination - * - * Returns TRUE if repeated commands may continue - */ -bool_ do_cmd_tunnel_aux(int y, int x, int dir) -{ - int skill_req = 0, skill_req_1pct = 0; - cave_type *c_ptr = &cave[y][x]; - - feature_type *f_ptr = &f_info[c_ptr->feat]; - - bool_ more = FALSE; - - - /* Must be have something to dig with (except for sandwalls) */ - if ((c_ptr->feat < FEAT_SANDWALL) || (c_ptr->feat > FEAT_SANDWALL_K)) - { - if (!p_ptr->inventory[INVEN_TOOL].k_idx || - (p_ptr->inventory[INVEN_TOOL].tval != TV_DIGGING)) - { - msg_print("You need to have a shovel or pick in your tool slot."); - - return (FALSE); - } - } - - /* Verify legality */ - if (!do_cmd_tunnel_test(y, x)) return (FALSE); - - /* Take a turn */ - energy_use = 100; - - /* Get grid */ - c_ptr = &cave[y][x]; - - /* Sound */ - sound(SOUND_DIG); - - /* Titanium */ - if (f_ptr->flags1 & FF1_PERMANENT) - { - msg_print(f_text + f_ptr->tunnel); - } - - else if ((c_ptr->feat == FEAT_TREES) || (c_ptr->feat == FEAT_DEAD_TREE)) - { - /* Chop Down */ - skill_req = 10; - skill_req_1pct = 14; - if ((p_ptr->skill_dig > 10 + rand_int(400)) && twall(y, x, FEAT_GRASS)) - { - msg_print("You have cleared away the trees."); - } - - /* Keep trying */ - else - { - /* We may continue chopping */ - msg_print(f_text + f_ptr->tunnel); - more = TRUE; - - /* Occasional Search XXX XXX */ - if (rand_int(100) < 25) search(); - } - } - - - /* Granite */ - else if ((c_ptr->feat >= FEAT_WALL_EXTRA) && - (c_ptr->feat <= FEAT_WALL_SOLID)) - { - /* Tunnel */ - skill_req = 40; - skill_req_1pct = 56; - if ((p_ptr->skill_dig > 40 + rand_int(1600)) && twall(y, x, FEAT_FLOOR)) - { - msg_print("You have finished the tunnel."); - } - - /* Keep trying */ - else - { - /* We may continue tunelling */ - msg_print(f_text + f_ptr->tunnel); - more = TRUE; - } - } - - - /* Quartz / Magma / Sandwall */ - else if (((c_ptr->feat >= FEAT_MAGMA) && - (c_ptr->feat <= FEAT_QUARTZ_K)) || - ((c_ptr->feat >= FEAT_SANDWALL) && - (c_ptr->feat <= FEAT_SANDWALL_K))) - { - bool_ okay = FALSE; - bool_ gold = FALSE; - bool_ hard = FALSE; - bool_ soft = FALSE; - - /* Found gold */ - if ((c_ptr->feat >= FEAT_MAGMA_H) && - (c_ptr->feat <= FEAT_QUARTZ_K)) gold = TRUE; - - if ((c_ptr->feat == FEAT_SANDWALL_H) || - (c_ptr->feat == FEAT_SANDWALL_K)) - { - gold = TRUE; - soft = TRUE; - } - else - /* Extract "quartz" flag XXX XXX XXX */ - if ((c_ptr->feat - FEAT_MAGMA) & 0x01) hard = TRUE; - - /* Quartz */ - if (hard) - { - skill_req = 20; - skill_req_1pct = 28; - okay = (p_ptr->skill_dig > 20 + rand_int(800)); - } - - /* Sandwall */ - else if (soft) - { - skill_req = 5; - skill_req_1pct = 8; - okay = (p_ptr->skill_dig > 5 + rand_int(250)); - } - - /* Magma */ - else - { - skill_req = 10; - skill_req_1pct = 14; - okay = (p_ptr->skill_dig > 10 + rand_int(400)); - } - - /* Success */ - if (okay && twall(y, x, FEAT_FLOOR)) - { - /* Found treasure */ - if (gold) - { - /* Place some gold */ - place_gold(y, x); - - /* Message */ - msg_print("You have found something!"); - } - - /* Found nothing */ - else - { - /* Message */ - msg_print("You have finished the tunnel."); - } - } - - /* Failure */ - else - { - /* Message, continue digging */ - msg_print(f_text + f_ptr->tunnel); - more = TRUE; - } - } - - /* Rubble */ - else if (c_ptr->feat == FEAT_RUBBLE) - { - /* Remove the rubble */ - skill_req = 0; - skill_req_1pct = 2; - if ((p_ptr->skill_dig > rand_int(200)) && - twall(y, x, d_info[dungeon_type].floor1)) - { - /* Message */ - msg_print("You have removed the rubble."); - - /* Hack -- place an object */ - if (rand_int(100) < 10) - { - /* Create a simple object */ - place_object(y, x, FALSE, FALSE, OBJ_FOUND_RUBBLE); - - /* Observe new object */ - if (player_can_see_bold(y, x)) - { - msg_print("You have found something!"); - } - } - } - - else - { - /* Message, keep digging */ - msg_print(f_text + f_ptr->tunnel); - more = TRUE; - } - } - - /* Secret doors */ - else if (c_ptr->feat >= FEAT_SECRET) - { - /* Tunnel */ - skill_req = 30; - skill_req_1pct = 42; - if ((p_ptr->skill_dig > 30 + rand_int(1200)) && twall(y, x, FEAT_FLOOR)) - { - msg_print("You have finished the tunnel."); - c_ptr->mimic = 0; - lite_spot(y, x); - - /* Set off trap */ - if (c_ptr->t_idx != 0) player_activate_door_trap(y, x); - } - - /* Keep trying */ - else - { - int feat; - - if (c_ptr->mimic) feat = c_ptr->mimic; - else - feat = c_ptr->feat; - - /* We may continue tunelling */ - msg_print(f_text + f_info[feat].tunnel); - more = TRUE; - - /* Occasional Search XXX XXX */ - if (rand_int(100) < 25) search(); - } - } - - /* Doors */ - else - { - /* Tunnel */ - skill_req = 30; - skill_req_1pct = 42; - if ((p_ptr->skill_dig > 30 + rand_int(1200)) && twall(y, x, FEAT_FLOOR)) - { - msg_print("You have finished the tunnel."); - } - - /* Keep trying */ - else - { - /* We may continue tunelling */ - msg_print(f_text + f_ptr->tunnel); - more = TRUE; - } - } - - if (more && magik(2)) - { - if (p_ptr->skill_dig < skill_req) - { - msg_print("You fail to make even the slightest of progress."); - more = FALSE; - } - else if (p_ptr->skill_dig < skill_req_1pct) - { - msg_print("This will take some time."); - } - } - - /* Notice new floor grids */ - if (!cave_floor_bold(y, x)) - { - /* Update some things */ - p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MONSTERS | PU_MON_LITE); - } - - /* Result */ - return (more); -} - - -/* - * Tunnels through "walls" (including rubble and closed doors) - * - * Note that you must tunnel in order to hit invisible monsters - * in walls, though moving into walls still takes a turn anyway. - * - * Digging is very difficult without a "digger" weapon, but can be - * accomplished by strong players using heavy weapons. - */ -void do_cmd_tunnel(void) -{ - int y, x, dir; - - cave_type *c_ptr; - - bool_ more = FALSE; - - - if (p_ptr->wild_mode) return; - - /* Allow repeated command */ - if (command_arg) - { - /* Set repeat count */ - command_rep = command_arg - 1; - - /* Redraw the state */ - p_ptr->redraw |= (PR_STATE); - - /* Cancel the arg */ - command_arg = 0; - } - - /* Get a direction to tunnel, or Abort */ - if (get_rep_dir(&dir)) - { - /* Get location */ - y = p_ptr->py + ddy[dir]; - x = p_ptr->px + ddx[dir]; - - /* Get grid */ - c_ptr = &cave[y][x]; - - /* No tunnelling through doors */ - if (((c_ptr->feat >= FEAT_DOOR_HEAD) && - (c_ptr->feat <= FEAT_DOOR_TAIL)) || (c_ptr->feat == FEAT_SHOP)) - { - /* Message */ - msg_print("You cannot tunnel through doors."); - } - - /* No tunnelling through air */ - else if (cave_floor_grid(c_ptr)) - { - /* Message */ - msg_print("You cannot tunnel through air."); - } - - /* A monster is in the way */ - else if (c_ptr->m_idx) - { - /* Take a turn */ - energy_use = 100; - - /* Message */ - msg_print("There is a monster in the way!"); - - /* Attack */ - py_attack(y, x, -1); - } - - /* Try digging */ - else - { - /* Tunnel through walls */ - more = do_cmd_tunnel_aux(y, x, dir); - } - } - - /* Cancel repetition unless we can continue */ - if (!more) disturb(0); -} - - -/* - * easy_open_door -- - * - * If there is a jammed/closed/locked door at the given location, - * then attempt to unlock/open it. Return TRUE if an attempt was - * made (successful or not), otherwise return FALSE. - * - * The code here should be nearly identical to that in - * do_cmd_open_test() and do_cmd_open_aux(). - */ - -bool_ easy_open_door(int y, int x) -{ - int i, j; - - cave_type *c_ptr = &cave[y][x]; - - monster_race *r_ptr = &r_info[p_ptr->body_monster]; - - - if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_OPEN_DOOR)) - { - msg_print("You cannot open doors."); - - return (FALSE); - } - - /* Must be a closed door */ - if (!((c_ptr->feat >= FEAT_DOOR_HEAD) && (c_ptr->feat <= FEAT_DOOR_TAIL))) - { - /* Nope */ - return (FALSE); - } - - /* Jammed door */ - if (c_ptr->feat >= FEAT_DOOR_HEAD + 0x08) - { - /* Stuck */ - msg_print("The door appears to be stuck."); - } - - /* Locked door */ - else if (c_ptr->feat >= FEAT_DOOR_HEAD + 0x01) - { - /* Disarm factor */ - i = p_ptr->skill_dis; - - /* Penalize some conditions */ - if (p_ptr->blind || no_lite()) i = i / 10; - if (p_ptr->confused || p_ptr->image) i = i / 10; - - /* Extract the lock power */ - j = c_ptr->feat - FEAT_DOOR_HEAD; - - /* Extract the difficulty XXX XXX XXX */ - j = i - (j * 4); - - /* Always have a small chance of success */ - if (j < 2) j = 2; - - /* Success */ - if (rand_int(100) < j) - { - /* Message */ - msg_print("You have picked the lock."); - - /* Set off trap */ - if (c_ptr->t_idx != 0) player_activate_door_trap(y, x); - - /* Open the door */ - cave_set_feat(y, x, FEAT_OPEN); - - /* Update some things */ - p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_MON_LITE); - - /* Sound */ - sound(SOUND_OPENDOOR); - - /* Process the appropriate hooks */ - process_hooks(HOOK_OPEN, "(d)", is_quest(dun_level)); - - /* Experience */ - gain_exp(1); - } - - /* Failure */ - else - { - /* Failure */ - if (flush_failure) flush(); - - /* Message */ - msg_print("You failed to pick the lock."); - } - } - - /* Closed door */ - else - { - /* Set off trap */ - if (c_ptr->t_idx != 0) player_activate_door_trap(y, x); - - /* Open the door */ - cave_set_feat(y, x, FEAT_OPEN); - - /* Update some things */ - p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_MON_LITE); - - /* Sound */ - sound(SOUND_OPENDOOR); - } - - /* Result */ - return (TRUE); -} - - -/* - * Perform the basic "disarm" command - * - * Assume destination is a visible trap - * - * Assume there is no monster blocking the destination - * - * Returns TRUE if repeated commands may continue - */ -static bool_ do_cmd_disarm_chest(int y, int x, s16b o_idx) -{ - int i, j; - - bool_ more = FALSE; - - object_type *o_ptr = &o_list[o_idx]; - - trap_type *t_ptr = &t_info[o_ptr->pval]; - - - /* Take a turn */ - energy_use = 100; - - /* Get the "disarm" factor */ - i = p_ptr->skill_dis; - - /* Penalize some conditions */ - if (p_ptr->blind || no_lite()) i = i / 10; - if (p_ptr->confused || p_ptr->image) i = i / 10; - - /* Extract the difficulty */ - j = i - t_ptr->difficulty * 3; - - /* Always have a small chance of success */ - if (j < 2) j = 2; - - /* Must find the trap first. */ - if (!object_known_p(o_ptr)) - { - msg_print("I don't see any traps."); - } - - /* Already disarmed/unlocked */ - else if (o_ptr->pval <= 0) - { - msg_print("The chest is not trapped."); - } - - /* Success (get a lot of experience) */ - else if (rand_int(100) < j) - { - msg_print("You have disarmed the chest."); - gain_exp(t_ptr->difficulty * 3); - o_ptr->pval = (0 - o_ptr->pval); - } - - /* Failure -- Keep trying */ - else if ((i > 5) && (randint(i) > 5)) - { - /* We may keep trying */ - more = TRUE; - if (flush_failure) flush(); - msg_print("You failed to disarm the chest."); - } - - /* Failure -- Set off the trap */ - else - { - msg_print("You set off a trap!"); - sound(SOUND_FAIL); - chest_trap(y, x, o_idx); - } - - /* Result */ - return (more); -} - - -/* - * Perform the basic "disarm" command - * - * Assume destination is a visible trap - * - * Assume there is no monster blocking the destination - * - * Returns TRUE if repeated commands may continue - */ -bool_ do_cmd_disarm_aux(int y, int x, int dir, int do_pickup) -{ - int i, j, power; - - cave_type *c_ptr; - - cptr name; - - bool_ more = FALSE; - - - /* Take a turn */ - energy_use = 100; - - /* Get grid and contents */ - c_ptr = &cave[y][x]; - - /* Access trap name */ - if (t_info[c_ptr->t_idx].ident) - name = (t_name + t_info[c_ptr->t_idx].name); - else - name = "unknown trap"; - - /* Get the "disarm" factor */ - i = p_ptr->skill_dis; - - /* Penalize some conditions */ - if (p_ptr->blind || no_lite()) i = i / 10; - if (p_ptr->confused || p_ptr->image) i = i / 10; - - /* XXX XXX XXX Variable power? */ - - /* Extract trap "power" */ - power = t_info[c_ptr->t_idx].difficulty; - - /* Extract the difficulty */ - j = i - power; - - /* Always have a small chance of success */ - if (j < 2) j = 2; - - /* Success */ - if (rand_int(100) < j) - { - /* Message */ - msg_format("You have disarmed the %s.", name); - - /* Reward */ - gain_exp(power); - - /* Forget the trap */ - c_ptr->info &= ~(CAVE_MARK | CAVE_TRDT); - - /* Remove the trap */ - c_ptr->t_idx = 0; - - /* Move the player onto the trap */ - if (!(f_info[c_ptr->feat].flags1 & FF1_DOOR)) - move_player_aux(dir, do_pickup, 0, TRUE); - - /* Remove trap attr from grid */ - note_spot(y, x); - lite_spot(y, x); - } - - /* Failure -- Keep trying */ - else if ((i > 5) && (randint(i) > 5)) - { - /* Failure */ - if (flush_failure) flush(); - - /* Message */ - msg_format("You failed to disarm the %s.", name); - - /* We may keep trying */ - more = TRUE; - } - - /* Failure -- Set off the trap */ - else - { - /* Message */ - msg_format("You set off the %s!", name); - - /* Move the player onto the trap */ - if (!(f_info[c_ptr->feat].flags1 & FF1_DOOR)) - move_player_aux(dir, do_pickup, 0, FALSE); - } - - /* Result */ - return (more); -} - - -/* - * Disamrs the monster traps(no failure) - */ -void do_cmd_disarm_mon_trap(int y, int x) -{ - msg_print("You disarm the monster trap."); - - place_floor_convert_glass(y, x); - cave[p_ptr->py][p_ptr->px].special = cave[p_ptr->py][p_ptr->px].special2 = 0; -} - - -/* - * Disarms a trap, or chest - */ -void do_cmd_disarm(void) -{ - int y, x, dir; - - s16b o_idx; - - cave_type *c_ptr; - - bool_ more = FALSE; - - - /* Option: Pick a direction */ - if (easy_disarm) - { - int num_traps, num_chests; - - /* Count visible traps */ - num_traps = count_feats(&y, &x, is_trap, TRUE); - - /* Count chests (trapped) */ - num_chests = count_chests(&y, &x, TRUE); - - /* See if only one target */ - if (num_traps || num_chests) - { - if (num_traps + num_chests <= 1) - command_dir = coords_to_dir(y, x); - } - } - - /* Allow repeated command */ - if (command_arg) - { - /* Set repeat count */ - command_rep = command_arg - 1; - - /* Redraw the state */ - p_ptr->redraw |= (PR_STATE); - - /* Cancel the arg */ - command_arg = 0; - } - - /* Get a direction (or abort) */ - if (get_rep_dir(&dir)) - { - /* Get location */ - y = p_ptr->py + ddy[dir]; - x = p_ptr->px + ddx[dir]; - - /* Get grid and contents */ - c_ptr = &cave[y][x]; - - /* Check for chests */ - o_idx = chest_check(y, x); - - /* Disarm a trap */ - if (((c_ptr->t_idx == 0) || (!(c_ptr->info & CAVE_TRDT))) && - !o_idx && (c_ptr->feat != FEAT_MON_TRAP)) - { - /* Message */ - msg_print("You see nothing there to disarm."); - } - - /* Monster in the way */ - else if (c_ptr->m_idx) - { - /* Message */ - msg_print("There is a monster in the way!"); - - /* Attack */ - py_attack(y, x, -1); - } - - /* Disarm chest */ - else if (o_idx) - { - /* Disarm the chest */ - more = do_cmd_disarm_chest(y, x, o_idx); - } - - /* Disarm trap */ - else - { - /* Disarm the trap */ - if (c_ptr->feat == FEAT_MON_TRAP) - { - do_cmd_disarm_mon_trap(y, x); - more = FALSE; - } - else - more = do_cmd_disarm_aux(y, x, dir, always_pickup); - } - } - - /* Cancel repeat unless told not to */ - if (!more) disturb(0); -} - - -/* - * Perform the basic "bash" command - * - * Assume destination is a closed/locked/jammed door - * - * Assume there is no monster blocking the destination - * - * Returns TRUE if repeated commands may continue - */ -static bool_ do_cmd_bash_aux(int y, int x, int dir) -{ - int bash, temp; - - cave_type *c_ptr; - - bool_ more = FALSE; - - monster_race *r_ptr = &r_info[p_ptr->body_monster]; - - - if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_BASH_DOOR)) - { - msg_print("You cannot do that."); - - return (FALSE); - } - - /* Take a turn */ - energy_use = 100; - - /* Get grid */ - c_ptr = &cave[y][x]; - - /* Message */ - msg_print("You smash into the door!"); - - /* Hack -- Bash power based on strength */ - /* (Ranges from 3 to 20 to 100 to 200) */ - bash = adj_str_blow[p_ptr->stat_ind[A_STR]]; - - /* Extract door power */ - temp = ((c_ptr->feat - FEAT_DOOR_HEAD) & 0x07); - - /* Compare bash power to door power XXX XXX XXX */ - temp = (bash - (temp * 10)); - - /* Hack -- always have a chance */ - if (temp < 1) temp = 1; - - /* Hack -- attempt to bash down the door */ - if (rand_int(100) < temp) - { - /* Message */ - msg_print("The door crashes open!"); - - /* Break down the door */ - if (rand_int(100) < 50) - { - /* Set off trap */ - if (c_ptr->t_idx != 0) player_activate_door_trap(y, x); - - cave_set_feat(y, x, FEAT_BROKEN); - } - - /* Open the door */ - else - { - /* Set off trap */ - if (c_ptr->t_idx != 0) player_activate_door_trap(y, x); - - cave_set_feat(y, x, FEAT_OPEN); - } - - /* Sound */ - sound(SOUND_OPENDOOR); - - /* Hack -- Fall through the door. Can't disarm while falling. */ - move_player_aux(dir, always_pickup, 0, FALSE); - - /* Update some things */ - p_ptr->update |= (PU_VIEW | PU_MON_LITE); - p_ptr->update |= (PU_DISTANCE); - } - - /* Saving throw against stun */ - else if (rand_int(100) < adj_dex_safe[p_ptr->stat_ind[A_DEX]] + p_ptr->lev) - { - /* Message */ - msg_print("The door holds firm."); - - /* Allow repeated bashing */ - more = TRUE; - } - - /* High dexterity yields coolness */ - else - { - /* Message */ - msg_print("You are off-balance."); - - /* Hack -- Lose balance ala paralysis */ - (void)set_paralyzed(2 + rand_int(2)); - } - - /* Result */ - return (more); -} - - -/* - * Bash open a door, success based on character strength - * - * For a closed door, pval is positive if locked; negative if stuck. - * - * For an open door, pval is positive for a broken door. - * - * A closed door can be opened - harder if locked. Any door might be - * bashed open (and thereby broken). Bashing a door is (potentially) - * faster! You move into the door way. To open a stuck door, it must - * be bashed. A closed door can be jammed (see do_cmd_spike()). - * - * Creatures can also open or bash doors, see elsewhere. - */ -void do_cmd_bash(void) -{ - int y, x, dir; - - cave_type *c_ptr; - - bool_ more = FALSE; - - monster_race *r_ptr = &r_info[p_ptr->body_monster]; - - - if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_BASH_DOOR)) - { - msg_print("You cannot do that."); - - return; - } - - /* Allow repeated command */ - if (command_arg) - { - /* Set repeat count */ - command_rep = command_arg - 1; - - /* Redraw the state */ - p_ptr->redraw |= (PR_STATE); - - /* Cancel the arg */ - command_arg = 0; - } - - /* Get a "repeated" direction */ - if (get_rep_dir(&dir)) - { - /* Bash location */ - y = p_ptr->py + ddy[dir]; - x = p_ptr->px + ddx[dir]; - - /* Get grid */ - c_ptr = &cave[y][x]; - - /* Nothing useful */ - if ((c_ptr->feat < FEAT_DOOR_HEAD || - c_ptr->feat > FEAT_DOOR_TAIL) && - (c_ptr->feat < FEAT_ALTAR_HEAD || - c_ptr->feat > FEAT_ALTAR_TAIL) && (c_ptr->feat != FEAT_FOUNTAIN)) - { - /* Message */ - msg_print("You see nothing there to bash."); - } - - /* Monster in the way */ - else if (c_ptr->m_idx) - { - /* Take a turn */ - energy_use = 100; - - /* Message */ - msg_print("There is a monster in the way!"); - - /* Attack */ - py_attack(y, x, -1); - } - - else if (c_ptr->feat >= FEAT_ALTAR_HEAD && - c_ptr->feat <= FEAT_ALTAR_TAIL) - { - more = do_cmd_bash_altar(y, x); - } - /* Bash a closed door */ - else if (c_ptr->feat == FEAT_FOUNTAIN) - { - more = do_cmd_bash_fountain(y, x); - } - else - { - /* Bash the door */ - more = do_cmd_bash_aux(y, x, dir); - } - } - - /* Unless valid action taken, cancel bash */ - if (!more) disturb(0); -} - - - -/* - * Manipulate an adjacent grid in some way - * - * Attack monsters, tunnel through walls, disarm traps, open doors. - * - * Consider confusion XXX XXX XXX - * - * This command must always take a turn, to prevent free detection - * of invisible monsters. - */ -void do_cmd_alter(void) -{ - int y, x, dir; - - cave_type *c_ptr; - - bool_ more = FALSE; - - - /* Allow repeated command */ - if (command_arg) - { - /* Set repeat count */ - command_rep = command_arg - 1; - - /* Redraw the state */ - p_ptr->redraw |= (PR_STATE); - - /* Cancel the arg */ - command_arg = 0; - } - - /* Get a direction */ - if (get_rep_dir(&dir)) - { - /* Get location */ - y = p_ptr->py + ddy[dir]; - x = p_ptr->px + ddx[dir]; - - /* Get grid */ - c_ptr = &cave[y][x]; - - /* Take a turn */ - energy_use = 100; - - /* Attack monsters */ - if (c_ptr->m_idx) - { - /* Attack */ - py_attack(y, x, -1); - } - - /* Open closed doors */ - else if ((c_ptr->feat >= FEAT_DOOR_HEAD) && - (c_ptr->feat <= FEAT_DOOR_TAIL)) - { - /* Tunnel */ - more = do_cmd_open_aux(y, x, dir); - } - - /* Tunnel through walls */ - else if (f_info[c_ptr->feat].flags1 & FF1_TUNNELABLE) - { - /* Tunnel */ - more = do_cmd_tunnel_aux(y, x, dir); - } - - /* Disarm traps */ - else if (c_ptr->t_idx != 0) - { - /* Tunnel */ - more = do_cmd_disarm_aux(y, x, dir, always_pickup); - } - - /* Oops */ - else - { - /* Oops */ - msg_print("You attack the empty air."); - } - } - - /* Cancel repetition unless we can continue */ - if (!more) disturb(0); -} - - -/* - * Find the index of some "spikes", if possible. - * - * XXX XXX XXX Let user choose a pile of spikes, perhaps? - */ -static bool_ get_spike(int *ip) -{ - int i; - - - /* Check every item in the pack */ - for (i = 0; i < INVEN_PACK; i++) - { - object_type *o_ptr = &p_ptr->inventory[i]; - - /* Skip non-objects */ - if (!o_ptr->k_idx) continue; - - /* Check the "tval" code */ - if (o_ptr->tval == TV_SPIKE) - { - /* Save the spike index */ - (*ip) = i; - - /* Success */ - return (TRUE); - } - } - - /* Oops */ - return (FALSE); -} - - - -/* - * Jam a closed door with a spike - * - * This command may NOT be repeated - */ -void do_cmd_spike(void) -{ - int y, x, dir, item; - - cave_type *c_ptr; - - - /* Get a "repeated" direction */ - if (get_rep_dir(&dir)) - { - /* Get location */ - y = p_ptr->py + ddy[dir]; - x = p_ptr->px + ddx[dir]; - - /* Get grid and contents */ - c_ptr = &cave[y][x]; - - /* Require closed door */ - if (!((c_ptr->feat >= FEAT_DOOR_HEAD) && - (c_ptr->feat <= FEAT_DOOR_TAIL))) - { - /* Message */ - msg_print("You see nothing there to spike."); - } - - /* Get a spike */ - else if (!get_spike(&item)) - { - /* Message */ - msg_print("You have no spikes!"); - } - - /* Is a monster in the way? */ - else if (c_ptr->m_idx) - { - /* Take a turn */ - energy_use = 100; - - /* Message */ - msg_print("There is a monster in the way!"); - - /* Attack */ - py_attack(y, x, -1); - } - - /* Go for it */ - else - { - /* Take a turn */ - energy_use = 100; - - /* Successful jamming */ - msg_print("You jam the door with a spike."); - - /* Convert "locked" to "stuck" XXX XXX XXX */ - if (c_ptr->feat < FEAT_DOOR_HEAD + 0x08) c_ptr->feat += 0x08; - - /* Add one spike to the door */ - if (c_ptr->feat < FEAT_DOOR_TAIL) c_ptr->feat++; - - /* Use up, and describe, a single spike, from the bottom */ - inc_stack_size(item, -1); - } - } -} - - -static void do_cmd_walk_jump(int pickup, bool_ disarm) -{ - int dir; - - bool_ more = FALSE; - - - /* Allow repeated command */ - if (command_arg) - { - /* Set repeat count */ - command_rep = command_arg - 1; - - /* Redraw the state */ - p_ptr->redraw |= (PR_STATE); - - /* Cancel the arg */ - command_arg = 0; - } - - /* Get a "repeated" direction */ - if (get_rep_dir(&dir)) - { - /* Take a turn */ - energy_use = 100; - - /* Actually move the character */ - move_player(dir, pickup, disarm); - - /* Allow more walking */ - more = TRUE; - } - - /* Hack -- In small scale wilderness it takes MUCH more time to move */ - energy_use *= (p_ptr->wild_mode) ? ((MAX_HGT + MAX_WID) / 2) : 1; - - /* Hack again -- Is there a special encounter ??? */ - if (p_ptr->wild_mode && - magik(wf_info[wild_map[p_ptr->py][p_ptr->px].feat].level - (p_ptr->lev * 2))) - { - /* Go into large wilderness view */ - p_ptr->wilderness_x = p_ptr->px; - p_ptr->wilderness_y = p_ptr->py; - energy_use = 100; - change_wild_mode(); - - /* HACk -- set the encouter flag for the wilderness generation */ - generate_encounter = TRUE; - p_ptr->oldpx = MAX_WID / 2; - p_ptr->oldpy = MAX_HGT / 2; - - /* Inform the player of his horrible fate :=) */ - msg_print("You are ambushed!"); - } - - /* Cancel repeat unless we may continue */ - if (!more) disturb(0); -} - - -/* - * Support code for the "Walk" and "Jump" commands - */ -void do_cmd_walk(int pickup, bool_ disarm) -{ - /* Move (usually pickup) */ - - if (p_ptr->immovable) - { - do_cmd_unwalk(); - } - else - { - do_cmd_walk_jump(pickup, disarm); - } -} - - -void do_cmd_run_run() -{ - int dir; - - - /* Hack -- no running when confused */ - if (p_ptr->confused) - { - msg_print("You are too confused!"); - return; - } - - /* Get a "repeated" direction */ - if (get_rep_dir(&dir)) - { - /* Hack -- Set the run counter */ - running = (command_arg ? command_arg : 1000); - - /* First step */ - run_step(dir); - } - p_ptr->window |= (PW_OVERHEAD); -} - - -/* - * Start running. - */ -void do_cmd_run(void) -{ - if (p_ptr->immovable) - { - return; - } - else - { - do_cmd_run_run(); - } -} - - - -/* - * Stay still. Search. Enter stores. - * Pick up treasure if "pickup" is true. - */ -void do_cmd_stay(int pickup) -{ - cave_type *c_ptr = &cave[p_ptr->py][p_ptr->px]; - - - /* Allow repeated command */ - if (command_arg) - { - /* Set repeat count */ - command_rep = command_arg - 1; - - /* Redraw the state */ - p_ptr->redraw |= (PR_STATE); - - /* Cancel the arg */ - command_arg = 0; - } - - - /* Take a turn */ - energy_use = 100; - - - /* Spontaneous Searching */ - if ((p_ptr->skill_fos >= 50) || (0 == rand_int(50 - p_ptr->skill_fos))) - { - search(); - } - - /* Continuous Searching */ - if (p_ptr->searching) - { - search(); - } - - - /* Handle "objects" */ - carry(pickup); - - - /* Hack -- enter a store if we are on one */ - if (c_ptr->feat == FEAT_SHOP) - { - /* Disturb */ - disturb(0); - - /* Hack -- enter store */ - command_new = '_'; - } -} - -/* - * Resting allows a player to safely restore his hp -RAK- - */ -void do_cmd_rest(void) -{ - /* Can't rest on a Void Jumpgate -- too dangerous */ - if (cave[p_ptr->py][p_ptr->px].feat == FEAT_BETWEEN) - { - /* 'R&\n' is one of our favourite macros, so we have to do this */ - if (flush_failure) flush(); - - /* Tell the player why */ - msg_print(format("Resting on a %s is too dangerous!", - f_name + f_info[cave[p_ptr->py][p_ptr->px].feat].name)); - - /* Done */ - return; - } - - /* Can't rest while undead, it would mean dying */ - if (p_ptr->necro_extra & CLASS_UNDEAD) - { - /* 'R&\n' is one of our favourite macros, so we have to do this */ - if (flush_failure) flush(); - - /* Tell the player why */ - msg_print("Resting is impossible while undead!"); - - /* Done */ - return; - } - - /* Prompt for time if needed */ - if (command_arg <= 0) - { - cptr p = "Rest (0-9999, '*' for HP/SP, '&' as needed): "; - - char out_val[80]; - - /* Default */ - strcpy(out_val, "&"); - - /* Ask for duration */ - if (!get_string(p, out_val, 4)) return; - - /* Rest until done */ - if (out_val[0] == '&') - { - command_arg = ( -2); - } - - /* Rest a lot */ - else if (out_val[0] == '*') - { - command_arg = ( -1); - } - - /* Rest some */ - else - { - command_arg = atoi(out_val); - if (command_arg <= 0) return; - } - } - - - /* Paranoia */ - if (command_arg > 9999) command_arg = 9999; - - - /* Take a turn XXX XXX XXX (?) */ - energy_use = 100; - - /* Save the rest code */ - resting = command_arg; - - /* Cancel searching */ - p_ptr->searching = FALSE; - - /* Recalculate bonuses */ - p_ptr->update |= (PU_BONUS); - - /* Redraw the state */ - p_ptr->redraw |= (PR_STATE); - - /* Handle stuff */ - handle_stuff(); - - /* Refresh */ - Term_fresh(); -} - - - - - - -/* - * Determines the odds of an object breaking when thrown at a monster - * - * Note that artifacts never break, see the "drop_near()" function. - */ -int breakage_chance(object_type *o_ptr) -{ - int reducer = - 1 + ((get_skill(SKILL_ARCHERY)) ? (get_skill_scale(SKILL_ARCHERY, 10)) : 0); - - /* Examine the item type */ - switch (o_ptr->tval) - { - /* Always break */ - case TV_FLASK: - case TV_POTION: - case TV_POTION2: - case TV_BOTTLE: - case TV_FOOD: - { - return (100); - } - - /* Often break */ - case TV_LITE: - case TV_SCROLL: - case TV_SKELETON: - { - return (50); - } - - case TV_ARROW: - { - return (50 / reducer); - } - - /* Sometimes break */ - case TV_WAND: - case TV_SPIKE: - { - return (25); - } - - case TV_SHOT: - case TV_BOLT: - { - return (25 / reducer); - } - case TV_BOOMERANG: - { - return 1; - } - } - - /* Rarely break */ - return (10); -} - -/* - * Return multiplier of an object - */ -int get_shooter_mult(object_type *o_ptr) -{ - /* Assume a base multiplier */ - int tmul = 1; - - /* Analyze the launcher */ - switch (o_ptr->sval) - { - case SV_SLING: - { - /* Sling and ammo */ - tmul = 2; - break; - } - - case SV_SHORT_BOW: - { - /* Short Bow and Arrow */ - tmul = 2; - break; - } - - case SV_LONG_BOW: - { - /* Long Bow and Arrow */ - tmul = 3; - break; - } - - /* Light Crossbow and Bolt */ - case SV_LIGHT_XBOW: - { - tmul = 3; - break; - } - - /* Heavy Crossbow and Bolt */ - case SV_HEAVY_XBOW: - { - tmul = 4; - break; - } - } - return tmul; -} - - -/* - * Fire an object from the pack or floor. - * - * You may only fire items that "match" your missile launcher. - * - * You must use slings + pebbles/shots, bows + arrows, xbows + bolts. - * - * See "calc_bonuses()" for more calculations and such. - * - * Note that "firing" a missile is MUCH better than "throwing" it. - * - * Note: "unseen" monsters are very hard to hit. - * - * Objects are more likely to break if they "attempt" to hit a monster. - * - * Rangers (with Bows) and Anyone (with "Extra Shots") get extra shots. - * - * The "extra shot" code works by decreasing the amount of energy - * required to make each shot, spreading the shots out over time. - * - * Note that when firing missiles, the launcher multiplier is applied - * after all the bonuses are added in, making multipliers very useful. - * - * Note that Bows of "Extra Might" get extra range and an extra bonus - * for the damage multiplier. - * - * Note that Bows of "Extra Shots" give an extra shot. - */ -void do_cmd_fire(void) -{ - int dir, item; - - int j, y, x, ny, nx, ty, tx, by, bx; - - int oldtdam, tdam, tdis, thits, tmul; - - int bonus, chance; - - int cur_dis, visible; - - int breakage = -1, num_pierce = 0; - - s32b special = 0; - - object_type forge; - - object_type *q_ptr; - - object_type *o_ptr; - - object_type *j_ptr; - - bool_ hit_body = FALSE; - - byte missile_attr; - - char missile_char; - - char o_name[80]; - - cptr q, s; - - int msec = delay_factor * delay_factor * delay_factor; - - - /* Get the "bow" (if any) */ - j_ptr = &p_ptr->inventory[INVEN_BOW]; - - /* Require a launcher */ - if (!j_ptr->tval) - { - msg_print("You have nothing with which to fire."); - return; - } - - /* XXX HACK */ - if (j_ptr->tval == TV_INSTRUMENT) - { - msg_print("You cannot fire with an instrument."); - return; - } - - /* Get the "ammo" (if any) */ - o_ptr = &p_ptr->inventory[INVEN_AMMO]; - - item = INVEN_AMMO; - - /* If nothing correct try to choose from the backpack */ - if ((p_ptr->tval_ammo != o_ptr->tval) || (!o_ptr->k_idx)) - { - /* Require proper missile */ - item_tester_tval = p_ptr->tval_ammo; - - /* Get an item */ - q = "Your quiver is empty. Fire which item? "; - s = "You have nothing to fire."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - - /* Access the item */ - o_ptr = get_object(item); - } - - - /* Get a direction (or cancel) */ - if (!get_aim_dir(&dir)) return; - - - /* Get local object */ - q_ptr = &forge; - - /* Obtain a local object */ - object_copy(q_ptr, o_ptr); - - /* Single object */ - q_ptr->number = 1; - - /* Reduce stack and describe */ - inc_stack_size(item, -1); - - /* Break goi/manashield */ - if (p_ptr->invuln) - { - set_invuln(0); - } - if (p_ptr->disrupt_shield) - { - set_disrupt_shield(0); - } - - - /* Sound */ - sound(SOUND_SHOOT); - - - /* Describe the object */ - object_desc(o_name, q_ptr, FALSE, 3); - - /* Find the color and symbol for the object for throwing */ - missile_attr = object_attr(q_ptr); - missile_char = object_char(q_ptr); - - - /* Use the proper number of shots */ - thits = p_ptr->num_fire; - - /* Use a base distance */ - tdis = 10; - - /* Base damage from thrown object plus launcher bonus */ - tdam = damroll(q_ptr->dd, q_ptr->ds) + q_ptr->to_d + j_ptr->to_d; - - /* Actually "fire" the object */ - bonus = (p_ptr->to_h + p_ptr->to_h_ranged + q_ptr->to_h + j_ptr->to_h); - - chance = (p_ptr->skill_thb + (bonus * BTH_PLUS_ADJ)); - if (chance < 5) chance = 5; - - tmul = get_shooter_mult(j_ptr); - - /* Get extra "power" from "extra might" */ - tmul += p_ptr->xtra_might; - - /* Boost the damage */ - tdam *= tmul; - - /* Add in the player damage */ - tdam += p_ptr->to_d_ranged; - - /* Base range */ - tdis = 10 + 5 * tmul; - - - /* Take a (partial) turn */ - energy_use = (100 / thits); - - /* piercing shots ? */ - if (p_ptr->use_piercing_shots) - { - num_pierce = (get_skill(SKILL_COMBAT) / 10) - 1; - num_pierce = (num_pierce < 0) ? 0 : num_pierce; - } - - /* Start at the player */ - by = p_ptr->py; - bx = p_ptr->px; - y = p_ptr->py; - x = p_ptr->px; - - /* Predict the "target" location */ - tx = p_ptr->px + 99 * ddx[dir]; - ty = p_ptr->py + 99 * ddy[dir]; - - /* Check for "target request" */ - if ((dir == 5) && target_okay()) - { - tx = target_col; - ty = target_row; - } - - - /* Hack -- Handle stuff */ - handle_stuff(); - - oldtdam = tdam; - while (TRUE) - { - /* Reset after a piercing shot */ - tdam = oldtdam; - - /* Travel until stopped */ - for (cur_dis = 0; cur_dis <= tdis; ) - { - /* Hack -- Stop at the target */ - if ((y == ty) && (x == tx)) break; - - /* Calculate the new location (see "project()") */ - ny = y; - nx = x; - mmove2(&ny, &nx, by, bx, ty, tx); - - /* Stopped by walls/doors */ - if (!cave_floor_bold(ny, nx)) break; - - /* Advance the distance */ - cur_dis++; - - /* Save the new location */ - x = nx; - y = ny; - - - /* The player can see the (on screen) missile */ - if (panel_contains(y, x) && player_can_see_bold(y, x)) - { - /* Draw, Hilite, Fresh, Pause, Erase */ - print_rel(missile_char, missile_attr, y, x); - move_cursor_relative(y, x); - Term_fresh(); - Term_xtra(TERM_XTRA_DELAY, msec); - lite_spot(y, x); - Term_fresh(); - } - - /* The player cannot see the missile */ - else - { - /* Pause anyway, for consistancy */ - Term_xtra(TERM_XTRA_DELAY, msec); - } - - - /* Monster here, Try to hit it */ - if (cave[y][x].m_idx) - { - cave_type *c_ptr = &cave[y][x]; - - monster_type *m_ptr = &m_list[c_ptr->m_idx]; - monster_race *r_ptr = race_inf(m_ptr); - - /* Check the visibility */ - visible = m_ptr->ml; - - /* Note the collision */ - hit_body = TRUE; - - /* Did we hit it (penalize range) */ - if (test_hit_fire(chance - cur_dis, m_ptr->ac, m_ptr->ml)) - { - bool_ fear = FALSE; - - /* Assume a default death */ - cptr note_dies = " dies."; - - /* Some monsters get "destroyed" */ - if ((r_ptr->flags3 & (RF3_DEMON)) || - (r_ptr->flags3 & (RF3_UNDEAD)) || - (r_ptr->flags2 & (RF2_STUPID)) || - (strchr("Evg", r_ptr->d_char))) - { - /* Special note at death */ - note_dies = " is destroyed."; - } - - - /* Handle unseen monster */ - if (!visible) - { - /* Invisible monster */ - msg_format("The %s finds a mark.", o_name); - } - - /* Handle visible monster */ - else - { - char m_name[80]; - - /* Get "the monster" or "it" */ - monster_desc(m_name, m_ptr, 0); - - /* Message */ - msg_format("The %s hits %s.", o_name, m_name); - - /* Hack -- Track this monster race */ - if (m_ptr->ml) monster_race_track(m_ptr->r_idx, - m_ptr->ego); - - /* Hack -- Track this monster */ - if (m_ptr->ml) health_track(c_ptr->m_idx); - - /* Anger friends */ - { - char m_name[80]; - monster_desc(m_name, m_ptr, 0); - switch (is_friend(m_ptr)) - { - case 1: - { - msg_format("%^s gets angry!", m_name); - change_side(m_ptr); - break; - } - case 0: - { - msg_format("%^s gets angry!", m_name); - m_ptr->status = MSTATUS_NEUTRAL_M; - break; - } - } - } - } - - /* Apply special damage XXX XXX XXX */ - tdam = tot_dam_aux(q_ptr, tdam, m_ptr, &special); - tdam = critical_shot(q_ptr->weight, q_ptr->to_h, tdam, SKILL_ARCHERY); - - /* No negative damage */ - if (tdam < 0) tdam = 0; - - /* Complex message */ - if (wizard) - { - msg_format("You do %d (out of %d) damage.", - tdam, m_ptr->hp); - } - - /* Hit the monster, check for death */ - if (mon_take_hit(c_ptr->m_idx, tdam, &fear, note_dies)) - { - /* Dead monster */ - } - - /* No death */ - else - { - /* Message */ - message_pain(c_ptr->m_idx, tdam); - - if (special) attack_special(m_ptr, special, tdam); - - /* Take note */ - if (fear && m_ptr->ml) - { - char m_name[80]; - - /* Sound */ - sound(SOUND_FLEE); - - /* Get the monster name (or "it") */ - monster_desc(m_name, m_ptr, 0); - - /* Message */ - msg_format("%^s flees in terror!", m_name); - } - } - } - - /* Stop looking */ - break; - } - } - - /* Exploding arrow ? */ - if (q_ptr->pval2 != 0) - { - int rad = 0, dam = - (damroll(q_ptr->dd, q_ptr->ds) + q_ptr->to_d) * 2; - int flag = - PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | - PROJECT_JUMP; - switch (q_ptr->sval) - { - case SV_AMMO_LIGHT: - rad = 2; - dam /= 2; - break; - case SV_AMMO_NORMAL: - rad = 3; - break; - case SV_AMMO_HEAVY: - rad = 4; - dam *= 2; - break; - } - - project(0, rad, y, x, dam, q_ptr->pval2, flag); - } - - /* Chance of breakage (during attacks) */ - j = (hit_body ? breakage_chance(q_ptr) : 0); - - /* Break ? */ - if ((q_ptr->pval2 != 0) || (rand_int(100) < j)) - { - breakage = 100; - break; - } - - /* If the ammo doesn't break, it can pierce through */ - if ((num_pierce) && (hit_body) && - (magik(45 + get_skill(SKILL_ARCHERY)))) - { - num_pierce--; - hit_body = FALSE; - - /* If target isn't reached, continue moving to target */ - if ( !((tx < x && x < bx) || (bx < x && x < tx)) && - !((ty < y && y < by) || (by < y && y < ty))) - { - /* Continue moving in same direction if we reached the target */ - int dx = tx - bx; - int dy = ty - by; - tx = x + 99 * dx; - ty = y + 99 * dy; - - /* New base location */ - by = y; - bx = x; - } - - msg_format("The %s pierces through!", o_name); - } - else - break; - } - - /* Drop (or break) near that location */ - drop_near(q_ptr, breakage, y, x); -} - - -/* - * Why is this here? even if it's temporary boost... - * Moved into player_type, hoping it might be useful in future extensions - * -- pelpel - */ -/* int throw_mult = 1; */ - -/* - * Throw an object from the pack or floor. - * - * Note: "unseen" monsters are very hard to hit. - * - * Should throwing a weapon do full damage? Should it allow the magic - * to hit bonus of the weapon to have an effect? Should it ever cause - * the item to be destroyed? Should it do any damage at all? - */ -void do_cmd_throw(void) -{ - int dir, item; - - s32b special = 0; - - int j, y, x, ny, nx, ty, tx; - - int chance, tdam, tdis; - - int mul, div; - - int boulder_add = 0; - int boulder_mult = 0; - - int cur_dis, visible; - - object_type forge; - - object_type *q_ptr; - - object_type *o_ptr; - - bool_ hit_body = FALSE; - - bool_ hit_wall = FALSE; - - byte missile_attr; - - char missile_char; - - char o_name[80]; - - int msec = delay_factor * delay_factor * delay_factor; - - cptr q, s; - - u32b f1, f2, f3, f4, f5, esp; - - - /* Get an item */ - q = "Throw which item? "; - s = "You have nothing to throw."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - /* Access the item */ - o_ptr = get_object(item); - - - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* Hack - Cannot throw away 'no drop' cursed items */ - if (cursed_p(o_ptr) && (f4 & TR4_CURSE_NO_DROP)) - { - /* Oops */ - msg_print("Hmmm, you seem to be unable to throw it."); - - /* Nope */ - return; - } - - /* Boulder throwing */ - if ((o_ptr->tval == TV_JUNK) && (o_ptr->sval == SV_BOULDER) && (get_skill(SKILL_BOULDER))) - { - boulder_add = get_skill_scale(SKILL_BOULDER, 80); - boulder_mult = get_skill_scale(SKILL_BOULDER, 6); - } - - /* Get a direction (or cancel) */ - if (!get_aim_dir(&dir)) return; - - /* Break goi/manashield */ - if (p_ptr->invuln) - { - set_invuln(0); - } - if (p_ptr->disrupt_shield) - { - set_disrupt_shield(0); - } - - /* Get local object */ - q_ptr = &forge; - - /* Obtain a local object */ - object_copy(q_ptr, o_ptr); - - /* - * Hack -- If rods or wands are thrown, the total maximum timeout or - * charges need to be allocated between the two stacks. - */ - if (o_ptr->tval == TV_WAND) - { - q_ptr->pval = o_ptr->pval / o_ptr->number; - - if (o_ptr->number > 1) o_ptr->pval -= q_ptr->pval; - } - - /* Single object */ - q_ptr->number = 1; - - /* Reduce stack and describe */ - inc_stack_size(item, -1); - - /* Description */ - object_desc(o_name, q_ptr, FALSE, 3); - - /* Find the color and symbol for the object for throwing */ - missile_attr = object_attr(q_ptr); - missile_char = object_char(q_ptr); - - /* Extract a "distance multiplier" */ - /* Changed for 'launcher' corruption */ - mul = 10 + (2 * (p_ptr->throw_mult - 1)) + (2 * boulder_mult); - - /* Enforce a minimum "weight" of one pound */ - div = ((q_ptr->weight > 10) ? q_ptr->weight : 10); - - /* Hack -- Distance -- Reward strength, penalize weight */ - tdis = (adj_str_blow[p_ptr->stat_ind[A_STR]] + 20) * mul / div; - - /* Max distance of 10-18 */ - if (tdis > mul) tdis = mul; - - /* Hack -- Base damage from thrown object */ - tdam = damroll(q_ptr->dd, q_ptr->ds) + q_ptr->to_d + boulder_add; - tdam *= p_ptr->throw_mult + boulder_mult; - - /* Chance of hitting - adjusted for Weaponmasters -- Gumby */ - chance = (p_ptr->skill_tht + (p_ptr->to_h * BTH_PLUS_ADJ)); - - /* Take a turn */ - energy_use = 100; - - - /* Start at the player */ - y = p_ptr->py; - x = p_ptr->px; - - /* Predict the "target" location */ - tx = p_ptr->px + 99 * ddx[dir]; - ty = p_ptr->py + 99 * ddy[dir]; - - /* Check for "target request" */ - if ((dir == 5) && target_okay()) - { - tx = target_col; - ty = target_row; - } - - - /* Hack -- Handle stuff */ - handle_stuff(); - - - /* Travel until stopped */ - for (cur_dis = 0; cur_dis <= tdis; ) - { - /* Hack -- Stop at the target */ - if ((y == ty) && (x == tx)) break; - - /* Calculate the new location (see "project()") */ - ny = y; - nx = x; - mmove2(&ny, &nx, p_ptr->py, p_ptr->px, ty, tx); - - /* Stopped by walls/doors */ - if (!cave_floor_bold(ny, nx)) - { - hit_wall = TRUE; - break; - } - - /* Advance the distance */ - cur_dis++; - - /* Save the new location */ - x = nx; - y = ny; - - - /* The player can see the (on screen) missile */ - if (panel_contains(y, x) && player_can_see_bold(y, x)) - { - /* Draw, Hilite, Fresh, Pause, Erase */ - print_rel(missile_char, missile_attr, y, x); - move_cursor_relative(y, x); - Term_fresh(); - Term_xtra(TERM_XTRA_DELAY, msec); - lite_spot(y, x); - Term_fresh(); - } - - /* The player cannot see the missile */ - else - { - /* Pause anyway, for consistancy */ - Term_xtra(TERM_XTRA_DELAY, msec); - } - - - /* Monster here, Try to hit it */ - if (cave[y][x].m_idx) - { - cave_type *c_ptr = &cave[y][x]; - - monster_type *m_ptr = &m_list[c_ptr->m_idx]; - monster_race *r_ptr = race_inf(m_ptr); - - /* Check the visibility */ - visible = m_ptr->ml; - - /* Note the collision */ - hit_body = TRUE; - - /* Did we hit it (penalize range) */ - if (test_hit_fire(chance - cur_dis, m_ptr->ac, m_ptr->ml)) - { - bool_ fear = FALSE; - - /* Assume a default death */ - cptr note_dies = " dies."; - - /* Some monsters get "destroyed" */ - if ((r_ptr->flags3 & (RF3_DEMON)) || - (r_ptr->flags3 & (RF3_UNDEAD)) || - (r_ptr->flags2 & (RF2_STUPID)) || - (strchr("Evg", r_ptr->d_char))) - { - /* Special note at death */ - note_dies = " is destroyed."; - } - - - /* Handle unseen monster */ - if (!visible) - { - /* Invisible monster */ - msg_format("The %s finds a mark.", o_name); - } - - /* Handle visible monster */ - else - { - char m_name[80]; - - /* Get "the monster" or "it" */ - monster_desc(m_name, m_ptr, 0); - - /* Message */ - msg_format("The %s hits %s.", o_name, m_name); - - /* Hack -- Track this monster race */ - if (m_ptr->ml) monster_race_track(m_ptr->r_idx, m_ptr->ego); - - /* Hack -- Track this monster */ - if (m_ptr->ml) health_track(c_ptr->m_idx); - } - - /* Apply special damage XXX XXX XXX */ - tdam = tot_dam_aux(q_ptr, tdam, m_ptr, &special); - tdam = critical_shot(q_ptr->weight, q_ptr->to_h, tdam, o_ptr->sval == SV_BOULDER ? SKILL_BOULDER : SKILL_ARCHERY); - - /* No negative damage */ - if (tdam < 0) tdam = 0; - - /* Complex message */ - if (wizard) - { - msg_format("You do %d (out of %d) damage.", - tdam, m_ptr->hp); - } - - /* Hit the monster, check for death */ - if (mon_take_hit(c_ptr->m_idx, tdam, &fear, note_dies)) - { - /* Dead monster */ - } - - /* No death */ - else - { - /* Message */ - message_pain(c_ptr->m_idx, tdam); - - if (special) attack_special(m_ptr, special, tdam); - - /* Anger friends */ - if (!(k_info[q_ptr->k_idx].tval == TV_POTION)) - { - char m_name[80]; - monster_desc(m_name, m_ptr, 0); - switch (is_friend(m_ptr)) - { - case 1: - msg_format("%^s gets angry!", m_name); - change_side(m_ptr); - break; - case 0: - msg_format("%^s gets angry!", m_name); - m_ptr->status = MSTATUS_NEUTRAL_M; - break; - } - } - - /* Take note */ - if (fear && m_ptr->ml) - { - char m_name[80]; - - /* Sound */ - sound(SOUND_FLEE); - - /* Get the monster name (or "it") */ - monster_desc(m_name, m_ptr, 0); - - /* Message */ - msg_format("%^s flees in terror!", m_name); - } - } - } - - /* Stop looking */ - break; - } - } - - /* Chance of breakage (during attacks) */ - j = (hit_body ? breakage_chance(q_ptr) : 0); - - /* Potions smash open */ - if (k_info[q_ptr->k_idx].tval == TV_POTION) - { - if ((hit_body) || (hit_wall) || (randint(100) < j)) - { - /* Message */ - msg_format("The %s shatters!", o_name); - - if (potion_smash_effect(0, y, x, q_ptr->sval)) - { - if (cave[y][x].m_idx) - { - char m_name[80]; - monster_desc(m_name, &m_list[cave[y][x].m_idx], 0); - switch (is_friend(&m_list[cave[y][x].m_idx])) - { - case 1: - msg_format("%^s gets angry!", m_name); - change_side(&m_list[cave[y][x].m_idx]); - break; - case 0: - msg_format("%^s gets angry!", m_name); - m_list[cave[y][x].m_idx].status = MSTATUS_NEUTRAL_M; - break; - } - } - } - - return; - } - else - { - j = 0; - } - } - - /* Drop (or break) near that location */ - drop_near(q_ptr, j, y, x); -} - - -/* - * Throw a boomerang object from the equipement(bow). - * - * Note: "unseen" monsters are very hard to hit. - * - * Should throwing a weapon do full damage? Should it allow the magic - * to hit bonus of the weapon to have an effect? Should it ever cause - * the item to be destroyed? Should it do any damage at all? - */ -void do_cmd_boomerang(void) -{ - int dir; - - int j, y, x, ny, nx, ty, tx; - - int chance, tdam, tdis; - - int mul, div; - - int cur_dis, visible; - - object_type forge; - - object_type *q_ptr; - - object_type *o_ptr; - - bool_ hit_body = FALSE; - - byte missile_attr; - - char missile_char; - - char o_name[80]; - - s32b special = 0; - - int msec = delay_factor * delay_factor * delay_factor; - - - /* Get the "bow" (if any) */ - o_ptr = &p_ptr->inventory[INVEN_BOW]; - - - /* Get a direction (or cancel) */ - if (!get_aim_dir(&dir)) return; - - - /* Get local object */ - q_ptr = &forge; - - /* Obtain a local object */ - object_copy(q_ptr, o_ptr); - - /* Single object */ - q_ptr->number = 1; - - /* Description */ - object_desc(o_name, q_ptr, FALSE, 3); - - /* Find the color and symbol for the object for throwing */ - missile_attr = object_attr(q_ptr); - missile_char = object_char(q_ptr); - - /* Extract a "distance multiplier" */ - /* Changed for 'launcher' corruption */ - mul = 10 + 2 * (p_ptr->throw_mult - 1); - - /* Enforce a minimum "weight" of one pound */ - div = ((q_ptr->weight > 10) ? q_ptr->weight : 10); - - /* Hack -- Distance -- Reward strength, penalize weight */ - tdis = (adj_str_blow[p_ptr->stat_ind[A_STR]] + 20) * mul / div; - - /* Max distance of 10-18 */ - if (tdis > mul) tdis = mul; - - /* Hack -- Base damage from thrown object */ - tdam = damroll(q_ptr->dd, q_ptr->ds) + q_ptr->to_d; - tdam *= p_ptr->throw_mult; - - /* Chance of hitting */ - chance = - (p_ptr->skill_tht + - ((p_ptr->to_h + p_ptr->to_h_ranged) * BTH_PLUS_ADJ)); - - chance += get_skill(SKILL_BOOMERANG); - - /* Take a turn */ - energy_use = 100; - - - /* Start at the player */ - y = p_ptr->py; - x = p_ptr->px; - - /* Predict the "target" location */ - tx = p_ptr->px + 99 * ddx[dir]; - ty = p_ptr->py + 99 * ddy[dir]; - - /* Check for "target request" */ - if ((dir == 5) && target_okay()) - { - tx = target_col; - ty = target_row; - } - - - /* Hack -- Handle stuff */ - handle_stuff(); - - - /* Travel until stopped */ - for (cur_dis = 0; cur_dis <= tdis; ) - { - /* Hack -- Stop at the target */ - if ((y == ty) && (x == tx)) break; - - /* Calculate the new location (see "project()") */ - ny = y; - nx = x; - mmove2(&ny, &nx, p_ptr->py, p_ptr->px, ty, tx); - - /* Stopped by walls/doors */ - if (!cave_floor_bold(ny, nx)) - { - break; - } - - /* Advance the distance */ - cur_dis++; - - /* Save the new location */ - x = nx; - y = ny; - - - /* The player can see the (on screen) missile */ - if (panel_contains(y, x) && player_can_see_bold(y, x)) - { - /* Draw, Hilite, Fresh, Pause, Erase */ - print_rel(missile_char, missile_attr, y, x); - move_cursor_relative(y, x); - Term_fresh(); - Term_xtra(TERM_XTRA_DELAY, msec); - lite_spot(y, x); - Term_fresh(); - } - - /* The player cannot see the missile */ - else - { - /* Pause anyway, for consistancy */ - Term_xtra(TERM_XTRA_DELAY, msec); - } - - - /* Monster here, Try to hit it */ - if (cave[y][x].m_idx) - { - cave_type *c_ptr = &cave[y][x]; - - monster_type *m_ptr = &m_list[c_ptr->m_idx]; - monster_race *r_ptr = race_inf(m_ptr); - - /* Check the visibility */ - visible = m_ptr->ml; - - /* Note the collision */ - hit_body = TRUE; - - /* Did we hit it (penalize range) */ - if (test_hit_fire(chance - cur_dis, m_ptr->ac, m_ptr->ml)) - { - bool_ fear = FALSE; - - /* Assume a default death */ - cptr note_dies = " dies."; - - /* Some monsters get "destroyed" */ - if ((r_ptr->flags3 & (RF3_DEMON)) || - (r_ptr->flags3 & (RF3_UNDEAD)) || - (r_ptr->flags2 & (RF2_STUPID)) || - (strchr("Evg", r_ptr->d_char))) - { - /* Special note at death */ - note_dies = " is destroyed."; - } - - - /* Handle unseen monster */ - if (!visible) - { - /* Invisible monster */ - msg_format("The %s finds a mark.", o_name); - } - - /* Handle visible monster */ - else - { - char m_name[80]; - - /* Get "the monster" or "it" */ - monster_desc(m_name, m_ptr, 0); - - /* Message */ - msg_format("The %s hits %s.", o_name, m_name); - - /* Hack -- Track this monster race */ - if (m_ptr->ml) monster_race_track(m_ptr->r_idx, m_ptr->ego); - - /* Hack -- Track this monster */ - if (m_ptr->ml) health_track(c_ptr->m_idx); - } - - /* Apply special damage XXX XXX XXX */ - tdam = tot_dam_aux(q_ptr, tdam, m_ptr, &special); - tdam = critical_shot(q_ptr->weight, q_ptr->to_h, tdam, SKILL_ARCHERY); - - /* No negative damage */ - if (tdam < 0) tdam = 0; - - /* Complex message */ - if (wizard) - { - msg_format("You do %d (out of %d) damage.", - tdam, m_ptr->hp); - } - - /* Hit the monster, check for death */ - if (mon_take_hit(c_ptr->m_idx, tdam, &fear, note_dies)) - { - /* Dead monster */ - } - - /* No death */ - else - { - /* Message */ - message_pain(c_ptr->m_idx, tdam); - - if (special) attack_special(m_ptr, special, tdam); - - /* Anger friends */ - if (!(k_info[q_ptr->k_idx].tval == TV_POTION)) - { - char m_name[80]; - monster_desc(m_name, m_ptr, 0); - switch (is_friend(m_ptr)) - { - case 1: - msg_format("%^s gets angry!", m_name); - change_side(m_ptr); - break; - case 0: - msg_format("%^s gets angry!", m_name); - m_ptr->status = MSTATUS_NEUTRAL_M; - break; - } - } - - /* Take note */ - if (fear && m_ptr->ml) - { - char m_name[80]; - - /* Sound */ - sound(SOUND_FLEE); - - /* Get the monster name (or "it") */ - monster_desc(m_name, m_ptr, 0); - - /* Message */ - msg_format("%^s flees in terror!", m_name); - } - } - - /* Chance of breakage (during attacks) */ - j = (hit_body ? breakage_chance(o_ptr) : 0); - - /* Break the boomerang */ - if (!(o_ptr->art_name || artifact_p(o_ptr)) && - (rand_int(100) < j)) - { - msg_print(format("Your %s is destroyed.", o_name)); - inc_stack_size_ex(INVEN_BOW, -1, OPTIMIZE, NO_DESCRIBE); - } - } - - /* Stop looking */ - break; - } - } - - /* Travel back to the player */ - for (cur_dis = 0; cur_dis <= tdis; ) - { - /* Hack -- Stop at the target */ - if ((y == p_ptr->py) && (x == p_ptr->px)) break; - - /* Calculate the new location (see "project()") */ - ny = y; - nx = x; - mmove2(&ny, &nx, ty, tx, p_ptr->py, p_ptr->px); - - /* Advance the distance */ - cur_dis++; - - /* Save the new location */ - x = nx; - y = ny; - - - /* The player can see the (on screen) missile */ - if (panel_contains(y, x) && player_can_see_bold(y, x)) - { - /* Draw, Hilite, Fresh, Pause, Erase */ - print_rel(missile_char, missile_attr, y, x); - move_cursor_relative(y, x); - Term_fresh(); - Term_xtra(TERM_XTRA_DELAY, msec); - lite_spot(y, x); - Term_fresh(); - } - - /* The player cannot see the missile */ - else - { - /* Pause anyway, for consistancy */ - Term_xtra(TERM_XTRA_DELAY, msec); - } - } -} - - -/* - * Try to ``walk'' using phase door. - */ -void do_cmd_unwalk() -{ - int dir, y, x, feat; - - cave_type *c_ptr; - - bool_ more = FALSE; - - - if (!get_rep_dir(&dir)) return; - - y = p_ptr->py + ddy[dir]; - x = p_ptr->px + ddx[dir]; - - c_ptr = &cave[y][x]; - feat = c_ptr->feat; - - /* Must have knowledge to know feature XXX XXX */ - if (!(c_ptr->info & (CAVE_MARK))) feat = FEAT_NONE; - - /* Take a turn */ - energy_use = 100; - energy_use *= (p_ptr->wild_mode) ? (5 * (MAX_HGT + MAX_WID) / 2) : 1; - - - /* Allow repeated command */ - if (command_arg) - { - /* Set repeat count */ - command_rep = command_arg - 1; - - /* Redraw the state */ - p_ptr->redraw |= (PR_STATE); - - /* Cancel the arg */ - command_arg = 0; - } - - - /* Attack monsters */ - if (c_ptr->m_idx > 0) - { - /* Attack */ - py_attack(y, x, -1); - } - - /* Exit the area */ - else if ((!dun_level) && (!p_ptr->wild_mode) && - ((x == 0) || (x == cur_wid - 1) || (y == 0) || (y == cur_hgt - 1))) - { - /* Can the player enter the grid? */ - if (player_can_enter(c_ptr->mimic)) - { - /* Hack: move to new area */ - if ((y == 0) && (x == 0)) - { - p_ptr->wilderness_y--; - p_ptr->wilderness_x--; - p_ptr->oldpy = cur_hgt - 2; - p_ptr->oldpx = cur_wid - 2; - ambush_flag = FALSE; - } - - else if ((y == 0) && (x == MAX_WID - 1)) - { - p_ptr->wilderness_y--; - p_ptr->wilderness_x++; - p_ptr->oldpy = cur_hgt - 2; - p_ptr->oldpx = 1; - ambush_flag = FALSE; - } - - else if ((y == MAX_HGT - 1) && (x == 0)) - { - p_ptr->wilderness_y++; - p_ptr->wilderness_x--; - p_ptr->oldpy = 1; - p_ptr->oldpx = cur_wid - 2; - ambush_flag = FALSE; - } - - else if ((y == MAX_HGT - 1) && (x == MAX_WID - 1)) - { - p_ptr->wilderness_y++; - p_ptr->wilderness_x++; - p_ptr->oldpy = 1; - p_ptr->oldpx = 1; - ambush_flag = FALSE; - } - - else if (y == 0) - { - p_ptr->wilderness_y--; - p_ptr->oldpy = cur_hgt - 2; - p_ptr->oldpx = x; - ambush_flag = FALSE; - } - - else if (y == cur_hgt - 1) - { - p_ptr->wilderness_y++; - p_ptr->oldpy = 1; - p_ptr->oldpx = x; - ambush_flag = FALSE; - } - - else if (x == 0) - { - p_ptr->wilderness_x--; - p_ptr->oldpx = cur_wid - 2; - p_ptr->oldpy = y; - ambush_flag = FALSE; - } - - else if (x == cur_wid - 1) - { - p_ptr->wilderness_x++; - p_ptr->oldpx = 1; - p_ptr->oldpy = y; - ambush_flag = FALSE; - } - - p_ptr->leaving = TRUE; - - return; - } - } - - /* Hack -- Ignore weird terrain types. */ - else if (!cave_floor_grid(c_ptr)) - { - teleport_player(10); - } - - /* Enter quests */ - else if (((feat >= FEAT_QUEST_ENTER) && (feat <= FEAT_QUEST_UP)) || - ((feat >= FEAT_LESS) && (feat <= FEAT_MORE))) - { - move_player(dir, always_pickup, TRUE); - more = FALSE; - } - - /* Hack -- Ignore wilderness mofe. */ - else if (p_ptr->wild_mode) - { - /* Chance to not blink right */ - if (magik(15)) - { - do - { - dir = rand_range(1, 9); - } - while (dir == 5); - } - - move_player(dir, always_pickup, TRUE); - } - - /* Walking semantics */ - else - { - teleport_player_directed(10, dir); - } - - /* Cancel repetition unless we can continue */ - if (!more) disturb(0); -} - - -static bool_ tport_vertically(bool_ how) -{ - /* arena or quest -KMW- */ - if ((p_ptr->inside_arena) || (p_ptr->inside_quest)) - { - msg_print("There is no effect."); - return (FALSE); - } - - if (dungeon_flags2 & DF2_NO_EASY_MOVE) - { - msg_print("Some powerful force prevents you from teleporting."); - return FALSE; - } - - /* Go down */ - if (how) - { - if (dun_level >= d_info[dungeon_type].maxdepth) - { - msg_print("The floor is impermeable."); - return (FALSE); - } - - msg_print("You sink through the floor."); - dun_level++; - p_ptr->leaving = TRUE; - } - else - { - if (dun_level < d_info[dungeon_type].mindepth) - { - msg_print("There is nothing above you but air."); - return (FALSE); - } - - msg_print("You rise through the ceiling."); - dun_level--; - p_ptr->leaving = TRUE; - } - - return (TRUE); -} - - -/* - * Do a special ``movement'' action. Meant to be used for ``immovable'' - * characters. - */ -void do_cmd_immovable_special(void) -{ - int i, ii, ij, dir; - - int foo = p_ptr->immov_cntr; - - int lose_sp = 0; - - int lose_hp = 0; - - bool_ did_act = FALSE; - - bool_ did_load = FALSE; - - - if (foo > 1) - { - if (p_ptr->csp > foo / 2) - { - - msg_format("This will drain %d mana points!", foo / 2); - if (!get_check("Proceed? ")) return; - - lose_sp = foo / 2; - - } - else if (p_ptr->chp > foo / 2) - { - - msg_format("Warning: This will drain %d hit points!", foo / 2); - if (!get_check("Proceed? ")) return; - - lose_hp = foo / 2; - - } - else - { - msg_print("You can't use your powers yet."); - return; - } - } - - /* Enter "icky" mode */ - character_icky = TRUE; - - /* Save the screen */ - Term_save(); - - - /* Interact until done */ - while (1) - { - /* Clear screen */ - Term_clear(); - - /* Ask for a choice */ - prt("Do what special action:", 2, 0); - - /* Give some choices */ - prt("(a) Teleport to a specific place.", 4, 5); - prt("(b) Fetch an item.", 5, 5); - prt("(c) Go up 50'", 6, 5); - prt("(d) Go down 50'", 7, 5); - - /* Prompt */ - prt("Command: ", 9, 0); - - /* Prompt */ - i = inkey(); - - /* Done */ - if (i == ESCAPE) break; - - /* Tele-to */ - if (i == 'a') - { - Term_load(); - character_icky = FALSE; - did_load = TRUE; - - if (!tgt_pt(&ii, &ij)) break; - - /* Teleport to the target */ - teleport_player_to(ij, ii); - - did_act = TRUE; - break; - } - - /* Fetch item */ - else if (i == 'b') - { - Term_load(); - character_icky = FALSE; - did_load = TRUE; - - if (!get_aim_dir(&dir)) return; - fetch(dir, p_ptr->lev * 15, FALSE); - py_pickup_floor(always_pickup); - - did_act = TRUE; - break; - } - - /* Move up */ - else if (i == 'c') - { - Term_load(); - character_icky = FALSE; - did_load = TRUE; - - if (!tport_vertically(FALSE)) return; - - did_act = TRUE; - break; - } - - /* Move down */ - else if (i == 'd') - { - Term_load(); - character_icky = FALSE; - did_load = TRUE; - - if (!tport_vertically(TRUE)) return; - - did_act = TRUE; - break; - } - - /* Unknown option */ - else - { - bell(); - } - - } - - /* Check if screen was restored before */ - if (!did_load) - { - /* Restore the screen */ - Term_load(); - - /* Leave "icky" mode */ - character_icky = FALSE; - } - - /* Apply stat losses if something was done */ - if (did_act) - { - p_ptr->immov_cntr += 101 - (p_ptr->lev * 2); - - if (lose_sp) - { - p_ptr->csp -= lose_sp; - p_ptr->redraw |= (PR_MANA); - } - - if (lose_hp) - { - p_ptr->chp -= lose_hp; - p_ptr->redraw |= (PR_HP); - } - - energy_use = 100; - } -} - -/* Can we sacrifice it ? */ -static bool_ item_tester_hook_sacrifiable(object_type *o_ptr) -{ - GOD(GOD_MELKOR) - { - /* Corpses are */ - if (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_CORPSE_CORPSE) - return (TRUE); - - /* Books without any udun spells */ - if ((o_ptr->tval == TV_BOOK) && udun_in_book(o_ptr->sval, o_ptr->pval) <= 0) - { - return TRUE; - } - } - - /* Assume not */ - return (FALSE); -} - -/* - * Is item eligible for sacrifice to Aule? - */ -static bool_ item_tester_hook_sacrifice_aule(object_type *o_ptr) -{ - /* perhaps restrict this only to metal armour and weapons */ - return (o_ptr->found == OBJ_FOUND_SELFMADE); -} - -/* - * Handle sacrifices to Aule - */ -static void do_cmd_sacrifice_aule() -{ - int item; - - item_tester_hook = item_tester_hook_sacrifice_aule; - if (!get_item(&item, - "Sacrifice which item? ", - "You have nothing to sacrifice.", - USE_INVEN)) - { - return; - } - - /* Increase piety by the value of the item / 10. */ - { - object_type *o_ptr = get_object(item); - s32b delta = object_value(o_ptr) / 10; - - inc_piety(GOD_ALL, delta); - } - - /* Destroy the object */ - inc_stack_size(item, -1); -} - -/* - * Handle sacrifices. - * Grace is increased by value of sacrifice. - */ -void do_cmd_sacrifice(void) -{ - byte on_what = cave[p_ptr->py][p_ptr->px].feat; - - /* Check valididty */ - if ((on_what < FEAT_ALTAR_HEAD) || (on_what > FEAT_ALTAR_TAIL)) - { - show_god_info(FALSE); - return; - } - else - { - int agod = on_what - FEAT_ALTAR_HEAD + 1; - - /* Not worshipping a god ? ahhhh! */ - GOD(GOD_NONE) - { - int i; - - for (i = 0; i < 10; i++) - { - if (deity_info[agod].desc[i] != NULL) - msg_print(deity_info[agod].desc[i]); - } - if (get_check(format("Do you want to worship %s? ", deity_info[agod].name))) - { - follow_god(agod, FALSE); - p_ptr->grace = -200; - inc_piety(p_ptr->pgod, 0); - } - } - else if (p_ptr->pgod == agod) - { - GOD(GOD_MELKOR) - { - /* One can sacrifice some HP for piety or damage */ - if ((p_ptr->mhp > 10) && (p_ptr->chp > 10) && get_check("Do you want to sacrifice a part of yourself? ")) - { - /* 10 HP = 300 * wis piety */ - if (get_check("Do you want to sacrifice for more piety instead of damage? ")) - { - int x = wisdom_scale(6); - if (x < 1) x = 1; - - p_ptr->hp_mod -= 10; - take_hit(10, "self sacrifice to Melkor"); - msg_print("Your life slips away, and Melkor seems happier."); - inc_piety(GOD_MELKOR, x * 300); - p_ptr->update |= (PU_HP); - } - /* 10 HP = +wis damage */ - else - { - take_hit(10, "self sacrifice to Melkor"); - msg_print("Your life slips away, and your arms grow stronger."); - p_ptr->melkor_sacrifice++; - p_ptr->update |= (PU_BONUS | PU_HP); - } - } - else - { - int item; - object_type *o_ptr; - - /* Restrict choices to food */ - item_tester_hook = item_tester_hook_sacrifiable; - - /* Get an item */ - if (!get_item(&item, "Sacrifice which item? ", "You have nothing to sacrifice.", (USE_INVEN))) return; - o_ptr = get_object(item); - - /* Piety for corpses is based on monster level */ - if (o_ptr->tval == TV_CORPSE) - { - inc_piety(GOD_MELKOR, 2 * r_info[o_ptr->pval2].level); - } - - /* In books it depends of the spell levels*/ - if (o_ptr->tval == TV_BOOK) - { - int x = levels_in_book(o_ptr->sval, o_ptr->pval); - - inc_piety(GOD_MELKOR, 2 * x); - } - - /* Remove the item */ - inc_stack_size(item, -1); - } - } - - GOD(GOD_AULE) - { - do_cmd_sacrifice_aule(); - } - - } - } -} - - -/* - * scan_monst -- - * - * Return a list of o_list[] indexes of items of the given monster - */ -bool_ scan_monst(int *items, int *item_num, int m_idx) -{ - int this_o_idx, next_o_idx; - - int num = 0; - - - (*item_num) = 0; - - /* Scan all objects in the grid */ - for (this_o_idx = m_list[m_idx].hold_o_idx; this_o_idx; - this_o_idx = next_o_idx) - { - object_type * o_ptr; - - /* Acquire object */ - o_ptr = &o_list[this_o_idx]; - - /* Acquire next object */ - next_o_idx = o_ptr->next_o_idx; - - /* Accept this item */ - items[num++] = this_o_idx; - - /* XXX Hack -- Enforce limit */ - if (num == 23) break; - } - - /* Number of items */ - (*item_num) = num; - - /* Result */ - return (num != 0); -} - - -/* - * Display a list of the items that the given monster carries. - */ -byte show_monster_inven(int m_idx, int *monst_list) -{ - int i, j, k, l; - - int col, len, lim; - - object_type *o_ptr; - - char o_name[80]; - - char tmp_val[80]; - - int out_index[23]; - - byte out_color[23]; - - char out_desc[23][80]; - - int monst_num; - - - /* Default length */ - len = 79 - 50; - - /* Maximum space allowed for descriptions */ - lim = 79 - 3; - - /* Require space for weight */ - lim -= 9; - - /* Scan for objects on the monster */ - (void)scan_monst(monst_list, &monst_num, m_idx); - - /* Display the p_ptr->inventory */ - for (k = 0, i = 0; i < monst_num; i++) - { - o_ptr = &o_list[monst_list[i]]; - - /* Describe the object */ - object_desc(o_name, o_ptr, TRUE, 3); - - /* Hack -- enforce max length */ - o_name[lim] = '\0'; - - /* Save the index */ - out_index[k] = i; - - /* Acquire p_ptr->inventory color */ - out_color[k] = tval_to_attr[o_ptr->tval & 0x7F]; - - /* Save the object description */ - strcpy(out_desc[k], o_name); - - /* Find the predicted "line length" */ - l = strlen(out_desc[k]) + 5; - - /* Account for the weight */ - l += 9; - - /* Maintain the maximum length */ - if (l > len) len = l; - - /* Advance to next "line" */ - k++; - } - - /* Find the column to start in */ - col = (len > 76) ? 0 : (79 - len); - - /* Output each entry */ - for (j = 0; j < k; j++) - { - /* Get the index */ - i = monst_list[out_index[j]]; - - /* Get the item */ - o_ptr = &o_list[i]; - - /* Clear the line */ - prt("", j + 1, col ? col - 2 : col); - - /* Prepare an index --(-- */ - strnfmt(tmp_val, 80, "%c)", index_to_label(j)); - - /* Clear the line with the (possibly indented) index */ - put_str(tmp_val, j + 1, col); - - /* Display the entry itself */ - c_put_str(out_color[j], out_desc[j], j + 1, col + 3); - - /* Display the weight if needed */ - { - int wgt = o_ptr->weight * o_ptr->number; - strnfmt(tmp_val, 80, "%3d.%1d lb", wgt / 10, wgt % 10); - put_str(tmp_val, j + 1, 71); - } - } - - /* Make a "shadow" below the list (only if needed) */ - if (j && (j < 23)) prt("", j + 1, col ? col - 2 : col); - - return monst_num; -} - - -/* - * Steal an object from a monster - */ -void do_cmd_steal() -{ - int x, y, dir = 0, item = -1, k = -1; - - cave_type *c_ptr; - - monster_type *m_ptr; - - object_type *o_ptr, forge; - - byte num = 0; - - bool_ done = FALSE; - - int monst_list[23]; - - - /* Only works on adjacent monsters */ - if (!get_rep_dir(&dir)) return; - y = p_ptr->py + ddy[dir]; - x = p_ptr->px + ddx[dir]; - c_ptr = &cave[y][x]; - - if (!(c_ptr->m_idx)) - { - msg_print("There is no monster there!"); - return; - } - - m_ptr = &m_list[c_ptr->m_idx]; - - /* There were no non-gold items */ - if (!m_ptr->hold_o_idx) - { - msg_print("That monster has no objects!"); - return; - } - - /* The monster is immune */ - if (r_info[m_ptr->r_idx].flags7 & (RF7_NO_THEFT)) - { - msg_print("The monster is guarding the treasures."); - return; - } - - screen_save(); - - num = show_monster_inven(c_ptr->m_idx, monst_list); - - /* Repeat until done */ - while (!done) - { - char tmp_val[80]; - char which = ' '; - - /* Build the prompt */ - strnfmt(tmp_val, 80, "Choose an item to steal (a-%c) or ESC:", - 'a' - 1 + num); - - /* Show the prompt */ - prt(tmp_val, 0, 0); - - /* Get a key */ - which = inkey(); - - /* Parse it */ - switch (which) - { - case ESCAPE: - { - done = TRUE; - - break; - } - - default: - { - int ver; - - /* Extract "query" setting */ - ver = isupper(which); - which = tolower(which); - - k = islower(which) ? A2I(which) : -1; - if (k < 0 || k >= num) - { - bell(); - - break; - } - - /* Verify the item */ - if (ver && !verify("Try", 0 - monst_list[k])) - { - done = TRUE; - - break; - } - - /* Accept that choice */ - item = monst_list[k]; - done = TRUE; - - break; - } - } - } - - if (item != -1) - { - int chance; - - chance = 40 - p_ptr->stat_ind[A_DEX]; - chance += - o_list[item].weight / (get_skill_scale(SKILL_STEALING, 19) + 1); - chance += get_skill_scale(SKILL_STEALING, 29) + 1; - chance -= (m_ptr->csleep) ? 10 : 0; - chance += m_ptr->level; - - /* Failure check */ - if (rand_int(chance) > 1 + get_skill_scale(SKILL_STEALING, 25)) - { - /* Take a turn */ - energy_use = 100; - - /* Wake up */ - m_ptr->csleep = 0; - - /* Speed up because monsters are ANGRY when you try to thief them */ - m_ptr->mspeed += 5; - - screen_load(); - - msg_print("Oops! The monster is now really *ANGRY*!"); - - return; - } - - /* Reconnect the objects list */ - if (num == 1) m_ptr->hold_o_idx = 0; - else - { - if (k > 0) o_list[monst_list[k - 1]].next_o_idx = monst_list[k + 1]; - if (k + 1 >= num) o_list[monst_list[k - 1]].next_o_idx = 0; - if (k == 0) m_ptr->hold_o_idx = monst_list[k + 1]; - } - - /* Rogues gain some xp */ - if (PRACE_FLAGS(PR1_EASE_STEAL)) - { - s32b max_point; - - /* Max XP gained from stealing */ - max_point = (o_list[item].weight / 2) + (m_ptr->level * 10); - - /* Randomise it a bit, with half a max guaranteed */ - gain_exp((max_point / 2) + (randint(max_point) / 2)); - - /* Allow escape */ - if (get_check("Phase door?")) teleport_player(10); - } - - /* Get the item */ - o_ptr = &forge; - - /* Special handling for gold */ - if (o_list[item].tval == TV_GOLD) - { - /* Collect the gold */ - p_ptr->au += o_list[item].pval; - - /* Redraw gold */ - p_ptr->redraw |= (PR_GOLD); - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - } - else - { - object_copy(o_ptr, &o_list[item]); - - inven_carry(o_ptr, FALSE); - } - - /* Delete it */ - o_list[item].k_idx = 0; - } - - screen_load(); - - /* Take a turn */ - energy_use = 100; -} - - -/* - * Give an item to a monster - */ -void do_cmd_give() -{ - int dir, x, y; - - cave_type *c_ptr; - - cptr q, s; - - int item; - - - /* Get a "repeated" direction */ - if (!get_rep_dir(&dir)) return; - - /* Get requested location */ - y = p_ptr->py + ddy[dir]; - x = p_ptr->px + ddx[dir]; - - /* Get requested grid */ - c_ptr = &cave[y][x]; - - /* No monster in the way */ - if (c_ptr->m_idx == 0) - { - msg_print("There is no monster there."); - return; - } - - /* Get an item */ - q = "What item do you want to offer? "; - s = "You have nothing to offer."; - if (!get_item(&item, q, s, USE_INVEN)) return; - - /* Process hooks if there are any */ - if (!process_hooks(HOOK_GIVE, "(d,d)", c_ptr->m_idx, item)) - { - hook_give_in in = { c_ptr->m_idx, item }; - if (!process_hooks_new(HOOK_GIVE, &in, NULL)) - { - msg_print("The monster does not want your item."); - } - } - - /* Take a turn, even if the offer is declined */ - energy_use = 100; -} - - -/* - * Chat with a monster - */ -void do_cmd_chat() -{ - int dir, x, y; - - cave_type *c_ptr; - - - /* Get a "repeated" direction */ - if (!get_rep_dir(&dir)) return; - - /* Get requested location */ - y = p_ptr->py + ddy[dir]; - x = p_ptr->px + ddx[dir]; - - /* Get requested grid */ - c_ptr = &cave[y][x]; - - /* No monster in the way */ - if (c_ptr->m_idx == 0) - { - msg_print("There is no monster there."); - return; - } - - /* Process hook if there are any */ - if (!process_hooks(HOOK_CHAT, "(d)", c_ptr->m_idx)) - { - msg_print("The monster does not want to chat."); - } - - /* No energy spent */ -} diff --git a/src/cmd2.cc b/src/cmd2.cc new file mode 100644 index 00000000..67f25098 --- /dev/null +++ b/src/cmd2.cc @@ -0,0 +1,5182 @@ +/* File: cmd2.c */ + +/* Purpose: Movement commands (part 2) */ + +/* + * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke + * + * This software may be copied and distributed for educational, research, and + * not for profit purposes provided that this copyright and statement are + * included in all such copies. + */ + +#include "angband.h" +#include "hooks.h" + +void do_cmd_immovable_special(void); + +/* + * Try to bash an altar + */ +static bool_ do_cmd_bash_altar(int y, int x) +{ + msg_print("Are you mad? You want to anger the gods?"); + return (FALSE); +} + + +/* + * Try to bash a fountain + */ +static bool_ do_cmd_bash_fountain(int y, int x) +{ + int bash, temp; + + bool_ more = TRUE; + + monster_race *r_ptr = &r_info[p_ptr->body_monster]; + + + if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_BASH_DOOR)) + { + msg_print("You cannot do that."); + + return (FALSE); + } + + /* Take a turn */ + energy_use = 100; + + /* Message */ + msg_print("You smash into the fountain!"); + + /* Hack -- Bash power based on strength */ + /* (Ranges from 3 to 20 to 100 to 200) */ + bash = adj_str_blow[p_ptr->stat_ind[A_STR]]; + + /* Compare bash power to door power XXX XXX XXX */ + temp = (bash - 50); + + /* Hack -- always have a chance */ + if (temp < 1) temp = 1; + + /* Hack -- attempt to bash down the door */ + if (rand_int(200) < temp) + { + /* Message */ + msg_print("The fountain breaks!"); + + fire_ball(GF_WATER, 5, damroll(6, 8), 2); + + cave_set_feat(y, x, FEAT_DEEP_WATER); + more = FALSE; + } + + return (more); +} + +/* + * Stair hooks + */ +static bool_ stair_hooks(stairs_direction direction) +{ + cptr direction_s = (direction == STAIRS_UP) ? "up" : "down"; + + /* Old-style hooks */ + if (process_hooks(HOOK_STAIR, "(s)", direction_s)) + { + return TRUE; /* Prevent movement */ + } + + /* New-style hooks */ + { + hook_stair_in in = { direction }; + hook_stair_out out = { TRUE }; /* Allow by default */ + + process_hooks_new(HOOK_STAIR, &in, &out); + + return (!out.allow); + } +} + + +/* + * Go up one level + */ +void do_cmd_go_up(void) +{ + bool_ go_up = FALSE, go_up_many = FALSE, prob_traveling = FALSE; + + cave_type *c_ptr; + + int oldl = dun_level; + + dungeon_info_type *d_ptr = &d_info[dungeon_type]; + + + /* Player grid */ + c_ptr = &cave[p_ptr->py][p_ptr->px]; + + /* Can we ? */ + if (stair_hooks(STAIRS_UP)) + { + return; + } + + /* Normal up stairs */ + if ((c_ptr->feat == FEAT_LESS) || (c_ptr->feat == FEAT_WAY_LESS)) + { + if (!dun_level) + { + go_up = TRUE; + } + else if ((dungeon_flags2 & DF2_ASK_LEAVE)) + { + go_up = get_check("Leave this unique level forever? "); + } + else if (confirm_stairs) + { + go_up = get_check("Really leave the level? "); + } + else + { + go_up = TRUE; + } + } + + /* Shaft up */ + else if (c_ptr->feat == FEAT_SHAFT_UP) + { + if (dun_level == 1) + { + go_up = TRUE; + } + else if ((dungeon_flags2 & DF2_ASK_LEAVE)) + { + go_up = get_check("Leave this unique level forever? "); + } + else if (confirm_stairs) + { + go_up_many = get_check("Really leave the level? "); + } + else + { + go_up_many = TRUE; + } + } + + /* Quest exit */ + else if (c_ptr->feat == FEAT_QUEST_EXIT) + { + leaving_quest = p_ptr->inside_quest; + + if ((dungeon_flags2 & DF2_ASK_LEAVE) && + !get_check("Leave this unique level forever? ")) + return; + + p_ptr->inside_quest = c_ptr->special; + dun_level = 0; + p_ptr->oldpx = 0; + p_ptr->oldpy = 0; + p_ptr->leaving = TRUE; + + return; + } + + /* Exits to previous area in flat terrains */ + else if (!(dungeon_flags1 & DF1_FLAT) && + p_ptr->prob_travel && !p_ptr->inside_quest) + { + if (d_ptr->mindepth == dun_level) return; + + if (dungeon_flags2 & DF2_NO_EASY_MOVE) + { + msg_print("Some powerful force prevents your from teleporting."); + return; + } + + prob_traveling = TRUE; + + if (confirm_stairs) + { + if (get_check("Really leave the level? ")) + go_up = TRUE; + } + else + { + go_up = TRUE; + } + } + else + { + msg_print("I see no up staircase here."); + return; + } + + if (go_up || go_up_many) + { + + energy_use = 0; + + /* Success */ + if (c_ptr->feat == FEAT_WAY_LESS) + msg_print("You enter the previous area."); + else + msg_print("You enter a maze of up staircases."); + + autosave_checkpoint(); + + if (p_ptr->inside_quest) + { + dun_level = 1; + leaving_quest = p_ptr->inside_quest; + + p_ptr->inside_quest = c_ptr->special; + } + + /* Create a way back */ + if (go_up_many) + create_down_shaft = TRUE; + else + create_down_stair = TRUE; + + /* New depth */ + if (go_up) + dun_level--; + else + { + dun_level -= randint(3) + 1; + if (dun_level <= 0) dun_level = 0; + } + + if (c_ptr->special && (!prob_traveling)) + { + dun_level = oldl; + dun_level = get_flevel(); + dungeon_type = c_ptr->special; + dun_level += d_info[dungeon_type].mindepth; + } + + /* Leaving */ + p_ptr->leaving = TRUE; + } +} + + +/* + * Returns TRUE if we are in the Between... + */ +static bool_ between_effect(void) +{ + byte bx, by; + + + if (cave[p_ptr->py][p_ptr->px].feat == FEAT_BETWEEN) + { + + bx = cave[p_ptr->py][p_ptr->px].special & 255; + by = cave[p_ptr->py][p_ptr->px].special >> 8; + + msg_print("You fall into the void."); + msg_print("Brrrr! It's deadly cold."); + + swap_position(by, bx); + + /* To avoid being teleported back */ + energy_use = 100; + + return (TRUE); + } + + else if (cave[p_ptr->py][p_ptr->px].feat == FEAT_BETWEEN2) + { + between_exit *be_ptr = &between_exits[cave[p_ptr->py][p_ptr->px].special]; + + p_ptr->wild_mode = FALSE; + p_ptr->wilderness_x = be_ptr->wild_x; + p_ptr->wilderness_y = be_ptr->wild_y; + p_ptr->oldpx = p_ptr->px = be_ptr->px; + p_ptr->oldpy = p_ptr->py = be_ptr->py; + dungeon_type = be_ptr->d_idx; + dun_level = be_ptr->level; + p_ptr->leaving = TRUE; + + return (TRUE); + } + else + return (FALSE); +} + +/* + * Go down one level + */ +void do_cmd_go_down(void) +{ + cave_type *c_ptr; + + bool_ go_down = FALSE, go_down_many = FALSE, prob_traveling = FALSE; + + bool_ fall_trap = FALSE; + + char i; + + int old_dun = dun_level; + + dungeon_info_type *d_ptr = &d_info[dungeon_type]; + + + /* MUST be actived now */ + if (between_effect()) return; + + /* Player grid */ + c_ptr = &cave[p_ptr->py][p_ptr->px]; + + if (p_ptr->astral && (dun_level == 98)) return; + + if (c_ptr->t_idx == TRAP_OF_SINKING) fall_trap = TRUE; + + /* test if on special level */ + if ((dungeon_flags2 & DF2_ASK_LEAVE)) + { + prt("Leave this unique level forever (y/n) ? ", 0, 0); + flush(); + i = inkey(); + prt("", 0, 0); + if (i != 'y') return; + } + + /* Can we ? */ + if (stair_hooks(STAIRS_DOWN)) + { + return; + } + + /* Normal up stairs */ + if (c_ptr->feat == FEAT_SHAFT_DOWN) + { + if (!dun_level) + { + go_down = TRUE; + + /* Save old player position */ + p_ptr->oldpx = p_ptr->px; + p_ptr->oldpy = p_ptr->py; + } + else + { + if (confirm_stairs) + { + if (get_check("Really leave the level? ")) + go_down_many = TRUE; + } + else + { + go_down_many = TRUE; + } + } + } + + /* Normal stairs */ + else if ((c_ptr->feat == FEAT_MORE) || (c_ptr->feat == FEAT_WAY_MORE)) + { + if (p_ptr->prob_travel) + { + if (d_ptr->maxdepth == dun_level) return; + } + if (!dun_level) + { + go_down = TRUE; + + /* Save old player position */ + p_ptr->oldpx = p_ptr->px; + p_ptr->oldpy = p_ptr->py; + } + else + { + if (confirm_stairs) + { + if (get_check("Really leave the level? ")) + go_down = TRUE; + } + else + { + go_down = TRUE; + } + } + } + + /* Handle quest areas -KMW- */ + else if (c_ptr->feat == FEAT_QUEST_ENTER) + { + /* Enter quest level */ + enter_quest(); + + return; + } + + else if (!(dungeon_flags1 & DF1_FLAT) && + p_ptr->prob_travel && !p_ptr->inside_quest) + { + if (d_ptr->maxdepth == dun_level) return; + + if (dungeon_flags2 & DF2_NO_EASY_MOVE) + { + msg_print("Some powerfull force prevents your from teleporting."); + return; + } + + prob_traveling = TRUE; + + if (confirm_stairs) + { + if (get_check("Really leave the level? ")) + go_down = TRUE; + } + else + { + go_down = TRUE; + } + } + + else if (!(fall_trap)) + { + msg_print("I see no down staircase here."); + return; + } + + if (go_down || go_down_many) + { + energy_use = 0; + + if (fall_trap) + msg_print("You deliberately jump through the trap door."); + else + { + if (c_ptr->feat == FEAT_WAY_MORE) + msg_print("You enter the next area."); + else + msg_print("You enter a maze of down staircases."); + } + + autosave_checkpoint(); + + /* Go down */ + if (go_down) + { + dun_level++; + } + else if (go_down_many) + { + int i = randint(3) + 1, j; + + for (j = 1; j < i; j++) + { + dun_level++; + if (is_quest(dun_level + i - 1)) break; + if (d_ptr->maxdepth == dun_level) break; + } + } + + /* We change place */ + if (c_ptr->special && (!prob_traveling)) + { + if (d_info[c_ptr->special].min_plev <= p_ptr->lev) + { + dungeon_info_type *d_ptr = &d_info[c_ptr->special]; + + /* Do the lua scripts refuse ? ;) */ + if (process_hooks(HOOK_ENTER_DUNGEON, "(d)", c_ptr->special)) + { + dun_level = old_dun; + return; + } + + /* Ok go in the new dungeon */ + dungeon_type = c_ptr->special; + d_ptr = &d_info[dungeon_type]; + + if ((p_ptr->wilderness_x == d_ptr->ix) && + (p_ptr->wilderness_y == d_ptr->iy)) + { + dun_level = d_ptr->mindepth; + } + else if ((p_ptr->wilderness_x == d_ptr->ox) && + (p_ptr->wilderness_y == d_ptr->oy)) + { + dun_level = d_ptr->maxdepth; + } + else + { + dun_level = d_ptr->mindepth; + } + + msg_format("You go into %s", + d_text + d_info[dungeon_type].text); + } + else + { + msg_print + ("You don't feel yourself experienced enough to go there..."); + dun_level = old_dun; + return; + } + } + + /* Leaving */ + p_ptr->leaving = TRUE; + + if (!fall_trap) + { + /* Create a way back */ + if (go_down_many) + create_up_shaft = TRUE; + else + create_up_stair = TRUE; + } + } +} + + + +/* + * Simple command to "search" for one turn + */ +void do_cmd_search(void) +{ + /* Allow repeated command */ + if (command_arg) + { + /* Set repeat count */ + command_rep = command_arg - 1; + + /* Redraw the state */ + p_ptr->redraw |= (PR_STATE); + + /* Cancel the arg */ + command_arg = 0; + } + + /* Take a turn */ + energy_use = 100; + + /* Search */ + search(); +} + + +/* + * Hack -- toggle search mode + */ +void do_cmd_toggle_search(void) +{ + /* Stop searching */ + if (p_ptr->searching) + { + /* Clear the searching flag */ + p_ptr->searching = FALSE; + + /* Recalculate bonuses */ + p_ptr->update |= (PU_BONUS); + + /* Redraw the state */ + p_ptr->redraw |= (PR_STATE); + } + + /* Start searching */ + else + { + /* Set the searching flag */ + p_ptr->searching = TRUE; + + /* Update stuff */ + p_ptr->update |= (PU_BONUS); + + /* Redraw stuff */ + p_ptr->redraw |= (PR_STATE | PR_SPEED); + } +} + + + +/* + * Determine if a grid contains a chest + */ +static s16b chest_check(int y, int x) +{ + cave_type *c_ptr = &cave[y][x]; + + s16b this_o_idx, next_o_idx = 0; + + + /* Scan all objects in the grid */ + for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) + { + object_type * o_ptr; + + /* Acquire object */ + o_ptr = &o_list[this_o_idx]; + + /* Acquire next object */ + next_o_idx = o_ptr->next_o_idx; + + /* Skip unknown chests XXX XXX */ + /* if (!o_ptr->marked) continue; */ + + /* Check for chest */ + if (o_ptr->tval == TV_CHEST) return (this_o_idx); + } + + /* No chest */ + return (0); +} + + +/* + * Allocates objects upon opening a chest -BEN- + * + * Disperse treasures from the given chest, centered at (x,y). + * + * Small chests often contain "gold", while Large chests always contain + * items. Wooden chests contain 2 items, Iron chests contain 4 items, + * and Steel chests contain 6 items. The "value" of the items in a + * chest is based on the "power" of the chest, which is in turn based + * on the level on which the chest is generated. + */ +static void chest_death(int y, int x, s16b o_idx) +{ + int number; + + bool_ small; + + object_type forge; + object_type *q_ptr; + + object_type *o_ptr = &o_list[o_idx]; + + + /* Small chests often hold "gold" */ + small = (o_ptr->sval < SV_CHEST_MIN_LARGE); + + /* Determine how much to drop (see above) */ + number = (o_ptr->sval % SV_CHEST_MIN_LARGE) * 2; + + /* Zero pval means empty chest */ + if (!o_ptr->pval) number = 0; + + /* Opening a chest */ + opening_chest = TRUE; + + /* Determine the "value" of the items */ + object_level = ABS(o_ptr->pval) + 10; + + /* Drop some objects (non-chests) */ + for (; number > 0; --number) + { + /* Get local object */ + q_ptr = &forge; + + /* Wipe the object */ + object_wipe(q_ptr); + + /* Small chests often drop gold */ + if (small && (rand_int(100) < 75)) + { + /* Make some gold */ + if (!make_gold(q_ptr)) continue; + } + + /* Otherwise drop an item */ + else + { + /* Make an object */ + if (!make_object(q_ptr, FALSE, FALSE, d_info[dungeon_type].objs)) + continue; + } + + /* Drop it in the dungeon */ + drop_near(q_ptr, -1, y, x); + } + + /* Reset the object level */ + object_level = dun_level; + + /* No longer opening a chest */ + opening_chest = FALSE; + + /* Empty */ + o_ptr->pval = 0; + o_ptr->pval2 = 0; + + /* Known */ + object_known(o_ptr); +} + + +/* + * Chests have traps too. + * + * Exploding chest destroys contents (and traps). + * Note that the chest itself is never destroyed. + */ +static void chest_trap(int y, int x, s16b o_idx) +{ + int trap; + + object_type *o_ptr = &o_list[o_idx]; + + bool_ ident = FALSE; + + + /* Ignore disarmed chests */ + if (o_ptr->pval <= 0) return; + + /* Obtain the trap */ + trap = o_ptr->pval; + + /* Message */ + msg_print("You found a trap!"); + + /* Set off trap */ + ident = player_activate_trap_type(y, x, o_ptr, o_idx); + if (ident) + { + t_info[o_ptr->pval].ident = TRUE; + msg_format("You identified the trap as %s.", + t_name + t_info[trap].name); + } +} + + +/* + * Attempt to open the given chest at the given location + * + * Assume there is no monster blocking the destination + * + * Returns TRUE if repeated commands may continue + */ +static bool_ do_cmd_open_chest(int y, int x, s16b o_idx) +{ + int i, j; + + bool_ flag = TRUE; + + bool_ more = FALSE; + + object_type *o_ptr = &o_list[o_idx]; + + monster_race *r_ptr = &r_info[p_ptr->body_monster]; + + + if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_OPEN_DOOR)) + { + msg_print("You cannot open chests."); + + return (FALSE); + } + + /* Take a turn */ + energy_use = 100; + + /* Attempt to unlock it */ + if (o_ptr->pval > 0) + { + /* Assume locked, and thus not open */ + flag = FALSE; + + /* Get the "disarm" factor */ + i = p_ptr->skill_dis; + + /* Penalize some conditions */ + if (p_ptr->blind || no_lite()) i = i / 10; + if (p_ptr->confused || p_ptr->image) i = i / 10; + + /* Extract the difficulty */ + j = i - o_ptr->pval; + + /* Always have a small chance of success */ + if (j < 2) j = 2; + + /* Success -- May still have traps */ + if (rand_int(100) < j) + { + msg_print("You have picked the lock."); + gain_exp(1); + flag = TRUE; + } + + /* Failure -- Keep trying */ + else + { + /* We may continue repeating */ + more = TRUE; + + if (flush_failure) flush(); + + msg_print("You failed to pick the lock."); + } + } + + /* Allowed to open */ + if (flag) + { + /* Apply chest traps, if any */ + chest_trap(y, x, o_idx); + + /* Let the Chest drop items */ + chest_death(y, x, o_idx); + } + + /* Result */ + return (more); +} + + +/* + * Original code by TNB, improvement for Angband 2.9.3 by rr9 + * Slightly modified for ToME because of its trap implementation + */ + +/* + * Return TRUE if the given grid is an open door + */ +static bool_ is_open(cave_type *c_ptr) +{ + return (c_ptr->feat == FEAT_OPEN); +} + + +/* + * Return TRUE if the given grid is a closed door + */ +static bool_ is_closed(cave_type *c_ptr) +{ + byte feat; + + if (c_ptr->mimic) feat = c_ptr->mimic; + else feat = c_ptr->feat; + + return ((feat >= FEAT_DOOR_HEAD) && (feat <= FEAT_DOOR_TAIL)); +} + + +/* + * Return TRUE if the given grid has a trap + */ +static bool_ is_trap(cave_type *c_ptr) +{ + return ((c_ptr->info & (CAVE_TRDT)) != 0); +} + + +/* + * Return the number of doors/traps around (or under) + * the character using the filter function 'test' + */ +static int count_feats(int *y, int *x, bool_ (*test) (cave_type *c_ptr), + bool_ under) +{ + int d; + + int xx, yy; + + int count; + + + /* Clear match counter */ + count = 0; + + /* Check around (and under) the character */ + for (d = 0; d < 9; d++) + { + /* Ignore current grid if told so -- See tables.c */ + if ((d == 8) && !under) continue; + + /* Extract adjacent (legal) location */ + yy = p_ptr->py + ddy_ddd[d]; + xx = p_ptr->px + ddx_ddd[d]; + + /* Paranoia */ + if (!in_bounds(yy, xx)) continue; + + /* Must have knowledge */ + if (!(cave[yy][xx].info & (CAVE_MARK))) continue; + + /* Not looking for this feature */ + if (!(*test) (&cave[yy][xx])) continue; + + /* Count it */ + count++; + + /* Remember the location. Only meaningful if there's + exactly one match */ + *y = yy; + *x = xx; + } + + /* All done */ + return (count); +} + + +/* + * Return the number of chests around (or under) the character. + * If requested, count only trapped chests. + */ +static int count_chests(int *y, int *x, bool_ trapped) +{ + int d, count, o_idx; + + object_type *o_ptr; + + + /* Count how many matches */ + count = 0; + + /* Check around (and under) the character */ + for (d = 0; d < 9; d++) + { + + /* Extract adjacent (legal) location */ + int yy = p_ptr->py + ddy_ddd[d]; + int xx = p_ptr->px + ddx_ddd[d]; + + /* No (visible) chest is there */ + if ((o_idx = chest_check(yy, xx)) == 0) continue; + + /* Grab the object */ + o_ptr = &o_list[o_idx]; + + /* Already open */ + if (o_ptr->pval == 0) continue; + + /* No (known) traps here */ + if (trapped && (!object_known_p(o_ptr) || !o_ptr->pval)) continue; + + /* OK */ + ++count; + + /* Remember the location. Only useful if only one match */ + *y = yy; + *x = xx; + } + + /* All done */ + return (count); +} + + +/* + * Convert an adjacent location to a direction. + */ +static int coords_to_dir(int y, int x) +{ + int d[3][3] = + { + {7, 4, 1}, + {8, 5, 2}, + {9, 6, 3} }; + + int dy, dx; + + + dy = y - p_ptr->py; + dx = x - p_ptr->px; + + /* Paranoia */ + if (ABS(dx) > 1 || ABS(dy) > 1) return (0); + + return d[dx + 1][dy + 1]; +} + + +/* + * Perform the basic "open" command on doors + * + * Assume destination is a closed/locked/jammed door + * + * Assume there is no monster blocking the destination + * + * Returns TRUE if repeated commands may continue + */ +static bool_ do_cmd_open_aux(int y, int x, int dir) +{ + int i, j; + + cave_type *c_ptr; + + bool_ more = FALSE; + + monster_race *r_ptr = &r_info[p_ptr->body_monster]; + + + if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_OPEN_DOOR)) + { + msg_print("You cannot open doors."); + + return (FALSE); + } + + /* Take a turn */ + energy_use = 100; + + /* Get requested grid */ + c_ptr = &cave[y][x]; + + /* Jammed door */ + if (c_ptr->feat >= FEAT_DOOR_HEAD + 0x08) + { + /* Stuck */ + msg_print("The door appears to be stuck."); + } + + /* Locked door */ + else if (c_ptr->feat >= FEAT_DOOR_HEAD + 0x01) + { + /* Disarm factor */ + i = p_ptr->skill_dis; + + /* Penalize some conditions */ + if (p_ptr->blind || no_lite()) i = i / 10; + if (p_ptr->confused || p_ptr->image) i = i / 10; + + /* Extract the lock power */ + j = c_ptr->feat - FEAT_DOOR_HEAD; + + /* Extract the difficulty XXX XXX XXX */ + j = i - (j * 4); + + /* Always have a small chance of success */ + if (j < 2) j = 2; + + /* Success */ + if (rand_int(100) < j) + { + /* Message */ + msg_print("You have picked the lock."); + + /* Set off trap */ + if (c_ptr->t_idx != 0) player_activate_door_trap(y, x); + + /* Open the door */ + cave_set_feat(y, x, FEAT_OPEN); + + /* Update some things */ + p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_MON_LITE); + + /* Sound */ + sound(SOUND_OPENDOOR); + + /* Experience */ + gain_exp(1); + } + + /* Failure */ + else + { + /* Failure */ + if (flush_failure) flush(); + + /* Message */ + msg_print("You failed to pick the lock."); + + /* We may keep trying */ + more = TRUE; + } + } + + /* Closed door */ + else + { + /* Set off trap */ + if (c_ptr->t_idx != 0) player_activate_door_trap(y, x); + + /* Open the door */ + cave_set_feat(y, x, FEAT_OPEN); + + /* Update some things */ + p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_MON_LITE); + + /* Sound */ + sound(SOUND_OPENDOOR); + } + + /* Result */ + return (more); +} + + + +/* + * Open a closed/locked/jammed door or a closed/locked chest. + * + * Unlocking a locked door/chest is worth one experience point. + */ +void do_cmd_open(void) +{ + int y, x, dir; + + s16b o_idx; + + cave_type *c_ptr; + + bool_ more = FALSE; + + monster_race *r_ptr = &r_info[p_ptr->body_monster]; + + + if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_OPEN_DOOR)) + { + msg_print("You cannot open doors."); + + return; + } + + /* Option: Pick a direction */ + if (easy_open) + { + int num_doors, num_chests; + + /* Count closed doors (locked or jammed) */ + num_doors = count_feats(&y, &x, is_closed, FALSE); + + /* Count chests (locked) */ + num_chests = count_chests(&y, &x, FALSE); + + /* There is nothing the player can open */ + if ((num_doors + num_chests) == 0) + { + /* Message */ + msg_print("You see nothing there to open."); + + /* Done */ + return; + } + + /* Set direction if there is only one target */ + else if ((num_doors + num_chests) == 1) + { + command_dir = coords_to_dir(y, x); + } + } + + /* Allow repeated command */ + if (command_arg) + { + /* Set repeat count */ + command_rep = command_arg - 1; + + /* Redraw the state */ + p_ptr->redraw |= (PR_STATE); + + /* Cancel the arg */ + command_arg = 0; + } + + /* Get a "repeated" direction */ + if (get_rep_dir(&dir)) + { + /* Get requested location */ + y = p_ptr->py + ddy[dir]; + x = p_ptr->px + ddx[dir]; + + /* Get requested grid */ + c_ptr = &cave[y][x]; + + /* Check for chest */ + o_idx = chest_check(y, x); + + /* Nothing useful */ + if (!((c_ptr->feat >= FEAT_DOOR_HEAD) && + (c_ptr->feat <= FEAT_DOOR_TAIL)) && !o_idx) + { + /* Message */ + msg_print("You see nothing there to open."); + } + + /* Monster in the way */ + else if (c_ptr->m_idx) + { + /* Take a turn */ + energy_use = 100; + + /* Message */ + msg_print("There is a monster in the way!"); + + /* Attack */ + py_attack(y, x, -1); + } + + /* Handle chests */ + else if (o_idx) + { + /* Open the chest */ + more = do_cmd_open_chest(y, x, o_idx); + } + + /* Handle doors */ + else + { + /* Open the door */ + more = do_cmd_open_aux(y, x, dir); + } + } + + /* Process the appropriate hooks */ + process_hooks(HOOK_OPEN, "(d)", is_quest(dun_level)); + + /* Cancel repeat unless we may continue */ + if (!more) disturb(0); +} + + + +/* + * Perform the basic "close" command + * + * Assume destination is an open/broken door + * + * Assume there is no monster blocking the destination + * + * Returns TRUE if repeated commands may continue + */ +static bool_ do_cmd_close_aux(int y, int x, int dir) +{ + cave_type *c_ptr; + + bool_ more = FALSE; + + monster_race *r_ptr = &r_info[p_ptr->body_monster]; + + + if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_OPEN_DOOR)) + { + msg_print("You cannot close doors."); + + return (FALSE); + } + + /* Take a turn */ + energy_use = 100; + + /* Get grid and contents */ + c_ptr = &cave[y][x]; + + /* Set off trap */ + if (c_ptr->t_idx != 0) player_activate_door_trap(y, x); + + /* Broken door */ + if (c_ptr->feat == FEAT_BROKEN) + { + /* Message */ + msg_print("The door appears to be broken."); + } + + /* Open door */ + else + { + /* Close the door */ + cave_set_feat(y, x, FEAT_DOOR_HEAD + 0x00); + + /* Update some things */ + p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_MON_LITE); + + /* Sound */ + sound(SOUND_SHUTDOOR); + } + + /* Result */ + return (more); +} + + +/* + * Close an open door. + */ +void do_cmd_close(void) +{ + int y, x, dir; + + cave_type *c_ptr; + + bool_ more = FALSE; + + + /* Option: Pick a direction */ + if (easy_open) + { + int num_doors; + + /* Count open doors */ + num_doors = count_feats(&y, &x, is_open, FALSE); + + /* There are no doors the player can close */ + if (num_doors == 0) + { + /* Message */ + msg_print("You see nothing there to close."); + + /* Done */ + return; + } + + /* Exactly one closeable door */ + else if (num_doors == 1) + { + command_dir = coords_to_dir(y, x); + } + } + + /* Allow repeated command */ + if (command_arg) + { + /* Set repeat count */ + command_rep = command_arg - 1; + + /* Redraw the state */ + p_ptr->redraw |= (PR_STATE); + + /* Cancel the arg */ + command_arg = 0; + } + + /* Get a "repeated" direction */ + if (get_rep_dir(&dir)) + { + /* Get requested location */ + y = p_ptr->py + ddy[dir]; + x = p_ptr->px + ddx[dir]; + + /* Get grid and contents */ + c_ptr = &cave[y][x]; + + /* Require open/broken door */ + if ((c_ptr->feat != FEAT_OPEN) && (c_ptr->feat != FEAT_BROKEN)) + { + /* Message */ + msg_print("You see nothing there to close."); + } + + /* Monster in the way */ + else if (c_ptr->m_idx) + { + /* Take a turn */ + energy_use = 100; + + /* Message */ + msg_print("There is a monster in the way!"); + + /* Attack */ + py_attack(y, x, -1); + } + + /* Close the door */ + else + { + /* Close the door */ + more = do_cmd_close_aux(y, x, dir); + } + } + + /* Cancel repeat unless we may continue */ + if (!more) disturb(0); +} + + +/* + * Determine if a given grid may be "tunneled" + */ +static bool_ do_cmd_tunnel_test(int y, int x) +{ + /* Must have knowledge(execpt on "forget" levels) */ + if (!(cave[y][x].info & (CAVE_MARK))) + { + /* Message */ + msg_print("You see nothing there."); + + /* Nope */ + return (FALSE); + } + + /* Must be a wall/door/etc */ + if (cave_floor_bold(y, x)) + { + /* Message */ + msg_print("You see nothing there to tunnel."); + + /* Nope */ + return (FALSE); + } + + /* Must be tunnelable */ + if (!(f_info[cave[y][x].feat].flags1 & FF1_TUNNELABLE)) + { + /* Message */ + msg_print(f_text + f_info[cave[y][x].feat].tunnel); + + /* Nope */ + return (FALSE); + } + + /* Okay */ + return (TRUE); +} + + + +/* + * Tunnel through wall. Assumes valid location. + * + * Note that it is impossible to "extend" rooms past their + * outer walls (which are actually part of the room). + * + * This will, however, produce grids which are NOT illuminated + * (or darkened) along with the rest of the room. + */ +static bool_ twall(int y, int x, byte feat) +{ + cave_type *c_ptr = &cave[y][x]; + + + /* Paranoia -- Require a wall or door or some such */ + if (cave_floor_bold(y, x)) return (FALSE); + + /* Forget the wall */ + c_ptr->info &= ~(CAVE_MARK); + + /* Remove the feature */ + cave_set_feat(y, x, feat); + + /* Update some things */ + p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MONSTERS | PU_MON_LITE); + + /* Result */ + return (TRUE); +} + + + +/* + * Perform the basic "tunnel" command + * + * Assumes that the destination is a wall, a vein, a secret + * door, or rubble. + * + * Assumes that no monster is blocking the destination + * + * Returns TRUE if repeated commands may continue + */ +bool_ do_cmd_tunnel_aux(int y, int x, int dir) +{ + int skill_req = 0, skill_req_1pct = 0; + cave_type *c_ptr = &cave[y][x]; + + feature_type *f_ptr = &f_info[c_ptr->feat]; + + bool_ more = FALSE; + + + /* Must be have something to dig with (except for sandwalls) */ + if ((c_ptr->feat < FEAT_SANDWALL) || (c_ptr->feat > FEAT_SANDWALL_K)) + { + if (!p_ptr->inventory[INVEN_TOOL].k_idx || + (p_ptr->inventory[INVEN_TOOL].tval != TV_DIGGING)) + { + msg_print("You need to have a shovel or pick in your tool slot."); + + return (FALSE); + } + } + + /* Verify legality */ + if (!do_cmd_tunnel_test(y, x)) return (FALSE); + + /* Take a turn */ + energy_use = 100; + + /* Get grid */ + c_ptr = &cave[y][x]; + + /* Sound */ + sound(SOUND_DIG); + + /* Titanium */ + if (f_ptr->flags1 & FF1_PERMANENT) + { + msg_print(f_text + f_ptr->tunnel); + } + + else if ((c_ptr->feat == FEAT_TREES) || (c_ptr->feat == FEAT_DEAD_TREE)) + { + /* Chop Down */ + skill_req = 10; + skill_req_1pct = 14; + if ((p_ptr->skill_dig > 10 + rand_int(400)) && twall(y, x, FEAT_GRASS)) + { + msg_print("You have cleared away the trees."); + } + + /* Keep trying */ + else + { + /* We may continue chopping */ + msg_print(f_text + f_ptr->tunnel); + more = TRUE; + + /* Occasional Search XXX XXX */ + if (rand_int(100) < 25) search(); + } + } + + + /* Granite */ + else if ((c_ptr->feat >= FEAT_WALL_EXTRA) && + (c_ptr->feat <= FEAT_WALL_SOLID)) + { + /* Tunnel */ + skill_req = 40; + skill_req_1pct = 56; + if ((p_ptr->skill_dig > 40 + rand_int(1600)) && twall(y, x, FEAT_FLOOR)) + { + msg_print("You have finished the tunnel."); + } + + /* Keep trying */ + else + { + /* We may continue tunelling */ + msg_print(f_text + f_ptr->tunnel); + more = TRUE; + } + } + + + /* Quartz / Magma / Sandwall */ + else if (((c_ptr->feat >= FEAT_MAGMA) && + (c_ptr->feat <= FEAT_QUARTZ_K)) || + ((c_ptr->feat >= FEAT_SANDWALL) && + (c_ptr->feat <= FEAT_SANDWALL_K))) + { + bool_ okay = FALSE; + bool_ gold = FALSE; + bool_ hard = FALSE; + bool_ soft = FALSE; + + /* Found gold */ + if ((c_ptr->feat >= FEAT_MAGMA_H) && + (c_ptr->feat <= FEAT_QUARTZ_K)) gold = TRUE; + + if ((c_ptr->feat == FEAT_SANDWALL_H) || + (c_ptr->feat == FEAT_SANDWALL_K)) + { + gold = TRUE; + soft = TRUE; + } + else + /* Extract "quartz" flag XXX XXX XXX */ + if ((c_ptr->feat - FEAT_MAGMA) & 0x01) hard = TRUE; + + /* Quartz */ + if (hard) + { + skill_req = 20; + skill_req_1pct = 28; + okay = (p_ptr->skill_dig > 20 + rand_int(800)); + } + + /* Sandwall */ + else if (soft) + { + skill_req = 5; + skill_req_1pct = 8; + okay = (p_ptr->skill_dig > 5 + rand_int(250)); + } + + /* Magma */ + else + { + skill_req = 10; + skill_req_1pct = 14; + okay = (p_ptr->skill_dig > 10 + rand_int(400)); + } + + /* Success */ + if (okay && twall(y, x, FEAT_FLOOR)) + { + /* Found treasure */ + if (gold) + { + /* Place some gold */ + place_gold(y, x); + + /* Message */ + msg_print("You have found something!"); + } + + /* Found nothing */ + else + { + /* Message */ + msg_print("You have finished the tunnel."); + } + } + + /* Failure */ + else + { + /* Message, continue digging */ + msg_print(f_text + f_ptr->tunnel); + more = TRUE; + } + } + + /* Rubble */ + else if (c_ptr->feat == FEAT_RUBBLE) + { + /* Remove the rubble */ + skill_req = 0; + skill_req_1pct = 2; + if ((p_ptr->skill_dig > rand_int(200)) && + twall(y, x, d_info[dungeon_type].floor1)) + { + /* Message */ + msg_print("You have removed the rubble."); + + /* Hack -- place an object */ + if (rand_int(100) < 10) + { + /* Create a simple object */ + place_object(y, x, FALSE, FALSE, OBJ_FOUND_RUBBLE); + + /* Observe new object */ + if (player_can_see_bold(y, x)) + { + msg_print("You have found something!"); + } + } + } + + else + { + /* Message, keep digging */ + msg_print(f_text + f_ptr->tunnel); + more = TRUE; + } + } + + /* Secret doors */ + else if (c_ptr->feat >= FEAT_SECRET) + { + /* Tunnel */ + skill_req = 30; + skill_req_1pct = 42; + if ((p_ptr->skill_dig > 30 + rand_int(1200)) && twall(y, x, FEAT_FLOOR)) + { + msg_print("You have finished the tunnel."); + c_ptr->mimic = 0; + lite_spot(y, x); + + /* Set off trap */ + if (c_ptr->t_idx != 0) player_activate_door_trap(y, x); + } + + /* Keep trying */ + else + { + int feat; + + if (c_ptr->mimic) feat = c_ptr->mimic; + else + feat = c_ptr->feat; + + /* We may continue tunelling */ + msg_print(f_text + f_info[feat].tunnel); + more = TRUE; + + /* Occasional Search XXX XXX */ + if (rand_int(100) < 25) search(); + } + } + + /* Doors */ + else + { + /* Tunnel */ + skill_req = 30; + skill_req_1pct = 42; + if ((p_ptr->skill_dig > 30 + rand_int(1200)) && twall(y, x, FEAT_FLOOR)) + { + msg_print("You have finished the tunnel."); + } + + /* Keep trying */ + else + { + /* We may continue tunelling */ + msg_print(f_text + f_ptr->tunnel); + more = TRUE; + } + } + + if (more && magik(2)) + { + if (p_ptr->skill_dig < skill_req) + { + msg_print("You fail to make even the slightest of progress."); + more = FALSE; + } + else if (p_ptr->skill_dig < skill_req_1pct) + { + msg_print("This will take some time."); + } + } + + /* Notice new floor grids */ + if (!cave_floor_bold(y, x)) + { + /* Update some things */ + p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MONSTERS | PU_MON_LITE); + } + + /* Result */ + return (more); +} + + +/* + * Tunnels through "walls" (including rubble and closed doors) + * + * Note that you must tunnel in order to hit invisible monsters + * in walls, though moving into walls still takes a turn anyway. + * + * Digging is very difficult without a "digger" weapon, but can be + * accomplished by strong players using heavy weapons. + */ +void do_cmd_tunnel(void) +{ + int y, x, dir; + + cave_type *c_ptr; + + bool_ more = FALSE; + + + if (p_ptr->wild_mode) return; + + /* Allow repeated command */ + if (command_arg) + { + /* Set repeat count */ + command_rep = command_arg - 1; + + /* Redraw the state */ + p_ptr->redraw |= (PR_STATE); + + /* Cancel the arg */ + command_arg = 0; + } + + /* Get a direction to tunnel, or Abort */ + if (get_rep_dir(&dir)) + { + /* Get location */ + y = p_ptr->py + ddy[dir]; + x = p_ptr->px + ddx[dir]; + + /* Get grid */ + c_ptr = &cave[y][x]; + + /* No tunnelling through doors */ + if (((c_ptr->feat >= FEAT_DOOR_HEAD) && + (c_ptr->feat <= FEAT_DOOR_TAIL)) || (c_ptr->feat == FEAT_SHOP)) + { + /* Message */ + msg_print("You cannot tunnel through doors."); + } + + /* No tunnelling through air */ + else if (cave_floor_grid(c_ptr)) + { + /* Message */ + msg_print("You cannot tunnel through air."); + } + + /* A monster is in the way */ + else if (c_ptr->m_idx) + { + /* Take a turn */ + energy_use = 100; + + /* Message */ + msg_print("There is a monster in the way!"); + + /* Attack */ + py_attack(y, x, -1); + } + + /* Try digging */ + else + { + /* Tunnel through walls */ + more = do_cmd_tunnel_aux(y, x, dir); + } + } + + /* Cancel repetition unless we can continue */ + if (!more) disturb(0); +} + + +/* + * easy_open_door -- + * + * If there is a jammed/closed/locked door at the given location, + * then attempt to unlock/open it. Return TRUE if an attempt was + * made (successful or not), otherwise return FALSE. + * + * The code here should be nearly identical to that in + * do_cmd_open_test() and do_cmd_open_aux(). + */ + +bool_ easy_open_door(int y, int x) +{ + int i, j; + + cave_type *c_ptr = &cave[y][x]; + + monster_race *r_ptr = &r_info[p_ptr->body_monster]; + + + if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_OPEN_DOOR)) + { + msg_print("You cannot open doors."); + + return (FALSE); + } + + /* Must be a closed door */ + if (!((c_ptr->feat >= FEAT_DOOR_HEAD) && (c_ptr->feat <= FEAT_DOOR_TAIL))) + { + /* Nope */ + return (FALSE); + } + + /* Jammed door */ + if (c_ptr->feat >= FEAT_DOOR_HEAD + 0x08) + { + /* Stuck */ + msg_print("The door appears to be stuck."); + } + + /* Locked door */ + else if (c_ptr->feat >= FEAT_DOOR_HEAD + 0x01) + { + /* Disarm factor */ + i = p_ptr->skill_dis; + + /* Penalize some conditions */ + if (p_ptr->blind || no_lite()) i = i / 10; + if (p_ptr->confused || p_ptr->image) i = i / 10; + + /* Extract the lock power */ + j = c_ptr->feat - FEAT_DOOR_HEAD; + + /* Extract the difficulty XXX XXX XXX */ + j = i - (j * 4); + + /* Always have a small chance of success */ + if (j < 2) j = 2; + + /* Success */ + if (rand_int(100) < j) + { + /* Message */ + msg_print("You have picked the lock."); + + /* Set off trap */ + if (c_ptr->t_idx != 0) player_activate_door_trap(y, x); + + /* Open the door */ + cave_set_feat(y, x, FEAT_OPEN); + + /* Update some things */ + p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_MON_LITE); + + /* Sound */ + sound(SOUND_OPENDOOR); + + /* Process the appropriate hooks */ + process_hooks(HOOK_OPEN, "(d)", is_quest(dun_level)); + + /* Experience */ + gain_exp(1); + } + + /* Failure */ + else + { + /* Failure */ + if (flush_failure) flush(); + + /* Message */ + msg_print("You failed to pick the lock."); + } + } + + /* Closed door */ + else + { + /* Set off trap */ + if (c_ptr->t_idx != 0) player_activate_door_trap(y, x); + + /* Open the door */ + cave_set_feat(y, x, FEAT_OPEN); + + /* Update some things */ + p_ptr->update |= (PU_VIEW | PU_MONSTERS | PU_MON_LITE); + + /* Sound */ + sound(SOUND_OPENDOOR); + } + + /* Result */ + return (TRUE); +} + + +/* + * Perform the basic "disarm" command + * + * Assume destination is a visible trap + * + * Assume there is no monster blocking the destination + * + * Returns TRUE if repeated commands may continue + */ +static bool_ do_cmd_disarm_chest(int y, int x, s16b o_idx) +{ + int i, j; + + bool_ more = FALSE; + + object_type *o_ptr = &o_list[o_idx]; + + trap_type *t_ptr = &t_info[o_ptr->pval]; + + + /* Take a turn */ + energy_use = 100; + + /* Get the "disarm" factor */ + i = p_ptr->skill_dis; + + /* Penalize some conditions */ + if (p_ptr->blind || no_lite()) i = i / 10; + if (p_ptr->confused || p_ptr->image) i = i / 10; + + /* Extract the difficulty */ + j = i - t_ptr->difficulty * 3; + + /* Always have a small chance of success */ + if (j < 2) j = 2; + + /* Must find the trap first. */ + if (!object_known_p(o_ptr)) + { + msg_print("I don't see any traps."); + } + + /* Already disarmed/unlocked */ + else if (o_ptr->pval <= 0) + { + msg_print("The chest is not trapped."); + } + + /* Success (get a lot of experience) */ + else if (rand_int(100) < j) + { + msg_print("You have disarmed the chest."); + gain_exp(t_ptr->difficulty * 3); + o_ptr->pval = (0 - o_ptr->pval); + } + + /* Failure -- Keep trying */ + else if ((i > 5) && (randint(i) > 5)) + { + /* We may keep trying */ + more = TRUE; + if (flush_failure) flush(); + msg_print("You failed to disarm the chest."); + } + + /* Failure -- Set off the trap */ + else + { + msg_print("You set off a trap!"); + sound(SOUND_FAIL); + chest_trap(y, x, o_idx); + } + + /* Result */ + return (more); +} + + +/* + * Perform the basic "disarm" command + * + * Assume destination is a visible trap + * + * Assume there is no monster blocking the destination + * + * Returns TRUE if repeated commands may continue + */ +bool_ do_cmd_disarm_aux(int y, int x, int dir, int do_pickup) +{ + int i, j, power; + + cave_type *c_ptr; + + cptr name; + + bool_ more = FALSE; + + + /* Take a turn */ + energy_use = 100; + + /* Get grid and contents */ + c_ptr = &cave[y][x]; + + /* Access trap name */ + if (t_info[c_ptr->t_idx].ident) + name = (t_name + t_info[c_ptr->t_idx].name); + else + name = "unknown trap"; + + /* Get the "disarm" factor */ + i = p_ptr->skill_dis; + + /* Penalize some conditions */ + if (p_ptr->blind || no_lite()) i = i / 10; + if (p_ptr->confused || p_ptr->image) i = i / 10; + + /* XXX XXX XXX Variable power? */ + + /* Extract trap "power" */ + power = t_info[c_ptr->t_idx].difficulty; + + /* Extract the difficulty */ + j = i - power; + + /* Always have a small chance of success */ + if (j < 2) j = 2; + + /* Success */ + if (rand_int(100) < j) + { + /* Message */ + msg_format("You have disarmed the %s.", name); + + /* Reward */ + gain_exp(power); + + /* Forget the trap */ + c_ptr->info &= ~(CAVE_MARK | CAVE_TRDT); + + /* Remove the trap */ + c_ptr->t_idx = 0; + + /* Move the player onto the trap */ + if (!(f_info[c_ptr->feat].flags1 & FF1_DOOR)) + move_player_aux(dir, do_pickup, 0, TRUE); + + /* Remove trap attr from grid */ + note_spot(y, x); + lite_spot(y, x); + } + + /* Failure -- Keep trying */ + else if ((i > 5) && (randint(i) > 5)) + { + /* Failure */ + if (flush_failure) flush(); + + /* Message */ + msg_format("You failed to disarm the %s.", name); + + /* We may keep trying */ + more = TRUE; + } + + /* Failure -- Set off the trap */ + else + { + /* Message */ + msg_format("You set off the %s!", name); + + /* Move the player onto the trap */ + if (!(f_info[c_ptr->feat].flags1 & FF1_DOOR)) + move_player_aux(dir, do_pickup, 0, FALSE); + } + + /* Result */ + return (more); +} + + +/* + * Disamrs the monster traps(no failure) + */ +void do_cmd_disarm_mon_trap(int y, int x) +{ + msg_print("You disarm the monster trap."); + + place_floor_convert_glass(y, x); + cave[p_ptr->py][p_ptr->px].special = cave[p_ptr->py][p_ptr->px].special2 = 0; +} + + +/* + * Disarms a trap, or chest + */ +void do_cmd_disarm(void) +{ + int y, x, dir; + + s16b o_idx; + + cave_type *c_ptr; + + bool_ more = FALSE; + + + /* Option: Pick a direction */ + if (easy_disarm) + { + int num_traps, num_chests; + + /* Count visible traps */ + num_traps = count_feats(&y, &x, is_trap, TRUE); + + /* Count chests (trapped) */ + num_chests = count_chests(&y, &x, TRUE); + + /* See if only one target */ + if (num_traps || num_chests) + { + if (num_traps + num_chests <= 1) + command_dir = coords_to_dir(y, x); + } + } + + /* Allow repeated command */ + if (command_arg) + { + /* Set repeat count */ + command_rep = command_arg - 1; + + /* Redraw the state */ + p_ptr->redraw |= (PR_STATE); + + /* Cancel the arg */ + command_arg = 0; + } + + /* Get a direction (or abort) */ + if (get_rep_dir(&dir)) + { + /* Get location */ + y = p_ptr->py + ddy[dir]; + x = p_ptr->px + ddx[dir]; + + /* Get grid and contents */ + c_ptr = &cave[y][x]; + + /* Check for chests */ + o_idx = chest_check(y, x); + + /* Disarm a trap */ + if (((c_ptr->t_idx == 0) || (!(c_ptr->info & CAVE_TRDT))) && + !o_idx && (c_ptr->feat != FEAT_MON_TRAP)) + { + /* Message */ + msg_print("You see nothing there to disarm."); + } + + /* Monster in the way */ + else if (c_ptr->m_idx) + { + /* Message */ + msg_print("There is a monster in the way!"); + + /* Attack */ + py_attack(y, x, -1); + } + + /* Disarm chest */ + else if (o_idx) + { + /* Disarm the chest */ + more = do_cmd_disarm_chest(y, x, o_idx); + } + + /* Disarm trap */ + else + { + /* Disarm the trap */ + if (c_ptr->feat == FEAT_MON_TRAP) + { + do_cmd_disarm_mon_trap(y, x); + more = FALSE; + } + else + more = do_cmd_disarm_aux(y, x, dir, always_pickup); + } + } + + /* Cancel repeat unless told not to */ + if (!more) disturb(0); +} + + +/* + * Perform the basic "bash" command + * + * Assume destination is a closed/locked/jammed door + * + * Assume there is no monster blocking the destination + * + * Returns TRUE if repeated commands may continue + */ +static bool_ do_cmd_bash_aux(int y, int x, int dir) +{ + int bash, temp; + + cave_type *c_ptr; + + bool_ more = FALSE; + + monster_race *r_ptr = &r_info[p_ptr->body_monster]; + + + if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_BASH_DOOR)) + { + msg_print("You cannot do that."); + + return (FALSE); + } + + /* Take a turn */ + energy_use = 100; + + /* Get grid */ + c_ptr = &cave[y][x]; + + /* Message */ + msg_print("You smash into the door!"); + + /* Hack -- Bash power based on strength */ + /* (Ranges from 3 to 20 to 100 to 200) */ + bash = adj_str_blow[p_ptr->stat_ind[A_STR]]; + + /* Extract door power */ + temp = ((c_ptr->feat - FEAT_DOOR_HEAD) & 0x07); + + /* Compare bash power to door power XXX XXX XXX */ + temp = (bash - (temp * 10)); + + /* Hack -- always have a chance */ + if (temp < 1) temp = 1; + + /* Hack -- attempt to bash down the door */ + if (rand_int(100) < temp) + { + /* Message */ + msg_print("The door crashes open!"); + + /* Break down the door */ + if (rand_int(100) < 50) + { + /* Set off trap */ + if (c_ptr->t_idx != 0) player_activate_door_trap(y, x); + + cave_set_feat(y, x, FEAT_BROKEN); + } + + /* Open the door */ + else + { + /* Set off trap */ + if (c_ptr->t_idx != 0) player_activate_door_trap(y, x); + + cave_set_feat(y, x, FEAT_OPEN); + } + + /* Sound */ + sound(SOUND_OPENDOOR); + + /* Hack -- Fall through the door. Can't disarm while falling. */ + move_player_aux(dir, always_pickup, 0, FALSE); + + /* Update some things */ + p_ptr->update |= (PU_VIEW | PU_MON_LITE); + p_ptr->update |= (PU_DISTANCE); + } + + /* Saving throw against stun */ + else if (rand_int(100) < adj_dex_safe[p_ptr->stat_ind[A_DEX]] + p_ptr->lev) + { + /* Message */ + msg_print("The door holds firm."); + + /* Allow repeated bashing */ + more = TRUE; + } + + /* High dexterity yields coolness */ + else + { + /* Message */ + msg_print("You are off-balance."); + + /* Hack -- Lose balance ala paralysis */ + (void)set_paralyzed(2 + rand_int(2)); + } + + /* Result */ + return (more); +} + + +/* + * Bash open a door, success based on character strength + * + * For a closed door, pval is positive if locked; negative if stuck. + * + * For an open door, pval is positive for a broken door. + * + * A closed door can be opened - harder if locked. Any door might be + * bashed open (and thereby broken). Bashing a door is (potentially) + * faster! You move into the door way. To open a stuck door, it must + * be bashed. A closed door can be jammed (see do_cmd_spike()). + * + * Creatures can also open or bash doors, see elsewhere. + */ +void do_cmd_bash(void) +{ + int y, x, dir; + + cave_type *c_ptr; + + bool_ more = FALSE; + + monster_race *r_ptr = &r_info[p_ptr->body_monster]; + + + if ((p_ptr->body_monster != 0) && !(r_ptr->flags2 & RF2_BASH_DOOR)) + { + msg_print("You cannot do that."); + + return; + } + + /* Allow repeated command */ + if (command_arg) + { + /* Set repeat count */ + command_rep = command_arg - 1; + + /* Redraw the state */ + p_ptr->redraw |= (PR_STATE); + + /* Cancel the arg */ + command_arg = 0; + } + + /* Get a "repeated" direction */ + if (get_rep_dir(&dir)) + { + /* Bash location */ + y = p_ptr->py + ddy[dir]; + x = p_ptr->px + ddx[dir]; + + /* Get grid */ + c_ptr = &cave[y][x]; + + /* Nothing useful */ + if ((c_ptr->feat < FEAT_DOOR_HEAD || + c_ptr->feat > FEAT_DOOR_TAIL) && + (c_ptr->feat < FEAT_ALTAR_HEAD || + c_ptr->feat > FEAT_ALTAR_TAIL) && (c_ptr->feat != FEAT_FOUNTAIN)) + { + /* Message */ + msg_print("You see nothing there to bash."); + } + + /* Monster in the way */ + else if (c_ptr->m_idx) + { + /* Take a turn */ + energy_use = 100; + + /* Message */ + msg_print("There is a monster in the way!"); + + /* Attack */ + py_attack(y, x, -1); + } + + else if (c_ptr->feat >= FEAT_ALTAR_HEAD && + c_ptr->feat <= FEAT_ALTAR_TAIL) + { + more = do_cmd_bash_altar(y, x); + } + /* Bash a closed door */ + else if (c_ptr->feat == FEAT_FOUNTAIN) + { + more = do_cmd_bash_fountain(y, x); + } + else + { + /* Bash the door */ + more = do_cmd_bash_aux(y, x, dir); + } + } + + /* Unless valid action taken, cancel bash */ + if (!more) disturb(0); +} + + + +/* + * Manipulate an adjacent grid in some way + * + * Attack monsters, tunnel through walls, disarm traps, open doors. + * + * Consider confusion XXX XXX XXX + * + * This command must always take a turn, to prevent free detection + * of invisible monsters. + */ +void do_cmd_alter(void) +{ + int y, x, dir; + + cave_type *c_ptr; + + bool_ more = FALSE; + + + /* Allow repeated command */ + if (command_arg) + { + /* Set repeat count */ + command_rep = command_arg - 1; + + /* Redraw the state */ + p_ptr->redraw |= (PR_STATE); + + /* Cancel the arg */ + command_arg = 0; + } + + /* Get a direction */ + if (get_rep_dir(&dir)) + { + /* Get location */ + y = p_ptr->py + ddy[dir]; + x = p_ptr->px + ddx[dir]; + + /* Get grid */ + c_ptr = &cave[y][x]; + + /* Take a turn */ + energy_use = 100; + + /* Attack monsters */ + if (c_ptr->m_idx) + { + /* Attack */ + py_attack(y, x, -1); + } + + /* Open closed doors */ + else if ((c_ptr->feat >= FEAT_DOOR_HEAD) && + (c_ptr->feat <= FEAT_DOOR_TAIL)) + { + /* Tunnel */ + more = do_cmd_open_aux(y, x, dir); + } + + /* Tunnel through walls */ + else if (f_info[c_ptr->feat].flags1 & FF1_TUNNELABLE) + { + /* Tunnel */ + more = do_cmd_tunnel_aux(y, x, dir); + } + + /* Disarm traps */ + else if (c_ptr->t_idx != 0) + { + /* Tunnel */ + more = do_cmd_disarm_aux(y, x, dir, always_pickup); + } + + /* Oops */ + else + { + /* Oops */ + msg_print("You attack the empty air."); + } + } + + /* Cancel repetition unless we can continue */ + if (!more) disturb(0); +} + + +/* + * Find the index of some "spikes", if possible. + * + * XXX XXX XXX Let user choose a pile of spikes, perhaps? + */ +static bool_ get_spike(int *ip) +{ + int i; + + + /* Check every item in the pack */ + for (i = 0; i < INVEN_PACK; i++) + { + object_type *o_ptr = &p_ptr->inventory[i]; + + /* Skip non-objects */ + if (!o_ptr->k_idx) continue; + + /* Check the "tval" code */ + if (o_ptr->tval == TV_SPIKE) + { + /* Save the spike index */ + (*ip) = i; + + /* Success */ + return (TRUE); + } + } + + /* Oops */ + return (FALSE); +} + + + +/* + * Jam a closed door with a spike + * + * This command may NOT be repeated + */ +void do_cmd_spike(void) +{ + int y, x, dir, item; + + cave_type *c_ptr; + + + /* Get a "repeated" direction */ + if (get_rep_dir(&dir)) + { + /* Get location */ + y = p_ptr->py + ddy[dir]; + x = p_ptr->px + ddx[dir]; + + /* Get grid and contents */ + c_ptr = &cave[y][x]; + + /* Require closed door */ + if (!((c_ptr->feat >= FEAT_DOOR_HEAD) && + (c_ptr->feat <= FEAT_DOOR_TAIL))) + { + /* Message */ + msg_print("You see nothing there to spike."); + } + + /* Get a spike */ + else if (!get_spike(&item)) + { + /* Message */ + msg_print("You have no spikes!"); + } + + /* Is a monster in the way? */ + else if (c_ptr->m_idx) + { + /* Take a turn */ + energy_use = 100; + + /* Message */ + msg_print("There is a monster in the way!"); + + /* Attack */ + py_attack(y, x, -1); + } + + /* Go for it */ + else + { + /* Take a turn */ + energy_use = 100; + + /* Successful jamming */ + msg_print("You jam the door with a spike."); + + /* Convert "locked" to "stuck" XXX XXX XXX */ + if (c_ptr->feat < FEAT_DOOR_HEAD + 0x08) c_ptr->feat += 0x08; + + /* Add one spike to the door */ + if (c_ptr->feat < FEAT_DOOR_TAIL) c_ptr->feat++; + + /* Use up, and describe, a single spike, from the bottom */ + inc_stack_size(item, -1); + } + } +} + + +static void do_cmd_walk_jump(int pickup, bool_ disarm) +{ + int dir; + + bool_ more = FALSE; + + + /* Allow repeated command */ + if (command_arg) + { + /* Set repeat count */ + command_rep = command_arg - 1; + + /* Redraw the state */ + p_ptr->redraw |= (PR_STATE); + + /* Cancel the arg */ + command_arg = 0; + } + + /* Get a "repeated" direction */ + if (get_rep_dir(&dir)) + { + /* Take a turn */ + energy_use = 100; + + /* Actually move the character */ + move_player(dir, pickup, disarm); + + /* Allow more walking */ + more = TRUE; + } + + /* Hack -- In small scale wilderness it takes MUCH more time to move */ + energy_use *= (p_ptr->wild_mode) ? ((MAX_HGT + MAX_WID) / 2) : 1; + + /* Hack again -- Is there a special encounter ??? */ + if (p_ptr->wild_mode && + magik(wf_info[wild_map[p_ptr->py][p_ptr->px].feat].level - (p_ptr->lev * 2))) + { + /* Go into large wilderness view */ + p_ptr->wilderness_x = p_ptr->px; + p_ptr->wilderness_y = p_ptr->py; + energy_use = 100; + change_wild_mode(); + + /* HACk -- set the encouter flag for the wilderness generation */ + generate_encounter = TRUE; + p_ptr->oldpx = MAX_WID / 2; + p_ptr->oldpy = MAX_HGT / 2; + + /* Inform the player of his horrible fate :=) */ + msg_print("You are ambushed!"); + } + + /* Cancel repeat unless we may continue */ + if (!more) disturb(0); +} + + +/* + * Support code for the "Walk" and "Jump" commands + */ +void do_cmd_walk(int pickup, bool_ disarm) +{ + /* Move (usually pickup) */ + + if (p_ptr->immovable) + { + do_cmd_unwalk(); + } + else + { + do_cmd_walk_jump(pickup, disarm); + } +} + + +void do_cmd_run_run() +{ + int dir; + + + /* Hack -- no running when confused */ + if (p_ptr->confused) + { + msg_print("You are too confused!"); + return; + } + + /* Get a "repeated" direction */ + if (get_rep_dir(&dir)) + { + /* Hack -- Set the run counter */ + running = (command_arg ? command_arg : 1000); + + /* First step */ + run_step(dir); + } + p_ptr->window |= (PW_OVERHEAD); +} + + +/* + * Start running. + */ +void do_cmd_run(void) +{ + if (p_ptr->immovable) + { + return; + } + else + { + do_cmd_run_run(); + } +} + + + +/* + * Stay still. Search. Enter stores. + * Pick up treasure if "pickup" is true. + */ +void do_cmd_stay(int pickup) +{ + cave_type *c_ptr = &cave[p_ptr->py][p_ptr->px]; + + + /* Allow repeated command */ + if (command_arg) + { + /* Set repeat count */ + command_rep = command_arg - 1; + + /* Redraw the state */ + p_ptr->redraw |= (PR_STATE); + + /* Cancel the arg */ + command_arg = 0; + } + + + /* Take a turn */ + energy_use = 100; + + + /* Spontaneous Searching */ + if ((p_ptr->skill_fos >= 50) || (0 == rand_int(50 - p_ptr->skill_fos))) + { + search(); + } + + /* Continuous Searching */ + if (p_ptr->searching) + { + search(); + } + + + /* Handle "objects" */ + carry(pickup); + + + /* Hack -- enter a store if we are on one */ + if (c_ptr->feat == FEAT_SHOP) + { + /* Disturb */ + disturb(0); + + /* Hack -- enter store */ + command_new = '_'; + } +} + +/* + * Resting allows a player to safely restore his hp -RAK- + */ +void do_cmd_rest(void) +{ + /* Can't rest on a Void Jumpgate -- too dangerous */ + if (cave[p_ptr->py][p_ptr->px].feat == FEAT_BETWEEN) + { + /* 'R&\n' is one of our favourite macros, so we have to do this */ + if (flush_failure) flush(); + + /* Tell the player why */ + msg_print(format("Resting on a %s is too dangerous!", + f_name + f_info[cave[p_ptr->py][p_ptr->px].feat].name)); + + /* Done */ + return; + } + + /* Can't rest while undead, it would mean dying */ + if (p_ptr->necro_extra & CLASS_UNDEAD) + { + /* 'R&\n' is one of our favourite macros, so we have to do this */ + if (flush_failure) flush(); + + /* Tell the player why */ + msg_print("Resting is impossible while undead!"); + + /* Done */ + return; + } + + /* Prompt for time if needed */ + if (command_arg <= 0) + { + cptr p = "Rest (0-9999, '*' for HP/SP, '&' as needed): "; + + char out_val[80]; + + /* Default */ + strcpy(out_val, "&"); + + /* Ask for duration */ + if (!get_string(p, out_val, 4)) return; + + /* Rest until done */ + if (out_val[0] == '&') + { + command_arg = ( -2); + } + + /* Rest a lot */ + else if (out_val[0] == '*') + { + command_arg = ( -1); + } + + /* Rest some */ + else + { + command_arg = atoi(out_val); + if (command_arg <= 0) return; + } + } + + + /* Paranoia */ + if (command_arg > 9999) command_arg = 9999; + + + /* Take a turn XXX XXX XXX (?) */ + energy_use = 100; + + /* Save the rest code */ + resting = command_arg; + + /* Cancel searching */ + p_ptr->searching = FALSE; + + /* Recalculate bonuses */ + p_ptr->update |= (PU_BONUS); + + /* Redraw the state */ + p_ptr->redraw |= (PR_STATE); + + /* Handle stuff */ + handle_stuff(); + + /* Refresh */ + Term_fresh(); +} + + + + + + +/* + * Determines the odds of an object breaking when thrown at a monster + * + * Note that artifacts never break, see the "drop_near()" function. + */ +int breakage_chance(object_type *o_ptr) +{ + int reducer = + 1 + ((get_skill(SKILL_ARCHERY)) ? (get_skill_scale(SKILL_ARCHERY, 10)) : 0); + + /* Examine the item type */ + switch (o_ptr->tval) + { + /* Always break */ + case TV_FLASK: + case TV_POTION: + case TV_POTION2: + case TV_BOTTLE: + case TV_FOOD: + { + return (100); + } + + /* Often break */ + case TV_LITE: + case TV_SCROLL: + case TV_SKELETON: + { + return (50); + } + + case TV_ARROW: + { + return (50 / reducer); + } + + /* Sometimes break */ + case TV_WAND: + case TV_SPIKE: + { + return (25); + } + + case TV_SHOT: + case TV_BOLT: + { + return (25 / reducer); + } + case TV_BOOMERANG: + { + return 1; + } + } + + /* Rarely break */ + return (10); +} + +/* + * Return multiplier of an object + */ +int get_shooter_mult(object_type *o_ptr) +{ + /* Assume a base multiplier */ + int tmul = 1; + + /* Analyze the launcher */ + switch (o_ptr->sval) + { + case SV_SLING: + { + /* Sling and ammo */ + tmul = 2; + break; + } + + case SV_SHORT_BOW: + { + /* Short Bow and Arrow */ + tmul = 2; + break; + } + + case SV_LONG_BOW: + { + /* Long Bow and Arrow */ + tmul = 3; + break; + } + + /* Light Crossbow and Bolt */ + case SV_LIGHT_XBOW: + { + tmul = 3; + break; + } + + /* Heavy Crossbow and Bolt */ + case SV_HEAVY_XBOW: + { + tmul = 4; + break; + } + } + return tmul; +} + + +/* + * Fire an object from the pack or floor. + * + * You may only fire items that "match" your missile launcher. + * + * You must use slings + pebbles/shots, bows + arrows, xbows + bolts. + * + * See "calc_bonuses()" for more calculations and such. + * + * Note that "firing" a missile is MUCH better than "throwing" it. + * + * Note: "unseen" monsters are very hard to hit. + * + * Objects are more likely to break if they "attempt" to hit a monster. + * + * Rangers (with Bows) and Anyone (with "Extra Shots") get extra shots. + * + * The "extra shot" code works by decreasing the amount of energy + * required to make each shot, spreading the shots out over time. + * + * Note that when firing missiles, the launcher multiplier is applied + * after all the bonuses are added in, making multipliers very useful. + * + * Note that Bows of "Extra Might" get extra range and an extra bonus + * for the damage multiplier. + * + * Note that Bows of "Extra Shots" give an extra shot. + */ +void do_cmd_fire(void) +{ + int dir, item; + + int j, y, x, ny, nx, ty, tx, by, bx; + + int oldtdam, tdam, tdis, thits, tmul; + + int bonus, chance; + + int cur_dis, visible; + + int breakage = -1, num_pierce = 0; + + s32b special = 0; + + object_type forge; + + object_type *q_ptr; + + object_type *o_ptr; + + object_type *j_ptr; + + bool_ hit_body = FALSE; + + byte missile_attr; + + char missile_char; + + char o_name[80]; + + cptr q, s; + + int msec = delay_factor * delay_factor * delay_factor; + + + /* Get the "bow" (if any) */ + j_ptr = &p_ptr->inventory[INVEN_BOW]; + + /* Require a launcher */ + if (!j_ptr->tval) + { + msg_print("You have nothing with which to fire."); + return; + } + + /* XXX HACK */ + if (j_ptr->tval == TV_INSTRUMENT) + { + msg_print("You cannot fire with an instrument."); + return; + } + + /* Get the "ammo" (if any) */ + o_ptr = &p_ptr->inventory[INVEN_AMMO]; + + item = INVEN_AMMO; + + /* If nothing correct try to choose from the backpack */ + if ((p_ptr->tval_ammo != o_ptr->tval) || (!o_ptr->k_idx)) + { + /* Require proper missile */ + item_tester_tval = p_ptr->tval_ammo; + + /* Get an item */ + q = "Your quiver is empty. Fire which item? "; + s = "You have nothing to fire."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; + + + /* Access the item */ + o_ptr = get_object(item); + } + + + /* Get a direction (or cancel) */ + if (!get_aim_dir(&dir)) return; + + + /* Get local object */ + q_ptr = &forge; + + /* Obtain a local object */ + object_copy(q_ptr, o_ptr); + + /* Single object */ + q_ptr->number = 1; + + /* Reduce stack and describe */ + inc_stack_size(item, -1); + + /* Break goi/manashield */ + if (p_ptr->invuln) + { + set_invuln(0); + } + if (p_ptr->disrupt_shield) + { + set_disrupt_shield(0); + } + + + /* Sound */ + sound(SOUND_SHOOT); + + + /* Describe the object */ + object_desc(o_name, q_ptr, FALSE, 3); + + /* Find the color and symbol for the object for throwing */ + missile_attr = object_attr(q_ptr); + missile_char = object_char(q_ptr); + + + /* Use the proper number of shots */ + thits = p_ptr->num_fire; + + /* Use a base distance */ + tdis = 10; + + /* Base damage from thrown object plus launcher bonus */ + tdam = damroll(q_ptr->dd, q_ptr->ds) + q_ptr->to_d + j_ptr->to_d; + + /* Actually "fire" the object */ + bonus = (p_ptr->to_h + p_ptr->to_h_ranged + q_ptr->to_h + j_ptr->to_h); + + chance = (p_ptr->skill_thb + (bonus * BTH_PLUS_ADJ)); + if (chance < 5) chance = 5; + + tmul = get_shooter_mult(j_ptr); + + /* Get extra "power" from "extra might" */ + tmul += p_ptr->xtra_might; + + /* Boost the damage */ + tdam *= tmul; + + /* Add in the player damage */ + tdam += p_ptr->to_d_ranged; + + /* Base range */ + tdis = 10 + 5 * tmul; + + + /* Take a (partial) turn */ + energy_use = (100 / thits); + + /* piercing shots ? */ + if (p_ptr->use_piercing_shots) + { + num_pierce = (get_skill(SKILL_COMBAT) / 10) - 1; + num_pierce = (num_pierce < 0) ? 0 : num_pierce; + } + + /* Start at the player */ + by = p_ptr->py; + bx = p_ptr->px; + y = p_ptr->py; + x = p_ptr->px; + + /* Predict the "target" location */ + tx = p_ptr->px + 99 * ddx[dir]; + ty = p_ptr->py + 99 * ddy[dir]; + + /* Check for "target request" */ + if ((dir == 5) && target_okay()) + { + tx = target_col; + ty = target_row; + } + + + /* Hack -- Handle stuff */ + handle_stuff(); + + oldtdam = tdam; + while (TRUE) + { + /* Reset after a piercing shot */ + tdam = oldtdam; + + /* Travel until stopped */ + for (cur_dis = 0; cur_dis <= tdis; ) + { + /* Hack -- Stop at the target */ + if ((y == ty) && (x == tx)) break; + + /* Calculate the new location (see "project()") */ + ny = y; + nx = x; + mmove2(&ny, &nx, by, bx, ty, tx); + + /* Stopped by walls/doors */ + if (!cave_floor_bold(ny, nx)) break; + + /* Advance the distance */ + cur_dis++; + + /* Save the new location */ + x = nx; + y = ny; + + + /* The player can see the (on screen) missile */ + if (panel_contains(y, x) && player_can_see_bold(y, x)) + { + /* Draw, Hilite, Fresh, Pause, Erase */ + print_rel(missile_char, missile_attr, y, x); + move_cursor_relative(y, x); + Term_fresh(); + Term_xtra(TERM_XTRA_DELAY, msec); + lite_spot(y, x); + Term_fresh(); + } + + /* The player cannot see the missile */ + else + { + /* Pause anyway, for consistancy */ + Term_xtra(TERM_XTRA_DELAY, msec); + } + + + /* Monster here, Try to hit it */ + if (cave[y][x].m_idx) + { + cave_type *c_ptr = &cave[y][x]; + + monster_type *m_ptr = &m_list[c_ptr->m_idx]; + monster_race *r_ptr = race_inf(m_ptr); + + /* Check the visibility */ + visible = m_ptr->ml; + + /* Note the collision */ + hit_body = TRUE; + + /* Did we hit it (penalize range) */ + if (test_hit_fire(chance - cur_dis, m_ptr->ac, m_ptr->ml)) + { + bool_ fear = FALSE; + + /* Assume a default death */ + cptr note_dies = " dies."; + + /* Some monsters get "destroyed" */ + if ((r_ptr->flags3 & (RF3_DEMON)) || + (r_ptr->flags3 & (RF3_UNDEAD)) || + (r_ptr->flags2 & (RF2_STUPID)) || + (strchr("Evg", r_ptr->d_char))) + { + /* Special note at death */ + note_dies = " is destroyed."; + } + + + /* Handle unseen monster */ + if (!visible) + { + /* Invisible monster */ + msg_format("The %s finds a mark.", o_name); + } + + /* Handle visible monster */ + else + { + char m_name[80]; + + /* Get "the monster" or "it" */ + monster_desc(m_name, m_ptr, 0); + + /* Message */ + msg_format("The %s hits %s.", o_name, m_name); + + /* Hack -- Track this monster race */ + if (m_ptr->ml) monster_race_track(m_ptr->r_idx, + m_ptr->ego); + + /* Hack -- Track this monster */ + if (m_ptr->ml) health_track(c_ptr->m_idx); + + /* Anger friends */ + { + char m_name[80]; + monster_desc(m_name, m_ptr, 0); + switch (is_friend(m_ptr)) + { + case 1: + { + msg_format("%^s gets angry!", m_name); + change_side(m_ptr); + break; + } + case 0: + { + msg_format("%^s gets angry!", m_name); + m_ptr->status = MSTATUS_NEUTRAL_M; + break; + } + } + } + } + + /* Apply special damage XXX XXX XXX */ + tdam = tot_dam_aux(q_ptr, tdam, m_ptr, &special); + tdam = critical_shot(q_ptr->weight, q_ptr->to_h, tdam, SKILL_ARCHERY); + + /* No negative damage */ + if (tdam < 0) tdam = 0; + + /* Complex message */ + if (wizard) + { + msg_format("You do %d (out of %d) damage.", + tdam, m_ptr->hp); + } + + /* Hit the monster, check for death */ + if (mon_take_hit(c_ptr->m_idx, tdam, &fear, note_dies)) + { + /* Dead monster */ + } + + /* No death */ + else + { + /* Message */ + message_pain(c_ptr->m_idx, tdam); + + if (special) attack_special(m_ptr, special, tdam); + + /* Take note */ + if (fear && m_ptr->ml) + { + char m_name[80]; + + /* Sound */ + sound(SOUND_FLEE); + + /* Get the monster name (or "it") */ + monster_desc(m_name, m_ptr, 0); + + /* Message */ + msg_format("%^s flees in terror!", m_name); + } + } + } + + /* Stop looking */ + break; + } + } + + /* Exploding arrow ? */ + if (q_ptr->pval2 != 0) + { + int rad = 0, dam = + (damroll(q_ptr->dd, q_ptr->ds) + q_ptr->to_d) * 2; + int flag = + PROJECT_STOP | PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL | + PROJECT_JUMP; + switch (q_ptr->sval) + { + case SV_AMMO_LIGHT: + rad = 2; + dam /= 2; + break; + case SV_AMMO_NORMAL: + rad = 3; + break; + case SV_AMMO_HEAVY: + rad = 4; + dam *= 2; + break; + } + + project(0, rad, y, x, dam, q_ptr->pval2, flag); + } + + /* Chance of breakage (during attacks) */ + j = (hit_body ? breakage_chance(q_ptr) : 0); + + /* Break ? */ + if ((q_ptr->pval2 != 0) || (rand_int(100) < j)) + { + breakage = 100; + break; + } + + /* If the ammo doesn't break, it can pierce through */ + if ((num_pierce) && (hit_body) && + (magik(45 + get_skill(SKILL_ARCHERY)))) + { + num_pierce--; + hit_body = FALSE; + + /* If target isn't reached, continue moving to target */ + if ( !((tx < x && x < bx) || (bx < x && x < tx)) && + !((ty < y && y < by) || (by < y && y < ty))) + { + /* Continue moving in same direction if we reached the target */ + int dx = tx - bx; + int dy = ty - by; + tx = x + 99 * dx; + ty = y + 99 * dy; + + /* New base location */ + by = y; + bx = x; + } + + msg_format("The %s pierces through!", o_name); + } + else + break; + } + + /* Drop (or break) near that location */ + drop_near(q_ptr, breakage, y, x); +} + + +/* + * Why is this here? even if it's temporary boost... + * Moved into player_type, hoping it might be useful in future extensions + * -- pelpel + */ +/* int throw_mult = 1; */ + +/* + * Throw an object from the pack or floor. + * + * Note: "unseen" monsters are very hard to hit. + * + * Should throwing a weapon do full damage? Should it allow the magic + * to hit bonus of the weapon to have an effect? Should it ever cause + * the item to be destroyed? Should it do any damage at all? + */ +void do_cmd_throw(void) +{ + int dir, item; + + s32b special = 0; + + int j, y, x, ny, nx, ty, tx; + + int chance, tdam, tdis; + + int mul, div; + + int boulder_add = 0; + int boulder_mult = 0; + + int cur_dis, visible; + + object_type forge; + + object_type *q_ptr; + + object_type *o_ptr; + + bool_ hit_body = FALSE; + + bool_ hit_wall = FALSE; + + byte missile_attr; + + char missile_char; + + char o_name[80]; + + int msec = delay_factor * delay_factor * delay_factor; + + cptr q, s; + + u32b f1, f2, f3, f4, f5, esp; + + + /* Get an item */ + q = "Throw which item? "; + s = "You have nothing to throw."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; + + /* Access the item */ + o_ptr = get_object(item); + + + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* Hack - Cannot throw away 'no drop' cursed items */ + if (cursed_p(o_ptr) && (f4 & TR4_CURSE_NO_DROP)) + { + /* Oops */ + msg_print("Hmmm, you seem to be unable to throw it."); + + /* Nope */ + return; + } + + /* Boulder throwing */ + if ((o_ptr->tval == TV_JUNK) && (o_ptr->sval == SV_BOULDER) && (get_skill(SKILL_BOULDER))) + { + boulder_add = get_skill_scale(SKILL_BOULDER, 80); + boulder_mult = get_skill_scale(SKILL_BOULDER, 6); + } + + /* Get a direction (or cancel) */ + if (!get_aim_dir(&dir)) return; + + /* Break goi/manashield */ + if (p_ptr->invuln) + { + set_invuln(0); + } + if (p_ptr->disrupt_shield) + { + set_disrupt_shield(0); + } + + /* Get local object */ + q_ptr = &forge; + + /* Obtain a local object */ + object_copy(q_ptr, o_ptr); + + /* + * Hack -- If rods or wands are thrown, the total maximum timeout or + * charges need to be allocated between the two stacks. + */ + if (o_ptr->tval == TV_WAND) + { + q_ptr->pval = o_ptr->pval / o_ptr->number; + + if (o_ptr->number > 1) o_ptr->pval -= q_ptr->pval; + } + + /* Single object */ + q_ptr->number = 1; + + /* Reduce stack and describe */ + inc_stack_size(item, -1); + + /* Description */ + object_desc(o_name, q_ptr, FALSE, 3); + + /* Find the color and symbol for the object for throwing */ + missile_attr = object_attr(q_ptr); + missile_char = object_char(q_ptr); + + /* Extract a "distance multiplier" */ + /* Changed for 'launcher' corruption */ + mul = 10 + (2 * (p_ptr->throw_mult - 1)) + (2 * boulder_mult); + + /* Enforce a minimum "weight" of one pound */ + div = ((q_ptr->weight > 10) ? q_ptr->weight : 10); + + /* Hack -- Distance -- Reward strength, penalize weight */ + tdis = (adj_str_blow[p_ptr->stat_ind[A_STR]] + 20) * mul / div; + + /* Max distance of 10-18 */ + if (tdis > mul) tdis = mul; + + /* Hack -- Base damage from thrown object */ + tdam = damroll(q_ptr->dd, q_ptr->ds) + q_ptr->to_d + boulder_add; + tdam *= p_ptr->throw_mult + boulder_mult; + + /* Chance of hitting - adjusted for Weaponmasters -- Gumby */ + chance = (p_ptr->skill_tht + (p_ptr->to_h * BTH_PLUS_ADJ)); + + /* Take a turn */ + energy_use = 100; + + + /* Start at the player */ + y = p_ptr->py; + x = p_ptr->px; + + /* Predict the "target" location */ + tx = p_ptr->px + 99 * ddx[dir]; + ty = p_ptr->py + 99 * ddy[dir]; + + /* Check for "target request" */ + if ((dir == 5) && target_okay()) + { + tx = target_col; + ty = target_row; + } + + + /* Hack -- Handle stuff */ + handle_stuff(); + + + /* Travel until stopped */ + for (cur_dis = 0; cur_dis <= tdis; ) + { + /* Hack -- Stop at the target */ + if ((y == ty) && (x == tx)) break; + + /* Calculate the new location (see "project()") */ + ny = y; + nx = x; + mmove2(&ny, &nx, p_ptr->py, p_ptr->px, ty, tx); + + /* Stopped by walls/doors */ + if (!cave_floor_bold(ny, nx)) + { + hit_wall = TRUE; + break; + } + + /* Advance the distance */ + cur_dis++; + + /* Save the new location */ + x = nx; + y = ny; + + + /* The player can see the (on screen) missile */ + if (panel_contains(y, x) && player_can_see_bold(y, x)) + { + /* Draw, Hilite, Fresh, Pause, Erase */ + print_rel(missile_char, missile_attr, y, x); + move_cursor_relative(y, x); + Term_fresh(); + Term_xtra(TERM_XTRA_DELAY, msec); + lite_spot(y, x); + Term_fresh(); + } + + /* The player cannot see the missile */ + else + { + /* Pause anyway, for consistancy */ + Term_xtra(TERM_XTRA_DELAY, msec); + } + + + /* Monster here, Try to hit it */ + if (cave[y][x].m_idx) + { + cave_type *c_ptr = &cave[y][x]; + + monster_type *m_ptr = &m_list[c_ptr->m_idx]; + monster_race *r_ptr = race_inf(m_ptr); + + /* Check the visibility */ + visible = m_ptr->ml; + + /* Note the collision */ + hit_body = TRUE; + + /* Did we hit it (penalize range) */ + if (test_hit_fire(chance - cur_dis, m_ptr->ac, m_ptr->ml)) + { + bool_ fear = FALSE; + + /* Assume a default death */ + cptr note_dies = " dies."; + + /* Some monsters get "destroyed" */ + if ((r_ptr->flags3 & (RF3_DEMON)) || + (r_ptr->flags3 & (RF3_UNDEAD)) || + (r_ptr->flags2 & (RF2_STUPID)) || + (strchr("Evg", r_ptr->d_char))) + { + /* Special note at death */ + note_dies = " is destroyed."; + } + + + /* Handle unseen monster */ + if (!visible) + { + /* Invisible monster */ + msg_format("The %s finds a mark.", o_name); + } + + /* Handle visible monster */ + else + { + char m_name[80]; + + /* Get "the monster" or "it" */ + monster_desc(m_name, m_ptr, 0); + + /* Message */ + msg_format("The %s hits %s.", o_name, m_name); + + /* Hack -- Track this monster race */ + if (m_ptr->ml) monster_race_track(m_ptr->r_idx, m_ptr->ego); + + /* Hack -- Track this monster */ + if (m_ptr->ml) health_track(c_ptr->m_idx); + } + + /* Apply special damage XXX XXX XXX */ + tdam = tot_dam_aux(q_ptr, tdam, m_ptr, &special); + tdam = critical_shot(q_ptr->weight, q_ptr->to_h, tdam, o_ptr->sval == SV_BOULDER ? SKILL_BOULDER : SKILL_ARCHERY); + + /* No negative damage */ + if (tdam < 0) tdam = 0; + + /* Complex message */ + if (wizard) + { + msg_format("You do %d (out of %d) damage.", + tdam, m_ptr->hp); + } + + /* Hit the monster, check for death */ + if (mon_take_hit(c_ptr->m_idx, tdam, &fear, note_dies)) + { + /* Dead monster */ + } + + /* No death */ + else + { + /* Message */ + message_pain(c_ptr->m_idx, tdam); + + if (special) attack_special(m_ptr, special, tdam); + + /* Anger friends */ + if (!(k_info[q_ptr->k_idx].tval == TV_POTION)) + { + char m_name[80]; + monster_desc(m_name, m_ptr, 0); + switch (is_friend(m_ptr)) + { + case 1: + msg_format("%^s gets angry!", m_name); + change_side(m_ptr); + break; + case 0: + msg_format("%^s gets angry!", m_name); + m_ptr->status = MSTATUS_NEUTRAL_M; + break; + } + } + + /* Take note */ + if (fear && m_ptr->ml) + { + char m_name[80]; + + /* Sound */ + sound(SOUND_FLEE); + + /* Get the monster name (or "it") */ + monster_desc(m_name, m_ptr, 0); + + /* Message */ + msg_format("%^s flees in terror!", m_name); + } + } + } + + /* Stop looking */ + break; + } + } + + /* Chance of breakage (during attacks) */ + j = (hit_body ? breakage_chance(q_ptr) : 0); + + /* Potions smash open */ + if (k_info[q_ptr->k_idx].tval == TV_POTION) + { + if ((hit_body) || (hit_wall) || (randint(100) < j)) + { + /* Message */ + msg_format("The %s shatters!", o_name); + + if (potion_smash_effect(0, y, x, q_ptr->sval)) + { + if (cave[y][x].m_idx) + { + char m_name[80]; + monster_desc(m_name, &m_list[cave[y][x].m_idx], 0); + switch (is_friend(&m_list[cave[y][x].m_idx])) + { + case 1: + msg_format("%^s gets angry!", m_name); + change_side(&m_list[cave[y][x].m_idx]); + break; + case 0: + msg_format("%^s gets angry!", m_name); + m_list[cave[y][x].m_idx].status = MSTATUS_NEUTRAL_M; + break; + } + } + } + + return; + } + else + { + j = 0; + } + } + + /* Drop (or break) near that location */ + drop_near(q_ptr, j, y, x); +} + + +/* + * Throw a boomerang object from the equipement(bow). + * + * Note: "unseen" monsters are very hard to hit. + * + * Should throwing a weapon do full damage? Should it allow the magic + * to hit bonus of the weapon to have an effect? Should it ever cause + * the item to be destroyed? Should it do any damage at all? + */ +void do_cmd_boomerang(void) +{ + int dir; + + int j, y, x, ny, nx, ty, tx; + + int chance, tdam, tdis; + + int mul, div; + + int cur_dis, visible; + + object_type forge; + + object_type *q_ptr; + + object_type *o_ptr; + + bool_ hit_body = FALSE; + + byte missile_attr; + + char missile_char; + + char o_name[80]; + + s32b special = 0; + + int msec = delay_factor * delay_factor * delay_factor; + + + /* Get the "bow" (if any) */ + o_ptr = &p_ptr->inventory[INVEN_BOW]; + + + /* Get a direction (or cancel) */ + if (!get_aim_dir(&dir)) return; + + + /* Get local object */ + q_ptr = &forge; + + /* Obtain a local object */ + object_copy(q_ptr, o_ptr); + + /* Single object */ + q_ptr->number = 1; + + /* Description */ + object_desc(o_name, q_ptr, FALSE, 3); + + /* Find the color and symbol for the object for throwing */ + missile_attr = object_attr(q_ptr); + missile_char = object_char(q_ptr); + + /* Extract a "distance multiplier" */ + /* Changed for 'launcher' corruption */ + mul = 10 + 2 * (p_ptr->throw_mult - 1); + + /* Enforce a minimum "weight" of one pound */ + div = ((q_ptr->weight > 10) ? q_ptr->weight : 10); + + /* Hack -- Distance -- Reward strength, penalize weight */ + tdis = (adj_str_blow[p_ptr->stat_ind[A_STR]] + 20) * mul / div; + + /* Max distance of 10-18 */ + if (tdis > mul) tdis = mul; + + /* Hack -- Base damage from thrown object */ + tdam = damroll(q_ptr->dd, q_ptr->ds) + q_ptr->to_d; + tdam *= p_ptr->throw_mult; + + /* Chance of hitting */ + chance = + (p_ptr->skill_tht + + ((p_ptr->to_h + p_ptr->to_h_ranged) * BTH_PLUS_ADJ)); + + chance += get_skill(SKILL_BOOMERANG); + + /* Take a turn */ + energy_use = 100; + + + /* Start at the player */ + y = p_ptr->py; + x = p_ptr->px; + + /* Predict the "target" location */ + tx = p_ptr->px + 99 * ddx[dir]; + ty = p_ptr->py + 99 * ddy[dir]; + + /* Check for "target request" */ + if ((dir == 5) && target_okay()) + { + tx = target_col; + ty = target_row; + } + + + /* Hack -- Handle stuff */ + handle_stuff(); + + + /* Travel until stopped */ + for (cur_dis = 0; cur_dis <= tdis; ) + { + /* Hack -- Stop at the target */ + if ((y == ty) && (x == tx)) break; + + /* Calculate the new location (see "project()") */ + ny = y; + nx = x; + mmove2(&ny, &nx, p_ptr->py, p_ptr->px, ty, tx); + + /* Stopped by walls/doors */ + if (!cave_floor_bold(ny, nx)) + { + break; + } + + /* Advance the distance */ + cur_dis++; + + /* Save the new location */ + x = nx; + y = ny; + + + /* The player can see the (on screen) missile */ + if (panel_contains(y, x) && player_can_see_bold(y, x)) + { + /* Draw, Hilite, Fresh, Pause, Erase */ + print_rel(missile_char, missile_attr, y, x); + move_cursor_relative(y, x); + Term_fresh(); + Term_xtra(TERM_XTRA_DELAY, msec); + lite_spot(y, x); + Term_fresh(); + } + + /* The player cannot see the missile */ + else + { + /* Pause anyway, for consistancy */ + Term_xtra(TERM_XTRA_DELAY, msec); + } + + + /* Monster here, Try to hit it */ + if (cave[y][x].m_idx) + { + cave_type *c_ptr = &cave[y][x]; + + monster_type *m_ptr = &m_list[c_ptr->m_idx]; + monster_race *r_ptr = race_inf(m_ptr); + + /* Check the visibility */ + visible = m_ptr->ml; + + /* Note the collision */ + hit_body = TRUE; + + /* Did we hit it (penalize range) */ + if (test_hit_fire(chance - cur_dis, m_ptr->ac, m_ptr->ml)) + { + bool_ fear = FALSE; + + /* Assume a default death */ + cptr note_dies = " dies."; + + /* Some monsters get "destroyed" */ + if ((r_ptr->flags3 & (RF3_DEMON)) || + (r_ptr->flags3 & (RF3_UNDEAD)) || + (r_ptr->flags2 & (RF2_STUPID)) || + (strchr("Evg", r_ptr->d_char))) + { + /* Special note at death */ + note_dies = " is destroyed."; + } + + + /* Handle unseen monster */ + if (!visible) + { + /* Invisible monster */ + msg_format("The %s finds a mark.", o_name); + } + + /* Handle visible monster */ + else + { + char m_name[80]; + + /* Get "the monster" or "it" */ + monster_desc(m_name, m_ptr, 0); + + /* Message */ + msg_format("The %s hits %s.", o_name, m_name); + + /* Hack -- Track this monster race */ + if (m_ptr->ml) monster_race_track(m_ptr->r_idx, m_ptr->ego); + + /* Hack -- Track this monster */ + if (m_ptr->ml) health_track(c_ptr->m_idx); + } + + /* Apply special damage XXX XXX XXX */ + tdam = tot_dam_aux(q_ptr, tdam, m_ptr, &special); + tdam = critical_shot(q_ptr->weight, q_ptr->to_h, tdam, SKILL_ARCHERY); + + /* No negative damage */ + if (tdam < 0) tdam = 0; + + /* Complex message */ + if (wizard) + { + msg_format("You do %d (out of %d) damage.", + tdam, m_ptr->hp); + } + + /* Hit the monster, check for death */ + if (mon_take_hit(c_ptr->m_idx, tdam, &fear, note_dies)) + { + /* Dead monster */ + } + + /* No death */ + else + { + /* Message */ + message_pain(c_ptr->m_idx, tdam); + + if (special) attack_special(m_ptr, special, tdam); + + /* Anger friends */ + if (!(k_info[q_ptr->k_idx].tval == TV_POTION)) + { + char m_name[80]; + monster_desc(m_name, m_ptr, 0); + switch (is_friend(m_ptr)) + { + case 1: + msg_format("%^s gets angry!", m_name); + change_side(m_ptr); + break; + case 0: + msg_format("%^s gets angry!", m_name); + m_ptr->status = MSTATUS_NEUTRAL_M; + break; + } + } + + /* Take note */ + if (fear && m_ptr->ml) + { + char m_name[80]; + + /* Sound */ + sound(SOUND_FLEE); + + /* Get the monster name (or "it") */ + monster_desc(m_name, m_ptr, 0); + + /* Message */ + msg_format("%^s flees in terror!", m_name); + } + } + + /* Chance of breakage (during attacks) */ + j = (hit_body ? breakage_chance(o_ptr) : 0); + + /* Break the boomerang */ + if (!(o_ptr->art_name || artifact_p(o_ptr)) && + (rand_int(100) < j)) + { + msg_print(format("Your %s is destroyed.", o_name)); + inc_stack_size_ex(INVEN_BOW, -1, OPTIMIZE, NO_DESCRIBE); + } + } + + /* Stop looking */ + break; + } + } + + /* Travel back to the player */ + for (cur_dis = 0; cur_dis <= tdis; ) + { + /* Hack -- Stop at the target */ + if ((y == p_ptr->py) && (x == p_ptr->px)) break; + + /* Calculate the new location (see "project()") */ + ny = y; + nx = x; + mmove2(&ny, &nx, ty, tx, p_ptr->py, p_ptr->px); + + /* Advance the distance */ + cur_dis++; + + /* Save the new location */ + x = nx; + y = ny; + + + /* The player can see the (on screen) missile */ + if (panel_contains(y, x) && player_can_see_bold(y, x)) + { + /* Draw, Hilite, Fresh, Pause, Erase */ + print_rel(missile_char, missile_attr, y, x); + move_cursor_relative(y, x); + Term_fresh(); + Term_xtra(TERM_XTRA_DELAY, msec); + lite_spot(y, x); + Term_fresh(); + } + + /* The player cannot see the missile */ + else + { + /* Pause anyway, for consistancy */ + Term_xtra(TERM_XTRA_DELAY, msec); + } + } +} + + +/* + * Try to ``walk'' using phase door. + */ +void do_cmd_unwalk() +{ + int dir, y, x, feat; + + cave_type *c_ptr; + + bool_ more = FALSE; + + + if (!get_rep_dir(&dir)) return; + + y = p_ptr->py + ddy[dir]; + x = p_ptr->px + ddx[dir]; + + c_ptr = &cave[y][x]; + feat = c_ptr->feat; + + /* Must have knowledge to know feature XXX XXX */ + if (!(c_ptr->info & (CAVE_MARK))) feat = FEAT_NONE; + + /* Take a turn */ + energy_use = 100; + energy_use *= (p_ptr->wild_mode) ? (5 * (MAX_HGT + MAX_WID) / 2) : 1; + + + /* Allow repeated command */ + if (command_arg) + { + /* Set repeat count */ + command_rep = command_arg - 1; + + /* Redraw the state */ + p_ptr->redraw |= (PR_STATE); + + /* Cancel the arg */ + command_arg = 0; + } + + + /* Attack monsters */ + if (c_ptr->m_idx > 0) + { + /* Attack */ + py_attack(y, x, -1); + } + + /* Exit the area */ + else if ((!dun_level) && (!p_ptr->wild_mode) && + ((x == 0) || (x == cur_wid - 1) || (y == 0) || (y == cur_hgt - 1))) + { + /* Can the player enter the grid? */ + if (player_can_enter(c_ptr->mimic)) + { + /* Hack: move to new area */ + if ((y == 0) && (x == 0)) + { + p_ptr->wilderness_y--; + p_ptr->wilderness_x--; + p_ptr->oldpy = cur_hgt - 2; + p_ptr->oldpx = cur_wid - 2; + ambush_flag = FALSE; + } + + else if ((y == 0) && (x == MAX_WID - 1)) + { + p_ptr->wilderness_y--; + p_ptr->wilderness_x++; + p_ptr->oldpy = cur_hgt - 2; + p_ptr->oldpx = 1; + ambush_flag = FALSE; + } + + else if ((y == MAX_HGT - 1) && (x == 0)) + { + p_ptr->wilderness_y++; + p_ptr->wilderness_x--; + p_ptr->oldpy = 1; + p_ptr->oldpx = cur_wid - 2; + ambush_flag = FALSE; + } + + else if ((y == MAX_HGT - 1) && (x == MAX_WID - 1)) + { + p_ptr->wilderness_y++; + p_ptr->wilderness_x++; + p_ptr->oldpy = 1; + p_ptr->oldpx = 1; + ambush_flag = FALSE; + } + + else if (y == 0) + { + p_ptr->wilderness_y--; + p_ptr->oldpy = cur_hgt - 2; + p_ptr->oldpx = x; + ambush_flag = FALSE; + } + + else if (y == cur_hgt - 1) + { + p_ptr->wilderness_y++; + p_ptr->oldpy = 1; + p_ptr->oldpx = x; + ambush_flag = FALSE; + } + + else if (x == 0) + { + p_ptr->wilderness_x--; + p_ptr->oldpx = cur_wid - 2; + p_ptr->oldpy = y; + ambush_flag = FALSE; + } + + else if (x == cur_wid - 1) + { + p_ptr->wilderness_x++; + p_ptr->oldpx = 1; + p_ptr->oldpy = y; + ambush_flag = FALSE; + } + + p_ptr->leaving = TRUE; + + return; + } + } + + /* Hack -- Ignore weird terrain types. */ + else if (!cave_floor_grid(c_ptr)) + { + teleport_player(10); + } + + /* Enter quests */ + else if (((feat >= FEAT_QUEST_ENTER) && (feat <= FEAT_QUEST_UP)) || + ((feat >= FEAT_LESS) && (feat <= FEAT_MORE))) + { + move_player(dir, always_pickup, TRUE); + more = FALSE; + } + + /* Hack -- Ignore wilderness mofe. */ + else if (p_ptr->wild_mode) + { + /* Chance to not blink right */ + if (magik(15)) + { + do + { + dir = rand_range(1, 9); + } + while (dir == 5); + } + + move_player(dir, always_pickup, TRUE); + } + + /* Walking semantics */ + else + { + teleport_player_directed(10, dir); + } + + /* Cancel repetition unless we can continue */ + if (!more) disturb(0); +} + + +static bool_ tport_vertically(bool_ how) +{ + /* arena or quest -KMW- */ + if ((p_ptr->inside_arena) || (p_ptr->inside_quest)) + { + msg_print("There is no effect."); + return (FALSE); + } + + if (dungeon_flags2 & DF2_NO_EASY_MOVE) + { + msg_print("Some powerful force prevents you from teleporting."); + return FALSE; + } + + /* Go down */ + if (how) + { + if (dun_level >= d_info[dungeon_type].maxdepth) + { + msg_print("The floor is impermeable."); + return (FALSE); + } + + msg_print("You sink through the floor."); + dun_level++; + p_ptr->leaving = TRUE; + } + else + { + if (dun_level < d_info[dungeon_type].mindepth) + { + msg_print("There is nothing above you but air."); + return (FALSE); + } + + msg_print("You rise through the ceiling."); + dun_level--; + p_ptr->leaving = TRUE; + } + + return (TRUE); +} + + +/* + * Do a special ``movement'' action. Meant to be used for ``immovable'' + * characters. + */ +void do_cmd_immovable_special(void) +{ + int i, ii, ij, dir; + + int foo = p_ptr->immov_cntr; + + int lose_sp = 0; + + int lose_hp = 0; + + bool_ did_act = FALSE; + + bool_ did_load = FALSE; + + + if (foo > 1) + { + if (p_ptr->csp > foo / 2) + { + + msg_format("This will drain %d mana points!", foo / 2); + if (!get_check("Proceed? ")) return; + + lose_sp = foo / 2; + + } + else if (p_ptr->chp > foo / 2) + { + + msg_format("Warning: This will drain %d hit points!", foo / 2); + if (!get_check("Proceed? ")) return; + + lose_hp = foo / 2; + + } + else + { + msg_print("You can't use your powers yet."); + return; + } + } + + /* Enter "icky" mode */ + character_icky = TRUE; + + /* Save the screen */ + Term_save(); + + + /* Interact until done */ + while (1) + { + /* Clear screen */ + Term_clear(); + + /* Ask for a choice */ + prt("Do what special action:", 2, 0); + + /* Give some choices */ + prt("(a) Teleport to a specific place.", 4, 5); + prt("(b) Fetch an item.", 5, 5); + prt("(c) Go up 50'", 6, 5); + prt("(d) Go down 50'", 7, 5); + + /* Prompt */ + prt("Command: ", 9, 0); + + /* Prompt */ + i = inkey(); + + /* Done */ + if (i == ESCAPE) break; + + /* Tele-to */ + if (i == 'a') + { + Term_load(); + character_icky = FALSE; + did_load = TRUE; + + if (!tgt_pt(&ii, &ij)) break; + + /* Teleport to the target */ + teleport_player_to(ij, ii); + + did_act = TRUE; + break; + } + + /* Fetch item */ + else if (i == 'b') + { + Term_load(); + character_icky = FALSE; + did_load = TRUE; + + if (!get_aim_dir(&dir)) return; + fetch(dir, p_ptr->lev * 15, FALSE); + py_pickup_floor(always_pickup); + + did_act = TRUE; + break; + } + + /* Move up */ + else if (i == 'c') + { + Term_load(); + character_icky = FALSE; + did_load = TRUE; + + if (!tport_vertically(FALSE)) return; + + did_act = TRUE; + break; + } + + /* Move down */ + else if (i == 'd') + { + Term_load(); + character_icky = FALSE; + did_load = TRUE; + + if (!tport_vertically(TRUE)) return; + + did_act = TRUE; + break; + } + + /* Unknown option */ + else + { + bell(); + } + + } + + /* Check if screen was restored before */ + if (!did_load) + { + /* Restore the screen */ + Term_load(); + + /* Leave "icky" mode */ + character_icky = FALSE; + } + + /* Apply stat losses if something was done */ + if (did_act) + { + p_ptr->immov_cntr += 101 - (p_ptr->lev * 2); + + if (lose_sp) + { + p_ptr->csp -= lose_sp; + p_ptr->redraw |= (PR_MANA); + } + + if (lose_hp) + { + p_ptr->chp -= lose_hp; + p_ptr->redraw |= (PR_HP); + } + + energy_use = 100; + } +} + +/* Can we sacrifice it ? */ +static bool_ item_tester_hook_sacrifiable(object_type *o_ptr) +{ + GOD(GOD_MELKOR) + { + /* Corpses are */ + if (o_ptr->tval == TV_CORPSE && o_ptr->sval == SV_CORPSE_CORPSE) + return (TRUE); + + /* Books without any udun spells */ + if ((o_ptr->tval == TV_BOOK) && udun_in_book(o_ptr->sval, o_ptr->pval) <= 0) + { + return TRUE; + } + } + + /* Assume not */ + return (FALSE); +} + +/* + * Is item eligible for sacrifice to Aule? + */ +static bool_ item_tester_hook_sacrifice_aule(object_type *o_ptr) +{ + /* perhaps restrict this only to metal armour and weapons */ + return (o_ptr->found == OBJ_FOUND_SELFMADE); +} + +/* + * Handle sacrifices to Aule + */ +static void do_cmd_sacrifice_aule() +{ + int item; + + item_tester_hook = item_tester_hook_sacrifice_aule; + if (!get_item(&item, + "Sacrifice which item? ", + "You have nothing to sacrifice.", + USE_INVEN)) + { + return; + } + + /* Increase piety by the value of the item / 10. */ + { + object_type *o_ptr = get_object(item); + s32b delta = object_value(o_ptr) / 10; + + inc_piety(GOD_ALL, delta); + } + + /* Destroy the object */ + inc_stack_size(item, -1); +} + +/* + * Handle sacrifices. + * Grace is increased by value of sacrifice. + */ +void do_cmd_sacrifice(void) +{ + byte on_what = cave[p_ptr->py][p_ptr->px].feat; + + /* Check valididty */ + if ((on_what < FEAT_ALTAR_HEAD) || (on_what > FEAT_ALTAR_TAIL)) + { + show_god_info(FALSE); + return; + } + else + { + int agod = on_what - FEAT_ALTAR_HEAD + 1; + + /* Not worshipping a god ? ahhhh! */ + GOD(GOD_NONE) + { + int i; + + for (i = 0; i < 10; i++) + { + if (deity_info[agod].desc[i] != NULL) + msg_print(deity_info[agod].desc[i]); + } + if (get_check(format("Do you want to worship %s? ", deity_info[agod].name))) + { + follow_god(agod, FALSE); + p_ptr->grace = -200; + inc_piety(p_ptr->pgod, 0); + } + } + else if (p_ptr->pgod == agod) + { + GOD(GOD_MELKOR) + { + /* One can sacrifice some HP for piety or damage */ + if ((p_ptr->mhp > 10) && (p_ptr->chp > 10) && get_check("Do you want to sacrifice a part of yourself? ")) + { + /* 10 HP = 300 * wis piety */ + if (get_check("Do you want to sacrifice for more piety instead of damage? ")) + { + int x = wisdom_scale(6); + if (x < 1) x = 1; + + p_ptr->hp_mod -= 10; + take_hit(10, "self sacrifice to Melkor"); + msg_print("Your life slips away, and Melkor seems happier."); + inc_piety(GOD_MELKOR, x * 300); + p_ptr->update |= (PU_HP); + } + /* 10 HP = +wis damage */ + else + { + take_hit(10, "self sacrifice to Melkor"); + msg_print("Your life slips away, and your arms grow stronger."); + p_ptr->melkor_sacrifice++; + p_ptr->update |= (PU_BONUS | PU_HP); + } + } + else + { + int item; + object_type *o_ptr; + + /* Restrict choices to food */ + item_tester_hook = item_tester_hook_sacrifiable; + + /* Get an item */ + if (!get_item(&item, "Sacrifice which item? ", "You have nothing to sacrifice.", (USE_INVEN))) return; + o_ptr = get_object(item); + + /* Piety for corpses is based on monster level */ + if (o_ptr->tval == TV_CORPSE) + { + inc_piety(GOD_MELKOR, 2 * r_info[o_ptr->pval2].level); + } + + /* In books it depends of the spell levels*/ + if (o_ptr->tval == TV_BOOK) + { + int x = levels_in_book(o_ptr->sval, o_ptr->pval); + + inc_piety(GOD_MELKOR, 2 * x); + } + + /* Remove the item */ + inc_stack_size(item, -1); + } + } + + GOD(GOD_AULE) + { + do_cmd_sacrifice_aule(); + } + + } + } +} + + +/* + * scan_monst -- + * + * Return a list of o_list[] indexes of items of the given monster + */ +bool_ scan_monst(int *items, int *item_num, int m_idx) +{ + int this_o_idx, next_o_idx; + + int num = 0; + + + (*item_num) = 0; + + /* Scan all objects in the grid */ + for (this_o_idx = m_list[m_idx].hold_o_idx; this_o_idx; + this_o_idx = next_o_idx) + { + object_type * o_ptr; + + /* Acquire object */ + o_ptr = &o_list[this_o_idx]; + + /* Acquire next object */ + next_o_idx = o_ptr->next_o_idx; + + /* Accept this item */ + items[num++] = this_o_idx; + + /* XXX Hack -- Enforce limit */ + if (num == 23) break; + } + + /* Number of items */ + (*item_num) = num; + + /* Result */ + return (num != 0); +} + + +/* + * Display a list of the items that the given monster carries. + */ +byte show_monster_inven(int m_idx, int *monst_list) +{ + int i, j, k, l; + + int col, len, lim; + + object_type *o_ptr; + + char o_name[80]; + + char tmp_val[80]; + + int out_index[23]; + + byte out_color[23]; + + char out_desc[23][80]; + + int monst_num; + + + /* Default length */ + len = 79 - 50; + + /* Maximum space allowed for descriptions */ + lim = 79 - 3; + + /* Require space for weight */ + lim -= 9; + + /* Scan for objects on the monster */ + (void)scan_monst(monst_list, &monst_num, m_idx); + + /* Display the p_ptr->inventory */ + for (k = 0, i = 0; i < monst_num; i++) + { + o_ptr = &o_list[monst_list[i]]; + + /* Describe the object */ + object_desc(o_name, o_ptr, TRUE, 3); + + /* Hack -- enforce max length */ + o_name[lim] = '\0'; + + /* Save the index */ + out_index[k] = i; + + /* Acquire p_ptr->inventory color */ + out_color[k] = tval_to_attr[o_ptr->tval & 0x7F]; + + /* Save the object description */ + strcpy(out_desc[k], o_name); + + /* Find the predicted "line length" */ + l = strlen(out_desc[k]) + 5; + + /* Account for the weight */ + l += 9; + + /* Maintain the maximum length */ + if (l > len) len = l; + + /* Advance to next "line" */ + k++; + } + + /* Find the column to start in */ + col = (len > 76) ? 0 : (79 - len); + + /* Output each entry */ + for (j = 0; j < k; j++) + { + /* Get the index */ + i = monst_list[out_index[j]]; + + /* Get the item */ + o_ptr = &o_list[i]; + + /* Clear the line */ + prt("", j + 1, col ? col - 2 : col); + + /* Prepare an index --(-- */ + strnfmt(tmp_val, 80, "%c)", index_to_label(j)); + + /* Clear the line with the (possibly indented) index */ + put_str(tmp_val, j + 1, col); + + /* Display the entry itself */ + c_put_str(out_color[j], out_desc[j], j + 1, col + 3); + + /* Display the weight if needed */ + { + int wgt = o_ptr->weight * o_ptr->number; + strnfmt(tmp_val, 80, "%3d.%1d lb", wgt / 10, wgt % 10); + put_str(tmp_val, j + 1, 71); + } + } + + /* Make a "shadow" below the list (only if needed) */ + if (j && (j < 23)) prt("", j + 1, col ? col - 2 : col); + + return monst_num; +} + + +/* + * Steal an object from a monster + */ +void do_cmd_steal() +{ + int x, y, dir = 0, item = -1, k = -1; + + cave_type *c_ptr; + + monster_type *m_ptr; + + object_type *o_ptr, forge; + + byte num = 0; + + bool_ done = FALSE; + + int monst_list[23]; + + + /* Only works on adjacent monsters */ + if (!get_rep_dir(&dir)) return; + y = p_ptr->py + ddy[dir]; + x = p_ptr->px + ddx[dir]; + c_ptr = &cave[y][x]; + + if (!(c_ptr->m_idx)) + { + msg_print("There is no monster there!"); + return; + } + + m_ptr = &m_list[c_ptr->m_idx]; + + /* There were no non-gold items */ + if (!m_ptr->hold_o_idx) + { + msg_print("That monster has no objects!"); + return; + } + + /* The monster is immune */ + if (r_info[m_ptr->r_idx].flags7 & (RF7_NO_THEFT)) + { + msg_print("The monster is guarding the treasures."); + return; + } + + screen_save(); + + num = show_monster_inven(c_ptr->m_idx, monst_list); + + /* Repeat until done */ + while (!done) + { + char tmp_val[80]; + char which = ' '; + + /* Build the prompt */ + strnfmt(tmp_val, 80, "Choose an item to steal (a-%c) or ESC:", + 'a' - 1 + num); + + /* Show the prompt */ + prt(tmp_val, 0, 0); + + /* Get a key */ + which = inkey(); + + /* Parse it */ + switch (which) + { + case ESCAPE: + { + done = TRUE; + + break; + } + + default: + { + int ver; + + /* Extract "query" setting */ + ver = isupper(which); + which = tolower(which); + + k = islower(which) ? A2I(which) : -1; + if (k < 0 || k >= num) + { + bell(); + + break; + } + + /* Verify the item */ + if (ver && !verify("Try", 0 - monst_list[k])) + { + done = TRUE; + + break; + } + + /* Accept that choice */ + item = monst_list[k]; + done = TRUE; + + break; + } + } + } + + if (item != -1) + { + int chance; + + chance = 40 - p_ptr->stat_ind[A_DEX]; + chance += + o_list[item].weight / (get_skill_scale(SKILL_STEALING, 19) + 1); + chance += get_skill_scale(SKILL_STEALING, 29) + 1; + chance -= (m_ptr->csleep) ? 10 : 0; + chance += m_ptr->level; + + /* Failure check */ + if (rand_int(chance) > 1 + get_skill_scale(SKILL_STEALING, 25)) + { + /* Take a turn */ + energy_use = 100; + + /* Wake up */ + m_ptr->csleep = 0; + + /* Speed up because monsters are ANGRY when you try to thief them */ + m_ptr->mspeed += 5; + + screen_load(); + + msg_print("Oops! The monster is now really *ANGRY*!"); + + return; + } + + /* Reconnect the objects list */ + if (num == 1) m_ptr->hold_o_idx = 0; + else + { + if (k > 0) o_list[monst_list[k - 1]].next_o_idx = monst_list[k + 1]; + if (k + 1 >= num) o_list[monst_list[k - 1]].next_o_idx = 0; + if (k == 0) m_ptr->hold_o_idx = monst_list[k + 1]; + } + + /* Rogues gain some xp */ + if (PRACE_FLAGS(PR1_EASE_STEAL)) + { + s32b max_point; + + /* Max XP gained from stealing */ + max_point = (o_list[item].weight / 2) + (m_ptr->level * 10); + + /* Randomise it a bit, with half a max guaranteed */ + gain_exp((max_point / 2) + (randint(max_point) / 2)); + + /* Allow escape */ + if (get_check("Phase door?")) teleport_player(10); + } + + /* Get the item */ + o_ptr = &forge; + + /* Special handling for gold */ + if (o_list[item].tval == TV_GOLD) + { + /* Collect the gold */ + p_ptr->au += o_list[item].pval; + + /* Redraw gold */ + p_ptr->redraw |= (PR_GOLD); + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + } + else + { + object_copy(o_ptr, &o_list[item]); + + inven_carry(o_ptr, FALSE); + } + + /* Delete it */ + o_list[item].k_idx = 0; + } + + screen_load(); + + /* Take a turn */ + energy_use = 100; +} + + +/* + * Give an item to a monster + */ +void do_cmd_give() +{ + int dir, x, y; + + cave_type *c_ptr; + + cptr q, s; + + int item; + + + /* Get a "repeated" direction */ + if (!get_rep_dir(&dir)) return; + + /* Get requested location */ + y = p_ptr->py + ddy[dir]; + x = p_ptr->px + ddx[dir]; + + /* Get requested grid */ + c_ptr = &cave[y][x]; + + /* No monster in the way */ + if (c_ptr->m_idx == 0) + { + msg_print("There is no monster there."); + return; + } + + /* Get an item */ + q = "What item do you want to offer? "; + s = "You have nothing to offer."; + if (!get_item(&item, q, s, USE_INVEN)) return; + + /* Process hooks if there are any */ + if (!process_hooks(HOOK_GIVE, "(d,d)", c_ptr->m_idx, item)) + { + hook_give_in in = { c_ptr->m_idx, item }; + if (!process_hooks_new(HOOK_GIVE, &in, NULL)) + { + msg_print("The monster does not want your item."); + } + } + + /* Take a turn, even if the offer is declined */ + energy_use = 100; +} + + +/* + * Chat with a monster + */ +void do_cmd_chat() +{ + int dir, x, y; + + cave_type *c_ptr; + + + /* Get a "repeated" direction */ + if (!get_rep_dir(&dir)) return; + + /* Get requested location */ + y = p_ptr->py + ddy[dir]; + x = p_ptr->px + ddx[dir]; + + /* Get requested grid */ + c_ptr = &cave[y][x]; + + /* No monster in the way */ + if (c_ptr->m_idx == 0) + { + msg_print("There is no monster there."); + return; + } + + /* Process hook if there are any */ + if (!process_hooks(HOOK_CHAT, "(d)", c_ptr->m_idx)) + { + msg_print("The monster does not want to chat."); + } + + /* No energy spent */ +} diff --git a/src/cmd3.c b/src/cmd3.c deleted file mode 100644 index 9f4170bc..00000000 --- a/src/cmd3.c +++ /dev/null @@ -1,2333 +0,0 @@ -/* File: cmd3.c */ - -/* Purpose: Inventory commands */ - -/* - * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke - * - * This software may be copied and distributed for educational, research, and - * not for profit purposes provided that this copyright and statement are - * included in all such copies. - */ - -#include "angband.h" - -#include "quark.h" -#include "hooks.h" - -/* - * Display p_ptr->inventory - */ -void do_cmd_inven(void) -{ - char out_val[160]; - - - /* Note that we are in "p_ptr->inventory" mode */ - command_wrk = FALSE; - - /* Save the screen */ - character_icky = TRUE; - Term_save(); - - /* Hack -- show empty slots */ - item_tester_full = TRUE; - - /* Display the p_ptr->inventory */ - show_inven(); - - /* Hack -- hide empty slots */ - item_tester_full = FALSE; - - - { - s32b total_weight = calc_total_weight(); - - strnfmt(out_val, 160, - "Inventory: carrying %ld.%ld pounds (%ld%% of capacity). Command: ", - total_weight / 10, total_weight % 10, - (total_weight * 100) / ((weight_limit()) / 2)); - } - - /* Get a command */ - prt(out_val, 0, 0); - - /* Get a new command */ - command_new = inkey(); - - /* Restore the screen */ - Term_load(); - character_icky = FALSE; - - - /* Process "Escape" */ - if (command_new == ESCAPE) - { - /* Reset stuff */ - command_new = 0; - } - - /* Process normal keys */ - else - { - /* Mega-Hack -- Don't disable keymaps for this key */ - request_command_inven_mode = TRUE; - } -} - - -/* - * Display equipment - */ -void do_cmd_equip(void) -{ - char out_val[160]; - - - /* Note that we are in "equipment" mode */ - command_wrk = TRUE; - - /* Save the screen */ - character_icky = TRUE; - Term_save(); - - /* Hack -- show empty slots */ - item_tester_full = TRUE; - - /* Display the equipment */ - show_equip(); - - /* Hack -- undo the hack above */ - item_tester_full = FALSE; - - /* Build a prompt */ - { - s32b total_weight = calc_total_weight(); - - /* Build a prompt */ - strnfmt(out_val, 160, - "Equipment: carrying %ld.%ld pounds (%ld%% of capacity). Command: ", - total_weight / 10, total_weight % 10, - (total_weight * 100) / ((weight_limit()) / 2)); - } - - /* Get a command */ - prt(out_val, 0, 0); - - /* Get a new command */ - command_new = inkey(); - - /* Restore the screen */ - Term_load(); - character_icky = FALSE; - - - /* Process "Escape" */ - if (command_new == ESCAPE) - { - /* Reset stuff */ - command_new = 0; - } - - /* Process normal keys */ - else - { - /* Mega-Hack -- Don't disable keymaps for this key */ - request_command_inven_mode = TRUE; - } -} - - -/* - * The "wearable" tester - */ -static bool_ item_tester_hook_wear(object_type *o_ptr) -{ - u32b f1, f2, f3, f4, f5, esp; - int slot = wield_slot(o_ptr); - - - /* Extract the flags */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* Only one ultimate at a time */ - if (f4 & TR4_ULTIMATE) - { - int i; - - for (i = INVEN_WIELD; i < INVEN_TOTAL; i++) - { - object_type *q_ptr = &p_ptr->inventory[i]; - - /* Extract the flags */ - object_flags(q_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - if (!q_ptr->k_idx) continue; - - if (f4 & TR4_ULTIMATE) return (FALSE); - } - } - - if ((slot < INVEN_WIELD) || ((p_ptr->body_parts[slot - INVEN_WIELD] == INVEN_WIELD) && (p_ptr->melee_style != SKILL_MASTERY))) - return (FALSE); - - /* Check for a usable slot */ - if (slot >= INVEN_WIELD) return (TRUE); - - /* Assume not wearable */ - return (FALSE); -} - - -bool_ is_slot_ok(int slot) -{ - if ((slot >= INVEN_WIELD) && (slot < INVEN_TOTAL)) - { - return (TRUE); - } - else - { - return (FALSE); - } -} - - -/* - * Wield or wear a single item from the pack or floor - */ -void do_cmd_wield(void) -{ - int item, slot, num = 1; - - object_type forge; - - object_type *q_ptr; - - object_type *o_ptr, *i_ptr; - - cptr act; - - char o_name[80]; - - cptr q, s; - - u32b f1, f2, f3, f4, f5, esp; - - - /* Restrict the choices */ - item_tester_hook = item_tester_hook_wear; - - /* Get an item */ - q = "Wear/Wield which item? "; - s = "You have nothing you can wear or wield."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - /* Get the item */ - o_ptr = get_object(item); - - /* Check the slot */ - slot = wield_slot(o_ptr); - - /* Prevent wielding into a cursed slot */ - if (cursed_p(&p_ptr->inventory[slot])) - { - /* Describe it */ - object_desc(o_name, &p_ptr->inventory[slot], FALSE, 0); - - /* Message */ - msg_format("The %s you are %s appears to be cursed.", - o_name, describe_use(slot)); - - /* Cancel the command */ - return; - } - - if ((cursed_p(o_ptr)) && (wear_confirm) - && (object_known_p(o_ptr) || (o_ptr->ident & (IDENT_SENSE)))) - { - char dummy[512]; - - /* Describe it */ - object_desc(o_name, o_ptr, FALSE, 0); - - strnfmt(dummy, 512, "Really use the %s {cursed}? ", o_name); - if (!(get_check(dummy))) - return; - } - - /* Can we wield */ - if (process_hooks(HOOK_WIELD, "(d)", item)) return; - - /* Extract the flags */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* Two handed weapons can't be wielded with a shield */ - if ((is_slot_ok(slot - INVEN_WIELD + INVEN_ARM)) && - (f4 & TR4_MUST2H) && - (p_ptr->inventory[slot - INVEN_WIELD + INVEN_ARM].k_idx != 0)) - { - object_desc(o_name, o_ptr, FALSE, 0); - msg_format("You cannot wield your %s with a shield.", o_name); - return; - } - - if (is_slot_ok(slot - INVEN_ARM + INVEN_WIELD)) - { - i_ptr = &p_ptr->inventory[slot - INVEN_ARM + INVEN_WIELD]; - - /* Extract the flags */ - object_flags(i_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* Prevent shield from being put on if wielding 2H */ - if ((f4 & TR4_MUST2H) && (i_ptr->k_idx) && - (p_ptr->body_parts[slot - INVEN_WIELD] == INVEN_ARM)) - { - object_desc(o_name, o_ptr, FALSE, 0); - msg_format("You cannot wield your %s with a two-handed weapon.", o_name); - return; - } - - if ((p_ptr->body_parts[slot - INVEN_WIELD] == INVEN_ARM) && - (f4 & TR4_COULD2H)) - { - if (!get_check("Are you sure you want to restrict your fighting? ")) - { - return; - } - } - } - - - /* Extract the flags */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - if ((is_slot_ok(slot - INVEN_WIELD + INVEN_ARM)) && - (p_ptr->inventory[slot - INVEN_WIELD + INVEN_ARM].k_idx != 0) && - (f4 & TR4_COULD2H)) - { - if (!get_check("Are you sure you want to use this weapon with a shield?")) - { - return; - } - } - - /* Can we take off existing item */ - if (slot != INVEN_AMMO) - { - if (p_ptr->inventory[slot].k_idx) - if (process_hooks(HOOK_TAKEOFF, "(d)", slot)) return; - } - else - { - if (p_ptr->inventory[slot].k_idx) - if (!object_similar(&p_ptr->inventory[slot], o_ptr)) - if (process_hooks(HOOK_TAKEOFF, "(d)", slot)) return; - } - - /* Take a turn */ - energy_use = 100; - - /* Get local object */ - q_ptr = &forge; - - /* Obtain local object */ - object_copy(q_ptr, o_ptr); - - if (slot == INVEN_AMMO) num = o_ptr->number; - - /* Modify quantity */ - q_ptr->number = num; - - /* Decrease the item */ - inc_stack_size_ex(item, -num, OPTIMIZE, NO_DESCRIBE); - - /* Access the wield slot */ - o_ptr = &p_ptr->inventory[slot]; - - /* Take off existing item */ - if (slot != INVEN_AMMO) - { - if (o_ptr->k_idx) - { - /* Take off existing item */ - (void)inven_takeoff(slot, 255, FALSE); - } - } - else - { - if (o_ptr->k_idx) - { - if (!object_similar(o_ptr, q_ptr)) - { - /* Take off existing item */ - (void)inven_takeoff(slot, 255, FALSE); - } - else - { - q_ptr->number += o_ptr->number; - } - } - } - - - /* Wear the new stuff */ - object_copy(o_ptr, q_ptr); - - /* Increment the equip counter by hand */ - equip_cnt++; - - /* Where is the item now */ - if (slot == INVEN_WIELD) - { - act = "You are wielding"; - } - else if (( slot == INVEN_BOW ) && (o_ptr->tval == TV_INSTRUMENT)) - { - act = "You are holding"; - } - else if (slot == INVEN_BOW) - { - act = "You are shooting with"; - } - else if (slot == INVEN_LITE) - { - act = "Your light source is"; - } - else if (slot == INVEN_AMMO) - { - act = "In your quiver you have"; - } - else if (slot == INVEN_TOOL) - { - act = "You are using"; - } - else - { - act = "You are wearing"; - } - - /* Describe the result */ - object_desc(o_name, o_ptr, TRUE, 3); - - /* Message */ - msg_format("%s %s (%c).", act, o_name, index_to_label(slot)); - - /* Cursed! */ - if (cursed_p(o_ptr)) - { - /* Warn the player */ - msg_print("Oops! It feels deathly cold!"); - - /* Note the curse */ - o_ptr->ident |= (IDENT_SENSE); - o_ptr->sense = SENSE_CURSED; - } - - /* Take care of item sets */ - if (o_ptr->name1) - { - wield_set(o_ptr->name1, a_info[o_ptr->name1].set, FALSE); - } - - /* Recalculate bonuses */ - p_ptr->update |= (PU_BONUS); - - /* Recalculate torch */ - p_ptr->update |= (PU_TORCH); - - /* Recalculate hitpoint */ - p_ptr->update |= (PU_HP); - - /* Recalculate mana */ - p_ptr->update |= (PU_MANA | PU_SPELLS); - - /* Redraw monster hitpoint */ - p_ptr->redraw |= (PR_MH); - - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); -} - - - -/* - * Take off an item - */ -void do_cmd_takeoff(void) -{ - int item; - - object_type *o_ptr; - - cptr q, s; - - - /* Get an item */ - q = "Take off which item? "; - s = "You are not wearing anything to take off."; - if (!get_item(&item, q, s, (USE_EQUIP))) return; - - /* Get the item */ - o_ptr = get_object(item); - - /* Can we take it off */ - if (process_hooks(HOOK_TAKEOFF, "(d)", item)) return; - - /* Item is cursed */ - if (cursed_p(o_ptr) && (!wizard)) - { - /* Oops */ - msg_print("Hmmm, it seems to be cursed."); - - /* Nope */ - return; - } - - - /* Take a partial turn */ - energy_use = 50; - - /* Take off the item */ - (void)inven_takeoff(item, 255, FALSE); - - /* Recalculate hitpoint */ - p_ptr->update |= (PU_HP); - - p_ptr->redraw |= (PR_MH); -} - - -/* - * Drop an item - */ -void do_cmd_drop(void) -{ - int item, amt = 1; - - object_type *o_ptr; - - u32b f1, f2, f3, f4, f5, esp; - - cptr q, s; - - - /* Get an item */ - q = "Drop which item? "; - s = "You have nothing to drop."; - if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN))) return; - - /* Get the item */ - o_ptr = get_object(item); - - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* Can we drop */ - if (process_hooks(HOOK_DROP, "(d)", item)) return; - - /* Hack -- Cannot remove cursed items */ - if (cursed_p(o_ptr)) - { - if (item >= INVEN_WIELD) - { - /* Oops */ - msg_print("Hmmm, it seems to be cursed."); - - /* Nope */ - return; - } - else - { - if (f4 & TR4_CURSE_NO_DROP) - { - /* Oops */ - msg_print("Hmmm, you seem to be unable to drop it."); - - /* Nope */ - return; - } - } - } - - - /* See how many items */ - if (o_ptr->number > 1) - { - /* Get a quantity */ - amt = get_quantity(NULL, o_ptr->number); - - /* Allow user abort */ - if (amt <= 0) return; - } - - /* Take a partial turn */ - energy_use = 50; - - /* Drop (some of) the item */ - inven_drop(item, amt, p_ptr->py, p_ptr->px, FALSE); -} - - -/* - * Destroy an item - */ -void do_cmd_destroy(void) -{ - int item, amt = 1; - - int old_number; - - bool_ force = FALSE; - - object_type *o_ptr; - - char o_name[80]; - - char out_val[160]; - - cptr q, s; - - u32b f1, f2, f3, f4, f5, esp; - - - /* Hack -- force destruction */ - if (command_arg > 0) force = TRUE; - - - /* Get an item */ - q = "Destroy which item? "; - s = "You have nothing to destroy."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_AUTO))) return; - - /* Get the item */ - o_ptr = get_object(item); - - - /* See how many items */ - if (o_ptr->number > 1) - { - /* Get a quantity */ - amt = get_quantity(NULL, o_ptr->number); - - /* Allow user abort */ - if (amt <= 0) return; - } - - - /* Describe the object */ - old_number = o_ptr->number; - o_ptr->number = amt; - object_desc(o_name, o_ptr, TRUE, 3); - o_ptr->number = old_number; - - /* Verify unless quantity given */ - if (!force) - { - if (!((auto_destroy) && (object_value(o_ptr) < 1))) - { - /* Make a verification */ - strnfmt(out_val, 160, "Really destroy %s? ", o_name); - if (!get_check(out_val)) return; - } - } - - /* Take no time, just like the automatizer */ - energy_use = 0; - - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - if ((f4 & TR4_CURSE_NO_DROP) && cursed_p(o_ptr)) - { - /* Oops */ - msg_print("Hmmm, you seem to be unable to destroy it."); - - /* Nope */ - return; - } - - - /* Artifacts cannot be destroyed */ - if (artifact_p(o_ptr) || o_ptr->art_name) - { - byte feel = SENSE_SPECIAL; - - energy_use = 0; - - /* Message */ - msg_format("You cannot destroy %s.", o_name); - - /* Hack -- Handle icky artifacts */ - if (cursed_p(o_ptr)) feel = SENSE_TERRIBLE; - - /* Hack -- inscribe the artifact */ - o_ptr->sense = feel; - - /* We have "felt" it (again) */ - o_ptr->ident |= (IDENT_SENSE); - - /* Combine the pack */ - p_ptr->notice |= (PN_COMBINE); - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP); - - /* Done */ - return; - } - - /* Message */ - msg_format("You destroy %s.", o_name); - sound(SOUND_DESTITEM); - - /* Create an automatizer rule */ - if (automatizer_create) - { - automatizer_add_rule(o_ptr, TRUE); - } - - /* - * Hack -- If rods or wand are destroyed, the total maximum timeout or - * charges of the stack needs to be reduced, unless all the items are - * being destroyed. -LM- - */ - if ((o_ptr->tval == TV_WAND) && (amt < o_ptr->number)) - { - o_ptr->pval -= o_ptr->pval * amt / o_ptr->number; - } - - /* Eru wont be happy */ - if (f3 & TR3_BLESSED) - inc_piety(GOD_ERU, -10 * k_info[o_ptr->k_idx].level); - - /* Eliminate the item */ - inc_stack_size(item, -amt); -} - - -/* - * Observe an item which has been *identify*-ed - */ -void do_cmd_observe(void) -{ - int item; - - object_type *o_ptr; - - char o_name[80]; - - cptr q, s; - - - /* Get an item */ - q = "Examine which item? "; - s = "You have nothing to examine."; - if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR))) return; - - /* Get the item */ - o_ptr = get_object(item); - - /* Description */ - object_desc(o_name, o_ptr, TRUE, 3); - - /* Describe */ - cmsg_format(TERM_L_BLUE, "%s", o_name); - - /* Describe it fully */ - if (!object_out_desc(o_ptr, NULL, FALSE, TRUE)) msg_print("You see nothing special."); -} - - - -/* - * Remove the inscription from an object - * XXX Mention item (when done)? - */ -void do_cmd_uninscribe(void) -{ - int item; - - object_type *o_ptr; - - cptr q, s; - - - /* Get an item */ - q = "Un-inscribe which item? "; - s = "You have nothing to un-inscribe."; - if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR))) return; - - /* Get the item */ - o_ptr = get_object(item); - - /* Nothing to remove */ - if (!o_ptr->note) - { - msg_print("That item had no inscription to remove."); - return; - } - - /* Message */ - msg_print("Inscription removed."); - - /* Remove the incription */ - o_ptr->note = 0; - - /* Combine the pack */ - p_ptr->notice |= (PN_COMBINE); - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP); -} - - -/* - * Inscribe an object with a comment - */ -void do_cmd_inscribe(void) -{ - int item; - - object_type *o_ptr; - - char o_name[80]; - - char out_val[80]; - - cptr q, s; - - - /* Get an item */ - q = "Inscribe which item? "; - s = "You have nothing to inscribe."; - if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR))) return; - - /* Get the item */ - o_ptr = get_object(item); - - /* Describe the activity */ - object_desc(o_name, o_ptr, TRUE, 3); - - /* Message */ - msg_format("Inscribing %s.", o_name); - msg_print(NULL); - - /* Start with nothing */ - strcpy(out_val, ""); - - /* Use old inscription */ - if (o_ptr->note) - { - /* Start with the old inscription */ - strcpy(out_val, quark_str(o_ptr->note)); - } - - /* Get a new inscription (possibly empty) */ - if (get_string("Inscription: ", out_val, 80)) - { - /* Save the inscription */ - o_ptr->note = quark_add(out_val); - - /* Combine the pack */ - p_ptr->notice |= (PN_COMBINE); - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP); - } -} - - - -/* - * An "item_tester_hook" for refilling lanterns - */ -static bool_ item_tester_refill_lantern(object_type *o_ptr) -{ - /* Flasks of oil are okay */ - if (o_ptr->tval == TV_FLASK) return (TRUE); - - /* Lanterns are okay */ - if ((o_ptr->tval == TV_LITE) && - (o_ptr->sval == SV_LITE_LANTERN)) return (TRUE); - - /* Assume not okay */ - return (FALSE); -} - - -/* - * Refill the players lamp (from the pack or floor) - */ -static void do_cmd_refill_lamp(void) -{ - int item; - - object_type *o_ptr; - object_type *j_ptr; - - cptr q, s; - - - /* Restrict the choices */ - item_tester_hook = item_tester_refill_lantern; - - /* Get an item */ - q = "Refill with which flask? "; - s = "You have no flasks of oil."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - /* Get the item */ - o_ptr = get_object(item); - - /* Take a partial turn */ - energy_use = 50; - - /* Access the lantern */ - j_ptr = &p_ptr->inventory[INVEN_LITE]; - - /* Refuel */ - if (o_ptr->tval == TV_FLASK) - j_ptr->timeout += o_ptr->pval; - else - j_ptr->timeout += o_ptr->timeout; - - /* Message */ - msg_print("You fuel your lamp."); - - /* Comment */ - if (j_ptr->timeout >= FUEL_LAMP) - { - j_ptr->timeout = FUEL_LAMP; - msg_print("Your lamp is full."); - } - - /* Decrease the item stack */ - inc_stack_size(item, -1); - - /* Recalculate torch */ - p_ptr->update |= (PU_TORCH); -} - - -/* - * An "item_tester_hook" for refilling torches - */ -static bool_ item_tester_refill_torch(object_type *o_ptr) -{ - /* Torches are okay */ - if ((o_ptr->tval == TV_LITE) && - (o_ptr->sval == SV_LITE_TORCH)) return (TRUE); - - /* Assume not okay */ - return (FALSE); -} - - -/* - * Refuel the players torch (from the pack or floor) - */ -static void do_cmd_refill_torch(void) -{ - int item; - - object_type *o_ptr; - - object_type *j_ptr; - - cptr q, s; - - - /* Restrict the choices */ - item_tester_hook = item_tester_refill_torch; - - /* Get an item */ - q = "Refuel with which torch? "; - s = "You have no extra torches."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - /* Get the item */ - o_ptr = get_object(item); - - /* Take a partial turn */ - energy_use = 50; - - /* Access the primary torch */ - j_ptr = &p_ptr->inventory[INVEN_LITE]; - - /* Refuel */ - j_ptr->timeout += o_ptr->timeout + 5; - - /* Message */ - msg_print("You combine the torches."); - - /* Over-fuel message */ - if (j_ptr->timeout >= FUEL_TORCH) - { - j_ptr->timeout = FUEL_TORCH; - msg_print("Your torch is fully fueled."); - } - - /* Refuel message */ - else - { - msg_print("Your torch glows more brightly."); - } - - /* Decrease the item stack */ - inc_stack_size(item, -1); - - /* Recalculate torch */ - p_ptr->update |= (PU_TORCH); -} - - -/* - * Refill the players lamp, or restock his torches - */ -void do_cmd_refill(void) -{ - object_type *o_ptr; - - u32b f1, f2, f3, f4, f5, esp; - - - /* Get the light */ - o_ptr = &p_ptr->inventory[INVEN_LITE]; - - /* It is nothing */ - if (o_ptr->tval != TV_LITE) - { - msg_print("You are not wielding a light."); - return; - } - - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - if (f4 & TR4_FUEL_LITE) - { - /* It's a torch */ - if (o_ptr->sval == SV_LITE_TORCH || - o_ptr->sval == SV_LITE_TORCH_EVER) - { - do_cmd_refill_torch(); - } - - /* It's a lamp */ - else if (o_ptr->sval == SV_LITE_LANTERN || - o_ptr->sval == SV_LITE_DWARVEN || - o_ptr->sval == SV_LITE_FEANORIAN) - { - do_cmd_refill_lamp(); - } - } - - /* No torch to refill */ - else - { - msg_print("Your light cannot be refilled."); - } -} - - -/* - * Target command - */ -void do_cmd_target(void) -{ - /* Target set */ - if (target_set(TARGET_KILL)) - { - msg_print("Target Selected."); - } - - /* Target aborted */ - else - { - msg_print("Target Aborted."); - } -} - - - -/* - * Look command - */ -void do_cmd_look(void) -{ - /* Look around */ - if (target_set(TARGET_LOOK)) - { - msg_print("Target Selected."); - } -} - - - -/* - * Allow the player to examine other sectors on the map - */ -void do_cmd_locate(void) -{ - int dir, y1, x1, y2, x2; - int panel_hgt, panel_wid; - char tmp_val[80]; - char out_val[160]; - - - /* Retrieve size of the Angband window */ - Term_get_size(&panel_wid, &panel_hgt); - - /* Calcurate size of the dungeon map area */ - panel_hgt = (panel_hgt - (ROW_MAP + 1)) / 2; - panel_wid = (panel_wid - (COL_MAP + 1)) / 2; - - /* Start at current panel */ - y2 = y1 = panel_row_min; - x2 = x1 = panel_col_min; - - /* Show panels until done */ - while (1) - { - /* Describe the location */ - if ((y2 == y1) && (x2 == x1)) - { - tmp_val[0] = '\0'; - } - else - { - strnfmt(tmp_val, 80, "%s%s of", - ((y2 < y1) ? " North" : (y2 > y1) ? " South" : ""), - ((x2 < x1) ? " West" : (x2 > x1) ? " East" : "")); - } - - /* Prepare to ask which way to look */ - if ((panel_hgt == PANEL_HGT) && (panel_wid == PANEL_WID)) - { - /* Avoid surprising the standard screen users */ - strnfmt(out_val, 160, - "Map sector [%d,%d], which is%s your sector. Direction?", - y2 / panel_hgt, x2 / panel_wid, tmp_val); - } - - /* Big screen */ - else - { - /* Panels are measured by current map area size */ - strnfmt(out_val, 160, - "Map sector [%d(%02d),%d(%02d)], which is%s your sector. Direction?", - y2 / panel_hgt, y2 % panel_hgt, - x2 / panel_wid, x2 % panel_wid, tmp_val); - } - - /* Assume no direction */ - dir = 0; - - /* Get a direction */ - while (!dir) - { - char ch; - - /* Get a command (or cancel) */ - if (!get_com(out_val, &ch)) break; - - /* Extract the action (if any) */ - dir = get_keymap_dir(ch); - - /* Error */ - if (!dir) bell(); - } - - /* No direction */ - if (!dir) break; - - /* Apply the motion */ - if (change_panel(ddy[dir], ddx[dir])) - { - y2 = panel_row_min; - x2 = panel_col_min; - } - } - - /* Recenter the map around the player */ - verify_panel(); - - /* Update stuff */ - p_ptr->update |= (PU_MONSTERS); - - /* Redraw map */ - p_ptr->redraw |= (PR_MAP); - - /* Window stuff */ - p_ptr->window |= (PW_OVERHEAD); - - /* Handle stuff */ - handle_stuff(); -} - - - - - - -/* - * The table of "symbol info" -- each entry is a string of the form - * "X:desc" where "X" is the trigger, and "desc" is the "info". - */ -static cptr ident_info[] = -{ - " :A dark grid", - "!:A potion (or oil)", - "\":An amulet (or necklace)", - "#:A wall (or secret door)", - "$:Treasure (gold or gems)", - "%:A vein (magma or quartz)", - /* "&:unused", */ - "':An open door", - "(:Soft armor", - "):A shield", - "*:A vein with treasure", - "+:A closed door", - ",:Food (or mushroom patch)", - "-:A wand (or rod)", - ".:Floor", - "/:A polearm (Axe/Pike/etc)", - "0:An altar", - "1:Entrance to General Store", - "2:Entrance to Armory", - "3:Entrance to Weaponsmith", - "4:Entrance to Temple", - "5:Entrance to Alchemy shop", - "6:Entrance to Magic store", - "7:Entrance to Black Market", - "8:Entrance to your home", - "9:Entrance to Bookstore", - "::Rubble", - ";:A glyph of warding / explosive rune", - "<:An up staircase", - "=:A ring", - ">:A down staircase", - "?:A scroll", - "@:You", - "A:Angel", - "B:Bird", - "C:Canine", - "D:Ancient Dragon/Wyrm", - "E:Elemental", - "F:Dragon Fly", - "G:Ghost", - "H:Hybrid", - "I:Insect", - "J:Snake", - "K:Killer Beetle", - "L:Lich", - "M:Multi-Headed Reptile", - /* "N:unused", */ - "O:Ogre", - "P:Giant Humanoid", - "Q:Quylthulg (Pulsing Flesh Mound)", - "R:Reptile/Amphibian", - "S:Spider/Scorpion/Tick", - "T:Troll", - "U:Major Demon", - "V:Vampire", - "W:Wight/Wraith/etc", - "X:Xorn/Xaren/etc", - "Y:Yeti", - "Z:Zephyr Hound", - "[:Hard armor", - "\\:A hafted weapon (mace/whip/etc)", - "]:Misc. armor", - "^:A trap", - "_:A staff", - /* "`:unused", */ - "a:Ant", - "b:Bat", - "c:Centipede", - "d:Dragon", - "e:Floating Eye", - "f:Feline", - "g:Golem", - "h:Hobbit/Elf/Dwarf", - "i:Icky Thing", - "j:Jelly", - "k:Kobold", - "l:Louse", - "m:Mold", - "n:Naga", - "o:Orc", - "p:Person/Human", - "q:Quadruped", - "r:Rodent", - "s:Skeleton", - "t:Townsperson", - "u:Minor Demon", - "v:Vortex", - "w:Worm/Worm-Mass", - /* "x:unused", */ - "y:Yeek", - "z:Zombie/Mummy", - "{:A missile (arrow/bolt/shot)", - "|:An edged weapon (sword/dagger/etc)", - "}:A launcher (bow/crossbow/sling)", - "~:A tool (or miscellaneous item)", - NULL -}; - - - -/* - * Sorting hook -- Comp function -- see below - * - * We use "u" to point to array of monster indexes, - * and "v" to select the type of sorting to perform on "u". - */ -static bool_ ang_sort_comp_hook(vptr u, vptr v, int a, int b) -{ - u16b *who = (u16b*)(u); - - u16b *why = (u16b*)(v); - - int w1 = who[a]; - - int w2 = who[b]; - - int z1, z2; - - - /* Sort by player kills */ - if (*why >= 4) - { - /* Extract player kills */ - z1 = r_info[w1].r_pkills; - z2 = r_info[w2].r_pkills; - - /* Compare player kills */ - if (z1 < z2) return (TRUE); - if (z1 > z2) return (FALSE); - } - - - /* Sort by total kills */ - if (*why >= 3) - { - /* Extract total kills */ - z1 = r_info[w1].r_tkills; - z2 = r_info[w2].r_tkills; - - /* Compare total kills */ - if (z1 < z2) return (TRUE); - if (z1 > z2) return (FALSE); - } - - - /* Sort by monster level */ - if (*why >= 2) - { - /* Extract levels */ - z1 = r_info[w1].level; - z2 = r_info[w2].level; - - /* Compare levels */ - if (z1 < z2) return (TRUE); - if (z1 > z2) return (FALSE); - } - - - /* Sort by monster experience */ - if (*why >= 1) - { - /* Extract experience */ - z1 = r_info[w1].mexp; - z2 = r_info[w2].mexp; - - /* Compare experience */ - if (z1 < z2) return (TRUE); - if (z1 > z2) return (FALSE); - } - - - /* Compare indexes */ - return (w1 <= w2); -} - - -/* - * Sorting hook -- Swap function -- see below - * - * We use "u" to point to array of monster indexes, - * and "v" to select the type of sorting to perform. - */ -static void ang_sort_swap_hook(vptr u, vptr v, int a, int b) -{ - u16b *who = (u16b*)(u); - - u16b holder; - - - /* XXX XXX */ - v = v ? v : 0; - - /* Swap */ - holder = who[a]; - who[a] = who[b]; - who[b] = holder; -} - - - -/* - * Hack -- Display the "name" and "attr/chars" of a monster race - */ -static void roff_top(int r_idx) -{ - monster_race *r_ptr = &r_info[r_idx]; - - byte a1, a2; - - char c1, c2; - - - /* Access the chars */ - c1 = r_ptr->d_char; - c2 = r_ptr->x_char; - - /* Access the attrs */ - a1 = r_ptr->d_attr; - a2 = r_ptr->x_attr; - - - /* Clear the top line */ - Term_erase(0, 0, 255); - - /* Reset the cursor */ - Term_gotoxy(0, 0); - - /* A title (use "The" for non-uniques) */ - if (!(r_ptr->flags1 & (RF1_UNIQUE))) - { - Term_addstr( -1, TERM_WHITE, "The "); - } - - /* Dump the name */ - Term_addstr( -1, TERM_WHITE, (r_name + r_ptr->name)); - - /* Append the "standard" attr/char info */ - Term_addstr( -1, TERM_WHITE, " ('"); - Term_addch(a1, c1); - if (use_bigtile && (a1 & 0x80)) Term_addch(255, 255); - Term_addstr( -1, TERM_WHITE, "')"); - - /* Append the "optional" attr/char info */ - Term_addstr( -1, TERM_WHITE, "/('"); - Term_addch(a2, c2); - if (use_bigtile && (a2 & 0x80)) Term_addch(255, 255); - Term_addstr( -1, TERM_WHITE, "'):"); -} - - -/* - * Identify a character, allow recall of monsters - * - * Several "special" responses recall "multiple" monsters: - * ^A (all monsters) - * ^U (all unique monsters) - * ^N (all non-unique monsters) - * ^M (case insensitive name search) - * - * The responses may be sorted in several ways, see below. - * - * Note that the player ghosts are ignored. XXX XXX XXX - */ -void do_cmd_query_symbol(void) -{ - int i, n, r_idx; - - char sym, query; - - char buf[128]; - - - bool_ all = FALSE; - - bool_ uniq = FALSE; - - bool_ norm = FALSE; - - - bool_ name = FALSE; - - char temp[80] = ""; - - - bool_ recall = FALSE; - - - u16b why = 0; - - u16b *who; - - - /* Get a character, or abort */ - if (!get_com("Enter character to be identified, " - "or (Ctrl-A, Ctrl-U, Ctrl-N, Ctrl-M):", &sym)) return; - - /* Find that character info, and describe it */ - for (i = 0; ident_info[i]; ++i) - { - if (sym == ident_info[i][0]) break; - } - - /* Describe */ - if (sym == KTRL('A')) - { - all = TRUE; - strcpy(buf, "Full monster list."); - } - else if (sym == KTRL('U')) - { - all = uniq = TRUE; - strcpy(buf, "Unique monster list."); - } - else if (sym == KTRL('N')) - { - all = norm = TRUE; - strcpy(buf, "Non-unique monster list."); - } - else if (sym == KTRL('M')) - { - all = name = TRUE; - if (!get_string("Name:", temp, 70)) return; - strnfmt(buf, 128, "Monsters with a name \"%s\"", temp); - strlower(temp); - } - else if (ident_info[i]) - { - strnfmt(buf, 128, "%c - %s.", sym, ident_info[i] + 2); - } - else - { - strnfmt(buf, 128, "%c - %s.", sym, "Unknown Symbol"); - } - - /* Display the result */ - prt(buf, 0, 0); - - /* Allocate the "who" array */ - C_MAKE(who, max_r_idx, u16b); - - /* Collect matching monsters */ - for (n = 0, i = 1; i < max_r_idx; i++) - { - monster_race *r_ptr = &r_info[i]; - - /* Nothing to recall */ - if (!cheat_know && !r_ptr->r_sights) continue; - - /* Require non-unique monsters if needed */ - if (norm && (r_ptr->flags1 & (RF1_UNIQUE))) continue; - - /* Require unique monsters if needed */ - if (uniq && !(r_ptr->flags1 & (RF1_UNIQUE))) continue; - - /* Require monsters with the name requested if needed */ - if (name) - { - char mon_name[80]; - - strcpy(mon_name, r_name + r_ptr->name); - strlower(mon_name); - - if (!strstr(mon_name, temp)) continue; - } - - /* Collect "appropriate" monsters */ - if (all || (r_ptr->d_char == sym)) who[n++] = i; - } - - /* Nothing to recall */ - if (!n) - { - /* Free the "who" array */ - C_KILL(who, max_r_idx, u16b); - - return; - } - - - /* Prompt XXX XXX XXX */ - put_str("Recall details? (k/p/y/n): ", 0, 40); - - /* Query */ - query = inkey(); - - /* Restore */ - prt(buf, 0, 0); - - - /* Sort by kills (and level) */ - if (query == 'k') - { - why = 4; - query = 'y'; - } - - /* Sort by level */ - if (query == 'p') - { - why = 2; - query = 'y'; - } - - /* Catch "escape" */ - if (query != 'y') - { - /* Free the "who" array */ - C_KILL(who, max_r_idx, u16b); - - return; - } - - - /* Sort if needed */ - if (why) - { - /* Select the sort method */ - ang_sort_comp = ang_sort_comp_hook; - ang_sort_swap = ang_sort_swap_hook; - - /* Sort the array */ - ang_sort(who, &why, n); - } - - - /* Start at the end */ - i = n - 1; - - /* Scan the monster memory */ - while (1) - { - /* Extract a race */ - r_idx = who[i]; - - /* Hack -- Auto-recall */ - monster_race_track(r_idx, 0); - - /* Hack -- Handle stuff */ - handle_stuff(); - - /* Hack -- Begin the prompt */ - roff_top(r_idx); - - /* Hack -- Complete the prompt */ - Term_addstr( -1, TERM_WHITE, " [(r)ecall, ESC]"); - - /* Interact */ - while (1) - { - /* Recall */ - if (recall) - { - /* Save the screen */ - character_icky = TRUE; - Term_save(); - - /* Recall on screen */ - screen_roff(who[i], 0, 0); - - /* Hack -- Complete the prompt (again) */ - Term_addstr( -1, TERM_WHITE, " [(r)ecall, ESC]"); - } - - /* Command */ - query = inkey(); - - /* Unrecall */ - if (recall) - { - /* Restore */ - Term_load(); - character_icky = FALSE; - } - - /* Normal commands */ - if (query != 'r') break; - - /* Toggle recall */ - recall = !recall; - } - - /* Stop scanning */ - if (query == ESCAPE) break; - - /* Move to "prev" monster */ - if (query == '-') - { - if (++i == n) - { - i = 0; - if (!expand_list) break; - } - } - - /* Move to "next" monster */ - else - { - if (i-- == 0) - { - i = n - 1; - if (!expand_list) break; - } - } - } - - /* Re-display the identity */ - prt(buf, 0, 0); - - /* Free the "who" array */ - C_KILL(who, max_r_idx, u16b); -} - - -/* - * research_mon - * -KMW- - */ -bool_ research_mon() -{ - int i, n, r_idx; - - char sym, query; - - char buf[128]; - - - s16b oldkills; - - byte oldwake; - - bool_ oldcheat; - - - bool_ all = FALSE; - - bool_ uniq = FALSE; - - bool_ norm = FALSE; - - bool_ notpicked; - - - bool_ recall = FALSE; - - u16b why = 0; - - monster_race *r2_ptr; - - u16b *who; - - - /* Hack -- Remember "cheat_know" flag */ - oldcheat = cheat_know; - - - /* Get a character, or abort */ - if (!get_com("Enter character of monster: ", &sym)) return (TRUE); - - /* Allocate the "who" array */ - C_MAKE(who, max_r_idx, u16b); - - /* Find that character info, and describe it */ - for (i = 0; ident_info[i]; ++i) - { - if (sym == ident_info[i][0]) break; - } - - if (ident_info[i]) - { - strnfmt(buf, 128, "%c - %s.", sym, ident_info[i] + 2); - } - else - { - strnfmt(buf, 128, "%c - %s.", sym, "Unknown Symbol"); - } - - /* Display the result */ - prt(buf, 16, 10); - - - /* Collect matching monsters */ - for (n = 0, i = 1; i < max_r_idx; i++) - { - monster_race *r_ptr = &r_info[i]; - - /* Hack -- Force "cheat_know" */ - cheat_know = TRUE; - - /* Nothing to recall */ - if (!cheat_know && !r_ptr->r_sights) continue; - - /* Require non-unique monsters if needed */ - if (norm && (r_ptr->flags1 & (RF1_UNIQUE))) continue; - - /* Require unique monsters if needed */ - if (uniq && !(r_ptr->flags1 & (RF1_UNIQUE))) continue; - - /* Collect "appropriate" monsters */ - if (all || (r_ptr->d_char == sym)) who[n++] = i; - } - - /* Nothing to recall */ - if (!n) - { - /* Free the "who" array */ - C_KILL(who, max_r_idx, u16b); - - /* Restore the "cheat_know" flag */ - cheat_know = oldcheat; - - return (TRUE); - } - - - /* Sort by level */ - why = 2; - query = 'y'; - - /* Sort if needed */ - if (why) - { - /* Select the sort method */ - ang_sort_comp = ang_sort_comp_hook; - ang_sort_swap = ang_sort_swap_hook; - - /* Sort the array */ - ang_sort(who, &why, n); - } - - - /* Start at the end */ - i = n - 1; - - notpicked = TRUE; - - /* Scan the monster memory */ - while (notpicked) - { - /* Extract a race */ - r_idx = who[i]; - - /* Hack -- Auto-recall */ - monster_race_track(r_idx, 0); - - /* Hack -- Handle stuff */ - handle_stuff(); - - /* Hack -- Begin the prompt */ - roff_top(r_idx); - - /* Hack -- Complete the prompt */ - Term_addstr( -1, TERM_WHITE, " [(r)ecall, ESC, space to continue]"); - - /* Interact */ - while (1) - { - /* Recall */ - if (recall) - { - /* Save the screen */ - character_icky = TRUE; - Term_save(); - - /* Recall on screen */ - r2_ptr = &r_info[r_idx]; - - oldkills = r2_ptr->r_tkills; - oldwake = r2_ptr->r_wake; - screen_roff(who[i], 0, 1); - r2_ptr->r_tkills = oldkills; - r2_ptr->r_wake = oldwake; - r2_ptr->r_sights = 1; - cheat_know = oldcheat; - notpicked = FALSE; - break; - - } - - /* Command */ - query = inkey(); - - /* Unrecall */ - if (recall) - { - /* Restore */ - Term_load(); - character_icky = FALSE; - } - - /* Normal commands */ - if (query != 'r') break; - - /* Toggle recall */ - recall = !recall; - } - - /* Stop scanning */ - if (query == ESCAPE) break; - - /* Move to "prev" monster */ - if (query == '-') - { - if (++i == n) - { - i = 0; - if (!expand_list) break; - } - } - - /* Move to "next" monster */ - else - { - if (i-- == 0) - { - i = n - 1; - if (!expand_list) break; - } - } - } - - - /* Re-display the identity */ - /* prt(buf, 5, 5);*/ - - /* Free the "who" array */ - C_KILL(who, max_r_idx, u16b); - - /* Restore the "cheat_know" flag */ - cheat_know = oldcheat; - - return (notpicked); -} - - -/* - * Try to "sense" the grid's mana - */ -bool_ do_cmd_sense_grid_mana() -{ - int chance, i; - - - /* Take (a lot of) time */ - energy_use = 200; - - /* Base chance of success */ - chance = p_ptr->skill_dev; - - /* Confusion hurts skill */ - if (p_ptr->confused) chance = chance / 2; - - /* Hight mana grids are harder */ - chance = chance - (cave[p_ptr->py][p_ptr->px].mana / 10); - - /* Give everyone a (slight) chance */ - if ((chance < USE_DEVICE) && (rand_int(USE_DEVICE - chance + 1) == 0)) - { - chance = USE_DEVICE; - } - - /* Roll for usage */ - if ((chance < USE_DEVICE) || (randint(chance) < USE_DEVICE)) - { - if (flush_failure) flush(); - msg_print("You failed to sense the grid's mana."); - sound(SOUND_FAIL); - return FALSE; - } - - /* Try to give an "average" value */ - i = (101 - p_ptr->skill_dev) / 2; - i = (i < 1) ? 1 : (i > 50) ? 50 : i; - - if (wizard) - { - msg_format("Grid's mana: %d.", cave[p_ptr->py][p_ptr->px].mana); - msg_format("Average grid's mana: %d.", (cave[p_ptr->py][p_ptr->px].mana / i) * i); - } - else - { - msg_format("Average Area's mana: %d", (cave[p_ptr->py][p_ptr->px].mana / i) * i); - } - return TRUE; -} - - -/* - * Calculate the weight of the portable holes - */ -s32b portable_hole_weight(void) -{ - s32b weight, i; - - store_type *st_ptr = &town_info[TOWN_RANDOM].store[STORE_HOME]; - - - /* Sum the objects in the appropriate home */ - for (i = 0, weight = 0; i < st_ptr->stock_num; i++) - { - object_type *o_ptr = &st_ptr->stock[i]; - - weight += (o_ptr->weight * o_ptr->number); - } - - /* Multiply the sum with 1.5 */ - weight = (weight * 3) / 2 + 2; - - return (weight); -} - - -/* - * Calculate and set the weight of the portable holes - */ -void set_portable_hole_weight(void) -{ - s32b weight, i, j; - - /* Calculate the weight of items in home */ - weight = portable_hole_weight(); - - /* Set the weight of portable holes in the shops, ... */ - for (i = 1; i < max_towns; i++) - { - for (j = 0; j < max_st_idx; j++) - { - store_type *st_ptr = &town_info[i].store[j]; - int k; - - for (k = 0; k < st_ptr->stock_num; k++) - { - object_type *o_ptr = &st_ptr->stock[k]; - - if ((o_ptr->tval == TV_TOOL) && - (o_ptr->sval == SV_PORTABLE_HOLE)) - o_ptr->weight = weight; - } - } - } - - /* ... in the object list, ... */ - for (i = 1; i < o_max; i++) - { - object_type *o_ptr = &o_list[i]; - - if ((o_ptr->tval == TV_TOOL) && - (o_ptr->sval == SV_PORTABLE_HOLE)) o_ptr->weight = weight; - } - - /* ... and in the p_ptr->inventory to the appropriate value */ - for (i = 0; i < INVEN_TOTAL; i++) - { - object_type *o_ptr = &p_ptr->inventory[i]; - - /* Skip non-objects */ - if ((o_ptr->tval == TV_TOOL) && - (o_ptr->sval == SV_PORTABLE_HOLE)) o_ptr->weight = weight; - } -} - - -/* - * Use a portable hole - */ -void do_cmd_portable_hole(void) -{ - cave_type *c_ptr = &cave[p_ptr->py][p_ptr->px]; - - int feat, special, town_num; - - /* Is it currently wielded? */ - if (!p_ptr->inventory[INVEN_TOOL].k_idx || - (p_ptr->inventory[INVEN_TOOL].tval != TV_TOOL) || - (p_ptr->inventory[INVEN_TOOL].sval != SV_PORTABLE_HOLE)) - { - /* No, it isn't */ - msg_print("You have to wield a portable hole to use your abilities"); - return; - } - - /* Mega-hack: Saving the old values, and then... */ - feat = c_ptr->feat; - special = c_ptr->special; - town_num = p_ptr->town_num; - - /* ... change the current grid to the home in town #1 */ - /* DG -- use the first random town, since random towns cannot have houses */ - /* - * pelpel -- This doesn't affect LoS, so we can manipulate - * terrain feature without calling cave_set_feat() - */ - c_ptr->feat = FEAT_SHOP; - c_ptr->special = STORE_HOME; - p_ptr->town_num = TOWN_RANDOM; - - /* Now use the portable hole */ - do_cmd_store(); - - /* Mega-hack part II: change the current grid to the original value */ - c_ptr->feat = feat; - c_ptr->special = special; - p_ptr->town_num = town_num; - - set_portable_hole_weight(); - - /* Recalculate bonuses */ - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - p_ptr->update |= (PU_BONUS); -} - - -/* - * Try to add a CLI action. - */ -void cli_add(cptr active, cptr trigger, cptr descr) -{ - s16b num; - cli_comm *cli_ptr, *old_ptr; - - /* Too many macros. */ - if (cli_total >= CLI_MAX) return; - - /* First try to read active as a number. */ - if (strtol(active, 0, 0)) - { - num = strtol(active, 0, 0); - } - /* Then try to read it as a character. */ - else if (strlen(active) == 1) - { - num = active[0]; - } - /* Give up if it doesn't work. */ - else - { - return; - } - - /* Dump the macro. */ - cli_ptr = cli_info + cli_total; - old_ptr = cli_info + cli_total - 1; - - /* - * Trim 's from the ends of a token. This turns '@' into @ and - * ''' into '. This may be the intent of the code in tokenize(), - * but I've left it for lack of comments to back me up. - */ - if (strchr(trigger, '\'')) - { - char temp[80], *t; - cptr s; - for (s = trigger, t = temp; ; s++, t++) - { - /* tokenize() causes each ' to be followed by another character, - * and then another '. Trim the 's here. */ - if (*s == '\'') - { - *t = *(++s); - s++; - } - else - { - *t = *s; - } - if (*t == '\0') break; - } - cli_ptr->comm = string_make(temp); - } - else - { - cli_ptr->comm = string_make(trigger); - } - - /* First try copying everything across. */ - cli_ptr->key = num; - cli_ptr->descrip = string_make(descr); - - /* Take description for the previous record if appropriate. */ - if ((cli_total > 0) && (old_ptr->key == cli_ptr->key) && (cli_ptr->descrip == 0)) - { - cli_ptr->descrip = old_ptr->descrip; - } - - /* Accept the macro. */ - if (cli_ptr->key && cli_ptr->comm && cli_ptr->descrip) cli_total++; -} - - - -/* - * Get a string using CLI completion. - */ -bool_ get_string_cli(cptr prompt, char *buf, int len) -{ - bool_ res; - - - /* Paranoia XXX XXX XXX */ - msg_print(NULL); - - /* Display prompt */ - prt(prompt, 0, 0); - - /* Ask the user for a string */ - askfor_aux_complete = TRUE; - res = askfor_aux(buf, len); - askfor_aux_complete = FALSE; - - /* Clear prompt */ - prt("", 0, 0); - - /* Result */ - return (res); -} - - -/* - * Do a command line command - * - * This is a wrapper around process command to provide a "reverse keymap" - * whereby a set of keypresses is mapped to one. - * - * This is useful because command_cmd is a s16b, and so allows each command a - * unique representation. - * - * See defines.h for a list of the codes used. - */ -void do_cmd_cli(void) -{ - char buff[80]; - - cli_comm *cli_ptr; - - /* Clear the input buffer */ - strcpy(buff, ""); - - /* Accept command */ - if (!get_string_cli("Command: ", buff, 30)) return; - - - /* Analyse the input */ - for (cli_ptr = cli_info; cli_ptr->comm; cli_ptr++) - { - if (!strcmp(buff, cli_ptr->comm)) - { - /* Process the command without keymaps or macros. */ - command_new = cli_ptr->key; - return; - } - } - - msg_format("No such command: %s", buff); -} - - -/* - * Display on-line help for the CLI commands - */ -void do_cmd_cli_help() -{ - int i, j; - - FILE *fff; - - char file_name[1024]; - - - /* Temporary file */ - if (path_temp(file_name, 1024)) return; - - /* Open a new file */ - fff = my_fopen(file_name, "w"); - - for (i = 0, j = -1; i < cli_total; i++) - { - if (j < i - 1) fprintf(fff, "/"); - fprintf(fff, "[[[[[G%s]", cli_info[i].comm); - if (cli_info[i].descrip != cli_info[i + 1].descrip) - { - fprintf(fff, " %s\n", cli_info[i].descrip); - j = i; - } - } - - /* Close the file */ - my_fclose(fff); - - /* Enter "icky" mode */ - character_icky = TRUE; - - /* Save the screen */ - Term_save(); - - /* Display the file contents */ - show_file(file_name, "Command line help", 0, 0); - - /* Restore the screen */ - Term_load(); - - /* Leave "icky" mode */ - character_icky = FALSE; - - /* Remove the file */ - fd_kill(file_name); -} - - -/* - * Dump screen shot in HTML - */ -void do_cmd_html_dump() -{ - char tmp_val[81]; - bool_ html = TRUE; - term_win *save; - - /* Save the screen */ - save = Term_save_to(); - - if (wizard && get_check("WIZARD MODE: Do an help file dump?")) - html = FALSE; - - /* Ask for a file */ - if (html) - { - strcpy(tmp_val, "dummy.htm"); - if (!get_string("File(you can post it to http://angband.oook.cz/): ", tmp_val, 80)) - { - /* Now restore the screen to initial state */ - Term_load_from(save, TRUE); - Term_fresh(); - return; - } - } - else - { - strcpy(tmp_val, "dummy.txt"); - if (!get_string("File: ", tmp_val, 80)) - { - /* Now restore the screen to initial state */ - Term_load_from(save, TRUE); - Term_fresh(); - return; - } - } - - /* Now restore the screen to dump it */ - Term_load_from(save, TRUE); - - if (html) - html_screenshot(tmp_val); - else - help_file_screenshot(tmp_val); - - Term_erase(0, 0, 255); - msg_print("Dump saved."); - Term_fresh(); - fix_message(); -} diff --git a/src/cmd3.cc b/src/cmd3.cc new file mode 100644 index 00000000..6b618cb8 --- /dev/null +++ b/src/cmd3.cc @@ -0,0 +1,2267 @@ +/* File: cmd3.c */ + +/* Purpose: Inventory commands */ + +/* + * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke + * + * This software may be copied and distributed for educational, research, and + * not for profit purposes provided that this copyright and statement are + * included in all such copies. + */ + +#include "angband.h" + +#include "quark.h" +#include "hooks.h" + +#include +#include +#include + +/* + * Display p_ptr->inventory + */ +void do_cmd_inven(void) +{ + char out_val[160]; + + + /* Note that we are in "p_ptr->inventory" mode */ + command_wrk = FALSE; + + /* Save the screen */ + character_icky = TRUE; + Term_save(); + + /* Hack -- show empty slots */ + item_tester_full = TRUE; + + /* Display the p_ptr->inventory */ + show_inven(); + + /* Hack -- hide empty slots */ + item_tester_full = FALSE; + + + { + s32b total_weight = calc_total_weight(); + + strnfmt(out_val, 160, + "Inventory: carrying %ld.%ld pounds (%ld%% of capacity). Command: ", + total_weight / 10, total_weight % 10, + (total_weight * 100) / ((weight_limit()) / 2)); + } + + /* Get a command */ + prt(out_val, 0, 0); + + /* Get a new command */ + command_new = inkey(); + + /* Restore the screen */ + Term_load(); + character_icky = FALSE; + + + /* Process "Escape" */ + if (command_new == ESCAPE) + { + /* Reset stuff */ + command_new = 0; + } + + /* Process normal keys */ + else + { + /* Mega-Hack -- Don't disable keymaps for this key */ + request_command_inven_mode = TRUE; + } +} + + +/* + * Display equipment + */ +void do_cmd_equip(void) +{ + char out_val[160]; + + + /* Note that we are in "equipment" mode */ + command_wrk = TRUE; + + /* Save the screen */ + character_icky = TRUE; + Term_save(); + + /* Hack -- show empty slots */ + item_tester_full = TRUE; + + /* Display the equipment */ + show_equip(); + + /* Hack -- undo the hack above */ + item_tester_full = FALSE; + + /* Build a prompt */ + { + s32b total_weight = calc_total_weight(); + + /* Build a prompt */ + strnfmt(out_val, 160, + "Equipment: carrying %ld.%ld pounds (%ld%% of capacity). Command: ", + total_weight / 10, total_weight % 10, + (total_weight * 100) / ((weight_limit()) / 2)); + } + + /* Get a command */ + prt(out_val, 0, 0); + + /* Get a new command */ + command_new = inkey(); + + /* Restore the screen */ + Term_load(); + character_icky = FALSE; + + + /* Process "Escape" */ + if (command_new == ESCAPE) + { + /* Reset stuff */ + command_new = 0; + } + + /* Process normal keys */ + else + { + /* Mega-Hack -- Don't disable keymaps for this key */ + request_command_inven_mode = TRUE; + } +} + + +/* + * The "wearable" tester + */ +static bool_ item_tester_hook_wear(object_type *o_ptr) +{ + u32b f1, f2, f3, f4, f5, esp; + int slot = wield_slot(o_ptr); + + + /* Extract the flags */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* Only one ultimate at a time */ + if (f4 & TR4_ULTIMATE) + { + int i; + + for (i = INVEN_WIELD; i < INVEN_TOTAL; i++) + { + object_type *q_ptr = &p_ptr->inventory[i]; + + /* Extract the flags */ + object_flags(q_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + if (!q_ptr->k_idx) continue; + + if (f4 & TR4_ULTIMATE) return (FALSE); + } + } + + if ((slot < INVEN_WIELD) || ((p_ptr->body_parts[slot - INVEN_WIELD] == INVEN_WIELD) && (p_ptr->melee_style != SKILL_MASTERY))) + return (FALSE); + + /* Check for a usable slot */ + if (slot >= INVEN_WIELD) return (TRUE); + + /* Assume not wearable */ + return (FALSE); +} + + +bool_ is_slot_ok(int slot) +{ + if ((slot >= INVEN_WIELD) && (slot < INVEN_TOTAL)) + { + return (TRUE); + } + else + { + return (FALSE); + } +} + + +/* + * Wield or wear a single item from the pack or floor + */ +void do_cmd_wield(void) +{ + int item, slot, num = 1; + + object_type forge; + + object_type *q_ptr; + + object_type *o_ptr, *i_ptr; + + cptr act; + + char o_name[80]; + + cptr q, s; + + u32b f1, f2, f3, f4, f5, esp; + + + /* Restrict the choices */ + item_tester_hook = item_tester_hook_wear; + + /* Get an item */ + q = "Wear/Wield which item? "; + s = "You have nothing you can wear or wield."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; + + /* Get the item */ + o_ptr = get_object(item); + + /* Check the slot */ + slot = wield_slot(o_ptr); + + /* Prevent wielding into a cursed slot */ + if (cursed_p(&p_ptr->inventory[slot])) + { + /* Describe it */ + object_desc(o_name, &p_ptr->inventory[slot], FALSE, 0); + + /* Message */ + msg_format("The %s you are %s appears to be cursed.", + o_name, describe_use(slot)); + + /* Cancel the command */ + return; + } + + if ((cursed_p(o_ptr)) && (wear_confirm) + && (object_known_p(o_ptr) || (o_ptr->ident & (IDENT_SENSE)))) + { + char dummy[512]; + + /* Describe it */ + object_desc(o_name, o_ptr, FALSE, 0); + + strnfmt(dummy, 512, "Really use the %s {cursed}? ", o_name); + if (!(get_check(dummy))) + return; + } + + /* Can we wield */ + if (process_hooks(HOOK_WIELD, "(d)", item)) return; + + /* Extract the flags */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* Two handed weapons can't be wielded with a shield */ + if ((is_slot_ok(slot - INVEN_WIELD + INVEN_ARM)) && + (f4 & TR4_MUST2H) && + (p_ptr->inventory[slot - INVEN_WIELD + INVEN_ARM].k_idx != 0)) + { + object_desc(o_name, o_ptr, FALSE, 0); + msg_format("You cannot wield your %s with a shield.", o_name); + return; + } + + if (is_slot_ok(slot - INVEN_ARM + INVEN_WIELD)) + { + i_ptr = &p_ptr->inventory[slot - INVEN_ARM + INVEN_WIELD]; + + /* Extract the flags */ + object_flags(i_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* Prevent shield from being put on if wielding 2H */ + if ((f4 & TR4_MUST2H) && (i_ptr->k_idx) && + (p_ptr->body_parts[slot - INVEN_WIELD] == INVEN_ARM)) + { + object_desc(o_name, o_ptr, FALSE, 0); + msg_format("You cannot wield your %s with a two-handed weapon.", o_name); + return; + } + + if ((p_ptr->body_parts[slot - INVEN_WIELD] == INVEN_ARM) && + (f4 & TR4_COULD2H)) + { + if (!get_check("Are you sure you want to restrict your fighting? ")) + { + return; + } + } + } + + + /* Extract the flags */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + if ((is_slot_ok(slot - INVEN_WIELD + INVEN_ARM)) && + (p_ptr->inventory[slot - INVEN_WIELD + INVEN_ARM].k_idx != 0) && + (f4 & TR4_COULD2H)) + { + if (!get_check("Are you sure you want to use this weapon with a shield?")) + { + return; + } + } + + /* Can we take off existing item */ + if (slot != INVEN_AMMO) + { + if (p_ptr->inventory[slot].k_idx) + if (process_hooks(HOOK_TAKEOFF, "(d)", slot)) return; + } + else + { + if (p_ptr->inventory[slot].k_idx) + if (!object_similar(&p_ptr->inventory[slot], o_ptr)) + if (process_hooks(HOOK_TAKEOFF, "(d)", slot)) return; + } + + /* Take a turn */ + energy_use = 100; + + /* Get local object */ + q_ptr = &forge; + + /* Obtain local object */ + object_copy(q_ptr, o_ptr); + + if (slot == INVEN_AMMO) num = o_ptr->number; + + /* Modify quantity */ + q_ptr->number = num; + + /* Decrease the item */ + inc_stack_size_ex(item, -num, OPTIMIZE, NO_DESCRIBE); + + /* Access the wield slot */ + o_ptr = &p_ptr->inventory[slot]; + + /* Take off existing item */ + if (slot != INVEN_AMMO) + { + if (o_ptr->k_idx) + { + /* Take off existing item */ + (void)inven_takeoff(slot, 255, FALSE); + } + } + else + { + if (o_ptr->k_idx) + { + if (!object_similar(o_ptr, q_ptr)) + { + /* Take off existing item */ + (void)inven_takeoff(slot, 255, FALSE); + } + else + { + q_ptr->number += o_ptr->number; + } + } + } + + + /* Wear the new stuff */ + object_copy(o_ptr, q_ptr); + + /* Increment the equip counter by hand */ + equip_cnt++; + + /* Where is the item now */ + if (slot == INVEN_WIELD) + { + act = "You are wielding"; + } + else if (( slot == INVEN_BOW ) && (o_ptr->tval == TV_INSTRUMENT)) + { + act = "You are holding"; + } + else if (slot == INVEN_BOW) + { + act = "You are shooting with"; + } + else if (slot == INVEN_LITE) + { + act = "Your light source is"; + } + else if (slot == INVEN_AMMO) + { + act = "In your quiver you have"; + } + else if (slot == INVEN_TOOL) + { + act = "You are using"; + } + else + { + act = "You are wearing"; + } + + /* Describe the result */ + object_desc(o_name, o_ptr, TRUE, 3); + + /* Message */ + msg_format("%s %s (%c).", act, o_name, index_to_label(slot)); + + /* Cursed! */ + if (cursed_p(o_ptr)) + { + /* Warn the player */ + msg_print("Oops! It feels deathly cold!"); + + /* Note the curse */ + o_ptr->ident |= (IDENT_SENSE); + o_ptr->sense = SENSE_CURSED; + } + + /* Take care of item sets */ + if (o_ptr->name1) + { + wield_set(o_ptr->name1, a_info[o_ptr->name1].set, FALSE); + } + + /* Recalculate bonuses */ + p_ptr->update |= (PU_BONUS); + + /* Recalculate torch */ + p_ptr->update |= (PU_TORCH); + + /* Recalculate hitpoint */ + p_ptr->update |= (PU_HP); + + /* Recalculate mana */ + p_ptr->update |= (PU_MANA | PU_SPELLS); + + /* Redraw monster hitpoint */ + p_ptr->redraw |= (PR_MH); + + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); +} + + + +/* + * Take off an item + */ +void do_cmd_takeoff(void) +{ + int item; + + object_type *o_ptr; + + cptr q, s; + + + /* Get an item */ + q = "Take off which item? "; + s = "You are not wearing anything to take off."; + if (!get_item(&item, q, s, (USE_EQUIP))) return; + + /* Get the item */ + o_ptr = get_object(item); + + /* Can we take it off */ + if (process_hooks(HOOK_TAKEOFF, "(d)", item)) return; + + /* Item is cursed */ + if (cursed_p(o_ptr) && (!wizard)) + { + /* Oops */ + msg_print("Hmmm, it seems to be cursed."); + + /* Nope */ + return; + } + + + /* Take a partial turn */ + energy_use = 50; + + /* Take off the item */ + (void)inven_takeoff(item, 255, FALSE); + + /* Recalculate hitpoint */ + p_ptr->update |= (PU_HP); + + p_ptr->redraw |= (PR_MH); +} + + +/* + * Drop an item + */ +void do_cmd_drop(void) +{ + int item, amt = 1; + + object_type *o_ptr; + + u32b f1, f2, f3, f4, f5, esp; + + cptr q, s; + + + /* Get an item */ + q = "Drop which item? "; + s = "You have nothing to drop."; + if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN))) return; + + /* Get the item */ + o_ptr = get_object(item); + + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* Can we drop */ + if (process_hooks(HOOK_DROP, "(d)", item)) return; + + /* Hack -- Cannot remove cursed items */ + if (cursed_p(o_ptr)) + { + if (item >= INVEN_WIELD) + { + /* Oops */ + msg_print("Hmmm, it seems to be cursed."); + + /* Nope */ + return; + } + else + { + if (f4 & TR4_CURSE_NO_DROP) + { + /* Oops */ + msg_print("Hmmm, you seem to be unable to drop it."); + + /* Nope */ + return; + } + } + } + + + /* See how many items */ + if (o_ptr->number > 1) + { + /* Get a quantity */ + amt = get_quantity(NULL, o_ptr->number); + + /* Allow user abort */ + if (amt <= 0) return; + } + + /* Take a partial turn */ + energy_use = 50; + + /* Drop (some of) the item */ + inven_drop(item, amt, p_ptr->py, p_ptr->px, FALSE); +} + + +/* + * Destroy an item + */ +void do_cmd_destroy(void) +{ + int item, amt = 1; + + int old_number; + + bool_ force = FALSE; + + object_type *o_ptr; + + char o_name[80]; + + char out_val[160]; + + cptr q, s; + + u32b f1, f2, f3, f4, f5, esp; + + + /* Hack -- force destruction */ + if (command_arg > 0) force = TRUE; + + + /* Get an item */ + q = "Destroy which item? "; + s = "You have nothing to destroy."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_AUTO))) return; + + /* Get the item */ + o_ptr = get_object(item); + + + /* See how many items */ + if (o_ptr->number > 1) + { + /* Get a quantity */ + amt = get_quantity(NULL, o_ptr->number); + + /* Allow user abort */ + if (amt <= 0) return; + } + + + /* Describe the object */ + old_number = o_ptr->number; + o_ptr->number = amt; + object_desc(o_name, o_ptr, TRUE, 3); + o_ptr->number = old_number; + + /* Verify unless quantity given */ + if (!force) + { + if (!((auto_destroy) && (object_value(o_ptr) < 1))) + { + /* Make a verification */ + strnfmt(out_val, 160, "Really destroy %s? ", o_name); + if (!get_check(out_val)) return; + } + } + + /* Take no time, just like the automatizer */ + energy_use = 0; + + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + if ((f4 & TR4_CURSE_NO_DROP) && cursed_p(o_ptr)) + { + /* Oops */ + msg_print("Hmmm, you seem to be unable to destroy it."); + + /* Nope */ + return; + } + + + /* Artifacts cannot be destroyed */ + if (artifact_p(o_ptr) || o_ptr->art_name) + { + byte feel = SENSE_SPECIAL; + + energy_use = 0; + + /* Message */ + msg_format("You cannot destroy %s.", o_name); + + /* Hack -- Handle icky artifacts */ + if (cursed_p(o_ptr)) feel = SENSE_TERRIBLE; + + /* Hack -- inscribe the artifact */ + o_ptr->sense = feel; + + /* We have "felt" it (again) */ + o_ptr->ident |= (IDENT_SENSE); + + /* Combine the pack */ + p_ptr->notice |= (PN_COMBINE); + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP); + + /* Done */ + return; + } + + /* Message */ + msg_format("You destroy %s.", o_name); + sound(SOUND_DESTITEM); + + /* Create an automatizer rule */ + if (automatizer_create) + { + automatizer_add_rule(o_ptr, TRUE); + } + + /* + * Hack -- If rods or wand are destroyed, the total maximum timeout or + * charges of the stack needs to be reduced, unless all the items are + * being destroyed. -LM- + */ + if ((o_ptr->tval == TV_WAND) && (amt < o_ptr->number)) + { + o_ptr->pval -= o_ptr->pval * amt / o_ptr->number; + } + + /* Eru wont be happy */ + if (f3 & TR3_BLESSED) + inc_piety(GOD_ERU, -10 * k_info[o_ptr->k_idx].level); + + /* Eliminate the item */ + inc_stack_size(item, -amt); +} + + +/* + * Observe an item which has been *identify*-ed + */ +void do_cmd_observe(void) +{ + int item; + + object_type *o_ptr; + + char o_name[80]; + + cptr q, s; + + + /* Get an item */ + q = "Examine which item? "; + s = "You have nothing to examine."; + if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR))) return; + + /* Get the item */ + o_ptr = get_object(item); + + /* Description */ + object_desc(o_name, o_ptr, TRUE, 3); + + /* Describe */ + cmsg_format(TERM_L_BLUE, "%s", o_name); + + /* Describe it fully */ + if (!object_out_desc(o_ptr, NULL, FALSE, TRUE)) msg_print("You see nothing special."); +} + + + +/* + * Remove the inscription from an object + * XXX Mention item (when done)? + */ +void do_cmd_uninscribe(void) +{ + int item; + + object_type *o_ptr; + + cptr q, s; + + + /* Get an item */ + q = "Un-inscribe which item? "; + s = "You have nothing to un-inscribe."; + if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR))) return; + + /* Get the item */ + o_ptr = get_object(item); + + /* Nothing to remove */ + if (!o_ptr->note) + { + msg_print("That item had no inscription to remove."); + return; + } + + /* Message */ + msg_print("Inscription removed."); + + /* Remove the incription */ + o_ptr->note = 0; + + /* Combine the pack */ + p_ptr->notice |= (PN_COMBINE); + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP); +} + + +/* + * Inscribe an object with a comment + */ +void do_cmd_inscribe(void) +{ + int item; + + object_type *o_ptr; + + char o_name[80]; + + char out_val[80]; + + cptr q, s; + + + /* Get an item */ + q = "Inscribe which item? "; + s = "You have nothing to inscribe."; + if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN | USE_FLOOR))) return; + + /* Get the item */ + o_ptr = get_object(item); + + /* Describe the activity */ + object_desc(o_name, o_ptr, TRUE, 3); + + /* Message */ + msg_format("Inscribing %s.", o_name); + msg_print(NULL); + + /* Start with nothing */ + strcpy(out_val, ""); + + /* Use old inscription */ + if (o_ptr->note) + { + /* Start with the old inscription */ + strcpy(out_val, quark_str(o_ptr->note)); + } + + /* Get a new inscription (possibly empty) */ + if (get_string("Inscription: ", out_val, 80)) + { + /* Save the inscription */ + o_ptr->note = quark_add(out_val); + + /* Combine the pack */ + p_ptr->notice |= (PN_COMBINE); + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP); + } +} + + + +/* + * An "item_tester_hook" for refilling lanterns + */ +static bool_ item_tester_refill_lantern(object_type *o_ptr) +{ + /* Flasks of oil are okay */ + if (o_ptr->tval == TV_FLASK) return (TRUE); + + /* Lanterns are okay */ + if ((o_ptr->tval == TV_LITE) && + (o_ptr->sval == SV_LITE_LANTERN)) return (TRUE); + + /* Assume not okay */ + return (FALSE); +} + + +/* + * Refill the players lamp (from the pack or floor) + */ +static void do_cmd_refill_lamp(void) +{ + int item; + + object_type *o_ptr; + object_type *j_ptr; + + cptr q, s; + + + /* Restrict the choices */ + item_tester_hook = item_tester_refill_lantern; + + /* Get an item */ + q = "Refill with which flask? "; + s = "You have no flasks of oil."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; + + /* Get the item */ + o_ptr = get_object(item); + + /* Take a partial turn */ + energy_use = 50; + + /* Access the lantern */ + j_ptr = &p_ptr->inventory[INVEN_LITE]; + + /* Refuel */ + if (o_ptr->tval == TV_FLASK) + j_ptr->timeout += o_ptr->pval; + else + j_ptr->timeout += o_ptr->timeout; + + /* Message */ + msg_print("You fuel your lamp."); + + /* Comment */ + if (j_ptr->timeout >= FUEL_LAMP) + { + j_ptr->timeout = FUEL_LAMP; + msg_print("Your lamp is full."); + } + + /* Decrease the item stack */ + inc_stack_size(item, -1); + + /* Recalculate torch */ + p_ptr->update |= (PU_TORCH); +} + + +/* + * An "item_tester_hook" for refilling torches + */ +static bool_ item_tester_refill_torch(object_type *o_ptr) +{ + /* Torches are okay */ + if ((o_ptr->tval == TV_LITE) && + (o_ptr->sval == SV_LITE_TORCH)) return (TRUE); + + /* Assume not okay */ + return (FALSE); +} + + +/* + * Refuel the players torch (from the pack or floor) + */ +static void do_cmd_refill_torch(void) +{ + int item; + + object_type *o_ptr; + + object_type *j_ptr; + + cptr q, s; + + + /* Restrict the choices */ + item_tester_hook = item_tester_refill_torch; + + /* Get an item */ + q = "Refuel with which torch? "; + s = "You have no extra torches."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; + + /* Get the item */ + o_ptr = get_object(item); + + /* Take a partial turn */ + energy_use = 50; + + /* Access the primary torch */ + j_ptr = &p_ptr->inventory[INVEN_LITE]; + + /* Refuel */ + j_ptr->timeout += o_ptr->timeout + 5; + + /* Message */ + msg_print("You combine the torches."); + + /* Over-fuel message */ + if (j_ptr->timeout >= FUEL_TORCH) + { + j_ptr->timeout = FUEL_TORCH; + msg_print("Your torch is fully fueled."); + } + + /* Refuel message */ + else + { + msg_print("Your torch glows more brightly."); + } + + /* Decrease the item stack */ + inc_stack_size(item, -1); + + /* Recalculate torch */ + p_ptr->update |= (PU_TORCH); +} + + +/* + * Refill the players lamp, or restock his torches + */ +void do_cmd_refill(void) +{ + object_type *o_ptr; + + u32b f1, f2, f3, f4, f5, esp; + + + /* Get the light */ + o_ptr = &p_ptr->inventory[INVEN_LITE]; + + /* It is nothing */ + if (o_ptr->tval != TV_LITE) + { + msg_print("You are not wielding a light."); + return; + } + + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + if (f4 & TR4_FUEL_LITE) + { + /* It's a torch */ + if (o_ptr->sval == SV_LITE_TORCH || + o_ptr->sval == SV_LITE_TORCH_EVER) + { + do_cmd_refill_torch(); + } + + /* It's a lamp */ + else if (o_ptr->sval == SV_LITE_LANTERN || + o_ptr->sval == SV_LITE_DWARVEN || + o_ptr->sval == SV_LITE_FEANORIAN) + { + do_cmd_refill_lamp(); + } + } + + /* No torch to refill */ + else + { + msg_print("Your light cannot be refilled."); + } +} + + +/* + * Target command + */ +void do_cmd_target(void) +{ + /* Target set */ + if (target_set(TARGET_KILL)) + { + msg_print("Target Selected."); + } + + /* Target aborted */ + else + { + msg_print("Target Aborted."); + } +} + + + +/* + * Look command + */ +void do_cmd_look(void) +{ + /* Look around */ + if (target_set(TARGET_LOOK)) + { + msg_print("Target Selected."); + } +} + + + +/* + * Allow the player to examine other sectors on the map + */ +void do_cmd_locate(void) +{ + int dir, y1, x1, y2, x2; + int panel_hgt, panel_wid; + char tmp_val[80]; + char out_val[160]; + + + /* Retrieve size of the Angband window */ + Term_get_size(&panel_wid, &panel_hgt); + + /* Calcurate size of the dungeon map area */ + panel_hgt = (panel_hgt - (ROW_MAP + 1)) / 2; + panel_wid = (panel_wid - (COL_MAP + 1)) / 2; + + /* Start at current panel */ + y2 = y1 = panel_row_min; + x2 = x1 = panel_col_min; + + /* Show panels until done */ + while (1) + { + /* Describe the location */ + if ((y2 == y1) && (x2 == x1)) + { + tmp_val[0] = '\0'; + } + else + { + strnfmt(tmp_val, 80, "%s%s of", + ((y2 < y1) ? " North" : (y2 > y1) ? " South" : ""), + ((x2 < x1) ? " West" : (x2 > x1) ? " East" : "")); + } + + /* Prepare to ask which way to look */ + if ((panel_hgt == PANEL_HGT) && (panel_wid == PANEL_WID)) + { + /* Avoid surprising the standard screen users */ + strnfmt(out_val, 160, + "Map sector [%d,%d], which is%s your sector. Direction?", + y2 / panel_hgt, x2 / panel_wid, tmp_val); + } + + /* Big screen */ + else + { + /* Panels are measured by current map area size */ + strnfmt(out_val, 160, + "Map sector [%d(%02d),%d(%02d)], which is%s your sector. Direction?", + y2 / panel_hgt, y2 % panel_hgt, + x2 / panel_wid, x2 % panel_wid, tmp_val); + } + + /* Assume no direction */ + dir = 0; + + /* Get a direction */ + while (!dir) + { + char ch; + + /* Get a command (or cancel) */ + if (!get_com(out_val, &ch)) break; + + /* Extract the action (if any) */ + dir = get_keymap_dir(ch); + + /* Error */ + if (!dir) bell(); + } + + /* No direction */ + if (!dir) break; + + /* Apply the motion */ + if (change_panel(ddy[dir], ddx[dir])) + { + y2 = panel_row_min; + x2 = panel_col_min; + } + } + + /* Recenter the map around the player */ + verify_panel(); + + /* Update stuff */ + p_ptr->update |= (PU_MONSTERS); + + /* Redraw map */ + p_ptr->redraw |= (PR_MAP); + + /* Window stuff */ + p_ptr->window |= (PW_OVERHEAD); + + /* Handle stuff */ + handle_stuff(); +} + + + + + + +/* + * The table of "symbol info" -- each entry is a string of the form + * "X:desc" where "X" is the trigger, and "desc" is the "info". + */ +static cptr ident_info[] = +{ + " :A dark grid", + "!:A potion (or oil)", + "\":An amulet (or necklace)", + "#:A wall (or secret door)", + "$:Treasure (gold or gems)", + "%:A vein (magma or quartz)", + /* "&:unused", */ + "':An open door", + "(:Soft armor", + "):A shield", + "*:A vein with treasure", + "+:A closed door", + ",:Food (or mushroom patch)", + "-:A wand (or rod)", + ".:Floor", + "/:A polearm (Axe/Pike/etc)", + "0:An altar", + "1:Entrance to General Store", + "2:Entrance to Armory", + "3:Entrance to Weaponsmith", + "4:Entrance to Temple", + "5:Entrance to Alchemy shop", + "6:Entrance to Magic store", + "7:Entrance to Black Market", + "8:Entrance to your home", + "9:Entrance to Bookstore", + "::Rubble", + ";:A glyph of warding / explosive rune", + "<:An up staircase", + "=:A ring", + ">:A down staircase", + "?:A scroll", + "@:You", + "A:Angel", + "B:Bird", + "C:Canine", + "D:Ancient Dragon/Wyrm", + "E:Elemental", + "F:Dragon Fly", + "G:Ghost", + "H:Hybrid", + "I:Insect", + "J:Snake", + "K:Killer Beetle", + "L:Lich", + "M:Multi-Headed Reptile", + /* "N:unused", */ + "O:Ogre", + "P:Giant Humanoid", + "Q:Quylthulg (Pulsing Flesh Mound)", + "R:Reptile/Amphibian", + "S:Spider/Scorpion/Tick", + "T:Troll", + "U:Major Demon", + "V:Vampire", + "W:Wight/Wraith/etc", + "X:Xorn/Xaren/etc", + "Y:Yeti", + "Z:Zephyr Hound", + "[:Hard armor", + "\\:A hafted weapon (mace/whip/etc)", + "]:Misc. armor", + "^:A trap", + "_:A staff", + /* "`:unused", */ + "a:Ant", + "b:Bat", + "c:Centipede", + "d:Dragon", + "e:Floating Eye", + "f:Feline", + "g:Golem", + "h:Hobbit/Elf/Dwarf", + "i:Icky Thing", + "j:Jelly", + "k:Kobold", + "l:Louse", + "m:Mold", + "n:Naga", + "o:Orc", + "p:Person/Human", + "q:Quadruped", + "r:Rodent", + "s:Skeleton", + "t:Townsperson", + "u:Minor Demon", + "v:Vortex", + "w:Worm/Worm-Mass", + /* "x:unused", */ + "y:Yeek", + "z:Zombie/Mummy", + "{:A missile (arrow/bolt/shot)", + "|:An edged weapon (sword/dagger/etc)", + "}:A launcher (bow/crossbow/sling)", + "~:A tool (or miscellaneous item)", + NULL +}; + + +/** + * Sort by monster experience. + */ +static bool compare_monster_experience(int w1, int w2) +{ + /* Extract experience */ + s32b z1 = r_info[w1].mexp; + s32b z2 = r_info[w2].mexp; + + /* Compare experience */ + if (z1 < z2) return true; + if (z1 > z2) return false; + + /* Punt to index */ + return w1 < w2; +} + +/** + * Sort by monster level. + */ +static bool compare_monster_level(int w1, int w2) +{ + /* Extract levels */ + byte z1 = r_info[w1].level; + byte z2 = r_info[w2].level; + + /* Compare levels */ + if (z1 < z2) return true; + if (z1 > z2) return false; + + /* Punt to monster experience. */ + return compare_monster_experience(w1, w2); +} + +/** + * Sort by total number of kills + */ +static bool compare_total_kills(int w1, int w2) +{ + /* Extract total kills */ + s16b z1 = r_info[w1].r_tkills; + s16b z2 = r_info[w2].r_tkills; + + /* Compare total kills */ + if (z1 < z2) return true; + if (z1 > z2) return false; + + /* Punt to monster level. */ + return compare_monster_level(w1, w2); +} + +/* + * Sort by player kills + */ +static bool compare_player_kills(int w1, int w2) +{ + /* Extract player kills */ + s16b z1 = r_info[w1].r_pkills; + s16b z2 = r_info[w2].r_pkills; + + /* Compare player kills */ + if (z1 < z2) return true; + if (z1 > z2) return false; + + /* Punt to total number of kills. */ + return compare_total_kills(w1, w2); +} + + +/* + * Hack -- Display the "name" and "attr/chars" of a monster race + */ +static void roff_top(int r_idx) +{ + monster_race *r_ptr = &r_info[r_idx]; + + byte a1, a2; + + char c1, c2; + + + /* Access the chars */ + c1 = r_ptr->d_char; + c2 = r_ptr->x_char; + + /* Access the attrs */ + a1 = r_ptr->d_attr; + a2 = r_ptr->x_attr; + + + /* Clear the top line */ + Term_erase(0, 0, 255); + + /* Reset the cursor */ + Term_gotoxy(0, 0); + + /* A title (use "The" for non-uniques) */ + if (!(r_ptr->flags1 & (RF1_UNIQUE))) + { + Term_addstr( -1, TERM_WHITE, "The "); + } + + /* Dump the name */ + Term_addstr( -1, TERM_WHITE, (r_name + r_ptr->name)); + + /* Append the "standard" attr/char info */ + Term_addstr( -1, TERM_WHITE, " ('"); + Term_addch(a1, c1); + if (use_bigtile && (a1 & 0x80)) Term_addch(255, 255); + Term_addstr( -1, TERM_WHITE, "')"); + + /* Append the "optional" attr/char info */ + Term_addstr( -1, TERM_WHITE, "/('"); + Term_addch(a2, c2); + if (use_bigtile && (a2 & 0x80)) Term_addch(255, 255); + Term_addstr( -1, TERM_WHITE, "'):"); +} + + +/* + * Identify a character, allow recall of monsters + * + * Several "special" responses recall "multiple" monsters: + * ^A (all monsters) + * ^U (all unique monsters) + * ^N (all non-unique monsters) + * ^M (case insensitive name search) + * + * The responses may be sorted in several ways, see below. + * + * Note that the player ghosts are ignored. XXX XXX XXX + */ +void do_cmd_query_symbol(void) +{ + int i, r_idx; + + char sym, query; + + char buf[128]; + + + bool_ all = FALSE; + + bool_ uniq = FALSE; + + bool_ norm = FALSE; + + + bool_ name = FALSE; + + char temp[80] = ""; + + + bool_ recall = FALSE; + + bool (*sort_by)(int,int) = nullptr; + + /* Get a character, or abort */ + if (!get_com("Enter character to be identified, " + "or (Ctrl-A, Ctrl-U, Ctrl-N, Ctrl-M):", &sym)) return; + + /* Find that character info, and describe it */ + for (i = 0; ident_info[i]; ++i) + { + if (sym == ident_info[i][0]) break; + } + + /* Describe */ + if (sym == KTRL('A')) + { + all = TRUE; + strcpy(buf, "Full monster list."); + } + else if (sym == KTRL('U')) + { + all = uniq = TRUE; + strcpy(buf, "Unique monster list."); + } + else if (sym == KTRL('N')) + { + all = norm = TRUE; + strcpy(buf, "Non-unique monster list."); + } + else if (sym == KTRL('M')) + { + all = name = TRUE; + if (!get_string("Name:", temp, 70)) return; + strnfmt(buf, 128, "Monsters with a name \"%s\"", temp); + strlower(temp); + } + else if (ident_info[i]) + { + strnfmt(buf, 128, "%c - %s.", sym, ident_info[i] + 2); + } + else + { + strnfmt(buf, 128, "%c - %s.", sym, "Unknown Symbol"); + } + + /* Display the result */ + prt(buf, 0, 0); + + /* Collect matching monsters */ + std::vector who; + for (i = 1; i < max_r_idx; i++) + { + monster_race *r_ptr = &r_info[i]; + + /* Nothing to recall */ + if (!cheat_know && !r_ptr->r_sights) continue; + + /* Require non-unique monsters if needed */ + if (norm && (r_ptr->flags1 & (RF1_UNIQUE))) continue; + + /* Require unique monsters if needed */ + if (uniq && !(r_ptr->flags1 & (RF1_UNIQUE))) continue; + + /* Require monsters with the name requested if needed */ + if (name) + { + char mon_name[80]; + + strcpy(mon_name, r_name + r_ptr->name); + strlower(mon_name); + + if (!strstr(mon_name, temp)) continue; + } + + /* Collect "appropriate" monsters */ + if (all || (r_ptr->d_char == sym)) { + who.push_back(i); + } + } + + /* Nothing to recall */ + if (who.empty()) + { + return; + } + + + /* Prompt XXX XXX XXX */ + put_str("Recall details? (k/p/y/n): ", 0, 40); + + /* Query */ + query = inkey(); + + /* Restore */ + prt(buf, 0, 0); + + + /* Sort by kills (and level) */ + if (query == 'k') + { + sort_by = compare_player_kills; + query = 'y'; + } + + /* Sort by level */ + if (query == 'p') + { + sort_by = compare_monster_level; + query = 'y'; + } + + /* Catch "escape" */ + if (query != 'y') + { + return; + } + + + /* Sort if needed */ + if (sort_by) + { + /* Sort the array */ + std::sort(std::begin(who), std::end(who), sort_by); + } + + + /* Start at the end */ + i = who.size() - 1; + + /* Scan the monster memory */ + while (1) + { + /* Extract a race */ + r_idx = who[i]; + + /* Hack -- Auto-recall */ + monster_race_track(r_idx, 0); + + /* Hack -- Handle stuff */ + handle_stuff(); + + /* Hack -- Begin the prompt */ + roff_top(r_idx); + + /* Hack -- Complete the prompt */ + Term_addstr( -1, TERM_WHITE, " [(r)ecall, ESC]"); + + /* Interact */ + while (1) + { + /* Recall */ + if (recall) + { + /* Save the screen */ + character_icky = TRUE; + Term_save(); + + /* Recall on screen */ + screen_roff(who[i], 0, 0); + + /* Hack -- Complete the prompt (again) */ + Term_addstr( -1, TERM_WHITE, " [(r)ecall, ESC]"); + } + + /* Command */ + query = inkey(); + + /* Unrecall */ + if (recall) + { + /* Restore */ + Term_load(); + character_icky = FALSE; + } + + /* Normal commands */ + if (query != 'r') break; + + /* Toggle recall */ + recall = !recall; + } + + /* Stop scanning */ + if (query == ESCAPE) break; + + /* Move to "prev" monster */ + if (query == '-') + { + if (++i == who.size()) + { + i = 0; + if (!expand_list) break; + } + } + + /* Move to "next" monster */ + else + { + if (i-- == 0) + { + i = who.size() - 1; + if (!expand_list) break; + } + } + } + + /* Re-display the identity */ + prt(buf, 0, 0); +} + + +/* + * research_mon + * -KMW- + */ +bool_ research_mon() +{ + int i, r_idx; + + char sym, query; + + char buf[128]; + + + s16b oldkills; + + byte oldwake; + + bool_ oldcheat; + + + bool_ all = FALSE; + + bool_ uniq = FALSE; + + bool_ norm = FALSE; + + bool_ notpicked; + + + bool_ recall = FALSE; + + monster_race *r2_ptr; + + /* Hack -- Remember "cheat_know" flag */ + oldcheat = cheat_know; + + + /* Get a character, or abort */ + if (!get_com("Enter character of monster: ", &sym)) return (TRUE); + + /* Find that character info, and describe it */ + for (i = 0; ident_info[i]; ++i) + { + if (sym == ident_info[i][0]) break; + } + + if (ident_info[i]) + { + strnfmt(buf, 128, "%c - %s.", sym, ident_info[i] + 2); + } + else + { + strnfmt(buf, 128, "%c - %s.", sym, "Unknown Symbol"); + } + + /* Display the result */ + prt(buf, 16, 10); + + + /* Collect matching monsters */ + std::vector who; + for (i = 1; i < max_r_idx; i++) + { + monster_race *r_ptr = &r_info[i]; + + /* Hack -- Force "cheat_know" */ + cheat_know = TRUE; + + /* Nothing to recall */ + if (!cheat_know && !r_ptr->r_sights) continue; + + /* Require non-unique monsters if needed */ + if (norm && (r_ptr->flags1 & (RF1_UNIQUE))) continue; + + /* Require unique monsters if needed */ + if (uniq && !(r_ptr->flags1 & (RF1_UNIQUE))) continue; + + /* Collect "appropriate" monsters */ + if (all || (r_ptr->d_char == sym)) { + who.push_back(i); + } + } + + /* Nothing to recall */ + if (who.empty()) + { + /* Restore the "cheat_know" flag */ + cheat_know = oldcheat; + + return (TRUE); + } + + + query = 'y'; + + /* Sort by level */ + std::sort(std::begin(who), std::end(who), compare_monster_level); + + + /* Start at the end */ + i = who.size() - 1; + + notpicked = TRUE; + + /* Scan the monster memory */ + while (notpicked) + { + /* Extract a race */ + r_idx = who[i]; + + /* Hack -- Auto-recall */ + monster_race_track(r_idx, 0); + + /* Hack -- Handle stuff */ + handle_stuff(); + + /* Hack -- Begin the prompt */ + roff_top(r_idx); + + /* Hack -- Complete the prompt */ + Term_addstr( -1, TERM_WHITE, " [(r)ecall, ESC, space to continue]"); + + /* Interact */ + while (1) + { + /* Recall */ + if (recall) + { + /* Save the screen */ + character_icky = TRUE; + Term_save(); + + /* Recall on screen */ + r2_ptr = &r_info[r_idx]; + + oldkills = r2_ptr->r_tkills; + oldwake = r2_ptr->r_wake; + screen_roff(who[i], 0, 1); + r2_ptr->r_tkills = oldkills; + r2_ptr->r_wake = oldwake; + r2_ptr->r_sights = 1; + cheat_know = oldcheat; + notpicked = FALSE; + break; + + } + + /* Command */ + query = inkey(); + + /* Unrecall */ + if (recall) + { + /* Restore */ + Term_load(); + character_icky = FALSE; + } + + /* Normal commands */ + if (query != 'r') break; + + /* Toggle recall */ + recall = !recall; + } + + /* Stop scanning */ + if (query == ESCAPE) break; + + /* Move to "prev" monster */ + if (query == '-') + { + if (++i == who.size()) + { + i = 0; + if (!expand_list) break; + } + } + + /* Move to "next" monster */ + else + { + if (i-- == 0) + { + i = who.size() - 1; + if (!expand_list) break; + } + } + } + + + /* Re-display the identity */ + /* prt(buf, 5, 5);*/ + + /* Restore the "cheat_know" flag */ + cheat_know = oldcheat; + + return (notpicked); +} + + +/* + * Try to "sense" the grid's mana + */ +bool_ do_cmd_sense_grid_mana() +{ + int chance, i; + + + /* Take (a lot of) time */ + energy_use = 200; + + /* Base chance of success */ + chance = p_ptr->skill_dev; + + /* Confusion hurts skill */ + if (p_ptr->confused) chance = chance / 2; + + /* Hight mana grids are harder */ + chance = chance - (cave[p_ptr->py][p_ptr->px].mana / 10); + + /* Give everyone a (slight) chance */ + if ((chance < USE_DEVICE) && (rand_int(USE_DEVICE - chance + 1) == 0)) + { + chance = USE_DEVICE; + } + + /* Roll for usage */ + if ((chance < USE_DEVICE) || (randint(chance) < USE_DEVICE)) + { + if (flush_failure) flush(); + msg_print("You failed to sense the grid's mana."); + sound(SOUND_FAIL); + return FALSE; + } + + /* Try to give an "average" value */ + i = (101 - p_ptr->skill_dev) / 2; + i = (i < 1) ? 1 : (i > 50) ? 50 : i; + + if (wizard) + { + msg_format("Grid's mana: %d.", cave[p_ptr->py][p_ptr->px].mana); + msg_format("Average grid's mana: %d.", (cave[p_ptr->py][p_ptr->px].mana / i) * i); + } + else + { + msg_format("Average Area's mana: %d", (cave[p_ptr->py][p_ptr->px].mana / i) * i); + } + return TRUE; +} + + +/* + * Calculate the weight of the portable holes + */ +s32b portable_hole_weight(void) +{ + s32b weight, i; + + store_type *st_ptr = &town_info[TOWN_RANDOM].store[STORE_HOME]; + + + /* Sum the objects in the appropriate home */ + for (i = 0, weight = 0; i < st_ptr->stock_num; i++) + { + object_type *o_ptr = &st_ptr->stock[i]; + + weight += (o_ptr->weight * o_ptr->number); + } + + /* Multiply the sum with 1.5 */ + weight = (weight * 3) / 2 + 2; + + return (weight); +} + + +/* + * Calculate and set the weight of the portable holes + */ +void set_portable_hole_weight(void) +{ + s32b weight, i, j; + + /* Calculate the weight of items in home */ + weight = portable_hole_weight(); + + /* Set the weight of portable holes in the shops, ... */ + for (i = 1; i < max_towns; i++) + { + for (j = 0; j < max_st_idx; j++) + { + store_type *st_ptr = &town_info[i].store[j]; + int k; + + for (k = 0; k < st_ptr->stock_num; k++) + { + object_type *o_ptr = &st_ptr->stock[k]; + + if ((o_ptr->tval == TV_TOOL) && + (o_ptr->sval == SV_PORTABLE_HOLE)) + o_ptr->weight = weight; + } + } + } + + /* ... in the object list, ... */ + for (i = 1; i < o_max; i++) + { + object_type *o_ptr = &o_list[i]; + + if ((o_ptr->tval == TV_TOOL) && + (o_ptr->sval == SV_PORTABLE_HOLE)) o_ptr->weight = weight; + } + + /* ... and in the p_ptr->inventory to the appropriate value */ + for (i = 0; i < INVEN_TOTAL; i++) + { + object_type *o_ptr = &p_ptr->inventory[i]; + + /* Skip non-objects */ + if ((o_ptr->tval == TV_TOOL) && + (o_ptr->sval == SV_PORTABLE_HOLE)) o_ptr->weight = weight; + } +} + + +/* + * Use a portable hole + */ +void do_cmd_portable_hole(void) +{ + cave_type *c_ptr = &cave[p_ptr->py][p_ptr->px]; + + int feat, special, town_num; + + /* Is it currently wielded? */ + if (!p_ptr->inventory[INVEN_TOOL].k_idx || + (p_ptr->inventory[INVEN_TOOL].tval != TV_TOOL) || + (p_ptr->inventory[INVEN_TOOL].sval != SV_PORTABLE_HOLE)) + { + /* No, it isn't */ + msg_print("You have to wield a portable hole to use your abilities"); + return; + } + + /* Mega-hack: Saving the old values, and then... */ + feat = c_ptr->feat; + special = c_ptr->special; + town_num = p_ptr->town_num; + + /* ... change the current grid to the home in town #1 */ + /* DG -- use the first random town, since random towns cannot have houses */ + /* + * pelpel -- This doesn't affect LoS, so we can manipulate + * terrain feature without calling cave_set_feat() + */ + c_ptr->feat = FEAT_SHOP; + c_ptr->special = STORE_HOME; + p_ptr->town_num = TOWN_RANDOM; + + /* Now use the portable hole */ + do_cmd_store(); + + /* Mega-hack part II: change the current grid to the original value */ + c_ptr->feat = feat; + c_ptr->special = special; + p_ptr->town_num = town_num; + + set_portable_hole_weight(); + + /* Recalculate bonuses */ + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + p_ptr->update |= (PU_BONUS); +} + + +/* + * Try to add a CLI action. + */ +void cli_add(cptr active, cptr trigger, cptr descr) +{ + s16b num; + cli_comm *cli_ptr, *old_ptr; + + /* Too many macros. */ + if (cli_total >= CLI_MAX) return; + + /* First try to read active as a number. */ + if (strtol(active, 0, 0)) + { + num = strtol(active, 0, 0); + } + /* Then try to read it as a character. */ + else if (strlen(active) == 1) + { + num = active[0]; + } + /* Give up if it doesn't work. */ + else + { + return; + } + + /* Dump the macro. */ + cli_ptr = cli_info + cli_total; + old_ptr = cli_info + cli_total - 1; + + /* + * Trim 's from the ends of a token. This turns '@' into @ and + * ''' into '. This may be the intent of the code in tokenize(), + * but I've left it for lack of comments to back me up. + */ + if (strchr(trigger, '\'')) + { + char temp[80], *t; + cptr s; + for (s = trigger, t = temp; ; s++, t++) + { + /* tokenize() causes each ' to be followed by another character, + * and then another '. Trim the 's here. */ + if (*s == '\'') + { + *t = *(++s); + s++; + } + else + { + *t = *s; + } + if (*t == '\0') break; + } + cli_ptr->comm = string_make(temp); + } + else + { + cli_ptr->comm = string_make(trigger); + } + + /* First try copying everything across. */ + cli_ptr->key = num; + cli_ptr->descrip = string_make(descr); + + /* Take description for the previous record if appropriate. */ + if ((cli_total > 0) && (old_ptr->key == cli_ptr->key) && (cli_ptr->descrip == 0)) + { + cli_ptr->descrip = old_ptr->descrip; + } + + /* Accept the macro. */ + if (cli_ptr->key && cli_ptr->comm && cli_ptr->descrip) cli_total++; +} + + + +/* + * Get a string using CLI completion. + */ +bool_ get_string_cli(cptr prompt, char *buf, int len) +{ + bool_ res; + + + /* Paranoia XXX XXX XXX */ + msg_print(NULL); + + /* Display prompt */ + prt(prompt, 0, 0); + + /* Ask the user for a string */ + askfor_aux_complete = TRUE; + res = askfor_aux(buf, len); + askfor_aux_complete = FALSE; + + /* Clear prompt */ + prt("", 0, 0); + + /* Result */ + return (res); +} + + +/* + * Do a command line command + * + * This is a wrapper around process command to provide a "reverse keymap" + * whereby a set of keypresses is mapped to one. + * + * This is useful because command_cmd is a s16b, and so allows each command a + * unique representation. + * + * See defines.h for a list of the codes used. + */ +void do_cmd_cli(void) +{ + char buff[80]; + + cli_comm *cli_ptr; + + /* Clear the input buffer */ + strcpy(buff, ""); + + /* Accept command */ + if (!get_string_cli("Command: ", buff, 30)) return; + + + /* Analyse the input */ + for (cli_ptr = cli_info; cli_ptr->comm; cli_ptr++) + { + if (!strcmp(buff, cli_ptr->comm)) + { + /* Process the command without keymaps or macros. */ + command_new = cli_ptr->key; + return; + } + } + + msg_format("No such command: %s", buff); +} + + +/* + * Display on-line help for the CLI commands + */ +void do_cmd_cli_help() +{ + int i, j; + + FILE *fff; + + char file_name[1024]; + + + /* Temporary file */ + if (path_temp(file_name, 1024)) return; + + /* Open a new file */ + fff = my_fopen(file_name, "w"); + + for (i = 0, j = -1; i < cli_total; i++) + { + if (j < i - 1) fprintf(fff, "/"); + fprintf(fff, "[[[[[G%s]", cli_info[i].comm); + if (cli_info[i].descrip != cli_info[i + 1].descrip) + { + fprintf(fff, " %s\n", cli_info[i].descrip); + j = i; + } + } + + /* Close the file */ + my_fclose(fff); + + /* Enter "icky" mode */ + character_icky = TRUE; + + /* Save the screen */ + Term_save(); + + /* Display the file contents */ + show_file(file_name, "Command line help", 0, 0); + + /* Restore the screen */ + Term_load(); + + /* Leave "icky" mode */ + character_icky = FALSE; + + /* Remove the file */ + fd_kill(file_name); +} + + +/* + * Dump screen shot in HTML + */ +void do_cmd_html_dump() +{ + char tmp_val[81]; + bool_ html = TRUE; + term_win *save; + + /* Save the screen */ + save = Term_save_to(); + + if (wizard && get_check("WIZARD MODE: Do an help file dump?")) + html = FALSE; + + /* Ask for a file */ + if (html) + { + strcpy(tmp_val, "dummy.htm"); + if (!get_string("File(you can post it to http://angband.oook.cz/): ", tmp_val, 80)) + { + /* Now restore the screen to initial state */ + Term_load_from(save, TRUE); + Term_fresh(); + return; + } + } + else + { + strcpy(tmp_val, "dummy.txt"); + if (!get_string("File: ", tmp_val, 80)) + { + /* Now restore the screen to initial state */ + Term_load_from(save, TRUE); + Term_fresh(); + return; + } + } + + /* Now restore the screen to dump it */ + Term_load_from(save, TRUE); + + if (html) + html_screenshot(tmp_val); + else + help_file_screenshot(tmp_val); + + Term_erase(0, 0, 255); + msg_print("Dump saved."); + Term_fresh(); + fix_message(); +} diff --git a/src/cmd4.c b/src/cmd4.c deleted file mode 100644 index 3a6ef2cc..00000000 --- a/src/cmd4.c +++ /dev/null @@ -1,4632 +0,0 @@ -/* File: cmd4.c */ - -/* Purpose: Interface commands */ - -/* - * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke - * - * This software may be copied and distributed for educational, research, and - * not for profit purposes provided that this copyright and statement are - * included in all such copies. - */ - -#include "angband.h" - -#include "messages.h" -#include "hooks.h" - -/* - * Hack -- redraw the screen - * - * This command performs various low level updates, clears all the "extra" - * windows, does a total redraw of the main window, and requests all of the - * interesting updates and redraws that I can think of. - * - * This command is also used to "instantiate" the results of the user - * selecting various things, such as graphics mode, so it must call - * the "TERM_XTRA_REACT" hook before redrawing the windows. - */ -void do_cmd_redraw(void) -{ - int j; - - term *old = Term; - - - /* Hack -- react to changes */ - Term_xtra(TERM_XTRA_REACT, 0); - - - /* Combine and Reorder the pack (later) */ - p_ptr->notice |= (PN_COMBINE | PN_REORDER); - - - /* Update torch */ - p_ptr->update |= (PU_TORCH); - - /* Update stuff */ - p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS | PU_POWERS | - PU_SANITY | PU_BODY); - - /* Forget view */ - p_ptr->update |= (PU_UN_VIEW); - - /* Update view */ - p_ptr->update |= (PU_VIEW); - - /* Update monster light */ - p_ptr->update |= (PU_MON_LITE); - - /* Update monsters */ - p_ptr->update |= (PU_MONSTERS); - - /* Redraw everything */ - p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP); - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER | PW_M_LIST); - - /* Window stuff */ - p_ptr->window |= (PW_MESSAGE | PW_OVERHEAD | PW_MONSTER | PW_OBJECT); - - /* Hack -- update */ - handle_stuff(); - - - /* Redraw every window */ - for (j = 0; j < 8; j++) - { - /* Dead window */ - if (!angband_term[j]) continue; - - /* Activate */ - Term_activate(angband_term[j]); - - /* Redraw */ - Term_redraw(); - - /* Refresh */ - Term_fresh(); - - /* Restore */ - Term_activate(old); - } -} - - -/* - * Hack -- change name - */ -void do_cmd_change_name(void) -{ - char c; - - int mode = 0; - - char tmp[160]; - - - /* Enter "icky" mode */ - character_icky = TRUE; - - /* Save the screen */ - Term_save(); - - /* Forever */ - while (1) - { - /* keep mode below 7 */ - mode = (mode + 6) % 6; - - /* Display the player */ - display_player(mode); - - /* Prompt */ - if (mode == 0) - { - Term_putstr(14, 22, -1, TERM_WHITE, - "['t/T' to change tactics, 'e/E' to change movement]"); - } - - Term_putstr(4, 23, -1, TERM_WHITE, - "['c' to change name, 'f' to file, 'p' for previous, 'n' for next, or ESC]"); - - /* Query */ - c = inkey(); - - /* Exit */ - if (c == ESCAPE) break; - - /* Change name */ - if (c == 'c') - { - get_name(); - } - - /* File dump */ - else if (c == 'f') - { - strnfmt(tmp, 160, "%s.txt", player_name); - if (get_string("Filename(you can post it to http://angband.oook.cz/): ", tmp, 80)) - { - if (tmp[0] && (tmp[0] != ' ')) - { - file_character(tmp, FALSE); - } - } - } - - /* Toggle mode */ - else if (c == 'n') - { - mode++; - } - else if (c == 'p') - { - mode--; - } - - else if (mode == 0) - { - /* Change tactic */ - if (c == 't') - { - (void)do_cmd_change_tactic( -1); - } - else if (c == 'T') - { - (void)do_cmd_change_tactic(1); - } - - /* Change movement */ - else if (c == 'e') - { - do_cmd_change_movement( -1); - } - else if (c == 'E') - { - do_cmd_change_movement(1); - } - else - { - bell(); - } - } - /* Oops */ - else - { - bell(); - } - - /* Flush messages */ - msg_print(NULL); - } - - /* Restore the screen */ - Term_load(); - - /* Leave "icky" mode */ - character_icky = FALSE; - - - /* Redraw everything */ - p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP); - - handle_stuff(); -} - - -/* - * Recall the most recent message - */ -void do_cmd_message_one(void) -{ - cptr msg = format("> %s", message_str(0)); - - /* Recall one message XXX XXX XXX */ - display_message(0, 0, strlen(msg), message_color(0), msg); -} - - -/* - * Show previous messages to the user -BEN- - * - * The screen format uses line 0 and (Term->hgt - 1) for headers and prompts, - * skips line 1 and (Term->hgt - 2), and uses line 2 thru (Term->hgt - 3) for - * old messages. - * - * This command shows you which commands you are viewing, and allows - * you to "search" for strings in the recall. - * - * Note that messages may be longer than 80 characters, but they are - * displayed using "infinite" length, with a special sub-command to - * "slide" the virtual display to the left or right. - * - * Attempt to only hilite the matching portions of the string. - * - * Now taking advantages of big-screen. -pav- - */ -void do_cmd_messages(void) -{ - int i, j, k, n; - u32b q; - int wid, hgt; - - char shower[80]; - char finder[80]; - - /* Wipe finder */ - strcpy(finder, ""); - - /* Wipe shower */ - strcpy(shower, ""); - - - /* Total messages */ - n = message_num(); - - /* Start on first message */ - i = 0; - - /* Start at leftmost edge */ - q = 0; - - /* Enter "icky" mode */ - character_icky = TRUE; - - /* Save the screen */ - Term_save(); - - /* Process requests until done */ - while (1) - { - /* Clear screen */ - Term_clear(); - - /* Retrieve current screen size */ - Term_get_size(&wid, &hgt); - - /* Dump up to 20 (or more in bigscreen) lines of messages */ - for (j = 0; (j < (hgt - 4)) && (i + j < n); j++) - { - cptr msg = message_str(i + j); - byte color = message_color(i + j); - - /* Apply horizontal scroll */ - msg = (strlen(msg) >= q) ? (msg + q) : ""; - - /* Dump the messages, bottom to top */ - display_message(0, (hgt - 3) - j, strlen(msg), color, msg); - - /* Hilite "shower" */ - if (shower[0]) - { - cptr str = msg; - - /* Display matches */ - while ((str = strstr(str, shower)) != NULL) - { - int len = strlen(shower); - - /* Display the match */ - Term_putstr(str - msg, (hgt - 3) - j, len, TERM_YELLOW, shower); - - /* Advance */ - str += len; - } - } - } - - /* Display header XXX XXX XXX */ - prt(format("Message Recall (%d-%d of %d), Offset %d", - i, i + j - 1, n, q), 0, 0); - - /* Display prompt (not very informative) */ - prt("[Press 'p' for older, 'n' for newer, ..., or ESCAPE]", hgt - 1, 0); - - /* Get a command */ - k = inkey(); - - /* Exit on Escape */ - if (k == ESCAPE) break; - - /* Hack -- Save the old index */ - j = i; - - /* Horizontal scroll */ - if (k == '4') - { - /* Scroll left */ - q = (q >= ((u32b)wid / 2)) ? (q - wid / 2) : 0; - - /* Success */ - continue; - } - - /* Horizontal scroll */ - if (k == '6') - { - /* Scroll right */ - q = q + wid / 2; - - /* Success */ - continue; - } - - /* Hack -- handle show */ - if (k == '=') - { - /* Prompt */ - prt("Show: ", hgt - 1, 0); - - /* Get a "shower" string, or continue */ - if (!askfor_aux(shower, 80)) continue; - - /* Okay */ - continue; - } - - /* Hack -- handle find */ - if (k == '/') - { - s16b z; - - /* Prompt */ - prt("Find: ", hgt - 1, 0); - - /* Get a "finder" string, or continue */ - if (!askfor_aux(finder, 80)) continue; - - /* Show it */ - strcpy(shower, finder); - - /* Scan messages */ - for (z = i + 1; z < n; z++) - { - cptr msg = message_str(z); - - /* Search for it */ - if (strstr(msg, finder)) - { - /* New location */ - i = z; - - /* Done */ - break; - } - } - } - - /* Recall 1 older message */ - if ((k == '8') || (k == '\n') || (k == '\r')) - { - /* Go newer if legal */ - if (i + 1 < n) i += 1; - } - - /* Recall 10 older messages */ - if (k == '+') - { - /* Go older if legal */ - if (i + 10 < n) i += 10; - } - - /* Recall one screen of older messages */ - if ((k == 'p') || (k == KTRL('P')) || (k == ' ')) - { - /* Go older if legal */ - if (i + (hgt - 4) < n) i += (hgt - 4); - } - - /* Recall one screen of newer messages */ - if ((k == 'n') || (k == KTRL('N'))) - { - /* Go newer (if able) */ - i = (i >= (hgt - 4)) ? (i - (hgt - 4)) : 0; - } - - /* Recall 10 newer messages */ - if (k == '-') - { - /* Go newer (if able) */ - i = (i >= 10) ? (i - 10) : 0; - } - - /* Recall 1 newer messages */ - if (k == '2') - { - /* Go newer (if able) */ - i = (i >= 1) ? (i - 1) : 0; - } - - /* Hack -- Error of some kind */ - if (i == j) bell(); - } - - /* Restore the screen */ - Term_load(); - - /* Leave "icky" mode */ - character_icky = FALSE; -} - - - -/* - * Number of cheating options - */ -#define CHEAT_MAX 6 - -/* - * Cheating options - */ -static option_type cheat_info[CHEAT_MAX] = -{ - { &cheat_peek, FALSE, 0, 0, "cheat_peek", "Peek into object creation" }, - { &cheat_hear, FALSE, 0, 1, "cheat_hear", "Peek into monster creation" }, - { &cheat_room, FALSE, 0, 2, "cheat_room", "Peek into dungeon creation" }, - { &cheat_xtra, FALSE, 0, 3, "cheat_xtra", "Peek into something else" }, - { &cheat_know, FALSE, 0, 4, "cheat_know", "Know complete monster info" }, - { &cheat_live, FALSE, 0, 5, "cheat_live", "Allow player to avoid death" } -}; - -/* - * Interact with some options for cheating - */ -static void do_cmd_options_cheat(cptr info) -{ - char ch; - - int i, k = 0, n = CHEAT_MAX; - - int dir; - - char buf[80]; - - - /* Clear screen */ - Term_clear(); - - /* Interact with the player */ - while (TRUE) - { - /* Prompt XXX XXX XXX */ - strnfmt(buf, 80, "%s (RET to advance, y/n to set, ESC to accept) ", info); - prt(buf, 0, 0); - - /* Display the options */ - for (i = 0; i < n; i++) - { - byte a = TERM_WHITE; - - /* Color current option */ - if (i == k) a = TERM_L_BLUE; - - /* Display the option text */ - strnfmt(buf, 80, "%-48s: %s (%s)", - cheat_info[i].o_desc, - (*cheat_info[i].o_var ? "yes" : "no "), - cheat_info[i].o_text); - c_prt(a, buf, i + 2, 0); - } - - /* Hilite current option */ - move_cursor(k + 2, 50); - - /* Get a key */ - ch = inkey(); - - /* - * Hack -- Try to translate the key into a direction - * to allow the use of roguelike keys for navigation - */ - dir = get_keymap_dir(ch); - if ((dir == 2) || (dir == 4) || (dir == 6) || (dir == 8)) ch = I2D(dir); - - - /* Analyze */ - switch (ch) - { - case ESCAPE: - { - return; - } - - case '-': - case '8': - { - k = (n + k - 1) % n; - - break; - } - - case ' ': - case '\n': - case '\r': - case '2': - { - k = (k + 1) % n; - - break; - } - - case 'y': - case 'Y': - case '6': - { - noscore |= (cheat_info[k].o_page * 256 + cheat_info[k].o_bit); - (*cheat_info[k].o_var) = TRUE; - k = (k + 1) % n; - - break; - } - - case 'n': - case 'N': - case '4': - { - (*cheat_info[k].o_var) = FALSE; - k = (k + 1) % n; - - break; - } - - default: - { - bell(); - - break; - } - } - } -} - - -static option_type autosave_info[2] = -{ - { &autosave_l, FALSE, 0, 6, "autosave_l", "Autosave when entering new levels" }, - { &autosave_t, FALSE, 0, 7, "autosave_t", "Timed autosave" }, -}; - -s16b toggle_frequency(s16b current) -{ - if (current == 0) return (50); - if (current == 50) return (100); - if (current == 100) return (250); - if (current == 250) return (500); - if (current == 500) return (1000); - if (current == 1000) return (2500); - if (current == 2500) return (5000); - if (current == 5000) return (10000); - if (current == 10000) return (25000); - - return (0); -} - - -/* - * Interact with some options for cheating - */ -static void do_cmd_options_autosave(cptr info) -{ - char ch; - - int i, k = 0, n = 2; - - int dir; - - char buf[80]; - - - /* Clear screen */ - Term_clear(); - - /* Interact with the player */ - while (TRUE) - { - /* Prompt XXX XXX XXX */ - strnfmt(buf, 80, - "%s (RET to advance, y/n to set, 'F' for frequency, ESC to accept) ", - info); - prt(buf, 0, 0); - - /* Display the options */ - for (i = 0; i < n; i++) - { - byte a = TERM_WHITE; - - /* Color current option */ - if (i == k) a = TERM_L_BLUE; - - /* Display the option text */ - strnfmt(buf, 80, "%-48s: %s (%s)", - autosave_info[i].o_desc, - (*autosave_info[i].o_var ? "yes" : "no "), - autosave_info[i].o_text); - c_prt(a, buf, i + 2, 0); - } - - prt(format("Timed autosave frequency: every %d turns", autosave_freq), 5, 0); - - - /* Hilite current option */ - move_cursor(k + 2, 50); - - /* Get a key */ - ch = inkey(); - - /* - * Hack -- Try to translate the key into a direction - * to allow the use of roguelike keys for navigation - */ - dir = get_keymap_dir(ch); - if ((dir == 2) || (dir == 4) || (dir == 6) || (dir == 8)) ch = I2D(dir); - - /* Analyze */ - switch (ch) - { - case ESCAPE: - { - return; - } - - case '-': - case '8': - { - k = (n + k - 1) % n; - - break; - } - - case ' ': - case '\n': - case '\r': - case '2': - { - k = (k + 1) % n; - - break; - } - - case 'y': - case 'Y': - case '6': - { - - (*autosave_info[k].o_var) = TRUE; - k = (k + 1) % n; - - break; - } - - case 'n': - case 'N': - case '4': - { - (*autosave_info[k].o_var) = FALSE; - k = (k + 1) % n; - - break; - } - - case 'f': - case 'F': - { - autosave_freq = toggle_frequency(autosave_freq); - prt(format("Timed autosave frequency: every %d turns", - autosave_freq), 5, 0); - - break; - } - - default: - { - bell(); - - break; - } - } - } -} - -/* Switch an option by only knowing its name */ -bool_ change_option(cptr name, bool_ value) -{ - int i; - - /* Scan the options */ - for (i = 0; option_info[i].o_desc; i++) - { - if (!strcmp(option_info[i].o_text, name)) - { - bool_ old = (*option_info[i].o_var); - - (*option_info[i].o_var) = value; - - return old; - } - } - - cmsg_format(TERM_VIOLET, "Warning, change_option couldn't find option '%s'.", name); - return FALSE; -} - -/* - * Interact with some options - */ -void do_cmd_options_aux(int page, cptr info, bool_ read_only) -{ - char ch; - - int i, k = 0, n = 0; - - int dir; - - int opt[24]; - - char buf[80]; - - - /* Lookup the options */ - for (i = 0; i < 24; i++) opt[i] = 0; - - /* Scan the options */ - for (i = 0; option_info[i].o_desc; i++) - { - /* Notice options on this "page" */ - if (option_info[i].o_page == page) opt[n++] = i; - } - - - /* Clear screen */ - Term_clear(); - - /* Interact with the player */ - while (TRUE) - { - /* Prompt XXX XXX XXX */ - strnfmt(buf, 80, "%s (RET to advance, y/n to set, ESC to accept) ", info); - prt(buf, 0, 0); - - /* Display the options */ - for (i = 0; i < n; i++) - { - byte a = TERM_WHITE; - - /* Color current option */ - if (i == k) a = TERM_L_BLUE; - - /* Display the option text */ - strnfmt(buf, 80, "%-48s: %s (%s)", - option_info[opt[i]].o_desc, - (*option_info[opt[i]].o_var ? "yes" : "no "), - option_info[opt[i]].o_text); - c_prt(a, buf, i + 2, 0); - } - - /* Hilite current option */ - move_cursor(k + 2, 50); - - /* Get a key */ - ch = inkey(); - - /* - * Hack -- Try to translate the key into a direction - * to allow the use of roguelike keys for navigation - */ - dir = get_keymap_dir(ch); - if ((dir == 2) || (dir == 4) || (dir == 6) || (dir == 8)) ch = I2D(dir); - - /* Analyze */ - switch (ch) - { - case ESCAPE: - { - return; - } - - case '-': - case '8': - { - k = (n + k - 1) % n; - - break; - } - - case ' ': - case '\n': - case '\r': - case '2': - { - k = (k + 1) % n; - - break; - } - - case 'y': - case 'Y': - case '6': - { - if (read_only) break; - - (*option_info[opt[k]].o_var) = TRUE; - k = (k + 1) % n; - - break; - } - - case 'n': - case 'N': - case '4': - { - if (read_only) break; - - (*option_info[opt[k]].o_var) = FALSE; - k = (k + 1) % n; - - break; - } - - default: - { - bell(); - - break; - } - } - } -} - - -/* - * Modify the "window" options - */ -static void do_cmd_options_win(void) -{ - int i, j, d; - - int y = 0; - - int x = 0; - - char ch; - - bool_ go = TRUE; - - u32b old_flag[8]; - - - /* Memorize old flags */ - for (j = 0; j < 8; j++) - { - /* Acquire current flags */ - old_flag[j] = window_flag[j]; - } - - - /* Clear screen */ - Term_clear(); - - /* Interact */ - while (go) - { - /* Prompt XXX XXX XXX */ - prt("Window Flags (, t, y, n, ESC) ", 0, 0); - - /* Display the windows */ - for (j = 0; j < 8; j++) - { - byte a = TERM_WHITE; - - cptr s = angband_term_name[j]; - - /* Use color */ - if (j == x) a = TERM_L_BLUE; - - /* Window name, staggered, centered */ - Term_putstr(35 + j * 5 - strlen(s) / 2, 2 + j % 2, -1, a, s); - } - - /* Display the options */ - for (i = 0; i < 16; i++) - { - byte a = TERM_WHITE; - - cptr str = window_flag_desc[i]; - - /* Use color */ - if (i == y) a = TERM_L_BLUE; - - /* Unused option */ - if (!str) str = "(Unused option)"; - - /* Flag name */ - Term_putstr(0, i + 5, -1, a, str); - - /* Display the windows */ - for (j = 0; j < 8; j++) - { - byte a = TERM_WHITE; - - char c = '.'; - - /* Use color */ - if ((i == y) && (j == x)) a = TERM_L_BLUE; - - /* Active flag */ - if (window_flag[j] & (1L << i)) c = 'X'; - - /* Flag value */ - Term_putch(35 + j * 5, i + 5, a, c); - } - } - - /* Place Cursor */ - Term_gotoxy(35 + x * 5, y + 5); - - /* Get key */ - ch = inkey(); - - /* Analyze */ - switch (ch) - { - case ESCAPE: - { - go = FALSE; - - break; - } - - case 'T': - case 't': - { - /* Clear windows */ - for (j = 0; j < 8; j++) - { - window_flag[j] &= ~(1L << y); - } - - /* Clear flags */ - for (i = 0; i < 16; i++) - { - window_flag[x] &= ~(1L << i); - } - - /* Fall through */ - } - - case 'y': - case 'Y': - { - /* Ignore screen */ - if (x == 0) break; - - /* Set flag */ - window_flag[x] |= (1L << y); - - break; - } - - case 'n': - case 'N': - { - /* Clear flag */ - window_flag[x] &= ~(1L << y); - - break; - } - - default: - { - d = get_keymap_dir(ch); - - x = (x + ddx[d] + 8) % 8; - y = (y + ddy[d] + 16) % 16; - - if (!d) bell(); - - break; - } - } - } - - /* Notice changes */ - for (j = 0; j < 8; j++) - { - term *old = Term; - - /* Dead window */ - if (!angband_term[j]) continue; - - /* Ignore non-changes */ - if (window_flag[j] == old_flag[j]) continue; - - /* Activate */ - Term_activate(angband_term[j]); - - /* Erase */ - Term_clear(); - - /* Refresh */ - Term_fresh(); - - /* Restore */ - Term_activate(old); - } -} - - -/* - * Write all current options to the given preference file in the - * lib/user directory. Modified from KAmband 1.8. - */ -static errr option_dump(cptr fname) -{ - int i, j; - - FILE *fff; - - char buf[1024]; - - - /* Build the filename */ - path_build(buf, 1024, ANGBAND_DIR_USER, fname); - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - /* Append to the file */ - fff = my_fopen(buf, "a"); - - /* Failure */ - if (!fff) return ( -1); - - - /* Skip some lines */ - fprintf(fff, "\n\n"); - - /* Start dumping */ - fprintf(fff, "# Automatic option dump\n\n"); - - /* Dump options (skip cheat, adult, score) */ - for (i = 0; option_info[i].o_var != NULL; i++) - { - /* Require a real option */ - if (!option_info[i].o_text) continue; - - /* No birth options */ - if (option_info[i].o_page == 6) continue; - - /* Comment */ - fprintf(fff, "# Option '%s'\n", option_info[i].o_desc); - - /* Dump the option */ - if ((*option_info[i].o_var)) - { - fprintf(fff, "Y:%s\n", option_info[i].o_text); - } - else - { - fprintf(fff, "X:%s\n", option_info[i].o_text); - } - - /* Skip a line */ - fprintf(fff, "\n"); - } - - /* Dump window flags */ - for (i = 1; i < ANGBAND_TERM_MAX; i++) - { - /* Require a real window */ - if (!angband_term[i]) continue; - - /* Check each flag */ - for (j = 0; j < 32; j++) - { - /* Require a real flag */ - if (!window_flag_desc[j]) continue; - - /* Comment */ - fprintf(fff, "# Window '%s', Flag '%s'\n", - angband_term_name[i], window_flag_desc[j]); - - /* Dump the flag */ - if (window_flag[i] & (1L << j)) - { - fprintf(fff, "W:%d:%d:1\n", i, j); - } - else - { - fprintf(fff, "W:%d:%d:0\n", i, j); - } - - /* Skip a line */ - fprintf(fff, "\n"); - } - } - - /* Close */ - my_fclose(fff); - - /* Success */ - return (0); -} - - -/* - * Ask for a "user pref file" and process it. - * - * This function should only be used by standard interaction commands, - * in which a standard "Command:" prompt is present on the given row. - * - * Allow absolute file names? XXX XXX XXX - */ -static void do_cmd_pref_file_hack(int row) -{ - char ftmp[80]; - - - /* Prompt */ - prt("Command: Load a user pref file", row, 0); - - /* Prompt */ - prt("File: ", row + 2, 0); - - /* Default filename */ - strnfmt(ftmp, 80, "%s.prf", player_base); - - /* Ask for a file (or cancel) */ - if (!askfor_aux(ftmp, 80)) return; - - /* Process the given filename */ - if (process_pref_file(ftmp)) - { - /* Mention failure */ - msg_format("Failed to load '%s'!", ftmp); - } - else - { - /* Mention success */ - msg_format("Loaded '%s'.", ftmp); - } -} - - -/* - * Set or unset various options. - * - * The user must use the "Ctrl-R" command to "adapt" to changes - * in any options which control "visual" aspects of the game. - */ -void do_cmd_options(void) -{ - int k; - - - /* Save the screen */ - screen_save(); - - /* Interact */ - while (1) - { - /* Clear screen */ - Term_clear(); - - /* Why are we here */ - prt("Options", 2, 0); - - /* Give some choices */ - prt("(1) User Interface Options", 4, 5); - prt("(2) Disturbance Options", 5, 5); - prt("(3) Game-Play Options", 6, 5); - prt("(4) Efficiency Options", 7, 5); - prt("(5) ToME Options", 8, 5); - prt("(6) Birth Options(read only)", 9, 5); - - /* Special choices */ - prt("(D) Base Delay Factor", 10, 5); - prt("(H) Hitpoint Warning", 11, 5); - prt("(A) Autosave Options", 12, 5); - - /* Automatizer */ - prt("(T) Automatizer", 14, 5); - - - /* Window flags */ - prt("(W) Window Flags", 16, 5); - - /* Cheating */ - prt("(C) Cheating Options", 18, 5); - - /* Dump */ - prt("(U) Dump Options setting", 20, 5); - prt("(O) Load Options setting", 21, 5); - - /* Prompt */ - prt("Command: ", 22, 0); - - /* Get command */ - k = inkey(); - - /* Exit */ - if (k == ESCAPE) break; - - /* Analyze */ - switch (k) - { - /* Load a user pref file */ - case 'o': - case 'O': - { - /* Ask for and load a user pref file */ - do_cmd_pref_file_hack(21); - - break; - } - - /* Append options to a file */ - case 'u': - case 'U': - { - char ftmp[80]; - - /* Prompt */ - prt("Command: Append options to a file", 21, 0); - - /* Prompt */ - prt("File: ", 21, 0); - - /* Default filename */ - strnfmt(ftmp, 80, "%s.prf", player_base); - - /* Ask for a file */ - if (!askfor_aux(ftmp, 80)) continue; - - /* Dump the options */ - if (option_dump(ftmp)) - { - /* Failure */ - msg_print("Failed!"); - } - else - { - /* Success */ - msg_print("Done."); - } - - break; - } - - /* General Options */ - case '1': - { - /* Process the general options */ - do_cmd_options_aux(1, "User Interface Options", FALSE); - - break; - } - - /* Disturbance Options */ - case '2': - { - /* Spawn */ - do_cmd_options_aux(2, "Disturbance Options", FALSE); - - break; - } - - /* Inventory Options */ - case '3': - { - /* Spawn */ - do_cmd_options_aux(3, "Game-Play Options", FALSE); - - break; - } - - /* Efficiency Options */ - case '4': - { - /* Spawn */ - do_cmd_options_aux(4, "Efficiency Options", FALSE); - - break; - } - - /* ToME Options */ - case '5': - { - do_cmd_options_aux(5, "ToME Options", FALSE); - - break; - } - - /* Birth Options - read only */ - case '6': - { - do_cmd_options_aux(6, "Birth Options(read only)", TRUE); - - break; - } - /* Cheating Options */ - case 'C': - { - /* Spawn */ - do_cmd_options_cheat("Cheaters never win"); - - break; - } - - case 't': - case 'T': - { - do_cmd_automatizer(); - break; - } - - case 'a': - case 'A': - { - do_cmd_options_autosave("Autosave"); - - break; - } - - /* Window flags */ - case 'W': - case 'w': - { - /* Spawn */ - do_cmd_options_win(); - - break; - } - - /* Hack -- Delay Speed */ - case 'D': - case 'd': - { - /* Prompt */ - prt("Command: Base Delay Factor", 21, 0); - - /* Get a new value */ - while (1) - { - int msec = delay_factor * delay_factor * delay_factor; - prt(format("Current base delay factor: %d (%d msec)", - delay_factor, msec), 22, 0); - prt("Delay Factor (0-9 or ESC to accept): ", 23, 0); - k = inkey(); - if (k == ESCAPE) break; - if (isdigit(k)) delay_factor = D2I(k); - else bell(); - } - - break; - } - - /* Hack -- hitpoint warning factor */ - case 'H': - case 'h': - { - /* Prompt */ - prt("Command: Hitpoint Warning", 18, 0); - - /* Get a new value */ - while (1) - { - prt(format("Current hitpoint warning: %d0%%", - hitpoint_warn), 22, 0); - prt("Hitpoint Warning (0-9 or ESC to accept): ", 20, 0); - k = inkey(); - if (k == ESCAPE) break; - if (isdigit(k)) hitpoint_warn = D2I(k); - else bell(); - } - - break; - } - - /* Unknown option */ - default: - { - /* Oops */ - bell(); - - break; - } - } - - /* Flush messages */ - msg_print(NULL); - } - - - /* Restore the screen */ - screen_load(); -} - - - -/* - * Ask for a "user pref line" and process it - * - * XXX XXX XXX Allow absolute file names? - */ -void do_cmd_pref(void) -{ - char buf[80]; - - - /* Default */ - strcpy(buf, ""); - - /* Ask for a "user pref command" */ - if (!get_string("Pref: ", buf, 80)) return; - - /* Process that pref command */ - (void)process_pref_file_aux(buf); -} - - -/* - * Hack -- append all current macros to the given file - */ -static errr macro_dump(cptr fname) -{ - int i; - - FILE *fff; - - char buf[1024]; - - - /* Build the filename */ - path_build(buf, 1024, ANGBAND_DIR_USER, fname); - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - /* Append to the file */ - fff = my_fopen(buf, "a"); - - /* Failure */ - if (!fff) return ( -1); - - - /* Skip space */ - fprintf(fff, "\n\n"); - - /* Start dumping */ - fprintf(fff, "# Automatic macro dump\n\n"); - - /* Dump them */ - for (i = 0; i < macro__num; i++) - { - /* Start the macro */ - fprintf(fff, "# Macro '%d'\n\n", i); - - /* Extract the action */ - ascii_to_text(buf, macro__act[i]); - - /* Dump the macro */ - fprintf(fff, "A:%s\n", buf); - - /* Extract the action */ - ascii_to_text(buf, macro__pat[i]); - - /* Dump normal macros */ - fprintf(fff, "P:%s\n", buf); - - /* End the macro */ - fprintf(fff, "\n\n"); - } - - /* Start dumping */ - fprintf(fff, "\n\n\n\n"); - - - /* Close */ - my_fclose(fff); - - /* Success */ - return (0); -} - - -/* - * Hack -- ask for a "trigger" (see below) - * - * Note the complex use of the "inkey()" function from "util.c". - * - * Note that both "flush()" calls are extremely important. - */ -static void do_cmd_macro_aux(char *buf, bool_ macro_screen) -{ - int i, n = 0; - - char tmp[1024]; - - - /* Flush */ - flush(); - - /* Do not process macros */ - inkey_base = TRUE; - - /* First key */ - i = inkey(); - - /* Read the pattern */ - while (i) - { - /* Save the key */ - buf[n++] = i; - - /* Do not process macros */ - inkey_base = TRUE; - - /* Do not wait for keys */ - inkey_scan = TRUE; - - /* Attempt to read a key */ - i = inkey(); - } - - /* Terminate */ - buf[n] = '\0'; - - /* Flush */ - flush(); - - - if (macro_screen) - { - /* Convert the trigger */ - ascii_to_text(tmp, buf); - - /* Hack -- display the trigger */ - Term_addstr( -1, TERM_WHITE, tmp); - } -} - -/* - * Hack -- ask for a keymap "trigger" (see below) - * - * Note that both "flush()" calls are extremely important. This may - * no longer be true, since "util.c" is much simpler now. XXX XXX XXX - */ -static void do_cmd_macro_aux_keymap(char *buf) -{ - char tmp[1024]; - - - /* Flush */ - flush(); - - - /* Get a key */ - buf[0] = inkey(); - buf[1] = '\0'; - - - /* Convert to ascii */ - ascii_to_text(tmp, buf); - - /* Hack -- display the trigger */ - Term_addstr( -1, TERM_WHITE, tmp); - - - /* Flush */ - flush(); -} - - -/* - * Hack -- append all keymaps to the given file - */ -static errr keymap_dump(cptr fname) -{ - int i; - - FILE *fff; - - char key[1024]; - char buf[1024]; - - int mode; - - - /* Keymap mode */ - mode = get_keymap_mode(); - - /* Build the filename */ - path_build(buf, 1024, ANGBAND_DIR_USER, fname); - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - /* Append to the file */ - fff = my_fopen(buf, "a"); - - /* Failure */ - if (!fff) return ( -1); - - - /* Skip space */ - fprintf(fff, "\n\n"); - - /* Start dumping */ - fprintf(fff, "# Automatic keymap dump\n\n"); - - /* Dump them */ - for (i = 0; i < 256; i++) - { - cptr act; - - /* Loop up the keymap */ - act = keymap_act[mode][i]; - - /* Skip empty keymaps */ - if (!act) continue; - - /* Encode the key */ - buf[0] = i; - buf[1] = '\0'; - ascii_to_text(key, buf); - - /* Encode the action */ - ascii_to_text(buf, act); - - /* Dump the macro */ - fprintf(fff, "A:%s\n", buf); - fprintf(fff, "C:%d:%s\n", mode, key); - } - - /* Start dumping */ - fprintf(fff, "\n\n\n"); - - - /* Close */ - my_fclose(fff); - - /* Success */ - return (0); -} - - - -/* - * Interact with "macros" - * - * Note that the macro "action" must be defined before the trigger. - * - * Could use some helpful instructions on this page. XXX XXX XXX - */ -void do_cmd_macros(void) -{ - int i; - - char tmp[1024]; - - char buf[1024]; - - int mode; - - - /* Keymap mode */ - mode = get_keymap_mode(); - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - - /* Enter "icky" mode */ - character_icky = TRUE; - - /* Save screen */ - Term_save(); - - - /* Process requests until done */ - while (1) - { - /* Clear screen */ - Term_clear(); - - /* Describe */ - prt("Interact with Macros", 2, 0); - - - /* Describe that action */ - prt("Current action (if any) shown below:", 20, 0); - - /* Analyze the current action */ - ascii_to_text(buf, macro__buf); - - /* Display the current action */ - prt(buf, 22, 0); - - - /* Selections */ - prt("(1) Load a user pref file", 4, 5); - prt("(2) Append macros to a file", 5, 5); - prt("(3) Query a macro", 6, 5); - prt("(4) Create a macro", 7, 5); - prt("(5) Remove a macro", 8, 5); - prt("(6) Append keymaps to a file", 9, 5); - prt("(7) Query a keymap", 10, 5); - prt("(8) Create a keymap", 11, 5); - prt("(9) Remove a keymap", 12, 5); - prt("(0) Enter a new action", 13, 5); - - /* Prompt */ - prt("Command: ", 16, 0); - - /* Get a command */ - i = inkey(); - - /* Leave */ - if (i == ESCAPE) break; - - /* Load a 'macro' file */ - else if (i == '1') - { - /* Prompt */ - prt("Command: Load a user pref file", 16, 0); - - /* Prompt */ - prt("File: ", 18, 0); - - /* Default filename */ - strnfmt(tmp, 1024, "%s.prf", player_name); - - /* Ask for a file */ - if (!askfor_aux(tmp, 80)) continue; - - /* Process the given filename */ - if (0 != process_pref_file(tmp)) - { - /* Prompt */ - msg_print("Could not load file!"); - } - } - - /* Save macros */ - else if (i == '2') - { - /* Prompt */ - prt("Command: Append macros to a file", 16, 0); - - /* Prompt */ - prt("File: ", 18, 0); - - /* Default filename */ - strnfmt(tmp, 1024, "%s.prf", player_name); - - /* Ask for a file */ - if (!askfor_aux(tmp, 80)) continue; - - /* Dump the macros */ - (void)macro_dump(tmp); - - /* Prompt */ - msg_print("Appended macros."); - } - - /* Query a macro */ - else if (i == '3') - { - int k; - - /* Prompt */ - prt("Command: Query a macro", 16, 0); - - /* Prompt */ - prt("Trigger: ", 18, 0); - - /* Get a macro trigger */ - do_cmd_macro_aux(buf, TRUE); - - /* Acquire action */ - k = macro_find_exact(buf); - - /* Nothing found */ - if (k < 0) - { - /* Prompt */ - msg_print("Found no macro."); - } - - /* Found one */ - else - { - /* Obtain the action */ - strcpy(macro__buf, macro__act[k]); - - /* Analyze the current action */ - ascii_to_text(buf, macro__buf); - - /* Display the current action */ - prt(buf, 22, 0); - - /* Prompt */ - msg_print("Found a macro."); - } - } - - /* Create a macro */ - else if (i == '4') - { - /* Prompt */ - prt("Command: Create a macro", 16, 0); - - /* Prompt */ - prt("Trigger: ", 18, 0); - - /* Get a macro trigger */ - do_cmd_macro_aux(buf, TRUE); - - /* Clear */ - clear_from(20); - - /* Prompt */ - prt("Action: ", 20, 0); - - /* Convert to text */ - ascii_to_text(tmp, macro__buf); - - /* Get an encoded action */ - if (askfor_aux(tmp, 80)) - { - /* Convert to ascii */ - text_to_ascii(macro__buf, tmp); - - /* Link the macro */ - macro_add(buf, macro__buf); - - /* Prompt */ - msg_print("Added a macro."); - } - } - - /* Remove a macro */ - else if (i == '5') - { - /* Prompt */ - prt("Command: Remove a macro", 16, 0); - - /* Prompt */ - prt("Trigger: ", 18, 0); - - /* Get a macro trigger */ - do_cmd_macro_aux(buf, TRUE); - - /* Link the macro */ - macro_add(buf, buf); - - /* Prompt */ - msg_print("Removed a macro."); - } - - /* Save keymaps */ - else if (i == '6') - { - /* Prompt */ - prt("Command: Append keymaps to a file", 16, 0); - - /* Prompt */ - prt("File: ", 18, 0); - - /* Default filename */ - strnfmt(tmp, 1024, "%s.prf", player_name); - - /* Ask for a file */ - if (!askfor_aux(tmp, 80)) continue; - - /* Dump the macros */ - (void)keymap_dump(tmp); - - /* Prompt */ - msg_print("Appended keymaps."); - } - - /* Query a keymap */ - else if (i == '7') - { - cptr act; - - /* Prompt */ - prt("Command: Query a keymap", 16, 0); - - /* Prompt */ - prt("Keypress: ", 18, 0); - - /* Get a keymap trigger */ - do_cmd_macro_aux_keymap(buf); - - /* Look up the keymap */ - act = keymap_act[mode][(byte)(buf[0])]; - - /* Nothing found */ - if (!act) - { - /* Prompt */ - msg_print("Found no keymap."); - } - - /* Found one */ - else - { - /* Obtain the action */ - strcpy(macro__buf, act); - - /* Analyze the current action */ - ascii_to_text(buf, macro__buf); - - /* Display the current action */ - prt(buf, 22, 0); - - /* Prompt */ - msg_print("Found a keymap."); - } - } - - /* Create a keymap */ - else if (i == '8') - { - /* Prompt */ - prt("Command: Create a keymap", 16, 0); - - /* Prompt */ - prt("Keypress: ", 18, 0); - - /* Get a keymap trigger */ - do_cmd_macro_aux_keymap(buf); - - /* Clear */ - clear_from(20); - - /* Prompt */ - prt("Action: ", 20, 0); - - /* Convert to text */ - ascii_to_text(tmp, macro__buf); - - /* Get an encoded action */ - if (askfor_aux(tmp, 80)) - { - /* Convert to ascii */ - text_to_ascii(macro__buf, tmp); - - /* Free old keymap */ - string_free(keymap_act[mode][(byte)(buf[0])]); - - /* Make new keymap */ - keymap_act[mode][(byte)(buf[0])] = string_make(macro__buf); - - /* Prompt */ - msg_print("Added a keymap."); - } - } - - /* Remove a keymap */ - else if (i == '9') - { - /* Prompt */ - prt("Command: Remove a keymap", 16, 0); - - /* Prompt */ - prt("Keypress: ", 18, 0); - - /* Get a keymap trigger */ - do_cmd_macro_aux_keymap(buf); - - /* Free old keymap */ - string_free(keymap_act[mode][(byte)(buf[0])]); - - /* Make new keymap */ - keymap_act[mode][(byte)(buf[0])] = NULL; - - /* Prompt */ - msg_print("Removed a keymap."); - } - - /* Enter a new action */ - else if (i == '0') - { - /* Prompt */ - prt("Command: Enter a new action", 16, 0); - - /* Go to the correct location */ - Term_gotoxy(0, 22); - - /* Hack -- limit the value */ - tmp[80] = '\0'; - - /* Get an encoded action */ - if (!askfor_aux(buf, 80)) continue; - - /* Extract an action */ - text_to_ascii(macro__buf, buf); - } - - /* Oops */ - else - { - /* Oops */ - bell(); - } - - /* Flush messages */ - msg_print(NULL); - } - - /* Load screen */ - Term_load(); - - /* Leave "icky" mode */ - character_icky = FALSE; -} - - -/* - * Interact with "visuals" - */ -void do_cmd_visuals(void) -{ - int i; - - FILE *fff; - - char tmp[160]; - - char buf[1024]; - - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - - /* Enter "icky" mode */ - character_icky = TRUE; - - /* Save the screen */ - Term_save(); - - - /* Interact until done */ - while (1) - { - /* Clear screen */ - Term_clear(); - - /* Ask for a choice */ - prt("Interact with Visuals", 2, 0); - - /* Give some choices */ - prt("(1) Load a user pref file", 4, 5); - prt("(2) Dump monster attr/chars", 5, 5); - prt("(3) Dump object attr/chars", 6, 5); - prt("(4) Dump feature attr/chars", 7, 5); - prt("(5) (unused)", 8, 5); - prt("(6) Change monster attr/chars", 9, 5); - prt("(7) Change object attr/chars", 10, 5); - prt("(8) Change feature attr/chars", 11, 5); - prt("(9) (unused)", 12, 5); - prt("(0) Reset visuals", 13, 5); - - /* Prompt */ - prt("Command: ", 15, 0); - - /* Prompt */ - i = inkey(); - - /* Done */ - if (i == ESCAPE) break; - - /* Load a 'pref' file */ - else if (i == '1') - { - /* Prompt */ - prt("Command: Load a user pref file", 15, 0); - - /* Prompt */ - prt("File: ", 17, 0); - - /* Default filename */ - strnfmt(tmp, 160, "user-%s.prf", ANGBAND_SYS); - - /* Query */ - if (!askfor_aux(tmp, 70)) continue; - - /* Process the given filename */ - (void)process_pref_file(tmp); - } - - /* Dump monster attr/chars */ - else if (i == '2') - { - /* Prompt */ - prt("Command: Dump monster attr/chars", 15, 0); - - /* Prompt */ - prt("File: ", 17, 0); - - /* Default filename */ - strnfmt(tmp, 160, "user-%s.prf", ANGBAND_SYS); - - /* Get a filename */ - if (!askfor_aux(tmp, 70)) continue; - - /* Build the filename */ - path_build(buf, 1024, ANGBAND_DIR_USER, tmp); - - /* Append to the file */ - fff = my_fopen(buf, "a"); - - /* Failure */ - if (!fff) continue; - - /* Start dumping */ - fprintf(fff, "\n\n"); - fprintf(fff, "# Monster attr/char definitions\n\n"); - - /* Dump monsters */ - for (i = 0; i < max_r_idx; i++) - { - monster_race *r_ptr = &r_info[i]; - - /* Skip non-entries */ - if (!r_ptr->name) continue; - - /* Dump a comment */ - fprintf(fff, "# %s\n", (r_name + r_ptr->name)); - - /* Dump the monster attr/char info */ - fprintf(fff, "R:%d:0x%02X:0x%02X\n\n", i, - (byte)(r_ptr->x_attr), (byte)(r_ptr->x_char)); - } - - /* All done */ - fprintf(fff, "\n\n\n\n"); - - /* Close */ - my_fclose(fff); - - /* Message */ - msg_print("Dumped monster attr/chars."); - } - - /* Dump object attr/chars */ - else if (i == '3') - { - /* Prompt */ - prt("Command: Dump object attr/chars", 15, 0); - - /* Prompt */ - prt("File: ", 17, 0); - - /* Default filename */ - strnfmt(tmp, 160, "user-%s.prf", ANGBAND_SYS); - - /* Get a filename */ - if (!askfor_aux(tmp, 70)) continue; - - /* Build the filename */ - path_build(buf, 1024, ANGBAND_DIR_USER, tmp); - - /* Append to the file */ - fff = my_fopen(buf, "a"); - - /* Failure */ - if (!fff) continue; - - /* Start dumping */ - fprintf(fff, "\n\n"); - fprintf(fff, "# Object attr/char definitions\n\n"); - - /* Dump objects */ - for (i = 0; i < max_k_idx; i++) - { - object_kind *k_ptr = &k_info[i]; - - /* Skip non-entries */ - if (!k_ptr->name) continue; - - /* Dump a comment */ - fprintf(fff, "# %s\n", (k_name + k_ptr->name)); - - /* Dump the object attr/char info */ - fprintf(fff, "K:%d:0x%02X:0x%02X\n\n", i, - (byte)(k_ptr->x_attr), (byte)(k_ptr->x_char)); - } - - /* All done */ - fprintf(fff, "\n\n\n\n"); - - /* Close */ - my_fclose(fff); - - /* Message */ - msg_print("Dumped object attr/chars."); - } - - /* Dump feature attr/chars */ - else if (i == '4') - { - /* Prompt */ - prt("Command: Dump feature attr/chars", 15, 0); - - /* Prompt */ - prt("File: ", 17, 0); - - /* Default filename */ - strnfmt(tmp, 160, "user-%s.prf", ANGBAND_SYS); - - /* Get a filename */ - if (!askfor_aux(tmp, 70)) continue; - - /* Build the filename */ - path_build(buf, 1024, ANGBAND_DIR_USER, tmp); - - /* Append to the file */ - fff = my_fopen(buf, "a"); - - /* Failure */ - if (!fff) continue; - - /* Start dumping */ - fprintf(fff, "\n\n"); - fprintf(fff, "# Feature attr/char definitions\n\n"); - - /* Dump features */ - for (i = 0; i < max_f_idx; i++) - { - feature_type *f_ptr = &f_info[i]; - - /* Skip non-entries */ - if (!f_ptr->name) continue; - - /* Dump a comment */ - fprintf(fff, "# %s\n", (f_name + f_ptr->name)); - - /* Dump the feature attr/char info */ - fprintf(fff, "F:%d:0x%02X:0x%02X\n\n", i, - (byte)(f_ptr->x_attr), (byte)(f_ptr->x_char)); - } - - /* All done */ - fprintf(fff, "\n\n\n\n"); - - /* Close */ - my_fclose(fff); - - /* Message */ - msg_print("Dumped feature attr/chars."); - } - - /* Modify monster attr/chars */ - else if (i == '6') - { - static int r = 0; - - /* Prompt */ - prt("Command: Change monster attr/chars", 15, 0); - - /* Hack -- query until done */ - while (1) - { - monster_race *r_ptr = &r_info[r]; - - byte da = (r_ptr->d_attr); - char dc = (r_ptr->d_char); - byte ca = (r_ptr->x_attr); - char cc = (r_ptr->x_char); - - /* Label the object */ - Term_putstr(5, 17, -1, TERM_WHITE, - format("Monster = %d, Name = %-40.40s", - r, (r_name + r_ptr->name))); - - /* Label the Default values */ - Term_putstr(10, 19, -1, TERM_WHITE, - format("Default attr/char = %3u / %3u", da, (dc & 0xFF))); - Term_putstr(40, 19, -1, TERM_WHITE, "<< ? >>"); - Term_putch(43, 19, da, dc); - if (use_bigtile) - { - if (da & 0x80) - Term_putch(44, 19, 255, 255); - else - Term_putch(44, 19, 0, ' '); - } - - /* Label the Current values */ - Term_putstr(10, 20, -1, TERM_WHITE, - format("Current attr/char = %3u / %3u", ca, (cc & 0xFF))); - Term_putstr(40, 20, -1, TERM_WHITE, "<< ? >>"); - Term_putch(43, 20, ca, cc); - if (use_bigtile) - { - if (ca & 0x80) - Term_putch(44, 20, 255, 255); - else - Term_putch(44, 20, 0, ' '); - } - - /* Prompt */ - Term_putstr(0, 22, -1, TERM_WHITE, - "Command (n/N/a/A/c/C): "); - - /* Get a command */ - i = inkey(); - - /* All done */ - if (i == ESCAPE) break; - - /* Analyze */ - if (i == 'n') r = (r + max_r_idx + 1) % max_r_idx; - if (i == 'N') r = (r + max_r_idx - 1) % max_r_idx; - if (i == 'a') r_ptr->x_attr = (ca + 1); - if (i == 'A') r_ptr->x_attr = (ca - 1); - if (i == 'c') r_ptr->x_char = (cc + 1); - if (i == 'C') r_ptr->x_char = (cc - 1); - } - } - - /* Modify object attr/chars */ - else if (i == '7') - { - static int k = 0; - - /* Prompt */ - prt("Command: Change object attr/chars", 15, 0); - - /* Hack -- query until done */ - while (1) - { - object_kind *k_ptr = &k_info[k]; - - byte da = k_ptr->d_attr; - char dc = k_ptr->d_char; - byte ca = k_ptr->x_attr; - char cc = k_ptr->x_char; - - /* Label the object */ - Term_putstr(5, 17, -1, TERM_WHITE, - format("Object = %d, Name = %-40.40s", - k, (k_name + k_ptr->name))); - - /* Label the Default values */ - Term_putstr(10, 19, -1, TERM_WHITE, - format("Default attr/char = %3u / %3u", da, (dc & 0xFF))); - Term_putstr(40, 19, -1, TERM_WHITE, "<< ? >>"); - Term_putch(43, 19, da, dc); - if (use_bigtile) - { - if (da & 0x80) - Term_putch(44, 19, 255, 255); - else - Term_putch(44, 19, 0, ' '); - } - - /* Label the Current values */ - Term_putstr(10, 20, -1, TERM_WHITE, - format("Current attr/char = %3u / %3u", ca, (cc & 0xFF))); - Term_putstr(40, 20, -1, TERM_WHITE, "<< ? >>"); - Term_putch(43, 20, ca, cc); - if (use_bigtile) - { - if (ca & 0x80) - Term_putch(44, 20, 255, 255); - else - Term_putch(44, 20, 0, ' '); - } - - /* Prompt */ - Term_putstr(0, 22, -1, TERM_WHITE, - "Command (n/N/a/A/c/C): "); - - /* Get a command */ - i = inkey(); - - /* All done */ - if (i == ESCAPE) break; - - /* Analyze */ - if (i == 'n') k = (k + max_k_idx + 1) % max_k_idx; - if (i == 'N') k = (k + max_k_idx - 1) % max_k_idx; - if (i == 'a') k_info[k].x_attr = (ca + 1); - if (i == 'A') k_info[k].x_attr = (ca - 1); - if (i == 'c') k_info[k].x_char = (cc + 1); - if (i == 'C') k_info[k].x_char = (cc - 1); - } - } - - /* Modify feature attr/chars */ - else if (i == '8') - { - static int f = 0; - - /* Prompt */ - prt("Command: Change feature attr/chars", 15, 0); - - /* Hack -- query until done */ - while (1) - { - feature_type *f_ptr = &f_info[f]; - - byte da = f_ptr->d_attr; - char dc = f_ptr->d_char; - byte ca = f_ptr->x_attr; - char cc = f_ptr->x_char; - - /* Label the object */ - Term_putstr(5, 17, -1, TERM_WHITE, - format("Terrain = %d, Name = %-40.40s", - f, (f_name + f_ptr->name))); - - /* Label the Default values */ - Term_putstr(10, 19, -1, TERM_WHITE, - format("Default attr/char = %3u / %3u", da, (dc & 0xFF))); - Term_putstr(40, 19, -1, TERM_WHITE, "<< ? >>"); - Term_putch(43, 19, da, dc); - if (use_bigtile) - { - if (da & 0x80) - Term_putch(44, 19, 255, 255); - else - Term_putch(44, 19, 0, ' '); - } - - /* Label the Current values */ - Term_putstr(10, 20, -1, TERM_WHITE, - format("Current attr/char = %3u / %3u", ca, (cc & 0xFF))); - Term_putstr(40, 20, -1, TERM_WHITE, "<< ? >>"); - Term_putch(43, 20, ca, cc); - if (use_bigtile) - { - if (ca & 0x80) - Term_putch(44, 20, 255, 255); - else - Term_putch(44, 20, 0, ' '); - } - - /* Prompt */ - Term_putstr(0, 22, -1, TERM_WHITE, - "Command (n/N/a/A/c/C/d): "); - - /* Get a command */ - i = inkey(); - - /* All done */ - if (i == ESCAPE) break; - - /* Analyze */ - if (i == 'n') f = (f + max_f_idx + 1) % max_f_idx; - if (i == 'N') f = (f + max_f_idx - 1) % max_f_idx; - if (i == 'a') f_info[f].x_attr = (ca + 1); - if (i == 'A') f_info[f].x_attr = (ca - 1); - if (i == 'c') f_info[f].x_char = (cc + 1); - if (i == 'C') f_info[f].x_char = (cc - 1); - if (i == 'd') - { - f_info[f].x_char = f_ptr->d_char; - f_info[f].x_attr = f_ptr->d_attr; - } - } - } - - /* Reset visuals */ - else if (i == '0') - { - /* Reset */ - reset_visuals(); - - /* Message */ - msg_print("Visual attr/char tables reset."); - } - - /* Unknown option */ - else - { - bell(); - } - - /* Flush messages */ - msg_print(NULL); - } - - - /* Restore the screen */ - Term_load(); - - /* Leave "icky" mode */ - character_icky = FALSE; -} - - -/* - * Interact with "colors" - */ -void do_cmd_colors(void) -{ - int i; - - FILE *fff; - - char tmp[160]; - - char buf[1024]; - - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - - /* Enter "icky" mode */ - character_icky = TRUE; - - /* Save the screen */ - Term_save(); - - - /* Interact until done */ - while (1) - { - /* Clear screen */ - Term_clear(); - - /* Ask for a choice */ - prt("Interact with Colors", 2, 0); - - /* Give some choices */ - prt("(1) Load a user pref file", 4, 5); - prt("(2) Dump colors", 5, 5); - prt("(3) Modify colors", 6, 5); - - /* Prompt */ - prt("Command: ", 8, 0); - - /* Prompt */ - i = inkey(); - - /* Done */ - if (i == ESCAPE) break; - - /* Load a 'pref' file */ - if (i == '1') - { - /* Prompt */ - prt("Command: Load a user pref file", 8, 0); - - /* Prompt */ - prt("File: ", 10, 0); - - /* Default file */ - strnfmt(tmp, 160, "user-%s.prf", ANGBAND_SYS); - - /* Query */ - if (!askfor_aux(tmp, 70)) continue; - - /* Process the given filename */ - (void)process_pref_file(tmp); - - /* Mega-Hack -- react to changes */ - Term_xtra(TERM_XTRA_REACT, 0); - - /* Mega-Hack -- redraw */ - Term_redraw(); - } - - /* Dump colors */ - else if (i == '2') - { - /* Prompt */ - prt("Command: Dump colors", 8, 0); - - /* Prompt */ - prt("File: ", 10, 0); - - /* Default filename */ - strnfmt(tmp, 160, "user-%s.prf", ANGBAND_SYS); - - /* Get a filename */ - if (!askfor_aux(tmp, 70)) continue; - - /* Build the filename */ - path_build(buf, 1024, ANGBAND_DIR_USER, tmp); - - /* Append to the file */ - fff = my_fopen(buf, "a"); - - /* Failure */ - if (!fff) continue; - - /* Start dumping */ - fprintf(fff, "\n\n"); - fprintf(fff, "# Color redefinitions\n\n"); - - /* Dump colors */ - for (i = 0; i < 256; i++) - { - int kv = angband_color_table[i][0]; - int rv = angband_color_table[i][1]; - int gv = angband_color_table[i][2]; - int bv = angband_color_table[i][3]; - - cptr name = "unknown"; - - /* Skip non-entries */ - if (!kv && !rv && !gv && !bv) continue; - - /* Extract the color name */ - if (i < 16) name = color_names[i]; - - /* Dump a comment */ - fprintf(fff, "# Color '%s'\n", name); - - /* Dump the monster attr/char info */ - fprintf(fff, "V:%d:0x%02X:0x%02X:0x%02X:0x%02X\n\n", - i, kv, rv, gv, bv); - } - - /* All done */ - fprintf(fff, "\n\n\n\n"); - - /* Close */ - my_fclose(fff); - - /* Message */ - msg_print("Dumped color redefinitions."); - } - - /* Edit colors */ - else if (i == '3') - { - static byte a = 0; - - /* Prompt */ - prt("Command: Modify colors", 8, 0); - - /* Hack -- query until done */ - while (1) - { - cptr name; - - /* Clear */ - clear_from(10); - - /* Exhibit the normal colors */ - for (i = 0; i < 16; i++) - { - /* Exhibit this color */ - Term_putstr(i*4, 20, -1, a, "###"); - - /* Exhibit all colors */ - Term_putstr(i*4, 22, -1, i, format("%3d", i)); - } - - /* Describe the color */ - name = ((a < 16) ? color_names[a] : "undefined"); - - /* Describe the color */ - Term_putstr(5, 10, -1, TERM_WHITE, - format("Color = %d, Name = %s", a, name)); - - /* Label the Current values */ - Term_putstr(5, 12, -1, TERM_WHITE, - format("K = 0x%02x / R,G,B = 0x%02x,0x%02x,0x%02x", - angband_color_table[a][0], - angband_color_table[a][1], - angband_color_table[a][2], - angband_color_table[a][3])); - - /* Prompt */ - Term_putstr(0, 14, -1, TERM_WHITE, - "Command (n/N/k/K/r/R/g/G/b/B): "); - - /* Get a command */ - i = inkey(); - - /* All done */ - if (i == ESCAPE) break; - - /* Analyze */ - if (i == 'n') a = (a + 1); - if (i == 'N') a = (a - 1); - if (i == 'k') angband_color_table[a][0] = (angband_color_table[a][0] + 1); - if (i == 'K') angband_color_table[a][0] = (angband_color_table[a][0] - 1); - if (i == 'r') angband_color_table[a][1] = (angband_color_table[a][1] + 1); - if (i == 'R') angband_color_table[a][1] = (angband_color_table[a][1] - 1); - if (i == 'g') angband_color_table[a][2] = (angband_color_table[a][2] + 1); - if (i == 'G') angband_color_table[a][2] = (angband_color_table[a][2] - 1); - if (i == 'b') angband_color_table[a][3] = (angband_color_table[a][3] + 1); - if (i == 'B') angband_color_table[a][3] = (angband_color_table[a][3] - 1); - - /* Hack -- react to changes */ - Term_xtra(TERM_XTRA_REACT, 0); - - /* Hack -- redraw */ - Term_redraw(); - } - } - - /* Unknown option */ - else - { - bell(); - } - - /* Flush messages */ - msg_print(NULL); - } - - - /* Restore the screen */ - Term_load(); - - /* Leave "icky" mode */ - character_icky = FALSE; -} - - -/* - * Take notes. There are two ways this can happen, either in the message - * recall or a file. - */ -void do_cmd_note(void) -{ - char buf[80]; - - - /* Default */ - strcpy(buf, ""); - - if (!get_string("Note: ", buf, 60)) return; - - /* Ignore empty notes */ - if (!buf[0] || (buf[0] == ' ')) return; - - /* Add note to file */ - add_note(buf, ' '); -} - - -/* - * Mention the current version - */ -void do_cmd_version(void) -{ - /* Silly message */ - msg_format("You are playing %s made by %s (%s).", - get_version_string(), - modules[game_module_idx].meta.author.name, - modules[game_module_idx].meta.author.email); -} - - - -/* - * Array of feeling strings - */ -static cptr do_cmd_feeling_text[11] = -{ - "Looks like any other level.", - "You feel there is something special about this level.", - "You have a superb feeling about this level.", - "You have an excellent feeling...", - "You have a very good feeling...", - "You have a good feeling...", - "You feel strangely lucky...", - "You feel your luck is turning...", - "You like the look of this place...", - "This level can't be all bad...", - "What a boring place..." -}; - - -/* - * Note that "feeling" is set to zero unless some time has passed. - * Note that this is done when the level is GENERATED, not entered. - */ -void do_cmd_feeling(void) -{ - /* Verify the feeling */ - if (feeling < 0) feeling = 0; - if (feeling > 10) feeling = 10; - - /* Feeling of the fate */ - if (fate_flag && !(dungeon_flags2 & DF2_SPECIAL) && !p_ptr->inside_quest) - { - msg_print("You feel that you will meet your fate here."); - } - - /* Hooked feelings ? */ - if (process_hooks(HOOK_FEELING, "(d)", is_quest(dun_level))) - { - return; - } - - /* No useful feeling in special levels */ - if (dungeon_flags2 & DF2_DESC) - { - char buf[1024]; - - if ((get_dungeon_save(buf)) || (generate_special_feeling) || (dungeon_flags2 & DF2_DESC_ALWAYS)) - { - if (!get_level_desc(buf)) msg_print("Someone forgot to describe this level!"); - else msg_print(buf); - return; - } - } - - /* No useful feeling in quests */ - if (p_ptr->inside_quest) - { - msg_print("Looks like a typical quest level."); - return; - } - - /* Display feelings in the dungeon, nothing on the surface */ - if (dun_level) - { - /* This could be simplified with a correct p_ptr->town_num */ - int i, town_level = 0; - dungeon_info_type *d_ptr = &d_info[dungeon_type]; - - /* Is it a town level ? */ - for (i = 0; i < TOWN_DUNGEON; i++) - { - if (d_ptr->t_level[i] == dun_level) town_level = d_ptr->t_idx[i]; - } - - if (town_level) - msg_print("You hear the sound of a market."); - else - msg_print(do_cmd_feeling_text[feeling]); - } - return; -} - - - -/* - * Encode the screen colors - */ -static char hack[17] = "dwsorgbuDWvyRGBU"; - - -/* - * Hack -- load a screen dump from a file - */ -void do_cmd_load_screen(void) -{ - int i, y, x; - - int wid, hgt; - int len; - - byte a = 0; - char c = ' '; - - bool_ okay = TRUE; - - FILE *fff; - - char buf[1024]; - - - /* Build the filename */ - path_build(buf, 1024, ANGBAND_DIR_USER, "dump.txt"); - - /* Append to the file */ - fff = my_fopen(buf, "r"); - - /* Oops */ - if (!fff) return; - - - /* Retrieve the current screen size */ - Term_get_size(&wid, &hgt); - - /* Enter "icky" mode */ - character_icky = TRUE; - - /* Save the screen */ - Term_save(); - - /* Clear the screen */ - Term_clear(); - - - /* Load the screen */ - for (y = 0; okay; y++) - { - /* Get a line of data */ - if (my_fgets(fff, buf, 1024)) okay = FALSE; - - /* Stop on blank line */ - if (!buf[0]) break; - - /* Ignore off screen lines */ - if (y >= hgt) continue; - - /* Get width */ - len = strlen(buf); - - /* Truncate if it's longer than current screen width */ - if (len > wid) len = wid; - - /* Show each row */ - for (x = 0; x < len; x++) - { - /* Put the attr/char */ - Term_draw(x, y, TERM_WHITE, buf[x]); - } - } - - /* Dump the screen */ - for (y = 0; okay; y++) - { - /* Get a line of data */ - if (my_fgets(fff, buf, 1024)) okay = FALSE; - - /* Stop on blank line */ - if (!buf[0]) break; - - /* Ignore off screen lines */ - if (y >= hgt) continue; - - /* Get width */ - len = strlen(buf); - - /* Truncate if it's longer than current screen width */ - if (len > wid) len = wid; - - /* Dump each row */ - for (x = 0; x < len; x++) - { - /* Get the attr/char */ - (void)(Term_what(x, y, &a, &c)); - - /* Look up the attr */ - for (i = 0; i < 16; i++) - { - /* Use attr matches */ - if (hack[i] == buf[x]) a = i; - } - - /* Put the attr/char */ - Term_draw(x, y, a, c); - } - } - - - /* Close it */ - my_fclose(fff); - - - /* Message */ - msg_print("Screen dump loaded."); - msg_print(NULL); - - - /* Restore the screen */ - Term_load(); - - /* Leave "icky" mode */ - character_icky = FALSE; -} - - - -/* - * Redefinable "save_screen" action - */ -void (*screendump_aux)(void) = NULL; - - - - - - -/* - * Hack -- save a screen dump to a file - */ -void do_cmd_save_screen(void) -{ - /* Do we use a special screendump function ? */ - if (screendump_aux) - { - /* Dump the screen to a graphics file */ - (*screendump_aux)(); - } - - /* Dump the screen as text */ - else - { - int y, x; - int wid, hgt; - - byte a = 0; - char c = ' '; - - FILE *fff; - - char buf[1024]; - - - /* Build the filename */ - path_build(buf, 1024, ANGBAND_DIR_USER, "dump.txt"); - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - /* Append to the file */ - fff = my_fopen(buf, "w"); - - /* Oops */ - if (!fff) return; - - - /* Retrieve the current screen size */ - Term_get_size(&wid, &hgt); - - /* Enter "icky" mode */ - character_icky = TRUE; - - /* Save the screen */ - Term_save(); - - - /* Dump the screen */ - for (y = 0; y < hgt; y++) - { - /* Dump each row */ - for (x = 0; x < wid; x++) - { - /* Get the attr/char */ - (void)(Term_what(x, y, &a, &c)); - - /* Dump it */ - buf[x] = c; - } - - /* Terminate */ - buf[x] = '\0'; - - /* End the row */ - fprintf(fff, "%s\n", buf); - } - - /* Skip a line */ - fprintf(fff, "\n"); - - - /* Dump the screen */ - for (y = 0; y < hgt; y++) - { - /* Dump each row */ - for (x = 0; x < wid; x++) - { - /* Get the attr/char */ - (void)(Term_what(x, y, &a, &c)); - - /* Dump it */ - buf[x] = hack[a & 0x0F]; - } - - /* Terminate */ - buf[x] = '\0'; - - /* End the row */ - fprintf(fff, "%s\n", buf); - } - - /* Skip a line */ - fprintf(fff, "\n"); - - - /* Close it */ - my_fclose(fff); - - - /* Message */ - msg_print("Screen dump saved."); - msg_print(NULL); - - - /* Restore the screen */ - Term_load(); - - /* Leave "icky" mode */ - character_icky = FALSE; - } -} - - -/* - * Check the status of "artifacts" - */ -void do_cmd_knowledge_artifacts(void) -{ - int i, k, z, x, y; - - FILE *fff; - - char file_name[1024]; - - char base_name[80]; - - bool_ *okay, *okayk; - - - /* Allocate the "okay" array */ - C_MAKE(okay, max_a_idx, bool_); - C_MAKE(okayk, max_k_idx, bool_); - - /* Temporary file */ - if (path_temp(file_name, 1024)) return; - - /* Open a new file */ - fff = my_fopen(file_name, "w"); - - /* Scan the artifacts */ - for (k = 0; k < max_a_idx; k++) - { - artifact_type *a_ptr = &a_info[k]; - - /* Default */ - okay[k] = FALSE; - - /* Skip "empty" artifacts */ - if (!a_ptr->name) continue; - - /* Skip "uncreated" artifacts */ - if (!a_ptr->cur_num) continue; - - /* Assume okay */ - okay[k] = TRUE; - } - - for (k = 0; k < max_k_idx; k++) - { - object_kind *k_ptr = &k_info[k]; - - /* Default */ - okayk[k] = FALSE; - - /* Skip "empty" artifacts */ - if (!(k_ptr->flags3 & TR3_NORM_ART)) continue; - - /* Skip "uncreated" artifacts */ - if (!k_ptr->artifact) continue; - - /* Assume okay */ - okayk[k] = TRUE; - } - - /* Check the dungeon */ - for (y = 0; y < cur_hgt; y++) - { - for (x = 0; x < cur_wid; x++) - { - cave_type *c_ptr = &cave[y][x]; - - s16b this_o_idx, next_o_idx = 0; - - /* Scan all objects in the grid */ - for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) - { - object_type * o_ptr; - - /* Acquire object */ - o_ptr = &o_list[this_o_idx]; - - /* Acquire next object */ - next_o_idx = o_ptr->next_o_idx; - - /* Ignore random artifacts */ - if (o_ptr->tval == TV_RANDART) continue; - - /* Ignore non-artifacts */ - if (!artifact_p(o_ptr)) continue; - - /* Ignore known items */ - if (object_known_p(o_ptr)) continue; - - /* Note the artifact */ - if (k_info[o_ptr->k_idx].flags3 & TR3_NORM_ART) - { - okayk[o_ptr->k_idx] = FALSE; - } - else - { - okay[o_ptr->name1] = FALSE; - } - } - } - } - - /* Check monsters in the dungeon */ - for (i = 0; i < m_max; i++) - { - monster_type *m_ptr = &m_list[i]; - - s16b this_o_idx, next_o_idx = 0; - - /* Scan all objects the monster carries */ - for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx) - { - object_type * o_ptr; - - /* Acquire object */ - o_ptr = &o_list[this_o_idx]; - - /* Acquire next object */ - next_o_idx = o_ptr->next_o_idx; - - /* Ignore random artifacts */ - if (o_ptr->tval == TV_RANDART) continue; - - /* Ignore non-artifacts */ - if (!artifact_p(o_ptr)) continue; - - /* Ignore known items */ - if (object_known_p(o_ptr)) continue; - - /* Note the artifact */ - if (k_info[o_ptr->k_idx].flags3 & TR3_NORM_ART) - { - okayk[o_ptr->k_idx] = FALSE; - } - else - { - okay[o_ptr->name1] = FALSE; - } - } - } - - /* Check the p_ptr->inventory and equipment */ - for (i = 0; i < INVEN_TOTAL; i++) - { - object_type *o_ptr = &p_ptr->inventory[i]; - - /* Ignore non-objects */ - if (!o_ptr->k_idx) continue; - - /* Ignore random artifacts */ - if (o_ptr->tval == TV_RANDART) continue; - - /* Ignore non-artifacts */ - if (!artifact_p(o_ptr)) continue; - - /* Ignore known items */ - if (object_known_p(o_ptr)) continue; - - /* Note the artifact */ - if (k_info[o_ptr->k_idx].flags3 & TR3_NORM_ART) - { - okayk[o_ptr->k_idx] = FALSE; - } - else - { - okay[o_ptr->name1] = FALSE; - } - } - - /* Scan the artifacts */ - for (k = 0; k < max_a_idx; k++) - { - artifact_type *a_ptr = &a_info[k]; - - /* List "dead" ones */ - if (!okay[k]) continue; - - /* Paranoia */ - strcpy(base_name, "Unknown Artifact"); - - /* Obtain the base object type */ - z = lookup_kind(a_ptr->tval, a_ptr->sval); - - /* Real object */ - if (z) - { - object_type forge; - object_type *q_ptr; - u32b f1, f2, f3, f4, f5, esp; - - /* Get local object */ - q_ptr = &forge; - - /* Create fake object */ - object_prep(q_ptr, z); - - /* Make it an artifact */ - q_ptr->name1 = k; - - /* Spell in it ? no ! */ - object_flags(q_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - if (f5 & TR5_SPELL_CONTAIN) - q_ptr->pval2 = -1; - - /* Describe the artifact */ - object_desc_store(base_name, q_ptr, FALSE, 0); - } - - /* Hack -- Build the artifact name */ - fprintf(fff, " The %s\n", base_name); - } - - for (k = 0; k < max_k_idx; k++) - { - /* List "dead" ones */ - if (!okayk[k]) continue; - - /* Paranoia */ - strcpy(base_name, "Unknown Artifact"); - - /* Real object */ - if (k) - { - object_type forge; - object_type *q_ptr; - - /* Get local object */ - q_ptr = &forge; - - /* Create fake object */ - object_prep(q_ptr, k); - - /* Describe the artifact */ - object_desc_store(base_name, q_ptr, FALSE, 0); - } - - /* Hack -- Build the artifact name */ - fprintf(fff, " The %s\n", base_name); - } - - /* Close the file */ - my_fclose(fff); - - /* Display the file contents */ - show_file(file_name, "Artifacts Seen", 0, 0); - - /* Remove the file */ - fd_kill(file_name); - - C_FREE(okay, max_a_idx, bool_); - C_FREE(okayk, max_k_idx, bool_); -} - - -/* - * Check the status of traps - */ -void do_cmd_knowledge_traps(void) -{ - int k; - - FILE *fff; - - trap_type *t_ptr; - - char file_name[1024]; - - - /* Temporary file */ - if (path_temp(file_name, 1024)) return; - - /* Open a new file */ - fff = my_fopen(file_name, "w"); - - /* Scan the traps */ - for (k = 0; k < max_t_idx; k++) - { - /* Get the trap */ - t_ptr = &t_info[k]; - - /* Skip "empty" traps */ - if (!t_ptr->name) continue; - - /* Skip unidentified traps */ - if (!t_ptr->ident) continue; - - /* Hack -- Build the trap name */ - fprintf(fff, " %s\n", t_name + t_ptr->name); - } - - /* Close the file */ - my_fclose(fff); - - /* Display the file contents */ - show_file(file_name, "Traps known", 0, 0); - - /* Remove the file */ - fd_kill(file_name); -} - - -/* - * Display known uniques - * - * Note that the player ghosts are ignored. XXX XXX XXX - */ -static void insert_sort_unique(int *sort_uniques, int *num, int r_idx) -{ - int i, j; - - monster_race *r_ptr = &r_info[r_idx]; - - int level = r_ptr->level; - - - /* Hack -- Morgoth is always at the bottom of the list */ - if (r_idx == 862) level = 20000; - - /* Find the place */ - for (i = 0; i < *num; i++) - { - monster_race *r2_ptr = &r_info[sort_uniques[i]]; - int level2 = r2_ptr->level; - - if (sort_uniques[i] == 862) level2 = 20000; - - if (level < level2) break; - } - - /* Move the remaining items */ - for (j = *num - 1; j >= i; j--) - { - sort_uniques[j + 1] = sort_uniques[j]; - } - - /* Insert it */ - sort_uniques[i] = r_idx; - (*num)++; -} - - -static void do_cmd_knowledge_uniques(void) -{ - int k; - - int *sort_uniques; - - int num = 0; - - FILE *fff; - - char file_name[1024]; - - - /* Temporary file */ - if (path_temp(file_name, 1024)) return; - - /* Open a new file */ - fff = my_fopen(file_name, "w"); - - C_MAKE(sort_uniques, max_r_idx, int); - - /* Sort the monster races */ - for (k = 1; k < max_r_idx; k++) - { - monster_race *r_ptr = &r_info[k]; - - /* Only print Uniques */ - if (r_ptr->flags1 & (RF1_UNIQUE) && - !(r_ptr->flags7 & RF7_PET) && - !(r_ptr->flags7 & RF7_NEUTRAL)) - { - insert_sort_unique(sort_uniques, &num, k); - } - } - - /* Scan the monster races -- sorted */ - for (k = 0; k < num; k++) - { - monster_race *r_ptr = &r_info[sort_uniques[k]]; - - /* Only print Uniques */ - if (r_ptr->flags1 & (RF1_UNIQUE)) - { - bool_ dead = (r_ptr->max_num == 0); - - /* Only display "known" uniques */ - if (dead || cheat_know || r_ptr->r_sights) - { - /* Print a message */ - if (dead) - { - /* Don't print the unique's ASCII symbol - * if use_graphics is on. */ - if (use_graphics) - { - fprintf(fff, "[[[[[R%-70s is dead]\n", - (r_name + r_ptr->name)); - } - else - { - fprintf(fff, "[[[[[%c%c] [[[[[R%-68s is dead]\n", - conv_color[r_ptr->d_attr], - r_ptr->d_char, - (r_name + r_ptr->name)); - } - } - else - { - /* Don't print the unique's ASCII symbol - * if use_graphics is on. */ - if (use_graphics) - { - fprintf(fff, "[[[[[w%-70s is alive]\n", - (r_name + r_ptr->name)); - } - else - { - fprintf(fff, "[[[[[%c%c] [[[[[w%-68s is alive]\n", - conv_color[r_ptr->d_attr], - r_ptr->d_char, - (r_name + r_ptr->name)); - } - } - } - } - } - - C_FREE(sort_uniques, max_r_idx, int); - - /* Close the file */ - my_fclose(fff); - - /* Display the file contents */ - show_file(file_name, "Known Uniques", 0, 0); - - /* Remove the file */ - fd_kill(file_name); -} - - -void plural_aux(char *name) -{ - int name_len = strlen(name); - - /* Hack -- Precedent must be pluralised for this one */ - if (strstr(name, "Disembodied hand")) - { - strcpy(name, "Disembodied hands that strangled people"); - } - - /* "someone of something" */ - else if (strstr(name, " of ")) - { - cptr aider = strstr(name, " of "); - char dummy[80]; - int i = 0; - cptr ctr = name; - - while (ctr < aider) - { - dummy[i] = *ctr; - ctr++; - i++; - } - - if (dummy[i - 1] == 's') - { - strcpy(&dummy[i], "es"); - i++; - } - else - { - strcpy(&dummy[i], "s"); - } - - strcpy(&dummy[i + 1], aider); - strcpy(name, dummy); - } - - /* Creeping coins */ - else if (strstr(name, "coins")) - { - char dummy[80]; - strcpy(dummy, "piles of "); - strcat(dummy, name); - strcpy(name, dummy); - return; - } - - /* Manes stay manes */ - else if (strstr(name, "Manes")) - { - return; - } - - /* Broken plurals are, well, broken */ - else if (name[name_len - 1] == 'y') - { - strcpy(&name[name_len - 1], "ies"); - } - else if (streq(&name[name_len - 4], "ouse")) - { - strcpy(&name[name_len - 4], "ice"); - } - else if (streq(&name[name_len - 6], "kelman")) - { - strcpy(&name[name_len - 6], "kelmen"); - } - else if (streq(&name[name_len - 2], "ex")) - { - strcpy(&name[name_len - 2], "ices"); - } - else if (streq(&name[name_len - 3], "olf")) - { - strcpy(&name[name_len - 3], "olves"); - } - - /* Now begins sane cases */ - else if ((streq(&name[name_len - 2], "ch")) || (name[name_len - 1] == 's')) - { - strcpy(&name[name_len], "es"); - } - else - { - strcpy(&name[name_len], "s"); - } -} - - -/* - * Display current pets - */ -static void do_cmd_knowledge_pets(void) -{ - int i; - - FILE *fff; - - monster_type *m_ptr; - - int t_friends = 0; - - int t_levels = 0; - - int show_upkeep = 0; - - int upkeep_divider = 20; - - char file_name[1024]; - - - /* Temporary file */ - if (path_temp(file_name, 1024)) return; - - /* Open a new file */ - fff = my_fopen(file_name, "w"); - - if (has_ability(AB_PERFECT_CASTING)) upkeep_divider = 15; - - /* Process the monsters (backwards) */ - for (i = m_max - 1; i >= 1; i--) - { - /* Access the monster */ - m_ptr = &m_list[i]; - - /* Ignore "dead" monsters */ - if (!m_ptr->r_idx) continue; - - /* Calculate "upkeep" for friendly monsters */ - if (m_ptr->status >= MSTATUS_PET) - { - char pet_name[80]; - monster_race *r_ptr = race_inf(m_ptr); - - t_friends++; - t_levels += m_ptr->level; - monster_desc(pet_name, m_ptr, 0x88); - fprintf(fff, "%s%s (%s)\n", - (r_ptr->flags1 & RF1_UNIQUE) ? "#####G" : "", - pet_name, - (m_ptr->status < MSTATUS_COMPANION) ? "pet" : "companion"); - } - } - - if (t_friends > 1 + (p_ptr->lev / (upkeep_divider))) - { - show_upkeep = (t_levels); - - if (show_upkeep > 100) show_upkeep = 100; - else if (show_upkeep < 10) show_upkeep = 10; - } - - - fprintf(fff, "----------------------------------------------\n"); - fprintf(fff, " Total: %d pet%s.\n", t_friends, (t_friends == 1 ? "" : "s")); - fprintf(fff, " Upkeep: %d%% mana.\n", show_upkeep); - - - /* Close the file */ - my_fclose(fff); - - /* Display the file contents */ - show_file(file_name, "Current Pets", 0, 0); - - /* Remove the file */ - fd_kill(file_name); -} - - - -/* - * Total kill count - * - * Note that the player ghosts are ignored. XXX XXX XXX - */ -static void do_cmd_knowledge_kill_count(void) -{ - int k; - - FILE *fff; - - char file_name[1024]; - - s32b Total = 0; - - - /* Temporary file */ - if (path_temp(file_name, 1024)) return; - - /* Open a new file */ - fff = my_fopen(file_name, "w"); - - { - /* Monsters slain */ - int kk; - - /* For all monsters */ - for (kk = 1; kk < max_r_idx; kk++) - { - monster_race *r_ptr = &r_info[kk]; - - if (r_ptr->flags1 & (RF1_UNIQUE)) - { - bool_ dead = (r_ptr->max_num == 0); - - if (dead) - { - Total++; - } - } - else - { - s16b This = r_ptr->r_pkills; - - if (This > 0) - { - Total += This; - } - } - } - - if (Total < 1) - { - fprintf(fff, "You have defeated no enemies yet.\n\n"); - } - else if (Total == 1) - { - fprintf(fff, "You have defeated one enemy.\n\n"); - } - else - { - fprintf(fff, "You have defeated " FMTs32b " enemies.\n\n", Total); - } - } - - Total = 0; - - /* Scan the monster races */ - for (k = 0; k < max_r_idx; k++) - { - monster_race *r_ptr = &r_info[k]; - - if (r_ptr->flags1 & (RF1_UNIQUE)) - { - bool_ dead = (r_ptr->max_num == 0); - - if (dead) - { - /* Print a message */ - fprintf(fff, " %s\n", - (r_name + r_ptr->name)); - Total++; - } - } - else - { - s16b This = r_ptr->r_pkills; - - if (This > 0) - { - if (This < 2) - { - if (strstr(r_name + r_ptr->name, "coins")) - { - fprintf(fff, " 1 pile of %s\n", (r_name + r_ptr->name)); - } - else - { - fprintf(fff, " 1 %s\n", (r_name + r_ptr->name)); - } - } - else - { - char to_plural[80]; - strcpy(to_plural, (r_name + r_ptr->name)); - plural_aux(to_plural); - fprintf(fff, " %d %s\n", This, to_plural); - } - - Total += This; - } - } - } - - fprintf(fff, "----------------------------------------------\n"); - fprintf(fff, " Total: " FMTs32b " creature%s killed.\n", Total, (Total == 1 ? "" : "s")); - - /* Close the file */ - my_fclose(fff); - - /* Display the file contents */ - show_file(file_name, "Kill Count", 0, 0); - - /* Remove the file */ - fd_kill(file_name); -} - - -/* - * Display known objects - */ -static void do_cmd_knowledge_objects(void) -{ - int k; - - FILE *fff; - - char o_name[80]; - - char file_name[1024]; - - - /* Temporary file */ - if (path_temp(file_name, 1024)) return; - - /* Open a new file */ - fff = my_fopen(file_name, "w"); - - /* Scan the object kinds */ - for (k = 1; k < max_k_idx; k++) - { - object_kind *k_ptr = &k_info[k]; - - /* Hack -- skip artifacts */ - if (k_ptr->flags3 & (TR3_INSTA_ART)) continue; - - /* List known flavored objects */ - if (k_ptr->flavor && k_ptr->aware) - { - object_type *i_ptr; - object_type object_type_body; - - /* Get local object */ - i_ptr = &object_type_body; - - /* Create fake object */ - object_prep(i_ptr, k); - - /* Describe the object */ - object_desc_store(o_name, i_ptr, FALSE, 0); - - /* Print a message */ - fprintf(fff, " %s\n", o_name); - } - } - - /* Close the file */ - my_fclose(fff); - - /* Display the file contents */ - show_file(file_name, "Known Objects", 0, 0); - - /* Remove the file */ - fd_kill(file_name); -} - - -/* - * List recall depths - */ -static void do_cmd_knowledge_dungeons(void) -{ - int y; - char file_name[1024]; - FILE *fff; - - /* Temporary file */ - if (path_temp(file_name, 1024)) return; - - /* Open a new file */ - fff = my_fopen(file_name, "w"); - - /* Oops */ - if (fff == NULL) return; - - /* Scan all dungeons */ - for (y = 1; y < max_d_idx; y++) - { - /* The dungeon has a valid recall depth set */ - if (max_dlv[y]) - { - /* Describe the recall depth */ - fprintf(fff, " %c%s: Level %d (%d')\n", - (p_ptr->recall_dungeon == y) ? '*' : ' ', - d_name + d_info[y].name, - max_dlv[y], 50 * (max_dlv[y])); - } - } - - /* Close the file */ - my_fclose(fff); - - /* Display the file contents */ - show_file(file_name, "Recall Depths", 0, 0); - - /* Remove the file */ - fd_kill(file_name); -} - - -/* - * List known towns - */ -void do_cmd_knowledge_towns(void) -{ - int i, j; - char file_name[1024]; - FILE *fff; - - /* Temporary file */ - if (path_temp(file_name, 1024)) return; - - /* Open a new file */ - fff = my_fopen(file_name, "w"); - - /* Oops */ - if (fff == NULL) return; - - /* Scan all dungeons */ - for (i = 0; i < max_d_idx; i++) - { - dungeon_info_type *d_ptr = &d_info[i]; - - /* Scan all dungeon town slots */ - for (j = 0; j < TOWN_DUNGEON; j++) - { - int town_idx = d_ptr->t_idx[j]; - - /* Ignore non-existent towns */ - if (!(town_info[town_idx].flags & (TOWN_REAL))) continue; - - /* Ignore unknown towns */ - if (!(town_info[town_idx].flags & (TOWN_KNOWN))) continue; - - /* Describe the dungeon town */ - fprintf(fff, " %s: Level %d (%d')\n", - d_name + d_ptr->name, - d_ptr->t_level[j], - 50 * d_ptr->t_level[j]); - } - } - - /* Close the file */ - my_fclose(fff); - - /* Display the file contents */ - show_file(file_name, "Dungeon Towns", 0, 0); - - /* Remove the file */ - fd_kill(file_name); -} - - -/* - * List corruptions - */ -void do_cmd_knowledge_corruptions(void) -{ - FILE *fff; - - char file_name[1024]; - - - /* Temporary file */ - if (path_temp(file_name, 1024)) return; - - /* Open a new file */ - fff = my_fopen(file_name, "w"); - - /* Dump the corruptions to file */ - if (fff) - { - dump_corruptions(fff, TRUE, FALSE); - } - - /* Close the file */ - my_fclose(fff); - - /* Display the file contents */ - show_file(file_name, "Corruptions", 0, 0); - - /* Remove the file */ - fd_kill(file_name); -} - - -/* - * Helper function for do_cmd_knowledge_quests - */ -static void insert_sort_quest(int *order, int *num, int q_idx) -{ - int i, j; - - quest_type *q_ptr = &quest[q_idx]; - - int level = q_ptr->level; - - - /* Find the place */ - for (i = 0; i < *num; i++) - { - quest_type *q2_ptr = &quest[order[i]]; - int level2 = q2_ptr->level; - - if (level < level2) break; - } - - /* Move the remaining items */ - for (j = *num - 1; j >= i; j--) - { - order[j + 1] = order[j]; - } - - /* Insert it */ - order[i] = q_idx; - (*num)++; -} - - -/* - * Print quest status of all active quests - */ -static void do_cmd_knowledge_quests(void) -{ - FILE *fff; - - char file_name[1024]; - - int order[MAX_Q_IDX] = { }; - - int num = 0; - - int i, j, z; - - - /* Temporary file */ - if (path_temp(file_name, 1024)) return; - - /* Open a new file */ - fff = my_fopen(file_name, "w"); - - for (i = 0; i < MAX_Q_IDX; i++) - { - insert_sort_quest(order, &num, i); - } - - for (z = 0; z < MAX_Q_IDX; z++) - { - i = order[z]; - - /* Dynamic descriptions */ - if (quest[i].gen_desc != NULL) - { - if (!quest[i].gen_desc(fff)) - { - continue; - } - } - - /* Fixed quests (only known ones) */ - else if (!quest[i].silent) - { - if (quest[i].status == QUEST_STATUS_TAKEN) - { - /* Print the quest info */ - fprintf(fff, "#####y%s (Danger level: %d)\n", - quest[i].name, quest[i].level); - - j = 0; - while ((j < 10) && (quest[i].desc[j][0] != '\0')) - { - fprintf(fff, "%s\n", quest[i].desc[j++]); - } - fprintf(fff, "\n"); - } - else if (quest[i].status == QUEST_STATUS_COMPLETED) - { - fprintf(fff , "#####G%s Completed - Unrewarded\n", quest[i].name); - fprintf(fff, "\n"); - } - } - } - - /* Close the file */ - my_fclose(fff); - - /* Display the file contents */ - show_file(file_name, "Quest status", 0, 0); - - /* Remove the file */ - fd_kill(file_name); -} - - -/* - * Print fate status - */ -static void do_cmd_knowledge_fates(void) -{ - FILE *fff; - - char file_name[1024]; - - - /* Temporary file */ - if (path_temp(file_name, 1024)) return; - - /* Open a new file */ - fff = my_fopen(file_name, "w"); - - dump_fates(fff); - - /* Close the file */ - my_fclose(fff); - - /* Display the file contents */ - show_file(file_name, "Fate status", 0, 0); - - /* Remove the file */ - fd_kill(file_name); -} - - -/* - * Print the note file - */ -void do_cmd_knowledge_notes(void) -{ - /* Spawn */ - show_notes_file(); - - /* Done */ - return; -} - - -/* - * Interact with "knowledge" - */ -void do_cmd_knowledge(void) -{ - int i; - - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - /* Enter "icky" mode */ - character_icky = TRUE; - - /* Save the screen */ - Term_save(); - - /* Interact until done */ - while (1) - { - /* Clear screen */ - Term_clear(); - - /* Ask for a choice */ - prt("Display current knowledge", 2, 0); - - /* Give some choices */ - prt("(1) Display known artifacts", 4, 5); - prt("(2) Display known uniques", 5, 5); - prt("(3) Display known objects", 6, 5); - prt("(4) Display kill count", 7, 5); - prt("(5) Display recall depths", 8, 5); - prt("(6) Display corruptions", 9, 5); - prt("(7) Display current pets", 10, 5); - prt("(8) Display current quests", 11, 5); - prt("(9) Display current fates", 12, 5); - prt("(0) Display known traps", 13, 5); - prt("(A) Display known dungeon towns", 14, 5); - prt("(B) Display notes", 15, 5); - - /* Prompt */ - prt("Command: ", 17, 0); - - /* Prompt */ - i = inkey(); - - /* Done */ - if (i == ESCAPE) break; - - switch (i) - { - /* Artifacts */ - case '1': - { - do_cmd_knowledge_artifacts(); - - break; - } - - /* Uniques */ - case '2': - { - do_cmd_knowledge_uniques(); - - break; - } - - /* Objects */ - case '3': - { - do_cmd_knowledge_objects(); - - break; - } - - /* Kill count */ - case '4': - { - do_cmd_knowledge_kill_count(); - - break; - } - - /* Recall depths */ - case '5': - { - do_cmd_knowledge_dungeons(); - - break; - } - - /* corruptions */ - case '6': - { - do_cmd_knowledge_corruptions(); - - break; - } - - /* Pets */ - case '7': - { - do_cmd_knowledge_pets(); - - break; - } - - /* Quests */ - case '8': - { - do_cmd_knowledge_quests(); - - break; - } - - /* Fates */ - case '9': - { - do_cmd_knowledge_fates(); - - break; - } - - /* Traps */ - case '0': - { - do_cmd_knowledge_traps(); - - break; - } - - /* Dungeon towns */ - case 'A': - case 'a': - { - do_cmd_knowledge_towns(); - - break; - } - - /* Notes */ - case 'B': - case 'b': - { - do_cmd_knowledge_notes(); - - break; - } - - /* Unknown option */ - default: - { - bell(); - - break; - } - } - - /* Flush messages */ - msg_print(NULL); - } - - /* Restore the screen */ - Term_load(); - - /* Leave "icky" mode */ - character_icky = FALSE; -} - - -/* - * Check on the status of an active quest -KMW- - * TODO: Spill out status when not a simple kill # monster. - */ -void do_cmd_checkquest(void) -{ - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - /* Enter "icky" mode */ - character_icky = TRUE; - - /* Save the screen */ - Term_save(); - - /* Quest info */ - do_cmd_knowledge_quests(); - - /* Restore the screen */ - Term_load(); - - /* Leave "icky" mode */ - character_icky = FALSE; -} - - -/* - * Change player's "tactic" setting - */ -void do_cmd_change_tactic(int i) -{ - p_ptr->tactic += i; - if (p_ptr->tactic > 8) p_ptr->tactic = 0; - if (p_ptr->tactic < 0) p_ptr->tactic = 8; - - p_ptr->update |= (PU_BONUS); - update_stuff(); - prt("", 0, 0); -} - - -/* - * Change player's "movement" setting - */ -void do_cmd_change_movement(int i) -{ - p_ptr->movement += i; - if (p_ptr->movement > 8) p_ptr->movement = 0; - if (p_ptr->movement < 0) p_ptr->movement = 8; - - p_ptr->update |= (PU_BONUS); - update_stuff(); - prt("", 0, 0); -} - - -/* - * Display the time and date - */ -void do_cmd_time() -{ - int day = bst(DAY, turn); - - int hour = bst(HOUR, turn); - - int min = bst(MINUTE, turn); - - int full = hour * 100 + min; - - char buf2[20]; - - int start = 9999; - - int end = -9999; - - int num = 0; - - char desc[1024]; - - char buf[1024]; - - FILE *fff; - - - /* Note */ - strcpy(desc, "It is a strange time."); - - /* Format time of the day */ - strnfmt(buf2, 20, get_day(bst(YEAR, turn) + START_YEAR)); - - /* Display current date in the Elvish calendar */ - msg_format("This is %s of the %s year of the third age.", - get_month_name(day, wizard, FALSE), buf2); - - /* Message */ - msg_format("The time is %d:%02d %s.", - (hour % 12 == 0) ? 12 : (hour % 12), - min, (hour < 12) ? "AM" : "PM"); - - /* Find the path */ - if (!rand_int(10) || p_ptr->image) - { - path_build(buf, 1024, ANGBAND_DIR_FILE, "timefun.txt"); - } - else - { - path_build(buf, 1024, ANGBAND_DIR_FILE, "timenorm.txt"); - } - - /* Open this file */ - fff = my_fopen(buf, "rt"); - - /* Oops */ - if (!fff) return; - - /* Find this time */ - while (!my_fgets(fff, buf, 1024)) - { - /* Ignore comments */ - if (!buf[0] || (buf[0] == '#')) continue; - - /* Ignore invalid lines */ - if (buf[1] != ':') continue; - - /* Process 'Start' */ - if (buf[0] == 'S') - { - /* Extract the starting time */ - start = atoi(buf + 2); - - /* Assume valid for an hour */ - end = start + 59; - - /* Next... */ - continue; - } - - /* Process 'End' */ - if (buf[0] == 'E') - { - /* Extract the ending time */ - end = atoi(buf + 2); - - /* Next... */ - continue; - } - - /* Ignore incorrect range */ - if ((start > full) || (full > end)) continue; - - /* Process 'Description' */ - if (buf[0] == 'D') - { - num++; - - /* Apply the randomizer */ - if (!rand_int(num)) strcpy(desc, buf + 2); - - /* Next... */ - continue; - } - } - - /* Message */ - msg_print(desc); - - /* Close the file */ - my_fclose(fff); -} - -/* - * Macro recorder! - * It records all keypresses and then put them in a macro - * Not as powerful as the macro screen, but much easier for newbies - */ -char *macro_recorder_current = NULL; -void macro_recorder_start() -{ - msg_print("Starting macro recording, press this key again to stop. Note that if the action you want to record accepts the @ key, use it; it will remove your the need to inscribe stuff."); - C_MAKE(macro_recorder_current, 1, char); - macro_recorder_current[0] = '\0'; -} - -void macro_recorder_add(char c) -{ - char *old_macro_recorder_current = macro_recorder_current; - - if (macro_recorder_current == NULL) return; - - C_MAKE(macro_recorder_current, strlen(macro_recorder_current) + 1 + 1, char); - sprintf(macro_recorder_current, "%s%c", old_macro_recorder_current, c); - C_FREE(old_macro_recorder_current, strlen(old_macro_recorder_current) + 1, char); -} - -void macro_recorder_stop() -{ - char *str, *macro; - char buf[1024]; - - /* Ok we remove the last key, because it is the key to stop recording */ - macro_recorder_current[strlen(macro_recorder_current) - 1] = '\0'; - - /* Stop the recording */ - macro = macro_recorder_current; - macro_recorder_current = NULL; - - /* Add it */ - if (get_check("Are you satisfied and want to create the macro? ")) - { - prt("Trigger: ", 0, 0); - - /* Get a macro trigger */ - do_cmd_macro_aux(buf, FALSE); - - /* Link the macro */ - macro_add(buf, macro); - - /* Prompt */ - C_MAKE(str, (strlen(macro) + 1) * 3, char); - ascii_to_text(str, macro); - msg_format("Added a macro '%s'. If you want it to stay permanently, press @ now and dump macros to a file.", str); - C_FREE(str, (strlen(macro) + 1) * 3, char); - } - - /* Ok now rid of useless stuff */ - C_FREE(macro, strlen(macro) + 1, char); -} - -void do_cmd_macro_recorder() -{ - if (macro_recorder_current == NULL) - macro_recorder_start(); - else - macro_recorder_stop(); -} diff --git a/src/cmd4.cc b/src/cmd4.cc new file mode 100644 index 00000000..e00f5835 --- /dev/null +++ b/src/cmd4.cc @@ -0,0 +1,4607 @@ +/* File: cmd4.c */ + +/* Purpose: Interface commands */ + +/* + * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke + * + * This software may be copied and distributed for educational, research, and + * not for profit purposes provided that this copyright and statement are + * included in all such copies. + */ + +#include "angband.h" + +#include "messages.h" +#include "hooks.h" + +#include +#include +#include +#include + +/* + * Hack -- redraw the screen + * + * This command performs various low level updates, clears all the "extra" + * windows, does a total redraw of the main window, and requests all of the + * interesting updates and redraws that I can think of. + * + * This command is also used to "instantiate" the results of the user + * selecting various things, such as graphics mode, so it must call + * the "TERM_XTRA_REACT" hook before redrawing the windows. + */ +void do_cmd_redraw(void) +{ + int j; + + term *old = Term; + + + /* Hack -- react to changes */ + Term_xtra(TERM_XTRA_REACT, 0); + + + /* Combine and Reorder the pack (later) */ + p_ptr->notice |= (PN_COMBINE | PN_REORDER); + + + /* Update torch */ + p_ptr->update |= (PU_TORCH); + + /* Update stuff */ + p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS | PU_POWERS | + PU_SANITY | PU_BODY); + + /* Forget view */ + p_ptr->update |= (PU_UN_VIEW); + + /* Update view */ + p_ptr->update |= (PU_VIEW); + + /* Update monster light */ + p_ptr->update |= (PU_MON_LITE); + + /* Update monsters */ + p_ptr->update |= (PU_MONSTERS); + + /* Redraw everything */ + p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP); + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER | PW_M_LIST); + + /* Window stuff */ + p_ptr->window |= (PW_MESSAGE | PW_OVERHEAD | PW_MONSTER | PW_OBJECT); + + /* Hack -- update */ + handle_stuff(); + + + /* Redraw every window */ + for (j = 0; j < 8; j++) + { + /* Dead window */ + if (!angband_term[j]) continue; + + /* Activate */ + Term_activate(angband_term[j]); + + /* Redraw */ + Term_redraw(); + + /* Refresh */ + Term_fresh(); + + /* Restore */ + Term_activate(old); + } +} + + +/* + * Hack -- change name + */ +void do_cmd_change_name(void) +{ + char c; + + int mode = 0; + + char tmp[160]; + + + /* Enter "icky" mode */ + character_icky = TRUE; + + /* Save the screen */ + Term_save(); + + /* Forever */ + while (1) + { + /* keep mode below 7 */ + mode = (mode + 6) % 6; + + /* Display the player */ + display_player(mode); + + /* Prompt */ + if (mode == 0) + { + Term_putstr(14, 22, -1, TERM_WHITE, + "['t/T' to change tactics, 'e/E' to change movement]"); + } + + Term_putstr(4, 23, -1, TERM_WHITE, + "['c' to change name, 'f' to file, 'p' for previous, 'n' for next, or ESC]"); + + /* Query */ + c = inkey(); + + /* Exit */ + if (c == ESCAPE) break; + + /* Change name */ + if (c == 'c') + { + get_name(); + } + + /* File dump */ + else if (c == 'f') + { + strnfmt(tmp, 160, "%s.txt", player_name); + if (get_string("Filename(you can post it to http://angband.oook.cz/): ", tmp, 80)) + { + if (tmp[0] && (tmp[0] != ' ')) + { + file_character(tmp, FALSE); + } + } + } + + /* Toggle mode */ + else if (c == 'n') + { + mode++; + } + else if (c == 'p') + { + mode--; + } + + else if (mode == 0) + { + /* Change tactic */ + if (c == 't') + { + (void)do_cmd_change_tactic( -1); + } + else if (c == 'T') + { + (void)do_cmd_change_tactic(1); + } + + /* Change movement */ + else if (c == 'e') + { + do_cmd_change_movement( -1); + } + else if (c == 'E') + { + do_cmd_change_movement(1); + } + else + { + bell(); + } + } + /* Oops */ + else + { + bell(); + } + + /* Flush messages */ + msg_print(NULL); + } + + /* Restore the screen */ + Term_load(); + + /* Leave "icky" mode */ + character_icky = FALSE; + + + /* Redraw everything */ + p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP); + + handle_stuff(); +} + + +/* + * Recall the most recent message + */ +void do_cmd_message_one(void) +{ + cptr msg = format("> %s", message_str(0)); + + /* Recall one message XXX XXX XXX */ + display_message(0, 0, strlen(msg), message_color(0), msg); +} + + +/* + * Show previous messages to the user -BEN- + * + * The screen format uses line 0 and (Term->hgt - 1) for headers and prompts, + * skips line 1 and (Term->hgt - 2), and uses line 2 thru (Term->hgt - 3) for + * old messages. + * + * This command shows you which commands you are viewing, and allows + * you to "search" for strings in the recall. + * + * Note that messages may be longer than 80 characters, but they are + * displayed using "infinite" length, with a special sub-command to + * "slide" the virtual display to the left or right. + * + * Attempt to only hilite the matching portions of the string. + * + * Now taking advantages of big-screen. -pav- + */ +void do_cmd_messages(void) +{ + int i, j, k, n; + u32b q; + int wid, hgt; + + char shower[80]; + char finder[80]; + + /* Wipe finder */ + strcpy(finder, ""); + + /* Wipe shower */ + strcpy(shower, ""); + + + /* Total messages */ + n = message_num(); + + /* Start on first message */ + i = 0; + + /* Start at leftmost edge */ + q = 0; + + /* Enter "icky" mode */ + character_icky = TRUE; + + /* Save the screen */ + Term_save(); + + /* Process requests until done */ + while (1) + { + /* Clear screen */ + Term_clear(); + + /* Retrieve current screen size */ + Term_get_size(&wid, &hgt); + + /* Dump up to 20 (or more in bigscreen) lines of messages */ + for (j = 0; (j < (hgt - 4)) && (i + j < n); j++) + { + cptr msg = message_str(i + j); + byte color = message_color(i + j); + + /* Apply horizontal scroll */ + msg = (strlen(msg) >= q) ? (msg + q) : ""; + + /* Dump the messages, bottom to top */ + display_message(0, (hgt - 3) - j, strlen(msg), color, msg); + + /* Hilite "shower" */ + if (shower[0]) + { + cptr str = msg; + + /* Display matches */ + while ((str = strstr(str, shower)) != NULL) + { + int len = strlen(shower); + + /* Display the match */ + Term_putstr(str - msg, (hgt - 3) - j, len, TERM_YELLOW, shower); + + /* Advance */ + str += len; + } + } + } + + /* Display header XXX XXX XXX */ + prt(format("Message Recall (%d-%d of %d), Offset %d", + i, i + j - 1, n, q), 0, 0); + + /* Display prompt (not very informative) */ + prt("[Press 'p' for older, 'n' for newer, ..., or ESCAPE]", hgt - 1, 0); + + /* Get a command */ + k = inkey(); + + /* Exit on Escape */ + if (k == ESCAPE) break; + + /* Hack -- Save the old index */ + j = i; + + /* Horizontal scroll */ + if (k == '4') + { + /* Scroll left */ + q = (q >= ((u32b)wid / 2)) ? (q - wid / 2) : 0; + + /* Success */ + continue; + } + + /* Horizontal scroll */ + if (k == '6') + { + /* Scroll right */ + q = q + wid / 2; + + /* Success */ + continue; + } + + /* Hack -- handle show */ + if (k == '=') + { + /* Prompt */ + prt("Show: ", hgt - 1, 0); + + /* Get a "shower" string, or continue */ + if (!askfor_aux(shower, 80)) continue; + + /* Okay */ + continue; + } + + /* Hack -- handle find */ + if (k == '/') + { + s16b z; + + /* Prompt */ + prt("Find: ", hgt - 1, 0); + + /* Get a "finder" string, or continue */ + if (!askfor_aux(finder, 80)) continue; + + /* Show it */ + strcpy(shower, finder); + + /* Scan messages */ + for (z = i + 1; z < n; z++) + { + cptr msg = message_str(z); + + /* Search for it */ + if (strstr(msg, finder)) + { + /* New location */ + i = z; + + /* Done */ + break; + } + } + } + + /* Recall 1 older message */ + if ((k == '8') || (k == '\n') || (k == '\r')) + { + /* Go newer if legal */ + if (i + 1 < n) i += 1; + } + + /* Recall 10 older messages */ + if (k == '+') + { + /* Go older if legal */ + if (i + 10 < n) i += 10; + } + + /* Recall one screen of older messages */ + if ((k == 'p') || (k == KTRL('P')) || (k == ' ')) + { + /* Go older if legal */ + if (i + (hgt - 4) < n) i += (hgt - 4); + } + + /* Recall one screen of newer messages */ + if ((k == 'n') || (k == KTRL('N'))) + { + /* Go newer (if able) */ + i = (i >= (hgt - 4)) ? (i - (hgt - 4)) : 0; + } + + /* Recall 10 newer messages */ + if (k == '-') + { + /* Go newer (if able) */ + i = (i >= 10) ? (i - 10) : 0; + } + + /* Recall 1 newer messages */ + if (k == '2') + { + /* Go newer (if able) */ + i = (i >= 1) ? (i - 1) : 0; + } + + /* Hack -- Error of some kind */ + if (i == j) bell(); + } + + /* Restore the screen */ + Term_load(); + + /* Leave "icky" mode */ + character_icky = FALSE; +} + + + +/* + * Number of cheating options + */ +#define CHEAT_MAX 6 + +/* + * Cheating options + */ +static option_type cheat_info[CHEAT_MAX] = +{ + { &cheat_peek, FALSE, 0, 0, "cheat_peek", "Peek into object creation" }, + { &cheat_hear, FALSE, 0, 1, "cheat_hear", "Peek into monster creation" }, + { &cheat_room, FALSE, 0, 2, "cheat_room", "Peek into dungeon creation" }, + { &cheat_xtra, FALSE, 0, 3, "cheat_xtra", "Peek into something else" }, + { &cheat_know, FALSE, 0, 4, "cheat_know", "Know complete monster info" }, + { &cheat_live, FALSE, 0, 5, "cheat_live", "Allow player to avoid death" } +}; + +/* + * Interact with some options for cheating + */ +static void do_cmd_options_cheat(cptr info) +{ + char ch; + + int i, k = 0, n = CHEAT_MAX; + + int dir; + + char buf[80]; + + + /* Clear screen */ + Term_clear(); + + /* Interact with the player */ + while (TRUE) + { + /* Prompt XXX XXX XXX */ + strnfmt(buf, 80, "%s (RET to advance, y/n to set, ESC to accept) ", info); + prt(buf, 0, 0); + + /* Display the options */ + for (i = 0; i < n; i++) + { + byte a = TERM_WHITE; + + /* Color current option */ + if (i == k) a = TERM_L_BLUE; + + /* Display the option text */ + strnfmt(buf, 80, "%-48s: %s (%s)", + cheat_info[i].o_desc, + (*cheat_info[i].o_var ? "yes" : "no "), + cheat_info[i].o_text); + c_prt(a, buf, i + 2, 0); + } + + /* Hilite current option */ + move_cursor(k + 2, 50); + + /* Get a key */ + ch = inkey(); + + /* + * Hack -- Try to translate the key into a direction + * to allow the use of roguelike keys for navigation + */ + dir = get_keymap_dir(ch); + if ((dir == 2) || (dir == 4) || (dir == 6) || (dir == 8)) ch = I2D(dir); + + + /* Analyze */ + switch (ch) + { + case ESCAPE: + { + return; + } + + case '-': + case '8': + { + k = (n + k - 1) % n; + + break; + } + + case ' ': + case '\n': + case '\r': + case '2': + { + k = (k + 1) % n; + + break; + } + + case 'y': + case 'Y': + case '6': + { + noscore |= (cheat_info[k].o_page * 256 + cheat_info[k].o_bit); + (*cheat_info[k].o_var) = TRUE; + k = (k + 1) % n; + + break; + } + + case 'n': + case 'N': + case '4': + { + (*cheat_info[k].o_var) = FALSE; + k = (k + 1) % n; + + break; + } + + default: + { + bell(); + + break; + } + } + } +} + + +static option_type autosave_info[2] = +{ + { &autosave_l, FALSE, 0, 6, "autosave_l", "Autosave when entering new levels" }, + { &autosave_t, FALSE, 0, 7, "autosave_t", "Timed autosave" }, +}; + +s16b toggle_frequency(s16b current) +{ + if (current == 0) return (50); + if (current == 50) return (100); + if (current == 100) return (250); + if (current == 250) return (500); + if (current == 500) return (1000); + if (current == 1000) return (2500); + if (current == 2500) return (5000); + if (current == 5000) return (10000); + if (current == 10000) return (25000); + + return (0); +} + + +/* + * Interact with some options for cheating + */ +static void do_cmd_options_autosave(cptr info) +{ + char ch; + + int i, k = 0, n = 2; + + int dir; + + char buf[80]; + + + /* Clear screen */ + Term_clear(); + + /* Interact with the player */ + while (TRUE) + { + /* Prompt XXX XXX XXX */ + strnfmt(buf, 80, + "%s (RET to advance, y/n to set, 'F' for frequency, ESC to accept) ", + info); + prt(buf, 0, 0); + + /* Display the options */ + for (i = 0; i < n; i++) + { + byte a = TERM_WHITE; + + /* Color current option */ + if (i == k) a = TERM_L_BLUE; + + /* Display the option text */ + strnfmt(buf, 80, "%-48s: %s (%s)", + autosave_info[i].o_desc, + (*autosave_info[i].o_var ? "yes" : "no "), + autosave_info[i].o_text); + c_prt(a, buf, i + 2, 0); + } + + prt(format("Timed autosave frequency: every %d turns", autosave_freq), 5, 0); + + + /* Hilite current option */ + move_cursor(k + 2, 50); + + /* Get a key */ + ch = inkey(); + + /* + * Hack -- Try to translate the key into a direction + * to allow the use of roguelike keys for navigation + */ + dir = get_keymap_dir(ch); + if ((dir == 2) || (dir == 4) || (dir == 6) || (dir == 8)) ch = I2D(dir); + + /* Analyze */ + switch (ch) + { + case ESCAPE: + { + return; + } + + case '-': + case '8': + { + k = (n + k - 1) % n; + + break; + } + + case ' ': + case '\n': + case '\r': + case '2': + { + k = (k + 1) % n; + + break; + } + + case 'y': + case 'Y': + case '6': + { + + (*autosave_info[k].o_var) = TRUE; + k = (k + 1) % n; + + break; + } + + case 'n': + case 'N': + case '4': + { + (*autosave_info[k].o_var) = FALSE; + k = (k + 1) % n; + + break; + } + + case 'f': + case 'F': + { + autosave_freq = toggle_frequency(autosave_freq); + prt(format("Timed autosave frequency: every %d turns", + autosave_freq), 5, 0); + + break; + } + + default: + { + bell(); + + break; + } + } + } +} + +/* Switch an option by only knowing its name */ +bool_ change_option(cptr name, bool_ value) +{ + int i; + + /* Scan the options */ + for (i = 0; option_info[i].o_desc; i++) + { + if (!strcmp(option_info[i].o_text, name)) + { + bool_ old = (*option_info[i].o_var); + + (*option_info[i].o_var) = value; + + return old; + } + } + + cmsg_format(TERM_VIOLET, "Warning, change_option couldn't find option '%s'.", name); + return FALSE; +} + +/* + * Interact with some options + */ +void do_cmd_options_aux(int page, cptr info, bool_ read_only) +{ + char ch; + + int i, k = 0, n = 0; + + int dir; + + int opt[24]; + + char buf[80]; + + + /* Lookup the options */ + for (i = 0; i < 24; i++) opt[i] = 0; + + /* Scan the options */ + for (i = 0; option_info[i].o_desc; i++) + { + /* Notice options on this "page" */ + if (option_info[i].o_page == page) opt[n++] = i; + } + + + /* Clear screen */ + Term_clear(); + + /* Interact with the player */ + while (TRUE) + { + /* Prompt XXX XXX XXX */ + strnfmt(buf, 80, "%s (RET to advance, y/n to set, ESC to accept) ", info); + prt(buf, 0, 0); + + /* Display the options */ + for (i = 0; i < n; i++) + { + byte a = TERM_WHITE; + + /* Color current option */ + if (i == k) a = TERM_L_BLUE; + + /* Display the option text */ + strnfmt(buf, 80, "%-48s: %s (%s)", + option_info[opt[i]].o_desc, + (*option_info[opt[i]].o_var ? "yes" : "no "), + option_info[opt[i]].o_text); + c_prt(a, buf, i + 2, 0); + } + + /* Hilite current option */ + move_cursor(k + 2, 50); + + /* Get a key */ + ch = inkey(); + + /* + * Hack -- Try to translate the key into a direction + * to allow the use of roguelike keys for navigation + */ + dir = get_keymap_dir(ch); + if ((dir == 2) || (dir == 4) || (dir == 6) || (dir == 8)) ch = I2D(dir); + + /* Analyze */ + switch (ch) + { + case ESCAPE: + { + return; + } + + case '-': + case '8': + { + k = (n + k - 1) % n; + + break; + } + + case ' ': + case '\n': + case '\r': + case '2': + { + k = (k + 1) % n; + + break; + } + + case 'y': + case 'Y': + case '6': + { + if (read_only) break; + + (*option_info[opt[k]].o_var) = TRUE; + k = (k + 1) % n; + + break; + } + + case 'n': + case 'N': + case '4': + { + if (read_only) break; + + (*option_info[opt[k]].o_var) = FALSE; + k = (k + 1) % n; + + break; + } + + default: + { + bell(); + + break; + } + } + } +} + + +/* + * Modify the "window" options + */ +static void do_cmd_options_win(void) +{ + int i, j, d; + + int y = 0; + + int x = 0; + + char ch; + + bool_ go = TRUE; + + u32b old_flag[8]; + + + /* Memorize old flags */ + for (j = 0; j < 8; j++) + { + /* Acquire current flags */ + old_flag[j] = window_flag[j]; + } + + + /* Clear screen */ + Term_clear(); + + /* Interact */ + while (go) + { + /* Prompt XXX XXX XXX */ + prt("Window Flags (, t, y, n, ESC) ", 0, 0); + + /* Display the windows */ + for (j = 0; j < 8; j++) + { + byte a = TERM_WHITE; + + cptr s = angband_term_name[j]; + + /* Use color */ + if (j == x) a = TERM_L_BLUE; + + /* Window name, staggered, centered */ + Term_putstr(35 + j * 5 - strlen(s) / 2, 2 + j % 2, -1, a, s); + } + + /* Display the options */ + for (i = 0; i < 16; i++) + { + byte a = TERM_WHITE; + + cptr str = window_flag_desc[i]; + + /* Use color */ + if (i == y) a = TERM_L_BLUE; + + /* Unused option */ + if (!str) str = "(Unused option)"; + + /* Flag name */ + Term_putstr(0, i + 5, -1, a, str); + + /* Display the windows */ + for (j = 0; j < 8; j++) + { + byte a = TERM_WHITE; + + char c = '.'; + + /* Use color */ + if ((i == y) && (j == x)) a = TERM_L_BLUE; + + /* Active flag */ + if (window_flag[j] & (1L << i)) c = 'X'; + + /* Flag value */ + Term_putch(35 + j * 5, i + 5, a, c); + } + } + + /* Place Cursor */ + Term_gotoxy(35 + x * 5, y + 5); + + /* Get key */ + ch = inkey(); + + /* Analyze */ + switch (ch) + { + case ESCAPE: + { + go = FALSE; + + break; + } + + case 'T': + case 't': + { + /* Clear windows */ + for (j = 0; j < 8; j++) + { + window_flag[j] &= ~(1L << y); + } + + /* Clear flags */ + for (i = 0; i < 16; i++) + { + window_flag[x] &= ~(1L << i); + } + + /* Fall through */ + } + + case 'y': + case 'Y': + { + /* Ignore screen */ + if (x == 0) break; + + /* Set flag */ + window_flag[x] |= (1L << y); + + break; + } + + case 'n': + case 'N': + { + /* Clear flag */ + window_flag[x] &= ~(1L << y); + + break; + } + + default: + { + d = get_keymap_dir(ch); + + x = (x + ddx[d] + 8) % 8; + y = (y + ddy[d] + 16) % 16; + + if (!d) bell(); + + break; + } + } + } + + /* Notice changes */ + for (j = 0; j < 8; j++) + { + term *old = Term; + + /* Dead window */ + if (!angband_term[j]) continue; + + /* Ignore non-changes */ + if (window_flag[j] == old_flag[j]) continue; + + /* Activate */ + Term_activate(angband_term[j]); + + /* Erase */ + Term_clear(); + + /* Refresh */ + Term_fresh(); + + /* Restore */ + Term_activate(old); + } +} + + +/* + * Write all current options to the given preference file in the + * lib/user directory. Modified from KAmband 1.8. + */ +static errr option_dump(cptr fname) +{ + int i, j; + + FILE *fff; + + char buf[1024]; + + + /* Build the filename */ + path_build(buf, 1024, ANGBAND_DIR_USER, fname); + + /* File type is "TEXT" */ + FILE_TYPE(FILE_TYPE_TEXT); + + /* Append to the file */ + fff = my_fopen(buf, "a"); + + /* Failure */ + if (!fff) return ( -1); + + + /* Skip some lines */ + fprintf(fff, "\n\n"); + + /* Start dumping */ + fprintf(fff, "# Automatic option dump\n\n"); + + /* Dump options (skip cheat, adult, score) */ + for (i = 0; option_info[i].o_var != NULL; i++) + { + /* Require a real option */ + if (!option_info[i].o_text) continue; + + /* No birth options */ + if (option_info[i].o_page == 6) continue; + + /* Comment */ + fprintf(fff, "# Option '%s'\n", option_info[i].o_desc); + + /* Dump the option */ + if ((*option_info[i].o_var)) + { + fprintf(fff, "Y:%s\n", option_info[i].o_text); + } + else + { + fprintf(fff, "X:%s\n", option_info[i].o_text); + } + + /* Skip a line */ + fprintf(fff, "\n"); + } + + /* Dump window flags */ + for (i = 1; i < ANGBAND_TERM_MAX; i++) + { + /* Require a real window */ + if (!angband_term[i]) continue; + + /* Check each flag */ + for (j = 0; j < 32; j++) + { + /* Require a real flag */ + if (!window_flag_desc[j]) continue; + + /* Comment */ + fprintf(fff, "# Window '%s', Flag '%s'\n", + angband_term_name[i], window_flag_desc[j]); + + /* Dump the flag */ + if (window_flag[i] & (1L << j)) + { + fprintf(fff, "W:%d:%d:1\n", i, j); + } + else + { + fprintf(fff, "W:%d:%d:0\n", i, j); + } + + /* Skip a line */ + fprintf(fff, "\n"); + } + } + + /* Close */ + my_fclose(fff); + + /* Success */ + return (0); +} + + +/* + * Ask for a "user pref file" and process it. + * + * This function should only be used by standard interaction commands, + * in which a standard "Command:" prompt is present on the given row. + * + * Allow absolute file names? XXX XXX XXX + */ +static void do_cmd_pref_file_hack(int row) +{ + char ftmp[80]; + + + /* Prompt */ + prt("Command: Load a user pref file", row, 0); + + /* Prompt */ + prt("File: ", row + 2, 0); + + /* Default filename */ + strnfmt(ftmp, 80, "%s.prf", player_base); + + /* Ask for a file (or cancel) */ + if (!askfor_aux(ftmp, 80)) return; + + /* Process the given filename */ + if (process_pref_file(ftmp)) + { + /* Mention failure */ + msg_format("Failed to load '%s'!", ftmp); + } + else + { + /* Mention success */ + msg_format("Loaded '%s'.", ftmp); + } +} + + +/* + * Set or unset various options. + * + * The user must use the "Ctrl-R" command to "adapt" to changes + * in any options which control "visual" aspects of the game. + */ +void do_cmd_options(void) +{ + int k; + + + /* Save the screen */ + screen_save(); + + /* Interact */ + while (1) + { + /* Clear screen */ + Term_clear(); + + /* Why are we here */ + prt("Options", 2, 0); + + /* Give some choices */ + prt("(1) User Interface Options", 4, 5); + prt("(2) Disturbance Options", 5, 5); + prt("(3) Game-Play Options", 6, 5); + prt("(4) Efficiency Options", 7, 5); + prt("(5) ToME Options", 8, 5); + prt("(6) Birth Options(read only)", 9, 5); + + /* Special choices */ + prt("(D) Base Delay Factor", 10, 5); + prt("(H) Hitpoint Warning", 11, 5); + prt("(A) Autosave Options", 12, 5); + + /* Automatizer */ + prt("(T) Automatizer", 14, 5); + + + /* Window flags */ + prt("(W) Window Flags", 16, 5); + + /* Cheating */ + prt("(C) Cheating Options", 18, 5); + + /* Dump */ + prt("(U) Dump Options setting", 20, 5); + prt("(O) Load Options setting", 21, 5); + + /* Prompt */ + prt("Command: ", 22, 0); + + /* Get command */ + k = inkey(); + + /* Exit */ + if (k == ESCAPE) break; + + /* Analyze */ + switch (k) + { + /* Load a user pref file */ + case 'o': + case 'O': + { + /* Ask for and load a user pref file */ + do_cmd_pref_file_hack(21); + + break; + } + + /* Append options to a file */ + case 'u': + case 'U': + { + char ftmp[80]; + + /* Prompt */ + prt("Command: Append options to a file", 21, 0); + + /* Prompt */ + prt("File: ", 21, 0); + + /* Default filename */ + strnfmt(ftmp, 80, "%s.prf", player_base); + + /* Ask for a file */ + if (!askfor_aux(ftmp, 80)) continue; + + /* Dump the options */ + if (option_dump(ftmp)) + { + /* Failure */ + msg_print("Failed!"); + } + else + { + /* Success */ + msg_print("Done."); + } + + break; + } + + /* General Options */ + case '1': + { + /* Process the general options */ + do_cmd_options_aux(1, "User Interface Options", FALSE); + + break; + } + + /* Disturbance Options */ + case '2': + { + /* Spawn */ + do_cmd_options_aux(2, "Disturbance Options", FALSE); + + break; + } + + /* Inventory Options */ + case '3': + { + /* Spawn */ + do_cmd_options_aux(3, "Game-Play Options", FALSE); + + break; + } + + /* Efficiency Options */ + case '4': + { + /* Spawn */ + do_cmd_options_aux(4, "Efficiency Options", FALSE); + + break; + } + + /* ToME Options */ + case '5': + { + do_cmd_options_aux(5, "ToME Options", FALSE); + + break; + } + + /* Birth Options - read only */ + case '6': + { + do_cmd_options_aux(6, "Birth Options(read only)", TRUE); + + break; + } + /* Cheating Options */ + case 'C': + { + /* Spawn */ + do_cmd_options_cheat("Cheaters never win"); + + break; + } + + case 't': + case 'T': + { + do_cmd_automatizer(); + break; + } + + case 'a': + case 'A': + { + do_cmd_options_autosave("Autosave"); + + break; + } + + /* Window flags */ + case 'W': + case 'w': + { + /* Spawn */ + do_cmd_options_win(); + + break; + } + + /* Hack -- Delay Speed */ + case 'D': + case 'd': + { + /* Prompt */ + prt("Command: Base Delay Factor", 21, 0); + + /* Get a new value */ + while (1) + { + int msec = delay_factor * delay_factor * delay_factor; + prt(format("Current base delay factor: %d (%d msec)", + delay_factor, msec), 22, 0); + prt("Delay Factor (0-9 or ESC to accept): ", 23, 0); + k = inkey(); + if (k == ESCAPE) break; + if (isdigit(k)) delay_factor = D2I(k); + else bell(); + } + + break; + } + + /* Hack -- hitpoint warning factor */ + case 'H': + case 'h': + { + /* Prompt */ + prt("Command: Hitpoint Warning", 18, 0); + + /* Get a new value */ + while (1) + { + prt(format("Current hitpoint warning: %d0%%", + hitpoint_warn), 22, 0); + prt("Hitpoint Warning (0-9 or ESC to accept): ", 20, 0); + k = inkey(); + if (k == ESCAPE) break; + if (isdigit(k)) hitpoint_warn = D2I(k); + else bell(); + } + + break; + } + + /* Unknown option */ + default: + { + /* Oops */ + bell(); + + break; + } + } + + /* Flush messages */ + msg_print(NULL); + } + + + /* Restore the screen */ + screen_load(); +} + + + +/* + * Ask for a "user pref line" and process it + * + * XXX XXX XXX Allow absolute file names? + */ +void do_cmd_pref(void) +{ + char buf[80]; + + + /* Default */ + strcpy(buf, ""); + + /* Ask for a "user pref command" */ + if (!get_string("Pref: ", buf, 80)) return; + + /* Process that pref command */ + (void)process_pref_file_aux(buf); +} + + +/* + * Hack -- append all current macros to the given file + */ +static errr macro_dump(cptr fname) +{ + int i; + + FILE *fff; + + char buf[1024]; + + + /* Build the filename */ + path_build(buf, 1024, ANGBAND_DIR_USER, fname); + + /* File type is "TEXT" */ + FILE_TYPE(FILE_TYPE_TEXT); + + /* Append to the file */ + fff = my_fopen(buf, "a"); + + /* Failure */ + if (!fff) return ( -1); + + + /* Skip space */ + fprintf(fff, "\n\n"); + + /* Start dumping */ + fprintf(fff, "# Automatic macro dump\n\n"); + + /* Dump them */ + for (i = 0; i < macro__num; i++) + { + /* Start the macro */ + fprintf(fff, "# Macro '%d'\n\n", i); + + /* Extract the action */ + ascii_to_text(buf, macro__act[i]); + + /* Dump the macro */ + fprintf(fff, "A:%s\n", buf); + + /* Extract the action */ + ascii_to_text(buf, macro__pat[i]); + + /* Dump normal macros */ + fprintf(fff, "P:%s\n", buf); + + /* End the macro */ + fprintf(fff, "\n\n"); + } + + /* Start dumping */ + fprintf(fff, "\n\n\n\n"); + + + /* Close */ + my_fclose(fff); + + /* Success */ + return (0); +} + + +/* + * Hack -- ask for a "trigger" (see below) + * + * Note the complex use of the "inkey()" function from "util.c". + * + * Note that both "flush()" calls are extremely important. + */ +static void do_cmd_macro_aux(char *buf, bool_ macro_screen) +{ + int i, n = 0; + + char tmp[1024]; + + + /* Flush */ + flush(); + + /* Do not process macros */ + inkey_base = TRUE; + + /* First key */ + i = inkey(); + + /* Read the pattern */ + while (i) + { + /* Save the key */ + buf[n++] = i; + + /* Do not process macros */ + inkey_base = TRUE; + + /* Do not wait for keys */ + inkey_scan = TRUE; + + /* Attempt to read a key */ + i = inkey(); + } + + /* Terminate */ + buf[n] = '\0'; + + /* Flush */ + flush(); + + + if (macro_screen) + { + /* Convert the trigger */ + ascii_to_text(tmp, buf); + + /* Hack -- display the trigger */ + Term_addstr( -1, TERM_WHITE, tmp); + } +} + +/* + * Hack -- ask for a keymap "trigger" (see below) + * + * Note that both "flush()" calls are extremely important. This may + * no longer be true, since "util.c" is much simpler now. XXX XXX XXX + */ +static void do_cmd_macro_aux_keymap(char *buf) +{ + char tmp[1024]; + + + /* Flush */ + flush(); + + + /* Get a key */ + buf[0] = inkey(); + buf[1] = '\0'; + + + /* Convert to ascii */ + ascii_to_text(tmp, buf); + + /* Hack -- display the trigger */ + Term_addstr( -1, TERM_WHITE, tmp); + + + /* Flush */ + flush(); +} + + +/* + * Hack -- append all keymaps to the given file + */ +static errr keymap_dump(cptr fname) +{ + int i; + + FILE *fff; + + char key[1024]; + char buf[1024]; + + int mode; + + + /* Keymap mode */ + mode = get_keymap_mode(); + + /* Build the filename */ + path_build(buf, 1024, ANGBAND_DIR_USER, fname); + + /* File type is "TEXT" */ + FILE_TYPE(FILE_TYPE_TEXT); + + /* Append to the file */ + fff = my_fopen(buf, "a"); + + /* Failure */ + if (!fff) return ( -1); + + + /* Skip space */ + fprintf(fff, "\n\n"); + + /* Start dumping */ + fprintf(fff, "# Automatic keymap dump\n\n"); + + /* Dump them */ + for (i = 0; i < 256; i++) + { + cptr act; + + /* Loop up the keymap */ + act = keymap_act[mode][i]; + + /* Skip empty keymaps */ + if (!act) continue; + + /* Encode the key */ + buf[0] = i; + buf[1] = '\0'; + ascii_to_text(key, buf); + + /* Encode the action */ + ascii_to_text(buf, act); + + /* Dump the macro */ + fprintf(fff, "A:%s\n", buf); + fprintf(fff, "C:%d:%s\n", mode, key); + } + + /* Start dumping */ + fprintf(fff, "\n\n\n"); + + + /* Close */ + my_fclose(fff); + + /* Success */ + return (0); +} + + + +/* + * Interact with "macros" + * + * Note that the macro "action" must be defined before the trigger. + * + * Could use some helpful instructions on this page. XXX XXX XXX + */ +void do_cmd_macros(void) +{ + int i; + + char tmp[1024]; + + char buf[1024]; + + int mode; + + + /* Keymap mode */ + mode = get_keymap_mode(); + + /* File type is "TEXT" */ + FILE_TYPE(FILE_TYPE_TEXT); + + + /* Enter "icky" mode */ + character_icky = TRUE; + + /* Save screen */ + Term_save(); + + + /* Process requests until done */ + while (1) + { + /* Clear screen */ + Term_clear(); + + /* Describe */ + prt("Interact with Macros", 2, 0); + + + /* Describe that action */ + prt("Current action (if any) shown below:", 20, 0); + + /* Analyze the current action */ + ascii_to_text(buf, macro__buf); + + /* Display the current action */ + prt(buf, 22, 0); + + + /* Selections */ + prt("(1) Load a user pref file", 4, 5); + prt("(2) Append macros to a file", 5, 5); + prt("(3) Query a macro", 6, 5); + prt("(4) Create a macro", 7, 5); + prt("(5) Remove a macro", 8, 5); + prt("(6) Append keymaps to a file", 9, 5); + prt("(7) Query a keymap", 10, 5); + prt("(8) Create a keymap", 11, 5); + prt("(9) Remove a keymap", 12, 5); + prt("(0) Enter a new action", 13, 5); + + /* Prompt */ + prt("Command: ", 16, 0); + + /* Get a command */ + i = inkey(); + + /* Leave */ + if (i == ESCAPE) break; + + /* Load a 'macro' file */ + else if (i == '1') + { + /* Prompt */ + prt("Command: Load a user pref file", 16, 0); + + /* Prompt */ + prt("File: ", 18, 0); + + /* Default filename */ + strnfmt(tmp, 1024, "%s.prf", player_name); + + /* Ask for a file */ + if (!askfor_aux(tmp, 80)) continue; + + /* Process the given filename */ + if (0 != process_pref_file(tmp)) + { + /* Prompt */ + msg_print("Could not load file!"); + } + } + + /* Save macros */ + else if (i == '2') + { + /* Prompt */ + prt("Command: Append macros to a file", 16, 0); + + /* Prompt */ + prt("File: ", 18, 0); + + /* Default filename */ + strnfmt(tmp, 1024, "%s.prf", player_name); + + /* Ask for a file */ + if (!askfor_aux(tmp, 80)) continue; + + /* Dump the macros */ + (void)macro_dump(tmp); + + /* Prompt */ + msg_print("Appended macros."); + } + + /* Query a macro */ + else if (i == '3') + { + int k; + + /* Prompt */ + prt("Command: Query a macro", 16, 0); + + /* Prompt */ + prt("Trigger: ", 18, 0); + + /* Get a macro trigger */ + do_cmd_macro_aux(buf, TRUE); + + /* Acquire action */ + k = macro_find_exact(buf); + + /* Nothing found */ + if (k < 0) + { + /* Prompt */ + msg_print("Found no macro."); + } + + /* Found one */ + else + { + /* Obtain the action */ + strcpy(macro__buf, macro__act[k]); + + /* Analyze the current action */ + ascii_to_text(buf, macro__buf); + + /* Display the current action */ + prt(buf, 22, 0); + + /* Prompt */ + msg_print("Found a macro."); + } + } + + /* Create a macro */ + else if (i == '4') + { + /* Prompt */ + prt("Command: Create a macro", 16, 0); + + /* Prompt */ + prt("Trigger: ", 18, 0); + + /* Get a macro trigger */ + do_cmd_macro_aux(buf, TRUE); + + /* Clear */ + clear_from(20); + + /* Prompt */ + prt("Action: ", 20, 0); + + /* Convert to text */ + ascii_to_text(tmp, macro__buf); + + /* Get an encoded action */ + if (askfor_aux(tmp, 80)) + { + /* Convert to ascii */ + text_to_ascii(macro__buf, tmp); + + /* Link the macro */ + macro_add(buf, macro__buf); + + /* Prompt */ + msg_print("Added a macro."); + } + } + + /* Remove a macro */ + else if (i == '5') + { + /* Prompt */ + prt("Command: Remove a macro", 16, 0); + + /* Prompt */ + prt("Trigger: ", 18, 0); + + /* Get a macro trigger */ + do_cmd_macro_aux(buf, TRUE); + + /* Link the macro */ + macro_add(buf, buf); + + /* Prompt */ + msg_print("Removed a macro."); + } + + /* Save keymaps */ + else if (i == '6') + { + /* Prompt */ + prt("Command: Append keymaps to a file", 16, 0); + + /* Prompt */ + prt("File: ", 18, 0); + + /* Default filename */ + strnfmt(tmp, 1024, "%s.prf", player_name); + + /* Ask for a file */ + if (!askfor_aux(tmp, 80)) continue; + + /* Dump the macros */ + (void)keymap_dump(tmp); + + /* Prompt */ + msg_print("Appended keymaps."); + } + + /* Query a keymap */ + else if (i == '7') + { + cptr act; + + /* Prompt */ + prt("Command: Query a keymap", 16, 0); + + /* Prompt */ + prt("Keypress: ", 18, 0); + + /* Get a keymap trigger */ + do_cmd_macro_aux_keymap(buf); + + /* Look up the keymap */ + act = keymap_act[mode][(byte)(buf[0])]; + + /* Nothing found */ + if (!act) + { + /* Prompt */ + msg_print("Found no keymap."); + } + + /* Found one */ + else + { + /* Obtain the action */ + strcpy(macro__buf, act); + + /* Analyze the current action */ + ascii_to_text(buf, macro__buf); + + /* Display the current action */ + prt(buf, 22, 0); + + /* Prompt */ + msg_print("Found a keymap."); + } + } + + /* Create a keymap */ + else if (i == '8') + { + /* Prompt */ + prt("Command: Create a keymap", 16, 0); + + /* Prompt */ + prt("Keypress: ", 18, 0); + + /* Get a keymap trigger */ + do_cmd_macro_aux_keymap(buf); + + /* Clear */ + clear_from(20); + + /* Prompt */ + prt("Action: ", 20, 0); + + /* Convert to text */ + ascii_to_text(tmp, macro__buf); + + /* Get an encoded action */ + if (askfor_aux(tmp, 80)) + { + /* Convert to ascii */ + text_to_ascii(macro__buf, tmp); + + /* Free old keymap */ + string_free(keymap_act[mode][(byte)(buf[0])]); + + /* Make new keymap */ + keymap_act[mode][(byte)(buf[0])] = string_make(macro__buf); + + /* Prompt */ + msg_print("Added a keymap."); + } + } + + /* Remove a keymap */ + else if (i == '9') + { + /* Prompt */ + prt("Command: Remove a keymap", 16, 0); + + /* Prompt */ + prt("Keypress: ", 18, 0); + + /* Get a keymap trigger */ + do_cmd_macro_aux_keymap(buf); + + /* Free old keymap */ + string_free(keymap_act[mode][(byte)(buf[0])]); + + /* Make new keymap */ + keymap_act[mode][(byte)(buf[0])] = NULL; + + /* Prompt */ + msg_print("Removed a keymap."); + } + + /* Enter a new action */ + else if (i == '0') + { + /* Prompt */ + prt("Command: Enter a new action", 16, 0); + + /* Go to the correct location */ + Term_gotoxy(0, 22); + + /* Hack -- limit the value */ + tmp[80] = '\0'; + + /* Get an encoded action */ + if (!askfor_aux(buf, 80)) continue; + + /* Extract an action */ + text_to_ascii(macro__buf, buf); + } + + /* Oops */ + else + { + /* Oops */ + bell(); + } + + /* Flush messages */ + msg_print(NULL); + } + + /* Load screen */ + Term_load(); + + /* Leave "icky" mode */ + character_icky = FALSE; +} + + +/* + * Interact with "visuals" + */ +void do_cmd_visuals(void) +{ + int i; + + FILE *fff; + + char tmp[160]; + + char buf[1024]; + + + /* File type is "TEXT" */ + FILE_TYPE(FILE_TYPE_TEXT); + + + /* Enter "icky" mode */ + character_icky = TRUE; + + /* Save the screen */ + Term_save(); + + + /* Interact until done */ + while (1) + { + /* Clear screen */ + Term_clear(); + + /* Ask for a choice */ + prt("Interact with Visuals", 2, 0); + + /* Give some choices */ + prt("(1) Load a user pref file", 4, 5); + prt("(2) Dump monster attr/chars", 5, 5); + prt("(3) Dump object attr/chars", 6, 5); + prt("(4) Dump feature attr/chars", 7, 5); + prt("(5) (unused)", 8, 5); + prt("(6) Change monster attr/chars", 9, 5); + prt("(7) Change object attr/chars", 10, 5); + prt("(8) Change feature attr/chars", 11, 5); + prt("(9) (unused)", 12, 5); + prt("(0) Reset visuals", 13, 5); + + /* Prompt */ + prt("Command: ", 15, 0); + + /* Prompt */ + i = inkey(); + + /* Done */ + if (i == ESCAPE) break; + + /* Load a 'pref' file */ + else if (i == '1') + { + /* Prompt */ + prt("Command: Load a user pref file", 15, 0); + + /* Prompt */ + prt("File: ", 17, 0); + + /* Default filename */ + strnfmt(tmp, 160, "user-%s.prf", ANGBAND_SYS); + + /* Query */ + if (!askfor_aux(tmp, 70)) continue; + + /* Process the given filename */ + (void)process_pref_file(tmp); + } + + /* Dump monster attr/chars */ + else if (i == '2') + { + /* Prompt */ + prt("Command: Dump monster attr/chars", 15, 0); + + /* Prompt */ + prt("File: ", 17, 0); + + /* Default filename */ + strnfmt(tmp, 160, "user-%s.prf", ANGBAND_SYS); + + /* Get a filename */ + if (!askfor_aux(tmp, 70)) continue; + + /* Build the filename */ + path_build(buf, 1024, ANGBAND_DIR_USER, tmp); + + /* Append to the file */ + fff = my_fopen(buf, "a"); + + /* Failure */ + if (!fff) continue; + + /* Start dumping */ + fprintf(fff, "\n\n"); + fprintf(fff, "# Monster attr/char definitions\n\n"); + + /* Dump monsters */ + for (i = 0; i < max_r_idx; i++) + { + monster_race *r_ptr = &r_info[i]; + + /* Skip non-entries */ + if (!r_ptr->name) continue; + + /* Dump a comment */ + fprintf(fff, "# %s\n", (r_name + r_ptr->name)); + + /* Dump the monster attr/char info */ + fprintf(fff, "R:%d:0x%02X:0x%02X\n\n", i, + static_cast(r_ptr->x_attr), + static_cast(r_ptr->x_char)); + } + + /* All done */ + fprintf(fff, "\n\n\n\n"); + + /* Close */ + my_fclose(fff); + + /* Message */ + msg_print("Dumped monster attr/chars."); + } + + /* Dump object attr/chars */ + else if (i == '3') + { + /* Prompt */ + prt("Command: Dump object attr/chars", 15, 0); + + /* Prompt */ + prt("File: ", 17, 0); + + /* Default filename */ + strnfmt(tmp, 160, "user-%s.prf", ANGBAND_SYS); + + /* Get a filename */ + if (!askfor_aux(tmp, 70)) continue; + + /* Build the filename */ + path_build(buf, 1024, ANGBAND_DIR_USER, tmp); + + /* Append to the file */ + fff = my_fopen(buf, "a"); + + /* Failure */ + if (!fff) continue; + + /* Start dumping */ + fprintf(fff, "\n\n"); + fprintf(fff, "# Object attr/char definitions\n\n"); + + /* Dump objects */ + for (i = 0; i < max_k_idx; i++) + { + object_kind *k_ptr = &k_info[i]; + + /* Skip non-entries */ + if (!k_ptr->name) continue; + + /* Dump a comment */ + fprintf(fff, "# %s\n", (k_name + k_ptr->name)); + + /* Dump the object attr/char info */ + fprintf(fff, "K:%d:0x%02X:0x%02X\n\n", i, + (byte)(k_ptr->x_attr), (byte)(k_ptr->x_char)); + } + + /* All done */ + fprintf(fff, "\n\n\n\n"); + + /* Close */ + my_fclose(fff); + + /* Message */ + msg_print("Dumped object attr/chars."); + } + + /* Dump feature attr/chars */ + else if (i == '4') + { + /* Prompt */ + prt("Command: Dump feature attr/chars", 15, 0); + + /* Prompt */ + prt("File: ", 17, 0); + + /* Default filename */ + strnfmt(tmp, 160, "user-%s.prf", ANGBAND_SYS); + + /* Get a filename */ + if (!askfor_aux(tmp, 70)) continue; + + /* Build the filename */ + path_build(buf, 1024, ANGBAND_DIR_USER, tmp); + + /* Append to the file */ + fff = my_fopen(buf, "a"); + + /* Failure */ + if (!fff) continue; + + /* Start dumping */ + fprintf(fff, "\n\n"); + fprintf(fff, "# Feature attr/char definitions\n\n"); + + /* Dump features */ + for (i = 0; i < max_f_idx; i++) + { + feature_type *f_ptr = &f_info[i]; + + /* Skip non-entries */ + if (!f_ptr->name) continue; + + /* Dump a comment */ + fprintf(fff, "# %s\n", (f_name + f_ptr->name)); + + /* Dump the feature attr/char info */ + fprintf(fff, "F:%d:0x%02X:0x%02X\n\n", i, + (byte)(f_ptr->x_attr), (byte)(f_ptr->x_char)); + } + + /* All done */ + fprintf(fff, "\n\n\n\n"); + + /* Close */ + my_fclose(fff); + + /* Message */ + msg_print("Dumped feature attr/chars."); + } + + /* Modify monster attr/chars */ + else if (i == '6') + { + static int r = 0; + + /* Prompt */ + prt("Command: Change monster attr/chars", 15, 0); + + /* Hack -- query until done */ + while (1) + { + monster_race *r_ptr = &r_info[r]; + + byte da = (r_ptr->d_attr); + char dc = (r_ptr->d_char); + byte ca = (r_ptr->x_attr); + char cc = (r_ptr->x_char); + + /* Label the object */ + Term_putstr(5, 17, -1, TERM_WHITE, + format("Monster = %d, Name = %-40.40s", + r, (r_name + r_ptr->name))); + + /* Label the Default values */ + Term_putstr(10, 19, -1, TERM_WHITE, + format("Default attr/char = %3u / %3u", da, (dc & 0xFF))); + Term_putstr(40, 19, -1, TERM_WHITE, "<< ? >>"); + Term_putch(43, 19, da, dc); + if (use_bigtile) + { + if (da & 0x80) + Term_putch(44, 19, 255, 255); + else + Term_putch(44, 19, 0, ' '); + } + + /* Label the Current values */ + Term_putstr(10, 20, -1, TERM_WHITE, + format("Current attr/char = %3u / %3u", ca, (cc & 0xFF))); + Term_putstr(40, 20, -1, TERM_WHITE, "<< ? >>"); + Term_putch(43, 20, ca, cc); + if (use_bigtile) + { + if (ca & 0x80) + Term_putch(44, 20, 255, 255); + else + Term_putch(44, 20, 0, ' '); + } + + /* Prompt */ + Term_putstr(0, 22, -1, TERM_WHITE, + "Command (n/N/a/A/c/C): "); + + /* Get a command */ + i = inkey(); + + /* All done */ + if (i == ESCAPE) break; + + /* Analyze */ + if (i == 'n') r = (r + max_r_idx + 1) % max_r_idx; + if (i == 'N') r = (r + max_r_idx - 1) % max_r_idx; + if (i == 'a') r_ptr->x_attr = (ca + 1); + if (i == 'A') r_ptr->x_attr = (ca - 1); + if (i == 'c') r_ptr->x_char = (cc + 1); + if (i == 'C') r_ptr->x_char = (cc - 1); + } + } + + /* Modify object attr/chars */ + else if (i == '7') + { + static int k = 0; + + /* Prompt */ + prt("Command: Change object attr/chars", 15, 0); + + /* Hack -- query until done */ + while (1) + { + object_kind *k_ptr = &k_info[k]; + + byte da = k_ptr->d_attr; + char dc = k_ptr->d_char; + byte ca = k_ptr->x_attr; + char cc = k_ptr->x_char; + + /* Label the object */ + Term_putstr(5, 17, -1, TERM_WHITE, + format("Object = %d, Name = %-40.40s", + k, (k_name + k_ptr->name))); + + /* Label the Default values */ + Term_putstr(10, 19, -1, TERM_WHITE, + format("Default attr/char = %3u / %3u", da, (dc & 0xFF))); + Term_putstr(40, 19, -1, TERM_WHITE, "<< ? >>"); + Term_putch(43, 19, da, dc); + if (use_bigtile) + { + if (da & 0x80) + Term_putch(44, 19, 255, 255); + else + Term_putch(44, 19, 0, ' '); + } + + /* Label the Current values */ + Term_putstr(10, 20, -1, TERM_WHITE, + format("Current attr/char = %3u / %3u", ca, (cc & 0xFF))); + Term_putstr(40, 20, -1, TERM_WHITE, "<< ? >>"); + Term_putch(43, 20, ca, cc); + if (use_bigtile) + { + if (ca & 0x80) + Term_putch(44, 20, 255, 255); + else + Term_putch(44, 20, 0, ' '); + } + + /* Prompt */ + Term_putstr(0, 22, -1, TERM_WHITE, + "Command (n/N/a/A/c/C): "); + + /* Get a command */ + i = inkey(); + + /* All done */ + if (i == ESCAPE) break; + + /* Analyze */ + if (i == 'n') k = (k + max_k_idx + 1) % max_k_idx; + if (i == 'N') k = (k + max_k_idx - 1) % max_k_idx; + if (i == 'a') k_info[k].x_attr = (ca + 1); + if (i == 'A') k_info[k].x_attr = (ca - 1); + if (i == 'c') k_info[k].x_char = (cc + 1); + if (i == 'C') k_info[k].x_char = (cc - 1); + } + } + + /* Modify feature attr/chars */ + else if (i == '8') + { + static int f = 0; + + /* Prompt */ + prt("Command: Change feature attr/chars", 15, 0); + + /* Hack -- query until done */ + while (1) + { + feature_type *f_ptr = &f_info[f]; + + byte da = f_ptr->d_attr; + char dc = f_ptr->d_char; + byte ca = f_ptr->x_attr; + char cc = f_ptr->x_char; + + /* Label the object */ + Term_putstr(5, 17, -1, TERM_WHITE, + format("Terrain = %d, Name = %-40.40s", + f, (f_name + f_ptr->name))); + + /* Label the Default values */ + Term_putstr(10, 19, -1, TERM_WHITE, + format("Default attr/char = %3u / %3u", da, (dc & 0xFF))); + Term_putstr(40, 19, -1, TERM_WHITE, "<< ? >>"); + Term_putch(43, 19, da, dc); + if (use_bigtile) + { + if (da & 0x80) + Term_putch(44, 19, 255, 255); + else + Term_putch(44, 19, 0, ' '); + } + + /* Label the Current values */ + Term_putstr(10, 20, -1, TERM_WHITE, + format("Current attr/char = %3u / %3u", ca, (cc & 0xFF))); + Term_putstr(40, 20, -1, TERM_WHITE, "<< ? >>"); + Term_putch(43, 20, ca, cc); + if (use_bigtile) + { + if (ca & 0x80) + Term_putch(44, 20, 255, 255); + else + Term_putch(44, 20, 0, ' '); + } + + /* Prompt */ + Term_putstr(0, 22, -1, TERM_WHITE, + "Command (n/N/a/A/c/C/d): "); + + /* Get a command */ + i = inkey(); + + /* All done */ + if (i == ESCAPE) break; + + /* Analyze */ + if (i == 'n') f = (f + max_f_idx + 1) % max_f_idx; + if (i == 'N') f = (f + max_f_idx - 1) % max_f_idx; + if (i == 'a') f_info[f].x_attr = (ca + 1); + if (i == 'A') f_info[f].x_attr = (ca - 1); + if (i == 'c') f_info[f].x_char = (cc + 1); + if (i == 'C') f_info[f].x_char = (cc - 1); + if (i == 'd') + { + f_info[f].x_char = f_ptr->d_char; + f_info[f].x_attr = f_ptr->d_attr; + } + } + } + + /* Reset visuals */ + else if (i == '0') + { + /* Reset */ + reset_visuals(); + + /* Message */ + msg_print("Visual attr/char tables reset."); + } + + /* Unknown option */ + else + { + bell(); + } + + /* Flush messages */ + msg_print(NULL); + } + + + /* Restore the screen */ + Term_load(); + + /* Leave "icky" mode */ + character_icky = FALSE; +} + + +/* + * Interact with "colors" + */ +void do_cmd_colors(void) +{ + int i; + + FILE *fff; + + char tmp[160]; + + char buf[1024]; + + + /* File type is "TEXT" */ + FILE_TYPE(FILE_TYPE_TEXT); + + + /* Enter "icky" mode */ + character_icky = TRUE; + + /* Save the screen */ + Term_save(); + + + /* Interact until done */ + while (1) + { + /* Clear screen */ + Term_clear(); + + /* Ask for a choice */ + prt("Interact with Colors", 2, 0); + + /* Give some choices */ + prt("(1) Load a user pref file", 4, 5); + prt("(2) Dump colors", 5, 5); + prt("(3) Modify colors", 6, 5); + + /* Prompt */ + prt("Command: ", 8, 0); + + /* Prompt */ + i = inkey(); + + /* Done */ + if (i == ESCAPE) break; + + /* Load a 'pref' file */ + if (i == '1') + { + /* Prompt */ + prt("Command: Load a user pref file", 8, 0); + + /* Prompt */ + prt("File: ", 10, 0); + + /* Default file */ + strnfmt(tmp, 160, "user-%s.prf", ANGBAND_SYS); + + /* Query */ + if (!askfor_aux(tmp, 70)) continue; + + /* Process the given filename */ + (void)process_pref_file(tmp); + + /* Mega-Hack -- react to changes */ + Term_xtra(TERM_XTRA_REACT, 0); + + /* Mega-Hack -- redraw */ + Term_redraw(); + } + + /* Dump colors */ + else if (i == '2') + { + /* Prompt */ + prt("Command: Dump colors", 8, 0); + + /* Prompt */ + prt("File: ", 10, 0); + + /* Default filename */ + strnfmt(tmp, 160, "user-%s.prf", ANGBAND_SYS); + + /* Get a filename */ + if (!askfor_aux(tmp, 70)) continue; + + /* Build the filename */ + path_build(buf, 1024, ANGBAND_DIR_USER, tmp); + + /* Append to the file */ + fff = my_fopen(buf, "a"); + + /* Failure */ + if (!fff) continue; + + /* Start dumping */ + fprintf(fff, "\n\n"); + fprintf(fff, "# Color redefinitions\n\n"); + + /* Dump colors */ + for (i = 0; i < 256; i++) + { + int kv = angband_color_table[i][0]; + int rv = angband_color_table[i][1]; + int gv = angband_color_table[i][2]; + int bv = angband_color_table[i][3]; + + cptr name = "unknown"; + + /* Skip non-entries */ + if (!kv && !rv && !gv && !bv) continue; + + /* Extract the color name */ + if (i < 16) name = color_names[i]; + + /* Dump a comment */ + fprintf(fff, "# Color '%s'\n", name); + + /* Dump the monster attr/char info */ + fprintf(fff, "V:%d:0x%02X:0x%02X:0x%02X:0x%02X\n\n", + i, kv, rv, gv, bv); + } + + /* All done */ + fprintf(fff, "\n\n\n\n"); + + /* Close */ + my_fclose(fff); + + /* Message */ + msg_print("Dumped color redefinitions."); + } + + /* Edit colors */ + else if (i == '3') + { + static byte a = 0; + + /* Prompt */ + prt("Command: Modify colors", 8, 0); + + /* Hack -- query until done */ + while (1) + { + cptr name; + + /* Clear */ + clear_from(10); + + /* Exhibit the normal colors */ + for (i = 0; i < 16; i++) + { + /* Exhibit this color */ + Term_putstr(i*4, 20, -1, a, "###"); + + /* Exhibit all colors */ + Term_putstr(i*4, 22, -1, i, format("%3d", i)); + } + + /* Describe the color */ + name = ((a < 16) ? color_names[a] : "undefined"); + + /* Describe the color */ + Term_putstr(5, 10, -1, TERM_WHITE, + format("Color = %d, Name = %s", a, name)); + + /* Label the Current values */ + Term_putstr(5, 12, -1, TERM_WHITE, + format("K = 0x%02x / R,G,B = 0x%02x,0x%02x,0x%02x", + angband_color_table[a][0], + angband_color_table[a][1], + angband_color_table[a][2], + angband_color_table[a][3])); + + /* Prompt */ + Term_putstr(0, 14, -1, TERM_WHITE, + "Command (n/N/k/K/r/R/g/G/b/B): "); + + /* Get a command */ + i = inkey(); + + /* All done */ + if (i == ESCAPE) break; + + /* Analyze */ + if (i == 'n') a = (a + 1); + if (i == 'N') a = (a - 1); + if (i == 'k') angband_color_table[a][0] = (angband_color_table[a][0] + 1); + if (i == 'K') angband_color_table[a][0] = (angband_color_table[a][0] - 1); + if (i == 'r') angband_color_table[a][1] = (angband_color_table[a][1] + 1); + if (i == 'R') angband_color_table[a][1] = (angband_color_table[a][1] - 1); + if (i == 'g') angband_color_table[a][2] = (angband_color_table[a][2] + 1); + if (i == 'G') angband_color_table[a][2] = (angband_color_table[a][2] - 1); + if (i == 'b') angband_color_table[a][3] = (angband_color_table[a][3] + 1); + if (i == 'B') angband_color_table[a][3] = (angband_color_table[a][3] - 1); + + /* Hack -- react to changes */ + Term_xtra(TERM_XTRA_REACT, 0); + + /* Hack -- redraw */ + Term_redraw(); + } + } + + /* Unknown option */ + else + { + bell(); + } + + /* Flush messages */ + msg_print(NULL); + } + + + /* Restore the screen */ + Term_load(); + + /* Leave "icky" mode */ + character_icky = FALSE; +} + + +/* + * Take notes. There are two ways this can happen, either in the message + * recall or a file. + */ +void do_cmd_note(void) +{ + char buf[80]; + + + /* Default */ + strcpy(buf, ""); + + if (!get_string("Note: ", buf, 60)) return; + + /* Ignore empty notes */ + if (!buf[0] || (buf[0] == ' ')) return; + + /* Add note to file */ + add_note(buf, ' '); +} + + +/* + * Mention the current version + */ +void do_cmd_version(void) +{ + /* Silly message */ + msg_format("You are playing %s made by %s (%s).", + get_version_string(), + modules[game_module_idx].meta.author.name, + modules[game_module_idx].meta.author.email); +} + + + +/* + * Array of feeling strings + */ +static cptr do_cmd_feeling_text[11] = +{ + "Looks like any other level.", + "You feel there is something special about this level.", + "You have a superb feeling about this level.", + "You have an excellent feeling...", + "You have a very good feeling...", + "You have a good feeling...", + "You feel strangely lucky...", + "You feel your luck is turning...", + "You like the look of this place...", + "This level can't be all bad...", + "What a boring place..." +}; + + +/* + * Note that "feeling" is set to zero unless some time has passed. + * Note that this is done when the level is GENERATED, not entered. + */ +void do_cmd_feeling(void) +{ + /* Verify the feeling */ + if (feeling < 0) feeling = 0; + if (feeling > 10) feeling = 10; + + /* Feeling of the fate */ + if (fate_flag && !(dungeon_flags2 & DF2_SPECIAL) && !p_ptr->inside_quest) + { + msg_print("You feel that you will meet your fate here."); + } + + /* Hooked feelings ? */ + if (process_hooks(HOOK_FEELING, "(d)", is_quest(dun_level))) + { + return; + } + + /* No useful feeling in special levels */ + if (dungeon_flags2 & DF2_DESC) + { + char buf[1024]; + + if ((get_dungeon_save(buf)) || (generate_special_feeling) || (dungeon_flags2 & DF2_DESC_ALWAYS)) + { + if (!get_level_desc(buf)) msg_print("Someone forgot to describe this level!"); + else msg_print(buf); + return; + } + } + + /* No useful feeling in quests */ + if (p_ptr->inside_quest) + { + msg_print("Looks like a typical quest level."); + return; + } + + /* Display feelings in the dungeon, nothing on the surface */ + if (dun_level) + { + /* This could be simplified with a correct p_ptr->town_num */ + int i, town_level = 0; + dungeon_info_type *d_ptr = &d_info[dungeon_type]; + + /* Is it a town level ? */ + for (i = 0; i < TOWN_DUNGEON; i++) + { + if (d_ptr->t_level[i] == dun_level) town_level = d_ptr->t_idx[i]; + } + + if (town_level) + msg_print("You hear the sound of a market."); + else + msg_print(do_cmd_feeling_text[feeling]); + } + return; +} + + + +/* + * Encode the screen colors + */ +static char hack[17] = "dwsorgbuDWvyRGBU"; + + +/* + * Hack -- load a screen dump from a file + */ +void do_cmd_load_screen(void) +{ + int i, y, x; + + int wid, hgt; + int len; + + byte a = 0; + char c = ' '; + + bool_ okay = TRUE; + + FILE *fff; + + char buf[1024]; + + + /* Build the filename */ + path_build(buf, 1024, ANGBAND_DIR_USER, "dump.txt"); + + /* Append to the file */ + fff = my_fopen(buf, "r"); + + /* Oops */ + if (!fff) return; + + + /* Retrieve the current screen size */ + Term_get_size(&wid, &hgt); + + /* Enter "icky" mode */ + character_icky = TRUE; + + /* Save the screen */ + Term_save(); + + /* Clear the screen */ + Term_clear(); + + + /* Load the screen */ + for (y = 0; okay; y++) + { + /* Get a line of data */ + if (my_fgets(fff, buf, 1024)) okay = FALSE; + + /* Stop on blank line */ + if (!buf[0]) break; + + /* Ignore off screen lines */ + if (y >= hgt) continue; + + /* Get width */ + len = strlen(buf); + + /* Truncate if it's longer than current screen width */ + if (len > wid) len = wid; + + /* Show each row */ + for (x = 0; x < len; x++) + { + /* Put the attr/char */ + Term_draw(x, y, TERM_WHITE, buf[x]); + } + } + + /* Dump the screen */ + for (y = 0; okay; y++) + { + /* Get a line of data */ + if (my_fgets(fff, buf, 1024)) okay = FALSE; + + /* Stop on blank line */ + if (!buf[0]) break; + + /* Ignore off screen lines */ + if (y >= hgt) continue; + + /* Get width */ + len = strlen(buf); + + /* Truncate if it's longer than current screen width */ + if (len > wid) len = wid; + + /* Dump each row */ + for (x = 0; x < len; x++) + { + /* Get the attr/char */ + (void)(Term_what(x, y, &a, &c)); + + /* Look up the attr */ + for (i = 0; i < 16; i++) + { + /* Use attr matches */ + if (hack[i] == buf[x]) a = i; + } + + /* Put the attr/char */ + Term_draw(x, y, a, c); + } + } + + + /* Close it */ + my_fclose(fff); + + + /* Message */ + msg_print("Screen dump loaded."); + msg_print(NULL); + + + /* Restore the screen */ + Term_load(); + + /* Leave "icky" mode */ + character_icky = FALSE; +} + + + +/* + * Redefinable "save_screen" action + */ +void (*screendump_aux)(void) = NULL; + + + + + + +/* + * Hack -- save a screen dump to a file + */ +void do_cmd_save_screen(void) +{ + /* Do we use a special screendump function ? */ + if (screendump_aux) + { + /* Dump the screen to a graphics file */ + (*screendump_aux)(); + } + + /* Dump the screen as text */ + else + { + int y, x; + int wid, hgt; + + byte a = 0; + char c = ' '; + + FILE *fff; + + char buf[1024]; + + + /* Build the filename */ + path_build(buf, 1024, ANGBAND_DIR_USER, "dump.txt"); + + /* File type is "TEXT" */ + FILE_TYPE(FILE_TYPE_TEXT); + + /* Append to the file */ + fff = my_fopen(buf, "w"); + + /* Oops */ + if (!fff) return; + + + /* Retrieve the current screen size */ + Term_get_size(&wid, &hgt); + + /* Enter "icky" mode */ + character_icky = TRUE; + + /* Save the screen */ + Term_save(); + + + /* Dump the screen */ + for (y = 0; y < hgt; y++) + { + /* Dump each row */ + for (x = 0; x < wid; x++) + { + /* Get the attr/char */ + (void)(Term_what(x, y, &a, &c)); + + /* Dump it */ + buf[x] = c; + } + + /* Terminate */ + buf[x] = '\0'; + + /* End the row */ + fprintf(fff, "%s\n", buf); + } + + /* Skip a line */ + fprintf(fff, "\n"); + + + /* Dump the screen */ + for (y = 0; y < hgt; y++) + { + /* Dump each row */ + for (x = 0; x < wid; x++) + { + /* Get the attr/char */ + (void)(Term_what(x, y, &a, &c)); + + /* Dump it */ + buf[x] = hack[a & 0x0F]; + } + + /* Terminate */ + buf[x] = '\0'; + + /* End the row */ + fprintf(fff, "%s\n", buf); + } + + /* Skip a line */ + fprintf(fff, "\n"); + + + /* Close it */ + my_fclose(fff); + + + /* Message */ + msg_print("Screen dump saved."); + msg_print(NULL); + + + /* Restore the screen */ + Term_load(); + + /* Leave "icky" mode */ + character_icky = FALSE; + } +} + + +/* + * Check the status of "artifacts" + */ +void do_cmd_knowledge_artifacts(void) +{ + int i, k, z, x, y; + + FILE *fff; + + char file_name[1024]; + + char base_name[80]; + + /* Temporary file */ + if (path_temp(file_name, 1024)) return; + + /* Open a new file */ + fff = my_fopen(file_name, "w"); + + /* Scan the artifacts */ + std::unique_ptr okay(new bool_[max_a_idx]); + for (k = 0; k < max_a_idx; k++) + { + artifact_type *a_ptr = &a_info[k]; + + /* Default */ + okay[k] = FALSE; + + /* Skip "empty" artifacts */ + if (!a_ptr->name) continue; + + /* Skip "uncreated" artifacts */ + if (!a_ptr->cur_num) continue; + + /* Assume okay */ + okay[k] = TRUE; + } + + std::unique_ptr okayk(new bool_[max_k_idx]); + for (k = 0; k < max_k_idx; k++) + { + object_kind *k_ptr = &k_info[k]; + + /* Default */ + okayk[k] = FALSE; + + /* Skip "empty" artifacts */ + if (!(k_ptr->flags3 & TR3_NORM_ART)) continue; + + /* Skip "uncreated" artifacts */ + if (!k_ptr->artifact) continue; + + /* Assume okay */ + okayk[k] = TRUE; + } + + /* Check the dungeon */ + for (y = 0; y < cur_hgt; y++) + { + for (x = 0; x < cur_wid; x++) + { + cave_type *c_ptr = &cave[y][x]; + + s16b this_o_idx, next_o_idx = 0; + + /* Scan all objects in the grid */ + for (this_o_idx = c_ptr->o_idx; this_o_idx; this_o_idx = next_o_idx) + { + object_type * o_ptr; + + /* Acquire object */ + o_ptr = &o_list[this_o_idx]; + + /* Acquire next object */ + next_o_idx = o_ptr->next_o_idx; + + /* Ignore random artifacts */ + if (o_ptr->tval == TV_RANDART) continue; + + /* Ignore non-artifacts */ + if (!artifact_p(o_ptr)) continue; + + /* Ignore known items */ + if (object_known_p(o_ptr)) continue; + + /* Note the artifact */ + if (k_info[o_ptr->k_idx].flags3 & TR3_NORM_ART) + { + okayk[o_ptr->k_idx] = FALSE; + } + else + { + okay[o_ptr->name1] = FALSE; + } + } + } + } + + /* Check monsters in the dungeon */ + for (i = 0; i < m_max; i++) + { + monster_type *m_ptr = &m_list[i]; + + s16b this_o_idx, next_o_idx = 0; + + /* Scan all objects the monster carries */ + for (this_o_idx = m_ptr->hold_o_idx; this_o_idx; this_o_idx = next_o_idx) + { + object_type * o_ptr; + + /* Acquire object */ + o_ptr = &o_list[this_o_idx]; + + /* Acquire next object */ + next_o_idx = o_ptr->next_o_idx; + + /* Ignore random artifacts */ + if (o_ptr->tval == TV_RANDART) continue; + + /* Ignore non-artifacts */ + if (!artifact_p(o_ptr)) continue; + + /* Ignore known items */ + if (object_known_p(o_ptr)) continue; + + /* Note the artifact */ + if (k_info[o_ptr->k_idx].flags3 & TR3_NORM_ART) + { + okayk[o_ptr->k_idx] = FALSE; + } + else + { + okay[o_ptr->name1] = FALSE; + } + } + } + + /* Check the p_ptr->inventory and equipment */ + for (i = 0; i < INVEN_TOTAL; i++) + { + object_type *o_ptr = &p_ptr->inventory[i]; + + /* Ignore non-objects */ + if (!o_ptr->k_idx) continue; + + /* Ignore random artifacts */ + if (o_ptr->tval == TV_RANDART) continue; + + /* Ignore non-artifacts */ + if (!artifact_p(o_ptr)) continue; + + /* Ignore known items */ + if (object_known_p(o_ptr)) continue; + + /* Note the artifact */ + if (k_info[o_ptr->k_idx].flags3 & TR3_NORM_ART) + { + okayk[o_ptr->k_idx] = FALSE; + } + else + { + okay[o_ptr->name1] = FALSE; + } + } + + /* Scan the artifacts */ + for (k = 0; k < max_a_idx; k++) + { + artifact_type *a_ptr = &a_info[k]; + + /* List "dead" ones */ + if (!okay[k]) continue; + + /* Paranoia */ + strcpy(base_name, "Unknown Artifact"); + + /* Obtain the base object type */ + z = lookup_kind(a_ptr->tval, a_ptr->sval); + + /* Real object */ + if (z) + { + object_type forge; + object_type *q_ptr; + u32b f1, f2, f3, f4, f5, esp; + + /* Get local object */ + q_ptr = &forge; + + /* Create fake object */ + object_prep(q_ptr, z); + + /* Make it an artifact */ + q_ptr->name1 = k; + + /* Spell in it ? no ! */ + object_flags(q_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + if (f5 & TR5_SPELL_CONTAIN) + q_ptr->pval2 = -1; + + /* Describe the artifact */ + object_desc_store(base_name, q_ptr, FALSE, 0); + } + + /* Hack -- Build the artifact name */ + fprintf(fff, " The %s\n", base_name); + } + + for (k = 0; k < max_k_idx; k++) + { + /* List "dead" ones */ + if (!okayk[k]) continue; + + /* Paranoia */ + strcpy(base_name, "Unknown Artifact"); + + /* Real object */ + if (k) + { + object_type forge; + object_type *q_ptr; + + /* Get local object */ + q_ptr = &forge; + + /* Create fake object */ + object_prep(q_ptr, k); + + /* Describe the artifact */ + object_desc_store(base_name, q_ptr, FALSE, 0); + } + + /* Hack -- Build the artifact name */ + fprintf(fff, " The %s\n", base_name); + } + + /* Close the file */ + my_fclose(fff); + + /* Display the file contents */ + show_file(file_name, "Artifacts Seen", 0, 0); + + /* Remove the file */ + fd_kill(file_name); +} + + +/* + * Check the status of traps + */ +void do_cmd_knowledge_traps(void) +{ + int k; + + FILE *fff; + + trap_type *t_ptr; + + char file_name[1024]; + + + /* Temporary file */ + if (path_temp(file_name, 1024)) return; + + /* Open a new file */ + fff = my_fopen(file_name, "w"); + + /* Scan the traps */ + for (k = 0; k < max_t_idx; k++) + { + /* Get the trap */ + t_ptr = &t_info[k]; + + /* Skip "empty" traps */ + if (!t_ptr->name) continue; + + /* Skip unidentified traps */ + if (!t_ptr->ident) continue; + + /* Hack -- Build the trap name */ + fprintf(fff, " %s\n", t_name + t_ptr->name); + } + + /* Close the file */ + my_fclose(fff); + + /* Display the file contents */ + show_file(file_name, "Traps known", 0, 0); + + /* Remove the file */ + fd_kill(file_name); +} + + +static int monster_get_race_level(int r_idx) { + /* Hack -- Morgoth is always last */ + if (r_idx == 862) { + return 20000; + } + /* Otherwise, we'll use the real level. */ + return r_info[r_idx].level; +} + +static bool compare_monster_level(int r_idx1, int r_idx2) { + return monster_get_race_level(r_idx1) < monster_get_race_level(r_idx2); +} + +/* + * Display known uniques + * + * Note that the player ghosts are ignored. XXX XXX XXX + */ +static void do_cmd_knowledge_uniques(void) +{ + int k; + + FILE *fff; + + char file_name[1024]; + + + /* Temporary file */ + if (path_temp(file_name, 1024)) return; + + /* Open a new file */ + fff = my_fopen(file_name, "w"); + + // Extract the unique race indexes. + std::vector unique_r_idxs; + for (k = 1; k < max_r_idx; k++) + { + monster_race *r_ptr = &r_info[k]; + + /* Only print Uniques */ + if (r_ptr->flags1 & (RF1_UNIQUE) && + !(r_ptr->flags7 & RF7_PET) && + !(r_ptr->flags7 & RF7_NEUTRAL)) + { + unique_r_idxs.push_back(k); + } + } + + // Sort races by level. + std::sort(std::begin(unique_r_idxs), + std::end(unique_r_idxs), + compare_monster_level); + + /* Scan the monster races */ + for (int r_idx : unique_r_idxs) + { + monster_race *r_ptr = &r_info[r_idx]; + + /* Only print Uniques */ + if (r_ptr->flags1 & (RF1_UNIQUE)) + { + bool_ dead = (r_ptr->max_num == 0); + + /* Only display "known" uniques */ + if (dead || cheat_know || r_ptr->r_sights) + { + /* Print a message */ + if (dead) + { + /* Don't print the unique's ASCII symbol + * if use_graphics is on. */ + if (use_graphics) + { + fprintf(fff, "[[[[[R%-70s is dead]\n", + (r_name + r_ptr->name)); + } + else + { + fprintf(fff, "[[[[[%c%c] [[[[[R%-68s is dead]\n", + conv_color[r_ptr->d_attr], + r_ptr->d_char, + (r_name + r_ptr->name)); + } + } + else + { + /* Don't print the unique's ASCII symbol + * if use_graphics is on. */ + if (use_graphics) + { + fprintf(fff, "[[[[[w%-70s is alive]\n", + (r_name + r_ptr->name)); + } + else + { + fprintf(fff, "[[[[[%c%c] [[[[[w%-68s is alive]\n", + conv_color[r_ptr->d_attr], + r_ptr->d_char, + (r_name + r_ptr->name)); + } + } + } + } + } + + /* Close the file */ + my_fclose(fff); + + /* Display the file contents */ + show_file(file_name, "Known Uniques", 0, 0); + + /* Remove the file */ + fd_kill(file_name); +} + + +void plural_aux(char *name) +{ + int name_len = strlen(name); + + /* Hack -- Precedent must be pluralised for this one */ + if (strstr(name, "Disembodied hand")) + { + strcpy(name, "Disembodied hands that strangled people"); + } + + /* "someone of something" */ + else if (strstr(name, " of ")) + { + cptr aider = strstr(name, " of "); + char dummy[80]; + int i = 0; + cptr ctr = name; + + while (ctr < aider) + { + dummy[i] = *ctr; + ctr++; + i++; + } + + if (dummy[i - 1] == 's') + { + strcpy(&dummy[i], "es"); + i++; + } + else + { + strcpy(&dummy[i], "s"); + } + + strcpy(&dummy[i + 1], aider); + strcpy(name, dummy); + } + + /* Creeping coins */ + else if (strstr(name, "coins")) + { + char dummy[80]; + strcpy(dummy, "piles of "); + strcat(dummy, name); + strcpy(name, dummy); + return; + } + + /* Manes stay manes */ + else if (strstr(name, "Manes")) + { + return; + } + + /* Broken plurals are, well, broken */ + else if (name[name_len - 1] == 'y') + { + strcpy(&name[name_len - 1], "ies"); + } + else if (streq(&name[name_len - 4], "ouse")) + { + strcpy(&name[name_len - 4], "ice"); + } + else if (streq(&name[name_len - 6], "kelman")) + { + strcpy(&name[name_len - 6], "kelmen"); + } + else if (streq(&name[name_len - 2], "ex")) + { + strcpy(&name[name_len - 2], "ices"); + } + else if (streq(&name[name_len - 3], "olf")) + { + strcpy(&name[name_len - 3], "olves"); + } + + /* Now begins sane cases */ + else if ((streq(&name[name_len - 2], "ch")) || (name[name_len - 1] == 's')) + { + strcpy(&name[name_len], "es"); + } + else + { + strcpy(&name[name_len], "s"); + } +} + + +/* + * Display current pets + */ +static void do_cmd_knowledge_pets(void) +{ + int i; + + FILE *fff; + + monster_type *m_ptr; + + int t_friends = 0; + + int t_levels = 0; + + int show_upkeep = 0; + + int upkeep_divider = 20; + + char file_name[1024]; + + + /* Temporary file */ + if (path_temp(file_name, 1024)) return; + + /* Open a new file */ + fff = my_fopen(file_name, "w"); + + if (has_ability(AB_PERFECT_CASTING)) upkeep_divider = 15; + + /* Process the monsters (backwards) */ + for (i = m_max - 1; i >= 1; i--) + { + /* Access the monster */ + m_ptr = &m_list[i]; + + /* Ignore "dead" monsters */ + if (!m_ptr->r_idx) continue; + + /* Calculate "upkeep" for friendly monsters */ + if (m_ptr->status >= MSTATUS_PET) + { + char pet_name[80]; + monster_race *r_ptr = race_inf(m_ptr); + + t_friends++; + t_levels += m_ptr->level; + monster_desc(pet_name, m_ptr, 0x88); + fprintf(fff, "%s%s (%s)\n", + (r_ptr->flags1 & RF1_UNIQUE) ? "#####G" : "", + pet_name, + (m_ptr->status < MSTATUS_COMPANION) ? "pet" : "companion"); + } + } + + if (t_friends > 1 + (p_ptr->lev / (upkeep_divider))) + { + show_upkeep = (t_levels); + + if (show_upkeep > 100) show_upkeep = 100; + else if (show_upkeep < 10) show_upkeep = 10; + } + + + fprintf(fff, "----------------------------------------------\n"); + fprintf(fff, " Total: %d pet%s.\n", t_friends, (t_friends == 1 ? "" : "s")); + fprintf(fff, " Upkeep: %d%% mana.\n", show_upkeep); + + + /* Close the file */ + my_fclose(fff); + + /* Display the file contents */ + show_file(file_name, "Current Pets", 0, 0); + + /* Remove the file */ + fd_kill(file_name); +} + + + +/* + * Total kill count + * + * Note that the player ghosts are ignored. XXX XXX XXX + */ +static void do_cmd_knowledge_kill_count(void) +{ + int k; + + FILE *fff; + + char file_name[1024]; + + s32b Total = 0; + + + /* Temporary file */ + if (path_temp(file_name, 1024)) return; + + /* Open a new file */ + fff = my_fopen(file_name, "w"); + + { + /* Monsters slain */ + int kk; + + /* For all monsters */ + for (kk = 1; kk < max_r_idx; kk++) + { + monster_race *r_ptr = &r_info[kk]; + + if (r_ptr->flags1 & (RF1_UNIQUE)) + { + bool_ dead = (r_ptr->max_num == 0); + + if (dead) + { + Total++; + } + } + else + { + s16b This = r_ptr->r_pkills; + + if (This > 0) + { + Total += This; + } + } + } + + if (Total < 1) + { + fprintf(fff, "You have defeated no enemies yet.\n\n"); + } + else if (Total == 1) + { + fprintf(fff, "You have defeated one enemy.\n\n"); + } + else + { + fprintf(fff, "You have defeated " FMTs32b " enemies.\n\n", Total); + } + } + + Total = 0; + + /* Scan the monster races */ + for (k = 0; k < max_r_idx; k++) + { + monster_race *r_ptr = &r_info[k]; + + if (r_ptr->flags1 & (RF1_UNIQUE)) + { + bool_ dead = (r_ptr->max_num == 0); + + if (dead) + { + /* Print a message */ + fprintf(fff, " %s\n", + (r_name + r_ptr->name)); + Total++; + } + } + else + { + s16b This = r_ptr->r_pkills; + + if (This > 0) + { + if (This < 2) + { + if (strstr(r_name + r_ptr->name, "coins")) + { + fprintf(fff, " 1 pile of %s\n", (r_name + r_ptr->name)); + } + else + { + fprintf(fff, " 1 %s\n", (r_name + r_ptr->name)); + } + } + else + { + char to_plural[80]; + strcpy(to_plural, (r_name + r_ptr->name)); + plural_aux(to_plural); + fprintf(fff, " %d %s\n", This, to_plural); + } + + Total += This; + } + } + } + + fprintf(fff, "----------------------------------------------\n"); + fprintf(fff, " Total: " FMTs32b " creature%s killed.\n", Total, (Total == 1 ? "" : "s")); + + /* Close the file */ + my_fclose(fff); + + /* Display the file contents */ + show_file(file_name, "Kill Count", 0, 0); + + /* Remove the file */ + fd_kill(file_name); +} + + +/* + * Display known objects + */ +static void do_cmd_knowledge_objects(void) +{ + int k; + + FILE *fff; + + char o_name[80]; + + char file_name[1024]; + + + /* Temporary file */ + if (path_temp(file_name, 1024)) return; + + /* Open a new file */ + fff = my_fopen(file_name, "w"); + + /* Scan the object kinds */ + for (k = 1; k < max_k_idx; k++) + { + object_kind *k_ptr = &k_info[k]; + + /* Hack -- skip artifacts */ + if (k_ptr->flags3 & (TR3_INSTA_ART)) continue; + + /* List known flavored objects */ + if (k_ptr->flavor && k_ptr->aware) + { + object_type *i_ptr; + object_type object_type_body; + + /* Get local object */ + i_ptr = &object_type_body; + + /* Create fake object */ + object_prep(i_ptr, k); + + /* Describe the object */ + object_desc_store(o_name, i_ptr, FALSE, 0); + + /* Print a message */ + fprintf(fff, " %s\n", o_name); + } + } + + /* Close the file */ + my_fclose(fff); + + /* Display the file contents */ + show_file(file_name, "Known Objects", 0, 0); + + /* Remove the file */ + fd_kill(file_name); +} + + +/* + * List recall depths + */ +static void do_cmd_knowledge_dungeons(void) +{ + int y; + char file_name[1024]; + FILE *fff; + + /* Temporary file */ + if (path_temp(file_name, 1024)) return; + + /* Open a new file */ + fff = my_fopen(file_name, "w"); + + /* Oops */ + if (fff == NULL) return; + + /* Scan all dungeons */ + for (y = 1; y < max_d_idx; y++) + { + /* The dungeon has a valid recall depth set */ + if (max_dlv[y]) + { + /* Describe the recall depth */ + fprintf(fff, " %c%s: Level %d (%d')\n", + (p_ptr->recall_dungeon == y) ? '*' : ' ', + d_name + d_info[y].name, + max_dlv[y], 50 * (max_dlv[y])); + } + } + + /* Close the file */ + my_fclose(fff); + + /* Display the file contents */ + show_file(file_name, "Recall Depths", 0, 0); + + /* Remove the file */ + fd_kill(file_name); +} + + +/* + * List known towns + */ +void do_cmd_knowledge_towns(void) +{ + int i, j; + char file_name[1024]; + FILE *fff; + + /* Temporary file */ + if (path_temp(file_name, 1024)) return; + + /* Open a new file */ + fff = my_fopen(file_name, "w"); + + /* Oops */ + if (fff == NULL) return; + + /* Scan all dungeons */ + for (i = 0; i < max_d_idx; i++) + { + dungeon_info_type *d_ptr = &d_info[i]; + + /* Scan all dungeon town slots */ + for (j = 0; j < TOWN_DUNGEON; j++) + { + int town_idx = d_ptr->t_idx[j]; + + /* Ignore non-existent towns */ + if (!(town_info[town_idx].flags & (TOWN_REAL))) continue; + + /* Ignore unknown towns */ + if (!(town_info[town_idx].flags & (TOWN_KNOWN))) continue; + + /* Describe the dungeon town */ + fprintf(fff, " %s: Level %d (%d')\n", + d_name + d_ptr->name, + d_ptr->t_level[j], + 50 * d_ptr->t_level[j]); + } + } + + /* Close the file */ + my_fclose(fff); + + /* Display the file contents */ + show_file(file_name, "Dungeon Towns", 0, 0); + + /* Remove the file */ + fd_kill(file_name); +} + + +/* + * List corruptions + */ +void do_cmd_knowledge_corruptions(void) +{ + FILE *fff; + + char file_name[1024]; + + + /* Temporary file */ + if (path_temp(file_name, 1024)) return; + + /* Open a new file */ + fff = my_fopen(file_name, "w"); + + /* Dump the corruptions to file */ + if (fff) + { + dump_corruptions(fff, TRUE, FALSE); + } + + /* Close the file */ + my_fclose(fff); + + /* Display the file contents */ + show_file(file_name, "Corruptions", 0, 0); + + /* Remove the file */ + fd_kill(file_name); +} + + +/* + * Helper function for do_cmd_knowledge_quests + */ +static void insert_sort_quest(int *order, int *num, int q_idx) +{ + int i, j; + + quest_type *q_ptr = &quest[q_idx]; + + int level = q_ptr->level; + + + /* Find the place */ + for (i = 0; i < *num; i++) + { + quest_type *q2_ptr = &quest[order[i]]; + int level2 = q2_ptr->level; + + if (level < level2) break; + } + + /* Move the remaining items */ + for (j = *num - 1; j >= i; j--) + { + order[j + 1] = order[j]; + } + + /* Insert it */ + order[i] = q_idx; + (*num)++; +} + + +/* + * Print quest status of all active quests + */ +static void do_cmd_knowledge_quests(void) +{ + FILE *fff; + + char file_name[1024]; + + int order[MAX_Q_IDX] = { }; + + int num = 0; + + int i, j, z; + + + /* Temporary file */ + if (path_temp(file_name, 1024)) return; + + /* Open a new file */ + fff = my_fopen(file_name, "w"); + + for (i = 0; i < MAX_Q_IDX; i++) + { + insert_sort_quest(order, &num, i); + } + + for (z = 0; z < MAX_Q_IDX; z++) + { + i = order[z]; + + /* Dynamic descriptions */ + if (quest[i].gen_desc != NULL) + { + if (!quest[i].gen_desc(fff)) + { + continue; + } + } + + /* Fixed quests (only known ones) */ + else if (!quest[i].silent) + { + if (quest[i].status == QUEST_STATUS_TAKEN) + { + /* Print the quest info */ + fprintf(fff, "#####y%s (Danger level: %d)\n", + quest[i].name, quest[i].level); + + j = 0; + while ((j < 10) && (quest[i].desc[j][0] != '\0')) + { + fprintf(fff, "%s\n", quest[i].desc[j++]); + } + fprintf(fff, "\n"); + } + else if (quest[i].status == QUEST_STATUS_COMPLETED) + { + fprintf(fff , "#####G%s Completed - Unrewarded\n", quest[i].name); + fprintf(fff, "\n"); + } + } + } + + /* Close the file */ + my_fclose(fff); + + /* Display the file contents */ + show_file(file_name, "Quest status", 0, 0); + + /* Remove the file */ + fd_kill(file_name); +} + + +/* + * Print fate status + */ +static void do_cmd_knowledge_fates(void) +{ + FILE *fff; + + char file_name[1024]; + + + /* Temporary file */ + if (path_temp(file_name, 1024)) return; + + /* Open a new file */ + fff = my_fopen(file_name, "w"); + + dump_fates(fff); + + /* Close the file */ + my_fclose(fff); + + /* Display the file contents */ + show_file(file_name, "Fate status", 0, 0); + + /* Remove the file */ + fd_kill(file_name); +} + + +/* + * Print the note file + */ +void do_cmd_knowledge_notes(void) +{ + /* Spawn */ + show_notes_file(); + + /* Done */ + return; +} + + +/* + * Interact with "knowledge" + */ +void do_cmd_knowledge(void) +{ + int i; + + + /* File type is "TEXT" */ + FILE_TYPE(FILE_TYPE_TEXT); + + /* Enter "icky" mode */ + character_icky = TRUE; + + /* Save the screen */ + Term_save(); + + /* Interact until done */ + while (1) + { + /* Clear screen */ + Term_clear(); + + /* Ask for a choice */ + prt("Display current knowledge", 2, 0); + + /* Give some choices */ + prt("(1) Display known artifacts", 4, 5); + prt("(2) Display known uniques", 5, 5); + prt("(3) Display known objects", 6, 5); + prt("(4) Display kill count", 7, 5); + prt("(5) Display recall depths", 8, 5); + prt("(6) Display corruptions", 9, 5); + prt("(7) Display current pets", 10, 5); + prt("(8) Display current quests", 11, 5); + prt("(9) Display current fates", 12, 5); + prt("(0) Display known traps", 13, 5); + prt("(A) Display known dungeon towns", 14, 5); + prt("(B) Display notes", 15, 5); + + /* Prompt */ + prt("Command: ", 17, 0); + + /* Prompt */ + i = inkey(); + + /* Done */ + if (i == ESCAPE) break; + + switch (i) + { + /* Artifacts */ + case '1': + { + do_cmd_knowledge_artifacts(); + + break; + } + + /* Uniques */ + case '2': + { + do_cmd_knowledge_uniques(); + + break; + } + + /* Objects */ + case '3': + { + do_cmd_knowledge_objects(); + + break; + } + + /* Kill count */ + case '4': + { + do_cmd_knowledge_kill_count(); + + break; + } + + /* Recall depths */ + case '5': + { + do_cmd_knowledge_dungeons(); + + break; + } + + /* corruptions */ + case '6': + { + do_cmd_knowledge_corruptions(); + + break; + } + + /* Pets */ + case '7': + { + do_cmd_knowledge_pets(); + + break; + } + + /* Quests */ + case '8': + { + do_cmd_knowledge_quests(); + + break; + } + + /* Fates */ + case '9': + { + do_cmd_knowledge_fates(); + + break; + } + + /* Traps */ + case '0': + { + do_cmd_knowledge_traps(); + + break; + } + + /* Dungeon towns */ + case 'A': + case 'a': + { + do_cmd_knowledge_towns(); + + break; + } + + /* Notes */ + case 'B': + case 'b': + { + do_cmd_knowledge_notes(); + + break; + } + + /* Unknown option */ + default: + { + bell(); + + break; + } + } + + /* Flush messages */ + msg_print(NULL); + } + + /* Restore the screen */ + Term_load(); + + /* Leave "icky" mode */ + character_icky = FALSE; +} + + +/* + * Check on the status of an active quest -KMW- + * TODO: Spill out status when not a simple kill # monster. + */ +void do_cmd_checkquest(void) +{ + /* File type is "TEXT" */ + FILE_TYPE(FILE_TYPE_TEXT); + + /* Enter "icky" mode */ + character_icky = TRUE; + + /* Save the screen */ + Term_save(); + + /* Quest info */ + do_cmd_knowledge_quests(); + + /* Restore the screen */ + Term_load(); + + /* Leave "icky" mode */ + character_icky = FALSE; +} + + +/* + * Change player's "tactic" setting + */ +void do_cmd_change_tactic(int i) +{ + p_ptr->tactic += i; + if (p_ptr->tactic > 8) p_ptr->tactic = 0; + if (p_ptr->tactic < 0) p_ptr->tactic = 8; + + p_ptr->update |= (PU_BONUS); + update_stuff(); + prt("", 0, 0); +} + + +/* + * Change player's "movement" setting + */ +void do_cmd_change_movement(int i) +{ + p_ptr->movement += i; + if (p_ptr->movement > 8) p_ptr->movement = 0; + if (p_ptr->movement < 0) p_ptr->movement = 8; + + p_ptr->update |= (PU_BONUS); + update_stuff(); + prt("", 0, 0); +} + + +/* + * Display the time and date + */ +void do_cmd_time() +{ + int day = bst(DAY, turn); + + int hour = bst(HOUR, turn); + + int min = bst(MINUTE, turn); + + int full = hour * 100 + min; + + char buf2[20]; + + int start = 9999; + + int end = -9999; + + int num = 0; + + char desc[1024]; + + char buf[1024]; + + FILE *fff; + + + /* Note */ + strcpy(desc, "It is a strange time."); + + /* Format time of the day */ + strnfmt(buf2, 20, get_day(bst(YEAR, turn) + START_YEAR)); + + /* Display current date in the Elvish calendar */ + msg_format("This is %s of the %s year of the third age.", + get_month_name(day, wizard, FALSE), buf2); + + /* Message */ + msg_format("The time is %d:%02d %s.", + (hour % 12 == 0) ? 12 : (hour % 12), + min, (hour < 12) ? "AM" : "PM"); + + /* Find the path */ + if (!rand_int(10) || p_ptr->image) + { + path_build(buf, 1024, ANGBAND_DIR_FILE, "timefun.txt"); + } + else + { + path_build(buf, 1024, ANGBAND_DIR_FILE, "timenorm.txt"); + } + + /* Open this file */ + fff = my_fopen(buf, "rt"); + + /* Oops */ + if (!fff) return; + + /* Find this time */ + while (!my_fgets(fff, buf, 1024)) + { + /* Ignore comments */ + if (!buf[0] || (buf[0] == '#')) continue; + + /* Ignore invalid lines */ + if (buf[1] != ':') continue; + + /* Process 'Start' */ + if (buf[0] == 'S') + { + /* Extract the starting time */ + start = atoi(buf + 2); + + /* Assume valid for an hour */ + end = start + 59; + + /* Next... */ + continue; + } + + /* Process 'End' */ + if (buf[0] == 'E') + { + /* Extract the ending time */ + end = atoi(buf + 2); + + /* Next... */ + continue; + } + + /* Ignore incorrect range */ + if ((start > full) || (full > end)) continue; + + /* Process 'Description' */ + if (buf[0] == 'D') + { + num++; + + /* Apply the randomizer */ + if (!rand_int(num)) strcpy(desc, buf + 2); + + /* Next... */ + continue; + } + } + + /* Message */ + msg_print(desc); + + /* Close the file */ + my_fclose(fff); +} + +/* + * Macro recorder! + * It records all keypresses and then put them in a macro + * Not as powerful as the macro screen, but much easier for newbies + */ + +std::string *macro_recorder_current = nullptr; + +void macro_recorder_start() +{ + msg_print("Starting macro recording, press this key again to stop. Note that if the action you want to record accepts the @ key, use it; it will remove your the need to inscribe stuff."); + assert (macro_recorder_current == nullptr); + macro_recorder_current = new std::string(); +} + +void macro_recorder_add(char c) +{ + // Gets called unconditionally for all input, so ignore unless + // we're actual recording. + if (macro_recorder_current) { + macro_recorder_current->push_back(c); + } +} + +void macro_recorder_stop() +{ + assert(macro_recorder_current != nullptr); + + // Remove the last key, because it is the key to stop recording + macro_recorder_current->pop_back(); + + // Copy out current macro text. + std::string macro(*macro_recorder_current); + + // Stop recording. + delete macro_recorder_current; + macro_recorder_current = nullptr; + + /* Add it */ + if (get_check("Are you satisfied and want to create the macro? ")) + { + char buf[1024]; + + prt("Trigger: ", 0, 0); + + /* Get a macro trigger */ + do_cmd_macro_aux(buf, FALSE); + + /* Link the macro */ + macro_add(buf, macro.c_str()); + + /* Prompt */ + std::unique_ptr str(new char[(macro.length() + 1) * 3]); + str[0] = '\0'; + ascii_to_text(str.get(), macro.c_str()); + msg_format("Added a macro '%s'. If you want it to stay permanently, press @ now and dump macros to a file.", str.get()); + } +} + +void do_cmd_macro_recorder() +{ + if (macro_recorder_current == NULL) + macro_recorder_start(); + else + macro_recorder_stop(); +} diff --git a/src/cmd5.c b/src/cmd5.c deleted file mode 100644 index 95ae0346..00000000 --- a/src/cmd5.c +++ /dev/null @@ -1,2471 +0,0 @@ -/* File: cmd5.c */ - -/* Purpose: Class commands */ - -/* - * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke - * - * This software may be copied and distributed for educational, research, and - * not for profit purposes provided that this copyright and statement are - * included in all such copies. - */ - - -#include "angband.h" - -#include - -#include "spell_type.h" -#include "quark.h" - -/* Maximum number of tries for teleporting */ -#define MAX_TRIES 300 - -bool_ is_school_book(object_type *o_ptr) -{ - if (o_ptr->tval == TV_BOOK) - { - return TRUE; - } - else if (o_ptr->tval == TV_DAEMON_BOOK) - { - return TRUE; - } - else if (o_ptr->tval == TV_INSTRUMENT) - { - return TRUE; - } - else - { - return FALSE; - } -} - -/* Does it contains a schooled spell ? */ -static bool_ hook_school_spellable(object_type *o_ptr) -{ - if (is_school_book(o_ptr)) - return TRUE; - else - { - u32b f1, f2, f3, f4, f5, esp; - - /* Extract object flags */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - if ((f5 & TR5_SPELL_CONTAIN) && (o_ptr->pval2 != -1)) - return TRUE; - } - return FALSE; -} - -/* Is it a book */ -bool_ item_tester_hook_browsable(object_type *o_ptr) -{ - if (hook_school_spellable(o_ptr)) return TRUE; - if (o_ptr->tval >= TV_BOOK) return TRUE; - return FALSE; -} - -/* - * Are we using a mage staff - */ -bool_ is_magestaff() -{ - int i; - - - i = 0; - - while (p_ptr->body_parts[i] == INVEN_WIELD) - { - object_type *o_ptr = &p_ptr->inventory[INVEN_WIELD + i]; - - /* Wielding a mage staff */ - if ((o_ptr->k_idx) && (o_ptr->tval == TV_MSTAFF)) return (TRUE); - - /* Next slot */ - i++; - - /* Paranoia */ - if (i >= (INVEN_TOTAL - INVEN_WIELD)) break; - } - - /* Not wielding a mage staff */ - return (FALSE); -} - -/* - * Peruse the spells/prayers in a book - * - * Note that *all* spells in the book are listed - * - * Note that browsing is allowed while confused or blind, - * and in the dark, primarily to allow browsing in stores. - */ - -extern void do_cmd_browse_aux(object_type *o_ptr) -{ - u32b f1, f2, f3, f4, f5, esp; - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - if (is_school_book(o_ptr)) - browse_school_spell(o_ptr->sval, o_ptr->pval, o_ptr); - else if (f5 & TR5_SPELL_CONTAIN && o_ptr->pval2 != -1) - browse_school_spell(255, o_ptr->pval2, o_ptr); -} - -void do_cmd_browse(void) -{ - int item; - - cptr q, s; - - object_type *o_ptr; - - /* Restrict choices to "useful" books */ - item_tester_hook = item_tester_hook_browsable; - - /* Get an item */ - q = "Browse which book? "; - s = "You have no books that you can read."; - if (!get_item(&item, q, s, (USE_INVEN | USE_EQUIP | USE_FLOOR))) return; - - /* Get the item */ - o_ptr = get_object(item); - - do_cmd_browse_aux(o_ptr); -} - -void do_poly_wounds(void) -{ - /* Changed to always provide at least _some_ healing */ - s16b wounds = p_ptr->cut; - - s16b hit_p = (p_ptr->mhp - p_ptr->chp); - - s16b change = damroll(p_ptr->lev, 5); - - bool_ Nasty_effect = (randint(5) == 1); - - - if (!(wounds || hit_p || Nasty_effect)) return; - - msg_print("Your wounds are polymorphed into less serious ones."); - hp_player(change); - if (Nasty_effect) - { - msg_print("A new wound was created!"); - take_hit(change / 2, "a polymorphed wound"); - set_cut(change); - } - else - { - set_cut((p_ptr->cut) - (change / 2)); - } -} - -void do_poly_self(void) -{ - int power = p_ptr->lev; - int poly_power; - - msg_print("You feel a change coming over you..."); - - if ((power > rand_int(20)) && (rand_int(3) == 0)) - { - char effect_msg[80] = ""; - int new_race, expfact, goalexpfact; - - /* Some form of racial polymorph... */ - power -= 10; - - if ((power > rand_int(5)) && (rand_int(4) == 0)) - { - /* sex change */ - power -= 2; - - if (p_ptr->psex == SEX_MALE) - { - p_ptr->psex = SEX_FEMALE; - sp_ptr = &sex_info[p_ptr->psex]; - strcpy(effect_msg, "female"); - } - else - { - p_ptr->psex = SEX_MALE; - sp_ptr = &sex_info[p_ptr->psex]; - strcpy(effect_msg, "male"); - } - } - - if ((power > rand_int(30)) && (rand_int(5) == 0)) - { - int tmp = 0; - - /* Harmful deformity */ - power -= 15; - - while (tmp < 6) - { - if ( rand_int(2) == 0) - { - (void)dec_stat(tmp, randint(6) + 6, (rand_int(3) == 0)); - power -= 1; - } - tmp++; - } - - /* Deformities are discriminated against! */ - (void)dec_stat(A_CHR, randint(6), TRUE); - - if (effect_msg[0]) - { - char tmp_msg[10]; - strnfmt(tmp_msg, 10, "%s", effect_msg); - strnfmt(effect_msg, 80, "deformed %s", tmp_msg); - } - else - { - strcpy(effect_msg, "deformed"); - } - } - - while ((power > rand_int(20)) && (rand_int(10) == 0)) - { - /* Polymorph into a less corrupted form */ - power -= 10; - - lose_corruption(); - } - - /* - * I'm not sure 'power' is always positive, with *so* many minuses. - * Also, passing zero / negative numbers to randint/rand_int can - * cause a zero divide exception, IIRC, not to speak of its absurdity - * -- pelpel - */ - poly_power = (power > 1) ? power : 1; - - /* - * Restrict the race choices by exp penalty so weak polymorph - * always means weak race - */ - goalexpfact = 100 + 3 * rand_int(poly_power); - - /* Roll until an appropriate selection is made */ - while (1) - { - new_race = rand_int(max_rp_idx); - expfact = race_info[new_race].r_exp; - - if ((new_race != p_ptr->prace) && (expfact <= goalexpfact)) break; - } - - if (effect_msg[0]) - { - msg_format("You turn into a%s %s!", - ((is_a_vowel(rp_name[race_info[new_race].title])) ? "n" : ""), - race_info[new_race].title + rp_name); - } - else - { - msg_format("You turn into a %s %s!", effect_msg, - race_info[new_race].title); - } - - p_ptr->prace = new_race; - rp_ptr = &race_info[p_ptr->prace]; - - /* Experience factor */ - p_ptr->expfact = rp_ptr->r_exp + rmp_ptr->r_exp + cp_ptr->c_exp; - - /* Calculate the height/weight */ - get_height_weight(); - - - check_experience(); - p_ptr->max_plv = p_ptr->lev; - - p_ptr->redraw |= (PR_BASIC); - - p_ptr->update |= (PU_BONUS); - - handle_stuff(); - lite_spot(p_ptr->py, p_ptr->px); - } - - if ((power > rand_int(30)) && (rand_int(6) == 0)) - { - int tmp = 0; - - /* Abomination! */ - power -= 20; - - msg_print("Your internal organs are rearranged!"); - while (tmp < 6) - { - (void)dec_stat(tmp, randint(6) + 6, (rand_int(3) == 0)); - tmp++; - } - if (rand_int(6) == 0) - { - msg_print("You find living difficult in your present form!"); - take_hit(damroll(randint(10), p_ptr->lev), "a lethal corruption"); - power -= 10; - } - } - - if ((power > rand_int(20)) && (rand_int(4) == 0)) - { - power -= 10; - - do_cmd_rerate(); - } - - while ((power > rand_int(15)) && (rand_int(3) == 0)) - { - power -= 7; - gain_random_corruption(); - } - - if (power > rand_int(5)) - { - power -= 5; - do_poly_wounds(); - } - - /* Note: earlier deductions may have left power < 0 already. */ - while (power > 0) - { - corrupt_player(); - power--; - } -} - - -/* - * Brand the current weapon - */ -void brand_weapon(int brand_type) -{ - object_type *o_ptr; - - cptr act = NULL; - - char o_name[80]; - - - o_ptr = &p_ptr->inventory[INVEN_WIELD]; - - /* - * You can never modify artifacts / ego-items - * You can never modify cursed items - * - * TY: You _can_ modify broken items (if you're silly enough) - */ - if (!o_ptr->k_idx || artifact_p(o_ptr) || ego_item_p(o_ptr) || - o_ptr->art_name || cursed_p(o_ptr)) - { - if (flush_failure) flush(); - - msg_print("The Branding failed."); - - return; - } - - - /* Save the old name */ - object_desc(o_name, o_ptr, FALSE, 0); - - switch (brand_type) - { - case 6: - { - act = "glows with godly power."; - o_ptr->name2 = EGO_BLESS_BLADE; - o_ptr->pval = randint(4); - - break; - } - case 5: - { - act = "seems very powerful."; - o_ptr->name2 = EGO_EARTHQUAKES; - o_ptr->pval = randint(3); - - break; - } - case 4: - { - act = "seems very unstable now."; - o_ptr->name2 = EGO_DRAGON; - o_ptr->pval = randint(2); - - break; - } - case 3: - { - act = "thirsts for blood!"; - o_ptr->name2 = EGO_VAMPIRIC; - - break; - } - case 2: - { - act = "is coated with poison."; - o_ptr->name2 = EGO_BRAND_POIS; - - break; - } - case 1: - { - act = "is engulfed in raw chaos!"; - o_ptr->name2 = EGO_CHAOTIC; - - break; - } - default: - { - if (rand_int(100) < 25) - { - act = "is covered in a fiery shield!"; - o_ptr->name2 = EGO_BRAND_FIRE; - } - else - { - act = "glows deep, icy blue!"; - o_ptr->name2 = EGO_BRAND_COLD; - } - } - } - - /* Apply the ego */ - apply_magic(o_ptr, dun_level, FALSE, FALSE, FALSE); - o_ptr->discount = 100; - - msg_format("Your %s %s", o_name, act); - - enchant(o_ptr, rand_int(3) + 4, ENCH_TOHIT | ENCH_TODAM); -} - -/* - * Fetch an item (teleport it right underneath the caster) - */ -void fetch(int dir, int wgt, bool_ require_los) -{ - int ty, tx, i; - - cave_type *c_ptr; - - object_type *o_ptr; - - char o_name[80]; - - - /* Check to see if an object is already there */ - if (cave[p_ptr->py][p_ptr->px].o_idx) - { - msg_print("You can't fetch when you're already standing on something."); - return; - } - - /* Use a target */ - if ((dir == 5) && target_okay()) - { - tx = target_col; - ty = target_row; - - if (distance(p_ptr->py, p_ptr->px, ty, tx) > MAX_RANGE) - { - msg_print("You can't fetch something that far away!"); - return; - } - - c_ptr = &cave[ty][tx]; - - if (!c_ptr->o_idx) - { - msg_print("There is no object at this place."); - return; - } - - if (require_los && (!player_has_los_bold(ty, tx))) - { - msg_print("You have no direct line of sight to that location."); - return; - } - } - else - { - /* Use a direction */ - ty = p_ptr->py; /* Where to drop the item */ - tx = p_ptr->px; - - while (1) - { - ty += ddy[dir]; - tx += ddx[dir]; - c_ptr = &cave[ty][tx]; - - if ((distance(p_ptr->py, p_ptr->px, ty, tx) > MAX_RANGE) || - !cave_floor_bold(ty, tx)) return; - - if (c_ptr->o_idx) break; - } - } - - o_ptr = &o_list[c_ptr->o_idx]; - - if (o_ptr->weight > wgt) - { - /* Too heavy to 'fetch' */ - msg_print("The object is too heavy."); - return; - } - - i = c_ptr->o_idx; - c_ptr->o_idx = o_ptr->next_o_idx; - cave[p_ptr->py][p_ptr->px].o_idx = i; /* 'move' it */ - o_ptr->next_o_idx = 0; - o_ptr->iy = p_ptr->py; - o_ptr->ix = p_ptr->px; - - object_desc(o_name, o_ptr, TRUE, 0); - msg_format("%^s flies through the air to your feet.", o_name); - - note_spot(p_ptr->py, p_ptr->px); - p_ptr->redraw |= PR_MAP; -} - - -/* - * Handle random effects of player shrieking - */ -void shriek_effect() -{ - switch (randint(9)) - { - case 1: - case 5: - case 8: - case 9: - { - msg_print("You make a high-pitched shriek!"); - aggravate_monsters(1); - - break; - } - case 2: - case 6: - { - msg_print("Oops! You call a monster."); - summon_specific(p_ptr->py, p_ptr->px, max_dlv[dungeon_type], 0); - - break; - } - case 3: - case 7: - { - msg_print("The dungeon collapses!"); - earthquake(p_ptr->py, p_ptr->px, 5); - - break; - } - case 4: - { - msg_print("Your shriek is so horrible that you damage your health!"); - take_hit(damroll(p_ptr->lev / 5, 8), "inner hemorrhaging"); - - break; - } - } -} - - -/* - * Like all the random effect codes, this is *ugly*, - * and there is not a single line of comment, so I can't tell - * some fall throughs are really intended. Well, I know it's - * intended to be bizarre :) -- pelpel - */ -void wild_magic(int spell) -{ - int counter = 0; - int type = SUMMON_BIZARRE1 - 1 + randint(6); - - if (type < SUMMON_BIZARRE1) type = SUMMON_BIZARRE1; - else if (type > SUMMON_BIZARRE6) type = SUMMON_BIZARRE6; - - switch (randint(spell) + randint(8) + 1) - { - case 1: - case 2: - case 3: - { - teleport_player(10); - - break; - } - - case 4: - case 5: - case 6: - { - teleport_player(100); - - break; - } - - case 7: - case 8: - { - teleport_player(200); - - break; - } - - case 9: - case 10: - case 11: - { - unlite_area(10, 3); - - break; - } - - case 12: - case 13: - case 14: - { - lite_area(damroll(2, 3), 2); - - break; - } - - case 15: - { - destroy_doors_touch(); - - break; - } - - case 16: - case 17: - { - wall_breaker(); - - /* I don't think this is a fall through -- pelpel */ - break; - } - - case 18: - { - sleep_monsters_touch(); - - break; - } - - case 19: - case 20: - { - trap_creation(); - - break; - } - - case 21: - case 22: - { - door_creation(); - - break; - } - - case 23: - case 24: - case 25: - { - aggravate_monsters(1); - - break; - } - - case 26: - { - /* Prevent destruction of quest levels and town */ - if (!is_quest(dun_level) && dun_level) - earthquake(p_ptr->py, p_ptr->px, 5); - - break; - } - - case 27: - case 28: - { - break; - } - - case 29: - case 30: - { - apply_disenchant(0); - - break; - } - - case 31: - { - lose_all_info(); - - break; - } - - case 32: - { - fire_ball(GF_CHAOS, 0, spell + 5, 1 + (spell / 10)); - - break; - } - - case 33: - { - wall_stone(p_ptr->py, p_ptr->px); - - break; - } - - case 34: - case 35: - { - while (counter++ < 8) - { - (void) summon_specific(p_ptr->py, p_ptr->px, (dun_level * 3) / 2, type); - } - - break; - } - - case 36: - case 37: - { - activate_hi_summon(); - - break; - } - - case 38: - { - summon_cyber(); - - /* I don't think this is a fall through -- pelpel */ - break; - } - - default: - { - activate_ty_curse(); - } - } - - return; -} - - -/* - * Hack -- Determine if the player is wearing an artefact ring - * specified by art_type, that should be an index into a_info - */ -bool_ check_ring(int art_type) -{ - int i; - - - /* We are only interested in ring slots */ - i = INVEN_RING; - - /* Scan the list of rings until we reach the end */ - while (p_ptr->body_parts[i - INVEN_WIELD] == INVEN_RING) - { - /* Found the ring we were looking for */ - if (p_ptr->inventory[i].k_idx && (p_ptr->inventory[i].name1 == art_type)) - { - return (TRUE); - } - - /* Next item */ - i++; - } - - /* Found nothing */ - return (FALSE); -} - -/* - * Return the symbiote's name or description. - */ -cptr symbiote_name(bool_ capitalize) -{ - object_type *o_ptr = &p_ptr->inventory[INVEN_CARRY]; - static char buf[80]; - - /* Make sure there actually is a symbiote there... */ - if (!o_ptr->k_idx) - { - strcpy(buf, "A non-existent symbiote"); - } - else - { - monster_race *r_ptr = &r_info[o_ptr->pval]; - cptr s = NULL; - - if (r_ptr->flags1 & RF1_UNIQUE) - { - /* Unique monster; no preceding "your", and ignore our name. */ - strncpy(buf, r_name + r_ptr->name, sizeof(buf)); - } - else if (o_ptr->note && - (s = strstr(quark_str(o_ptr->note), "#named ")) != NULL) - { - /* We've named it. */ - strncpy(buf, s + 7, sizeof(buf)); - } - else - { - /* No special cases, just return "Your ". */ - strcpy(buf, "your "); - strncpy(buf + 5, r_name + r_ptr->name, sizeof(buf) - 5); - } - } - - /* Just in case... */ - buf[sizeof(buf) - 1] = '\0'; - if (capitalize) buf[0] = toupper(buf[0]); - return buf; -} - -/* - * Use a power of the monster in symbiosis - */ -int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost) -{ - int power = -1; - - int num = 0, dir = 0 , i; - - int powers[96]; - - bool_ flag; - - int ask, plev = p_ptr->lev; - - char choice; - - char out_val[160]; - - monster_race *r_ptr = &r_info[r_idx]; - - int rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1); - - int x = p_ptr->px, y = p_ptr->py, k; - - int rad; - - int label; - - - /* List the monster powers -- RF4_* */ - for (i = 0; i < 32; i++) - { - if (r_ptr->flags4 & BIT(i)) - { - if (monster_powers[i].great && (!great)) continue; - if (!monster_powers[i].power) continue; - powers[num++] = i; - } - } - - /* List the monster powers -- RF5_* */ - for (i = 0; i < 32; i++) - { - if (r_ptr->flags5 & BIT(i)) - { - if (monster_powers[i + 32].great && (!great)) continue; - if (!monster_powers[i + 32].power) continue; - powers[num++] = i + 32; - } - } - - /* List the monster powers -- RF6_* */ - for (i = 0; i < 32; i++) - { - if (r_ptr->flags6 & BIT(i)) - { - if (monster_powers[i + 64].great && (!great)) continue; - if (!monster_powers[i + 64].power) continue; - powers[num++] = i + 64; - } - } - - if (!num) - { - msg_print("You have no powers you can use."); - return (0); - } - - if (only_number) return (num); - - /* Nothing chosen yet */ - flag = FALSE; - - /* Get the last label */ - label = (num <= 26) ? I2A(num - 1) : I2D(num - 1 - 26); - - /* Build a prompt (accept all spells) */ - /* Mega Hack -- if no_cost is false, we're actually a Possessor -dsb */ - strnfmt(out_val, 78, - "(Powers a-%c, ESC=exit) Use which power of your %s? ", - label, (no_cost ? "symbiote" : "body")); - - /* Save the screen */ - character_icky = TRUE; - Term_save(); - - /* Get a spell from the user */ - while (!flag) - { - /* Show the list */ - { - byte y = 1, x = 0; - int ctr = 0; - char dummy[80]; - - strcpy(dummy, ""); - - prt ("", y++, x); - - while (ctr < num) - { - monster_power *mp_ptr = &monster_powers[powers[ctr]]; - int mana = mp_ptr->mana / 10; - - if (mana > p_ptr->msp) mana = p_ptr->msp; - - if (!mana) mana = 1; - - label = (ctr < 26) ? I2A(ctr) : I2D(ctr - 26); - - if (!no_cost) - { - strnfmt(dummy, 80, " %c) %2d %s", - label, mana, mp_ptr->name); - } - else - { - strnfmt(dummy, 80, " %c) %s", - label, mp_ptr->name); - } - - if (ctr < 17) - { - prt(dummy, y + ctr, x); - } - else - { - prt(dummy, y + ctr - 17, x + 40); - } - - ctr++; - } - - if (ctr < 17) - { - prt ("", y + ctr, x); - } - else - { - prt ("", y + 17, x); - } - } - - if (!get_com(out_val, &choice)) - { - flag = FALSE; - break; - } - - if (choice == '\r' && num == 1) - { - choice = 'a'; - } - - if (isalpha(choice)) - { - /* Note verify */ - ask = (isupper(choice)); - - /* Lowercase */ - if (ask) choice = tolower(choice); - - /* Extract request */ - i = (islower(choice) ? A2I(choice) : -1); - } - else - { - /* Can't uppercase digits XXX XXX XXX */ - ask = FALSE; - - i = choice - '0' + 26; - } - - /* Totally Illegal */ - if ((i < 0) || (i >= num)) - { - bell(); - continue; - } - - /* Save the spell index */ - power = powers[i]; - - /* Verify it */ - if (ask) - { - char tmp_val[160]; - - /* Prompt */ - strnfmt(tmp_val, 78, "Use %s? ", monster_powers[power].name); - - /* Belay that order */ - if (!get_check(tmp_val)) continue; - } - - /* Stop the loop */ - flag = TRUE; - } - - /* Restore the screen */ - Term_load(); - character_icky = FALSE; - - /* Abort if needed */ - if (!flag) - { - energy_use = 0; - return -1; - } - - /* 'Powerful' monsters have wider radii */ - if (r_ptr->flags2 & RF2_POWERFUL) - { - rad = 1 + (p_ptr->lev / 15); - } - else - { - rad = 1 + (p_ptr->lev / 20); - } - - - /* Analyse power */ - switch (power) - { - /**** RF4 (bit position) ****/ - - /* SHRIEK */ - case 0: - { - aggravate_monsters( -1); - - break; - } - - /* MULTIPLY */ - case 1: - { - do_cmd_wiz_named_friendly(p_ptr->body_monster, FALSE); - - break; - } - - /* S_ANIMAL */ - case 2: - { - summon_specific_friendly(y, x, rlev, SUMMON_ANIMAL, TRUE); - - break; - } - - /* ROCKET */ - case 3: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_ROCKET, dir, p_ptr->lev * 12, 1 + (p_ptr->lev / 20)); - - break; - } - - /* ARROW_1 */ - case 4: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_ARROW, dir, damroll(1, 6)); - - break; - } - - /* ARROW_2 */ - case 5: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_ARROW, dir, damroll(3, 6)); - - break; - } - - /* ARROW_3 */ - case 6: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_ARROW, dir, damroll(5, 6)); - - break; - } - - /* ARROW_4 */ - case 7: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_ARROW, dir, damroll(7, 6)); - - break; - } - - /* BR_ACID */ - case 8: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_ACID, dir, p_ptr->lev * 5, rad); - - break; - } - - /* BR_ELEC */ - case 9: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_ELEC, dir, p_ptr->lev * 5, rad); - - break; - } - - /* BR_FIRE */ - case 10: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_FIRE, dir, p_ptr->lev * 5, rad); - - break; - } - - /* BR_COLD */ - case 11: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_COLD, dir, p_ptr->lev * 5, rad); - - break; - } - - /* BR_POIS */ - case 12: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_POIS, dir, p_ptr->lev * 5, rad); - - break; - } - - /* BR_NETH */ - case 13: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_NETHER, dir, p_ptr->lev * 5, rad); - - break; - } - - /* BR_LITE */ - case 14: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_LITE, dir, p_ptr->lev * 8, rad); - - break; - } - - /* BR_DARK */ - case 15: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_DARK, dir, p_ptr->lev * 8, rad); - - break; - } - - /* BR_CONF */ - case 16: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_CONFUSION, dir, p_ptr->lev * 8, rad); - - break; - } - - /* BR_SOUN */ - case 17: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_SOUND, dir, p_ptr->lev * 8, rad); - - break; - } - - /* BR_CHAO */ - case 18: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_CHAOS, dir, p_ptr->lev * 7, rad); - - break; - } - - /* BR_DISE */ - case 19: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_DISENCHANT, dir, p_ptr->lev * 7, rad); - - break; - } - - /* BR_NEXU */ - case 20: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_NEXUS, dir, p_ptr->lev * 5, rad); - - break; - } - - /* BR_TIME */ - case 21: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_TIME, dir, p_ptr->lev * 3, rad); - - break; - } - - /* BR_INER */ - case 22: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_INERTIA, dir, p_ptr->lev * 4, rad); - - break; - } - - /* BR_GRAV */ - case 23: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_GRAVITY, dir, p_ptr->lev * 4, rad); - - break; - } - - /* BR_SHAR */ - case 24: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_SHARDS, dir, p_ptr->lev * 8, rad); - - break; - } - - /* BR_PLAS */ - case 25: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_PLASMA, dir, p_ptr->lev * 3, rad); - - break; - } - - /* BR_WALL */ - case 26: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_FORCE, dir, p_ptr->lev * 4, rad); - - break; - } - - /* BR_MANA */ - case 27: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_MANA, dir, p_ptr->lev * 5, rad); - - break; - } - - /* BA_NUKE */ - case 28: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_NUKE, dir, p_ptr->lev * 8, 1 + (p_ptr->lev / 20)); - - break; - } - - /* BR_NUKE */ - case 29: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_NUKE, dir, p_ptr->lev * 8, 1 + (p_ptr->lev / 20)); - - break; - } - - /* BA_CHAO */ - case 30: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_CHAOS, dir, p_ptr->lev * 4, 2); - - break; - } - - /* BR_DISI */ - case 31: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_DISINTEGRATE, dir, p_ptr->lev * 5, 1 + (p_ptr->lev / 20)); - - break; - } - - - /**** RF5 (bit position + 32) ****/ - - /* BA_ACID */ - case 32: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_ACID, dir, randint(p_ptr->lev * 6) + 20, 2); - - break; - } - - /* BA_ELEC */ - case 33: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_ELEC, dir, randint(p_ptr->lev * 3) + 20, 2); - - break; - } - - /* BA_FIRE */ - case 34: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_FIRE, dir, randint(p_ptr->lev * 7) + 20, 2); - - break; - } - - /* BA_COLD */ - case 35: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_COLD, dir, randint(p_ptr->lev * 3) + 20, 2); - - break; - } - - /* BA_POIS */ - case 36: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_POIS, dir, damroll(12, 2), 2); - - break; - } - - /* BA_NETH */ - case 37: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_NETHER, dir, randint(p_ptr->lev * 4) + 20, 2); - - break; - } - - /* BA_WATE */ - case 38: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_WATER, dir, randint(p_ptr->lev * 4) + 20, 2); - - break; - } - - /* BA_MANA */ - case 39: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_MANA, dir, randint(p_ptr->lev * 3) + 20, 2); - - break; - } - - /* BA_DARK */ - case 40: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_DARK, dir, randint(p_ptr->lev * 3) + 20, 2); - - break; - } - - /* 41 DRAIN_MANA -- Not available */ - - /* 42 MIND_BLAST -- Not available */ - - /* 43 BRAIN_SMASH -- Not available */ - - /* CAUSE_1 */ - case 44: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_MANA, dir, damroll(3, 8)); - - break; - } - - /* CAUSE_2 */ - case 45: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_MANA, dir, damroll(8, 8)); - - break; - } - - /* CAUSE_3 */ - case 46: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_MANA, dir, damroll(10, 15)); - - break; - } - - /* CAUSE_4 */ - case 47: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_MANA, dir, damroll(15, 15)); - - break; - } - - /* BO_ACID */ - case 48: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_ACID, dir, damroll(7, 8) + (p_ptr->lev / 3)); - - break; - } - - /* BO_ELEC */ - case 49: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_ELEC, dir, damroll(4, 8) + (p_ptr->lev / 3)); - - break; - } - - /* BO_FIRE */ - case 50: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_FIRE, dir, damroll(9, 8) + (p_ptr->lev / 3)); - - break; - } - - /* BO_COLD */ - case 51: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_COLD, dir, damroll(6, 8) + (p_ptr->lev / 3)); - - break; - } - - /* BO_POIS */ - case 52: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_POIS, dir, damroll(7, 8) + (p_ptr->lev / 3)); - - break; - } - - /* BO_NETH */ - case 53: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_NETHER, dir, damroll(5, 5) + (p_ptr->lev / 3)); - - break; - } - - /* BO_WATE */ - case 54: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_WATER, dir, damroll(10, 10) + (p_ptr->lev / 3)); - - break; - } - - /* BO_MANA */ - case 55: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_MANA, dir, damroll(3, 8) + (p_ptr->lev / 3)); - - break; - } - - /* BO_PLAS */ - case 56: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_PLASMA, dir, damroll(8, 8) + (p_ptr->lev / 3)); - - break; - } - - /* BO_ICEE */ - case 57: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_ICE, dir, damroll(6, 6) + (p_ptr->lev / 3)); - - break; - } - - /* MISSILE */ - case 58: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_MISSILE, dir, damroll(2, 6) + (p_ptr->lev / 3)); - - break; - } - - /* SCARE */ - case 59: - { - if (!get_aim_dir(&dir)) break; - - fear_monster(dir, plev); - - break; - } - - /* BLIND */ - case 60: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_CONFUSION, dir, damroll(1, 8) + (p_ptr->lev / 3)); - - break; - } - - /* CONF */ - case 61: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_CONFUSION, dir, damroll(7, 8) + (p_ptr->lev / 3)); - - break; - } - - /* SLOW */ - case 62: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_OLD_SLOW, dir, damroll(6, 8) + (p_ptr->lev / 3)); - - break; - } - - /* HOLD */ - case 63: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_OLD_SLEEP, dir, damroll(5, 8) + (p_ptr->lev / 3)); - - break; - } - - - /**** RF6 (bit position + 64) ****/ - - /* HASTE */ - case 64: - { - if (!p_ptr->fast) - { - (void)set_fast(randint(20 + (plev) ) + plev, 10); - } - else - { - (void)set_fast(p_ptr->fast + randint(5), 10); - } - - break; - } - - /* HAND_DOOM */ - case 65: - { - if (!get_aim_dir(&dir)) break; - - fire_bolt(GF_MANA, dir, damroll(10, 8) + (p_ptr->lev)); - - break; - } - - /* HEAL */ - case 66: - { - hp_player(damroll(8, 5)); - - break; - } - - /* S_ANIMALS */ - case 67: - { - for (k = 0; k < 4; k++) - { - summon_specific_friendly(y, x, rlev, SUMMON_ANIMAL, TRUE); - } - - break; - } - - /* BLINK */ - case 68: - { - if (dungeon_flags2 & DF2_NO_TELEPORT) - { - msg_print("No teleport on special levels..."); - break; - } - - teleport_player(10); - - break; - } - - /* TPORT */ - case 69: - { - if (dungeon_flags2 & DF2_NO_TELEPORT) - { - msg_print("No teleport on special levels..."); - break; - } - - teleport_player(plev * 5); - - break; - } - - /* TELE_TO */ - case 70: - { - int ii, ij; - - if (dungeon_flags2 & DF2_NO_TELEPORT) - { - msg_print("No teleport on special levels..."); - break; - } - - msg_print("You go between."); - - if (!tgt_pt(&ii, &ij)) break; - - p_ptr->energy -= 60 - plev; - - if (!cave_empty_bold(ij, ii) || - (cave[ij][ii].info & CAVE_ICKY) || - (distance(ij, ii, p_ptr->py, p_ptr->px) > plev * 20 + 2)) - { - msg_print("You fail to show the destination correctly!"); - p_ptr->energy -= 100; - teleport_player(10); - } - else teleport_player_to(ij, ii); - - break; - } - - /* TELE_AWAY */ - case 71: - { - if (dungeon_flags2 & DF2_NO_TELEPORT) - { - msg_print("No teleport on special levels..."); - break; - } - - if (!get_aim_dir(&dir)) break; - - (void)fire_beam(GF_AWAY_ALL, dir, plev); - - break; - } - - /* TELE_LEVEL */ - case 72: - { - if (dungeon_flags2 & DF2_NO_TELEPORT) - { - msg_print("No teleport on special levels..."); - break; - } - - teleport_player_level(); - - break; - } - - /* DARKNESS */ - case 73: - { - (void)project( -1, 3, p_ptr->py, p_ptr->px, 0, GF_DARK_WEAK, - PROJECT_GRID | PROJECT_KILL); - - /* Unlite the room */ - unlite_room(p_ptr->py, p_ptr->px); - - break; - } - - /* TRAPS */ - case 74: - { - trap_creation(); - - break; - } - - /* 75 FORGET -- Not available */ - - /* ANIM_DEAD -- Use the same code as the nether spell */ - case 76: - { - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_RAISE, dir, 1, 0); - - break; - } - - /* 77 S_BUG -- Not available, well we do that anyway ;) */ - - /* 78 S_RNG -- Not available, who dares? */ - - /* S_THUNDERLORD */ - case 79: - { - for (k = 0; k < 1; k++) - { - summon_specific_friendly(y, x, rlev, SUMMON_THUNDERLORD, TRUE); - } - - break; - } - - /* S_KIN -- Summon Kin, because we code bugs :) */ - case 80: - { - /* Big hack */ - summon_kin_type = r_ptr->d_char; - - for (k = 0; k < 6; k++) - { - summon_specific_friendly(y, x, rlev, SUMMON_KIN, TRUE); - } - - break; - } - - /* S_HI_DEMON */ - case 81: - { - for (k = 0; k < 1; k++) - { - summon_specific_friendly(y, x, rlev, SUMMON_HI_DEMON, TRUE); - } - - break; - } - - /* S_MONSTER */ - case 82: - { - for (k = 0; k < 1; k++) - { - summon_specific_friendly(y, x, rlev, 0, TRUE); - } - - break; - } - - /* S_MONSTERS */ - case 83: - { - for (k = 0; k < 6; k++) - { - summon_specific_friendly(y, x, rlev, 0, TRUE); - } - - break; - } - - /* S_ANT */ - case 84: - { - for (k = 0; k < 6; k++) - { - summon_specific_friendly(y, x, rlev, SUMMON_ANT, TRUE); - } - - break; - } - - /* S_SPIDER */ - case 85: - { - for (k = 0; k < 6; k++) - { - summon_specific_friendly(y, x, rlev, SUMMON_SPIDER, TRUE); - } - - break; - } - - /* S_HOUND */ - case 86: - { - for (k = 0; k < 6; k++) - { - summon_specific_friendly(y, x, rlev, SUMMON_HOUND, TRUE); - } - - break; - } - - /* S_HYDRA */ - case 87: - { - for (k = 0; k < 6; k++) - { - summon_specific_friendly(y, x, rlev, SUMMON_HYDRA, TRUE); - } - - break; - } - - /* S_ANGEL */ - case 88: - { - for (k = 0; k < 1; k++) - { - summon_specific_friendly(y, x, rlev, SUMMON_ANGEL, TRUE); - } - - break; - } - - /* S_DEMON */ - case 89: - { - for (k = 0; k < 1; k++) - { - summon_specific_friendly(y, x, rlev, SUMMON_DEMON, TRUE); - } - - break; - } - - /* S_UNDEAD */ - case 90: - { - for (k = 0; k < 1; k++) - { - summon_specific_friendly(y, x, rlev, SUMMON_UNDEAD, TRUE); - } - - break; - } - - /* S_DRAGON */ - case 91: - { - for (k = 0; k < 1; k++) - { - summon_specific_friendly(y, x, rlev, SUMMON_DRAGON, TRUE); - } - - break; - } - - /* S_HI_UNDEAD */ - case 92: - { - for (k = 0; k < 8; k++) - { - summon_specific_friendly(y, x, rlev, SUMMON_HI_UNDEAD_NO_UNIQUES, TRUE); - } - - break; - } - - /* S_HI_DRAGON */ - case 93: - { - for (k = 0; k < 8; k++) - { - summon_specific_friendly(y, x, rlev, SUMMON_HI_DRAGON_NO_UNIQUES, TRUE); - } - - break; - } - - /* S_WRAITH */ - case 94: - { - for (k = 0; k < 8; k++) - { - summon_specific_friendly(y, x, rlev, SUMMON_WRAITH, TRUE); - } - - break; - } - - /* 95 S_UNIQUE -- Not available */ - } - - /* Take some SP */ - if (!no_cost) - { - int chance, pchance; - - chance = (monster_powers[power].mana + r_ptr->level); - pchance = adj_str_wgt[p_ptr->stat_ind[A_WIS]] / 2 + get_skill(SKILL_POSSESSION); - - if (rand_int(chance) >= pchance) - { - int m = monster_powers[power].mana / 10; - - if (m > p_ptr->msp) m = p_ptr->msp; - if (!m) m = 1; - - p_ptr->csp -= m; - } - } - - /* Redraw mana */ - p_ptr->redraw |= (PR_MANA); - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - - return (num); -} - -/* - * Schooled magic - */ - -/* - * Find a spell in any books/objects - */ -static int hack_force_spell = -1; -static object_type *hack_force_spell_obj = NULL; -bool_ get_item_hook_find_spell(int *item) -{ - int i, spell; - char buf[80]; - - strcpy(buf, "Manathrust"); - if (!get_string("Spell name? ", buf, 79)) - return FALSE; - - spell = find_spell(buf); - if (spell == -1) return FALSE; - - for (i = 0; i < INVEN_TOTAL; i++) - { - object_type *o_ptr = &p_ptr->inventory[i]; - u32b f1, f2, f3, f4, f5, esp; - - /* Must we wield it ? */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - if ((wield_slot(o_ptr) != -1) && (i < INVEN_WIELD) && (f5 & TR5_WIELD_CAST)) continue; - - /* Is it a non-book? */ - if (!is_school_book(o_ptr)) - { - u32b f1, f2, f3, f4, f5, esp; - - /* Extract object flags */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - if ((f5 & TR5_SPELL_CONTAIN) && (o_ptr->pval2 == spell)) - { - *item = i; - hack_force_spell = spell; - hack_force_spell_obj = o_ptr; - return TRUE; - } - } - /* A random book ? */ - else if (school_book_contains_spell(o_ptr->sval, spell)) - { - *item = i; - hack_force_spell = spell; - hack_force_spell_obj = o_ptr; - return TRUE; - } - } - return FALSE; -} - -/* - * Is the spell castable? - */ -bool_ is_ok_spell(s32b spell_idx, object_type *o_ptr) -{ - spell_type *spell = spell_at(spell_idx); - assert(o_ptr != NULL); - - if (get_level(spell_idx, 50, 0) == 0) - { - return FALSE; - } - - if (o_ptr->pval < spell_type_minimum_pval(spell)) - { - return FALSE; - } - - return TRUE; -} - - -/* - * Get a spell from a book - */ -s32b get_school_spell(cptr do_what, s16b force_book) -{ - int i, item; - s32b spell = -1; - int num = 0; - s32b where = 1; - int ask; - bool_ flag; - char out_val[160]; - char buf2[40]; - char buf3[40]; - object_type *o_ptr, forge; - int tmp; - int sval, pval; - u32b f1, f2, f3, f4, f5, esp; - - hack_force_spell = -1; - hack_force_spell_obj = NULL; - - /* Ok do we need to ask for a book ? */ - if (!force_book) - { - get_item_extra_hook = get_item_hook_find_spell; - item_tester_hook = hook_school_spellable; - sprintf(buf2, "You have no book to %s from", do_what); - sprintf(buf3, "%s from which book?", do_what); - if (!get_item(&item, buf3, buf2, USE_INVEN | USE_EQUIP | USE_EXTRA )) return -1; - - /* Get the item */ - o_ptr = get_object(item); - - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* If it can be wielded, it must */ - if ((wield_slot(o_ptr) != -1) && (item < INVEN_WIELD) && (f5 & TR5_WIELD_CAST)) - { - msg_format("You cannot %s from that object; it must be wielded first.", do_what); - return -1; - } - } - else - { - o_ptr = &forge; - o_ptr->tval = TV_BOOK; - o_ptr->sval = force_book; - o_ptr->pval = 0; - } - - if (repeat_pull(&tmp)) - { - return tmp; - } - - /* Nothing chosen yet */ - flag = FALSE; - - /* Show choices */ - window_stuff(); - - /* No spell to cast by default */ - spell = -1; - - /* Is it a random book, or something else ? */ - if (is_school_book(o_ptr)) - { - sval = o_ptr->sval; - pval = o_ptr->pval; - } - else - { - sval = 255; - pval = o_ptr->pval2; - } - - /* Save the screen */ - character_icky = TRUE; - Term_save(); - - /* Go */ - if (hack_force_spell == -1) - { - num = school_book_length(sval); - - /* Build a prompt (accept all spells) */ - strnfmt(out_val, 78, "(Spells %c-%c, Descs %c-%c, ESC=exit) %^s which spell? ", - I2A(0), I2A(num - 1), I2A(0) - 'a' + 'A', I2A(num - 1) - 'a' + 'A', do_what); - - /* Get a spell from the user */ - while (!flag) - { - char choice; - - /* Restore and save screen; this prevents - subprompt from leaving garbage when going - around the loop multiple times. */ - Term_load(); - Term_save(); - - /* Display a list of spells */ - where = print_book(sval, pval, o_ptr); - - /* Input */ - if (!get_com(out_val, &choice)) - { - flag = FALSE; - break; - } - - /* Note verify */ - ask = (isupper(choice)); - - /* Lowercase */ - if (ask) choice = tolower(choice); - - /* Extract request */ - i = (islower(choice) ? A2I(choice) : -1); - - /* Totally Illegal */ - if ((i < 0) || (i >= num)) - { - bell(); - continue; - } - - /* Verify it */ - if (ask) - { - /* Display a list of spells */ - where = print_book(sval, pval, o_ptr); - print_spell_desc(spell_x(sval, pval, i), where); - } - else - { - bool_ ok; - - /* Save the spell index */ - spell = spell_x(sval, pval, i); - - /* Do we need to do some pre test */ - ok = is_ok_spell(spell, o_ptr); - - /* Require "okay" spells */ - if (!ok) - { - bell(); - msg_format("You may not %s that spell.", do_what); - spell = -1; - continue; - } - - /* Stop the loop */ - flag = TRUE; - } - } - } - else - { - bool_ ok; - - /* Require "okay" spells */ - ok = is_ok_spell(hack_force_spell, hack_force_spell_obj); - if (ok) - { - flag = TRUE; - spell = hack_force_spell; - } - else - { - bell(); - msg_format("You may not %s that spell.", do_what); - spell = -1; - } - } - - - /* Restore the screen */ - Term_load(); - character_icky = FALSE; - - - /* Show choices */ - window_stuff(); - - - /* Abort if needed */ - if (!flag) return -1; - - tmp = spell; - repeat_push(tmp); - return spell; -} - -void cast_school_spell() -{ - int spell; - - /* No magic */ - if (p_ptr->antimagic) - { - msg_print("Your anti-magic field disrupts any magic attempts."); - return; - } - - /* No magic */ - if (p_ptr->anti_magic) - { - msg_print("Your anti-magic shell disrupts any magic attempts."); - return; - } - - spell = get_school_spell("cast", 0); - - /* Actualy cast the choice */ - if (spell != -1) - { - lua_cast_school_spell(spell, FALSE); - } -} - -void browse_school_spell(int book, int pval, object_type *o_ptr) -{ - int i; - int num = 0, where = 1; - int ask; - char choice; - char out_val[160]; - - /* Show choices */ - window_stuff(); - - num = school_book_length(book); - - /* Build a prompt (accept all spells) */ - strnfmt(out_val, 78, "(Spells %c-%c, ESC=exit) cast which spell? ", - I2A(0), I2A(num - 1)); - - /* Save the screen */ - character_icky = TRUE; - Term_save(); - - /* Display a list of spells */ - where = print_book(book, pval, o_ptr); - - /* Get a spell from the user */ - while (get_com(out_val, &choice)) - { - /* Display a list of spells */ - where = print_book(book, pval, o_ptr); - - /* Note verify */ - ask = (isupper(choice)); - - /* Lowercase */ - if (ask) choice = tolower(choice); - - /* Extract request */ - i = (islower(choice) ? A2I(choice) : -1); - - /* Totally Illegal */ - if ((i < 0) || (i >= num)) - { - bell(); - continue; - } - - /* Restore the screen */ - Term_load(); - - /* Display a list of spells */ - where = print_book(book, pval, o_ptr); - print_spell_desc(spell_x(book, pval, i), where); - } - - - /* Restore the screen */ - Term_load(); - character_icky = FALSE; - - /* Show choices */ - window_stuff(); -} - -/* Can it contains a schooled spell ? */ -static bool_ hook_school_can_spellable(object_type *o_ptr) -{ - u32b f1, f2, f3, f4, f5, esp; - - /* Extract object flags */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - if ((f5 & TR5_SPELL_CONTAIN) && (o_ptr->pval2 == -1)) - return TRUE; - return FALSE; -} - -/* - * Copy a spell from a bok to an object - */ -void do_cmd_copy_spell() -{ - int spell = get_school_spell("copy", 0); - int item; - object_type *o_ptr; - - if (spell == -1) return; - - /* Spells that cannot be randomly created cannot be copied */ - if (spell_type_random_type(spell_at(spell)) <= 0) - { - msg_print("This spell cannot be copied."); - return; - } - - item_tester_hook = hook_school_can_spellable; - if (!get_item(&item, "Copy to which object? ", "You have no object to copy to.", (USE_INVEN | USE_EQUIP))) return; - o_ptr = get_object(item); - - msg_print("You copy the spell!"); - o_ptr->pval2 = spell; - inven_item_describe(item); -} diff --git a/src/cmd5.cc b/src/cmd5.cc new file mode 100644 index 00000000..95ae0346 --- /dev/null +++ b/src/cmd5.cc @@ -0,0 +1,2471 @@ +/* File: cmd5.c */ + +/* Purpose: Class commands */ + +/* + * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke + * + * This software may be copied and distributed for educational, research, and + * not for profit purposes provided that this copyright and statement are + * included in all such copies. + */ + + +#include "angband.h" + +#include + +#include "spell_type.h" +#include "quark.h" + +/* Maximum number of tries for teleporting */ +#define MAX_TRIES 300 + +bool_ is_school_book(object_type *o_ptr) +{ + if (o_ptr->tval == TV_BOOK) + { + return TRUE; + } + else if (o_ptr->tval == TV_DAEMON_BOOK) + { + return TRUE; + } + else if (o_ptr->tval == TV_INSTRUMENT) + { + return TRUE; + } + else + { + return FALSE; + } +} + +/* Does it contains a schooled spell ? */ +static bool_ hook_school_spellable(object_type *o_ptr) +{ + if (is_school_book(o_ptr)) + return TRUE; + else + { + u32b f1, f2, f3, f4, f5, esp; + + /* Extract object flags */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + if ((f5 & TR5_SPELL_CONTAIN) && (o_ptr->pval2 != -1)) + return TRUE; + } + return FALSE; +} + +/* Is it a book */ +bool_ item_tester_hook_browsable(object_type *o_ptr) +{ + if (hook_school_spellable(o_ptr)) return TRUE; + if (o_ptr->tval >= TV_BOOK) return TRUE; + return FALSE; +} + +/* + * Are we using a mage staff + */ +bool_ is_magestaff() +{ + int i; + + + i = 0; + + while (p_ptr->body_parts[i] == INVEN_WIELD) + { + object_type *o_ptr = &p_ptr->inventory[INVEN_WIELD + i]; + + /* Wielding a mage staff */ + if ((o_ptr->k_idx) && (o_ptr->tval == TV_MSTAFF)) return (TRUE); + + /* Next slot */ + i++; + + /* Paranoia */ + if (i >= (INVEN_TOTAL - INVEN_WIELD)) break; + } + + /* Not wielding a mage staff */ + return (FALSE); +} + +/* + * Peruse the spells/prayers in a book + * + * Note that *all* spells in the book are listed + * + * Note that browsing is allowed while confused or blind, + * and in the dark, primarily to allow browsing in stores. + */ + +extern void do_cmd_browse_aux(object_type *o_ptr) +{ + u32b f1, f2, f3, f4, f5, esp; + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + if (is_school_book(o_ptr)) + browse_school_spell(o_ptr->sval, o_ptr->pval, o_ptr); + else if (f5 & TR5_SPELL_CONTAIN && o_ptr->pval2 != -1) + browse_school_spell(255, o_ptr->pval2, o_ptr); +} + +void do_cmd_browse(void) +{ + int item; + + cptr q, s; + + object_type *o_ptr; + + /* Restrict choices to "useful" books */ + item_tester_hook = item_tester_hook_browsable; + + /* Get an item */ + q = "Browse which book? "; + s = "You have no books that you can read."; + if (!get_item(&item, q, s, (USE_INVEN | USE_EQUIP | USE_FLOOR))) return; + + /* Get the item */ + o_ptr = get_object(item); + + do_cmd_browse_aux(o_ptr); +} + +void do_poly_wounds(void) +{ + /* Changed to always provide at least _some_ healing */ + s16b wounds = p_ptr->cut; + + s16b hit_p = (p_ptr->mhp - p_ptr->chp); + + s16b change = damroll(p_ptr->lev, 5); + + bool_ Nasty_effect = (randint(5) == 1); + + + if (!(wounds || hit_p || Nasty_effect)) return; + + msg_print("Your wounds are polymorphed into less serious ones."); + hp_player(change); + if (Nasty_effect) + { + msg_print("A new wound was created!"); + take_hit(change / 2, "a polymorphed wound"); + set_cut(change); + } + else + { + set_cut((p_ptr->cut) - (change / 2)); + } +} + +void do_poly_self(void) +{ + int power = p_ptr->lev; + int poly_power; + + msg_print("You feel a change coming over you..."); + + if ((power > rand_int(20)) && (rand_int(3) == 0)) + { + char effect_msg[80] = ""; + int new_race, expfact, goalexpfact; + + /* Some form of racial polymorph... */ + power -= 10; + + if ((power > rand_int(5)) && (rand_int(4) == 0)) + { + /* sex change */ + power -= 2; + + if (p_ptr->psex == SEX_MALE) + { + p_ptr->psex = SEX_FEMALE; + sp_ptr = &sex_info[p_ptr->psex]; + strcpy(effect_msg, "female"); + } + else + { + p_ptr->psex = SEX_MALE; + sp_ptr = &sex_info[p_ptr->psex]; + strcpy(effect_msg, "male"); + } + } + + if ((power > rand_int(30)) && (rand_int(5) == 0)) + { + int tmp = 0; + + /* Harmful deformity */ + power -= 15; + + while (tmp < 6) + { + if ( rand_int(2) == 0) + { + (void)dec_stat(tmp, randint(6) + 6, (rand_int(3) == 0)); + power -= 1; + } + tmp++; + } + + /* Deformities are discriminated against! */ + (void)dec_stat(A_CHR, randint(6), TRUE); + + if (effect_msg[0]) + { + char tmp_msg[10]; + strnfmt(tmp_msg, 10, "%s", effect_msg); + strnfmt(effect_msg, 80, "deformed %s", tmp_msg); + } + else + { + strcpy(effect_msg, "deformed"); + } + } + + while ((power > rand_int(20)) && (rand_int(10) == 0)) + { + /* Polymorph into a less corrupted form */ + power -= 10; + + lose_corruption(); + } + + /* + * I'm not sure 'power' is always positive, with *so* many minuses. + * Also, passing zero / negative numbers to randint/rand_int can + * cause a zero divide exception, IIRC, not to speak of its absurdity + * -- pelpel + */ + poly_power = (power > 1) ? power : 1; + + /* + * Restrict the race choices by exp penalty so weak polymorph + * always means weak race + */ + goalexpfact = 100 + 3 * rand_int(poly_power); + + /* Roll until an appropriate selection is made */ + while (1) + { + new_race = rand_int(max_rp_idx); + expfact = race_info[new_race].r_exp; + + if ((new_race != p_ptr->prace) && (expfact <= goalexpfact)) break; + } + + if (effect_msg[0]) + { + msg_format("You turn into a%s %s!", + ((is_a_vowel(rp_name[race_info[new_race].title])) ? "n" : ""), + race_info[new_race].title + rp_name); + } + else + { + msg_format("You turn into a %s %s!", effect_msg, + race_info[new_race].title); + } + + p_ptr->prace = new_race; + rp_ptr = &race_info[p_ptr->prace]; + + /* Experience factor */ + p_ptr->expfact = rp_ptr->r_exp + rmp_ptr->r_exp + cp_ptr->c_exp; + + /* Calculate the height/weight */ + get_height_weight(); + + + check_experience(); + p_ptr->max_plv = p_ptr->lev; + + p_ptr->redraw |= (PR_BASIC); + + p_ptr->update |= (PU_BONUS); + + handle_stuff(); + lite_spot(p_ptr->py, p_ptr->px); + } + + if ((power > rand_int(30)) && (rand_int(6) == 0)) + { + int tmp = 0; + + /* Abomination! */ + power -= 20; + + msg_print("Your internal organs are rearranged!"); + while (tmp < 6) + { + (void)dec_stat(tmp, randint(6) + 6, (rand_int(3) == 0)); + tmp++; + } + if (rand_int(6) == 0) + { + msg_print("You find living difficult in your present form!"); + take_hit(damroll(randint(10), p_ptr->lev), "a lethal corruption"); + power -= 10; + } + } + + if ((power > rand_int(20)) && (rand_int(4) == 0)) + { + power -= 10; + + do_cmd_rerate(); + } + + while ((power > rand_int(15)) && (rand_int(3) == 0)) + { + power -= 7; + gain_random_corruption(); + } + + if (power > rand_int(5)) + { + power -= 5; + do_poly_wounds(); + } + + /* Note: earlier deductions may have left power < 0 already. */ + while (power > 0) + { + corrupt_player(); + power--; + } +} + + +/* + * Brand the current weapon + */ +void brand_weapon(int brand_type) +{ + object_type *o_ptr; + + cptr act = NULL; + + char o_name[80]; + + + o_ptr = &p_ptr->inventory[INVEN_WIELD]; + + /* + * You can never modify artifacts / ego-items + * You can never modify cursed items + * + * TY: You _can_ modify broken items (if you're silly enough) + */ + if (!o_ptr->k_idx || artifact_p(o_ptr) || ego_item_p(o_ptr) || + o_ptr->art_name || cursed_p(o_ptr)) + { + if (flush_failure) flush(); + + msg_print("The Branding failed."); + + return; + } + + + /* Save the old name */ + object_desc(o_name, o_ptr, FALSE, 0); + + switch (brand_type) + { + case 6: + { + act = "glows with godly power."; + o_ptr->name2 = EGO_BLESS_BLADE; + o_ptr->pval = randint(4); + + break; + } + case 5: + { + act = "seems very powerful."; + o_ptr->name2 = EGO_EARTHQUAKES; + o_ptr->pval = randint(3); + + break; + } + case 4: + { + act = "seems very unstable now."; + o_ptr->name2 = EGO_DRAGON; + o_ptr->pval = randint(2); + + break; + } + case 3: + { + act = "thirsts for blood!"; + o_ptr->name2 = EGO_VAMPIRIC; + + break; + } + case 2: + { + act = "is coated with poison."; + o_ptr->name2 = EGO_BRAND_POIS; + + break; + } + case 1: + { + act = "is engulfed in raw chaos!"; + o_ptr->name2 = EGO_CHAOTIC; + + break; + } + default: + { + if (rand_int(100) < 25) + { + act = "is covered in a fiery shield!"; + o_ptr->name2 = EGO_BRAND_FIRE; + } + else + { + act = "glows deep, icy blue!"; + o_ptr->name2 = EGO_BRAND_COLD; + } + } + } + + /* Apply the ego */ + apply_magic(o_ptr, dun_level, FALSE, FALSE, FALSE); + o_ptr->discount = 100; + + msg_format("Your %s %s", o_name, act); + + enchant(o_ptr, rand_int(3) + 4, ENCH_TOHIT | ENCH_TODAM); +} + +/* + * Fetch an item (teleport it right underneath the caster) + */ +void fetch(int dir, int wgt, bool_ require_los) +{ + int ty, tx, i; + + cave_type *c_ptr; + + object_type *o_ptr; + + char o_name[80]; + + + /* Check to see if an object is already there */ + if (cave[p_ptr->py][p_ptr->px].o_idx) + { + msg_print("You can't fetch when you're already standing on something."); + return; + } + + /* Use a target */ + if ((dir == 5) && target_okay()) + { + tx = target_col; + ty = target_row; + + if (distance(p_ptr->py, p_ptr->px, ty, tx) > MAX_RANGE) + { + msg_print("You can't fetch something that far away!"); + return; + } + + c_ptr = &cave[ty][tx]; + + if (!c_ptr->o_idx) + { + msg_print("There is no object at this place."); + return; + } + + if (require_los && (!player_has_los_bold(ty, tx))) + { + msg_print("You have no direct line of sight to that location."); + return; + } + } + else + { + /* Use a direction */ + ty = p_ptr->py; /* Where to drop the item */ + tx = p_ptr->px; + + while (1) + { + ty += ddy[dir]; + tx += ddx[dir]; + c_ptr = &cave[ty][tx]; + + if ((distance(p_ptr->py, p_ptr->px, ty, tx) > MAX_RANGE) || + !cave_floor_bold(ty, tx)) return; + + if (c_ptr->o_idx) break; + } + } + + o_ptr = &o_list[c_ptr->o_idx]; + + if (o_ptr->weight > wgt) + { + /* Too heavy to 'fetch' */ + msg_print("The object is too heavy."); + return; + } + + i = c_ptr->o_idx; + c_ptr->o_idx = o_ptr->next_o_idx; + cave[p_ptr->py][p_ptr->px].o_idx = i; /* 'move' it */ + o_ptr->next_o_idx = 0; + o_ptr->iy = p_ptr->py; + o_ptr->ix = p_ptr->px; + + object_desc(o_name, o_ptr, TRUE, 0); + msg_format("%^s flies through the air to your feet.", o_name); + + note_spot(p_ptr->py, p_ptr->px); + p_ptr->redraw |= PR_MAP; +} + + +/* + * Handle random effects of player shrieking + */ +void shriek_effect() +{ + switch (randint(9)) + { + case 1: + case 5: + case 8: + case 9: + { + msg_print("You make a high-pitched shriek!"); + aggravate_monsters(1); + + break; + } + case 2: + case 6: + { + msg_print("Oops! You call a monster."); + summon_specific(p_ptr->py, p_ptr->px, max_dlv[dungeon_type], 0); + + break; + } + case 3: + case 7: + { + msg_print("The dungeon collapses!"); + earthquake(p_ptr->py, p_ptr->px, 5); + + break; + } + case 4: + { + msg_print("Your shriek is so horrible that you damage your health!"); + take_hit(damroll(p_ptr->lev / 5, 8), "inner hemorrhaging"); + + break; + } + } +} + + +/* + * Like all the random effect codes, this is *ugly*, + * and there is not a single line of comment, so I can't tell + * some fall throughs are really intended. Well, I know it's + * intended to be bizarre :) -- pelpel + */ +void wild_magic(int spell) +{ + int counter = 0; + int type = SUMMON_BIZARRE1 - 1 + randint(6); + + if (type < SUMMON_BIZARRE1) type = SUMMON_BIZARRE1; + else if (type > SUMMON_BIZARRE6) type = SUMMON_BIZARRE6; + + switch (randint(spell) + randint(8) + 1) + { + case 1: + case 2: + case 3: + { + teleport_player(10); + + break; + } + + case 4: + case 5: + case 6: + { + teleport_player(100); + + break; + } + + case 7: + case 8: + { + teleport_player(200); + + break; + } + + case 9: + case 10: + case 11: + { + unlite_area(10, 3); + + break; + } + + case 12: + case 13: + case 14: + { + lite_area(damroll(2, 3), 2); + + break; + } + + case 15: + { + destroy_doors_touch(); + + break; + } + + case 16: + case 17: + { + wall_breaker(); + + /* I don't think this is a fall through -- pelpel */ + break; + } + + case 18: + { + sleep_monsters_touch(); + + break; + } + + case 19: + case 20: + { + trap_creation(); + + break; + } + + case 21: + case 22: + { + door_creation(); + + break; + } + + case 23: + case 24: + case 25: + { + aggravate_monsters(1); + + break; + } + + case 26: + { + /* Prevent destruction of quest levels and town */ + if (!is_quest(dun_level) && dun_level) + earthquake(p_ptr->py, p_ptr->px, 5); + + break; + } + + case 27: + case 28: + { + break; + } + + case 29: + case 30: + { + apply_disenchant(0); + + break; + } + + case 31: + { + lose_all_info(); + + break; + } + + case 32: + { + fire_ball(GF_CHAOS, 0, spell + 5, 1 + (spell / 10)); + + break; + } + + case 33: + { + wall_stone(p_ptr->py, p_ptr->px); + + break; + } + + case 34: + case 35: + { + while (counter++ < 8) + { + (void) summon_specific(p_ptr->py, p_ptr->px, (dun_level * 3) / 2, type); + } + + break; + } + + case 36: + case 37: + { + activate_hi_summon(); + + break; + } + + case 38: + { + summon_cyber(); + + /* I don't think this is a fall through -- pelpel */ + break; + } + + default: + { + activate_ty_curse(); + } + } + + return; +} + + +/* + * Hack -- Determine if the player is wearing an artefact ring + * specified by art_type, that should be an index into a_info + */ +bool_ check_ring(int art_type) +{ + int i; + + + /* We are only interested in ring slots */ + i = INVEN_RING; + + /* Scan the list of rings until we reach the end */ + while (p_ptr->body_parts[i - INVEN_WIELD] == INVEN_RING) + { + /* Found the ring we were looking for */ + if (p_ptr->inventory[i].k_idx && (p_ptr->inventory[i].name1 == art_type)) + { + return (TRUE); + } + + /* Next item */ + i++; + } + + /* Found nothing */ + return (FALSE); +} + +/* + * Return the symbiote's name or description. + */ +cptr symbiote_name(bool_ capitalize) +{ + object_type *o_ptr = &p_ptr->inventory[INVEN_CARRY]; + static char buf[80]; + + /* Make sure there actually is a symbiote there... */ + if (!o_ptr->k_idx) + { + strcpy(buf, "A non-existent symbiote"); + } + else + { + monster_race *r_ptr = &r_info[o_ptr->pval]; + cptr s = NULL; + + if (r_ptr->flags1 & RF1_UNIQUE) + { + /* Unique monster; no preceding "your", and ignore our name. */ + strncpy(buf, r_name + r_ptr->name, sizeof(buf)); + } + else if (o_ptr->note && + (s = strstr(quark_str(o_ptr->note), "#named ")) != NULL) + { + /* We've named it. */ + strncpy(buf, s + 7, sizeof(buf)); + } + else + { + /* No special cases, just return "Your ". */ + strcpy(buf, "your "); + strncpy(buf + 5, r_name + r_ptr->name, sizeof(buf) - 5); + } + } + + /* Just in case... */ + buf[sizeof(buf) - 1] = '\0'; + if (capitalize) buf[0] = toupper(buf[0]); + return buf; +} + +/* + * Use a power of the monster in symbiosis + */ +int use_symbiotic_power(int r_idx, bool_ great, bool_ only_number, bool_ no_cost) +{ + int power = -1; + + int num = 0, dir = 0 , i; + + int powers[96]; + + bool_ flag; + + int ask, plev = p_ptr->lev; + + char choice; + + char out_val[160]; + + monster_race *r_ptr = &r_info[r_idx]; + + int rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1); + + int x = p_ptr->px, y = p_ptr->py, k; + + int rad; + + int label; + + + /* List the monster powers -- RF4_* */ + for (i = 0; i < 32; i++) + { + if (r_ptr->flags4 & BIT(i)) + { + if (monster_powers[i].great && (!great)) continue; + if (!monster_powers[i].power) continue; + powers[num++] = i; + } + } + + /* List the monster powers -- RF5_* */ + for (i = 0; i < 32; i++) + { + if (r_ptr->flags5 & BIT(i)) + { + if (monster_powers[i + 32].great && (!great)) continue; + if (!monster_powers[i + 32].power) continue; + powers[num++] = i + 32; + } + } + + /* List the monster powers -- RF6_* */ + for (i = 0; i < 32; i++) + { + if (r_ptr->flags6 & BIT(i)) + { + if (monster_powers[i + 64].great && (!great)) continue; + if (!monster_powers[i + 64].power) continue; + powers[num++] = i + 64; + } + } + + if (!num) + { + msg_print("You have no powers you can use."); + return (0); + } + + if (only_number) return (num); + + /* Nothing chosen yet */ + flag = FALSE; + + /* Get the last label */ + label = (num <= 26) ? I2A(num - 1) : I2D(num - 1 - 26); + + /* Build a prompt (accept all spells) */ + /* Mega Hack -- if no_cost is false, we're actually a Possessor -dsb */ + strnfmt(out_val, 78, + "(Powers a-%c, ESC=exit) Use which power of your %s? ", + label, (no_cost ? "symbiote" : "body")); + + /* Save the screen */ + character_icky = TRUE; + Term_save(); + + /* Get a spell from the user */ + while (!flag) + { + /* Show the list */ + { + byte y = 1, x = 0; + int ctr = 0; + char dummy[80]; + + strcpy(dummy, ""); + + prt ("", y++, x); + + while (ctr < num) + { + monster_power *mp_ptr = &monster_powers[powers[ctr]]; + int mana = mp_ptr->mana / 10; + + if (mana > p_ptr->msp) mana = p_ptr->msp; + + if (!mana) mana = 1; + + label = (ctr < 26) ? I2A(ctr) : I2D(ctr - 26); + + if (!no_cost) + { + strnfmt(dummy, 80, " %c) %2d %s", + label, mana, mp_ptr->name); + } + else + { + strnfmt(dummy, 80, " %c) %s", + label, mp_ptr->name); + } + + if (ctr < 17) + { + prt(dummy, y + ctr, x); + } + else + { + prt(dummy, y + ctr - 17, x + 40); + } + + ctr++; + } + + if (ctr < 17) + { + prt ("", y + ctr, x); + } + else + { + prt ("", y + 17, x); + } + } + + if (!get_com(out_val, &choice)) + { + flag = FALSE; + break; + } + + if (choice == '\r' && num == 1) + { + choice = 'a'; + } + + if (isalpha(choice)) + { + /* Note verify */ + ask = (isupper(choice)); + + /* Lowercase */ + if (ask) choice = tolower(choice); + + /* Extract request */ + i = (islower(choice) ? A2I(choice) : -1); + } + else + { + /* Can't uppercase digits XXX XXX XXX */ + ask = FALSE; + + i = choice - '0' + 26; + } + + /* Totally Illegal */ + if ((i < 0) || (i >= num)) + { + bell(); + continue; + } + + /* Save the spell index */ + power = powers[i]; + + /* Verify it */ + if (ask) + { + char tmp_val[160]; + + /* Prompt */ + strnfmt(tmp_val, 78, "Use %s? ", monster_powers[power].name); + + /* Belay that order */ + if (!get_check(tmp_val)) continue; + } + + /* Stop the loop */ + flag = TRUE; + } + + /* Restore the screen */ + Term_load(); + character_icky = FALSE; + + /* Abort if needed */ + if (!flag) + { + energy_use = 0; + return -1; + } + + /* 'Powerful' monsters have wider radii */ + if (r_ptr->flags2 & RF2_POWERFUL) + { + rad = 1 + (p_ptr->lev / 15); + } + else + { + rad = 1 + (p_ptr->lev / 20); + } + + + /* Analyse power */ + switch (power) + { + /**** RF4 (bit position) ****/ + + /* SHRIEK */ + case 0: + { + aggravate_monsters( -1); + + break; + } + + /* MULTIPLY */ + case 1: + { + do_cmd_wiz_named_friendly(p_ptr->body_monster, FALSE); + + break; + } + + /* S_ANIMAL */ + case 2: + { + summon_specific_friendly(y, x, rlev, SUMMON_ANIMAL, TRUE); + + break; + } + + /* ROCKET */ + case 3: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_ROCKET, dir, p_ptr->lev * 12, 1 + (p_ptr->lev / 20)); + + break; + } + + /* ARROW_1 */ + case 4: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_ARROW, dir, damroll(1, 6)); + + break; + } + + /* ARROW_2 */ + case 5: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_ARROW, dir, damroll(3, 6)); + + break; + } + + /* ARROW_3 */ + case 6: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_ARROW, dir, damroll(5, 6)); + + break; + } + + /* ARROW_4 */ + case 7: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_ARROW, dir, damroll(7, 6)); + + break; + } + + /* BR_ACID */ + case 8: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_ACID, dir, p_ptr->lev * 5, rad); + + break; + } + + /* BR_ELEC */ + case 9: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_ELEC, dir, p_ptr->lev * 5, rad); + + break; + } + + /* BR_FIRE */ + case 10: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_FIRE, dir, p_ptr->lev * 5, rad); + + break; + } + + /* BR_COLD */ + case 11: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_COLD, dir, p_ptr->lev * 5, rad); + + break; + } + + /* BR_POIS */ + case 12: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_POIS, dir, p_ptr->lev * 5, rad); + + break; + } + + /* BR_NETH */ + case 13: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_NETHER, dir, p_ptr->lev * 5, rad); + + break; + } + + /* BR_LITE */ + case 14: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_LITE, dir, p_ptr->lev * 8, rad); + + break; + } + + /* BR_DARK */ + case 15: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_DARK, dir, p_ptr->lev * 8, rad); + + break; + } + + /* BR_CONF */ + case 16: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_CONFUSION, dir, p_ptr->lev * 8, rad); + + break; + } + + /* BR_SOUN */ + case 17: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_SOUND, dir, p_ptr->lev * 8, rad); + + break; + } + + /* BR_CHAO */ + case 18: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_CHAOS, dir, p_ptr->lev * 7, rad); + + break; + } + + /* BR_DISE */ + case 19: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_DISENCHANT, dir, p_ptr->lev * 7, rad); + + break; + } + + /* BR_NEXU */ + case 20: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_NEXUS, dir, p_ptr->lev * 5, rad); + + break; + } + + /* BR_TIME */ + case 21: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_TIME, dir, p_ptr->lev * 3, rad); + + break; + } + + /* BR_INER */ + case 22: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_INERTIA, dir, p_ptr->lev * 4, rad); + + break; + } + + /* BR_GRAV */ + case 23: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_GRAVITY, dir, p_ptr->lev * 4, rad); + + break; + } + + /* BR_SHAR */ + case 24: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_SHARDS, dir, p_ptr->lev * 8, rad); + + break; + } + + /* BR_PLAS */ + case 25: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_PLASMA, dir, p_ptr->lev * 3, rad); + + break; + } + + /* BR_WALL */ + case 26: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_FORCE, dir, p_ptr->lev * 4, rad); + + break; + } + + /* BR_MANA */ + case 27: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_MANA, dir, p_ptr->lev * 5, rad); + + break; + } + + /* BA_NUKE */ + case 28: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_NUKE, dir, p_ptr->lev * 8, 1 + (p_ptr->lev / 20)); + + break; + } + + /* BR_NUKE */ + case 29: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_NUKE, dir, p_ptr->lev * 8, 1 + (p_ptr->lev / 20)); + + break; + } + + /* BA_CHAO */ + case 30: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_CHAOS, dir, p_ptr->lev * 4, 2); + + break; + } + + /* BR_DISI */ + case 31: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_DISINTEGRATE, dir, p_ptr->lev * 5, 1 + (p_ptr->lev / 20)); + + break; + } + + + /**** RF5 (bit position + 32) ****/ + + /* BA_ACID */ + case 32: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_ACID, dir, randint(p_ptr->lev * 6) + 20, 2); + + break; + } + + /* BA_ELEC */ + case 33: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_ELEC, dir, randint(p_ptr->lev * 3) + 20, 2); + + break; + } + + /* BA_FIRE */ + case 34: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_FIRE, dir, randint(p_ptr->lev * 7) + 20, 2); + + break; + } + + /* BA_COLD */ + case 35: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_COLD, dir, randint(p_ptr->lev * 3) + 20, 2); + + break; + } + + /* BA_POIS */ + case 36: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_POIS, dir, damroll(12, 2), 2); + + break; + } + + /* BA_NETH */ + case 37: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_NETHER, dir, randint(p_ptr->lev * 4) + 20, 2); + + break; + } + + /* BA_WATE */ + case 38: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_WATER, dir, randint(p_ptr->lev * 4) + 20, 2); + + break; + } + + /* BA_MANA */ + case 39: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_MANA, dir, randint(p_ptr->lev * 3) + 20, 2); + + break; + } + + /* BA_DARK */ + case 40: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_DARK, dir, randint(p_ptr->lev * 3) + 20, 2); + + break; + } + + /* 41 DRAIN_MANA -- Not available */ + + /* 42 MIND_BLAST -- Not available */ + + /* 43 BRAIN_SMASH -- Not available */ + + /* CAUSE_1 */ + case 44: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_MANA, dir, damroll(3, 8)); + + break; + } + + /* CAUSE_2 */ + case 45: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_MANA, dir, damroll(8, 8)); + + break; + } + + /* CAUSE_3 */ + case 46: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_MANA, dir, damroll(10, 15)); + + break; + } + + /* CAUSE_4 */ + case 47: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_MANA, dir, damroll(15, 15)); + + break; + } + + /* BO_ACID */ + case 48: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_ACID, dir, damroll(7, 8) + (p_ptr->lev / 3)); + + break; + } + + /* BO_ELEC */ + case 49: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_ELEC, dir, damroll(4, 8) + (p_ptr->lev / 3)); + + break; + } + + /* BO_FIRE */ + case 50: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_FIRE, dir, damroll(9, 8) + (p_ptr->lev / 3)); + + break; + } + + /* BO_COLD */ + case 51: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_COLD, dir, damroll(6, 8) + (p_ptr->lev / 3)); + + break; + } + + /* BO_POIS */ + case 52: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_POIS, dir, damroll(7, 8) + (p_ptr->lev / 3)); + + break; + } + + /* BO_NETH */ + case 53: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_NETHER, dir, damroll(5, 5) + (p_ptr->lev / 3)); + + break; + } + + /* BO_WATE */ + case 54: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_WATER, dir, damroll(10, 10) + (p_ptr->lev / 3)); + + break; + } + + /* BO_MANA */ + case 55: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_MANA, dir, damroll(3, 8) + (p_ptr->lev / 3)); + + break; + } + + /* BO_PLAS */ + case 56: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_PLASMA, dir, damroll(8, 8) + (p_ptr->lev / 3)); + + break; + } + + /* BO_ICEE */ + case 57: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_ICE, dir, damroll(6, 6) + (p_ptr->lev / 3)); + + break; + } + + /* MISSILE */ + case 58: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_MISSILE, dir, damroll(2, 6) + (p_ptr->lev / 3)); + + break; + } + + /* SCARE */ + case 59: + { + if (!get_aim_dir(&dir)) break; + + fear_monster(dir, plev); + + break; + } + + /* BLIND */ + case 60: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_CONFUSION, dir, damroll(1, 8) + (p_ptr->lev / 3)); + + break; + } + + /* CONF */ + case 61: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_CONFUSION, dir, damroll(7, 8) + (p_ptr->lev / 3)); + + break; + } + + /* SLOW */ + case 62: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_OLD_SLOW, dir, damroll(6, 8) + (p_ptr->lev / 3)); + + break; + } + + /* HOLD */ + case 63: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_OLD_SLEEP, dir, damroll(5, 8) + (p_ptr->lev / 3)); + + break; + } + + + /**** RF6 (bit position + 64) ****/ + + /* HASTE */ + case 64: + { + if (!p_ptr->fast) + { + (void)set_fast(randint(20 + (plev) ) + plev, 10); + } + else + { + (void)set_fast(p_ptr->fast + randint(5), 10); + } + + break; + } + + /* HAND_DOOM */ + case 65: + { + if (!get_aim_dir(&dir)) break; + + fire_bolt(GF_MANA, dir, damroll(10, 8) + (p_ptr->lev)); + + break; + } + + /* HEAL */ + case 66: + { + hp_player(damroll(8, 5)); + + break; + } + + /* S_ANIMALS */ + case 67: + { + for (k = 0; k < 4; k++) + { + summon_specific_friendly(y, x, rlev, SUMMON_ANIMAL, TRUE); + } + + break; + } + + /* BLINK */ + case 68: + { + if (dungeon_flags2 & DF2_NO_TELEPORT) + { + msg_print("No teleport on special levels..."); + break; + } + + teleport_player(10); + + break; + } + + /* TPORT */ + case 69: + { + if (dungeon_flags2 & DF2_NO_TELEPORT) + { + msg_print("No teleport on special levels..."); + break; + } + + teleport_player(plev * 5); + + break; + } + + /* TELE_TO */ + case 70: + { + int ii, ij; + + if (dungeon_flags2 & DF2_NO_TELEPORT) + { + msg_print("No teleport on special levels..."); + break; + } + + msg_print("You go between."); + + if (!tgt_pt(&ii, &ij)) break; + + p_ptr->energy -= 60 - plev; + + if (!cave_empty_bold(ij, ii) || + (cave[ij][ii].info & CAVE_ICKY) || + (distance(ij, ii, p_ptr->py, p_ptr->px) > plev * 20 + 2)) + { + msg_print("You fail to show the destination correctly!"); + p_ptr->energy -= 100; + teleport_player(10); + } + else teleport_player_to(ij, ii); + + break; + } + + /* TELE_AWAY */ + case 71: + { + if (dungeon_flags2 & DF2_NO_TELEPORT) + { + msg_print("No teleport on special levels..."); + break; + } + + if (!get_aim_dir(&dir)) break; + + (void)fire_beam(GF_AWAY_ALL, dir, plev); + + break; + } + + /* TELE_LEVEL */ + case 72: + { + if (dungeon_flags2 & DF2_NO_TELEPORT) + { + msg_print("No teleport on special levels..."); + break; + } + + teleport_player_level(); + + break; + } + + /* DARKNESS */ + case 73: + { + (void)project( -1, 3, p_ptr->py, p_ptr->px, 0, GF_DARK_WEAK, + PROJECT_GRID | PROJECT_KILL); + + /* Unlite the room */ + unlite_room(p_ptr->py, p_ptr->px); + + break; + } + + /* TRAPS */ + case 74: + { + trap_creation(); + + break; + } + + /* 75 FORGET -- Not available */ + + /* ANIM_DEAD -- Use the same code as the nether spell */ + case 76: + { + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_RAISE, dir, 1, 0); + + break; + } + + /* 77 S_BUG -- Not available, well we do that anyway ;) */ + + /* 78 S_RNG -- Not available, who dares? */ + + /* S_THUNDERLORD */ + case 79: + { + for (k = 0; k < 1; k++) + { + summon_specific_friendly(y, x, rlev, SUMMON_THUNDERLORD, TRUE); + } + + break; + } + + /* S_KIN -- Summon Kin, because we code bugs :) */ + case 80: + { + /* Big hack */ + summon_kin_type = r_ptr->d_char; + + for (k = 0; k < 6; k++) + { + summon_specific_friendly(y, x, rlev, SUMMON_KIN, TRUE); + } + + break; + } + + /* S_HI_DEMON */ + case 81: + { + for (k = 0; k < 1; k++) + { + summon_specific_friendly(y, x, rlev, SUMMON_HI_DEMON, TRUE); + } + + break; + } + + /* S_MONSTER */ + case 82: + { + for (k = 0; k < 1; k++) + { + summon_specific_friendly(y, x, rlev, 0, TRUE); + } + + break; + } + + /* S_MONSTERS */ + case 83: + { + for (k = 0; k < 6; k++) + { + summon_specific_friendly(y, x, rlev, 0, TRUE); + } + + break; + } + + /* S_ANT */ + case 84: + { + for (k = 0; k < 6; k++) + { + summon_specific_friendly(y, x, rlev, SUMMON_ANT, TRUE); + } + + break; + } + + /* S_SPIDER */ + case 85: + { + for (k = 0; k < 6; k++) + { + summon_specific_friendly(y, x, rlev, SUMMON_SPIDER, TRUE); + } + + break; + } + + /* S_HOUND */ + case 86: + { + for (k = 0; k < 6; k++) + { + summon_specific_friendly(y, x, rlev, SUMMON_HOUND, TRUE); + } + + break; + } + + /* S_HYDRA */ + case 87: + { + for (k = 0; k < 6; k++) + { + summon_specific_friendly(y, x, rlev, SUMMON_HYDRA, TRUE); + } + + break; + } + + /* S_ANGEL */ + case 88: + { + for (k = 0; k < 1; k++) + { + summon_specific_friendly(y, x, rlev, SUMMON_ANGEL, TRUE); + } + + break; + } + + /* S_DEMON */ + case 89: + { + for (k = 0; k < 1; k++) + { + summon_specific_friendly(y, x, rlev, SUMMON_DEMON, TRUE); + } + + break; + } + + /* S_UNDEAD */ + case 90: + { + for (k = 0; k < 1; k++) + { + summon_specific_friendly(y, x, rlev, SUMMON_UNDEAD, TRUE); + } + + break; + } + + /* S_DRAGON */ + case 91: + { + for (k = 0; k < 1; k++) + { + summon_specific_friendly(y, x, rlev, SUMMON_DRAGON, TRUE); + } + + break; + } + + /* S_HI_UNDEAD */ + case 92: + { + for (k = 0; k < 8; k++) + { + summon_specific_friendly(y, x, rlev, SUMMON_HI_UNDEAD_NO_UNIQUES, TRUE); + } + + break; + } + + /* S_HI_DRAGON */ + case 93: + { + for (k = 0; k < 8; k++) + { + summon_specific_friendly(y, x, rlev, SUMMON_HI_DRAGON_NO_UNIQUES, TRUE); + } + + break; + } + + /* S_WRAITH */ + case 94: + { + for (k = 0; k < 8; k++) + { + summon_specific_friendly(y, x, rlev, SUMMON_WRAITH, TRUE); + } + + break; + } + + /* 95 S_UNIQUE -- Not available */ + } + + /* Take some SP */ + if (!no_cost) + { + int chance, pchance; + + chance = (monster_powers[power].mana + r_ptr->level); + pchance = adj_str_wgt[p_ptr->stat_ind[A_WIS]] / 2 + get_skill(SKILL_POSSESSION); + + if (rand_int(chance) >= pchance) + { + int m = monster_powers[power].mana / 10; + + if (m > p_ptr->msp) m = p_ptr->msp; + if (!m) m = 1; + + p_ptr->csp -= m; + } + } + + /* Redraw mana */ + p_ptr->redraw |= (PR_MANA); + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + + return (num); +} + +/* + * Schooled magic + */ + +/* + * Find a spell in any books/objects + */ +static int hack_force_spell = -1; +static object_type *hack_force_spell_obj = NULL; +bool_ get_item_hook_find_spell(int *item) +{ + int i, spell; + char buf[80]; + + strcpy(buf, "Manathrust"); + if (!get_string("Spell name? ", buf, 79)) + return FALSE; + + spell = find_spell(buf); + if (spell == -1) return FALSE; + + for (i = 0; i < INVEN_TOTAL; i++) + { + object_type *o_ptr = &p_ptr->inventory[i]; + u32b f1, f2, f3, f4, f5, esp; + + /* Must we wield it ? */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + if ((wield_slot(o_ptr) != -1) && (i < INVEN_WIELD) && (f5 & TR5_WIELD_CAST)) continue; + + /* Is it a non-book? */ + if (!is_school_book(o_ptr)) + { + u32b f1, f2, f3, f4, f5, esp; + + /* Extract object flags */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + if ((f5 & TR5_SPELL_CONTAIN) && (o_ptr->pval2 == spell)) + { + *item = i; + hack_force_spell = spell; + hack_force_spell_obj = o_ptr; + return TRUE; + } + } + /* A random book ? */ + else if (school_book_contains_spell(o_ptr->sval, spell)) + { + *item = i; + hack_force_spell = spell; + hack_force_spell_obj = o_ptr; + return TRUE; + } + } + return FALSE; +} + +/* + * Is the spell castable? + */ +bool_ is_ok_spell(s32b spell_idx, object_type *o_ptr) +{ + spell_type *spell = spell_at(spell_idx); + assert(o_ptr != NULL); + + if (get_level(spell_idx, 50, 0) == 0) + { + return FALSE; + } + + if (o_ptr->pval < spell_type_minimum_pval(spell)) + { + return FALSE; + } + + return TRUE; +} + + +/* + * Get a spell from a book + */ +s32b get_school_spell(cptr do_what, s16b force_book) +{ + int i, item; + s32b spell = -1; + int num = 0; + s32b where = 1; + int ask; + bool_ flag; + char out_val[160]; + char buf2[40]; + char buf3[40]; + object_type *o_ptr, forge; + int tmp; + int sval, pval; + u32b f1, f2, f3, f4, f5, esp; + + hack_force_spell = -1; + hack_force_spell_obj = NULL; + + /* Ok do we need to ask for a book ? */ + if (!force_book) + { + get_item_extra_hook = get_item_hook_find_spell; + item_tester_hook = hook_school_spellable; + sprintf(buf2, "You have no book to %s from", do_what); + sprintf(buf3, "%s from which book?", do_what); + if (!get_item(&item, buf3, buf2, USE_INVEN | USE_EQUIP | USE_EXTRA )) return -1; + + /* Get the item */ + o_ptr = get_object(item); + + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* If it can be wielded, it must */ + if ((wield_slot(o_ptr) != -1) && (item < INVEN_WIELD) && (f5 & TR5_WIELD_CAST)) + { + msg_format("You cannot %s from that object; it must be wielded first.", do_what); + return -1; + } + } + else + { + o_ptr = &forge; + o_ptr->tval = TV_BOOK; + o_ptr->sval = force_book; + o_ptr->pval = 0; + } + + if (repeat_pull(&tmp)) + { + return tmp; + } + + /* Nothing chosen yet */ + flag = FALSE; + + /* Show choices */ + window_stuff(); + + /* No spell to cast by default */ + spell = -1; + + /* Is it a random book, or something else ? */ + if (is_school_book(o_ptr)) + { + sval = o_ptr->sval; + pval = o_ptr->pval; + } + else + { + sval = 255; + pval = o_ptr->pval2; + } + + /* Save the screen */ + character_icky = TRUE; + Term_save(); + + /* Go */ + if (hack_force_spell == -1) + { + num = school_book_length(sval); + + /* Build a prompt (accept all spells) */ + strnfmt(out_val, 78, "(Spells %c-%c, Descs %c-%c, ESC=exit) %^s which spell? ", + I2A(0), I2A(num - 1), I2A(0) - 'a' + 'A', I2A(num - 1) - 'a' + 'A', do_what); + + /* Get a spell from the user */ + while (!flag) + { + char choice; + + /* Restore and save screen; this prevents + subprompt from leaving garbage when going + around the loop multiple times. */ + Term_load(); + Term_save(); + + /* Display a list of spells */ + where = print_book(sval, pval, o_ptr); + + /* Input */ + if (!get_com(out_val, &choice)) + { + flag = FALSE; + break; + } + + /* Note verify */ + ask = (isupper(choice)); + + /* Lowercase */ + if (ask) choice = tolower(choice); + + /* Extract request */ + i = (islower(choice) ? A2I(choice) : -1); + + /* Totally Illegal */ + if ((i < 0) || (i >= num)) + { + bell(); + continue; + } + + /* Verify it */ + if (ask) + { + /* Display a list of spells */ + where = print_book(sval, pval, o_ptr); + print_spell_desc(spell_x(sval, pval, i), where); + } + else + { + bool_ ok; + + /* Save the spell index */ + spell = spell_x(sval, pval, i); + + /* Do we need to do some pre test */ + ok = is_ok_spell(spell, o_ptr); + + /* Require "okay" spells */ + if (!ok) + { + bell(); + msg_format("You may not %s that spell.", do_what); + spell = -1; + continue; + } + + /* Stop the loop */ + flag = TRUE; + } + } + } + else + { + bool_ ok; + + /* Require "okay" spells */ + ok = is_ok_spell(hack_force_spell, hack_force_spell_obj); + if (ok) + { + flag = TRUE; + spell = hack_force_spell; + } + else + { + bell(); + msg_format("You may not %s that spell.", do_what); + spell = -1; + } + } + + + /* Restore the screen */ + Term_load(); + character_icky = FALSE; + + + /* Show choices */ + window_stuff(); + + + /* Abort if needed */ + if (!flag) return -1; + + tmp = spell; + repeat_push(tmp); + return spell; +} + +void cast_school_spell() +{ + int spell; + + /* No magic */ + if (p_ptr->antimagic) + { + msg_print("Your anti-magic field disrupts any magic attempts."); + return; + } + + /* No magic */ + if (p_ptr->anti_magic) + { + msg_print("Your anti-magic shell disrupts any magic attempts."); + return; + } + + spell = get_school_spell("cast", 0); + + /* Actualy cast the choice */ + if (spell != -1) + { + lua_cast_school_spell(spell, FALSE); + } +} + +void browse_school_spell(int book, int pval, object_type *o_ptr) +{ + int i; + int num = 0, where = 1; + int ask; + char choice; + char out_val[160]; + + /* Show choices */ + window_stuff(); + + num = school_book_length(book); + + /* Build a prompt (accept all spells) */ + strnfmt(out_val, 78, "(Spells %c-%c, ESC=exit) cast which spell? ", + I2A(0), I2A(num - 1)); + + /* Save the screen */ + character_icky = TRUE; + Term_save(); + + /* Display a list of spells */ + where = print_book(book, pval, o_ptr); + + /* Get a spell from the user */ + while (get_com(out_val, &choice)) + { + /* Display a list of spells */ + where = print_book(book, pval, o_ptr); + + /* Note verify */ + ask = (isupper(choice)); + + /* Lowercase */ + if (ask) choice = tolower(choice); + + /* Extract request */ + i = (islower(choice) ? A2I(choice) : -1); + + /* Totally Illegal */ + if ((i < 0) || (i >= num)) + { + bell(); + continue; + } + + /* Restore the screen */ + Term_load(); + + /* Display a list of spells */ + where = print_book(book, pval, o_ptr); + print_spell_desc(spell_x(book, pval, i), where); + } + + + /* Restore the screen */ + Term_load(); + character_icky = FALSE; + + /* Show choices */ + window_stuff(); +} + +/* Can it contains a schooled spell ? */ +static bool_ hook_school_can_spellable(object_type *o_ptr) +{ + u32b f1, f2, f3, f4, f5, esp; + + /* Extract object flags */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + if ((f5 & TR5_SPELL_CONTAIN) && (o_ptr->pval2 == -1)) + return TRUE; + return FALSE; +} + +/* + * Copy a spell from a bok to an object + */ +void do_cmd_copy_spell() +{ + int spell = get_school_spell("copy", 0); + int item; + object_type *o_ptr; + + if (spell == -1) return; + + /* Spells that cannot be randomly created cannot be copied */ + if (spell_type_random_type(spell_at(spell)) <= 0) + { + msg_print("This spell cannot be copied."); + return; + } + + item_tester_hook = hook_school_can_spellable; + if (!get_item(&item, "Copy to which object? ", "You have no object to copy to.", (USE_INVEN | USE_EQUIP))) return; + o_ptr = get_object(item); + + msg_print("You copy the spell!"); + o_ptr->pval2 = spell; + inven_item_describe(item); +} diff --git a/src/cmd6.c b/src/cmd6.c deleted file mode 100644 index b8a9f1df..00000000 --- a/src/cmd6.c +++ /dev/null @@ -1,7792 +0,0 @@ -/* File: cmd6.c */ - -/* Purpose: Object commands */ - -/* - * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke - * - * This software may be copied and distributed for educational, research, and - * not for profit purposes provided that this copyright and statement are - * included in all such copies. - */ - -#include "angband.h" - -#include "spell_type.h" -#include "hooks.h" - -/* - * Forward declare - */ -static bool_ activate_spell(object_type * o_ptr, byte choice); - - -/* - * General function to find an item by its name - */ -cptr get_item_hook_find_obj_what; -bool_ get_item_hook_find_obj(int *item) -{ - int i; - char buf[80]; - char buf2[100]; - - strcpy(buf, ""); - if (!get_string(get_item_hook_find_obj_what, buf, 79)) - return FALSE; - - for (i = 0; i < INVEN_TOTAL; i++) - { - object_type *o_ptr = &p_ptr->inventory[i]; - - if (!item_tester_okay(o_ptr)) continue; - - object_desc(buf2, o_ptr, -1, 0); - if (!strcmp(buf, buf2)) - { - *item = i; - return TRUE; - } - } - return FALSE; -} - - -/* - * This file includes code for eating food, drinking potions, - * reading scrolls, aiming wands, using staffs, zapping rods, - * and activating artifacts. - * - * In all cases, if the player becomes "aware" of the item's use - * by testing it, mark it as "aware" and reward some experience - * based on the object's level, always rounding up. If the player - * remains "unaware", mark that object "kind" as "tried". - * - * This code now correctly handles the unstacking of wands, staffs, - * and rods. Note the overly paranoid warning about potential pack - * overflow, which allows the player to use and drop a stacked item. - * - * In all "unstacking" scenarios, the "used" object is "carried" as if - * the player had just picked it up. In particular, this means that if - * the use of an item induces pack overflow, that item will be dropped. - * - * For simplicity, these routines induce a full "pack reorganization" - * which not only combines similar items, but also reorganizes various - * items to obey the current "sorting" method. This may require about - * 400 item comparisons, but only occasionally. - * - * There may be a BIG problem with any "effect" that can cause "changes" - * to the p_ptr->inventory. For example, a "scroll of recharging" can cause - * a wand/staff to "disappear", moving the p_ptr->inventory up. Luckily, the - * scrolls all appear BEFORE the staffs/wands, so this is not a problem. - * But, for example, a "staff of recharging" could cause MAJOR problems. - * In such a case, it will be best to either (1) "postpone" the effect - * until the end of the function, or (2) "change" the effect, say, into - * giving a staff "negative" charges, or "turning a staff into a stick". - * It seems as though a "rod of recharging" might in fact cause problems. - * The basic problem is that the act of recharging (and destroying) an - * item causes the inducer of that action to "move", causing "o_ptr" to - * no longer point at the correct item, with horrifying results. - * - * Note that food/potions/scrolls no longer use bit-flags for effects, - * but instead use the "sval" (which is also used to sort the objects). - */ - - -/* - * Determine the effects of eating a corpse. A corpse can be - * eaten whole or cut into pieces for later. - */ -static void corpse_effect(object_type *o_ptr, bool_ cutting) -{ - monster_race *r_ptr = &r_info[o_ptr->pval2]; - - /* Assume no bad effects */ - bool_ harmful = FALSE; - - byte method, effect, d_dice, d_side; - - int i, dam, idam = 0, mdam, brpow, brdam = 0; - - - /* How much of the monster's breath attack remains */ - if (o_ptr->pval <= r_ptr->weight) - { - brpow = 0; - } - else - { - brpow = (o_ptr->pval - r_ptr->weight) / 5; - if (brpow > (r_ptr->weight / 5)) brpow = r_ptr->weight / 5; - } - - if (o_ptr->weight <= 0) o_ptr->weight = 1; - if (o_ptr->pval <= 0) o_ptr->pval = 1; - - /* - * The breath is only discharged by accident or by slicing off pieces - * of meat, and only by corpses. - */ - if ((o_ptr->sval != SV_CORPSE_CORPSE) || - (rand_int(o_ptr->weight / 5) && !cutting)) brpow = 0; - - /* Immediate effects - poison, acid, fire, etc. */ - if (!cutting) - { - for (i = 0; i < 4; i++) - { - /* skip empty blow slot */ - if (!r_ptr->blow[i].method) continue; - - method = r_ptr->blow[i].method; - effect = r_ptr->blow[i].effect; - d_dice = r_ptr->blow[i].d_dice; - d_side = r_ptr->blow[i].d_side; - dam = damroll(d_dice, d_side) * o_ptr->pval / o_ptr->weight / 2; - idam = damroll(d_dice, d_side) * - ((o_ptr->weight / o_ptr->pval > 2) ? - o_ptr->weight / o_ptr->pval : 2); - mdam = maxroll(d_dice, d_side) * 2; - - /* Analyse method */ - switch (method) - { - /* Methods that are meaningless after death */ - case RBM_BITE: - case RBM_STING: - case RBM_ENGULF: - case RBM_DROOL: - case RBM_SPIT: - case RBM_GAZE: - case RBM_WAIL: - case RBM_BEG: - case RBM_INSULT: - case RBM_MOAN: - { - continue; - } - } - - /* Analyse effect */ - switch (effect) - { - /* Effects that are meaningless after death */ - case RBE_HURT: - case RBE_UN_BONUS: - case RBE_UN_POWER: - case RBE_EAT_GOLD: - case RBE_EAT_ITEM: - case RBE_EAT_FOOD: - case RBE_EAT_LITE: - case RBE_ELEC: - case RBE_COLD: - case RBE_SHATTER: - { - break; - } - - case RBE_POISON: - { - if (!(p_ptr->resist_pois || p_ptr->oppose_pois)) - { - set_poisoned(p_ptr->poisoned + dam + idam + 10); - harmful = TRUE; - } - - break; - } - - case RBE_ACID: - { - /* Total Immunity */ - if (!(p_ptr->immune_acid || (dam <= 0))) - { - /* Resist the damage */ - if (p_ptr->resist_acid) dam = (dam + 2) / 3; - if (p_ptr->oppose_acid) dam = (dam + 2) / 3; - - /* Take damage */ - take_hit(dam, "acidic food"); - harmful = TRUE; - } - else - { - set_oppose_acid(p_ptr->oppose_acid + idam); - } - - break; - } - - case RBE_FIRE: - { - /* Totally immune */ - if (p_ptr->immune_fire || (dam <= 0)) - { - /* Resist the damage */ - if (p_ptr->resist_fire) dam = (dam + 2) / 3; - if (p_ptr->oppose_fire) dam = (dam + 2) / 3; - - /* Take damage */ - take_hit(dam, "a fiery meal"); - harmful = TRUE; - } - else - { - set_oppose_fire(p_ptr->oppose_fire + idam); - } - - break; - } - - case RBE_BLIND: - { - if (!p_ptr->resist_blind) - { - set_blind(p_ptr->blind + dam * 2 + idam * 2 + 20); - } - - break; - } - - case RBE_CONFUSE: - { - if (!p_ptr->resist_conf) - { - set_confused(p_ptr->confused + dam + idam + 10); - } - if (!p_ptr->resist_chaos && rand_int(mdam - dam)) - { - set_image(p_ptr->image + dam * 10 + idam * 10 + 100); - } - - break; - } - - case RBE_HALLU: - { - if (!p_ptr->resist_chaos && rand_int(mdam - dam)) - { - set_image(p_ptr->image + dam * 10 + idam * 10 + 50); - } - - break; - } - - case RBE_TERRIFY: - { - if (!p_ptr->resist_fear) - { - set_afraid(p_ptr->afraid + dam + idam + 10); - } - - break; - } - - case RBE_PARALYZE: - { - if (!p_ptr->free_act) - { - set_paralyzed(dam + idam + 10); - } - - break; - } - - case RBE_LOSE_STR: - { - do_dec_stat(A_STR, STAT_DEC_NORMAL); - - break; - } - - case RBE_LOSE_INT: - { - do_dec_stat(A_INT, STAT_DEC_NORMAL); - - break; - } - - case RBE_LOSE_WIS: - { - do_dec_stat(A_WIS, STAT_DEC_NORMAL); - - break; - } - - case RBE_LOSE_DEX: - { - do_dec_stat(A_DEX, STAT_DEC_NORMAL); - - break; - } - - case RBE_LOSE_CON: - { - do_dec_stat(A_CON, STAT_DEC_NORMAL); - - break; - } - - case RBE_LOSE_CHR: - { - do_dec_stat(A_CHR, STAT_DEC_NORMAL); - - break; - } - - /* Don't eat Morgoth's corpse :) */ - case RBE_LOSE_ALL: - { - do_dec_stat(A_STR, STAT_DEC_NORMAL); - do_dec_stat(A_INT, STAT_DEC_NORMAL); - do_dec_stat(A_WIS, STAT_DEC_NORMAL); - do_dec_stat(A_DEX, STAT_DEC_NORMAL); - do_dec_stat(A_CON, STAT_DEC_NORMAL); - do_dec_stat(A_CHR, STAT_DEC_NORMAL); - o_ptr->pval = 1; - - break; - } - - case RBE_SANITY: - { - msg_print("You feel your sanity slipping away!"); - take_sanity_hit(dam, "eating an insane monster"); - - break; - } - - /* Unlife is bad to eat */ - case RBE_EXP_10: - { - msg_print("A black aura surrounds the corpse!"); - - if (p_ptr->hold_life && (rand_int(100) < 50)) - { - msg_print("You keep hold of your life force!"); - } - else - { - s32b d = damroll(10, 6) + - (p_ptr->exp / 100) * MON_DRAIN_LIFE; - - if (p_ptr->hold_life) - { - msg_print("You feel your life slipping away!"); - lose_exp(d / 10); - } - else - { - msg_print("You feel your life draining away!"); - lose_exp(d); - } - } - - o_ptr->pval = 1; - - break; - } - - case RBE_EXP_20: - { - msg_print("A black aura surrounds the corpse!"); - - if (p_ptr->hold_life && (rand_int(100) < 50)) - { - msg_print("You keep hold of your life force!"); - } - else - { - s32b d = damroll(20, 6) + - (p_ptr->exp / 100) * MON_DRAIN_LIFE; - - if (p_ptr->hold_life) - { - msg_print("You feel your life slipping away!"); - lose_exp(d / 10); - } - else - { - msg_print("You feel your life draining away!"); - lose_exp(d); - } - } - - o_ptr->pval = 1; - - break; - } - - case RBE_EXP_40: - { - msg_print("A black aura surrounds the corpse!"); - - if (p_ptr->hold_life && (rand_int(100) < 50)) - { - msg_print("You keep hold of your life force!"); - } - else - { - s32b d = damroll(40, 6) + - (p_ptr->exp / 100) * MON_DRAIN_LIFE; - - if (p_ptr->hold_life) - { - msg_print("You feel your life slipping away!"); - lose_exp(d / 10); - } - else - { - msg_print("You feel your life draining away!"); - lose_exp(d); - } - } - - o_ptr->pval = 1; - - break; - } - - case RBE_EXP_80: - { - msg_print("A black aura surrounds the corpse!"); - - if (p_ptr->hold_life && (rand_int(100) < 50)) - { - msg_print("You keep hold of your life force!"); - } - else - { - s32b d = damroll(80, 6) + - (p_ptr->exp / 100) * MON_DRAIN_LIFE; - - if (p_ptr->hold_life) - { - msg_print("You feel your life slipping away!"); - lose_exp(d / 10); - } - else - { - msg_print("You feel your life draining away!"); - lose_exp(d); - } - } - - o_ptr->pval = 1; - - break; - } - } - } - } /* if (!cutting) */ - - - /* - * The organ that supplies breath attacks is not - * immediately emptied upon death, although some types - * of breath have no effect. - * AMHD's make rather risky meals, and deadly snacks. - */ - - /* Acid */ - if (r_ptr->flags4 & RF4_BR_ACID && brpow > 0) - { - brdam = ((brpow / 3) > 1600 ? 1600 : (brpow / 3)); - - msg_print("You are hit by a gush of acid!"); - - /* Total Immunity */ - if (!(p_ptr->immune_acid || (brdam <= 0))) - { - /* Take damage */ - acid_dam(brdam, "a gush of acid"); - harmful = TRUE; - } - o_ptr->pval = 1; - } - else if (r_ptr->flags4 & RF4_BR_ACID) - { - set_oppose_acid(p_ptr->oppose_acid + rand_int(10) + 10); - } - - /* Electricity */ - if (r_ptr->flags4 & RF4_BR_ELEC && brpow > 0) - { - brdam = ((brpow / 3) > 1600 ? 1600 : (brpow / 3)); - - msg_print("You receive a heavy shock!"); - - /* Total Immunity */ - if (!(p_ptr->immune_elec || (brdam <= 0))) - { - /* Take damage */ - elec_dam(brdam, "an electric shock"); - harmful = TRUE; - } - o_ptr->weight = o_ptr->weight - brpow; - o_ptr->pval = o_ptr->weight; - } - else if (r_ptr->flags4 & RF4_BR_ELEC) - { - set_oppose_elec(p_ptr->oppose_elec + rand_int(10) + 10); - } - - /* Fire */ - if (r_ptr->flags4 & RF4_BR_FIRE && brpow > 0) - { - brdam = ((brpow / 3) > 1600 ? 1600 : (brpow / 3)); - - msg_print("Roaring flames engulf you!"); - - /* Total Immunity */ - if (!(p_ptr->immune_fire || (brdam <= 0))) - { - /* Take damage */ - fire_dam(brdam, "an explosion"); - harmful = TRUE; - } - o_ptr->pval = 1; - } - else if (r_ptr->flags4 & RF4_BR_FIRE) - { - set_oppose_fire(p_ptr->oppose_fire + rand_int(10) + 10); - } - - /* Cold */ - if (r_ptr->flags4 & RF4_BR_COLD && brpow > 0) - { - brdam = ((brpow / 3) > 1600 ? 1600 : (brpow / 3)); - - msg_print("You are caught in a freezing liquid!"); - - /* Total Immunity */ - if (!(p_ptr->immune_cold || (brdam <= 0))) - { - /* Take damage */ - cold_dam(brdam, "a chilling blast"); - harmful = TRUE; - } - o_ptr->weight = o_ptr->weight - brpow; - o_ptr->pval = o_ptr->weight; - } - else if (r_ptr->flags4 & RF4_BR_COLD) - { - set_oppose_cold(p_ptr->oppose_cold + rand_int(10) + 10); - } - - /* Poison */ - if (r_ptr->flags4 & RF4_BR_POIS && brpow > 0) - { - brdam = ((brpow / 3) > 800 ? 800 : (brpow / 3)); - - msg_print("You are surrounded by toxic gases!"); - - /* Resist the damage */ - if (p_ptr->resist_pois) brdam = (brdam + 2) / 3; - if (p_ptr->oppose_pois) brdam = (brdam + 2) / 3; - - if (!(p_ptr->resist_pois || p_ptr->oppose_pois)) - { - (void)set_poisoned(p_ptr->poisoned + rand_int(brdam) + 10); - } - - /* Take damage */ - take_hit(brdam, "toxic gases"); - o_ptr->weight = o_ptr->weight - brpow; - o_ptr->pval = o_ptr->weight; - harmful = TRUE; - } - - /* Nether */ - if (r_ptr->flags4 & RF4_BR_NETH && brpow > 0) - { - brdam = ((brpow / 6) > 550 ? 550 : (brpow / 6)); - - msg_print("A black aura surrounds the corpse!"); - - if (p_ptr->resist_neth) - { - brdam *= 6; - brdam /= (randint(6) + 6); - } - else - { - if (p_ptr->hold_life && (rand_int(100) < 75)) - { - msg_print("You keep hold of your life force!"); - } - else if (p_ptr->hold_life) - { - msg_print("You feel your life slipping away!"); - lose_exp(200 + (p_ptr->exp / 1000) * MON_DRAIN_LIFE); - } - else - { - msg_print("You feel your life draining away!"); - lose_exp(200 + (p_ptr->exp / 100) * MON_DRAIN_LIFE); - } - } - - /* Take damage */ - take_hit(brdam, "an unholy blast"); - harmful = TRUE; - o_ptr->weight = o_ptr->weight - brpow; - o_ptr->pval = o_ptr->weight; - } - - /* Confusion */ - if (r_ptr->flags4 & RF4_BR_CONF && brpow > 0) - { - msg_print("A strange liquid splashes on you!"); - - if (!p_ptr->resist_conf) - { - set_confused(p_ptr->confused + brdam + idam + 10); - } - o_ptr->weight = o_ptr->weight - brpow; - o_ptr->pval = o_ptr->weight; - } - - /* Chaos */ - if (r_ptr->flags4 & RF4_BR_CHAO && brpow > 0) - { - brdam = ((brpow / 6) > 600 ? 600 : (brpow / 6)); - - msg_print("A swirling cloud surrounds you!"); - - if (p_ptr->resist_chaos) - { - brdam *= 6; - brdam /= (randint(6) + 6); - } - - if (!p_ptr->resist_conf) - { - (void)set_confused(p_ptr->confused + rand_int(20) + 10); - } - - if (!p_ptr->resist_chaos) - { - (void)set_image(p_ptr->image + randint(10)); - } - - if (!p_ptr->resist_neth && !p_ptr->resist_chaos) - { - if (p_ptr->hold_life && (rand_int(100) < 75)) - { - msg_print("You keep hold of your life force!"); - } - else if (p_ptr->hold_life) - { - msg_print("You feel your life slipping away!"); - lose_exp(500 + (p_ptr->exp / 1000) * MON_DRAIN_LIFE); - } - else - { - msg_print("You feel your life draining away!"); - lose_exp(5000 + (p_ptr->exp / 100) * MON_DRAIN_LIFE); - } - } - - /* Take damage */ - take_hit(brdam, "chaotic forces"); - o_ptr->pval = 1; - } - - /* Disenchantment */ - if (r_ptr->flags4 & RF4_BR_DISE && brpow > 0) - { - brdam = ((brpow / 6) > 500 ? 500 : (brpow / 6)); - - msg_print("You are blasted by raw mana!"); - - if (p_ptr->resist_disen) - { - brdam *= 6; - brdam /= (randint(6) + 6); - } - else - { - (void)apply_disenchant(0); - } - - /* Take damage */ - take_hit(brdam, "raw mana"); - o_ptr->pval = 1; - } - - /* Plasma */ - if (r_ptr->flags4 & RF4_BR_PLAS && brpow > 0) - { - brdam = ((brpow / 6) > 150 ? 150 : (brpow / 6)); - - msg_print("Searing flames engulf the corpse!"); - - /* Resist the damage */ - if (p_ptr->resist_fire || p_ptr->oppose_fire) brdam = (brdam + 2) / 3; - - if (!p_ptr->resist_sound) - { - int k = (randint((brdam > 40) ? 35 : (brdam * 3 / 4 + 5))); - (void)set_stun(p_ptr->stun + k); - } - - /* Take damage */ - take_hit(brdam, "an explosion"); - harmful = TRUE; - o_ptr->pval = 1; - } - - /* Hack -- Jellies are immune to acid only if they are already acidic */ - if (strchr("j", r_ptr->d_char) && (r_ptr->flags3 & RF3_IM_ACID)) - { - dam = damroll(8, 8); - - /* Total Immunity */ - if (!(p_ptr->immune_acid || (dam <= 0))) - { - /* Resist the damage */ - if (p_ptr->resist_acid) dam = (dam + 2) / 3; - if (p_ptr->oppose_acid) dam = (dam + 2) / 3; - - /* Take damage */ - take_hit(dam, "acidic food"); - } - harmful = TRUE; - } - - /* - * Hack -- Jellies, kobolds, spiders, icky things, molds, and mushrooms - * are immune to poison because their body already contains - * poisonous chemicals. - */ - if (strchr("ijkmS,", r_ptr->d_char) && (r_ptr->flags3 & RF3_IM_POIS)) - { - if (!(p_ptr->resist_pois || p_ptr->oppose_pois)) - { - set_poisoned(p_ptr->poisoned + rand_int(15) + 10); - } - harmful = TRUE; - } - - /* - * Bad effects override good effects - * and hacked-up corpses lose intrinsics. - */ - if (!harmful && !cutting && (o_ptr->sval != SV_CORPSE_MEAT)) - { - if (r_ptr->flags3 & RF3_IM_ACID) - { - set_oppose_acid(p_ptr->oppose_acid + rand_int(10) + 10); - } - if (r_ptr->flags3 & RF3_IM_ELEC) - { - set_oppose_elec(p_ptr->oppose_elec + rand_int(10) + 10); - } - if (r_ptr->flags3 & RF3_IM_FIRE) - { - set_oppose_fire(p_ptr->oppose_fire + rand_int(10) + 10); - } - if (r_ptr->flags3 & RF3_IM_COLD) - { - set_oppose_cold(p_ptr->oppose_cold + rand_int(10) + 10); - } - if (r_ptr->flags3 & RF3_IM_POIS) - { - set_oppose_pois(p_ptr->oppose_pois + rand_int(10) + 10); - } - if (r_ptr->flags3 & RF3_RES_NETH) - { - set_protevil(p_ptr->protevil + rand_int(25) + 3 * r_ptr->level); - } - if (r_ptr->flags3 & RF3_RES_PLAS) - { - set_oppose_fire(p_ptr->oppose_fire + rand_int(20) + 20); - } - if (r_ptr->flags2 & RF2_SHAPECHANGER) - { - /* DGDGDG (void)set_mimic(20 , rand_int(MIMIC_VALAR)); */ - } - - if (r_ptr->flags3 & RF3_DEMON) - { - /* DGDGDG (void)set_mimic(30 , MIMIC_DEMON); */ - } - - if (r_ptr->flags3 & RF3_UNDEAD) - { - /* DGDGDG (void)set_mimic(30 , MIMIC_VAMPIRE); */ - } - - if (r_ptr->flags3 & RF3_NO_FEAR) - { - (void)set_afraid(0); - } - if (r_ptr->flags3 & RF3_NO_STUN) - { - (void)set_stun(0); - } - if (r_ptr->flags3 & RF3_NO_CONF) - { - (void)set_confused(0); - } - if (r_ptr->flags6 & RF6_S_THUNDERLORD) - { - summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_THUNDERLORD, FALSE); - } - if (r_ptr->flags6 & RF6_S_DEMON) - { - summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_DEMON, FALSE); - } - if (r_ptr->flags6 & RF6_S_KIN) - { - summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_KIN, FALSE); - } - if (r_ptr->flags6 & RF6_S_HI_DEMON) - { - summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_HI_DEMON, FALSE); - } - if (r_ptr->flags6 & RF6_S_MONSTER) - { - summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, 0, FALSE); - } - if (r_ptr->flags6 & RF6_S_MONSTERS) - { - int k; - for (k = 0; k < 8; k++) - { - summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, 0, FALSE); - } - } - if (r_ptr->flags6 & RF6_S_UNDEAD) - { - summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_UNDEAD, FALSE); - } - if (r_ptr->flags6 & RF6_S_DRAGON) - { - summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_DRAGON, FALSE); - } - if (r_ptr->flags6 & RF6_S_ANT) - { - summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_ANT, FALSE); - } - if (r_ptr->flags6 & RF6_S_SPIDER) - { - summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_SPIDER, FALSE); - } - if (r_ptr->flags6 & RF6_S_HOUND) - { - summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_HOUND, FALSE); - } - if (r_ptr->flags6 & RF6_S_HYDRA) - { - summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_HYDRA, FALSE); - } - if (r_ptr->flags6 & RF6_S_ANGEL) - { - summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_ANGEL, FALSE); - } - if (r_ptr->flags6 & RF6_S_HI_DRAGON) - { - summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_HI_DRAGON, FALSE); - } - if (r_ptr->flags6 & RF6_S_HI_UNDEAD) - { - summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_HI_UNDEAD, FALSE); - } - if (r_ptr->flags6 & RF6_S_WRAITH) - { - summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_WRAITH, FALSE); - } - if (r_ptr->flags6 & RF6_S_UNIQUE) - { - summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_UNIQUE, FALSE); - } - } -} - - -/* - * Hook to determine if an object is eatable - */ -static bool_ item_tester_hook_eatable(object_type *o_ptr) -{ - /* Foods and, well, corpses are edible */ - if ((o_ptr->tval == TV_FOOD) || (o_ptr->tval == TV_CORPSE)) return (TRUE); - - /* Assume not */ - return (FALSE); -} - - -/* - * Eat some food (from the pack or floor) - */ -void do_cmd_eat_food(void) -{ - int item, ident, lev, fval = 0; - - object_type *o_ptr; - object_type *q_ptr, forge; - - monster_race *r_ptr; - - cptr q, s; - - bool_ destroy = TRUE; - - - /* Restrict choices to food */ - item_tester_hook = item_tester_hook_eatable; - - /* Set up the extra finder */ - get_item_hook_find_obj_what = "Food full name? "; - get_item_extra_hook = get_item_hook_find_obj; - - /* Get an item */ - q = "Eat which item? "; - s = "You have nothing to eat."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EXTRA))) return; - - /* Get the item */ - o_ptr = get_object(item); - - /* Sound */ - sound(SOUND_EAT); - - - /* Take a turn */ - energy_use = 100; - - /* Identity not known yet */ - ident = FALSE; - - /* Object level */ - lev = k_info[o_ptr->k_idx].level; - - /* Scripted foods */ - hook_eat_in in = { o_ptr }; - hook_eat_out out = { FALSE }; - - if (process_hooks_ret(HOOK_EAT, "d", "(O)", o_ptr)) - { - ident = process_hooks_return[0].num; - } - else if (process_hooks_new(HOOK_EAT, &in, &out)) - { - ident = out.ident; - } - /* (not quite) Normal foods */ - else if (o_ptr->tval == TV_FOOD) - { - /* Analyze the food */ - switch (o_ptr->sval) - { - case SV_FOOD_GREAT_HEALTH: - { - p_ptr->hp_mod += 70; - msg_print("As you eat it you begin to feel your life flow getting stronger."); - ident = TRUE; - p_ptr->update |= (PU_HP); - - break; - } - - case SV_FOOD_POISON: - { - if (!(p_ptr->resist_pois || p_ptr->oppose_pois)) - { - if (set_poisoned(p_ptr->poisoned + rand_int(10) + 10)) - { - ident = TRUE; - } - } - - break; - } - - case SV_FOOD_BLINDNESS: - { - if (!p_ptr->resist_blind) - { - if (set_blind(p_ptr->blind + rand_int(200) + 200)) - { - ident = TRUE; - } - } - - break; - } - - case SV_FOOD_PARANOIA: - { - if (!p_ptr->resist_fear) - { - if (set_afraid(p_ptr->afraid + rand_int(10) + 10)) - { - ident = TRUE; - } - } - - break; - } - - case SV_FOOD_CONFUSION: - { - if (!p_ptr->resist_conf) - { - if (set_confused(p_ptr->confused + rand_int(10) + 10)) - { - ident = TRUE; - } - } - - break; - } - - case SV_FOOD_HALLUCINATION: - { - if (!p_ptr->resist_chaos) - { - if (set_image(p_ptr->image + rand_int(250) + 250)) - { - ident = TRUE; - } - } - - break; - } - - case SV_FOOD_PARALYSIS: - { - if (!p_ptr->free_act) - { - if (set_paralyzed(rand_int(10) + 10)) - { - ident = TRUE; - } - } - - break; - } - - case SV_FOOD_WEAKNESS: - { - take_hit(damroll(6, 6), "poisonous food"); - (void)do_dec_stat(A_STR, STAT_DEC_NORMAL); - - ident = TRUE; - - break; - } - - case SV_FOOD_SICKNESS: - { - take_hit(damroll(6, 6), "poisonous food"); - (void)do_dec_stat(A_CON, STAT_DEC_NORMAL); - - ident = TRUE; - - break; - } - - case SV_FOOD_STUPIDITY: - { - take_hit(damroll(8, 8), "poisonous food"); - (void)do_dec_stat(A_INT, STAT_DEC_NORMAL); - - ident = TRUE; - - break; - } - - case SV_FOOD_NAIVETY: - { - take_hit(damroll(8, 8), "poisonous food"); - (void)do_dec_stat(A_WIS, STAT_DEC_NORMAL); - - ident = TRUE; - - break; - } - - case SV_FOOD_UNHEALTH: - { - take_hit(damroll(10, 10), "poisonous food"); - (void)do_dec_stat(A_CON, STAT_DEC_NORMAL); - - ident = TRUE; - - break; - } - - case SV_FOOD_DISEASE: - { - take_hit(damroll(10, 10), "poisonous food"); - (void)do_dec_stat(A_STR, STAT_DEC_NORMAL); - - ident = TRUE; - - break; - } - - case SV_FOOD_CURE_POISON: - { - if (set_poisoned(0)) ident = TRUE; - - break; - } - - case SV_FOOD_CURE_BLINDNESS: - { - if (set_blind(0)) ident = TRUE; - - break; - } - - case SV_FOOD_CURE_PARANOIA: - { - if (set_afraid(0)) ident = TRUE; - - break; - } - - case SV_FOOD_CURE_CONFUSION: - { - if (set_confused(0)) ident = TRUE; - - break; - } - - case SV_FOOD_CURE_SERIOUS: - { - if (hp_player(damroll(4, 8))) ident = TRUE; - - break; - } - - case SV_FOOD_RESTORE_STR: - { - if (do_res_stat(A_STR, TRUE)) ident = TRUE; - - break; - } - - case SV_FOOD_RESTORE_CON: - { - if (do_res_stat(A_CON, TRUE)) ident = TRUE; - - break; - } - - case SV_FOOD_RESTORING: - { - if (do_res_stat(A_STR, TRUE)) ident = TRUE; - if (do_res_stat(A_INT, TRUE)) ident = TRUE; - if (do_res_stat(A_WIS, TRUE)) ident = TRUE; - if (do_res_stat(A_DEX, TRUE)) ident = TRUE; - if (do_res_stat(A_CON, TRUE)) ident = TRUE; - if (do_res_stat(A_CHR, TRUE)) ident = TRUE; - - break; - } - - case SV_FOOD_FORTUNE_COOKIE: - { - char rumour[80]; - - msg_print("That tastes good."); - msg_print("There is message in the cookie. It says:"); - msg_print(NULL); - - switch (randint(20)) - { - case 1: - { - get_rnd_line("chainswd.txt", rumour); - break; - } - - case 2: - { - get_rnd_line("error.txt", rumour); - break; - } - - case 3: - case 4: - case 5: - { - get_rnd_line("death.txt", rumour); - break; - } - - default: - { - get_rnd_line("rumors.txt", rumour); - break; - } - } - - msg_format("%s", rumour); - msg_print(NULL); - - ident = TRUE; - - break; - } - - - case SV_FOOD_RATION: - case SV_FOOD_BISCUIT: - case SV_FOOD_JERKY: - { - msg_print("That tastes good."); - - ident = TRUE; - - break; - } - - case SV_FOOD_SLIME_MOLD: - { - msg_print("That tastes good."); - - /* 2% chance of getting the mold power */ - if (magik(2)) - { - ADD_POWER(p_ptr->powers_mod, PWR_GROW_MOLD); - p_ptr->update |= PU_POWERS; - } - - ident = TRUE; - - break; - } - - case SV_FOOD_WAYBREAD: - { - msg_print("That tastes very good."); - (void)set_poisoned(0); - (void)hp_player(damroll(4, 8)); - set_food(PY_FOOD_MAX - 1); - - ident = TRUE; - - break; - } - - case SV_FOOD_PINT_OF_ALE: - case SV_FOOD_PINT_OF_WINE: - { - msg_print("That tastes good."); - - ident = TRUE; - - q_ptr = &forge; - object_prep(q_ptr, lookup_kind(TV_BOTTLE, 1)); - q_ptr->number = 1; - object_aware(q_ptr); - object_known(q_ptr); - q_ptr->ident |= IDENT_STOREB; - (void)inven_carry(q_ptr, FALSE); - - break; - } - - case SV_FOOD_ATHELAS: - { - msg_print("A fresh, clean essence rises, driving away wounds and poison."); - - (void)set_poisoned(0); - (void)set_stun(0); - (void)set_cut(0); - if (p_ptr->black_breath) - { - msg_print("The hold of the Black Breath on you is broken!"); - p_ptr->black_breath = FALSE; - } - - ident = TRUE; - - break; - } - } - } - - /* Corpses... */ - else - { - r_ptr = &r_info[o_ptr->pval2]; - - /* Analyse the corpse */ - switch (o_ptr->sval) - { - case SV_CORPSE_CORPSE: - { - bool_ no_meat = FALSE; - - /* Not all is edible. Apologies if messy. */ - - /* Check weight -- they have to have some meat left */ - if (r_ptr->flags9 & RF9_DROP_SKELETON) - { - if (o_ptr->weight <= (r_ptr->weight * 3) / 5) - { - no_meat = TRUE; - } - } - - /* Non-skeletons are naturally have more allowances */ - else - { - if (o_ptr->weight <= (r_ptr->weight * 7) / 20) - { - no_meat = TRUE; - } - } - - /* Nothing left to eat */ - if (no_meat) - { - msg_print("There is not enough meat."); - return; - } - - - /* Check freshness */ - if (!o_ptr->timeout) msg_print("Ugh! Raw meat!"); - else msg_print("That tastes good."); - - - /* A pound of raw meat */ - o_ptr->pval -= 10; - o_ptr->weight -= 10; - - /* Corpses still have meat on them */ - destroy = FALSE; - - ident = TRUE; - - break; - } - - case SV_CORPSE_HEAD: - { - msg_print("You feel rather sick."); - - /* A pound of raw meat */ - o_ptr->pval -= 10; - o_ptr->weight -= 10; - - /* Corpses still have meat on them */ - destroy = FALSE; - - ident = TRUE; - - break; - } - - case SV_CORPSE_MEAT: - { - /* Just meat */ - if (!o_ptr->timeout) msg_print("You quickly swallow the meat."); - else msg_print("That tastes good."); - - ident = TRUE; - - /* Those darn microorganisms */ - if (!o_ptr->timeout && (o_ptr->weight > o_ptr->pval) && - !(p_ptr->resist_pois || p_ptr->oppose_pois)) - { - set_poisoned(p_ptr->poisoned + rand_int(o_ptr->weight - o_ptr->pval) + - (o_ptr->weight - o_ptr->pval)); - } - - break; - } - } - - corpse_effect(o_ptr, FALSE); - - /* Less nutritious than food rations, but much more of it. */ - fval = (o_ptr->timeout) ? 2000 : 2500; - - /* Those darn microorganisms */ - if (!o_ptr->timeout && (o_ptr->weight - o_ptr->pval > 10) && - !(p_ptr->resist_pois || p_ptr->oppose_pois)) - { - set_poisoned(p_ptr->poisoned + rand_int(o_ptr->weight - o_ptr->pval) + - (o_ptr->weight - o_ptr->pval)); - } - - /* Partially cured */ - if (o_ptr->weight > o_ptr->timeout) - { - /* Adjust the "timeout" without overflowing */ - o_ptr->timeout = (o_ptr->timeout * ((100 * o_ptr->timeout) / o_ptr->weight)) / 100; - } - } - - - /* Combine / Reorder the pack (later) */ - p_ptr->notice |= (PN_COMBINE | PN_REORDER); - - /* We have tried it */ - object_tried(o_ptr); - - /* The player is now aware of the object */ - if (ident && !object_aware_p(o_ptr)) - { - object_aware(o_ptr); - gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev); - } - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - - if (!fval) fval = o_ptr->pval; - - /* Food can feed the player, in a different ways */ - - /* Vampires */ - if ((PRACE_FLAG(PR1_VAMPIRE)) || (p_ptr->mimic_form == resolve_mimic_name("Vampire"))) - { - /* Reduced nutritional benefit */ - /* (void)set_food(p_ptr->food + (fval / 10)); -- No more */ - msg_print("Mere victuals hold scant sustenance for a being such as yourself."); - - /* Hungry */ - if (p_ptr->food < PY_FOOD_ALERT) - { - msg_print("Your hunger can only be satisfied with fresh blood!"); - } - } - - else if (PRACE_FLAG(PR1_NO_FOOD)) - { - if (PRACE_FLAG(PR1_UNDEAD)) - { - msg_print("The food of mortals is poor sustenance for you."); - } - else - { - msg_print("Food is poor sustenance for you."); - } - set_food(p_ptr->food + ((fval) / 40)); - } - - /* Those living in fresh */ - else - { - (void)set_food(p_ptr->food + fval); - } - - - /* Destroy food? */ - if (destroy) - { - inc_stack_size(item, -1); - } -} - - -/* - * Cut a corpse up for convenient storage - */ -void do_cmd_cut_corpse(void) -{ - int item, meat = 0, not_meat = 0; - - object_type *o_ptr; - - object_type *i_ptr; - - object_type object_type_body; - - monster_race *r_ptr; - - cptr q, s; - - - /* Restrict choices to corpses */ - item_tester_tval = TV_CORPSE; - - /* Get an item */ - q = "Hack up which corpse? "; - s = "You have no corpses."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - /* Get the item */ - o_ptr = get_object(item); - - r_ptr = &r_info[o_ptr->pval2]; - - if ((o_ptr->sval != SV_CORPSE_CORPSE) && (o_ptr->sval != SV_CORPSE_HEAD)) - { - msg_print ("You cannot split that."); - return; - } - - switch (o_ptr->sval) - { - case SV_CORPSE_CORPSE: - { - if (r_ptr->flags9 & RF9_DROP_SKELETON) - { - not_meat = (r_ptr->weight * 3) / 5; - } - else - { - not_meat = (r_ptr->weight * 7) / 20; - } - meat = r_ptr->weight + r_ptr->weight / 10 - not_meat; - - break; - } - - case SV_CORPSE_HEAD: - { - not_meat = r_ptr->weight / 150; - meat = r_ptr->weight / 30 + r_ptr->weight / 300 - not_meat; - - break; - } - } - - if ((o_ptr->weight <= not_meat) || (meat < 10)) - { - msg_print("There is not enough meat."); - return; - } - - /* Hacking 10 pounds off */ - if (meat > 100) meat = 100; - - /* Take a turn */ - energy_use = 100; - - o_ptr->pval -= meat; - o_ptr->weight -= meat; - - msg_print("You hack some meat off the corpse."); - - corpse_effect(o_ptr, TRUE); - - /* Get local object */ - i_ptr = &object_type_body; - - /* Make some meat */ - object_prep(i_ptr, lookup_kind(TV_CORPSE, SV_CORPSE_MEAT)); - - i_ptr->number = meat / 10; - i_ptr->pval2 = o_ptr->pval2; - - /* Length of time before decay */ - i_ptr->pval = 1000 + rand_int(1000); - - if (inven_carry_okay(i_ptr)) - { - inven_carry(i_ptr, TRUE); - } - else - { - drop_near(i_ptr, 0, p_ptr->py, p_ptr->px); - } -} - - -/* - * Use a potion to cure some meat - * - * Salt water works well. - */ -void do_cmd_cure_meat(void) -{ - int item, num, cure; - - object_type *o_ptr; - - object_type *i_ptr; - - cptr q, s; - - - /* Restrict choices to corpses */ - item_tester_tval = TV_CORPSE; - item_tester_hook = item_tester_hook_eatable; - - /* Get some meat */ - q = "Cure which meat? "; - s = "You have no meat to cure."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - /* Get the item */ - o_ptr = get_object(item); - - /* Restrict choices to potions */ - item_tester_tval = TV_POTION; - - /* Get a potion */ - q = "Use which potion? "; - s = "You have no potions to use."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - /* Get the item */ - i_ptr = get_object(item); - - if (i_ptr->number > 1) - { - /* Get a number */ - get_count(1, i_ptr->number); - - /* Save it */ - num = command_arg; - } - else - { - num = 1; - } - - if (num == 0) return; - - /* Take a turn */ - energy_use = 100; - - q = "You soak the meat."; - s = "You soak the meat."; - - switch (i_ptr->sval) - { - case SV_POTION_SALT_WATER: - { - q = "You salt the meat."; - cure = 200 * num; - - break; - } - - case SV_POTION_POISON: - { - q = "You poison the meat."; - cure = 0; - o_ptr->pval /= 2; - if (o_ptr->pval > o_ptr->weight) o_ptr->pval = o_ptr->weight; - - break; - } - - case SV_POTION_CONFUSION: - { - cure = 80 * num; - - break; - } - - case SV_POTION_SLOW_POISON: - { - cure = 20 * num; - - break; - } - - case SV_POTION_CURE_POISON: - { - cure = 45 * num; - - break; - } - - case SV_POTION_DEATH: - { - q = "You ruin the meat."; - cure = 0; - o_ptr->pval /= 10; - if (o_ptr->pval > o_ptr->weight) o_ptr->pval = o_ptr->weight / 2; - - break; - } - - default: - { - cure = 0; - - break; - } - } - - /* Message */ - if (object_known_p(i_ptr)) msg_print(q); - else msg_print(s); - - /* The meat is already spoiling */ - if (((o_ptr->sval == SV_CORPSE_MEAT) && (o_ptr->weight > o_ptr->pval)) || - (o_ptr->weight - o_ptr->pval > 10)) - { - cure = (cure * o_ptr->pval) / (o_ptr->weight * 20); - } - - /* Cure the meat */ - o_ptr->timeout += cure / o_ptr->number; - - if (o_ptr->timeout > o_ptr->pval) o_ptr->timeout = o_ptr->pval; - - /* Use up the potions */ - inc_stack_size(item, -num); -} - - -/* - * Hook to determine if an object is quaffable - */ -static bool_ item_tester_hook_quaffable(object_type *o_ptr) -{ - if ((o_ptr->tval == TV_POTION) || (o_ptr->tval == TV_POTION2)) return (TRUE); - - /* Assume not */ - return (FALSE); -} - - -static bool_ quaff_potion(int tval, int sval, int pval, int pval2) -{ - int ident = FALSE; - - - /* "Traditional" potions */ - if (tval == TV_POTION) - { - switch (sval) - { - case SV_POTION_WATER: - case SV_POTION_APPLE_JUICE: - case SV_POTION_SLIME_MOLD: - { - msg_print("You feel less thirsty."); - ident = TRUE; - - break; - } - - case SV_POTION_SLOWNESS: - { - if (set_slow(p_ptr->slow + randint(25) + 15)) ident = TRUE; - - break; - } - - case SV_POTION_SALT_WATER: - { - msg_print("The potion makes you vomit!"); - (void)set_food(PY_FOOD_STARVE - 1); - (void)set_poisoned(0); - (void)set_paralyzed(4); - ident = TRUE; - - break; - } - - case SV_POTION_POISON: - { - if (!(p_ptr->resist_pois || p_ptr->oppose_pois)) - { - if (set_poisoned(p_ptr->poisoned + rand_int(15) + 10)) - { - ident = TRUE; - } - } - - break; - } - - case SV_POTION_BLINDNESS: - { - if (!p_ptr->resist_blind) - { - if (set_blind(p_ptr->blind + rand_int(100) + 100)) - { - ident = TRUE; - } - } - - break; - } - - /* Booze */ - case SV_POTION_CONFUSION: - { - if (!((p_ptr->resist_conf) || (p_ptr->resist_chaos))) - { - if (set_confused(p_ptr->confused + rand_int(20) + 15)) - { - ident = TRUE; - } - if (randint(2) == 1) - { - if (set_image(p_ptr->image + rand_int(150) + 150)) - { - ident = TRUE; - } - } - if (randint(13) == 1) - { - ident = TRUE; - if (randint(3) == 1) lose_all_info(); - else wiz_dark(); - teleport_player(100); - wiz_dark(); - msg_print("You wake up elsewhere with a sore head..."); - msg_print("You can't remember a thing, or how you got here!"); - } - } - - break; - } - - case SV_POTION_SLEEP: - { - if (!p_ptr->free_act) - { - if (set_paralyzed(rand_int(4) + 4)) - { - ident = TRUE; - } - } - - break; - } - - case SV_POTION_LOSE_MEMORIES: - { - if (!p_ptr->hold_life && (p_ptr->exp > 0)) - { - msg_print("You feel your memories fade."); - lose_exp(p_ptr->exp / 4); - ident = TRUE; - } - - break; - } - - case SV_POTION_RUINATION: - { - msg_print("Your nerves and muscles feel weak and lifeless!"); - take_hit(damroll(10, 10), "a potion of Ruination"); - (void)dec_stat(A_DEX, 25, TRUE); - (void)dec_stat(A_WIS, 25, TRUE); - (void)dec_stat(A_CON, 25, TRUE); - (void)dec_stat(A_STR, 25, TRUE); - (void)dec_stat(A_CHR, 25, TRUE); - (void)dec_stat(A_INT, 25, TRUE); - ident = TRUE; - - break; - } - - case SV_POTION_DEC_STR: - { - if (do_dec_stat(A_STR, STAT_DEC_NORMAL)) ident = TRUE; - - break; - } - - case SV_POTION_DEC_INT: - { - if (do_dec_stat(A_INT, STAT_DEC_NORMAL)) ident = TRUE; - - break; - } - - case SV_POTION_DEC_WIS: - { - if (do_dec_stat(A_WIS, STAT_DEC_NORMAL)) ident = TRUE; - - break; - } - - case SV_POTION_DEC_DEX: - { - if (do_dec_stat(A_DEX, STAT_DEC_NORMAL)) ident = TRUE; - - break; - } - - case SV_POTION_DEC_CON: - { - if (do_dec_stat(A_CON, STAT_DEC_NORMAL)) ident = TRUE; - - break; - } - - case SV_POTION_DEC_CHR: - { - if (do_dec_stat(A_CHR, STAT_DEC_NORMAL)) ident = TRUE; - - break; - } - - case SV_POTION_DETONATIONS: - { - msg_print("Massive explosions rupture your body!"); - take_hit(damroll(50, 20), "a potion of Detonation"); - (void)set_stun(p_ptr->stun + 75); - (void)set_cut(p_ptr->cut + 5000); - ident = TRUE; - - break; - } - - case SV_POTION_DEATH: - { - msg_print("A feeling of Death flows through your body."); - take_hit(5000, "a potion of Death"); - ident = TRUE; - - break; - } - - case SV_POTION_INFRAVISION: - { - if (set_tim_infra(p_ptr->tim_infra + 100 + randint(100))) - { - ident = TRUE; - } - - break; - } - - case SV_POTION_DETECT_INVIS: - { - if (set_tim_invis(p_ptr->tim_invis + 12 + randint(12))) - { - ident = TRUE; - } - - break; - } - - case SV_POTION_SLOW_POISON: - { - if (set_poisoned(p_ptr->poisoned / 2)) ident = TRUE; - - break; - } - - case SV_POTION_CURE_POISON: - { - if (set_poisoned(0)) ident = TRUE; - - break; - } - - case SV_POTION_BOLDNESS: - { - if (set_afraid(0)) ident = TRUE; - - break; - } - - case SV_POTION_SPEED: - { - if (!p_ptr->fast) - { - if (set_fast(randint(25) + 15, 10)) ident = TRUE; - } - else - { - (void)set_fast(p_ptr->fast + 5, 10); - } - - break; - } - - case SV_POTION_RESIST_HEAT: - { - if (set_oppose_fire(p_ptr->oppose_fire + randint(10) + 10)) - { - ident = TRUE; - } - - break; - } - - case SV_POTION_RESIST_COLD: - { - if (set_oppose_cold(p_ptr->oppose_cold + randint(10) + 10)) - { - ident = TRUE; - } - - break; - } - - case SV_POTION_HEROISM: - { - if (set_afraid(0)) ident = TRUE; - if (set_hero(p_ptr->hero + randint(25) + 25)) ident = TRUE; - if (hp_player(10)) ident = TRUE; - - break; - } - - case SV_POTION_BESERK_STRENGTH: - { - if (set_afraid(0)) ident = TRUE; - if (set_shero(p_ptr->shero + randint(25) + 25)) ident = TRUE; - if (hp_player(30)) ident = TRUE; - - break; - } - - case SV_POTION_CURE_LIGHT: - { - if (hp_player(damroll(2, 8))) ident = TRUE; - if (set_blind(0)) ident = TRUE; - if (set_cut(p_ptr->cut - 10)) ident = TRUE; - - break; - } - - case SV_POTION_CURE_SERIOUS: - { - if (hp_player(damroll(4, 8))) ident = TRUE; - if (set_blind(0)) ident = TRUE; - if (set_confused(0)) ident = TRUE; - if (set_cut((p_ptr->cut / 2) - 50)) ident = TRUE; - - break; - } - - case SV_POTION_CURE_CRITICAL: - { - if (hp_player(damroll(6, 8))) ident = TRUE; - if (set_blind(0)) ident = TRUE; - if (set_confused(0)) ident = TRUE; - if (set_poisoned(0)) ident = TRUE; - if (set_stun(0)) ident = TRUE; - if (set_cut(0)) ident = TRUE; - - break; - } - - case SV_POTION_HEALING: - { - if (hp_player(300)) ident = TRUE; - if (set_blind(0)) ident = TRUE; - if (set_confused(0)) ident = TRUE; - if (set_poisoned(0)) ident = TRUE; - if (set_stun(0)) ident = TRUE; - if (set_cut(0)) ident = TRUE; - - break; - } - - case SV_POTION_STAR_HEALING: - { - if (hp_player(1200)) ident = TRUE; - if (set_blind(0)) ident = TRUE; - if (set_confused(0)) ident = TRUE; - if (set_poisoned(0)) ident = TRUE; - if (set_stun(0)) ident = TRUE; - if (set_cut(0)) ident = TRUE; - - break; - } - - case SV_POTION_LIFE: - { - msg_print("You feel life flow through your body!"); - restore_level(); - hp_player(5000); - (void)set_poisoned(0); - (void)set_blind(0); - (void)set_confused(0); - (void)set_image(0); - (void)set_stun(0); - (void)set_cut(0); - (void)do_res_stat(A_STR, TRUE); - (void)do_res_stat(A_CON, TRUE); - (void)do_res_stat(A_DEX, TRUE); - (void)do_res_stat(A_WIS, TRUE); - (void)do_res_stat(A_INT, TRUE); - (void)do_res_stat(A_CHR, TRUE); - if (p_ptr->black_breath) - { - msg_print("The hold of the Black Breath on you is broken!"); - } - p_ptr->black_breath = FALSE; - ident = TRUE; - - break; - } - - case SV_POTION_RESTORE_MANA: - { - if (p_ptr->csp < p_ptr->msp) - { - p_ptr->csp = p_ptr->msp; - p_ptr->csp_frac = 0; - msg_print("Your feel your head clear."); - p_ptr->redraw |= (PR_MANA); - p_ptr->window |= (PW_PLAYER); - ident = TRUE; - } - - break; - } - - case SV_POTION_RESTORE_EXP: - { - if (restore_level()) ident = TRUE; - - break; - } - - case SV_POTION_RES_STR: - { - if (do_res_stat(A_STR, TRUE)) ident = TRUE; - - break; - } - - case SV_POTION_RES_INT: - { - if (do_res_stat(A_INT, TRUE)) ident = TRUE; - - break; - } - - case SV_POTION_RES_WIS: - { - if (do_res_stat(A_WIS, TRUE)) ident = TRUE; - - break; - } - - case SV_POTION_RES_DEX: - { - if (do_res_stat(A_DEX, TRUE)) ident = TRUE; - - break; - } - - case SV_POTION_RES_CON: - { - if (do_res_stat(A_CON, TRUE)) ident = TRUE; - - break; - } - - case SV_POTION_RES_CHR: - { - if (do_res_stat(A_CHR, TRUE)) ident = TRUE; - - break; - } - - case SV_POTION_INC_STR: - { - if (do_inc_stat(A_STR)) ident = TRUE; - - break; - } - - case SV_POTION_INC_INT: - { - if (do_inc_stat(A_INT)) ident = TRUE; - - break; - } - - case SV_POTION_INC_WIS: - { - if (do_inc_stat(A_WIS)) ident = TRUE; - - break; - } - - case SV_POTION_INC_DEX: - { - if (do_inc_stat(A_DEX)) ident = TRUE; - - break; - } - - case SV_POTION_INC_CON: - { - if (do_inc_stat(A_CON)) ident = TRUE; - - break; - } - - case SV_POTION_INC_CHR: - { - if (do_inc_stat(A_CHR)) ident = TRUE; - - break; - } - - case SV_POTION_AUGMENTATION: - { - if (do_inc_stat(A_STR)) ident = TRUE; - if (do_inc_stat(A_INT)) ident = TRUE; - if (do_inc_stat(A_WIS)) ident = TRUE; - if (do_inc_stat(A_DEX)) ident = TRUE; - if (do_inc_stat(A_CON)) ident = TRUE; - if (do_inc_stat(A_CHR)) ident = TRUE; - - break; - } - - case SV_POTION_ENLIGHTENMENT: - { - msg_print("An image of your surroundings forms in your mind..."); - wiz_lite(); - ident = TRUE; - - break; - } - - case SV_POTION_STAR_ENLIGHTENMENT: - { - msg_print("You begin to feel more enlightened..."); - msg_print(NULL); - wiz_lite_extra(); - (void)do_inc_stat(A_INT); - (void)do_inc_stat(A_WIS); - (void)detect_traps(DEFAULT_RADIUS); - (void)detect_doors(DEFAULT_RADIUS); - (void)detect_stairs(DEFAULT_RADIUS); - (void)detect_treasure(DEFAULT_RADIUS); - (void)detect_objects_gold(DEFAULT_RADIUS); - (void)detect_objects_normal(DEFAULT_RADIUS); - identify_pack(); - self_knowledge(NULL); - ident = TRUE; - - break; - } - - case SV_POTION_SELF_KNOWLEDGE: - { - msg_print("You begin to know yourself a little better..."); - msg_print(NULL); - self_knowledge(NULL); - ident = TRUE; - - break; - } - - case SV_POTION_EXPERIENCE: - { - if (p_ptr->exp < PY_MAX_EXP) - { - msg_print("You feel more experienced."); - gain_exp(100000L); - ident = TRUE; - } - - break; - } - - case SV_POTION_RESISTANCE: - { - (void)set_oppose_acid(p_ptr->oppose_acid + randint(20) + 20); - (void)set_oppose_elec(p_ptr->oppose_elec + randint(20) + 20); - (void)set_oppose_fire(p_ptr->oppose_fire + randint(20) + 20); - (void)set_oppose_cold(p_ptr->oppose_cold + randint(20) + 20); - (void)set_oppose_pois(p_ptr->oppose_pois + randint(20) + 20); - ident = TRUE; - - break; - } - - case SV_POTION_CURING: - { - if (hp_player(50)) ident = TRUE; - if (set_blind(0)) ident = TRUE; - if (set_poisoned(0)) ident = TRUE; - if (set_confused(0)) ident = TRUE; - if (set_stun(0)) ident = TRUE; - if (set_cut(0)) ident = TRUE; - if (set_image(0)) ident = TRUE; - if (heal_insanity(50)) ident = TRUE; - - break; - } - - case SV_POTION_INVULNERABILITY: - { - (void)set_invuln(p_ptr->invuln + randint(7) + 7); - ident = TRUE; - - break; - } - - case SV_POTION_NEW_LIFE: - { - do_cmd_rerate(); - ident = TRUE; - - break; - } - - case SV_POTION_BLOOD: - { - msg_print("You feel the blood of life running through your veins!"); - ident = TRUE; - p_ptr->allow_one_death++; - - break; - } - - case SV_POTION_MUTATION: - { - /* In Theme, Melkor likes players who quaff - potions of corruption. */ - if (game_module_idx == MODULE_THEME) - { - GOD(GOD_MELKOR) - { - msg_print("Your quaffing of this potion pleases Melkor!"); - set_grace(p_ptr->grace + 2); - } - } - - msg_print("You feel the dark corruptions of Morgoth coming over you!"); - gain_random_corruption(); - ident = TRUE; - break; - } - - case SV_POTION_INVIS: - { - int t = 30 + randint(30); - - if (set_invis(p_ptr->tim_invis + t, 35)) - { - ident = TRUE; - } - set_tim_invis(p_ptr->tim_invis + t); - - break; - } - - case SV_POTION_LEARNING: - { - p_ptr->skill_points += rand_range(4, 10 + luck( -4, 4)); - cmsg_format(TERM_L_GREEN, "You can increase %d more skills.", p_ptr->skill_points); - - break; - } - - default: - { - break; - } - } - } - - /* "Duplicate" potions */ - else - { - switch (sval) - { - case SV_POTION2_MIMIC: - { - if (!p_ptr->mimic_form) - { - s32b time = get_mimic_random_duration(pval2); - - set_mimic(time, pval2, (p_ptr->lev * 2) / 3); - - /* Redraw title */ - p_ptr->redraw |= (PR_TITLE); - - /* Recalculate bonuses */ - p_ptr->update |= (PU_BONUS); - - ident = TRUE; - } - - break; - } - - case SV_POTION2_CURE_LIGHT_SANITY: - { - if (heal_insanity(damroll(4, 8))) ident = TRUE; - - break; - } - - case SV_POTION2_CURE_SERIOUS_SANITY: - { - if (heal_insanity(damroll(8, 8))) ident = TRUE; - - break; - } - - case SV_POTION2_CURE_CRITICAL_SANITY: - { - if (heal_insanity(damroll(12, 8))) ident = TRUE; - - break; - } - - case SV_POTION2_CURE_SANITY: - { - if (heal_insanity(damroll(10, 100))) ident = TRUE; - - break; - } - - default: - { - break; - } - } - } - - return (ident); -} - - -/* - * Quaff a potion (from the pack or the floor) - */ -void do_cmd_quaff_potion(void) -{ - int item, ident, lev; - - object_type *o_ptr; - - object_type *q_ptr, forge; - - cptr q, s; - - - /* Restrict choices to potions */ - item_tester_hook = item_tester_hook_quaffable; - - /* Set up the extra finder */ - get_item_hook_find_obj_what = "Potion full name? "; - get_item_extra_hook = get_item_hook_find_obj; - - /* Get an item */ - q = "Quaff which potion? "; - s = "You have no potions to quaff."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EXTRA))) return; - - /* Get the item */ - o_ptr = get_object(item); - - - /* Sound */ - sound(SOUND_QUAFF); - - - /* Take a turn */ - energy_use = 100; - - /* Not identified yet */ - ident = FALSE; - - /* Object level */ - lev = k_info[o_ptr->k_idx].level; - - /* Demon Breath corruption can spoil potions. */ - if (player_has_corruption(CORRUPT_DEMON_BREATH) && magik(9)) - { - msg_print("Your demon breath spoils the potion!"); - ident = FALSE; - } - else - { - /* Normal potion handling */ - ident = quaff_potion(o_ptr->tval, o_ptr->sval, o_ptr->pval, o_ptr->pval2); - } - - /* Combine / Reorder the pack (later) */ - p_ptr->notice |= (PN_COMBINE | PN_REORDER); - - /* The item has been tried */ - object_tried(o_ptr); - - /* An identification was made */ - if (ident && !object_aware_p(o_ptr)) - { - object_aware(o_ptr); - gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev); - } - - if (get_skill(SKILL_ALCHEMY)) - { - if (item >= 0) - { - q_ptr = &forge; - object_prep(q_ptr, lookup_kind(TV_BOTTLE, 1)); - q_ptr->number = 1; - object_aware(q_ptr); - object_known(q_ptr); - - q_ptr->ident |= IDENT_STOREB; - - (void)inven_carry(q_ptr, FALSE); - } - } - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - - - /* Potions can feed the player */ - (void)set_food(p_ptr->food + o_ptr->pval); - - - /* Destroy potion */ - inc_stack_size(item, -1); -} - - -/* - * Drink from a fountain - */ -void do_cmd_drink_fountain(void) -{ - cave_type *c_ptr = &cave[p_ptr->py][p_ptr->px]; - - bool_ ident; - - int tval, sval, pval = 0; - - int i; - - char ch; - - - /* Is the fountain empty? */ - if (c_ptr->special2 <= 0) - { - msg_print("The fountain is dried out."); - return; - } - - /* We quaff or we fill ? */ - if (!get_com("Do you want to [Q]uaff or [F]ill from the fountain? ", &ch)) - { - return; - } - - if ((ch == 'F') || (ch == 'f')) - { - do_cmd_fill_bottle(); - - return; - } - - else if ((ch == 'Q') || (ch == 'q')) - { - if (c_ptr->special <= SV_POTION_LAST) - { - tval = TV_POTION; - sval = c_ptr->special; - } - else - { - tval = TV_POTION2; - sval = c_ptr->special - SV_POTION_LAST; - } - - for (i = 0; i < max_k_idx; i++) - { - object_kind *k_ptr = &k_info[i]; - - if (k_ptr->tval != tval) continue; - if (k_ptr->sval != sval) continue; - - pval = k_ptr->pval; - - break; - } - - ident = quaff_potion(tval, sval, pval, 0); - - c_ptr->special2--; - - if (c_ptr->special2 <= 0) - { - cave_set_feat(p_ptr->py, p_ptr->px, FEAT_EMPTY_FOUNTAIN); - } - - if (ident) c_ptr->info |= CAVE_IDNT; - } -} - - -/* - * Fill an empty bottle - */ -void do_cmd_fill_bottle(void) -{ - cave_type *c_ptr = &cave[p_ptr->py][p_ptr->px]; - - int tval, sval, item, amt = 1; - - object_type *q_ptr, *o_ptr, forge; - - cptr q, s; - - /* Is the fountain empty? */ - /* - * This check is redundant as it is done in do_cmd_drink_fountain() - * but I keep this because someone might want to call this directly. - * -- Kusunose - */ - if (c_ptr->special2 <= 0) - { - msg_print("The fountain has dried up."); - return; - } - - /* Determine the tval/sval of the potion */ - if (c_ptr->special <= SV_POTION_LAST) - { - tval = TV_POTION; - sval = c_ptr->special; - } - else - { - tval = TV_POTION2; - sval = c_ptr->special - SV_POTION_LAST; - } - - /* Restrict choices to bottles */ - item_tester_tval = TV_BOTTLE; - - /* Get an item */ - q = "Fill which bottle? "; - s = "You have no bottles to fill."; - if (!get_item(&item, q, s, (USE_INVEN))) return; - o_ptr = &p_ptr->inventory[item]; - - /* Find out how many the player wants */ - if (o_ptr->number > 1) - { - /* Get a quantity */ - amt = get_quantity(NULL, o_ptr->number); - - /* Allow user abort */ - if (amt <= 0) return; - } - - if (amt > c_ptr->special2) amt = c_ptr->special2; - - /* Destroy bottles */ - inc_stack_size(item, -amt); - - /* Create the potion */ - q_ptr = &forge; - object_prep(q_ptr, lookup_kind(tval, sval)); - q_ptr->number = amt; - - if (c_ptr->info & CAVE_IDNT) - { - object_aware(q_ptr); - object_known(q_ptr); - } - - inven_carry(q_ptr, TRUE); - - c_ptr->special2 -= amt; - - if (c_ptr->special2 <= 0) - { - cave_set_feat(p_ptr->py, p_ptr->px, FEAT_EMPTY_FOUNTAIN); - } - - return; -} - - -/* - * Curse the players armor - */ -bool_ curse_armor(void) -{ - object_type *o_ptr; - - char o_name[80]; - - - /* Curse the body armor */ - o_ptr = &p_ptr->inventory[INVEN_BODY]; - - /* Nothing to curse */ - if (!o_ptr->k_idx) return (FALSE); - - - /* Describe */ - object_desc(o_name, o_ptr, FALSE, 3); - - /* Attempt a saving throw for artifacts */ - if (((o_ptr->art_name) || artifact_p(o_ptr)) && (rand_int(100) < 50)) - { - /* Cool */ - msg_format("A terrible black aura tries to surround your armour, " - "but your %s resists the effects!", o_name); - } - - /* not artifact or failed save... */ - else - { - /* Oops */ - msg_format("A terrible black aura blasts your %s!", o_name); - - /* Blast the armor */ - o_ptr->name1 = 0; - o_ptr->name2 = EGO_BLASTED; - o_ptr->to_a = 0 - randint(5) - randint(5); - o_ptr->to_h = 0; - o_ptr->to_d = 0; - o_ptr->ac = 0; - o_ptr->dd = 0; - o_ptr->ds = 0; - o_ptr->art_flags1 = 0; - o_ptr->art_flags2 = 0; - o_ptr->art_flags3 = 0; - o_ptr->art_flags4 = 0; - - /* Curse it */ - o_ptr->ident |= (IDENT_CURSED); - - /* Recalculate bonuses */ - p_ptr->update |= (PU_BONUS); - - /* Recalculate mana */ - p_ptr->update |= (PU_MANA); - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - } - - return (TRUE); -} - - -/* - * Curse the players weapon - */ -bool_ curse_weapon(void) -{ - object_type *o_ptr; - - char o_name[80]; - - - /* Curse the weapon */ - o_ptr = &p_ptr->inventory[INVEN_WIELD]; - - /* Nothing to curse */ - if (!o_ptr->k_idx) return (FALSE); - - - /* Describe */ - object_desc(o_name, o_ptr, FALSE, 3); - - /* Attempt a saving throw */ - if ((artifact_p(o_ptr) || o_ptr->art_name) && (rand_int(100) < 50)) - { - /* Cool */ - msg_format("A terrible black aura tries to surround your weapon, " - "but your %s resists the effects!", o_name); - } - - /* not artifact or failed save... */ - else - { - /* Oops */ - msg_format("A terrible black aura blasts your %s!", o_name); - - /* Shatter the weapon */ - o_ptr->name1 = 0; - o_ptr->name2 = EGO_SHATTERED; - o_ptr->to_h = 0 - randint(5) - randint(5); - o_ptr->to_d = 0 - randint(5) - randint(5); - o_ptr->to_a = 0; - o_ptr->ac = 0; - o_ptr->dd = 0; - o_ptr->ds = 0; - o_ptr->art_flags1 = 0; - o_ptr->art_flags2 = 0; - o_ptr->art_flags3 = 0; - o_ptr->art_flags4 = 0; - - - /* Curse it */ - o_ptr->ident |= (IDENT_CURSED); - - /* Recalculate bonuses */ - p_ptr->update |= (PU_BONUS); - - /* Recalculate mana */ - p_ptr->update |= (PU_MANA); - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - } - - /* Notice */ - return (TRUE); -} - - -/* - * Hook to determine if an object is readable - */ -static bool_ item_tester_hook_readable(object_type *o_ptr) -{ - if ((o_ptr->tval == TV_SCROLL) || (o_ptr->tval == TV_PARCHMENT)) return (TRUE); - - /* Assume not */ - return (FALSE); -} - - -/* - * Read a scroll (from the pack or floor). - * - * Certain scrolls can be "aborted" without losing the scroll. These - * include scrolls with no effects but recharge or identify, which are - * cancelled before use. XXX Reading them still takes a turn, though. - */ -void do_cmd_read_scroll(void) -{ - int item, k, used_up, ident, lev; - - object_type *o_ptr; - - object_type *q_ptr, forge; - - cptr q, s; - - - /* Check some conditions */ - if (p_ptr->blind) - { - msg_print("You can't see anything."); - return; - } - - if (no_lite()) - { - msg_print("You have no light by which to read."); - return; - } - - if (p_ptr->confused) - { - msg_print("You are too confused!"); - return; - } - - - /* Restrict choices to scrolls */ - item_tester_hook = item_tester_hook_readable; - - /* Set up the extra finder */ - get_item_hook_find_obj_what = "Scroll full name? "; - get_item_extra_hook = get_item_hook_find_obj; - - /* Get an item */ - q = "Read which scroll? "; - s = "You have no scrolls to read."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EXTRA))) return; - - /* Get the item */ - o_ptr = get_object(item); - - /* Take a turn */ - energy_use = 100; - - /* Not identified yet */ - ident = FALSE; - - /* Object level */ - lev = k_info[o_ptr->k_idx].level; - - /* Assume the scroll will get used up */ - used_up = TRUE; - - /* Corruption */ - if (player_has_corruption(CORRUPT_BALROG_AURA) && magik(5)) - { - msg_print("Your demon aura burns the scroll before you read it!"); - used_up = TRUE; - ident = FALSE; - } - - /* Scrolls */ - else if (o_ptr->tval == TV_SCROLL) - { - /* Analyze the scroll */ - switch (o_ptr->sval) - { - case SV_SCROLL_MASS_RESURECTION: - { - int k; - - ident = TRUE; - msg_print("You feel the souls of the dead coming back " - "from the Halls of Mandos."); - - for (k = 0; k < max_r_idx; k++) - { - monster_race *r_ptr = &r_info[k]; - - if (r_ptr->flags1 & RF1_UNIQUE && - !(r_ptr->flags9 & RF9_SPECIAL_GENE)) - { - r_ptr->max_num = 1; - } - } - - break; - } - - case SV_SCROLL_DEINCARNATION: - { - if (!get_check("Do you really want to leave your body? " - "(beware, it'll be destroyed!) ")) - { - used_up = FALSE; - break; - } - - do_cmd_leave_body(FALSE); - - ident = TRUE; - used_up = TRUE; - - break; - } - - /* original didn't set used_up flag ??? -- pelpel */ - case SV_SCROLL_RESET_RECALL: - { - if (!reset_recall(TRUE)) - { - used_up = FALSE; - break; - } - - msg_format("Recall reset to %s at level %d.", - d_info[p_ptr->recall_dungeon].name + d_name, - max_dlv[p_ptr->recall_dungeon]); - - ident = TRUE; - used_up = TRUE; - - break; - } - - case SV_SCROLL_DIVINATION: - { - int i, count = 0; - char buf[120]; - - while (count < 1000) - { - count++; - i = rand_int(MAX_FATES); - if (!fates[i].fate) continue; - if (fates[i].know) continue; - - msg_print("A message appears on the scroll. It says:"); - msg_print(NULL); - - fate_desc(buf, i); - msg_format("%s", buf); - - msg_print(NULL); - msg_print("The scroll disappears in a puff of smoke!"); - - fates[i].know = TRUE; - ident = TRUE; - - break; - } - - break; - } - - case SV_SCROLL_DARKNESS: - { - if (!(p_ptr->resist_blind) && !(p_ptr->resist_dark)) - { - (void)set_blind(p_ptr->blind + 3 + randint(5)); - } - if (unlite_area(10, 3)) ident = TRUE; - - break; - } - - case SV_SCROLL_AGGRAVATE_MONSTER: - { - msg_print("There is a high-pitched humming noise."); - aggravate_monsters(1); - - ident = TRUE; - - break; - } - - case SV_SCROLL_CURSE_ARMOR: - { - if (curse_armor()) ident = TRUE; - - break; - } - - case SV_SCROLL_CURSE_WEAPON: - { - if (curse_weapon()) ident = TRUE; - - break; - } - - case SV_SCROLL_SUMMON_MONSTER: - { - for (k = 0; k < randint(3); k++) - { - if (summon_specific(p_ptr->py, p_ptr->px, dun_level, 0)) - { - ident = TRUE; - } - } - - break; - } - - case SV_SCROLL_SUMMON_MINE: - { - if (summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_MINE, FALSE)) - { - ident = TRUE; - } - - break; - } - - case SV_SCROLL_SUMMON_UNDEAD: - { - for (k = 0; k < randint(3); k++) - { - if (summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_UNDEAD)) - { - ident = TRUE; - } - } - - break; - } - - case SV_SCROLL_TRAP_CREATION: - { - if (trap_creation()) ident = TRUE; - - break; - } - - case SV_SCROLL_PHASE_DOOR: - { - teleport_player(10); - - ident = TRUE; - - break; - } - - case SV_SCROLL_TELEPORT: - { - teleport_player(100); - - ident = TRUE; - - break; - } - - case SV_SCROLL_TELEPORT_LEVEL: - { - (void)teleport_player_level(); - - ident = TRUE; - - break; - } - - case SV_SCROLL_WORD_OF_RECALL: - { - if ((dungeon_flags2 & DF2_ASK_LEAVE) && !get_check("Leave this unique level forever? ")) - { - used_up = FALSE; - } - else - { - recall_player(21, 15); - - ident = TRUE; - } - - break; - } - - case SV_SCROLL_IDENTIFY: - { - ident = TRUE; - - if (!ident_spell()) used_up = FALSE; - - break; - } - - case SV_SCROLL_STAR_IDENTIFY: - { - ident = TRUE; - - if (!identify_fully()) used_up = FALSE; - - break; - } - - case SV_SCROLL_REMOVE_CURSE: - { - if (remove_curse()) - { - msg_print("You feel as if someone is watching over you."); - ident = TRUE; - } - - break; - } - - case SV_SCROLL_STAR_REMOVE_CURSE: - { - remove_all_curse(); - - ident = TRUE; - - break; - } - - case SV_SCROLL_ENCHANT_ARMOR: - { - ident = TRUE; - - if (!enchant_spell(0, 0, 1, 0)) used_up = FALSE; - - break; - } - - case SV_SCROLL_ENCHANT_WEAPON_TO_HIT: - { - if (!enchant_spell(1, 0, 0, 0)) used_up = FALSE; - - ident = TRUE; - - break; - } - - case SV_SCROLL_ENCHANT_WEAPON_TO_DAM: - { - if (!enchant_spell(0, 1, 0, 0)) used_up = FALSE; - - ident = TRUE; - - break; - } - - case SV_SCROLL_ENCHANT_WEAPON_PVAL: - { - if (!enchant_spell(0, 0, 0, 1)) used_up = FALSE; - - ident = TRUE; - - break; - } - - case SV_SCROLL_STAR_ENCHANT_ARMOR: - { - if (!enchant_spell(0, 0, randint(3) + 2, 0)) used_up = FALSE; - - ident = TRUE; - - break; - } - - case SV_SCROLL_STAR_ENCHANT_WEAPON: - { - if (!enchant_spell(randint(3), randint(3), 0, 0)) used_up = FALSE; - - ident = TRUE; - - break; - } - - case SV_SCROLL_RECHARGING: - { - if (!recharge(60)) used_up = FALSE; - - ident = TRUE; - - break; - } - - case SV_SCROLL_LIGHT: - { - if (lite_area(damroll(2, 8), 2)) ident = TRUE; - - break; - } - - case SV_SCROLL_MAPPING: - { - map_area(); - - ident = TRUE; - - break; - } - - case SV_SCROLL_DETECT_GOLD: - { - if (detect_treasure(DEFAULT_RADIUS)) ident = TRUE; - if (detect_objects_gold(DEFAULT_RADIUS)) ident = TRUE; - - break; - } - - case SV_SCROLL_DETECT_ITEM: - { - if (detect_objects_normal(DEFAULT_RADIUS)) ident = TRUE; - - break; - } - - case SV_SCROLL_DETECT_TRAP: - { - if (detect_traps(DEFAULT_RADIUS)) ident = TRUE; - - break; - } - - case SV_SCROLL_DETECT_DOOR: - { - if (detect_doors(DEFAULT_RADIUS)) ident = TRUE; - if (detect_stairs(DEFAULT_RADIUS)) ident = TRUE; - - break; - } - - case SV_SCROLL_DETECT_INVIS: - { - if (detect_monsters_invis(DEFAULT_RADIUS)) ident = TRUE; - - break; - } - - case SV_SCROLL_SATISFY_HUNGER: - { - if (set_food(PY_FOOD_MAX - 1)) ident = TRUE; - - break; - } - - case SV_SCROLL_BLESSING: - { - if (set_blessed(p_ptr->blessed + randint(12) + 6)) ident = TRUE; - - break; - } - - case SV_SCROLL_HOLY_CHANT: - { - if (set_blessed(p_ptr->blessed + randint(24) + 12)) ident = TRUE; - - break; - } - - case SV_SCROLL_HOLY_PRAYER: - { - if (set_blessed(p_ptr->blessed + randint(48) + 24)) ident = TRUE; - - break; - } - - case SV_SCROLL_MONSTER_CONFUSION: - { - if (p_ptr->confusing == 0) - { - msg_print("Your hands begin to glow."); - p_ptr->confusing = TRUE; - ident = TRUE; - } - - break; - } - - case SV_SCROLL_PROTECTION_FROM_EVIL: - { - k = 3 * p_ptr->lev; - if (set_protevil(p_ptr->protevil + randint(25) + k)) ident = TRUE; - - break; - } - - case SV_SCROLL_RUNE_OF_PROTECTION: - { - warding_glyph(); - - ident = TRUE; - - break; - } - - case SV_SCROLL_TRAP_DOOR_DESTRUCTION: - { - if (destroy_doors_touch()) ident = TRUE; - - break; - } - - case SV_SCROLL_STAR_DESTRUCTION: - { - /* Prevent destruction of quest levels and town */ - if (!is_quest(dun_level) && dun_level) - { - destroy_area(p_ptr->py, p_ptr->px, 15, TRUE, FALSE); - } - else - { - msg_print("The dungeon trembles..."); - } - - ident = TRUE; - - break; - } - - case SV_SCROLL_DISPEL_UNDEAD: - { - if (dispel_undead(60)) ident = TRUE; - - break; - } - - case SV_SCROLL_GENOCIDE: - { - (void)genocide(TRUE); - - ident = TRUE; - - break; - } - - case SV_SCROLL_MASS_GENOCIDE: - { - (void)mass_genocide(TRUE); - - ident = TRUE; - - break; - } - - case SV_SCROLL_ACQUIREMENT: - { - acquirement(p_ptr->py, p_ptr->px, 1, TRUE, FALSE); - - ident = TRUE; - - break; - } - - case SV_SCROLL_STAR_ACQUIREMENT: - { - acquirement(p_ptr->py, p_ptr->px, randint(2) + 1, TRUE, FALSE); - - ident = TRUE; - - break; - } - - /* ZAngband scrolls */ - case SV_SCROLL_FIRE: - { - fire_ball(GF_FIRE, 0, 150, 4); - - /* - * Note: "Double" damage since it is centered on - * the player ... - */ - if (!p_ptr->oppose_fire && !p_ptr->resist_fire && - !p_ptr->immune_fire) - { - take_hit(50 + randint(50) + (p_ptr->sensible_fire) ? 20 : 0, - "a Scroll of Fire"); - } - - ident = TRUE; - - break; - } - - - case SV_SCROLL_ICE: - { - fire_ball(GF_ICE, 0, 175, 4); - - if (!p_ptr->oppose_cold && !p_ptr->resist_cold && - !p_ptr->immune_cold) - { - take_hit(100 + randint(100), "a Scroll of Ice"); - } - - ident = TRUE; - - break; - } - - case SV_SCROLL_CHAOS: - { - fire_ball(GF_CHAOS, 0, 222, 4); - - if (!p_ptr->resist_chaos) - { - take_hit(111 + randint(111), "a Scroll of Chaos"); - } - - ident = TRUE; - - break; - } - - case SV_SCROLL_RUMOR: - { - char rumour[80]; - - msg_print("There is message on the scroll. It says:"); - msg_print(NULL); - - /* Pick random text */ - switch (randint(20)) - { - case 1: - { - get_rnd_line("chainswd.txt", rumour); - - break; - } - - case 2: - { - get_rnd_line("error.txt", rumour); - - break; - } - - case 3: - case 4: - case 5: - { - get_rnd_line("death.txt", rumour); - - break; - } - - default: - { - get_rnd_line("rumors.txt", rumour); - - break; - } - } - - msg_format("%s", rumour); - msg_print(NULL); - - msg_print("The scroll disappears in a puff of smoke!"); - - ident = TRUE; - - break; - } - - case SV_SCROLL_ARTIFACT: - { - ident = TRUE; - - if (!artifact_scroll()) used_up = FALSE; - - break; - } - - case SV_SCROLL_STERILIZATION: - { - msg_print("A neutralising wave radiates from you!"); - set_no_breeders(randint(100) + 100); - - break; - } - - default: - { - break; - } - } - } - - /* Other readable items */ - else - { - /* Maps */ - if (o_ptr->sval >= 200) - { - int i, n; - char buf[80], fil[20]; - - strnfmt(fil, 20, "book-%d.txt", o_ptr->sval); - - n = atoi(get_line(fil, ANGBAND_DIR_FILE, buf, -1)); - - /* Parse all the fields */ - for (i = 0; i < n; i += 4) - { - /* Grab the fields */ - int x = atoi(get_line(fil, ANGBAND_DIR_FILE, buf, i + 0)); - int y = atoi(get_line(fil, ANGBAND_DIR_FILE, buf, i + 1)); - int w = atoi(get_line(fil, ANGBAND_DIR_FILE, buf, i + 2)); - int h = atoi(get_line(fil, ANGBAND_DIR_FILE, buf, i + 3)); - - reveal_wilderness_around_player(y, x, h, w); - } - } - - /* Normal parchements */ - else - { - /* Save screen */ - screen_save(); - - /* Get the filename */ - q = format("book-%d.txt", o_ptr->sval); - - /* Peruse the help file */ - (void)show_file(q, NULL, 0, 0); - - /* Load screen */ - screen_load(); - - if (o_ptr->sval >= 100) - { - inscription_info[o_ptr->sval - 100].know = TRUE; - } - - used_up = FALSE; - } - } - - - /* Combine / Reorder the pack (later) */ - p_ptr->notice |= (PN_COMBINE | PN_REORDER); - - /* The item was tried */ - object_tried(o_ptr); - - /* An identification was made */ - if (ident && !object_aware_p(o_ptr)) - { - object_aware(o_ptr); - gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev); - } - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - - - /* Hack -- allow certain scrolls to be "preserved" */ - if (!used_up) return; - - sound(SOUND_SCROLL); - - /* Destroy scroll */ - inc_stack_size(item, -1); - - if (get_skill(SKILL_ALCHEMY)) - { - if (item >= 0) - { - q_ptr = &forge; - object_prep(q_ptr, lookup_kind(TV_SCROLL, SV_SCROLL_NOTHING)); - object_aware(q_ptr); - object_known(q_ptr); - - q_ptr->ident |= IDENT_STOREB; - - (void)inven_carry(q_ptr, FALSE); - } - } -} - - - -/* Set the 'stick mode' on */ -void set_stick_mode(object_type *o_ptr) -{ - s32b bonus = o_ptr->pval3 & 0xFFFF; - s32b max = o_ptr->pval3 >> 16; - - get_level_use_stick = bonus; - get_level_max_stick = max; -} - -/* Remove 'stick mode' */ -void unset_stick_mode() -{ - get_level_use_stick = -1; - get_level_max_stick = -1; -} - - -/* - * Activate a device - */ -static void activate_stick(s16b s, bool_ *obvious, bool_ *use_charge) -{ - spell_type *spell = spell_at(s); - casting_result ret; - - assert(obvious != NULL); - assert(use_charge != NULL); - - ret = spell_type_produce_effect(spell, -1); - - switch (ret) - { - case NO_CAST: - *use_charge = FALSE; - *obvious = FALSE; - break; - case CAST_HIDDEN: - *use_charge = TRUE; - *obvious = FALSE; - break; - case CAST_OBVIOUS: - *use_charge = TRUE; - *obvious = TRUE; - break; - default: - assert(FALSE); - } -} - - -/* - * Use a staff. -RAK- - * - * One charge of one staff disappears. - * - * Hack -- staffs of identify can be "cancelled". - */ -void do_cmd_use_staff(void) -{ - int item, ident, chance; - - bool_ obvious, use_charge; - - object_type *o_ptr; - - u32b f1, f2, f3, f4, f5, esp; - - cptr q, s; - - /* No magic */ - if (p_ptr->antimagic) - { - msg_print("Your anti-magic field disrupts any magic attempts."); - return; - } - - /* Restrict choices to wands */ - item_tester_tval = TV_STAFF; - - /* Set up the extra finder */ - get_item_hook_find_obj_what = "Staff full name? "; - get_item_extra_hook = get_item_hook_find_obj; - - /* Get an item */ - q = "Use which staff? "; - s = "You have no staff to use."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EXTRA))) return; - - /* Get the item */ - o_ptr = get_object(item); - - /* Mega-Hack -- refuse to use a pile from the ground */ - if ((item < 0) && (o_ptr->number > 1)) - { - msg_print("You must first pick up the staffs."); - return; - } - - /* Enter device mode */ - set_stick_mode(o_ptr); - - /* Take a turn */ - energy_use = 100; - - /* Not identified yet */ - ident = FALSE; - - /* get the chance */ - chance = spell_chance(o_ptr->pval2); - - /* Extract object flags */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* Is it simple to use ? */ - if (f4 & TR4_EASY_USE) - { - chance /= 3; - } - - /* Give everyone a (slight) chance */ - if ((chance < USE_DEVICE) && (rand_int(USE_DEVICE - chance + 1) == 0)) - { - chance = USE_DEVICE; - } - - /* Roll for usage */ - if (magik(chance)) - { - if (flush_failure) flush(); - msg_print("You failed to use the staff properly."); - sound(SOUND_FAIL); - - /* Leave device mode */ - unset_stick_mode(); - return; - } - - /* Notice empty staffs */ - if (o_ptr->pval <= 0) - { - if (flush_failure) flush(); - msg_print("The staff has no charges left."); - o_ptr->ident |= (IDENT_EMPTY); - - /* Leave device mode */ - unset_stick_mode(); - return; - } - - - /* Sound */ - sound(SOUND_ZAP); - - - /* Analyze the staff */ - activate_stick(o_ptr->pval2, &obvious, &use_charge); - - /* Combine / Reorder the pack (later) */ - p_ptr->notice |= (PN_COMBINE | PN_REORDER); - - /* Tried the item */ - object_tried(o_ptr); - - /* An identification was made */ - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - - - /* Hack -- some uses are "free" */ - if (!use_charge) - { - /* Leave device mode */ - unset_stick_mode(); - - return; - } - - /* An identification was made */ - if (obvious) - { - object_aware(o_ptr); - } - - /* Use a single charge */ - o_ptr->pval--; - - /* XXX Hack -- unstack if necessary */ - if ((item >= 0) && (o_ptr->number > 1)) - { - object_type forge; - object_type *q_ptr; - - /* Get local object */ - q_ptr = &forge; - - /* Obtain a local object */ - object_copy(q_ptr, o_ptr); - - /* Modify quantity */ - q_ptr->number = 1; - - /* Restore the charges */ - o_ptr->pval++; - - /* Unstack the used item */ - o_ptr->number--; - item = inven_carry(q_ptr, FALSE); - - /* Message */ - msg_print("You unstack your staff."); - } - - /* Describe charges in the pack */ - if (item >= 0) - { - inven_item_charges(item); - } - - /* Describe charges on the floor */ - else - { - floor_item_charges(0 - item); - } - - /* Leave device mode */ - unset_stick_mode(); -} - - -/* - * Aim a wand (from the pack or floor). - * - * Use a single charge from a single item. - * Handle "unstacking" in a logical manner. - * - * For simplicity, you cannot use a stack of items from the - * ground. This would require too much nasty code. - * - * There are no wands which can "destroy" themselves, in the p_ptr->inventory - * or on the ground, so we can ignore this possibility. Note that this - * required giving "wand of wonder" the ability to ignore destruction - * by electric balls. - * - * All wands can be "cancelled" at the "Direction?" prompt for free. - * - * Note that the basic "bolt" wands do slightly less damage than the - * basic "bolt" rods, but the basic "ball" wands do the same damage - * as the basic "ball" rods. - */ -void do_cmd_aim_wand(void) -{ - bool_ obvious, use_charge; - - int item, ident, chance; - - object_type *o_ptr; - - cptr q, s; - - u32b f1, f2, f3, f4, f5, esp; - - - /* No magic */ - if (p_ptr->antimagic) - { - msg_print("Your anti-magic field disrupts any magic attempts."); - return; - } - - /* Restrict choices to wands */ - item_tester_tval = TV_WAND; - - /* Set up the extra finder */ - get_item_hook_find_obj_what = "Wand full name? "; - get_item_extra_hook = get_item_hook_find_obj; - - /* Get an item */ - q = "Aim which wand? "; - s = "You have no wand to aim."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EXTRA))) return; - - /* Get the item */ - o_ptr = get_object(item); - - - /* Mega-Hack -- refuse to aim a pile from the ground */ - if ((item < 0) && (o_ptr->number > 1)) - { - msg_print("You must first pick up the wands."); - return; - } - - /* Take a turn */ - energy_use = 100; - - /* Not identified yet */ - ident = FALSE; - - /* Enter device mode */ - set_stick_mode(o_ptr); - - /* get the chance */ - chance = spell_chance(o_ptr->pval2); - - /* Extract object flags */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* Is it simple to use ? */ - if (f4 & TR4_EASY_USE) - { - chance /= 3; - } - - /* Roll for usage */ - if (magik(chance)) - { - if (flush_failure) flush(); - msg_print("You failed to use the wand properly."); - sound(SOUND_FAIL); - - /* Leave device mode */ - unset_stick_mode(); - return; - } - - /* The wand is already empty! */ - if (o_ptr->pval <= 0) - { - if (flush_failure) flush(); - msg_print("The wand has no charges left."); - o_ptr->ident |= (IDENT_EMPTY); - - /* Leave device mode */ - unset_stick_mode(); - return; - } - - - /* Sound */ - sound(SOUND_ZAP); - - - /* Analyze the wand */ - activate_stick(o_ptr->pval2, &obvious, &use_charge); - - /* Combine / Reorder the pack (later) */ - p_ptr->notice |= (PN_COMBINE | PN_REORDER); - - /* Mark it as tried */ - object_tried(o_ptr); - - /* Hack -- some uses are "free" */ - if (!use_charge) - { - /* Leave device mode */ - unset_stick_mode(); - - return; - } - - /* An identification was made */ - if (obvious) - { - object_aware(o_ptr); - } - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - - - /* Use a single charge */ - o_ptr->pval--; - - /* Describe the charges in the pack */ - if (item >= 0) - { - inven_item_charges(item); - } - - /* Describe the charges on the floor */ - else - { - floor_item_charges(0 - item); - } - - /* Leave device mode */ - unset_stick_mode(); -} - - - - - - -/* - * Activate (zap) a Rod - * - * Unstack fully charged rods as needed. - * - * Hack -- rods of perception/genocide can be "cancelled" - * All rods can be cancelled at the "Direction?" prompt - */ - - -/* - * Hook to determine if an object is zapable - */ -static bool_ item_tester_hook_zapable(object_type *o_ptr) -{ - if ((o_ptr->tval == TV_ROD) || (o_ptr->tval == TV_ROD_MAIN)) return (TRUE); - - /* Assume not */ - return (FALSE); -} - - -/* - * Hook to determine if an object is attachable - */ -static bool_ item_tester_hook_attachable(object_type *o_ptr) -{ - if ((o_ptr->tval == TV_ROD_MAIN) && - (o_ptr->pval == SV_ROD_NOTHING)) return (TRUE); - - /* Assume not */ - return (FALSE); -} - - -/* - * Combine a rod and a rod tip - */ -void zap_combine_rod_tip(object_type *q_ptr, int tip_item) -{ - int item; - - object_type *o_ptr; - - cptr q, s; - - u32b f1, f2, f3, f4, f5, esp; - s32b cost; - - - /* No magic */ - if (p_ptr->antimagic) - { - msg_print("Your anti-magic field disrupts any magic attempts."); - return; - } - - /* Restrict choices to rods */ - item_tester_hook = item_tester_hook_attachable; - - /* Get an item */ - q = "Attach the rod tip with which rod? "; - s = "You have no rod to attach to."; - if (!get_item(&item, q, s, (USE_INVEN))) return; - - /* Get the item */ - o_ptr = get_object(item); - - /* Examine the rod */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* Calculate rod tip's mana cost */ - cost = q_ptr->pval; - - if (f4 & TR4_CHEAPNESS) - { - cost /= 2; - } - - /* - * The rod must have at least the same mana capacity as the - * rod tip spell needs - */ - if (o_ptr->pval2 < cost) - { - msg_print("This rod doesn't have enough mana for the rod tip."); - return; - } - - /* Attach the tip to the rod */ - o_ptr->pval = q_ptr->sval; - - /* Destroy rod tip */ - inc_stack_size(tip_item, -1); -} - - -/* - * Zap a rod, or attack a rod tip to a rod - */ -void do_cmd_zap_rod(void) -{ - int item, ident, chance, dir, lev; - - int cost; - - bool_ require_dir; - - object_type *o_ptr; - - object_kind *tip_ptr; - - u32b f1, f2, f3, f4, f5, esp; - - cptr q, s; - - /* Hack -- let perception get aborted */ - bool_ use_charge = TRUE; - - - /* No magic */ - if (p_ptr->antimagic) - { - msg_print("Your anti-magic field disrupts any magic attempts."); - return; - } - - - /* Restrict choices to rods */ - item_tester_hook = item_tester_hook_zapable; - - /* Set up the extra finder */ - get_item_hook_find_obj_what = "Rod full name? "; - get_item_extra_hook = get_item_hook_find_obj; - - /* Get an item */ - q = "Zap which rod? "; - s = "You have no rod to zap."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EXTRA))) return; - - /* Get the item */ - o_ptr = get_object(item); - - - /* "Zapping" a Rod Tip on rod of nothing will attach it */ - if (o_ptr->tval == TV_ROD) - { - if (item >= 0) - { - zap_combine_rod_tip(o_ptr, item); - return; - } - else - { - msg_print("You can't zap a rod tip that's on the floor."); - return; - } - } - - - /* Non-directed rods */ - if (o_ptr->pval < SV_ROD_MIN_DIRECTION) - { - require_dir = FALSE; - } - - /* Some rods always require direction */ - else - { - switch (o_ptr->pval) - { - case SV_ROD_DETECT_TRAP: - case SV_ROD_HAVOC: - case SV_ROD_HOME: - { - require_dir = FALSE; - break; - } - - default: - { - require_dir = TRUE; - break; - } - } - } - - /* Get a direction (unless KNOWN not to need it) */ - if (!object_aware_p(o_ptr) || require_dir) - { - /* Get a direction, allow cancel */ - if (!get_aim_dir(&dir)) return; - } - - /* Take a turn */ - energy_use = 100; - - /* Examine the rod */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - if (f4 & TR4_FAST_CAST) energy_use /= 2; - - /* Not identified yet */ - ident = FALSE; - - /* Extract the item level */ - tip_ptr = &k_info[lookup_kind(TV_ROD, o_ptr->pval)]; - lev = k_info[lookup_kind(TV_ROD, o_ptr->pval)].level; - - /* Base chance of success */ - chance = p_ptr->skill_dev; - - /* Confusion hurts skill */ - if (p_ptr->confused) chance = chance / 2; - - /* High level objects are harder */ - chance = chance - ((lev > 50) ? 50 : lev); - - if (chance <= 0) - { - chance = 1; - } - - /* Is it simple to use ? */ - if (f4 & TR4_EASY_USE) - { - chance *= 10; - } - - /* Give everyone a (slight) chance */ - if ((chance < USE_DEVICE) && (rand_int(USE_DEVICE - chance + 1) == 0)) - { - chance = USE_DEVICE; - } - - /* Roll for usage */ - if ((chance < USE_DEVICE) || (randint(chance) < USE_DEVICE)) - { - /* Flush input if necessary */ - if (flush_failure) flush(); - - /* Message */ - msg_print("You failed to use the rod properly."); - - sound(SOUND_FAIL); - - return; - } - - /* Extract mana cost */ - cost = tip_ptr->pval; - - /* "Cheapness" ego halven the cost */ - if (f4 & TR4_CHEAPNESS) cost = cost / 2; - - /* A single rod is still charging */ - if (o_ptr->timeout < cost) - { - /* Flush input if necessary */ - if (flush_failure) flush(); - - /* Message */ - msg_print("The rod does not have enough mana yet."); - - return; - } - - /* Increase the timeout by the rod kind's pval. */ - o_ptr->timeout -= cost; - - /* Sound */ - sound(SOUND_ZAP); - - /* Analyze the rod */ - switch (o_ptr->pval) - { - case SV_ROD_HOME: - { - ident = TRUE; - - do_cmd_home_trump(); - - break; - } - - case SV_ROD_DETECT_TRAP: - { - if (detect_traps(DEFAULT_RADIUS)) ident = TRUE; - - break; - } - - case SV_ROD_DETECT_DOOR: - { - if (detect_doors(DEFAULT_RADIUS)) ident = TRUE; - if (detect_stairs(DEFAULT_RADIUS)) ident = TRUE; - - break; - } - - case SV_ROD_IDENTIFY: - { - ident = TRUE; - - if (!ident_spell()) use_charge = FALSE; - - break; - } - - case SV_ROD_RECALL: - { - if ((dungeon_flags2 & DF2_ASK_LEAVE) && !get_check("Leave this unique level forever? ")) - { - use_charge = FALSE; - } - else - { - recall_player(21, 15); - - ident = TRUE; - } - - break; - } - - case SV_ROD_ILLUMINATION: - { - if (lite_area(damroll(2, 8), 2)) ident = TRUE; - - break; - } - - case SV_ROD_MAPPING: - { - map_area(); - - ident = TRUE; - - break; - } - - case SV_ROD_DETECTION: - { - detect_all(DEFAULT_RADIUS); - - ident = TRUE; - - break; - } - - case SV_ROD_PROBING: - { - probing(); - - ident = TRUE; - - break; - } - - case SV_ROD_CURING: - { - if (set_blind(0)) ident = TRUE; - if (set_poisoned(0)) ident = TRUE; - if (set_confused(0)) ident = TRUE; - if (set_stun(0)) ident = TRUE; - if (set_cut(0)) ident = TRUE; - if (set_image(0)) ident = TRUE; - - break; - } - - case SV_ROD_HEALING: - { - if (hp_player(500)) ident = TRUE; - if (set_stun(0)) ident = TRUE; - if (set_cut(0)) ident = TRUE; - - break; - } - - case SV_ROD_RESTORATION: - { - if (restore_level()) ident = TRUE; - if (do_res_stat(A_STR, TRUE)) ident = TRUE; - if (do_res_stat(A_INT, TRUE)) ident = TRUE; - if (do_res_stat(A_WIS, TRUE)) ident = TRUE; - if (do_res_stat(A_DEX, TRUE)) ident = TRUE; - if (do_res_stat(A_CON, TRUE)) ident = TRUE; - if (do_res_stat(A_CHR, TRUE)) ident = TRUE; - - break; - } - - case SV_ROD_SPEED: - { - if (!p_ptr->fast) - { - if (set_fast(randint(30) + 15, 10)) ident = TRUE; - } - else - { - (void)set_fast(p_ptr->fast + 5, 10); - } - - break; - } - - case SV_ROD_TELEPORT_AWAY: - { - if (teleport_monster(dir)) ident = TRUE; - - break; - } - - case SV_ROD_DISARMING: - { - if (disarm_trap(dir)) ident = TRUE; - - break; - } - - case SV_ROD_LITE: - { - msg_print("A line of blue shimmering light appears."); - lite_line(dir); - - ident = TRUE; - - break; - } - - case SV_ROD_SLEEP_MONSTER: - { - if (sleep_monster(dir)) ident = TRUE; - - break; - } - - case SV_ROD_SLOW_MONSTER: - { - if (slow_monster(dir)) ident = TRUE; - - break; - } - - case SV_ROD_DRAIN_LIFE: - { - if (drain_life(dir, 75)) ident = TRUE; - - break; - } - - case SV_ROD_POLYMORPH: - { - if (poly_monster(dir)) ident = TRUE; - - break; - } - - case SV_ROD_ACID_BOLT: - { - fire_bolt_or_beam(10, GF_ACID, dir, damroll(6, 8)); - - ident = TRUE; - - break; - } - - case SV_ROD_ELEC_BOLT: - { - fire_bolt_or_beam(10, GF_ELEC, dir, damroll(3, 8)); - - ident = TRUE; - - break; - } - - case SV_ROD_FIRE_BOLT: - { - fire_bolt_or_beam(10, GF_FIRE, dir, damroll(8, 8)); - - ident = TRUE; - - break; - } - - case SV_ROD_COLD_BOLT: - { - fire_bolt_or_beam(10, GF_COLD, dir, damroll(5, 8)); - - ident = TRUE; - - break; - } - - case SV_ROD_ACID_BALL: - { - fire_ball(GF_ACID, dir, 60, 2); - - ident = TRUE; - - break; - } - - case SV_ROD_ELEC_BALL: - { - fire_ball(GF_ELEC, dir, 32, 2); - - ident = TRUE; - - break; - } - - case SV_ROD_FIRE_BALL: - { - fire_ball(GF_FIRE, dir, 72, 2); - - ident = TRUE; - - break; - } - - case SV_ROD_COLD_BALL: - { - fire_ball(GF_COLD, dir, 48, 2); - - ident = TRUE; - - break; - } - - case SV_ROD_HAVOC: - { - call_chaos(); - - ident = TRUE; - - break; - } - - default: - { - process_hooks(HOOK_ZAP, "(d,d)", o_ptr->tval, o_ptr->sval); - - break; - } - } - - - /* Combine / Reorder the pack (later) */ - p_ptr->notice |= (PN_COMBINE | PN_REORDER); - - /* Tried the object */ - object_tried(o_ptr); - - /* Successfully determined the object function */ - if (ident && !object_aware_p(o_ptr)) - { - object_aware(o_ptr); - gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev); - } - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - - /* Hack -- deal with cancelled zap */ - if (!use_charge) - { - o_ptr->timeout += cost; - - return; - } -} - - - - -/* - * Hook to determine if an object is activable - */ -static bool_ item_tester_hook_activate(object_type *o_ptr) -{ - u32b f1, f2, f3, f4, f5, esp; - - - /* Not known */ - if (!object_known_p(o_ptr)) return (FALSE); - - /* Extract the flags */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* Check activation flag */ - if (f3 & (TR3_ACTIVATE)) return (TRUE); - - /* Assume not */ - return (FALSE); -} - - - -/* - * Hack -- activate the ring of power - */ -int ring_of_power() -{ - char ch = 0, p = 0; - - int plev = p_ptr->lev; - - int timeout = 0; - - - /* Select power to use */ - while (TRUE) - { - if (!get_com("[S]ummon a wraith, [R]ule the world or " - "[C]ast a powerful attack? ", &ch)) - { - return (0); - } - - if (ch == 'S' || ch == 's') - { - p = 1; - break; - } - if (ch == 'R' || ch == 'r') - { - p = 2; - break; - } - if (ch == 'C' || ch == 'c') - { - p = 3; - break; - } - } - - /* Summon a Wraith */ - if (p == 1) - { - /* Rewrite this -- pelpel */ - if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2), - (plev > 47 ? SUMMON_HI_UNDEAD_NO_UNIQUES : SUMMON_UNDEAD), - (((plev > 24) && (randint(3) == 1)) ? TRUE : FALSE))) - { - msg_print("Cold winds begin to blow around you, " - "carrying with them the stench of decay..."); - msg_print("Ancient, long-dead forms arise from the ground " - "to serve you!"); - } - timeout = 200 + rand_int(200); - } - - /* Rule the World -- only if we can really do so */ - else if (p == 2) - { - msg_print("The power of the ring destroys the world!"); - msg_print("The world changes!"); - - autosave_checkpoint(); - - /* Leaving */ - p_ptr->leaving = TRUE; - timeout = 250 + rand_int(250); - } - - /* Cast a powerful spell */ - else if (p == 3) - { - int dir; - - if (!get_aim_dir(&dir)) return (0); - - if (rand_int(3) == 0) - { - msg_print("You call the fire of Mount Doom!"); - fire_ball(GF_METEOR, dir, 600, 4); - } - else - { - msg_print("Your ring tries to take possession of your enemy's mind!"); - fire_bolt(GF_CHARM, dir, 600); - } - timeout = 300 + rand_int(300); - } - - return (timeout); -} - - - - -/* - * Enchant some bolts - */ -bool_ brand_bolts(void) -{ - int i; - - - /* Use the first acceptable bolts */ - for (i = 0; i < INVEN_PACK; i++) - { - object_type *o_ptr = &p_ptr->inventory[i]; - - /* Skip non-bolts */ - if (o_ptr->tval != TV_BOLT) continue; - - /* Skip artifacts and ego-items */ - if (o_ptr->art_name || artifact_p(o_ptr) || ego_item_p(o_ptr)) continue; - - /* Skip cursed/broken items */ - if (cursed_p(o_ptr)) continue; - - /* Randomize */ - if (rand_int(100) < 75) continue; - - /* Message */ - msg_print("Your bolts are covered in a fiery aura!"); - - /* Ego-item */ - o_ptr->name2 = EGO_FLAME; - - /* Apply the ego */ - apply_magic(o_ptr, dun_level, FALSE, FALSE, FALSE); - - /* Enchant */ - enchant(o_ptr, rand_int(3) + 4, ENCH_TOHIT | ENCH_TODAM); - - /* Notice */ - return (TRUE); - } - - /* Flush */ - if (flush_failure) flush(); - - /* Fail */ - msg_print("The fiery enchantment failed."); - - /* Notice */ - return (TRUE); -} - - -/* - * Objects in the p_ptr->inventory can now be activated, and - * SOME of those may be able to stack (ego wands or something) - * in any case, we can't know that it's impossible. *BUT* we'll - * ignore it for now, and the timeout will be set on the entire stack - * of objects. Reduces their utility, but oh well. - * - * Note that it always takes a turn to activate an object, even if - * the user hits "escape" at the "direction" prompt. - */ -void do_cmd_activate(void) -{ - int item, lev, chance; - - char ch, spell_choice; - - object_type *o_ptr; - - u32b f1, f2, f3, f4, f5, esp; - - cptr q, s; - - - /* Prepare the hook */ - item_tester_hook = item_tester_hook_activate; - - /* Get an item */ - command_wrk = USE_EQUIP; - q = "Activate which item? "; - s = "You have nothing to activate."; - if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN))) return; - - /* Get the item */ - o_ptr = get_object(item); - - /* Extract object flags */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* Wearable items have to be worn */ - if (!(f5 & TR5_ACTIVATE_NO_WIELD)) - { - if (item < INVEN_WIELD) - { - msg_print("You must wear it to activate it."); - return; - } - } - - /* Take a turn */ - energy_use = 100; - - /* Extract the item level */ - lev = k_info[o_ptr->k_idx].level; - - /* Hack -- Use artifact level instead */ - if (artifact_p(o_ptr)) - { - if (o_ptr->tval == TV_RANDART) - { - lev = random_artifacts[o_ptr->sval].level; - } - else - { - lev = a_info[o_ptr->name1].level; - } - } - - /* Base chance of success */ - chance = p_ptr->skill_dev; - - /* Confusion hurts skill */ - if (p_ptr->confused) chance = chance / 2; - - /* Hight level objects are harder */ - chance = chance - ((lev > 50) ? 50 : lev); - - if (chance <= 0) - { - chance = 1; - } - - /* Is it simple to use ? */ - if (f4 & TR4_EASY_USE) - { - chance *= 10; - } - - /* Give everyone a (slight) chance */ - if ((chance < USE_DEVICE) && (rand_int(USE_DEVICE - chance + 1) == 0)) - { - chance = USE_DEVICE; - } - - /* Roll for usage */ - if ((chance < USE_DEVICE) || (randint(chance) < USE_DEVICE)) - { - if (flush_failure) flush(); - msg_print("You failed to activate it properly."); - sound(SOUND_FAIL); - return; - } - - /* Check the recharge */ - if (o_ptr->timeout) - { - /* Mage Staff of Spells -- Have another timeout in xtra2 */ - if (is_ego_p(o_ptr, EGO_MSTAFF_SPELL) && o_ptr->xtra2) - { - msg_print("It whines, glows and fades..."); - return; - } - - /* Monster eggs */ - else if (o_ptr->tval == TV_EGG) - { - msg_print("You resume the development of the egg."); - o_ptr->timeout = 0; - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP); - - /* Success */ - return; - } - - /* Normal activatable items */ - else - { - msg_print("It whines, glows and fades..."); - return; - } - } - - - /* Activate the item */ - msg_print("You activate it..."); - - /* Sound */ - sound(SOUND_ZAP); - - /* Lua hook ? -- go first to allow lua to override */ - if (process_hooks(HOOK_ACTIVATE, "(d)", item)) - { - return; - } - - /* New mostly unified activation code - This has to be early to allow artifacts to override normal items -- neil */ - - if ( activation_aux(o_ptr, TRUE, item) == NULL ) - { - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP); - - /* Success */ - return; - } - - /* Mage Staff of Spells */ - if (is_ego_p(o_ptr, EGO_MSTAFF_SPELL)) - { - while (TRUE) - { - if (!get_com("Use Spell [1] or [2]?", &ch)) - { - return; - } - - if (ch == '1') - { - spell_choice = 1; - break; - } - - if (ch == '2') - { - spell_choice = 2; - break; - } - } - - if (spell_choice == 1) - { - /* Still need to check timeouts because there is another counter */ - if (o_ptr->timeout) - { - msg_print("The first spell is still charging!"); - return; - } - - /* Cast spell 1 */ - activate_spell(o_ptr, spell_choice); - } - else if (spell_choice == 2) - { - /* Still need to check timeouts because there is another counter */ - if (o_ptr->xtra2) - { - msg_print("The second spell is still charging!"); - return; - } - - /* Cast spell 2 */ - activate_spell(o_ptr, spell_choice); - } - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP); - - /* Success */ - return; - } - - /* Monster eggs */ - if (o_ptr->tval == TV_EGG) - { - msg_print("You stop the development of the egg."); - o_ptr->timeout = -1; - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP); - - /* Success */ - return; - } - - /* Musical instruments */ - if (o_ptr->tval == TV_INSTRUMENT) - { - /* Horns */ - if (o_ptr->sval == SV_HORN) - { - msg_format("Your instrument emits a loud sound!"); - - aggravate_monsters(1); - - o_ptr->timeout = 100; - } - - /* Success */ - return; - } - - /* Mistake */ - msg_print("Oops. That object cannot be activated."); -} - -const char *activation_aux(object_type * o_ptr, bool_ doit, int item) -{ - static char buf[256]; - int plev = get_skill(SKILL_DEVICE); - - int i = 0, ii = 0, ij = 0, k, dir, dummy = 0; - int chance; - bool_ is_junkart = (o_ptr->tval == TV_RANDART); - - int spell = 0; - - /* Junkarts */ - if (is_junkart) - spell = activation_info[o_ptr->pval2].spell; - - /* True Actifacts */ - if (!spell && o_ptr->name1) - spell = a_info[o_ptr->name1].activate; - - /* Random and Alchemist Artifacts */ - if (!spell && o_ptr->art_name) - spell = o_ptr->xtra2; - - /* Ego Items */ - if (!spell && o_ptr->name2) - spell = e_info[o_ptr->name2].activate; - - /* Dual egos with the second ego having the activation */ - if (!spell && o_ptr->name2b) - spell = e_info[o_ptr->name2b].activate; - - /* Intrinsic to item type (rings of Ice, etc) */ - if (!spell) - spell = k_info[o_ptr->k_idx].activate; - - /* Complain about mis-configured .txt files? */ - if (!spell) - return "Unknown!"; - - /* Negative means a unified spell index */ - if (spell < 0) - { - struct spell_type *spell_ptr = spell_at(-spell); - if (doit) - { - spell_type_produce_effect(spell_ptr, item); - o_ptr->timeout = spell_type_activation_roll_timeout(spell_ptr); - } - else - { - spell_type_activation_description(spell_ptr, buf); - return buf; - } - } - else - { - /* Activate for attack */ - switch (spell) - { - case ACT_GILGALAD: - { - if (!doit) return "starlight (75) every 75+d75 turns"; - for (k = 1; k < 10; k++) - { - if (k - 5) fire_beam(GF_LITE, k, 75); - } - - o_ptr->timeout = rand_int(75) + 75; - - break; - } - - case ACT_CELEBRIMBOR: - { - if (!doit) return "temporary ESP (dur 20+d20) every 20+d50 turns"; - set_tim_esp(p_ptr->tim_esp + randint(20) + 20); - - o_ptr->timeout = rand_int(50) + 20; - - break; - } - - case ACT_SKULLCLEAVER: - { - if (!doit) return "destruction every 200+d200 turns"; - destroy_area(p_ptr->py, p_ptr->px, 15, TRUE, FALSE); - - o_ptr->timeout = rand_int(200) + 200; - - break; - } - - case ACT_HARADRIM: - { - if (!doit) return "berserk strength every 50+d50 turns"; - set_afraid(0); - set_shero(p_ptr->shero + randint(25) + 25); - hp_player(30); - - o_ptr->timeout = rand_int(50) + 50; - - break; - } - - case ACT_FUNDIN: - { - if (!doit) return "dispel evil (x4) every 100+d100 turns"; - dispel_evil(p_ptr->lev * 4); - - o_ptr->timeout = rand_int(100) + 100; - - break; - } - - case ACT_EOL: - { - if (!doit) return "mana bolt (9d8) 7+d7 turns"; - if (!get_aim_dir(&dir)) break; - fire_bolt(GF_MANA, dir, damroll(9, 8)); - - o_ptr->timeout = rand_int(7) + 7; - - break; - } - - case ACT_UMBAR: - { - if (!doit) return "magic arrow (10d10) every 20+d20 turns"; - if (!get_aim_dir(&dir)) break; - fire_bolt(GF_MISSILE, dir, damroll(10, 10)); - - o_ptr->timeout = rand_int(20) + 20; - - break; - } - - case ACT_NUMENOR: - { - /* Give full knowledge */ - /* Hack -- Maximal info */ - monster_race *r_ptr; - cave_type *c_ptr; - int x, y, m; - - if (!doit) return "analyze monster every 500+d200 turns"; - - if (!tgt_pt(&x, &y)) break; - - c_ptr = &cave[y][x]; - if (!c_ptr->m_idx) break; - - r_ptr = &r_info[c_ptr->m_idx]; - - /* Observe "maximal" attacks */ - for (m = 0; m < 4; m++) - { - /* Examine "actual" blows */ - if (r_ptr->blow[m].effect || r_ptr->blow[m].method) - { - /* Hack -- maximal observations */ - r_ptr->r_blows[m] = MAX_UCHAR; - } - } - - /* Hack -- maximal drops */ - r_ptr->r_drop_gold = r_ptr->r_drop_item = - (((r_ptr->flags1 & (RF1_DROP_4D2)) ? 8 : 0) + - ((r_ptr->flags1 & (RF1_DROP_3D2)) ? 6 : 0) + - ((r_ptr->flags1 & (RF1_DROP_2D2)) ? 4 : 0) + - ((r_ptr->flags1 & (RF1_DROP_1D2)) ? 2 : 0) + - ((r_ptr->flags1 & (RF1_DROP_90)) ? 1 : 0) + - ((r_ptr->flags1 & (RF1_DROP_60)) ? 1 : 0)); - - /* Hack -- but only "valid" drops */ - if (r_ptr->flags1 & (RF1_ONLY_GOLD)) r_ptr->r_drop_item = 0; - if (r_ptr->flags1 & (RF1_ONLY_ITEM)) r_ptr->r_drop_gold = 0; - - /* Hack -- observe many spells */ - r_ptr->r_cast_inate = MAX_UCHAR; - r_ptr->r_cast_spell = MAX_UCHAR; - - /* Hack -- know all the flags */ - r_ptr->r_flags1 = r_ptr->flags1; - r_ptr->r_flags2 = r_ptr->flags2; - r_ptr->r_flags3 = r_ptr->flags3; - r_ptr->r_flags4 = r_ptr->flags4; - r_ptr->r_flags5 = r_ptr->flags5; - r_ptr->r_flags6 = r_ptr->flags6; - r_ptr->r_flags7 = r_ptr->flags7; - r_ptr->r_flags8 = r_ptr->flags8; - r_ptr->r_flags9 = r_ptr->flags9; - - o_ptr->timeout = rand_int(200) + 500; - - break; - } - - case ACT_KNOWLEDGE: - { - if (!doit) return "whispers from beyond(sanity drain) 100+d200 turns"; - identify_fully(); - take_sanity_hit(damroll(10, 7), "the sounds of the dead"); - - o_ptr->timeout = rand_int(200) + 100; - - break; - } - - case ACT_UNDEATH: - { - if (!doit) return "ruination every 10+d10 turns"; - msg_print("The phial wells with dark light..."); - unlite_area(damroll(2, 15), 3); - take_hit(damroll(10, 10), "activating The Phial of Undeath"); - (void)dec_stat(A_DEX, 25, STAT_DEC_PERMANENT); - (void)dec_stat(A_WIS, 25, STAT_DEC_PERMANENT); - (void)dec_stat(A_CON, 25, STAT_DEC_PERMANENT); - (void)dec_stat(A_STR, 25, STAT_DEC_PERMANENT); - (void)dec_stat(A_CHR, 25, STAT_DEC_PERMANENT); - (void)dec_stat(A_INT, 25, STAT_DEC_PERMANENT); - - o_ptr->timeout = rand_int(10) + 10; - - break; - } - - case ACT_THRAIN: - { - if (!doit) return "detection every 30+d30 turns"; - msg_print("The stone glows a deep green..."); - detect_all(DEFAULT_RADIUS); - - o_ptr->timeout = rand_int(30) + 30; - - break; - } - - case ACT_BARAHIR: - { - if (!doit) return "dispel small life every 55+d55 turns"; - msg_print("You exterminate small life."); - (void)dispel_monsters(4); - - o_ptr->timeout = rand_int(55) + 55; - - break; - } - - case ACT_TULKAS: - { - if (!doit) return "haste self (75+d75 turns) every 150+d150 turns"; - msg_print("The ring glows brightly..."); - if (!p_ptr->fast) - { - (void)set_fast(randint(75) + 75, 10); - } - else - { - (void)set_fast(p_ptr->fast + 5, 10); - } - - o_ptr->timeout = rand_int(150) + 150; - - break; - } - - case ACT_NARYA: - { - if (!doit) return "healing (500) every 200+d100 turns"; - msg_print("The ring glows deep red..."); - hp_player(500); - set_blind(0); - set_confused(0); - set_poisoned(0); - set_stun(0); - set_cut(0); - - o_ptr->timeout = rand_int(100) + 200; - - break; - } - - case ACT_NENYA: - { - if (!doit) return "healing (800) every 100+d200 turns"; - msg_print("The ring glows bright white..."); - hp_player(800); - set_blind(0); - set_confused(0); - set_poisoned(0); - set_stun(0); - set_cut(0); - - o_ptr->timeout = rand_int(200) + 100; - - break; - } - - case ACT_VILYA: - { - if (!doit) return "greater healing (900) every 200+d200 turns"; - msg_print("The ring glows deep blue..."); - hp_player(900); - set_blind(0); - set_confused(0); - set_poisoned(0); - set_stun(0); - set_cut(0); - if (p_ptr->black_breath) - { - p_ptr->black_breath = FALSE; - msg_print("The hold of the Black Breath on you is broken!"); - } - - o_ptr->timeout = rand_int(200) + 200; - - break; - } - - case ACT_POWER: - { - if (!doit) return "powerful things"; - msg_print("The ring glows intensely black..."); - - o_ptr->timeout = ring_of_power(); - - break; - } - - - /* The Stone of Lore is perilous, for the sake of game balance. */ - case ACT_STONE_LORE: - { - if (!doit) return "perilous identify every turn"; - msg_print("The stone reveals hidden mysteries..."); - if (!ident_spell()) break; - - if (has_ability(AB_PERFECT_CASTING)) - { - /* Sufficient mana */ - if (20 <= p_ptr->csp) - { - /* Use some mana */ - p_ptr->csp -= 20; - } - - /* Over-exert the player */ - else - { - int oops = 20 - p_ptr->csp; - - /* No mana left */ - p_ptr->csp = 0; - p_ptr->csp_frac = 0; - - /* Message */ - msg_print("You are too weak to control the stone!"); - - /* Hack -- Bypass free action */ - (void)set_paralyzed(randint(5 * oops + 1)); - - /* Confusing. */ - (void)set_confused(p_ptr->confused + - randint(5 * oops + 1)); - } - - /* Redraw mana */ - p_ptr->redraw |= (PR_MANA); - } - - take_hit(damroll(1, 12), "perilous secrets"); - - /* Confusing. */ - if (rand_int(5) == 0) - { - (void)set_confused(p_ptr->confused + randint(10)); - } - - /* Exercise a little care... */ - if (rand_int(20) == 0) - { - take_hit(damroll(4, 10), "perilous secrets"); - } - - o_ptr->timeout = 1; - - break; - } - - case ACT_RAZORBACK: - { - if (!doit) return "star ball (150) every 1000 turns"; - msg_print("Your armor is surrounded by lightning..."); - for (i = 0; i < 8; i++) fire_ball(GF_ELEC, ddd[i], 150, 3); - - o_ptr->timeout = 1000; - - break; - } - - case ACT_BLADETURNER: - { - if (!doit) return "invulnerability (4+d8) every 800 turns"; - set_invuln(p_ptr->invuln + randint(8) + 4); - - o_ptr->timeout = 800; - - break; - } - - case ACT_MEDIATOR: - { - if (!doit) return "breathe elements (300), berserk rage, bless, and resistance every 400 turns"; - if (!get_aim_dir(&dir)) break; - msg_print("You breathe the elements."); - fire_ball(GF_MISSILE, dir, 300, 4); - msg_print("Your armor glows many colours..."); - (void)set_afraid(0); - (void)set_shero(p_ptr->shero + randint(50) + 50); - (void)hp_player(30); - (void)set_blessed(p_ptr->blessed + randint(50) + 50); - (void)set_oppose_acid(p_ptr->oppose_acid + randint(50) + 50); - (void)set_oppose_elec(p_ptr->oppose_elec + randint(50) + 50); - (void)set_oppose_fire(p_ptr->oppose_fire + randint(50) + 50); - (void)set_oppose_cold(p_ptr->oppose_cold + randint(50) + 50); - (void)set_oppose_pois(p_ptr->oppose_pois + randint(50) + 50); - - o_ptr->timeout = 400; - - break; - } - - case ACT_BELEGENNON: - { - if (!doit) return ("heal (777), curing and heroism every 300 turns"); - msg_print("A heavenly choir sings..."); - (void)set_poisoned(0); - (void)set_cut(0); - (void)set_stun(0); - (void)set_confused(0); - (void)set_blind(0); - (void)set_hero(p_ptr->hero + randint(25) + 25); - (void)hp_player(777); - - o_ptr->timeout = 300; - - break; - } - - case ACT_GORLIM: - { - if (!doit) return "rays of fear in every direction"; - turn_monsters(40 + p_ptr->lev); - - o_ptr->timeout = 3 * (p_ptr->lev + 10); - - break; - } - - case ACT_COLLUIN: - { - if (!doit) return "resistance (20+d20 turns) every 111 turns"; - msg_print("Your cloak glows many colours..."); - (void)set_oppose_acid(p_ptr->oppose_acid + randint(20) + 20); - (void)set_oppose_elec(p_ptr->oppose_elec + randint(20) + 20); - (void)set_oppose_fire(p_ptr->oppose_fire + randint(20) + 20); - (void)set_oppose_cold(p_ptr->oppose_cold + randint(20) + 20); - (void)set_oppose_pois(p_ptr->oppose_pois + randint(20) + 20); - - o_ptr->timeout = 111; - - break; - } - - - case ACT_BELANGIL: - { - if (!doit) return "frost ball (48) every 5+d5 turns"; - msg_print("Your dagger is covered in frost..."); - if (!get_aim_dir(&dir)) break; - fire_ball(GF_COLD, dir, 48, 2); - - o_ptr->timeout = rand_int(5) + 5; - - break; - } - - case ACT_ANGUIREL: - { - if (!doit) return "a getaway every 35 turns"; - switch (randint(13)) - { - case 1: - case 2: - case 3: - case 4: - case 5: - { - teleport_player(10); - - break; - } - - case 6: - case 7: - case 8: - case 9: - case 10: - { - teleport_player(222); - - break; - } - - case 11: - case 12: - { - (void)stair_creation(); - - break; - } - - default: - { - if (get_check("Leave this level? ")) - { - autosave_checkpoint(); - - /* Leaving */ - p_ptr->leaving = TRUE; - } - - break; - } - } - - o_ptr->timeout = 35; - - break; - } - - case ACT_ERU: - { - if (!doit) return "healing(7000), curing every 500 turns"; - msg_print("Your sword glows an intense white..."); - hp_player(7000); - heal_insanity(50); - set_blind(0); - set_poisoned(0); - set_confused(0); - set_stun(0); - set_cut(0); - set_image(0); - - o_ptr->timeout = 500; - - break; - } - - case ACT_DAWN: - { - if (!doit) return "summon the Legion of the Dawn every 500+d500 turns"; - msg_print("You summon the Legion of the Dawn."); - (void)summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_DAWN, TRUE); - - o_ptr->timeout = 500 + randint(500); - - break; - } - - case ACT_FIRESTAR: - { - if (!doit) return "large fire ball (72) every 100 turns"; - msg_print("Your morning star rages in fire..."); - if (!get_aim_dir(&dir)) break; - fire_ball(GF_FIRE, dir, 72, 3); - - o_ptr->timeout = 100; - - break; - } - - case ACT_TURMIL: - { - if (!doit) return "drain life (90) every 70 turns"; - msg_print("Your hammer glows white..."); - if (!get_aim_dir(&dir)) break; - drain_life(dir, 90); - - o_ptr->timeout = 70; - - break; - } - - case ACT_CUBRAGOL: - { - if (!doit) return "fire branding of bolts every 999 turns"; - msg_print("Your crossbow glows deep red..."); - (void)brand_bolts(); - - o_ptr->timeout = 999; - - break; - } - - case ACT_ELESSAR: - { - if (!doit) return "heal and cure black breath every 200 turns"; - if (p_ptr->black_breath) - { - msg_print("The hold of the Black Breath on you is broken!"); - } - p_ptr->black_breath = FALSE; - hp_player(100); - - o_ptr->timeout = 200; - - break; - } - - case ACT_GANDALF: - { - if (!doit) return "restore mana every 666 turns"; - msg_print("Your mage staff glows deep blue..."); - if (p_ptr->csp < p_ptr->msp) - { - p_ptr->csp = p_ptr->msp; - p_ptr->csp_frac = 0; - msg_print("Your feel your head clear."); - p_ptr->redraw |= (PR_MANA); - p_ptr->window |= (PW_PLAYER); - } - - o_ptr->timeout = 666; - - break; - } - - case ACT_MARDA: - { - if (!doit) return "summon a thunderlord every 1000 turns"; - if (randint(3) == 1) - { - if (summon_specific(p_ptr->py, p_ptr->px, ((plev * 3) / 2), SUMMON_THUNDERLORD)) - { - msg_print("A Thunderlord comes from thin air!"); - msg_print("'I will burn you!'"); - } - } - else - { - if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2), - SUMMON_THUNDERLORD, (plev == 50 ? TRUE : FALSE))) - { - msg_print("A Thunderlord comes from thin air!"); - msg_print("'I will help you in your difficult task.'"); - } - } - - o_ptr->timeout = 1000; - - break; - } - - case ACT_PALANTIR: - { - if (!doit) return "clairvoyance every 100+d100 turns"; - msg_print("The stone glows a deep green..."); - wiz_lite_extra(); - (void)detect_traps(DEFAULT_RADIUS); - (void)detect_doors(DEFAULT_RADIUS); - (void)detect_stairs(DEFAULT_RADIUS); - - o_ptr->timeout = rand_int(100) + 100; - - break; - } - - case ACT_EREBOR: - { - if (!doit) return "open a secret passage every 75 turns"; - msg_print("Your pick twists in your hands."); - - if (!get_aim_dir(&dir)) break; - if (passwall(dir, TRUE)) - { - msg_print("A passage opens, and you step through."); - } - else - { - msg_print("There is no wall there!"); - } - - o_ptr->timeout = 75; - - break; - } - - case ACT_DRUEDAIN: - { - if (!doit) return "detection every 99 turns"; - msg_print("Your drum shows you the world."); - detect_all(DEFAULT_RADIUS); - - o_ptr->timeout = 99; - - break; - } - - case ACT_ROHAN: - { - if (!doit) return "heroism, berserker, and haste every 250 turns"; - msg_print("Your horn glows deep red."); - set_afraid(0); - set_shero(p_ptr->shero + damroll(5, 10) + 30); - set_afraid(0); - set_hero(p_ptr->hero + damroll(5, 10) + 30); - set_fast(p_ptr->fast + damroll(5, 10) + 30, 10); - hp_player(30); - - o_ptr->timeout = 250; - - break; - } - - case ACT_HELM: - { - if (!doit) return "sound ball (300) every 300 turns"; - msg_print("Your horn emits a loud sound."); - if (!get_aim_dir(&dir)) break; - fire_ball(GF_SOUND, dir, 300, 6); - - o_ptr->timeout = 300; - - break; - } - - case ACT_BOROMIR: - { - if (!doit) return "mass human summoning every 1000 turns"; - msg_print("Your horn calls for help."); - for (i = 0; i < 15; i++) - { - summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2), SUMMON_HUMAN, TRUE); - } - - o_ptr->timeout = 1000; - - break; - } - - case ACT_HURIN: - { - if (!doit) return "berserker and +10 to speed (50) every 100+d200 turns"; - if (!p_ptr->fast) - { - (void)set_fast(randint(50) + 50, 10); - } - else - { - (void)set_fast(p_ptr->fast + 5, 10); - } - hp_player(30); - set_afraid(0); - set_shero(p_ptr->shero + randint(50) + 50); - - o_ptr->timeout = rand_int(200) + 100; - - break; - } - - case ACT_AXE_GOTHMOG: - { - if (!doit) return "fire ball (300) every 200+d200 turns"; - msg_print("Your lochaber axe erupts in fire..."); - if (!get_aim_dir(&dir)) break; - fire_ball(GF_FIRE, dir, 300, 4); - - o_ptr->timeout = 200 + rand_int(200); - - break; - } - - case ACT_MELKOR: - { - if (!doit) return "darkness ball (150) every 100 turns"; - msg_print("Your spear is covered of darkness..."); - if (!get_aim_dir(&dir)) break; - fire_ball(GF_DARK, dir, 150, 3); - - o_ptr->timeout = 100; - - break; - } - - case ACT_GROND: - { - if (!doit) return "alter reality every 100 turns"; - msg_print("Your hammer hits the floor..."); - alter_reality(); - - o_ptr->timeout = 100; - - break; - } - - case ACT_NATUREBANE: - { - if (!doit) return "dispel monsters (300) every 200+d200 turns"; - msg_print("Your axe glows blood red..."); - dispel_monsters(300); - - o_ptr->timeout = 200 + randint(200); - - break; - } - - case ACT_NIGHT: - { - if (!doit) return "vampiric drain (3*100) every 250 turns"; - msg_print("Your axe emits a black aura..."); - if (!get_aim_dir(&dir)) break; - for (i = 0; i < 3; i++) - { - if (drain_life(dir, 100)) hp_player(100); - } - - o_ptr->timeout = 250; - - break; - } - - case ACT_ORCHAST: - { - if (!doit) return "detect orcs every 10 turns"; - msg_print("Your weapon glows brightly..."); - (void)detect_monsters_xxx(RF3_ORC, DEFAULT_RADIUS); - - o_ptr->timeout = 10; - - break; - } - case ACT_SUNLIGHT: - { - if (!doit) return "beam of sunlight every 10 turns"; - - if (!get_aim_dir(&dir)) break; - msg_print("A line of sunlight appears."); - lite_line(dir); - - o_ptr->timeout = 10; - - break; - } - - case ACT_BO_MISS_1: - { - if (!doit) return "magic missile (2d6) every 2 turns"; - msg_print("It glows extremely brightly..."); - if (!get_aim_dir(&dir)) break; - fire_bolt(GF_MISSILE, dir, damroll(2, 6)); - - o_ptr->timeout = 2; - - break; - } - - case ACT_BA_POIS_1: - { - if (!doit) return "stinking cloud (12), rad. 3, every 4+d4 turns"; - msg_print("It throbs deep green..."); - if (!get_aim_dir(&dir)) break; - fire_ball(GF_POIS, dir, 12, 3); - - o_ptr->timeout = rand_int(4) + 4; - - break; - } - - case ACT_BO_ELEC_1: - { - if (!doit) return "lightning bolt (4d8) every 6+d6 turns"; - msg_print("It is covered in sparks..."); - if (!get_aim_dir(&dir)) break; - fire_bolt(GF_ELEC, dir, damroll(4, 8)); - - o_ptr->timeout = rand_int(6) + 6; - - break; - } - - case ACT_BO_ACID_1: - { - if (!doit) return "acid bolt (5d8) every 5+d5 turns"; - msg_print("It is covered in acid..."); - if (!get_aim_dir(&dir)) break; - fire_bolt(GF_ACID, dir, damroll(5, 8)); - - o_ptr->timeout = rand_int(5) + 5; - - break; - } - - case ACT_BO_COLD_1: - { - if (!doit) return "frost bolt (6d8) every 7+d7 turns"; - msg_print("It is covered in frost..."); - if (!get_aim_dir(&dir)) break; - fire_bolt(GF_COLD, dir, damroll(6, 8)); - - o_ptr->timeout = rand_int(7) + 7; - - break; - } - - case ACT_BO_FIRE_1: - { - if (!doit) return "fire bolt (9d8) every 8+d8 turns"; - msg_print("It is covered in fire..."); - if (!get_aim_dir(&dir)) break; - fire_bolt(GF_FIRE, dir, damroll(9, 8)); - - o_ptr->timeout = rand_int(8) + 8; - - break; - } - - case ACT_BA_COLD_1: - { - if (!doit) return "ball of cold (48) every 400 turns"; - msg_print("It is covered in frost..."); - if (!get_aim_dir(&dir)) break; - fire_ball(GF_COLD, dir, 48, 2); - - o_ptr->timeout = 400; - - break; - } - - case ACT_BA_FIRE_1: - { - if (!doit) return "ball of fire (72) every 400 turns"; - msg_print("It glows an intense red..."); - if (!get_aim_dir(&dir)) break; - fire_ball(GF_FIRE, dir, 72, 2); - - o_ptr->timeout = 400; - - break; - } - - case ACT_DRAIN_1: - { - if (!doit) return "drain life (100) every 100+d100 turns"; - msg_print("It glows black..."); - if (!get_aim_dir(&dir)) break; - if (drain_life(dir, 100)) - - o_ptr->timeout = rand_int(100) + 100; - - break; - } - - case ACT_BA_COLD_2: - { - if (!doit) return "ball of cold (100) every 300 turns"; - msg_print("It glows an intense blue..."); - if (!get_aim_dir(&dir)) break; - fire_ball(GF_COLD, dir, 100, 2); - - o_ptr->timeout = 300; - - break; - } - - case ACT_BA_ELEC_2: - { - if (!doit) return "ball of lightning (100) every 500 turns"; - msg_print("It crackles with electricity..."); - if (!get_aim_dir(&dir)) break; - fire_ball(GF_ELEC, dir, 100, 3); - - o_ptr->timeout = 500; - - break; - } - - case ACT_DRAIN_2: - { - if (!doit) return "drain life (120) every 400 turns"; - msg_print("It glows black..."); - if (!get_aim_dir(&dir)) break; - drain_life(dir, 120); - - o_ptr->timeout = 400; - - break; - } - - case ACT_VAMPIRE_1: - { - if (!doit) return "vampiric drain (3*50) every 400 turns"; - if (!get_aim_dir(&dir)) break; - for (dummy = 0; dummy < 3; dummy++) - { - if (drain_life(dir, 50)) - hp_player(50); - } - - o_ptr->timeout = 400; - - break; - } - - case ACT_BO_MISS_2: - { - if (!doit) return "arrows (150) every 90+d90 turns"; - msg_print("It grows magical spikes..."); - if (!get_aim_dir(&dir)) break; - fire_bolt(GF_ARROW, dir, 150); - - o_ptr->timeout = rand_int(90) + 90; - - break; - } - - case ACT_BA_FIRE_2: - { - if (!doit) return "fire ball (120) every 225+d225 turns"; - msg_print("It glows deep red..."); - if (!get_aim_dir(&dir)) break; - fire_ball(GF_FIRE, dir, 120, 3); - - o_ptr->timeout = rand_int(225) + 225; - - break; - } - - case ACT_BA_COLD_3: - { - if (!doit) return "ball of cold (200) every 325+d325 turns"; - msg_print("It glows bright white..."); - if (!get_aim_dir(&dir)) break; - fire_ball(GF_COLD, dir, 200, 3); - - o_ptr->timeout = rand_int(325) + 325; - - break; - } - - case ACT_BA_ELEC_3: - { - if (!doit) return "Lightning Ball (250) every 425+d425 turns"; - msg_print("It glows deep blue..."); - if (!get_aim_dir(&dir)) break; - fire_ball(GF_ELEC, dir, 250, 3); - - o_ptr->timeout = rand_int(425) + 425; - - break; - } - - case ACT_WHIRLWIND: - { - int y = 0, x = 0; - cave_type *c_ptr; - monster_type *m_ptr; - if (!doit) return "whirlwind attack every 250 turns"; - - for (dir = 0; dir <= 9; dir++) - { - y = p_ptr->py + ddy[dir]; - x = p_ptr->px + ddx[dir]; - c_ptr = &cave[y][x]; - - /* Get the monster */ - m_ptr = &m_list[c_ptr->m_idx]; - - /* Hack -- attack monsters */ - if (c_ptr->m_idx && (m_ptr->ml || cave_floor_bold(y, x))) - { - py_attack(y, x, -1); - } - } - - o_ptr->timeout = 250; - - break; - } - - case ACT_VAMPIRE_2: - { - if (!doit) return "vampiric drain (3*100) every 400 turns"; - if (!get_aim_dir(&dir)) break; - for (dummy = 0; dummy < 3; dummy++) - { - if (drain_life(dir, 100)) - hp_player(100); - } - - o_ptr->timeout = 400; - - break; - } - - - case ACT_CALL_CHAOS: - { - if (!doit) return "call chaos every 350 turns"; - msg_print("It glows in scintillating colours..."); - call_chaos(); - - o_ptr->timeout = 350; - - break; - } - - case ACT_ROCKET: - { - if (!doit) return "launch rocket (120+level) every 400 turns"; - if (!get_aim_dir(&dir)) break; - msg_print("You launch a rocket!"); - fire_ball(GF_ROCKET, dir, 120 + (plev), 2); - - o_ptr->timeout = 400; - - break; - } - - case ACT_DISP_EVIL: - { - if (!doit) return "dispel evil (level*5) every 300+d300 turns"; - msg_print("It floods the area with goodness..."); - dispel_evil(p_ptr->lev * 5); - - o_ptr->timeout = rand_int(300) + 300; - - break; - } - - case ACT_DISP_GOOD: - { - if (!doit) return "dispel good (level*5) every 300+d300 turns"; - msg_print("It floods the area with evil..."); - dispel_good(p_ptr->lev * 5); - - o_ptr->timeout = rand_int(300) + 300; - - break; - } - - case ACT_BA_MISS_3: - { - if (!doit) return "elemental breath (300) every 500 turns"; - if (!get_aim_dir(&dir)) break; - msg_print("You breathe the elements."); - fire_ball(GF_MISSILE, dir, 300, 4); - - o_ptr->timeout = 500; - - break; - } - - /* Activate for other offensive action */ - - case ACT_CONFUSE: - { - if (!doit) return "confuse monster every 15 turns"; - msg_print("It glows in scintillating colours..."); - if (!get_aim_dir(&dir)) break; - confuse_monster(dir, 20); - - o_ptr->timeout = 15; - - break; - } - - case ACT_SLEEP: - { - if (!doit) return "sleep nearby monsters every 55 turns"; - msg_print("It glows deep blue..."); - sleep_monsters_touch(); - - o_ptr->timeout = 55; - - break; - } - - case ACT_QUAKE: - { - if (!doit) return "earthquake (rad 10) every 50 turns"; - /* Prevent destruction of quest levels and town */ - if (!is_quest(dun_level) && dun_level) - { - earthquake(p_ptr->py, p_ptr->px, 10); - o_ptr->timeout = 50; - } - - break; - } - - case ACT_TERROR: - { - if (!doit) return "terror every 3 * (level+10) turns"; - turn_monsters(40 + p_ptr->lev); - - o_ptr->timeout = 3 * (p_ptr->lev + 10); - - break; - } - - case ACT_TELE_AWAY: - { - if (!doit) return "teleport away every 200 turns"; - if (!get_aim_dir(&dir)) break; - (void)fire_beam(GF_AWAY_ALL, dir, plev); - - o_ptr->timeout = 200; - - break; - } - - case ACT_BANISH_EVIL: - { - if (!doit) return "banish evil every 250+d250 turns"; - if (banish_evil(100)) - { - msg_print("The power of the artifact banishes evil!"); - } - - o_ptr->timeout = 250 + randint(250); - - break; - } - - case ACT_GENOCIDE: - { - if (!doit) return "genocide every 500 turns"; - msg_print("It glows deep blue..."); - (void)genocide(TRUE); - - o_ptr->timeout = 500; - - break; - } - - case ACT_MASS_GENO: - { - if (!doit) return "mass genocide every 1000 turns"; - msg_print("It lets out a long, shrill note..."); - (void)mass_genocide(TRUE); - - o_ptr->timeout = 1000; - - break; - } - - /* Activate for summoning / charming */ - - case ACT_CHARM_ANIMAL: - { - if (!doit) return "charm animal every 300 turns"; - if (!get_aim_dir(&dir)) break; - (void) charm_animal(dir, plev); - - o_ptr->timeout = 300; - - break; - } - - case ACT_CHARM_UNDEAD: - { - if (!doit) return "enslave undead every 333 turns"; - if (!get_aim_dir(&dir)) break; - (void)control_one_undead(dir, plev); - - o_ptr->timeout = 333; - - break; - } - - case ACT_CHARM_OTHER: - { - if (!doit) return "charm monster every 400 turns"; - if (!get_aim_dir(&dir)) break; - (void) charm_monster(dir, plev); - - o_ptr->timeout = 400; - - break; - } - - case ACT_CHARM_ANIMALS: - { - if (!doit) return "animal friendship every 500 turns"; - (void) charm_animals(plev * 2); - - o_ptr->timeout = 500; - - break; - } - - case ACT_CHARM_OTHERS: - { - if (!doit) return "mass charm every 750 turns"; - charm_monsters(plev * 2); - - o_ptr->timeout = 750; - - break; - } - - case ACT_SUMMON_ANIMAL: - { - if (!doit) return "summon animal every 200+d300 turns"; - (void)summon_specific_friendly(p_ptr->py, p_ptr->px, plev, SUMMON_ANIMAL_RANGER, TRUE); - - o_ptr->timeout = 200 + randint(300); - - break; - } - - case ACT_SUMMON_PHANTOM: - { - if (!doit) return "summon phantasmal servant every 200+d200 turns"; - msg_print("You summon a phantasmal servant."); - (void)summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_PHANTOM, TRUE); - - o_ptr->timeout = 200 + randint(200); - - break; - } - - case ACT_SUMMON_ELEMENTAL: - { - if (!doit) return "summon elemental every 750 turns"; - if (randint(3) == 1) - { - if (summon_specific(p_ptr->py, p_ptr->px, ((plev * 3) / 2), SUMMON_ELEMENTAL)) - { - msg_print("An elemental materialises..."); - msg_print("You fail to control it!"); - } - } - else - { - if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2), - SUMMON_ELEMENTAL, (plev == 50 ? TRUE : FALSE))) - { - msg_print("An elemental materialises..."); - msg_print("It seems obedient to you."); - } - } - - o_ptr->timeout = 750; - - break; - } - - case ACT_SUMMON_DEMON: - { - if (!doit) return "summon demon every 666+d333 turns"; - if (randint(3) == 1) - { - if (summon_specific(p_ptr->py, p_ptr->px, ((plev * 3) / 2), SUMMON_DEMON)) - { - msg_print("The area fills with a stench of sulphur and brimstone."); - msg_print("'NON SERVIAM! Wretch! I shall feast on thy mortal soul!'"); - } - } - else - { - if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2), - SUMMON_DEMON, (plev == 50 ? TRUE : FALSE))) - { - msg_print("The area fills with a stench of sulphur and brimstone."); - msg_print("'What is thy bidding... Master?'"); - } - } - - o_ptr->timeout = 666 + randint(333); - - break; - } - - case ACT_SUMMON_UNDEAD: - { - if (!doit) return "summon undead every 666+d333 turns"; - if (randint(3) == 1) - { - if (summon_specific(p_ptr->py, p_ptr->px, ((plev * 3) / 2), - (plev > 47 ? SUMMON_HI_UNDEAD : SUMMON_UNDEAD))) - { - msg_print("Cold winds begin to blow around you, carrying with them the stench of decay..."); - msg_print("'The dead arise... to punish you for disturbing them!'"); - } - } - else - { - if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2), - (plev > 47 ? SUMMON_HI_UNDEAD_NO_UNIQUES : SUMMON_UNDEAD), - (((plev > 24) && (randint(3) == 1)) ? TRUE : FALSE))) - { - msg_print("Cold winds begin to blow around you, carrying with them the stench of decay..."); - msg_print("Ancient, long-dead forms arise from the ground to serve you!"); - } - } - - o_ptr->timeout = 666 + randint(333); - - break; - } - - /* Activate for healing */ - - case ACT_CURE_LW: - { - if (!doit) return format("cure light wounds every %d turns", (is_junkart ? 50 : 10)); - (void)set_afraid(0); - (void)hp_player(30); - - o_ptr->timeout = 10; - - break; - } - - case ACT_CURE_MW: - { - if (!doit) return format("cure serious wounds every %s turns", (is_junkart? "75" : "3+d3")); - msg_print("It radiates deep purple..."); - hp_player(damroll(4, 8)); - (void)set_cut((p_ptr->cut / 2) - 50); - - o_ptr->timeout = rand_int(3) + 3; - - break; - } - - case ACT_CURE_POISON: - { - if (!doit) return "remove fear and cure poison every 5 turns"; - msg_print("It glows deep blue..."); - (void)set_afraid(0); - (void)set_poisoned(0); - - o_ptr->timeout = 5; - - break; - } - - case ACT_REST_LIFE: - { - if (!doit) return "restore life levels every 450 turns"; - msg_print("It glows a deep red..."); - restore_level(); - - o_ptr->timeout = 450; - - break; - } - - case ACT_REST_ALL: - { - if (!doit) return format("restore stats and life levels every %d turns", (is_junkart ? 200 : 750)); - msg_print("It glows a deep green..."); - (void)do_res_stat(A_STR, TRUE); - (void)do_res_stat(A_INT, TRUE); - (void)do_res_stat(A_WIS, TRUE); - (void)do_res_stat(A_DEX, TRUE); - (void)do_res_stat(A_CON, TRUE); - (void)do_res_stat(A_CHR, TRUE); - (void)restore_level(); - - o_ptr->timeout = 750; - - break; - } - - case ACT_CURE_700: - { - if (!doit) return format("heal 700 hit points every %d turns", (is_junkart ? 100 : 250)); - msg_print("It glows deep blue..."); - msg_print("You feel a warm tingling inside..."); - (void)hp_player(700); - (void)set_cut(0); - - o_ptr->timeout = 250; - - break; - } - - case ACT_CURE_1000: - { - if (!doit) return "heal 1000 hit points every 888 turns"; - msg_print("It glows a bright white..."); - msg_print("You feel much better..."); - (void)hp_player(1000); - (void)set_cut(0); - - o_ptr->timeout = 888; - - break; - } - - case ACT_ESP: - { - if (!doit) return "temporary ESP (dur 25+d30) every 200 turns"; - (void)set_tim_esp(p_ptr->tim_esp + randint(30) + 25); - - o_ptr->timeout = 200; - - break; - } - - case ACT_BERSERK: - { - if (!doit) return "heroism and berserk (dur 50+d50) every 100+d100 turns"; - (void)set_shero(p_ptr->shero + randint(50) + 50); - (void)set_blessed(p_ptr->blessed + randint(50) + 50); - - o_ptr->timeout = 100 + randint(100); - - break; - } - - case ACT_PROT_EVIL: - { - if (!doit) return "protection from evil (dur level*3 + d25) every 225+d225 turns"; - msg_print("It lets out a shrill wail..."); - k = 3 * p_ptr->lev; - (void)set_protevil(p_ptr->protevil + randint(25) + k); - - o_ptr->timeout = rand_int(225) + 225; - - break; - } - - case ACT_RESIST_ALL: - { - if (!doit) return "resist elements (dur 40+d40) every 200 turns"; - msg_print("It glows many colours..."); - (void)set_oppose_acid(p_ptr->oppose_acid + randint(40) + 40); - (void)set_oppose_elec(p_ptr->oppose_elec + randint(40) + 40); - (void)set_oppose_fire(p_ptr->oppose_fire + randint(40) + 40); - (void)set_oppose_cold(p_ptr->oppose_cold + randint(40) + 40); - (void)set_oppose_pois(p_ptr->oppose_pois + randint(40) + 40); - - o_ptr->timeout = 200; - - break; - } - - case ACT_SPEED: - { - if (!doit) return "speed (dur 20+d20) every 250 turns"; - msg_print("It glows bright green..."); - if (!p_ptr->fast) - { - (void)set_fast(randint(20) + 20, 10); - } - else - { - (void)set_fast(p_ptr->fast + 5, 10); - } - - o_ptr->timeout = 250; - - break; - } - - case ACT_XTRA_SPEED: - { - if (!doit) return "speed (dur 75+d75) every 200+d200 turns"; - msg_print("It glows brightly..."); - if (!p_ptr->fast) - { - (void)set_fast(randint(75) + 75, 10); - } - else - { - (void)set_fast(p_ptr->fast + 5, 10); - } - - o_ptr->timeout = rand_int(200) + 200; - - break; - } - - case ACT_WRAITH: - { - if (!doit) return "wraith form (level/2 + d(level/2)) every 1000 turns"; - set_shadow(p_ptr->tim_wraith + randint(plev / 2) + (plev / 2)); - - o_ptr->timeout = 1000; - - break; - } - - case ACT_INVULN: - { - if (!doit) return "invulnerability (dur 8+d8) every 1000 turns"; - (void)set_invuln(p_ptr->invuln + randint(8) + 8); - - o_ptr->timeout = 1000; - - break; - } - - /* Activate for general purpose effect (detection etc.) */ - - case ACT_LIGHT: - { - if (!doit) return format("light area (dam 2d15) every %s turns", (is_junkart ? "100" : "10+d10")); - msg_print("It wells with clear light..."); - lite_area(damroll(2, 15), 3); - - o_ptr->timeout = rand_int(10) + 10; - - break; - } - - case ACT_MAP_LIGHT: - { - if (!doit) return "light (dam 2d15) & map area every 50+d50 turns"; - msg_print("It shines brightly..."); - map_area(); - lite_area(damroll(2, 15), 3); - - o_ptr->timeout = rand_int(50) + 50; - - break; - } - - case ACT_DETECT_ALL: - { - if (!doit) return "detection every 55+d55 turns"; - msg_print("It glows bright white..."); - msg_print("An image forms in your mind..."); - detect_all(DEFAULT_RADIUS); - - o_ptr->timeout = rand_int(55) + 55; - - break; - } - - case ACT_DETECT_XTRA: - { - if (!doit) return "detection, probing and identify true every 1000 turns"; - msg_print("It glows brightly..."); - detect_all(DEFAULT_RADIUS); - probing(); - identify_fully(); - - o_ptr->timeout = 1000; - - break; - } - - case ACT_ID_FULL: - { - if (!doit) return "identify true every 750 turns"; - msg_print("It glows yellow..."); - identify_fully(); - - o_ptr->timeout = 750; - - break; - } - - case ACT_ID_PLAIN: - { - if (!doit) return "identify spell every 10 turns"; - if (!ident_spell()) break; - - o_ptr->timeout = 10; - - break; - } - - case ACT_RUNE_EXPLO: - { - if (!doit) return "explosive rune every 200 turns"; - msg_print("It glows bright red..."); - explosive_rune(); - - o_ptr->timeout = 200; - - break; - } - - case ACT_RUNE_PROT: - { - if (!doit) return "rune of protection every 400 turns"; - msg_print("It glows light blue..."); - warding_glyph(); - - o_ptr->timeout = 400; - - break; - } - - case ACT_SATIATE: - { - if (!doit) return "satisfy hunger every 200 turns"; - (void)set_food(PY_FOOD_MAX - 1); - - o_ptr->timeout = 200; - - break; - } - - case ACT_DEST_DOOR: - { - if (!doit) return "destroy doors and traps every 10 turns"; - msg_print("It glows bright red..."); - destroy_doors_touch(); - - o_ptr->timeout = 10; - - break; - } - - case ACT_STONE_MUD: - { - if (!doit) return "stone to mud every 5 turns"; - msg_print("It pulsates..."); - if (!get_aim_dir(&dir)) break; - wall_to_mud(dir); - - o_ptr->timeout = 5; - - break; - } - - case ACT_RECHARGE: - { - if (!doit) return "recharging every 70 turns"; - recharge(60); - - o_ptr->timeout = 70; - - break; - } - - case ACT_ALCHEMY: - { - if (!doit) return "alchemy every 500 turns"; - msg_print("It glows bright yellow..."); - (void) alchemy(); - - o_ptr->timeout = 500; - - break; - } - - case ACT_DIM_DOOR: - { - if (!doit) return "dimension door every 100 turns"; - if (dungeon_flags2 & DF2_NO_TELEPORT) - { - msg_print("Not on special levels!"); - break; - } - - msg_print("You open a Void Jumpgate. Choose a destination."); - if (!tgt_pt(&ii, &ij)) break; - - p_ptr->energy -= 60 - plev; - - if (!cave_empty_bold(ij, ii) || (cave[ij][ii].info & CAVE_ICKY) || - (distance(ij, ii, p_ptr->py, p_ptr->px) > plev + 2) || - (!rand_int(plev * plev / 2))) - { - msg_print("You fail to exit the void correctly!"); - p_ptr->energy -= 100; - get_pos_player(10, &ij, &ii); - } - - cave_set_feat(p_ptr->py, p_ptr->px, FEAT_BETWEEN); - cave_set_feat(ij, ii, FEAT_BETWEEN); - cave[p_ptr->py][p_ptr->px].special = ii + (ij << 8); - cave[ij][ii].special = p_ptr->px + (p_ptr->py << 8); - - o_ptr->timeout = 100; - - break; - } - - case ACT_TELEPORT: - { - if (!doit) return format("teleport (range 100) every %d turns", (is_junkart? 100 : 45)); - msg_print("It twists space around you..."); - teleport_player(100); - - o_ptr->timeout = 45; - - break; - } - - case ACT_RECALL: - { - if (!(dungeon_flags2 & DF2_ASK_LEAVE) || ((dungeon_flags2 & DF2_ASK_LEAVE) && !get_check("Leave this unique level forever? "))) - { - if (!doit) return "word of recall every 200 turns"; - msg_print("It glows soft white..."); - recall_player(20,15); - - o_ptr->timeout = 200; - } - - break; - } - - case ACT_DEATH: - { - if (!doit) return "death"; - take_hit(5000, "activating a death spell"); - - /* Timeout is set before return */ - - break; - } - - case ACT_RUINATION: - { - if (!doit) return "Ruination"; - msg_print("Your nerves and muscles feel weak and lifeless!"); - - take_hit(damroll(10, 10), "activating Ruination"); - (void)dec_stat(A_DEX, 25, TRUE); - (void)dec_stat(A_WIS, 25, TRUE); - (void)dec_stat(A_CON, 25, TRUE); - (void)dec_stat(A_STR, 25, TRUE); - (void)dec_stat(A_CHR, 25, TRUE); - (void)dec_stat(A_INT, 25, TRUE); - - /* Timeout is set before return */ - - break; - } - - case ACT_DESTRUC: - { - if (!doit) return "Destruction every 100 turns"; - earthquake(p_ptr->py, p_ptr->px, 12); - - /* Timeout is set before return */ - - break; - } - - case ACT_UNINT: - { - if (!doit) return "decreasing Intelligence"; - (void)dec_stat(A_INT, 25, FALSE); - - /* Timeout is set before return */ - - break; - } - - case ACT_UNSTR: - { - if (!doit) return "decreasing Strength"; - (void)dec_stat(A_STR, 25, FALSE); - - /* Timeout is set before return */ - - break; - } - - case ACT_UNCON: - { - if (!doit) return "decreasing Constitution"; - (void)dec_stat(A_CON, 25, FALSE); - - /* Timeout is set before return */ - - break; - } - - case ACT_UNCHR: - { - if (!doit) return "decreasing Charisma"; - (void)dec_stat(A_CHR, 25, FALSE); - - /* Timeout is set before return */ - - break; - } - - case ACT_UNDEX: - { - if (!doit) return "decreasing Dexterity"; - (void)dec_stat(A_DEX, 25, FALSE); - - /* Timeout is set before return */ - - break; - } - - case ACT_UNWIS: - { - if (!doit) return "decreasing Wisdom"; - (void)dec_stat(A_WIS, 25, FALSE); - - /* Timeout is set before return */ - - break; - } - - case ACT_STATLOSS: - { - if (!doit) return "stat loss"; - (void)dec_stat(A_STR, 15, FALSE); - (void)dec_stat(A_INT, 15, FALSE); - (void)dec_stat(A_WIS, 15, FALSE); - (void)dec_stat(A_DEX, 15, FALSE); - (void)dec_stat(A_CON, 15, FALSE); - (void)dec_stat(A_CHR, 15, FALSE); - - /* Timeout is set before return */ - - break; - } - - case ACT_HISTATLOSS: - { - if (!doit) return "high stat loss"; - (void)dec_stat(A_STR, 25, FALSE); - (void)dec_stat(A_INT, 25, FALSE); - (void)dec_stat(A_WIS, 25, FALSE); - (void)dec_stat(A_DEX, 25, FALSE); - (void)dec_stat(A_CON, 25, FALSE); - (void)dec_stat(A_CHR, 25, FALSE); - - /* Timeout is set before return */ - - break; - } - - case ACT_EXPLOSS: - { - if (!doit) return "experience loss"; - lose_exp(p_ptr->exp / 20); - - /* Timeout is set before return */ - - break; - } - - case ACT_HIEXPLOSS: - { - if (!doit) return "high experience loss"; - lose_exp(p_ptr->exp / 10); - - /* Timeout is set before return */ - - break; - } - - case ACT_SUMMON_MONST: - { - if (!doit) return "summon monster"; - summon_specific(p_ptr->py, p_ptr->px, max_dlv[dungeon_type], 0); - - /* Timeout is set before return */ - - break; - } - - case ACT_PARALYZE: - { - if (!doit) return "paralyze"; - set_paralyzed(20 + randint(10)); - - /* Timeout is set before return */ - - break; - } - - case ACT_HALLU: - { - if (!doit) return "hallucination every 10 turns"; - set_image(p_ptr->image + 20 + randint(10)); - - /* Timeout is set before return */ - - break; - } - - case ACT_POISON: - { - if (!doit) return "poison"; - set_poisoned(p_ptr->poisoned + 20 + randint(10)); - - /* Timeout is set before return */ - - break; - } - - case ACT_HUNGER: - { - if (!doit) return "create hunger"; - (void)set_food(PY_FOOD_WEAK); - - /* Timeout is set before return */ - - break; - } - - case ACT_STUN: - { - if (!doit) return "stun"; - set_stun(p_ptr->stun + 20 + randint(10)); - - /* Timeout is set before return */ - - break; - } - - case ACT_CUTS: - { - if (!doit) return "cuts"; - set_cut(p_ptr->cut + 20 + randint(10)); - - /* Timeout is set before return */ - - break; - } - - case ACT_PARANO: - { - if (!doit) return "confusion"; - set_confused(p_ptr->confused + 30 + randint(10)); - - /* Timeout is set before return */ - - break; - } - - case ACT_CONFUSION: - { - if (!doit) return "confusion"; - set_confused(p_ptr->confused + 20 + randint(10)); - - /* Timeout is set before return */ - - break; - } - - case ACT_BLIND: - { - if (!doit) return "blindness"; - set_blind(p_ptr->blind + 20 + randint(10)); - - /* Timeout is set before return */ - - break; - } - - case ACT_PET_SUMMON: - { - if (!doit) return "summon pet every 101 turns"; - summon_specific_friendly(p_ptr->py, p_ptr->px, max_dlv[dungeon_type], 0, FALSE); - - /* Timeout is set before return */ - /*FINDME*/ - - break; - } - - case ACT_CURE_PARA: - { - if (!doit) return "cure confusion every 500 turns"; - set_confused(0); - - /* Timeout is set before return */ - - break; - } - - case ACT_CURE_HALLU: - { - if (!doit) return "cure hallucination every 100 turns"; - set_image(0); - - /* Timeout is set before return */ - - break; - } - - case ACT_CURE_POIS: - { - if (!doit) return "cure poison every 100 turns"; - set_poisoned(0); - - /* Timeout is set before return */ - - break; - } - - case ACT_CURE_HUNGER: - { - if (!doit) return "satisfy hunger every 100 turns"; - (void)set_food(PY_FOOD_MAX - 1); - - /* Timeout is set before return */ - - break; - } - - case ACT_CURE_STUN: - { - if (!doit) return "cure stun every 100 turns"; - set_stun(0); - - /* Timeout is set before return */ - - break; - } - - case ACT_CURE_CUTS: - { - if (!doit) return "cure cuts every 100 turns"; - set_cut(0); - - /* Timeout is set before return */ - - break; - } - - case ACT_CURE_FEAR: - { - if (!doit) return "cure fear every 100 turns"; - set_afraid(0); - - /* Timeout is set before return */ - - break; - } - - case ACT_CURE_CONF: - { - if (!doit) return "cure confusion every 100 turns"; - set_confused(0); - - /* Timeout is set before return */ - - break; - } - - case ACT_CURE_BLIND: - { - if (!doit) return "cure blindness every 100 turns"; - set_blind(0); - - /* Timeout is set before return */ - - break; - } - - case ACT_CURING: - { - if (!doit) return "curing every 110 turns"; - set_blind(0); - set_poisoned(0); - set_confused(0); - set_stun(0); - set_cut(0); - set_image(0); - - /* Timeout is set before return */ - - break; - } - - case ACT_DARKNESS: - { - if (!doit) return "darkness"; - unlite_area(damroll(2, 10), 10); - - /* Timeout is set before return */ - - break; - } - - case ACT_LEV_TELE: - { - if (!doit) return "teleport level every 50 turns"; - teleport_player_level(); - - /* Timeout is set before return */ - - break; - } - - case ACT_ACQUIREMENT: - { - if (!doit) return "acquirement every 3000 turns"; - acquirement(p_ptr->py, p_ptr->px, 1, FALSE, FALSE); - - /* Timeout is set before return */ - - break; - } - - case ACT_WEIRD: - { - if (!doit) return "something weird every 5 turns"; - /* It doesn't do anything */ - - /* Timeout is set before return */ - - break; - } - - case ACT_AGGRAVATE: - { - if (!doit) return "aggravate"; - aggravate_monsters(1); - - /* Timeout is set before return */ - - break; - } - - case ACT_MUT: - { - if (!doit) return "gain corruption every 10 turns"; - gain_random_corruption(); - /* Timeout is set before return */ - - break; - } - - case ACT_CURE_INSANITY: - { - if (!doit) return "cure insanity every 200 turns"; - heal_insanity(damroll(10, 10)); - - /* Timeout is set before return */ - - break; - } - - case ACT_CURE_MUT: - { - msg_print("Ahah, you wish."); - /* Timeout is set before return */ - - break; - } - - case ACT_LIGHT_ABSORBTION: - { - int y, x, light = 0, dir; - cave_type *c_ptr; - - if (!doit) return "light absorption every 80 turns"; - - for (y = p_ptr->py - 6; y <= p_ptr->py + 6; y++) - { - for (x = p_ptr->px - 6; x <= p_ptr->px + 6; x++) - { - if (!in_bounds(y, x)) continue; - - c_ptr = &cave[y][x]; - - if (distance(y, x, p_ptr->py, p_ptr->px) > 6) continue; - - if (c_ptr->info & CAVE_GLOW) - { - light++; - - /* No longer in the array */ - c_ptr->info &= ~(CAVE_TEMP); - - /* Darken the grid */ - c_ptr->info &= ~(CAVE_GLOW); - - /* Hack -- Forget "boring" grids */ - if (cave_plain_floor_grid(c_ptr) && - !(c_ptr->info & (CAVE_TRDT))) - { - /* Forget the grid */ - c_ptr->info &= ~(CAVE_MARK); - - /* Notice */ - note_spot(y, x); - } - - /* Process affected monsters */ - if (c_ptr->m_idx) - { - /* Update the monster */ - update_mon(c_ptr->m_idx, FALSE); - } - - /* Redraw */ - lite_spot(y, x); - } - } - } - - if (!get_aim_dir(&dir)) return (FALSE); - - msg_print("The light around you is absorbed... " - "and released in a powerful bolt!"); - fire_bolt(GF_LITE, dir, damroll(light, p_ptr->lev)); - - /* Timeout is set before return */ - - break; - } - /* Horns of DragonKind (Note that these are new egos)*/ - case ACT_BA_FIRE_H: - { - if (!doit) return "large fire ball (300) every 100 turns"; - fire_ball(GF_FIRE, 5, 300, 7); - - o_ptr->timeout = 100; - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP); - - break; - } - case ACT_BA_COLD_H: - { - if (!doit) return "large cold ball (300) every 100 turns"; - fire_ball(GF_COLD, 5, 300, 7); - - o_ptr->timeout = 100; - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP); - - break; - } - case ACT_BA_ELEC_H: - { - if (!doit) return "large lightning ball (300) every 100 turns"; - fire_ball(GF_ELEC, 5, 300, 7); - - o_ptr->timeout = 100; - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP); - - break; - } - case ACT_BA_ACID_H: - { - if (!doit) return "large acid ball (300) every 100 turns"; - fire_ball(GF_ACID, 5, 300, 7); - - o_ptr->timeout = 100; - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP); - - break; - } - - case ACT_SPIN: - { - if (!doit) return "spinning around every 50+d25 turns"; - do_spin(); - - o_ptr->timeout = 50 + randint(25); - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP); - - /* Done */ - break; - } - case ACT_NOLDOR: - { - if (!doit) return "detect treasure every 10+d20 turns"; - detect_treasure(DEFAULT_RADIUS); - - o_ptr->timeout = 10 + randint(20); - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP); - - /* Done */ - break; - } - case ACT_SPECTRAL: - { - if (!doit) return "wraith-form every 50+d50 turns"; - if (!p_ptr->wraith_form) - { - set_shadow(20 + randint(20)); - } - else - { - set_shadow(p_ptr->tim_wraith + randint(20)); - } - - o_ptr->timeout = 50 + randint(50); - - /* Window stuff */ - p_ptr->window |= PW_INVEN | PW_EQUIP; - - /* Done */ - break; - } - case ACT_JUMP: - { - if (!doit) return "phasing every 10+d10 turns"; - teleport_player(10); - o_ptr->timeout = 10 + randint(10); - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP); - - /* Done */ - break; - } - - case ACT_DEST_TELE: - { - if (!doit) return "teleportation and destruction of the ring"; - if (!item) - { - msg_print("You can't activate this when it's there!"); - } - if (get_check("This will destroy the ring. Do you wish to continue? ")) - { - msg_print("The ring explodes into a space distortion."); - teleport_player(200); - - /* It explodes, doesn't it ? */ - take_hit(damroll(2, 10), "an exploding ring"); - - inc_stack_size_ex(item, -255, OPTIMIZE, NO_DESCRIBE); - } - - break; - } - /*amulet of serpents dam 100, rad 2 timeout 40+d60 */ - case ACT_BA_POIS_4: - { - if (!doit) return "venom breathing every 40+d60 turns"; - /* Get a direction for breathing (or abort) */ - if (!get_aim_dir(&dir)) break; - - msg_print("You breathe venom..."); - fire_ball(GF_POIS, dir, 100, 2); - - o_ptr->timeout = rand_int(60) + 40; - - /* Window stuff */ - p_ptr->window |= PW_INVEN | PW_EQUIP; - - /* Done */ - break; - } - /*rings of X 50,50+d50 dur 20+d20 */ - case ACT_BA_COLD_4: - { - if (!doit) return "ball of cold and resist cold every 50+d50 turns"; - /* Get a direction for breathing (or abort) */ - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_COLD, dir, 50, 2); - (void)set_oppose_cold(p_ptr->oppose_cold + randint(20) + 20); - - o_ptr->timeout = rand_int(50) + 50; - - break; - } - - case ACT_BA_FIRE_4: - { - if (!doit) return "ball of fire and resist fire every 50+d50 turns"; - /* Get a direction for breathing (or abort) */ - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_FIRE, dir, 50, 2); - (void)set_oppose_fire(p_ptr->oppose_fire + randint(20) + 20); - - o_ptr->timeout = rand_int(50) + 50; - - break; - } - case ACT_BA_ACID_4: - { - if (!doit) return "ball of acid and resist acid every 50+d50 turns"; - /* Get a direction for breathing (or abort) */ - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_ACID, dir, 50, 2); - (void)set_oppose_acid(p_ptr->oppose_acid + randint(20) + 20); - - o_ptr->timeout = rand_int(50) + 50; - - break; - } - - case ACT_BA_ELEC_4: - { - if (!doit) return "ball of lightning and resist lightning every 50+d50 turns"; - /* Get a direction for breathing (or abort) */ - if (!get_aim_dir(&dir)) break; - - fire_ball(GF_ELEC, dir, 50, 2); - (void)set_oppose_elec(p_ptr->oppose_elec + randint(20) + 20); - - o_ptr->timeout = rand_int(50) + 50; - - break; - } - - case ACT_BR_ELEC: - { - if (!doit) return "breathe lightning (100) every 90+d90 turns"; - if (!get_aim_dir(&dir)) break; - msg_print("You breathe lightning."); - fire_ball(GF_ELEC, dir, 100, 2); - - o_ptr->timeout = rand_int(90) + 90; - - break; - } - - case ACT_BR_COLD: - { - if (!doit) return "breathe frost (110) every 90+d90 turns"; - if (!get_aim_dir(&dir)) break; - msg_print("You breathe frost."); - fire_ball(GF_COLD, dir, 110, 2); - - o_ptr->timeout = rand_int(90) + 90; - - break; - } - - case ACT_BR_FIRE: - { - if (!doit) return "breathe fire (200) every 90+d90 turns"; - if (!get_aim_dir(&dir)) break; - msg_print("You breathe fire."); - fire_ball(GF_FIRE, dir, 200, 2); - - o_ptr->timeout = rand_int(90) + 90; - - break; - } - - case ACT_BR_ACID: - { - if (!doit) return "breathe acid (130) every 90+d90 turns"; - if (!get_aim_dir(&dir)) break; - msg_print("You breathe acid."); - fire_ball(GF_ACID, dir, 130, 2); - - o_ptr->timeout = rand_int(90) + 90; - - break; - } - - case ACT_BR_POIS: - { - if (!doit) return "breathe poison gas (150) every 90+d90 turns"; - if (!get_aim_dir(&dir)) break; - msg_print("You breathe poison gas."); - fire_ball(GF_POIS, dir, 150, 2); - - o_ptr->timeout = rand_int(90) + 90; - - break; - } - - case ACT_BR_MANY: - { - if (!doit) return "breathe multi-hued (250) every 60+d60 turns"; - if (!get_aim_dir(&dir)) break; - chance = rand_int(5); - msg_format("You breathe %s.", - ((chance == 1) ? "lightning" : - ((chance == 2) ? "frost" : - ((chance == 3) ? "acid" : - ((chance == 4) ? "poison gas" : "fire"))))); - fire_ball(((chance == 1) ? GF_ELEC : - ((chance == 2) ? GF_COLD : - ((chance == 3) ? GF_ACID : - ((chance == 4) ? GF_POIS : GF_FIRE)))), - dir, 250, 2); - - o_ptr->timeout = rand_int(60) + 60; - - break; - } - - case ACT_BR_CONF: - { - if (!doit) return "breathe confusion (120) every 90+d90 turns"; - if (!get_aim_dir(&dir)) break; - msg_print("You breathe confusion."); - fire_ball(GF_CONFUSION, dir, 120, 2); - - o_ptr->timeout = rand_int(90) + 90; - - break; - } - - case ACT_BR_SOUND: - { - if (!doit) return "breathe sound (130) every 90+d90 turns"; - if (!get_aim_dir(&dir)) break; - msg_print("You breathe sound."); - fire_ball(GF_SOUND, dir, 130, 2); - - o_ptr->timeout = rand_int(90) + 90; - - break; - } - - case ACT_BR_CHAOS: - { - if (!doit) return "breathe chaos/disenchant (220) every 60+d90 turns"; - if (!get_aim_dir(&dir)) break; - chance = rand_int(2); - msg_format("You breathe %s.", - ((chance == 1 ? "chaos" : "disenchantment"))); - fire_ball((chance == 1 ? GF_CHAOS : GF_DISENCHANT), - dir, 220, 2); - - o_ptr->timeout = rand_int(90) + 60; - - break; - } - - case ACT_BR_SHARD: - { - if (!doit) return "breathe sound/shards (230) every 60+d90 turns"; - if (!get_aim_dir(&dir)) break; - chance = rand_int(2); - msg_format("You breathe %s.", - ((chance == 1 ? "sound" : "shards"))); - fire_ball((chance == 1 ? GF_SOUND : GF_SHARDS), - dir, 230, 2); - - o_ptr->timeout = rand_int(90) + 60; - - break; - } - - case ACT_BR_BALANCE: - { - if (!doit) return "breathe balance (250) every 60+d90 turns"; - if (!get_aim_dir(&dir)) break; - chance = rand_int(4); - msg_format("You breathe %s.", - ((chance == 1) ? "chaos" : - ((chance == 2) ? "disenchantment" : - ((chance == 3) ? "sound" : "shards")))); - fire_ball(((chance == 1) ? GF_CHAOS : - ((chance == 2) ? GF_DISENCHANT : - ((chance == 3) ? GF_SOUND : GF_SHARDS))), - dir, 250, 2); - - o_ptr->timeout = rand_int(90) + 60; - - break; - } - - case ACT_BR_LIGHT: - { - if (!doit) return "breathe light/darkness (200) every 60+d90 turns"; - if (!get_aim_dir(&dir)) break; - chance = rand_int(2); - msg_format("You breathe %s.", - ((chance == 0 ? "light" : "darkness"))); - fire_ball((chance == 0 ? GF_LITE : GF_DARK), dir, 200, 2); - - o_ptr->timeout = rand_int(90) + 60; - - break; - } - case ACT_BR_POWER: - { - if (!doit) return "breathe the elements (300) every 60+d90 turns"; - if (!get_aim_dir(&dir)) break; - msg_print("You breathe the elements."); - fire_ball(GF_MISSILE, dir, 300, 3); - - o_ptr->timeout = rand_int(90) + 60; - - break; - } - case ACT_GROW_MOLD: - { - if (!doit) return "grow mushrooms every 50+d50 turns"; - msg_print("You twirl and spores fly everywhere!"); - for (i = 0; i < 8; i++) - summon_specific_friendly(p_ptr->py, p_ptr->px, p_ptr->lev, SUMMON_BIZARRE1, FALSE); - - o_ptr->timeout = randint(50) + 50; - - break; - } - case ACT_MUSIC: - /* - fall through to unknown, as music should be - handled by calling procedure. - */ - - default: - { - msg_format("Unknown activation effect: %d.", spell); - if ( !doit ) return "Unknown Activation"; - return NULL; - } - } - } - - /* Set timeout for junkarts - * Note that I still need to set the timeouts for other - * (non-random) artifacts above - */ - if (is_junkart && doit) - o_ptr->timeout = activation_info[o_ptr->pval2].cost / 10; - - return NULL; -} - - -static bool_ activate_spell(object_type * o_ptr, byte choice) -{ - int mana = 0, gf = 0, mod = 0; - - rune_spell s_ptr; - - - if (choice == 1) - { - gf = o_ptr->pval & 0xFFFF; - mod = o_ptr->pval3 & 0xFFFF; - mana = o_ptr->pval2 & 0xFF; - } - else if (choice == 2) - { - gf = o_ptr->pval >> 16; - mod = o_ptr->pval3 >> 16; - mana = o_ptr->pval2 >> 8; - } - - s_ptr.type = gf; - s_ptr.rune2 = 1 << mod; - s_ptr.mana = mana; - - /* Execute */ - rune_exec(&s_ptr, 0); - - if (choice == 1) o_ptr->timeout = mana * 5; - if (choice == 2) o_ptr->xtra2 = mana * 5; - - return (TRUE); -} diff --git a/src/cmd6.cc b/src/cmd6.cc new file mode 100644 index 00000000..b8a9f1df --- /dev/null +++ b/src/cmd6.cc @@ -0,0 +1,7792 @@ +/* File: cmd6.c */ + +/* Purpose: Object commands */ + +/* + * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke + * + * This software may be copied and distributed for educational, research, and + * not for profit purposes provided that this copyright and statement are + * included in all such copies. + */ + +#include "angband.h" + +#include "spell_type.h" +#include "hooks.h" + +/* + * Forward declare + */ +static bool_ activate_spell(object_type * o_ptr, byte choice); + + +/* + * General function to find an item by its name + */ +cptr get_item_hook_find_obj_what; +bool_ get_item_hook_find_obj(int *item) +{ + int i; + char buf[80]; + char buf2[100]; + + strcpy(buf, ""); + if (!get_string(get_item_hook_find_obj_what, buf, 79)) + return FALSE; + + for (i = 0; i < INVEN_TOTAL; i++) + { + object_type *o_ptr = &p_ptr->inventory[i]; + + if (!item_tester_okay(o_ptr)) continue; + + object_desc(buf2, o_ptr, -1, 0); + if (!strcmp(buf, buf2)) + { + *item = i; + return TRUE; + } + } + return FALSE; +} + + +/* + * This file includes code for eating food, drinking potions, + * reading scrolls, aiming wands, using staffs, zapping rods, + * and activating artifacts. + * + * In all cases, if the player becomes "aware" of the item's use + * by testing it, mark it as "aware" and reward some experience + * based on the object's level, always rounding up. If the player + * remains "unaware", mark that object "kind" as "tried". + * + * This code now correctly handles the unstacking of wands, staffs, + * and rods. Note the overly paranoid warning about potential pack + * overflow, which allows the player to use and drop a stacked item. + * + * In all "unstacking" scenarios, the "used" object is "carried" as if + * the player had just picked it up. In particular, this means that if + * the use of an item induces pack overflow, that item will be dropped. + * + * For simplicity, these routines induce a full "pack reorganization" + * which not only combines similar items, but also reorganizes various + * items to obey the current "sorting" method. This may require about + * 400 item comparisons, but only occasionally. + * + * There may be a BIG problem with any "effect" that can cause "changes" + * to the p_ptr->inventory. For example, a "scroll of recharging" can cause + * a wand/staff to "disappear", moving the p_ptr->inventory up. Luckily, the + * scrolls all appear BEFORE the staffs/wands, so this is not a problem. + * But, for example, a "staff of recharging" could cause MAJOR problems. + * In such a case, it will be best to either (1) "postpone" the effect + * until the end of the function, or (2) "change" the effect, say, into + * giving a staff "negative" charges, or "turning a staff into a stick". + * It seems as though a "rod of recharging" might in fact cause problems. + * The basic problem is that the act of recharging (and destroying) an + * item causes the inducer of that action to "move", causing "o_ptr" to + * no longer point at the correct item, with horrifying results. + * + * Note that food/potions/scrolls no longer use bit-flags for effects, + * but instead use the "sval" (which is also used to sort the objects). + */ + + +/* + * Determine the effects of eating a corpse. A corpse can be + * eaten whole or cut into pieces for later. + */ +static void corpse_effect(object_type *o_ptr, bool_ cutting) +{ + monster_race *r_ptr = &r_info[o_ptr->pval2]; + + /* Assume no bad effects */ + bool_ harmful = FALSE; + + byte method, effect, d_dice, d_side; + + int i, dam, idam = 0, mdam, brpow, brdam = 0; + + + /* How much of the monster's breath attack remains */ + if (o_ptr->pval <= r_ptr->weight) + { + brpow = 0; + } + else + { + brpow = (o_ptr->pval - r_ptr->weight) / 5; + if (brpow > (r_ptr->weight / 5)) brpow = r_ptr->weight / 5; + } + + if (o_ptr->weight <= 0) o_ptr->weight = 1; + if (o_ptr->pval <= 0) o_ptr->pval = 1; + + /* + * The breath is only discharged by accident or by slicing off pieces + * of meat, and only by corpses. + */ + if ((o_ptr->sval != SV_CORPSE_CORPSE) || + (rand_int(o_ptr->weight / 5) && !cutting)) brpow = 0; + + /* Immediate effects - poison, acid, fire, etc. */ + if (!cutting) + { + for (i = 0; i < 4; i++) + { + /* skip empty blow slot */ + if (!r_ptr->blow[i].method) continue; + + method = r_ptr->blow[i].method; + effect = r_ptr->blow[i].effect; + d_dice = r_ptr->blow[i].d_dice; + d_side = r_ptr->blow[i].d_side; + dam = damroll(d_dice, d_side) * o_ptr->pval / o_ptr->weight / 2; + idam = damroll(d_dice, d_side) * + ((o_ptr->weight / o_ptr->pval > 2) ? + o_ptr->weight / o_ptr->pval : 2); + mdam = maxroll(d_dice, d_side) * 2; + + /* Analyse method */ + switch (method) + { + /* Methods that are meaningless after death */ + case RBM_BITE: + case RBM_STING: + case RBM_ENGULF: + case RBM_DROOL: + case RBM_SPIT: + case RBM_GAZE: + case RBM_WAIL: + case RBM_BEG: + case RBM_INSULT: + case RBM_MOAN: + { + continue; + } + } + + /* Analyse effect */ + switch (effect) + { + /* Effects that are meaningless after death */ + case RBE_HURT: + case RBE_UN_BONUS: + case RBE_UN_POWER: + case RBE_EAT_GOLD: + case RBE_EAT_ITEM: + case RBE_EAT_FOOD: + case RBE_EAT_LITE: + case RBE_ELEC: + case RBE_COLD: + case RBE_SHATTER: + { + break; + } + + case RBE_POISON: + { + if (!(p_ptr->resist_pois || p_ptr->oppose_pois)) + { + set_poisoned(p_ptr->poisoned + dam + idam + 10); + harmful = TRUE; + } + + break; + } + + case RBE_ACID: + { + /* Total Immunity */ + if (!(p_ptr->immune_acid || (dam <= 0))) + { + /* Resist the damage */ + if (p_ptr->resist_acid) dam = (dam + 2) / 3; + if (p_ptr->oppose_acid) dam = (dam + 2) / 3; + + /* Take damage */ + take_hit(dam, "acidic food"); + harmful = TRUE; + } + else + { + set_oppose_acid(p_ptr->oppose_acid + idam); + } + + break; + } + + case RBE_FIRE: + { + /* Totally immune */ + if (p_ptr->immune_fire || (dam <= 0)) + { + /* Resist the damage */ + if (p_ptr->resist_fire) dam = (dam + 2) / 3; + if (p_ptr->oppose_fire) dam = (dam + 2) / 3; + + /* Take damage */ + take_hit(dam, "a fiery meal"); + harmful = TRUE; + } + else + { + set_oppose_fire(p_ptr->oppose_fire + idam); + } + + break; + } + + case RBE_BLIND: + { + if (!p_ptr->resist_blind) + { + set_blind(p_ptr->blind + dam * 2 + idam * 2 + 20); + } + + break; + } + + case RBE_CONFUSE: + { + if (!p_ptr->resist_conf) + { + set_confused(p_ptr->confused + dam + idam + 10); + } + if (!p_ptr->resist_chaos && rand_int(mdam - dam)) + { + set_image(p_ptr->image + dam * 10 + idam * 10 + 100); + } + + break; + } + + case RBE_HALLU: + { + if (!p_ptr->resist_chaos && rand_int(mdam - dam)) + { + set_image(p_ptr->image + dam * 10 + idam * 10 + 50); + } + + break; + } + + case RBE_TERRIFY: + { + if (!p_ptr->resist_fear) + { + set_afraid(p_ptr->afraid + dam + idam + 10); + } + + break; + } + + case RBE_PARALYZE: + { + if (!p_ptr->free_act) + { + set_paralyzed(dam + idam + 10); + } + + break; + } + + case RBE_LOSE_STR: + { + do_dec_stat(A_STR, STAT_DEC_NORMAL); + + break; + } + + case RBE_LOSE_INT: + { + do_dec_stat(A_INT, STAT_DEC_NORMAL); + + break; + } + + case RBE_LOSE_WIS: + { + do_dec_stat(A_WIS, STAT_DEC_NORMAL); + + break; + } + + case RBE_LOSE_DEX: + { + do_dec_stat(A_DEX, STAT_DEC_NORMAL); + + break; + } + + case RBE_LOSE_CON: + { + do_dec_stat(A_CON, STAT_DEC_NORMAL); + + break; + } + + case RBE_LOSE_CHR: + { + do_dec_stat(A_CHR, STAT_DEC_NORMAL); + + break; + } + + /* Don't eat Morgoth's corpse :) */ + case RBE_LOSE_ALL: + { + do_dec_stat(A_STR, STAT_DEC_NORMAL); + do_dec_stat(A_INT, STAT_DEC_NORMAL); + do_dec_stat(A_WIS, STAT_DEC_NORMAL); + do_dec_stat(A_DEX, STAT_DEC_NORMAL); + do_dec_stat(A_CON, STAT_DEC_NORMAL); + do_dec_stat(A_CHR, STAT_DEC_NORMAL); + o_ptr->pval = 1; + + break; + } + + case RBE_SANITY: + { + msg_print("You feel your sanity slipping away!"); + take_sanity_hit(dam, "eating an insane monster"); + + break; + } + + /* Unlife is bad to eat */ + case RBE_EXP_10: + { + msg_print("A black aura surrounds the corpse!"); + + if (p_ptr->hold_life && (rand_int(100) < 50)) + { + msg_print("You keep hold of your life force!"); + } + else + { + s32b d = damroll(10, 6) + + (p_ptr->exp / 100) * MON_DRAIN_LIFE; + + if (p_ptr->hold_life) + { + msg_print("You feel your life slipping away!"); + lose_exp(d / 10); + } + else + { + msg_print("You feel your life draining away!"); + lose_exp(d); + } + } + + o_ptr->pval = 1; + + break; + } + + case RBE_EXP_20: + { + msg_print("A black aura surrounds the corpse!"); + + if (p_ptr->hold_life && (rand_int(100) < 50)) + { + msg_print("You keep hold of your life force!"); + } + else + { + s32b d = damroll(20, 6) + + (p_ptr->exp / 100) * MON_DRAIN_LIFE; + + if (p_ptr->hold_life) + { + msg_print("You feel your life slipping away!"); + lose_exp(d / 10); + } + else + { + msg_print("You feel your life draining away!"); + lose_exp(d); + } + } + + o_ptr->pval = 1; + + break; + } + + case RBE_EXP_40: + { + msg_print("A black aura surrounds the corpse!"); + + if (p_ptr->hold_life && (rand_int(100) < 50)) + { + msg_print("You keep hold of your life force!"); + } + else + { + s32b d = damroll(40, 6) + + (p_ptr->exp / 100) * MON_DRAIN_LIFE; + + if (p_ptr->hold_life) + { + msg_print("You feel your life slipping away!"); + lose_exp(d / 10); + } + else + { + msg_print("You feel your life draining away!"); + lose_exp(d); + } + } + + o_ptr->pval = 1; + + break; + } + + case RBE_EXP_80: + { + msg_print("A black aura surrounds the corpse!"); + + if (p_ptr->hold_life && (rand_int(100) < 50)) + { + msg_print("You keep hold of your life force!"); + } + else + { + s32b d = damroll(80, 6) + + (p_ptr->exp / 100) * MON_DRAIN_LIFE; + + if (p_ptr->hold_life) + { + msg_print("You feel your life slipping away!"); + lose_exp(d / 10); + } + else + { + msg_print("You feel your life draining away!"); + lose_exp(d); + } + } + + o_ptr->pval = 1; + + break; + } + } + } + } /* if (!cutting) */ + + + /* + * The organ that supplies breath attacks is not + * immediately emptied upon death, although some types + * of breath have no effect. + * AMHD's make rather risky meals, and deadly snacks. + */ + + /* Acid */ + if (r_ptr->flags4 & RF4_BR_ACID && brpow > 0) + { + brdam = ((brpow / 3) > 1600 ? 1600 : (brpow / 3)); + + msg_print("You are hit by a gush of acid!"); + + /* Total Immunity */ + if (!(p_ptr->immune_acid || (brdam <= 0))) + { + /* Take damage */ + acid_dam(brdam, "a gush of acid"); + harmful = TRUE; + } + o_ptr->pval = 1; + } + else if (r_ptr->flags4 & RF4_BR_ACID) + { + set_oppose_acid(p_ptr->oppose_acid + rand_int(10) + 10); + } + + /* Electricity */ + if (r_ptr->flags4 & RF4_BR_ELEC && brpow > 0) + { + brdam = ((brpow / 3) > 1600 ? 1600 : (brpow / 3)); + + msg_print("You receive a heavy shock!"); + + /* Total Immunity */ + if (!(p_ptr->immune_elec || (brdam <= 0))) + { + /* Take damage */ + elec_dam(brdam, "an electric shock"); + harmful = TRUE; + } + o_ptr->weight = o_ptr->weight - brpow; + o_ptr->pval = o_ptr->weight; + } + else if (r_ptr->flags4 & RF4_BR_ELEC) + { + set_oppose_elec(p_ptr->oppose_elec + rand_int(10) + 10); + } + + /* Fire */ + if (r_ptr->flags4 & RF4_BR_FIRE && brpow > 0) + { + brdam = ((brpow / 3) > 1600 ? 1600 : (brpow / 3)); + + msg_print("Roaring flames engulf you!"); + + /* Total Immunity */ + if (!(p_ptr->immune_fire || (brdam <= 0))) + { + /* Take damage */ + fire_dam(brdam, "an explosion"); + harmful = TRUE; + } + o_ptr->pval = 1; + } + else if (r_ptr->flags4 & RF4_BR_FIRE) + { + set_oppose_fire(p_ptr->oppose_fire + rand_int(10) + 10); + } + + /* Cold */ + if (r_ptr->flags4 & RF4_BR_COLD && brpow > 0) + { + brdam = ((brpow / 3) > 1600 ? 1600 : (brpow / 3)); + + msg_print("You are caught in a freezing liquid!"); + + /* Total Immunity */ + if (!(p_ptr->immune_cold || (brdam <= 0))) + { + /* Take damage */ + cold_dam(brdam, "a chilling blast"); + harmful = TRUE; + } + o_ptr->weight = o_ptr->weight - brpow; + o_ptr->pval = o_ptr->weight; + } + else if (r_ptr->flags4 & RF4_BR_COLD) + { + set_oppose_cold(p_ptr->oppose_cold + rand_int(10) + 10); + } + + /* Poison */ + if (r_ptr->flags4 & RF4_BR_POIS && brpow > 0) + { + brdam = ((brpow / 3) > 800 ? 800 : (brpow / 3)); + + msg_print("You are surrounded by toxic gases!"); + + /* Resist the damage */ + if (p_ptr->resist_pois) brdam = (brdam + 2) / 3; + if (p_ptr->oppose_pois) brdam = (brdam + 2) / 3; + + if (!(p_ptr->resist_pois || p_ptr->oppose_pois)) + { + (void)set_poisoned(p_ptr->poisoned + rand_int(brdam) + 10); + } + + /* Take damage */ + take_hit(brdam, "toxic gases"); + o_ptr->weight = o_ptr->weight - brpow; + o_ptr->pval = o_ptr->weight; + harmful = TRUE; + } + + /* Nether */ + if (r_ptr->flags4 & RF4_BR_NETH && brpow > 0) + { + brdam = ((brpow / 6) > 550 ? 550 : (brpow / 6)); + + msg_print("A black aura surrounds the corpse!"); + + if (p_ptr->resist_neth) + { + brdam *= 6; + brdam /= (randint(6) + 6); + } + else + { + if (p_ptr->hold_life && (rand_int(100) < 75)) + { + msg_print("You keep hold of your life force!"); + } + else if (p_ptr->hold_life) + { + msg_print("You feel your life slipping away!"); + lose_exp(200 + (p_ptr->exp / 1000) * MON_DRAIN_LIFE); + } + else + { + msg_print("You feel your life draining away!"); + lose_exp(200 + (p_ptr->exp / 100) * MON_DRAIN_LIFE); + } + } + + /* Take damage */ + take_hit(brdam, "an unholy blast"); + harmful = TRUE; + o_ptr->weight = o_ptr->weight - brpow; + o_ptr->pval = o_ptr->weight; + } + + /* Confusion */ + if (r_ptr->flags4 & RF4_BR_CONF && brpow > 0) + { + msg_print("A strange liquid splashes on you!"); + + if (!p_ptr->resist_conf) + { + set_confused(p_ptr->confused + brdam + idam + 10); + } + o_ptr->weight = o_ptr->weight - brpow; + o_ptr->pval = o_ptr->weight; + } + + /* Chaos */ + if (r_ptr->flags4 & RF4_BR_CHAO && brpow > 0) + { + brdam = ((brpow / 6) > 600 ? 600 : (brpow / 6)); + + msg_print("A swirling cloud surrounds you!"); + + if (p_ptr->resist_chaos) + { + brdam *= 6; + brdam /= (randint(6) + 6); + } + + if (!p_ptr->resist_conf) + { + (void)set_confused(p_ptr->confused + rand_int(20) + 10); + } + + if (!p_ptr->resist_chaos) + { + (void)set_image(p_ptr->image + randint(10)); + } + + if (!p_ptr->resist_neth && !p_ptr->resist_chaos) + { + if (p_ptr->hold_life && (rand_int(100) < 75)) + { + msg_print("You keep hold of your life force!"); + } + else if (p_ptr->hold_life) + { + msg_print("You feel your life slipping away!"); + lose_exp(500 + (p_ptr->exp / 1000) * MON_DRAIN_LIFE); + } + else + { + msg_print("You feel your life draining away!"); + lose_exp(5000 + (p_ptr->exp / 100) * MON_DRAIN_LIFE); + } + } + + /* Take damage */ + take_hit(brdam, "chaotic forces"); + o_ptr->pval = 1; + } + + /* Disenchantment */ + if (r_ptr->flags4 & RF4_BR_DISE && brpow > 0) + { + brdam = ((brpow / 6) > 500 ? 500 : (brpow / 6)); + + msg_print("You are blasted by raw mana!"); + + if (p_ptr->resist_disen) + { + brdam *= 6; + brdam /= (randint(6) + 6); + } + else + { + (void)apply_disenchant(0); + } + + /* Take damage */ + take_hit(brdam, "raw mana"); + o_ptr->pval = 1; + } + + /* Plasma */ + if (r_ptr->flags4 & RF4_BR_PLAS && brpow > 0) + { + brdam = ((brpow / 6) > 150 ? 150 : (brpow / 6)); + + msg_print("Searing flames engulf the corpse!"); + + /* Resist the damage */ + if (p_ptr->resist_fire || p_ptr->oppose_fire) brdam = (brdam + 2) / 3; + + if (!p_ptr->resist_sound) + { + int k = (randint((brdam > 40) ? 35 : (brdam * 3 / 4 + 5))); + (void)set_stun(p_ptr->stun + k); + } + + /* Take damage */ + take_hit(brdam, "an explosion"); + harmful = TRUE; + o_ptr->pval = 1; + } + + /* Hack -- Jellies are immune to acid only if they are already acidic */ + if (strchr("j", r_ptr->d_char) && (r_ptr->flags3 & RF3_IM_ACID)) + { + dam = damroll(8, 8); + + /* Total Immunity */ + if (!(p_ptr->immune_acid || (dam <= 0))) + { + /* Resist the damage */ + if (p_ptr->resist_acid) dam = (dam + 2) / 3; + if (p_ptr->oppose_acid) dam = (dam + 2) / 3; + + /* Take damage */ + take_hit(dam, "acidic food"); + } + harmful = TRUE; + } + + /* + * Hack -- Jellies, kobolds, spiders, icky things, molds, and mushrooms + * are immune to poison because their body already contains + * poisonous chemicals. + */ + if (strchr("ijkmS,", r_ptr->d_char) && (r_ptr->flags3 & RF3_IM_POIS)) + { + if (!(p_ptr->resist_pois || p_ptr->oppose_pois)) + { + set_poisoned(p_ptr->poisoned + rand_int(15) + 10); + } + harmful = TRUE; + } + + /* + * Bad effects override good effects + * and hacked-up corpses lose intrinsics. + */ + if (!harmful && !cutting && (o_ptr->sval != SV_CORPSE_MEAT)) + { + if (r_ptr->flags3 & RF3_IM_ACID) + { + set_oppose_acid(p_ptr->oppose_acid + rand_int(10) + 10); + } + if (r_ptr->flags3 & RF3_IM_ELEC) + { + set_oppose_elec(p_ptr->oppose_elec + rand_int(10) + 10); + } + if (r_ptr->flags3 & RF3_IM_FIRE) + { + set_oppose_fire(p_ptr->oppose_fire + rand_int(10) + 10); + } + if (r_ptr->flags3 & RF3_IM_COLD) + { + set_oppose_cold(p_ptr->oppose_cold + rand_int(10) + 10); + } + if (r_ptr->flags3 & RF3_IM_POIS) + { + set_oppose_pois(p_ptr->oppose_pois + rand_int(10) + 10); + } + if (r_ptr->flags3 & RF3_RES_NETH) + { + set_protevil(p_ptr->protevil + rand_int(25) + 3 * r_ptr->level); + } + if (r_ptr->flags3 & RF3_RES_PLAS) + { + set_oppose_fire(p_ptr->oppose_fire + rand_int(20) + 20); + } + if (r_ptr->flags2 & RF2_SHAPECHANGER) + { + /* DGDGDG (void)set_mimic(20 , rand_int(MIMIC_VALAR)); */ + } + + if (r_ptr->flags3 & RF3_DEMON) + { + /* DGDGDG (void)set_mimic(30 , MIMIC_DEMON); */ + } + + if (r_ptr->flags3 & RF3_UNDEAD) + { + /* DGDGDG (void)set_mimic(30 , MIMIC_VAMPIRE); */ + } + + if (r_ptr->flags3 & RF3_NO_FEAR) + { + (void)set_afraid(0); + } + if (r_ptr->flags3 & RF3_NO_STUN) + { + (void)set_stun(0); + } + if (r_ptr->flags3 & RF3_NO_CONF) + { + (void)set_confused(0); + } + if (r_ptr->flags6 & RF6_S_THUNDERLORD) + { + summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_THUNDERLORD, FALSE); + } + if (r_ptr->flags6 & RF6_S_DEMON) + { + summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_DEMON, FALSE); + } + if (r_ptr->flags6 & RF6_S_KIN) + { + summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_KIN, FALSE); + } + if (r_ptr->flags6 & RF6_S_HI_DEMON) + { + summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_HI_DEMON, FALSE); + } + if (r_ptr->flags6 & RF6_S_MONSTER) + { + summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, 0, FALSE); + } + if (r_ptr->flags6 & RF6_S_MONSTERS) + { + int k; + for (k = 0; k < 8; k++) + { + summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, 0, FALSE); + } + } + if (r_ptr->flags6 & RF6_S_UNDEAD) + { + summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_UNDEAD, FALSE); + } + if (r_ptr->flags6 & RF6_S_DRAGON) + { + summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_DRAGON, FALSE); + } + if (r_ptr->flags6 & RF6_S_ANT) + { + summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_ANT, FALSE); + } + if (r_ptr->flags6 & RF6_S_SPIDER) + { + summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_SPIDER, FALSE); + } + if (r_ptr->flags6 & RF6_S_HOUND) + { + summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_HOUND, FALSE); + } + if (r_ptr->flags6 & RF6_S_HYDRA) + { + summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_HYDRA, FALSE); + } + if (r_ptr->flags6 & RF6_S_ANGEL) + { + summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_ANGEL, FALSE); + } + if (r_ptr->flags6 & RF6_S_HI_DRAGON) + { + summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_HI_DRAGON, FALSE); + } + if (r_ptr->flags6 & RF6_S_HI_UNDEAD) + { + summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_HI_UNDEAD, FALSE); + } + if (r_ptr->flags6 & RF6_S_WRAITH) + { + summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_WRAITH, FALSE); + } + if (r_ptr->flags6 & RF6_S_UNIQUE) + { + summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_UNIQUE, FALSE); + } + } +} + + +/* + * Hook to determine if an object is eatable + */ +static bool_ item_tester_hook_eatable(object_type *o_ptr) +{ + /* Foods and, well, corpses are edible */ + if ((o_ptr->tval == TV_FOOD) || (o_ptr->tval == TV_CORPSE)) return (TRUE); + + /* Assume not */ + return (FALSE); +} + + +/* + * Eat some food (from the pack or floor) + */ +void do_cmd_eat_food(void) +{ + int item, ident, lev, fval = 0; + + object_type *o_ptr; + object_type *q_ptr, forge; + + monster_race *r_ptr; + + cptr q, s; + + bool_ destroy = TRUE; + + + /* Restrict choices to food */ + item_tester_hook = item_tester_hook_eatable; + + /* Set up the extra finder */ + get_item_hook_find_obj_what = "Food full name? "; + get_item_extra_hook = get_item_hook_find_obj; + + /* Get an item */ + q = "Eat which item? "; + s = "You have nothing to eat."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EXTRA))) return; + + /* Get the item */ + o_ptr = get_object(item); + + /* Sound */ + sound(SOUND_EAT); + + + /* Take a turn */ + energy_use = 100; + + /* Identity not known yet */ + ident = FALSE; + + /* Object level */ + lev = k_info[o_ptr->k_idx].level; + + /* Scripted foods */ + hook_eat_in in = { o_ptr }; + hook_eat_out out = { FALSE }; + + if (process_hooks_ret(HOOK_EAT, "d", "(O)", o_ptr)) + { + ident = process_hooks_return[0].num; + } + else if (process_hooks_new(HOOK_EAT, &in, &out)) + { + ident = out.ident; + } + /* (not quite) Normal foods */ + else if (o_ptr->tval == TV_FOOD) + { + /* Analyze the food */ + switch (o_ptr->sval) + { + case SV_FOOD_GREAT_HEALTH: + { + p_ptr->hp_mod += 70; + msg_print("As you eat it you begin to feel your life flow getting stronger."); + ident = TRUE; + p_ptr->update |= (PU_HP); + + break; + } + + case SV_FOOD_POISON: + { + if (!(p_ptr->resist_pois || p_ptr->oppose_pois)) + { + if (set_poisoned(p_ptr->poisoned + rand_int(10) + 10)) + { + ident = TRUE; + } + } + + break; + } + + case SV_FOOD_BLINDNESS: + { + if (!p_ptr->resist_blind) + { + if (set_blind(p_ptr->blind + rand_int(200) + 200)) + { + ident = TRUE; + } + } + + break; + } + + case SV_FOOD_PARANOIA: + { + if (!p_ptr->resist_fear) + { + if (set_afraid(p_ptr->afraid + rand_int(10) + 10)) + { + ident = TRUE; + } + } + + break; + } + + case SV_FOOD_CONFUSION: + { + if (!p_ptr->resist_conf) + { + if (set_confused(p_ptr->confused + rand_int(10) + 10)) + { + ident = TRUE; + } + } + + break; + } + + case SV_FOOD_HALLUCINATION: + { + if (!p_ptr->resist_chaos) + { + if (set_image(p_ptr->image + rand_int(250) + 250)) + { + ident = TRUE; + } + } + + break; + } + + case SV_FOOD_PARALYSIS: + { + if (!p_ptr->free_act) + { + if (set_paralyzed(rand_int(10) + 10)) + { + ident = TRUE; + } + } + + break; + } + + case SV_FOOD_WEAKNESS: + { + take_hit(damroll(6, 6), "poisonous food"); + (void)do_dec_stat(A_STR, STAT_DEC_NORMAL); + + ident = TRUE; + + break; + } + + case SV_FOOD_SICKNESS: + { + take_hit(damroll(6, 6), "poisonous food"); + (void)do_dec_stat(A_CON, STAT_DEC_NORMAL); + + ident = TRUE; + + break; + } + + case SV_FOOD_STUPIDITY: + { + take_hit(damroll(8, 8), "poisonous food"); + (void)do_dec_stat(A_INT, STAT_DEC_NORMAL); + + ident = TRUE; + + break; + } + + case SV_FOOD_NAIVETY: + { + take_hit(damroll(8, 8), "poisonous food"); + (void)do_dec_stat(A_WIS, STAT_DEC_NORMAL); + + ident = TRUE; + + break; + } + + case SV_FOOD_UNHEALTH: + { + take_hit(damroll(10, 10), "poisonous food"); + (void)do_dec_stat(A_CON, STAT_DEC_NORMAL); + + ident = TRUE; + + break; + } + + case SV_FOOD_DISEASE: + { + take_hit(damroll(10, 10), "poisonous food"); + (void)do_dec_stat(A_STR, STAT_DEC_NORMAL); + + ident = TRUE; + + break; + } + + case SV_FOOD_CURE_POISON: + { + if (set_poisoned(0)) ident = TRUE; + + break; + } + + case SV_FOOD_CURE_BLINDNESS: + { + if (set_blind(0)) ident = TRUE; + + break; + } + + case SV_FOOD_CURE_PARANOIA: + { + if (set_afraid(0)) ident = TRUE; + + break; + } + + case SV_FOOD_CURE_CONFUSION: + { + if (set_confused(0)) ident = TRUE; + + break; + } + + case SV_FOOD_CURE_SERIOUS: + { + if (hp_player(damroll(4, 8))) ident = TRUE; + + break; + } + + case SV_FOOD_RESTORE_STR: + { + if (do_res_stat(A_STR, TRUE)) ident = TRUE; + + break; + } + + case SV_FOOD_RESTORE_CON: + { + if (do_res_stat(A_CON, TRUE)) ident = TRUE; + + break; + } + + case SV_FOOD_RESTORING: + { + if (do_res_stat(A_STR, TRUE)) ident = TRUE; + if (do_res_stat(A_INT, TRUE)) ident = TRUE; + if (do_res_stat(A_WIS, TRUE)) ident = TRUE; + if (do_res_stat(A_DEX, TRUE)) ident = TRUE; + if (do_res_stat(A_CON, TRUE)) ident = TRUE; + if (do_res_stat(A_CHR, TRUE)) ident = TRUE; + + break; + } + + case SV_FOOD_FORTUNE_COOKIE: + { + char rumour[80]; + + msg_print("That tastes good."); + msg_print("There is message in the cookie. It says:"); + msg_print(NULL); + + switch (randint(20)) + { + case 1: + { + get_rnd_line("chainswd.txt", rumour); + break; + } + + case 2: + { + get_rnd_line("error.txt", rumour); + break; + } + + case 3: + case 4: + case 5: + { + get_rnd_line("death.txt", rumour); + break; + } + + default: + { + get_rnd_line("rumors.txt", rumour); + break; + } + } + + msg_format("%s", rumour); + msg_print(NULL); + + ident = TRUE; + + break; + } + + + case SV_FOOD_RATION: + case SV_FOOD_BISCUIT: + case SV_FOOD_JERKY: + { + msg_print("That tastes good."); + + ident = TRUE; + + break; + } + + case SV_FOOD_SLIME_MOLD: + { + msg_print("That tastes good."); + + /* 2% chance of getting the mold power */ + if (magik(2)) + { + ADD_POWER(p_ptr->powers_mod, PWR_GROW_MOLD); + p_ptr->update |= PU_POWERS; + } + + ident = TRUE; + + break; + } + + case SV_FOOD_WAYBREAD: + { + msg_print("That tastes very good."); + (void)set_poisoned(0); + (void)hp_player(damroll(4, 8)); + set_food(PY_FOOD_MAX - 1); + + ident = TRUE; + + break; + } + + case SV_FOOD_PINT_OF_ALE: + case SV_FOOD_PINT_OF_WINE: + { + msg_print("That tastes good."); + + ident = TRUE; + + q_ptr = &forge; + object_prep(q_ptr, lookup_kind(TV_BOTTLE, 1)); + q_ptr->number = 1; + object_aware(q_ptr); + object_known(q_ptr); + q_ptr->ident |= IDENT_STOREB; + (void)inven_carry(q_ptr, FALSE); + + break; + } + + case SV_FOOD_ATHELAS: + { + msg_print("A fresh, clean essence rises, driving away wounds and poison."); + + (void)set_poisoned(0); + (void)set_stun(0); + (void)set_cut(0); + if (p_ptr->black_breath) + { + msg_print("The hold of the Black Breath on you is broken!"); + p_ptr->black_breath = FALSE; + } + + ident = TRUE; + + break; + } + } + } + + /* Corpses... */ + else + { + r_ptr = &r_info[o_ptr->pval2]; + + /* Analyse the corpse */ + switch (o_ptr->sval) + { + case SV_CORPSE_CORPSE: + { + bool_ no_meat = FALSE; + + /* Not all is edible. Apologies if messy. */ + + /* Check weight -- they have to have some meat left */ + if (r_ptr->flags9 & RF9_DROP_SKELETON) + { + if (o_ptr->weight <= (r_ptr->weight * 3) / 5) + { + no_meat = TRUE; + } + } + + /* Non-skeletons are naturally have more allowances */ + else + { + if (o_ptr->weight <= (r_ptr->weight * 7) / 20) + { + no_meat = TRUE; + } + } + + /* Nothing left to eat */ + if (no_meat) + { + msg_print("There is not enough meat."); + return; + } + + + /* Check freshness */ + if (!o_ptr->timeout) msg_print("Ugh! Raw meat!"); + else msg_print("That tastes good."); + + + /* A pound of raw meat */ + o_ptr->pval -= 10; + o_ptr->weight -= 10; + + /* Corpses still have meat on them */ + destroy = FALSE; + + ident = TRUE; + + break; + } + + case SV_CORPSE_HEAD: + { + msg_print("You feel rather sick."); + + /* A pound of raw meat */ + o_ptr->pval -= 10; + o_ptr->weight -= 10; + + /* Corpses still have meat on them */ + destroy = FALSE; + + ident = TRUE; + + break; + } + + case SV_CORPSE_MEAT: + { + /* Just meat */ + if (!o_ptr->timeout) msg_print("You quickly swallow the meat."); + else msg_print("That tastes good."); + + ident = TRUE; + + /* Those darn microorganisms */ + if (!o_ptr->timeout && (o_ptr->weight > o_ptr->pval) && + !(p_ptr->resist_pois || p_ptr->oppose_pois)) + { + set_poisoned(p_ptr->poisoned + rand_int(o_ptr->weight - o_ptr->pval) + + (o_ptr->weight - o_ptr->pval)); + } + + break; + } + } + + corpse_effect(o_ptr, FALSE); + + /* Less nutritious than food rations, but much more of it. */ + fval = (o_ptr->timeout) ? 2000 : 2500; + + /* Those darn microorganisms */ + if (!o_ptr->timeout && (o_ptr->weight - o_ptr->pval > 10) && + !(p_ptr->resist_pois || p_ptr->oppose_pois)) + { + set_poisoned(p_ptr->poisoned + rand_int(o_ptr->weight - o_ptr->pval) + + (o_ptr->weight - o_ptr->pval)); + } + + /* Partially cured */ + if (o_ptr->weight > o_ptr->timeout) + { + /* Adjust the "timeout" without overflowing */ + o_ptr->timeout = (o_ptr->timeout * ((100 * o_ptr->timeout) / o_ptr->weight)) / 100; + } + } + + + /* Combine / Reorder the pack (later) */ + p_ptr->notice |= (PN_COMBINE | PN_REORDER); + + /* We have tried it */ + object_tried(o_ptr); + + /* The player is now aware of the object */ + if (ident && !object_aware_p(o_ptr)) + { + object_aware(o_ptr); + gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev); + } + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + + if (!fval) fval = o_ptr->pval; + + /* Food can feed the player, in a different ways */ + + /* Vampires */ + if ((PRACE_FLAG(PR1_VAMPIRE)) || (p_ptr->mimic_form == resolve_mimic_name("Vampire"))) + { + /* Reduced nutritional benefit */ + /* (void)set_food(p_ptr->food + (fval / 10)); -- No more */ + msg_print("Mere victuals hold scant sustenance for a being such as yourself."); + + /* Hungry */ + if (p_ptr->food < PY_FOOD_ALERT) + { + msg_print("Your hunger can only be satisfied with fresh blood!"); + } + } + + else if (PRACE_FLAG(PR1_NO_FOOD)) + { + if (PRACE_FLAG(PR1_UNDEAD)) + { + msg_print("The food of mortals is poor sustenance for you."); + } + else + { + msg_print("Food is poor sustenance for you."); + } + set_food(p_ptr->food + ((fval) / 40)); + } + + /* Those living in fresh */ + else + { + (void)set_food(p_ptr->food + fval); + } + + + /* Destroy food? */ + if (destroy) + { + inc_stack_size(item, -1); + } +} + + +/* + * Cut a corpse up for convenient storage + */ +void do_cmd_cut_corpse(void) +{ + int item, meat = 0, not_meat = 0; + + object_type *o_ptr; + + object_type *i_ptr; + + object_type object_type_body; + + monster_race *r_ptr; + + cptr q, s; + + + /* Restrict choices to corpses */ + item_tester_tval = TV_CORPSE; + + /* Get an item */ + q = "Hack up which corpse? "; + s = "You have no corpses."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; + + /* Get the item */ + o_ptr = get_object(item); + + r_ptr = &r_info[o_ptr->pval2]; + + if ((o_ptr->sval != SV_CORPSE_CORPSE) && (o_ptr->sval != SV_CORPSE_HEAD)) + { + msg_print ("You cannot split that."); + return; + } + + switch (o_ptr->sval) + { + case SV_CORPSE_CORPSE: + { + if (r_ptr->flags9 & RF9_DROP_SKELETON) + { + not_meat = (r_ptr->weight * 3) / 5; + } + else + { + not_meat = (r_ptr->weight * 7) / 20; + } + meat = r_ptr->weight + r_ptr->weight / 10 - not_meat; + + break; + } + + case SV_CORPSE_HEAD: + { + not_meat = r_ptr->weight / 150; + meat = r_ptr->weight / 30 + r_ptr->weight / 300 - not_meat; + + break; + } + } + + if ((o_ptr->weight <= not_meat) || (meat < 10)) + { + msg_print("There is not enough meat."); + return; + } + + /* Hacking 10 pounds off */ + if (meat > 100) meat = 100; + + /* Take a turn */ + energy_use = 100; + + o_ptr->pval -= meat; + o_ptr->weight -= meat; + + msg_print("You hack some meat off the corpse."); + + corpse_effect(o_ptr, TRUE); + + /* Get local object */ + i_ptr = &object_type_body; + + /* Make some meat */ + object_prep(i_ptr, lookup_kind(TV_CORPSE, SV_CORPSE_MEAT)); + + i_ptr->number = meat / 10; + i_ptr->pval2 = o_ptr->pval2; + + /* Length of time before decay */ + i_ptr->pval = 1000 + rand_int(1000); + + if (inven_carry_okay(i_ptr)) + { + inven_carry(i_ptr, TRUE); + } + else + { + drop_near(i_ptr, 0, p_ptr->py, p_ptr->px); + } +} + + +/* + * Use a potion to cure some meat + * + * Salt water works well. + */ +void do_cmd_cure_meat(void) +{ + int item, num, cure; + + object_type *o_ptr; + + object_type *i_ptr; + + cptr q, s; + + + /* Restrict choices to corpses */ + item_tester_tval = TV_CORPSE; + item_tester_hook = item_tester_hook_eatable; + + /* Get some meat */ + q = "Cure which meat? "; + s = "You have no meat to cure."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; + + /* Get the item */ + o_ptr = get_object(item); + + /* Restrict choices to potions */ + item_tester_tval = TV_POTION; + + /* Get a potion */ + q = "Use which potion? "; + s = "You have no potions to use."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; + + /* Get the item */ + i_ptr = get_object(item); + + if (i_ptr->number > 1) + { + /* Get a number */ + get_count(1, i_ptr->number); + + /* Save it */ + num = command_arg; + } + else + { + num = 1; + } + + if (num == 0) return; + + /* Take a turn */ + energy_use = 100; + + q = "You soak the meat."; + s = "You soak the meat."; + + switch (i_ptr->sval) + { + case SV_POTION_SALT_WATER: + { + q = "You salt the meat."; + cure = 200 * num; + + break; + } + + case SV_POTION_POISON: + { + q = "You poison the meat."; + cure = 0; + o_ptr->pval /= 2; + if (o_ptr->pval > o_ptr->weight) o_ptr->pval = o_ptr->weight; + + break; + } + + case SV_POTION_CONFUSION: + { + cure = 80 * num; + + break; + } + + case SV_POTION_SLOW_POISON: + { + cure = 20 * num; + + break; + } + + case SV_POTION_CURE_POISON: + { + cure = 45 * num; + + break; + } + + case SV_POTION_DEATH: + { + q = "You ruin the meat."; + cure = 0; + o_ptr->pval /= 10; + if (o_ptr->pval > o_ptr->weight) o_ptr->pval = o_ptr->weight / 2; + + break; + } + + default: + { + cure = 0; + + break; + } + } + + /* Message */ + if (object_known_p(i_ptr)) msg_print(q); + else msg_print(s); + + /* The meat is already spoiling */ + if (((o_ptr->sval == SV_CORPSE_MEAT) && (o_ptr->weight > o_ptr->pval)) || + (o_ptr->weight - o_ptr->pval > 10)) + { + cure = (cure * o_ptr->pval) / (o_ptr->weight * 20); + } + + /* Cure the meat */ + o_ptr->timeout += cure / o_ptr->number; + + if (o_ptr->timeout > o_ptr->pval) o_ptr->timeout = o_ptr->pval; + + /* Use up the potions */ + inc_stack_size(item, -num); +} + + +/* + * Hook to determine if an object is quaffable + */ +static bool_ item_tester_hook_quaffable(object_type *o_ptr) +{ + if ((o_ptr->tval == TV_POTION) || (o_ptr->tval == TV_POTION2)) return (TRUE); + + /* Assume not */ + return (FALSE); +} + + +static bool_ quaff_potion(int tval, int sval, int pval, int pval2) +{ + int ident = FALSE; + + + /* "Traditional" potions */ + if (tval == TV_POTION) + { + switch (sval) + { + case SV_POTION_WATER: + case SV_POTION_APPLE_JUICE: + case SV_POTION_SLIME_MOLD: + { + msg_print("You feel less thirsty."); + ident = TRUE; + + break; + } + + case SV_POTION_SLOWNESS: + { + if (set_slow(p_ptr->slow + randint(25) + 15)) ident = TRUE; + + break; + } + + case SV_POTION_SALT_WATER: + { + msg_print("The potion makes you vomit!"); + (void)set_food(PY_FOOD_STARVE - 1); + (void)set_poisoned(0); + (void)set_paralyzed(4); + ident = TRUE; + + break; + } + + case SV_POTION_POISON: + { + if (!(p_ptr->resist_pois || p_ptr->oppose_pois)) + { + if (set_poisoned(p_ptr->poisoned + rand_int(15) + 10)) + { + ident = TRUE; + } + } + + break; + } + + case SV_POTION_BLINDNESS: + { + if (!p_ptr->resist_blind) + { + if (set_blind(p_ptr->blind + rand_int(100) + 100)) + { + ident = TRUE; + } + } + + break; + } + + /* Booze */ + case SV_POTION_CONFUSION: + { + if (!((p_ptr->resist_conf) || (p_ptr->resist_chaos))) + { + if (set_confused(p_ptr->confused + rand_int(20) + 15)) + { + ident = TRUE; + } + if (randint(2) == 1) + { + if (set_image(p_ptr->image + rand_int(150) + 150)) + { + ident = TRUE; + } + } + if (randint(13) == 1) + { + ident = TRUE; + if (randint(3) == 1) lose_all_info(); + else wiz_dark(); + teleport_player(100); + wiz_dark(); + msg_print("You wake up elsewhere with a sore head..."); + msg_print("You can't remember a thing, or how you got here!"); + } + } + + break; + } + + case SV_POTION_SLEEP: + { + if (!p_ptr->free_act) + { + if (set_paralyzed(rand_int(4) + 4)) + { + ident = TRUE; + } + } + + break; + } + + case SV_POTION_LOSE_MEMORIES: + { + if (!p_ptr->hold_life && (p_ptr->exp > 0)) + { + msg_print("You feel your memories fade."); + lose_exp(p_ptr->exp / 4); + ident = TRUE; + } + + break; + } + + case SV_POTION_RUINATION: + { + msg_print("Your nerves and muscles feel weak and lifeless!"); + take_hit(damroll(10, 10), "a potion of Ruination"); + (void)dec_stat(A_DEX, 25, TRUE); + (void)dec_stat(A_WIS, 25, TRUE); + (void)dec_stat(A_CON, 25, TRUE); + (void)dec_stat(A_STR, 25, TRUE); + (void)dec_stat(A_CHR, 25, TRUE); + (void)dec_stat(A_INT, 25, TRUE); + ident = TRUE; + + break; + } + + case SV_POTION_DEC_STR: + { + if (do_dec_stat(A_STR, STAT_DEC_NORMAL)) ident = TRUE; + + break; + } + + case SV_POTION_DEC_INT: + { + if (do_dec_stat(A_INT, STAT_DEC_NORMAL)) ident = TRUE; + + break; + } + + case SV_POTION_DEC_WIS: + { + if (do_dec_stat(A_WIS, STAT_DEC_NORMAL)) ident = TRUE; + + break; + } + + case SV_POTION_DEC_DEX: + { + if (do_dec_stat(A_DEX, STAT_DEC_NORMAL)) ident = TRUE; + + break; + } + + case SV_POTION_DEC_CON: + { + if (do_dec_stat(A_CON, STAT_DEC_NORMAL)) ident = TRUE; + + break; + } + + case SV_POTION_DEC_CHR: + { + if (do_dec_stat(A_CHR, STAT_DEC_NORMAL)) ident = TRUE; + + break; + } + + case SV_POTION_DETONATIONS: + { + msg_print("Massive explosions rupture your body!"); + take_hit(damroll(50, 20), "a potion of Detonation"); + (void)set_stun(p_ptr->stun + 75); + (void)set_cut(p_ptr->cut + 5000); + ident = TRUE; + + break; + } + + case SV_POTION_DEATH: + { + msg_print("A feeling of Death flows through your body."); + take_hit(5000, "a potion of Death"); + ident = TRUE; + + break; + } + + case SV_POTION_INFRAVISION: + { + if (set_tim_infra(p_ptr->tim_infra + 100 + randint(100))) + { + ident = TRUE; + } + + break; + } + + case SV_POTION_DETECT_INVIS: + { + if (set_tim_invis(p_ptr->tim_invis + 12 + randint(12))) + { + ident = TRUE; + } + + break; + } + + case SV_POTION_SLOW_POISON: + { + if (set_poisoned(p_ptr->poisoned / 2)) ident = TRUE; + + break; + } + + case SV_POTION_CURE_POISON: + { + if (set_poisoned(0)) ident = TRUE; + + break; + } + + case SV_POTION_BOLDNESS: + { + if (set_afraid(0)) ident = TRUE; + + break; + } + + case SV_POTION_SPEED: + { + if (!p_ptr->fast) + { + if (set_fast(randint(25) + 15, 10)) ident = TRUE; + } + else + { + (void)set_fast(p_ptr->fast + 5, 10); + } + + break; + } + + case SV_POTION_RESIST_HEAT: + { + if (set_oppose_fire(p_ptr->oppose_fire + randint(10) + 10)) + { + ident = TRUE; + } + + break; + } + + case SV_POTION_RESIST_COLD: + { + if (set_oppose_cold(p_ptr->oppose_cold + randint(10) + 10)) + { + ident = TRUE; + } + + break; + } + + case SV_POTION_HEROISM: + { + if (set_afraid(0)) ident = TRUE; + if (set_hero(p_ptr->hero + randint(25) + 25)) ident = TRUE; + if (hp_player(10)) ident = TRUE; + + break; + } + + case SV_POTION_BESERK_STRENGTH: + { + if (set_afraid(0)) ident = TRUE; + if (set_shero(p_ptr->shero + randint(25) + 25)) ident = TRUE; + if (hp_player(30)) ident = TRUE; + + break; + } + + case SV_POTION_CURE_LIGHT: + { + if (hp_player(damroll(2, 8))) ident = TRUE; + if (set_blind(0)) ident = TRUE; + if (set_cut(p_ptr->cut - 10)) ident = TRUE; + + break; + } + + case SV_POTION_CURE_SERIOUS: + { + if (hp_player(damroll(4, 8))) ident = TRUE; + if (set_blind(0)) ident = TRUE; + if (set_confused(0)) ident = TRUE; + if (set_cut((p_ptr->cut / 2) - 50)) ident = TRUE; + + break; + } + + case SV_POTION_CURE_CRITICAL: + { + if (hp_player(damroll(6, 8))) ident = TRUE; + if (set_blind(0)) ident = TRUE; + if (set_confused(0)) ident = TRUE; + if (set_poisoned(0)) ident = TRUE; + if (set_stun(0)) ident = TRUE; + if (set_cut(0)) ident = TRUE; + + break; + } + + case SV_POTION_HEALING: + { + if (hp_player(300)) ident = TRUE; + if (set_blind(0)) ident = TRUE; + if (set_confused(0)) ident = TRUE; + if (set_poisoned(0)) ident = TRUE; + if (set_stun(0)) ident = TRUE; + if (set_cut(0)) ident = TRUE; + + break; + } + + case SV_POTION_STAR_HEALING: + { + if (hp_player(1200)) ident = TRUE; + if (set_blind(0)) ident = TRUE; + if (set_confused(0)) ident = TRUE; + if (set_poisoned(0)) ident = TRUE; + if (set_stun(0)) ident = TRUE; + if (set_cut(0)) ident = TRUE; + + break; + } + + case SV_POTION_LIFE: + { + msg_print("You feel life flow through your body!"); + restore_level(); + hp_player(5000); + (void)set_poisoned(0); + (void)set_blind(0); + (void)set_confused(0); + (void)set_image(0); + (void)set_stun(0); + (void)set_cut(0); + (void)do_res_stat(A_STR, TRUE); + (void)do_res_stat(A_CON, TRUE); + (void)do_res_stat(A_DEX, TRUE); + (void)do_res_stat(A_WIS, TRUE); + (void)do_res_stat(A_INT, TRUE); + (void)do_res_stat(A_CHR, TRUE); + if (p_ptr->black_breath) + { + msg_print("The hold of the Black Breath on you is broken!"); + } + p_ptr->black_breath = FALSE; + ident = TRUE; + + break; + } + + case SV_POTION_RESTORE_MANA: + { + if (p_ptr->csp < p_ptr->msp) + { + p_ptr->csp = p_ptr->msp; + p_ptr->csp_frac = 0; + msg_print("Your feel your head clear."); + p_ptr->redraw |= (PR_MANA); + p_ptr->window |= (PW_PLAYER); + ident = TRUE; + } + + break; + } + + case SV_POTION_RESTORE_EXP: + { + if (restore_level()) ident = TRUE; + + break; + } + + case SV_POTION_RES_STR: + { + if (do_res_stat(A_STR, TRUE)) ident = TRUE; + + break; + } + + case SV_POTION_RES_INT: + { + if (do_res_stat(A_INT, TRUE)) ident = TRUE; + + break; + } + + case SV_POTION_RES_WIS: + { + if (do_res_stat(A_WIS, TRUE)) ident = TRUE; + + break; + } + + case SV_POTION_RES_DEX: + { + if (do_res_stat(A_DEX, TRUE)) ident = TRUE; + + break; + } + + case SV_POTION_RES_CON: + { + if (do_res_stat(A_CON, TRUE)) ident = TRUE; + + break; + } + + case SV_POTION_RES_CHR: + { + if (do_res_stat(A_CHR, TRUE)) ident = TRUE; + + break; + } + + case SV_POTION_INC_STR: + { + if (do_inc_stat(A_STR)) ident = TRUE; + + break; + } + + case SV_POTION_INC_INT: + { + if (do_inc_stat(A_INT)) ident = TRUE; + + break; + } + + case SV_POTION_INC_WIS: + { + if (do_inc_stat(A_WIS)) ident = TRUE; + + break; + } + + case SV_POTION_INC_DEX: + { + if (do_inc_stat(A_DEX)) ident = TRUE; + + break; + } + + case SV_POTION_INC_CON: + { + if (do_inc_stat(A_CON)) ident = TRUE; + + break; + } + + case SV_POTION_INC_CHR: + { + if (do_inc_stat(A_CHR)) ident = TRUE; + + break; + } + + case SV_POTION_AUGMENTATION: + { + if (do_inc_stat(A_STR)) ident = TRUE; + if (do_inc_stat(A_INT)) ident = TRUE; + if (do_inc_stat(A_WIS)) ident = TRUE; + if (do_inc_stat(A_DEX)) ident = TRUE; + if (do_inc_stat(A_CON)) ident = TRUE; + if (do_inc_stat(A_CHR)) ident = TRUE; + + break; + } + + case SV_POTION_ENLIGHTENMENT: + { + msg_print("An image of your surroundings forms in your mind..."); + wiz_lite(); + ident = TRUE; + + break; + } + + case SV_POTION_STAR_ENLIGHTENMENT: + { + msg_print("You begin to feel more enlightened..."); + msg_print(NULL); + wiz_lite_extra(); + (void)do_inc_stat(A_INT); + (void)do_inc_stat(A_WIS); + (void)detect_traps(DEFAULT_RADIUS); + (void)detect_doors(DEFAULT_RADIUS); + (void)detect_stairs(DEFAULT_RADIUS); + (void)detect_treasure(DEFAULT_RADIUS); + (void)detect_objects_gold(DEFAULT_RADIUS); + (void)detect_objects_normal(DEFAULT_RADIUS); + identify_pack(); + self_knowledge(NULL); + ident = TRUE; + + break; + } + + case SV_POTION_SELF_KNOWLEDGE: + { + msg_print("You begin to know yourself a little better..."); + msg_print(NULL); + self_knowledge(NULL); + ident = TRUE; + + break; + } + + case SV_POTION_EXPERIENCE: + { + if (p_ptr->exp < PY_MAX_EXP) + { + msg_print("You feel more experienced."); + gain_exp(100000L); + ident = TRUE; + } + + break; + } + + case SV_POTION_RESISTANCE: + { + (void)set_oppose_acid(p_ptr->oppose_acid + randint(20) + 20); + (void)set_oppose_elec(p_ptr->oppose_elec + randint(20) + 20); + (void)set_oppose_fire(p_ptr->oppose_fire + randint(20) + 20); + (void)set_oppose_cold(p_ptr->oppose_cold + randint(20) + 20); + (void)set_oppose_pois(p_ptr->oppose_pois + randint(20) + 20); + ident = TRUE; + + break; + } + + case SV_POTION_CURING: + { + if (hp_player(50)) ident = TRUE; + if (set_blind(0)) ident = TRUE; + if (set_poisoned(0)) ident = TRUE; + if (set_confused(0)) ident = TRUE; + if (set_stun(0)) ident = TRUE; + if (set_cut(0)) ident = TRUE; + if (set_image(0)) ident = TRUE; + if (heal_insanity(50)) ident = TRUE; + + break; + } + + case SV_POTION_INVULNERABILITY: + { + (void)set_invuln(p_ptr->invuln + randint(7) + 7); + ident = TRUE; + + break; + } + + case SV_POTION_NEW_LIFE: + { + do_cmd_rerate(); + ident = TRUE; + + break; + } + + case SV_POTION_BLOOD: + { + msg_print("You feel the blood of life running through your veins!"); + ident = TRUE; + p_ptr->allow_one_death++; + + break; + } + + case SV_POTION_MUTATION: + { + /* In Theme, Melkor likes players who quaff + potions of corruption. */ + if (game_module_idx == MODULE_THEME) + { + GOD(GOD_MELKOR) + { + msg_print("Your quaffing of this potion pleases Melkor!"); + set_grace(p_ptr->grace + 2); + } + } + + msg_print("You feel the dark corruptions of Morgoth coming over you!"); + gain_random_corruption(); + ident = TRUE; + break; + } + + case SV_POTION_INVIS: + { + int t = 30 + randint(30); + + if (set_invis(p_ptr->tim_invis + t, 35)) + { + ident = TRUE; + } + set_tim_invis(p_ptr->tim_invis + t); + + break; + } + + case SV_POTION_LEARNING: + { + p_ptr->skill_points += rand_range(4, 10 + luck( -4, 4)); + cmsg_format(TERM_L_GREEN, "You can increase %d more skills.", p_ptr->skill_points); + + break; + } + + default: + { + break; + } + } + } + + /* "Duplicate" potions */ + else + { + switch (sval) + { + case SV_POTION2_MIMIC: + { + if (!p_ptr->mimic_form) + { + s32b time = get_mimic_random_duration(pval2); + + set_mimic(time, pval2, (p_ptr->lev * 2) / 3); + + /* Redraw title */ + p_ptr->redraw |= (PR_TITLE); + + /* Recalculate bonuses */ + p_ptr->update |= (PU_BONUS); + + ident = TRUE; + } + + break; + } + + case SV_POTION2_CURE_LIGHT_SANITY: + { + if (heal_insanity(damroll(4, 8))) ident = TRUE; + + break; + } + + case SV_POTION2_CURE_SERIOUS_SANITY: + { + if (heal_insanity(damroll(8, 8))) ident = TRUE; + + break; + } + + case SV_POTION2_CURE_CRITICAL_SANITY: + { + if (heal_insanity(damroll(12, 8))) ident = TRUE; + + break; + } + + case SV_POTION2_CURE_SANITY: + { + if (heal_insanity(damroll(10, 100))) ident = TRUE; + + break; + } + + default: + { + break; + } + } + } + + return (ident); +} + + +/* + * Quaff a potion (from the pack or the floor) + */ +void do_cmd_quaff_potion(void) +{ + int item, ident, lev; + + object_type *o_ptr; + + object_type *q_ptr, forge; + + cptr q, s; + + + /* Restrict choices to potions */ + item_tester_hook = item_tester_hook_quaffable; + + /* Set up the extra finder */ + get_item_hook_find_obj_what = "Potion full name? "; + get_item_extra_hook = get_item_hook_find_obj; + + /* Get an item */ + q = "Quaff which potion? "; + s = "You have no potions to quaff."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EXTRA))) return; + + /* Get the item */ + o_ptr = get_object(item); + + + /* Sound */ + sound(SOUND_QUAFF); + + + /* Take a turn */ + energy_use = 100; + + /* Not identified yet */ + ident = FALSE; + + /* Object level */ + lev = k_info[o_ptr->k_idx].level; + + /* Demon Breath corruption can spoil potions. */ + if (player_has_corruption(CORRUPT_DEMON_BREATH) && magik(9)) + { + msg_print("Your demon breath spoils the potion!"); + ident = FALSE; + } + else + { + /* Normal potion handling */ + ident = quaff_potion(o_ptr->tval, o_ptr->sval, o_ptr->pval, o_ptr->pval2); + } + + /* Combine / Reorder the pack (later) */ + p_ptr->notice |= (PN_COMBINE | PN_REORDER); + + /* The item has been tried */ + object_tried(o_ptr); + + /* An identification was made */ + if (ident && !object_aware_p(o_ptr)) + { + object_aware(o_ptr); + gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev); + } + + if (get_skill(SKILL_ALCHEMY)) + { + if (item >= 0) + { + q_ptr = &forge; + object_prep(q_ptr, lookup_kind(TV_BOTTLE, 1)); + q_ptr->number = 1; + object_aware(q_ptr); + object_known(q_ptr); + + q_ptr->ident |= IDENT_STOREB; + + (void)inven_carry(q_ptr, FALSE); + } + } + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + + + /* Potions can feed the player */ + (void)set_food(p_ptr->food + o_ptr->pval); + + + /* Destroy potion */ + inc_stack_size(item, -1); +} + + +/* + * Drink from a fountain + */ +void do_cmd_drink_fountain(void) +{ + cave_type *c_ptr = &cave[p_ptr->py][p_ptr->px]; + + bool_ ident; + + int tval, sval, pval = 0; + + int i; + + char ch; + + + /* Is the fountain empty? */ + if (c_ptr->special2 <= 0) + { + msg_print("The fountain is dried out."); + return; + } + + /* We quaff or we fill ? */ + if (!get_com("Do you want to [Q]uaff or [F]ill from the fountain? ", &ch)) + { + return; + } + + if ((ch == 'F') || (ch == 'f')) + { + do_cmd_fill_bottle(); + + return; + } + + else if ((ch == 'Q') || (ch == 'q')) + { + if (c_ptr->special <= SV_POTION_LAST) + { + tval = TV_POTION; + sval = c_ptr->special; + } + else + { + tval = TV_POTION2; + sval = c_ptr->special - SV_POTION_LAST; + } + + for (i = 0; i < max_k_idx; i++) + { + object_kind *k_ptr = &k_info[i]; + + if (k_ptr->tval != tval) continue; + if (k_ptr->sval != sval) continue; + + pval = k_ptr->pval; + + break; + } + + ident = quaff_potion(tval, sval, pval, 0); + + c_ptr->special2--; + + if (c_ptr->special2 <= 0) + { + cave_set_feat(p_ptr->py, p_ptr->px, FEAT_EMPTY_FOUNTAIN); + } + + if (ident) c_ptr->info |= CAVE_IDNT; + } +} + + +/* + * Fill an empty bottle + */ +void do_cmd_fill_bottle(void) +{ + cave_type *c_ptr = &cave[p_ptr->py][p_ptr->px]; + + int tval, sval, item, amt = 1; + + object_type *q_ptr, *o_ptr, forge; + + cptr q, s; + + /* Is the fountain empty? */ + /* + * This check is redundant as it is done in do_cmd_drink_fountain() + * but I keep this because someone might want to call this directly. + * -- Kusunose + */ + if (c_ptr->special2 <= 0) + { + msg_print("The fountain has dried up."); + return; + } + + /* Determine the tval/sval of the potion */ + if (c_ptr->special <= SV_POTION_LAST) + { + tval = TV_POTION; + sval = c_ptr->special; + } + else + { + tval = TV_POTION2; + sval = c_ptr->special - SV_POTION_LAST; + } + + /* Restrict choices to bottles */ + item_tester_tval = TV_BOTTLE; + + /* Get an item */ + q = "Fill which bottle? "; + s = "You have no bottles to fill."; + if (!get_item(&item, q, s, (USE_INVEN))) return; + o_ptr = &p_ptr->inventory[item]; + + /* Find out how many the player wants */ + if (o_ptr->number > 1) + { + /* Get a quantity */ + amt = get_quantity(NULL, o_ptr->number); + + /* Allow user abort */ + if (amt <= 0) return; + } + + if (amt > c_ptr->special2) amt = c_ptr->special2; + + /* Destroy bottles */ + inc_stack_size(item, -amt); + + /* Create the potion */ + q_ptr = &forge; + object_prep(q_ptr, lookup_kind(tval, sval)); + q_ptr->number = amt; + + if (c_ptr->info & CAVE_IDNT) + { + object_aware(q_ptr); + object_known(q_ptr); + } + + inven_carry(q_ptr, TRUE); + + c_ptr->special2 -= amt; + + if (c_ptr->special2 <= 0) + { + cave_set_feat(p_ptr->py, p_ptr->px, FEAT_EMPTY_FOUNTAIN); + } + + return; +} + + +/* + * Curse the players armor + */ +bool_ curse_armor(void) +{ + object_type *o_ptr; + + char o_name[80]; + + + /* Curse the body armor */ + o_ptr = &p_ptr->inventory[INVEN_BODY]; + + /* Nothing to curse */ + if (!o_ptr->k_idx) return (FALSE); + + + /* Describe */ + object_desc(o_name, o_ptr, FALSE, 3); + + /* Attempt a saving throw for artifacts */ + if (((o_ptr->art_name) || artifact_p(o_ptr)) && (rand_int(100) < 50)) + { + /* Cool */ + msg_format("A terrible black aura tries to surround your armour, " + "but your %s resists the effects!", o_name); + } + + /* not artifact or failed save... */ + else + { + /* Oops */ + msg_format("A terrible black aura blasts your %s!", o_name); + + /* Blast the armor */ + o_ptr->name1 = 0; + o_ptr->name2 = EGO_BLASTED; + o_ptr->to_a = 0 - randint(5) - randint(5); + o_ptr->to_h = 0; + o_ptr->to_d = 0; + o_ptr->ac = 0; + o_ptr->dd = 0; + o_ptr->ds = 0; + o_ptr->art_flags1 = 0; + o_ptr->art_flags2 = 0; + o_ptr->art_flags3 = 0; + o_ptr->art_flags4 = 0; + + /* Curse it */ + o_ptr->ident |= (IDENT_CURSED); + + /* Recalculate bonuses */ + p_ptr->update |= (PU_BONUS); + + /* Recalculate mana */ + p_ptr->update |= (PU_MANA); + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + } + + return (TRUE); +} + + +/* + * Curse the players weapon + */ +bool_ curse_weapon(void) +{ + object_type *o_ptr; + + char o_name[80]; + + + /* Curse the weapon */ + o_ptr = &p_ptr->inventory[INVEN_WIELD]; + + /* Nothing to curse */ + if (!o_ptr->k_idx) return (FALSE); + + + /* Describe */ + object_desc(o_name, o_ptr, FALSE, 3); + + /* Attempt a saving throw */ + if ((artifact_p(o_ptr) || o_ptr->art_name) && (rand_int(100) < 50)) + { + /* Cool */ + msg_format("A terrible black aura tries to surround your weapon, " + "but your %s resists the effects!", o_name); + } + + /* not artifact or failed save... */ + else + { + /* Oops */ + msg_format("A terrible black aura blasts your %s!", o_name); + + /* Shatter the weapon */ + o_ptr->name1 = 0; + o_ptr->name2 = EGO_SHATTERED; + o_ptr->to_h = 0 - randint(5) - randint(5); + o_ptr->to_d = 0 - randint(5) - randint(5); + o_ptr->to_a = 0; + o_ptr->ac = 0; + o_ptr->dd = 0; + o_ptr->ds = 0; + o_ptr->art_flags1 = 0; + o_ptr->art_flags2 = 0; + o_ptr->art_flags3 = 0; + o_ptr->art_flags4 = 0; + + + /* Curse it */ + o_ptr->ident |= (IDENT_CURSED); + + /* Recalculate bonuses */ + p_ptr->update |= (PU_BONUS); + + /* Recalculate mana */ + p_ptr->update |= (PU_MANA); + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + } + + /* Notice */ + return (TRUE); +} + + +/* + * Hook to determine if an object is readable + */ +static bool_ item_tester_hook_readable(object_type *o_ptr) +{ + if ((o_ptr->tval == TV_SCROLL) || (o_ptr->tval == TV_PARCHMENT)) return (TRUE); + + /* Assume not */ + return (FALSE); +} + + +/* + * Read a scroll (from the pack or floor). + * + * Certain scrolls can be "aborted" without losing the scroll. These + * include scrolls with no effects but recharge or identify, which are + * cancelled before use. XXX Reading them still takes a turn, though. + */ +void do_cmd_read_scroll(void) +{ + int item, k, used_up, ident, lev; + + object_type *o_ptr; + + object_type *q_ptr, forge; + + cptr q, s; + + + /* Check some conditions */ + if (p_ptr->blind) + { + msg_print("You can't see anything."); + return; + } + + if (no_lite()) + { + msg_print("You have no light by which to read."); + return; + } + + if (p_ptr->confused) + { + msg_print("You are too confused!"); + return; + } + + + /* Restrict choices to scrolls */ + item_tester_hook = item_tester_hook_readable; + + /* Set up the extra finder */ + get_item_hook_find_obj_what = "Scroll full name? "; + get_item_extra_hook = get_item_hook_find_obj; + + /* Get an item */ + q = "Read which scroll? "; + s = "You have no scrolls to read."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EXTRA))) return; + + /* Get the item */ + o_ptr = get_object(item); + + /* Take a turn */ + energy_use = 100; + + /* Not identified yet */ + ident = FALSE; + + /* Object level */ + lev = k_info[o_ptr->k_idx].level; + + /* Assume the scroll will get used up */ + used_up = TRUE; + + /* Corruption */ + if (player_has_corruption(CORRUPT_BALROG_AURA) && magik(5)) + { + msg_print("Your demon aura burns the scroll before you read it!"); + used_up = TRUE; + ident = FALSE; + } + + /* Scrolls */ + else if (o_ptr->tval == TV_SCROLL) + { + /* Analyze the scroll */ + switch (o_ptr->sval) + { + case SV_SCROLL_MASS_RESURECTION: + { + int k; + + ident = TRUE; + msg_print("You feel the souls of the dead coming back " + "from the Halls of Mandos."); + + for (k = 0; k < max_r_idx; k++) + { + monster_race *r_ptr = &r_info[k]; + + if (r_ptr->flags1 & RF1_UNIQUE && + !(r_ptr->flags9 & RF9_SPECIAL_GENE)) + { + r_ptr->max_num = 1; + } + } + + break; + } + + case SV_SCROLL_DEINCARNATION: + { + if (!get_check("Do you really want to leave your body? " + "(beware, it'll be destroyed!) ")) + { + used_up = FALSE; + break; + } + + do_cmd_leave_body(FALSE); + + ident = TRUE; + used_up = TRUE; + + break; + } + + /* original didn't set used_up flag ??? -- pelpel */ + case SV_SCROLL_RESET_RECALL: + { + if (!reset_recall(TRUE)) + { + used_up = FALSE; + break; + } + + msg_format("Recall reset to %s at level %d.", + d_info[p_ptr->recall_dungeon].name + d_name, + max_dlv[p_ptr->recall_dungeon]); + + ident = TRUE; + used_up = TRUE; + + break; + } + + case SV_SCROLL_DIVINATION: + { + int i, count = 0; + char buf[120]; + + while (count < 1000) + { + count++; + i = rand_int(MAX_FATES); + if (!fates[i].fate) continue; + if (fates[i].know) continue; + + msg_print("A message appears on the scroll. It says:"); + msg_print(NULL); + + fate_desc(buf, i); + msg_format("%s", buf); + + msg_print(NULL); + msg_print("The scroll disappears in a puff of smoke!"); + + fates[i].know = TRUE; + ident = TRUE; + + break; + } + + break; + } + + case SV_SCROLL_DARKNESS: + { + if (!(p_ptr->resist_blind) && !(p_ptr->resist_dark)) + { + (void)set_blind(p_ptr->blind + 3 + randint(5)); + } + if (unlite_area(10, 3)) ident = TRUE; + + break; + } + + case SV_SCROLL_AGGRAVATE_MONSTER: + { + msg_print("There is a high-pitched humming noise."); + aggravate_monsters(1); + + ident = TRUE; + + break; + } + + case SV_SCROLL_CURSE_ARMOR: + { + if (curse_armor()) ident = TRUE; + + break; + } + + case SV_SCROLL_CURSE_WEAPON: + { + if (curse_weapon()) ident = TRUE; + + break; + } + + case SV_SCROLL_SUMMON_MONSTER: + { + for (k = 0; k < randint(3); k++) + { + if (summon_specific(p_ptr->py, p_ptr->px, dun_level, 0)) + { + ident = TRUE; + } + } + + break; + } + + case SV_SCROLL_SUMMON_MINE: + { + if (summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_MINE, FALSE)) + { + ident = TRUE; + } + + break; + } + + case SV_SCROLL_SUMMON_UNDEAD: + { + for (k = 0; k < randint(3); k++) + { + if (summon_specific(p_ptr->py, p_ptr->px, dun_level, SUMMON_UNDEAD)) + { + ident = TRUE; + } + } + + break; + } + + case SV_SCROLL_TRAP_CREATION: + { + if (trap_creation()) ident = TRUE; + + break; + } + + case SV_SCROLL_PHASE_DOOR: + { + teleport_player(10); + + ident = TRUE; + + break; + } + + case SV_SCROLL_TELEPORT: + { + teleport_player(100); + + ident = TRUE; + + break; + } + + case SV_SCROLL_TELEPORT_LEVEL: + { + (void)teleport_player_level(); + + ident = TRUE; + + break; + } + + case SV_SCROLL_WORD_OF_RECALL: + { + if ((dungeon_flags2 & DF2_ASK_LEAVE) && !get_check("Leave this unique level forever? ")) + { + used_up = FALSE; + } + else + { + recall_player(21, 15); + + ident = TRUE; + } + + break; + } + + case SV_SCROLL_IDENTIFY: + { + ident = TRUE; + + if (!ident_spell()) used_up = FALSE; + + break; + } + + case SV_SCROLL_STAR_IDENTIFY: + { + ident = TRUE; + + if (!identify_fully()) used_up = FALSE; + + break; + } + + case SV_SCROLL_REMOVE_CURSE: + { + if (remove_curse()) + { + msg_print("You feel as if someone is watching over you."); + ident = TRUE; + } + + break; + } + + case SV_SCROLL_STAR_REMOVE_CURSE: + { + remove_all_curse(); + + ident = TRUE; + + break; + } + + case SV_SCROLL_ENCHANT_ARMOR: + { + ident = TRUE; + + if (!enchant_spell(0, 0, 1, 0)) used_up = FALSE; + + break; + } + + case SV_SCROLL_ENCHANT_WEAPON_TO_HIT: + { + if (!enchant_spell(1, 0, 0, 0)) used_up = FALSE; + + ident = TRUE; + + break; + } + + case SV_SCROLL_ENCHANT_WEAPON_TO_DAM: + { + if (!enchant_spell(0, 1, 0, 0)) used_up = FALSE; + + ident = TRUE; + + break; + } + + case SV_SCROLL_ENCHANT_WEAPON_PVAL: + { + if (!enchant_spell(0, 0, 0, 1)) used_up = FALSE; + + ident = TRUE; + + break; + } + + case SV_SCROLL_STAR_ENCHANT_ARMOR: + { + if (!enchant_spell(0, 0, randint(3) + 2, 0)) used_up = FALSE; + + ident = TRUE; + + break; + } + + case SV_SCROLL_STAR_ENCHANT_WEAPON: + { + if (!enchant_spell(randint(3), randint(3), 0, 0)) used_up = FALSE; + + ident = TRUE; + + break; + } + + case SV_SCROLL_RECHARGING: + { + if (!recharge(60)) used_up = FALSE; + + ident = TRUE; + + break; + } + + case SV_SCROLL_LIGHT: + { + if (lite_area(damroll(2, 8), 2)) ident = TRUE; + + break; + } + + case SV_SCROLL_MAPPING: + { + map_area(); + + ident = TRUE; + + break; + } + + case SV_SCROLL_DETECT_GOLD: + { + if (detect_treasure(DEFAULT_RADIUS)) ident = TRUE; + if (detect_objects_gold(DEFAULT_RADIUS)) ident = TRUE; + + break; + } + + case SV_SCROLL_DETECT_ITEM: + { + if (detect_objects_normal(DEFAULT_RADIUS)) ident = TRUE; + + break; + } + + case SV_SCROLL_DETECT_TRAP: + { + if (detect_traps(DEFAULT_RADIUS)) ident = TRUE; + + break; + } + + case SV_SCROLL_DETECT_DOOR: + { + if (detect_doors(DEFAULT_RADIUS)) ident = TRUE; + if (detect_stairs(DEFAULT_RADIUS)) ident = TRUE; + + break; + } + + case SV_SCROLL_DETECT_INVIS: + { + if (detect_monsters_invis(DEFAULT_RADIUS)) ident = TRUE; + + break; + } + + case SV_SCROLL_SATISFY_HUNGER: + { + if (set_food(PY_FOOD_MAX - 1)) ident = TRUE; + + break; + } + + case SV_SCROLL_BLESSING: + { + if (set_blessed(p_ptr->blessed + randint(12) + 6)) ident = TRUE; + + break; + } + + case SV_SCROLL_HOLY_CHANT: + { + if (set_blessed(p_ptr->blessed + randint(24) + 12)) ident = TRUE; + + break; + } + + case SV_SCROLL_HOLY_PRAYER: + { + if (set_blessed(p_ptr->blessed + randint(48) + 24)) ident = TRUE; + + break; + } + + case SV_SCROLL_MONSTER_CONFUSION: + { + if (p_ptr->confusing == 0) + { + msg_print("Your hands begin to glow."); + p_ptr->confusing = TRUE; + ident = TRUE; + } + + break; + } + + case SV_SCROLL_PROTECTION_FROM_EVIL: + { + k = 3 * p_ptr->lev; + if (set_protevil(p_ptr->protevil + randint(25) + k)) ident = TRUE; + + break; + } + + case SV_SCROLL_RUNE_OF_PROTECTION: + { + warding_glyph(); + + ident = TRUE; + + break; + } + + case SV_SCROLL_TRAP_DOOR_DESTRUCTION: + { + if (destroy_doors_touch()) ident = TRUE; + + break; + } + + case SV_SCROLL_STAR_DESTRUCTION: + { + /* Prevent destruction of quest levels and town */ + if (!is_quest(dun_level) && dun_level) + { + destroy_area(p_ptr->py, p_ptr->px, 15, TRUE, FALSE); + } + else + { + msg_print("The dungeon trembles..."); + } + + ident = TRUE; + + break; + } + + case SV_SCROLL_DISPEL_UNDEAD: + { + if (dispel_undead(60)) ident = TRUE; + + break; + } + + case SV_SCROLL_GENOCIDE: + { + (void)genocide(TRUE); + + ident = TRUE; + + break; + } + + case SV_SCROLL_MASS_GENOCIDE: + { + (void)mass_genocide(TRUE); + + ident = TRUE; + + break; + } + + case SV_SCROLL_ACQUIREMENT: + { + acquirement(p_ptr->py, p_ptr->px, 1, TRUE, FALSE); + + ident = TRUE; + + break; + } + + case SV_SCROLL_STAR_ACQUIREMENT: + { + acquirement(p_ptr->py, p_ptr->px, randint(2) + 1, TRUE, FALSE); + + ident = TRUE; + + break; + } + + /* ZAngband scrolls */ + case SV_SCROLL_FIRE: + { + fire_ball(GF_FIRE, 0, 150, 4); + + /* + * Note: "Double" damage since it is centered on + * the player ... + */ + if (!p_ptr->oppose_fire && !p_ptr->resist_fire && + !p_ptr->immune_fire) + { + take_hit(50 + randint(50) + (p_ptr->sensible_fire) ? 20 : 0, + "a Scroll of Fire"); + } + + ident = TRUE; + + break; + } + + + case SV_SCROLL_ICE: + { + fire_ball(GF_ICE, 0, 175, 4); + + if (!p_ptr->oppose_cold && !p_ptr->resist_cold && + !p_ptr->immune_cold) + { + take_hit(100 + randint(100), "a Scroll of Ice"); + } + + ident = TRUE; + + break; + } + + case SV_SCROLL_CHAOS: + { + fire_ball(GF_CHAOS, 0, 222, 4); + + if (!p_ptr->resist_chaos) + { + take_hit(111 + randint(111), "a Scroll of Chaos"); + } + + ident = TRUE; + + break; + } + + case SV_SCROLL_RUMOR: + { + char rumour[80]; + + msg_print("There is message on the scroll. It says:"); + msg_print(NULL); + + /* Pick random text */ + switch (randint(20)) + { + case 1: + { + get_rnd_line("chainswd.txt", rumour); + + break; + } + + case 2: + { + get_rnd_line("error.txt", rumour); + + break; + } + + case 3: + case 4: + case 5: + { + get_rnd_line("death.txt", rumour); + + break; + } + + default: + { + get_rnd_line("rumors.txt", rumour); + + break; + } + } + + msg_format("%s", rumour); + msg_print(NULL); + + msg_print("The scroll disappears in a puff of smoke!"); + + ident = TRUE; + + break; + } + + case SV_SCROLL_ARTIFACT: + { + ident = TRUE; + + if (!artifact_scroll()) used_up = FALSE; + + break; + } + + case SV_SCROLL_STERILIZATION: + { + msg_print("A neutralising wave radiates from you!"); + set_no_breeders(randint(100) + 100); + + break; + } + + default: + { + break; + } + } + } + + /* Other readable items */ + else + { + /* Maps */ + if (o_ptr->sval >= 200) + { + int i, n; + char buf[80], fil[20]; + + strnfmt(fil, 20, "book-%d.txt", o_ptr->sval); + + n = atoi(get_line(fil, ANGBAND_DIR_FILE, buf, -1)); + + /* Parse all the fields */ + for (i = 0; i < n; i += 4) + { + /* Grab the fields */ + int x = atoi(get_line(fil, ANGBAND_DIR_FILE, buf, i + 0)); + int y = atoi(get_line(fil, ANGBAND_DIR_FILE, buf, i + 1)); + int w = atoi(get_line(fil, ANGBAND_DIR_FILE, buf, i + 2)); + int h = atoi(get_line(fil, ANGBAND_DIR_FILE, buf, i + 3)); + + reveal_wilderness_around_player(y, x, h, w); + } + } + + /* Normal parchements */ + else + { + /* Save screen */ + screen_save(); + + /* Get the filename */ + q = format("book-%d.txt", o_ptr->sval); + + /* Peruse the help file */ + (void)show_file(q, NULL, 0, 0); + + /* Load screen */ + screen_load(); + + if (o_ptr->sval >= 100) + { + inscription_info[o_ptr->sval - 100].know = TRUE; + } + + used_up = FALSE; + } + } + + + /* Combine / Reorder the pack (later) */ + p_ptr->notice |= (PN_COMBINE | PN_REORDER); + + /* The item was tried */ + object_tried(o_ptr); + + /* An identification was made */ + if (ident && !object_aware_p(o_ptr)) + { + object_aware(o_ptr); + gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev); + } + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + + + /* Hack -- allow certain scrolls to be "preserved" */ + if (!used_up) return; + + sound(SOUND_SCROLL); + + /* Destroy scroll */ + inc_stack_size(item, -1); + + if (get_skill(SKILL_ALCHEMY)) + { + if (item >= 0) + { + q_ptr = &forge; + object_prep(q_ptr, lookup_kind(TV_SCROLL, SV_SCROLL_NOTHING)); + object_aware(q_ptr); + object_known(q_ptr); + + q_ptr->ident |= IDENT_STOREB; + + (void)inven_carry(q_ptr, FALSE); + } + } +} + + + +/* Set the 'stick mode' on */ +void set_stick_mode(object_type *o_ptr) +{ + s32b bonus = o_ptr->pval3 & 0xFFFF; + s32b max = o_ptr->pval3 >> 16; + + get_level_use_stick = bonus; + get_level_max_stick = max; +} + +/* Remove 'stick mode' */ +void unset_stick_mode() +{ + get_level_use_stick = -1; + get_level_max_stick = -1; +} + + +/* + * Activate a device + */ +static void activate_stick(s16b s, bool_ *obvious, bool_ *use_charge) +{ + spell_type *spell = spell_at(s); + casting_result ret; + + assert(obvious != NULL); + assert(use_charge != NULL); + + ret = spell_type_produce_effect(spell, -1); + + switch (ret) + { + case NO_CAST: + *use_charge = FALSE; + *obvious = FALSE; + break; + case CAST_HIDDEN: + *use_charge = TRUE; + *obvious = FALSE; + break; + case CAST_OBVIOUS: + *use_charge = TRUE; + *obvious = TRUE; + break; + default: + assert(FALSE); + } +} + + +/* + * Use a staff. -RAK- + * + * One charge of one staff disappears. + * + * Hack -- staffs of identify can be "cancelled". + */ +void do_cmd_use_staff(void) +{ + int item, ident, chance; + + bool_ obvious, use_charge; + + object_type *o_ptr; + + u32b f1, f2, f3, f4, f5, esp; + + cptr q, s; + + /* No magic */ + if (p_ptr->antimagic) + { + msg_print("Your anti-magic field disrupts any magic attempts."); + return; + } + + /* Restrict choices to wands */ + item_tester_tval = TV_STAFF; + + /* Set up the extra finder */ + get_item_hook_find_obj_what = "Staff full name? "; + get_item_extra_hook = get_item_hook_find_obj; + + /* Get an item */ + q = "Use which staff? "; + s = "You have no staff to use."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EXTRA))) return; + + /* Get the item */ + o_ptr = get_object(item); + + /* Mega-Hack -- refuse to use a pile from the ground */ + if ((item < 0) && (o_ptr->number > 1)) + { + msg_print("You must first pick up the staffs."); + return; + } + + /* Enter device mode */ + set_stick_mode(o_ptr); + + /* Take a turn */ + energy_use = 100; + + /* Not identified yet */ + ident = FALSE; + + /* get the chance */ + chance = spell_chance(o_ptr->pval2); + + /* Extract object flags */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* Is it simple to use ? */ + if (f4 & TR4_EASY_USE) + { + chance /= 3; + } + + /* Give everyone a (slight) chance */ + if ((chance < USE_DEVICE) && (rand_int(USE_DEVICE - chance + 1) == 0)) + { + chance = USE_DEVICE; + } + + /* Roll for usage */ + if (magik(chance)) + { + if (flush_failure) flush(); + msg_print("You failed to use the staff properly."); + sound(SOUND_FAIL); + + /* Leave device mode */ + unset_stick_mode(); + return; + } + + /* Notice empty staffs */ + if (o_ptr->pval <= 0) + { + if (flush_failure) flush(); + msg_print("The staff has no charges left."); + o_ptr->ident |= (IDENT_EMPTY); + + /* Leave device mode */ + unset_stick_mode(); + return; + } + + + /* Sound */ + sound(SOUND_ZAP); + + + /* Analyze the staff */ + activate_stick(o_ptr->pval2, &obvious, &use_charge); + + /* Combine / Reorder the pack (later) */ + p_ptr->notice |= (PN_COMBINE | PN_REORDER); + + /* Tried the item */ + object_tried(o_ptr); + + /* An identification was made */ + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + + + /* Hack -- some uses are "free" */ + if (!use_charge) + { + /* Leave device mode */ + unset_stick_mode(); + + return; + } + + /* An identification was made */ + if (obvious) + { + object_aware(o_ptr); + } + + /* Use a single charge */ + o_ptr->pval--; + + /* XXX Hack -- unstack if necessary */ + if ((item >= 0) && (o_ptr->number > 1)) + { + object_type forge; + object_type *q_ptr; + + /* Get local object */ + q_ptr = &forge; + + /* Obtain a local object */ + object_copy(q_ptr, o_ptr); + + /* Modify quantity */ + q_ptr->number = 1; + + /* Restore the charges */ + o_ptr->pval++; + + /* Unstack the used item */ + o_ptr->number--; + item = inven_carry(q_ptr, FALSE); + + /* Message */ + msg_print("You unstack your staff."); + } + + /* Describe charges in the pack */ + if (item >= 0) + { + inven_item_charges(item); + } + + /* Describe charges on the floor */ + else + { + floor_item_charges(0 - item); + } + + /* Leave device mode */ + unset_stick_mode(); +} + + +/* + * Aim a wand (from the pack or floor). + * + * Use a single charge from a single item. + * Handle "unstacking" in a logical manner. + * + * For simplicity, you cannot use a stack of items from the + * ground. This would require too much nasty code. + * + * There are no wands which can "destroy" themselves, in the p_ptr->inventory + * or on the ground, so we can ignore this possibility. Note that this + * required giving "wand of wonder" the ability to ignore destruction + * by electric balls. + * + * All wands can be "cancelled" at the "Direction?" prompt for free. + * + * Note that the basic "bolt" wands do slightly less damage than the + * basic "bolt" rods, but the basic "ball" wands do the same damage + * as the basic "ball" rods. + */ +void do_cmd_aim_wand(void) +{ + bool_ obvious, use_charge; + + int item, ident, chance; + + object_type *o_ptr; + + cptr q, s; + + u32b f1, f2, f3, f4, f5, esp; + + + /* No magic */ + if (p_ptr->antimagic) + { + msg_print("Your anti-magic field disrupts any magic attempts."); + return; + } + + /* Restrict choices to wands */ + item_tester_tval = TV_WAND; + + /* Set up the extra finder */ + get_item_hook_find_obj_what = "Wand full name? "; + get_item_extra_hook = get_item_hook_find_obj; + + /* Get an item */ + q = "Aim which wand? "; + s = "You have no wand to aim."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EXTRA))) return; + + /* Get the item */ + o_ptr = get_object(item); + + + /* Mega-Hack -- refuse to aim a pile from the ground */ + if ((item < 0) && (o_ptr->number > 1)) + { + msg_print("You must first pick up the wands."); + return; + } + + /* Take a turn */ + energy_use = 100; + + /* Not identified yet */ + ident = FALSE; + + /* Enter device mode */ + set_stick_mode(o_ptr); + + /* get the chance */ + chance = spell_chance(o_ptr->pval2); + + /* Extract object flags */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* Is it simple to use ? */ + if (f4 & TR4_EASY_USE) + { + chance /= 3; + } + + /* Roll for usage */ + if (magik(chance)) + { + if (flush_failure) flush(); + msg_print("You failed to use the wand properly."); + sound(SOUND_FAIL); + + /* Leave device mode */ + unset_stick_mode(); + return; + } + + /* The wand is already empty! */ + if (o_ptr->pval <= 0) + { + if (flush_failure) flush(); + msg_print("The wand has no charges left."); + o_ptr->ident |= (IDENT_EMPTY); + + /* Leave device mode */ + unset_stick_mode(); + return; + } + + + /* Sound */ + sound(SOUND_ZAP); + + + /* Analyze the wand */ + activate_stick(o_ptr->pval2, &obvious, &use_charge); + + /* Combine / Reorder the pack (later) */ + p_ptr->notice |= (PN_COMBINE | PN_REORDER); + + /* Mark it as tried */ + object_tried(o_ptr); + + /* Hack -- some uses are "free" */ + if (!use_charge) + { + /* Leave device mode */ + unset_stick_mode(); + + return; + } + + /* An identification was made */ + if (obvious) + { + object_aware(o_ptr); + } + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + + + /* Use a single charge */ + o_ptr->pval--; + + /* Describe the charges in the pack */ + if (item >= 0) + { + inven_item_charges(item); + } + + /* Describe the charges on the floor */ + else + { + floor_item_charges(0 - item); + } + + /* Leave device mode */ + unset_stick_mode(); +} + + + + + + +/* + * Activate (zap) a Rod + * + * Unstack fully charged rods as needed. + * + * Hack -- rods of perception/genocide can be "cancelled" + * All rods can be cancelled at the "Direction?" prompt + */ + + +/* + * Hook to determine if an object is zapable + */ +static bool_ item_tester_hook_zapable(object_type *o_ptr) +{ + if ((o_ptr->tval == TV_ROD) || (o_ptr->tval == TV_ROD_MAIN)) return (TRUE); + + /* Assume not */ + return (FALSE); +} + + +/* + * Hook to determine if an object is attachable + */ +static bool_ item_tester_hook_attachable(object_type *o_ptr) +{ + if ((o_ptr->tval == TV_ROD_MAIN) && + (o_ptr->pval == SV_ROD_NOTHING)) return (TRUE); + + /* Assume not */ + return (FALSE); +} + + +/* + * Combine a rod and a rod tip + */ +void zap_combine_rod_tip(object_type *q_ptr, int tip_item) +{ + int item; + + object_type *o_ptr; + + cptr q, s; + + u32b f1, f2, f3, f4, f5, esp; + s32b cost; + + + /* No magic */ + if (p_ptr->antimagic) + { + msg_print("Your anti-magic field disrupts any magic attempts."); + return; + } + + /* Restrict choices to rods */ + item_tester_hook = item_tester_hook_attachable; + + /* Get an item */ + q = "Attach the rod tip with which rod? "; + s = "You have no rod to attach to."; + if (!get_item(&item, q, s, (USE_INVEN))) return; + + /* Get the item */ + o_ptr = get_object(item); + + /* Examine the rod */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* Calculate rod tip's mana cost */ + cost = q_ptr->pval; + + if (f4 & TR4_CHEAPNESS) + { + cost /= 2; + } + + /* + * The rod must have at least the same mana capacity as the + * rod tip spell needs + */ + if (o_ptr->pval2 < cost) + { + msg_print("This rod doesn't have enough mana for the rod tip."); + return; + } + + /* Attach the tip to the rod */ + o_ptr->pval = q_ptr->sval; + + /* Destroy rod tip */ + inc_stack_size(tip_item, -1); +} + + +/* + * Zap a rod, or attack a rod tip to a rod + */ +void do_cmd_zap_rod(void) +{ + int item, ident, chance, dir, lev; + + int cost; + + bool_ require_dir; + + object_type *o_ptr; + + object_kind *tip_ptr; + + u32b f1, f2, f3, f4, f5, esp; + + cptr q, s; + + /* Hack -- let perception get aborted */ + bool_ use_charge = TRUE; + + + /* No magic */ + if (p_ptr->antimagic) + { + msg_print("Your anti-magic field disrupts any magic attempts."); + return; + } + + + /* Restrict choices to rods */ + item_tester_hook = item_tester_hook_zapable; + + /* Set up the extra finder */ + get_item_hook_find_obj_what = "Rod full name? "; + get_item_extra_hook = get_item_hook_find_obj; + + /* Get an item */ + q = "Zap which rod? "; + s = "You have no rod to zap."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR | USE_EXTRA))) return; + + /* Get the item */ + o_ptr = get_object(item); + + + /* "Zapping" a Rod Tip on rod of nothing will attach it */ + if (o_ptr->tval == TV_ROD) + { + if (item >= 0) + { + zap_combine_rod_tip(o_ptr, item); + return; + } + else + { + msg_print("You can't zap a rod tip that's on the floor."); + return; + } + } + + + /* Non-directed rods */ + if (o_ptr->pval < SV_ROD_MIN_DIRECTION) + { + require_dir = FALSE; + } + + /* Some rods always require direction */ + else + { + switch (o_ptr->pval) + { + case SV_ROD_DETECT_TRAP: + case SV_ROD_HAVOC: + case SV_ROD_HOME: + { + require_dir = FALSE; + break; + } + + default: + { + require_dir = TRUE; + break; + } + } + } + + /* Get a direction (unless KNOWN not to need it) */ + if (!object_aware_p(o_ptr) || require_dir) + { + /* Get a direction, allow cancel */ + if (!get_aim_dir(&dir)) return; + } + + /* Take a turn */ + energy_use = 100; + + /* Examine the rod */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + if (f4 & TR4_FAST_CAST) energy_use /= 2; + + /* Not identified yet */ + ident = FALSE; + + /* Extract the item level */ + tip_ptr = &k_info[lookup_kind(TV_ROD, o_ptr->pval)]; + lev = k_info[lookup_kind(TV_ROD, o_ptr->pval)].level; + + /* Base chance of success */ + chance = p_ptr->skill_dev; + + /* Confusion hurts skill */ + if (p_ptr->confused) chance = chance / 2; + + /* High level objects are harder */ + chance = chance - ((lev > 50) ? 50 : lev); + + if (chance <= 0) + { + chance = 1; + } + + /* Is it simple to use ? */ + if (f4 & TR4_EASY_USE) + { + chance *= 10; + } + + /* Give everyone a (slight) chance */ + if ((chance < USE_DEVICE) && (rand_int(USE_DEVICE - chance + 1) == 0)) + { + chance = USE_DEVICE; + } + + /* Roll for usage */ + if ((chance < USE_DEVICE) || (randint(chance) < USE_DEVICE)) + { + /* Flush input if necessary */ + if (flush_failure) flush(); + + /* Message */ + msg_print("You failed to use the rod properly."); + + sound(SOUND_FAIL); + + return; + } + + /* Extract mana cost */ + cost = tip_ptr->pval; + + /* "Cheapness" ego halven the cost */ + if (f4 & TR4_CHEAPNESS) cost = cost / 2; + + /* A single rod is still charging */ + if (o_ptr->timeout < cost) + { + /* Flush input if necessary */ + if (flush_failure) flush(); + + /* Message */ + msg_print("The rod does not have enough mana yet."); + + return; + } + + /* Increase the timeout by the rod kind's pval. */ + o_ptr->timeout -= cost; + + /* Sound */ + sound(SOUND_ZAP); + + /* Analyze the rod */ + switch (o_ptr->pval) + { + case SV_ROD_HOME: + { + ident = TRUE; + + do_cmd_home_trump(); + + break; + } + + case SV_ROD_DETECT_TRAP: + { + if (detect_traps(DEFAULT_RADIUS)) ident = TRUE; + + break; + } + + case SV_ROD_DETECT_DOOR: + { + if (detect_doors(DEFAULT_RADIUS)) ident = TRUE; + if (detect_stairs(DEFAULT_RADIUS)) ident = TRUE; + + break; + } + + case SV_ROD_IDENTIFY: + { + ident = TRUE; + + if (!ident_spell()) use_charge = FALSE; + + break; + } + + case SV_ROD_RECALL: + { + if ((dungeon_flags2 & DF2_ASK_LEAVE) && !get_check("Leave this unique level forever? ")) + { + use_charge = FALSE; + } + else + { + recall_player(21, 15); + + ident = TRUE; + } + + break; + } + + case SV_ROD_ILLUMINATION: + { + if (lite_area(damroll(2, 8), 2)) ident = TRUE; + + break; + } + + case SV_ROD_MAPPING: + { + map_area(); + + ident = TRUE; + + break; + } + + case SV_ROD_DETECTION: + { + detect_all(DEFAULT_RADIUS); + + ident = TRUE; + + break; + } + + case SV_ROD_PROBING: + { + probing(); + + ident = TRUE; + + break; + } + + case SV_ROD_CURING: + { + if (set_blind(0)) ident = TRUE; + if (set_poisoned(0)) ident = TRUE; + if (set_confused(0)) ident = TRUE; + if (set_stun(0)) ident = TRUE; + if (set_cut(0)) ident = TRUE; + if (set_image(0)) ident = TRUE; + + break; + } + + case SV_ROD_HEALING: + { + if (hp_player(500)) ident = TRUE; + if (set_stun(0)) ident = TRUE; + if (set_cut(0)) ident = TRUE; + + break; + } + + case SV_ROD_RESTORATION: + { + if (restore_level()) ident = TRUE; + if (do_res_stat(A_STR, TRUE)) ident = TRUE; + if (do_res_stat(A_INT, TRUE)) ident = TRUE; + if (do_res_stat(A_WIS, TRUE)) ident = TRUE; + if (do_res_stat(A_DEX, TRUE)) ident = TRUE; + if (do_res_stat(A_CON, TRUE)) ident = TRUE; + if (do_res_stat(A_CHR, TRUE)) ident = TRUE; + + break; + } + + case SV_ROD_SPEED: + { + if (!p_ptr->fast) + { + if (set_fast(randint(30) + 15, 10)) ident = TRUE; + } + else + { + (void)set_fast(p_ptr->fast + 5, 10); + } + + break; + } + + case SV_ROD_TELEPORT_AWAY: + { + if (teleport_monster(dir)) ident = TRUE; + + break; + } + + case SV_ROD_DISARMING: + { + if (disarm_trap(dir)) ident = TRUE; + + break; + } + + case SV_ROD_LITE: + { + msg_print("A line of blue shimmering light appears."); + lite_line(dir); + + ident = TRUE; + + break; + } + + case SV_ROD_SLEEP_MONSTER: + { + if (sleep_monster(dir)) ident = TRUE; + + break; + } + + case SV_ROD_SLOW_MONSTER: + { + if (slow_monster(dir)) ident = TRUE; + + break; + } + + case SV_ROD_DRAIN_LIFE: + { + if (drain_life(dir, 75)) ident = TRUE; + + break; + } + + case SV_ROD_POLYMORPH: + { + if (poly_monster(dir)) ident = TRUE; + + break; + } + + case SV_ROD_ACID_BOLT: + { + fire_bolt_or_beam(10, GF_ACID, dir, damroll(6, 8)); + + ident = TRUE; + + break; + } + + case SV_ROD_ELEC_BOLT: + { + fire_bolt_or_beam(10, GF_ELEC, dir, damroll(3, 8)); + + ident = TRUE; + + break; + } + + case SV_ROD_FIRE_BOLT: + { + fire_bolt_or_beam(10, GF_FIRE, dir, damroll(8, 8)); + + ident = TRUE; + + break; + } + + case SV_ROD_COLD_BOLT: + { + fire_bolt_or_beam(10, GF_COLD, dir, damroll(5, 8)); + + ident = TRUE; + + break; + } + + case SV_ROD_ACID_BALL: + { + fire_ball(GF_ACID, dir, 60, 2); + + ident = TRUE; + + break; + } + + case SV_ROD_ELEC_BALL: + { + fire_ball(GF_ELEC, dir, 32, 2); + + ident = TRUE; + + break; + } + + case SV_ROD_FIRE_BALL: + { + fire_ball(GF_FIRE, dir, 72, 2); + + ident = TRUE; + + break; + } + + case SV_ROD_COLD_BALL: + { + fire_ball(GF_COLD, dir, 48, 2); + + ident = TRUE; + + break; + } + + case SV_ROD_HAVOC: + { + call_chaos(); + + ident = TRUE; + + break; + } + + default: + { + process_hooks(HOOK_ZAP, "(d,d)", o_ptr->tval, o_ptr->sval); + + break; + } + } + + + /* Combine / Reorder the pack (later) */ + p_ptr->notice |= (PN_COMBINE | PN_REORDER); + + /* Tried the object */ + object_tried(o_ptr); + + /* Successfully determined the object function */ + if (ident && !object_aware_p(o_ptr)) + { + object_aware(o_ptr); + gain_exp((lev + (p_ptr->lev >> 1)) / p_ptr->lev); + } + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + + /* Hack -- deal with cancelled zap */ + if (!use_charge) + { + o_ptr->timeout += cost; + + return; + } +} + + + + +/* + * Hook to determine if an object is activable + */ +static bool_ item_tester_hook_activate(object_type *o_ptr) +{ + u32b f1, f2, f3, f4, f5, esp; + + + /* Not known */ + if (!object_known_p(o_ptr)) return (FALSE); + + /* Extract the flags */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* Check activation flag */ + if (f3 & (TR3_ACTIVATE)) return (TRUE); + + /* Assume not */ + return (FALSE); +} + + + +/* + * Hack -- activate the ring of power + */ +int ring_of_power() +{ + char ch = 0, p = 0; + + int plev = p_ptr->lev; + + int timeout = 0; + + + /* Select power to use */ + while (TRUE) + { + if (!get_com("[S]ummon a wraith, [R]ule the world or " + "[C]ast a powerful attack? ", &ch)) + { + return (0); + } + + if (ch == 'S' || ch == 's') + { + p = 1; + break; + } + if (ch == 'R' || ch == 'r') + { + p = 2; + break; + } + if (ch == 'C' || ch == 'c') + { + p = 3; + break; + } + } + + /* Summon a Wraith */ + if (p == 1) + { + /* Rewrite this -- pelpel */ + if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2), + (plev > 47 ? SUMMON_HI_UNDEAD_NO_UNIQUES : SUMMON_UNDEAD), + (((plev > 24) && (randint(3) == 1)) ? TRUE : FALSE))) + { + msg_print("Cold winds begin to blow around you, " + "carrying with them the stench of decay..."); + msg_print("Ancient, long-dead forms arise from the ground " + "to serve you!"); + } + timeout = 200 + rand_int(200); + } + + /* Rule the World -- only if we can really do so */ + else if (p == 2) + { + msg_print("The power of the ring destroys the world!"); + msg_print("The world changes!"); + + autosave_checkpoint(); + + /* Leaving */ + p_ptr->leaving = TRUE; + timeout = 250 + rand_int(250); + } + + /* Cast a powerful spell */ + else if (p == 3) + { + int dir; + + if (!get_aim_dir(&dir)) return (0); + + if (rand_int(3) == 0) + { + msg_print("You call the fire of Mount Doom!"); + fire_ball(GF_METEOR, dir, 600, 4); + } + else + { + msg_print("Your ring tries to take possession of your enemy's mind!"); + fire_bolt(GF_CHARM, dir, 600); + } + timeout = 300 + rand_int(300); + } + + return (timeout); +} + + + + +/* + * Enchant some bolts + */ +bool_ brand_bolts(void) +{ + int i; + + + /* Use the first acceptable bolts */ + for (i = 0; i < INVEN_PACK; i++) + { + object_type *o_ptr = &p_ptr->inventory[i]; + + /* Skip non-bolts */ + if (o_ptr->tval != TV_BOLT) continue; + + /* Skip artifacts and ego-items */ + if (o_ptr->art_name || artifact_p(o_ptr) || ego_item_p(o_ptr)) continue; + + /* Skip cursed/broken items */ + if (cursed_p(o_ptr)) continue; + + /* Randomize */ + if (rand_int(100) < 75) continue; + + /* Message */ + msg_print("Your bolts are covered in a fiery aura!"); + + /* Ego-item */ + o_ptr->name2 = EGO_FLAME; + + /* Apply the ego */ + apply_magic(o_ptr, dun_level, FALSE, FALSE, FALSE); + + /* Enchant */ + enchant(o_ptr, rand_int(3) + 4, ENCH_TOHIT | ENCH_TODAM); + + /* Notice */ + return (TRUE); + } + + /* Flush */ + if (flush_failure) flush(); + + /* Fail */ + msg_print("The fiery enchantment failed."); + + /* Notice */ + return (TRUE); +} + + +/* + * Objects in the p_ptr->inventory can now be activated, and + * SOME of those may be able to stack (ego wands or something) + * in any case, we can't know that it's impossible. *BUT* we'll + * ignore it for now, and the timeout will be set on the entire stack + * of objects. Reduces their utility, but oh well. + * + * Note that it always takes a turn to activate an object, even if + * the user hits "escape" at the "direction" prompt. + */ +void do_cmd_activate(void) +{ + int item, lev, chance; + + char ch, spell_choice; + + object_type *o_ptr; + + u32b f1, f2, f3, f4, f5, esp; + + cptr q, s; + + + /* Prepare the hook */ + item_tester_hook = item_tester_hook_activate; + + /* Get an item */ + command_wrk = USE_EQUIP; + q = "Activate which item? "; + s = "You have nothing to activate."; + if (!get_item(&item, q, s, (USE_EQUIP | USE_INVEN))) return; + + /* Get the item */ + o_ptr = get_object(item); + + /* Extract object flags */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* Wearable items have to be worn */ + if (!(f5 & TR5_ACTIVATE_NO_WIELD)) + { + if (item < INVEN_WIELD) + { + msg_print("You must wear it to activate it."); + return; + } + } + + /* Take a turn */ + energy_use = 100; + + /* Extract the item level */ + lev = k_info[o_ptr->k_idx].level; + + /* Hack -- Use artifact level instead */ + if (artifact_p(o_ptr)) + { + if (o_ptr->tval == TV_RANDART) + { + lev = random_artifacts[o_ptr->sval].level; + } + else + { + lev = a_info[o_ptr->name1].level; + } + } + + /* Base chance of success */ + chance = p_ptr->skill_dev; + + /* Confusion hurts skill */ + if (p_ptr->confused) chance = chance / 2; + + /* Hight level objects are harder */ + chance = chance - ((lev > 50) ? 50 : lev); + + if (chance <= 0) + { + chance = 1; + } + + /* Is it simple to use ? */ + if (f4 & TR4_EASY_USE) + { + chance *= 10; + } + + /* Give everyone a (slight) chance */ + if ((chance < USE_DEVICE) && (rand_int(USE_DEVICE - chance + 1) == 0)) + { + chance = USE_DEVICE; + } + + /* Roll for usage */ + if ((chance < USE_DEVICE) || (randint(chance) < USE_DEVICE)) + { + if (flush_failure) flush(); + msg_print("You failed to activate it properly."); + sound(SOUND_FAIL); + return; + } + + /* Check the recharge */ + if (o_ptr->timeout) + { + /* Mage Staff of Spells -- Have another timeout in xtra2 */ + if (is_ego_p(o_ptr, EGO_MSTAFF_SPELL) && o_ptr->xtra2) + { + msg_print("It whines, glows and fades..."); + return; + } + + /* Monster eggs */ + else if (o_ptr->tval == TV_EGG) + { + msg_print("You resume the development of the egg."); + o_ptr->timeout = 0; + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP); + + /* Success */ + return; + } + + /* Normal activatable items */ + else + { + msg_print("It whines, glows and fades..."); + return; + } + } + + + /* Activate the item */ + msg_print("You activate it..."); + + /* Sound */ + sound(SOUND_ZAP); + + /* Lua hook ? -- go first to allow lua to override */ + if (process_hooks(HOOK_ACTIVATE, "(d)", item)) + { + return; + } + + /* New mostly unified activation code + This has to be early to allow artifacts to override normal items -- neil */ + + if ( activation_aux(o_ptr, TRUE, item) == NULL ) + { + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP); + + /* Success */ + return; + } + + /* Mage Staff of Spells */ + if (is_ego_p(o_ptr, EGO_MSTAFF_SPELL)) + { + while (TRUE) + { + if (!get_com("Use Spell [1] or [2]?", &ch)) + { + return; + } + + if (ch == '1') + { + spell_choice = 1; + break; + } + + if (ch == '2') + { + spell_choice = 2; + break; + } + } + + if (spell_choice == 1) + { + /* Still need to check timeouts because there is another counter */ + if (o_ptr->timeout) + { + msg_print("The first spell is still charging!"); + return; + } + + /* Cast spell 1 */ + activate_spell(o_ptr, spell_choice); + } + else if (spell_choice == 2) + { + /* Still need to check timeouts because there is another counter */ + if (o_ptr->xtra2) + { + msg_print("The second spell is still charging!"); + return; + } + + /* Cast spell 2 */ + activate_spell(o_ptr, spell_choice); + } + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP); + + /* Success */ + return; + } + + /* Monster eggs */ + if (o_ptr->tval == TV_EGG) + { + msg_print("You stop the development of the egg."); + o_ptr->timeout = -1; + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP); + + /* Success */ + return; + } + + /* Musical instruments */ + if (o_ptr->tval == TV_INSTRUMENT) + { + /* Horns */ + if (o_ptr->sval == SV_HORN) + { + msg_format("Your instrument emits a loud sound!"); + + aggravate_monsters(1); + + o_ptr->timeout = 100; + } + + /* Success */ + return; + } + + /* Mistake */ + msg_print("Oops. That object cannot be activated."); +} + +const char *activation_aux(object_type * o_ptr, bool_ doit, int item) +{ + static char buf[256]; + int plev = get_skill(SKILL_DEVICE); + + int i = 0, ii = 0, ij = 0, k, dir, dummy = 0; + int chance; + bool_ is_junkart = (o_ptr->tval == TV_RANDART); + + int spell = 0; + + /* Junkarts */ + if (is_junkart) + spell = activation_info[o_ptr->pval2].spell; + + /* True Actifacts */ + if (!spell && o_ptr->name1) + spell = a_info[o_ptr->name1].activate; + + /* Random and Alchemist Artifacts */ + if (!spell && o_ptr->art_name) + spell = o_ptr->xtra2; + + /* Ego Items */ + if (!spell && o_ptr->name2) + spell = e_info[o_ptr->name2].activate; + + /* Dual egos with the second ego having the activation */ + if (!spell && o_ptr->name2b) + spell = e_info[o_ptr->name2b].activate; + + /* Intrinsic to item type (rings of Ice, etc) */ + if (!spell) + spell = k_info[o_ptr->k_idx].activate; + + /* Complain about mis-configured .txt files? */ + if (!spell) + return "Unknown!"; + + /* Negative means a unified spell index */ + if (spell < 0) + { + struct spell_type *spell_ptr = spell_at(-spell); + if (doit) + { + spell_type_produce_effect(spell_ptr, item); + o_ptr->timeout = spell_type_activation_roll_timeout(spell_ptr); + } + else + { + spell_type_activation_description(spell_ptr, buf); + return buf; + } + } + else + { + /* Activate for attack */ + switch (spell) + { + case ACT_GILGALAD: + { + if (!doit) return "starlight (75) every 75+d75 turns"; + for (k = 1; k < 10; k++) + { + if (k - 5) fire_beam(GF_LITE, k, 75); + } + + o_ptr->timeout = rand_int(75) + 75; + + break; + } + + case ACT_CELEBRIMBOR: + { + if (!doit) return "temporary ESP (dur 20+d20) every 20+d50 turns"; + set_tim_esp(p_ptr->tim_esp + randint(20) + 20); + + o_ptr->timeout = rand_int(50) + 20; + + break; + } + + case ACT_SKULLCLEAVER: + { + if (!doit) return "destruction every 200+d200 turns"; + destroy_area(p_ptr->py, p_ptr->px, 15, TRUE, FALSE); + + o_ptr->timeout = rand_int(200) + 200; + + break; + } + + case ACT_HARADRIM: + { + if (!doit) return "berserk strength every 50+d50 turns"; + set_afraid(0); + set_shero(p_ptr->shero + randint(25) + 25); + hp_player(30); + + o_ptr->timeout = rand_int(50) + 50; + + break; + } + + case ACT_FUNDIN: + { + if (!doit) return "dispel evil (x4) every 100+d100 turns"; + dispel_evil(p_ptr->lev * 4); + + o_ptr->timeout = rand_int(100) + 100; + + break; + } + + case ACT_EOL: + { + if (!doit) return "mana bolt (9d8) 7+d7 turns"; + if (!get_aim_dir(&dir)) break; + fire_bolt(GF_MANA, dir, damroll(9, 8)); + + o_ptr->timeout = rand_int(7) + 7; + + break; + } + + case ACT_UMBAR: + { + if (!doit) return "magic arrow (10d10) every 20+d20 turns"; + if (!get_aim_dir(&dir)) break; + fire_bolt(GF_MISSILE, dir, damroll(10, 10)); + + o_ptr->timeout = rand_int(20) + 20; + + break; + } + + case ACT_NUMENOR: + { + /* Give full knowledge */ + /* Hack -- Maximal info */ + monster_race *r_ptr; + cave_type *c_ptr; + int x, y, m; + + if (!doit) return "analyze monster every 500+d200 turns"; + + if (!tgt_pt(&x, &y)) break; + + c_ptr = &cave[y][x]; + if (!c_ptr->m_idx) break; + + r_ptr = &r_info[c_ptr->m_idx]; + + /* Observe "maximal" attacks */ + for (m = 0; m < 4; m++) + { + /* Examine "actual" blows */ + if (r_ptr->blow[m].effect || r_ptr->blow[m].method) + { + /* Hack -- maximal observations */ + r_ptr->r_blows[m] = MAX_UCHAR; + } + } + + /* Hack -- maximal drops */ + r_ptr->r_drop_gold = r_ptr->r_drop_item = + (((r_ptr->flags1 & (RF1_DROP_4D2)) ? 8 : 0) + + ((r_ptr->flags1 & (RF1_DROP_3D2)) ? 6 : 0) + + ((r_ptr->flags1 & (RF1_DROP_2D2)) ? 4 : 0) + + ((r_ptr->flags1 & (RF1_DROP_1D2)) ? 2 : 0) + + ((r_ptr->flags1 & (RF1_DROP_90)) ? 1 : 0) + + ((r_ptr->flags1 & (RF1_DROP_60)) ? 1 : 0)); + + /* Hack -- but only "valid" drops */ + if (r_ptr->flags1 & (RF1_ONLY_GOLD)) r_ptr->r_drop_item = 0; + if (r_ptr->flags1 & (RF1_ONLY_ITEM)) r_ptr->r_drop_gold = 0; + + /* Hack -- observe many spells */ + r_ptr->r_cast_inate = MAX_UCHAR; + r_ptr->r_cast_spell = MAX_UCHAR; + + /* Hack -- know all the flags */ + r_ptr->r_flags1 = r_ptr->flags1; + r_ptr->r_flags2 = r_ptr->flags2; + r_ptr->r_flags3 = r_ptr->flags3; + r_ptr->r_flags4 = r_ptr->flags4; + r_ptr->r_flags5 = r_ptr->flags5; + r_ptr->r_flags6 = r_ptr->flags6; + r_ptr->r_flags7 = r_ptr->flags7; + r_ptr->r_flags8 = r_ptr->flags8; + r_ptr->r_flags9 = r_ptr->flags9; + + o_ptr->timeout = rand_int(200) + 500; + + break; + } + + case ACT_KNOWLEDGE: + { + if (!doit) return "whispers from beyond(sanity drain) 100+d200 turns"; + identify_fully(); + take_sanity_hit(damroll(10, 7), "the sounds of the dead"); + + o_ptr->timeout = rand_int(200) + 100; + + break; + } + + case ACT_UNDEATH: + { + if (!doit) return "ruination every 10+d10 turns"; + msg_print("The phial wells with dark light..."); + unlite_area(damroll(2, 15), 3); + take_hit(damroll(10, 10), "activating The Phial of Undeath"); + (void)dec_stat(A_DEX, 25, STAT_DEC_PERMANENT); + (void)dec_stat(A_WIS, 25, STAT_DEC_PERMANENT); + (void)dec_stat(A_CON, 25, STAT_DEC_PERMANENT); + (void)dec_stat(A_STR, 25, STAT_DEC_PERMANENT); + (void)dec_stat(A_CHR, 25, STAT_DEC_PERMANENT); + (void)dec_stat(A_INT, 25, STAT_DEC_PERMANENT); + + o_ptr->timeout = rand_int(10) + 10; + + break; + } + + case ACT_THRAIN: + { + if (!doit) return "detection every 30+d30 turns"; + msg_print("The stone glows a deep green..."); + detect_all(DEFAULT_RADIUS); + + o_ptr->timeout = rand_int(30) + 30; + + break; + } + + case ACT_BARAHIR: + { + if (!doit) return "dispel small life every 55+d55 turns"; + msg_print("You exterminate small life."); + (void)dispel_monsters(4); + + o_ptr->timeout = rand_int(55) + 55; + + break; + } + + case ACT_TULKAS: + { + if (!doit) return "haste self (75+d75 turns) every 150+d150 turns"; + msg_print("The ring glows brightly..."); + if (!p_ptr->fast) + { + (void)set_fast(randint(75) + 75, 10); + } + else + { + (void)set_fast(p_ptr->fast + 5, 10); + } + + o_ptr->timeout = rand_int(150) + 150; + + break; + } + + case ACT_NARYA: + { + if (!doit) return "healing (500) every 200+d100 turns"; + msg_print("The ring glows deep red..."); + hp_player(500); + set_blind(0); + set_confused(0); + set_poisoned(0); + set_stun(0); + set_cut(0); + + o_ptr->timeout = rand_int(100) + 200; + + break; + } + + case ACT_NENYA: + { + if (!doit) return "healing (800) every 100+d200 turns"; + msg_print("The ring glows bright white..."); + hp_player(800); + set_blind(0); + set_confused(0); + set_poisoned(0); + set_stun(0); + set_cut(0); + + o_ptr->timeout = rand_int(200) + 100; + + break; + } + + case ACT_VILYA: + { + if (!doit) return "greater healing (900) every 200+d200 turns"; + msg_print("The ring glows deep blue..."); + hp_player(900); + set_blind(0); + set_confused(0); + set_poisoned(0); + set_stun(0); + set_cut(0); + if (p_ptr->black_breath) + { + p_ptr->black_breath = FALSE; + msg_print("The hold of the Black Breath on you is broken!"); + } + + o_ptr->timeout = rand_int(200) + 200; + + break; + } + + case ACT_POWER: + { + if (!doit) return "powerful things"; + msg_print("The ring glows intensely black..."); + + o_ptr->timeout = ring_of_power(); + + break; + } + + + /* The Stone of Lore is perilous, for the sake of game balance. */ + case ACT_STONE_LORE: + { + if (!doit) return "perilous identify every turn"; + msg_print("The stone reveals hidden mysteries..."); + if (!ident_spell()) break; + + if (has_ability(AB_PERFECT_CASTING)) + { + /* Sufficient mana */ + if (20 <= p_ptr->csp) + { + /* Use some mana */ + p_ptr->csp -= 20; + } + + /* Over-exert the player */ + else + { + int oops = 20 - p_ptr->csp; + + /* No mana left */ + p_ptr->csp = 0; + p_ptr->csp_frac = 0; + + /* Message */ + msg_print("You are too weak to control the stone!"); + + /* Hack -- Bypass free action */ + (void)set_paralyzed(randint(5 * oops + 1)); + + /* Confusing. */ + (void)set_confused(p_ptr->confused + + randint(5 * oops + 1)); + } + + /* Redraw mana */ + p_ptr->redraw |= (PR_MANA); + } + + take_hit(damroll(1, 12), "perilous secrets"); + + /* Confusing. */ + if (rand_int(5) == 0) + { + (void)set_confused(p_ptr->confused + randint(10)); + } + + /* Exercise a little care... */ + if (rand_int(20) == 0) + { + take_hit(damroll(4, 10), "perilous secrets"); + } + + o_ptr->timeout = 1; + + break; + } + + case ACT_RAZORBACK: + { + if (!doit) return "star ball (150) every 1000 turns"; + msg_print("Your armor is surrounded by lightning..."); + for (i = 0; i < 8; i++) fire_ball(GF_ELEC, ddd[i], 150, 3); + + o_ptr->timeout = 1000; + + break; + } + + case ACT_BLADETURNER: + { + if (!doit) return "invulnerability (4+d8) every 800 turns"; + set_invuln(p_ptr->invuln + randint(8) + 4); + + o_ptr->timeout = 800; + + break; + } + + case ACT_MEDIATOR: + { + if (!doit) return "breathe elements (300), berserk rage, bless, and resistance every 400 turns"; + if (!get_aim_dir(&dir)) break; + msg_print("You breathe the elements."); + fire_ball(GF_MISSILE, dir, 300, 4); + msg_print("Your armor glows many colours..."); + (void)set_afraid(0); + (void)set_shero(p_ptr->shero + randint(50) + 50); + (void)hp_player(30); + (void)set_blessed(p_ptr->blessed + randint(50) + 50); + (void)set_oppose_acid(p_ptr->oppose_acid + randint(50) + 50); + (void)set_oppose_elec(p_ptr->oppose_elec + randint(50) + 50); + (void)set_oppose_fire(p_ptr->oppose_fire + randint(50) + 50); + (void)set_oppose_cold(p_ptr->oppose_cold + randint(50) + 50); + (void)set_oppose_pois(p_ptr->oppose_pois + randint(50) + 50); + + o_ptr->timeout = 400; + + break; + } + + case ACT_BELEGENNON: + { + if (!doit) return ("heal (777), curing and heroism every 300 turns"); + msg_print("A heavenly choir sings..."); + (void)set_poisoned(0); + (void)set_cut(0); + (void)set_stun(0); + (void)set_confused(0); + (void)set_blind(0); + (void)set_hero(p_ptr->hero + randint(25) + 25); + (void)hp_player(777); + + o_ptr->timeout = 300; + + break; + } + + case ACT_GORLIM: + { + if (!doit) return "rays of fear in every direction"; + turn_monsters(40 + p_ptr->lev); + + o_ptr->timeout = 3 * (p_ptr->lev + 10); + + break; + } + + case ACT_COLLUIN: + { + if (!doit) return "resistance (20+d20 turns) every 111 turns"; + msg_print("Your cloak glows many colours..."); + (void)set_oppose_acid(p_ptr->oppose_acid + randint(20) + 20); + (void)set_oppose_elec(p_ptr->oppose_elec + randint(20) + 20); + (void)set_oppose_fire(p_ptr->oppose_fire + randint(20) + 20); + (void)set_oppose_cold(p_ptr->oppose_cold + randint(20) + 20); + (void)set_oppose_pois(p_ptr->oppose_pois + randint(20) + 20); + + o_ptr->timeout = 111; + + break; + } + + + case ACT_BELANGIL: + { + if (!doit) return "frost ball (48) every 5+d5 turns"; + msg_print("Your dagger is covered in frost..."); + if (!get_aim_dir(&dir)) break; + fire_ball(GF_COLD, dir, 48, 2); + + o_ptr->timeout = rand_int(5) + 5; + + break; + } + + case ACT_ANGUIREL: + { + if (!doit) return "a getaway every 35 turns"; + switch (randint(13)) + { + case 1: + case 2: + case 3: + case 4: + case 5: + { + teleport_player(10); + + break; + } + + case 6: + case 7: + case 8: + case 9: + case 10: + { + teleport_player(222); + + break; + } + + case 11: + case 12: + { + (void)stair_creation(); + + break; + } + + default: + { + if (get_check("Leave this level? ")) + { + autosave_checkpoint(); + + /* Leaving */ + p_ptr->leaving = TRUE; + } + + break; + } + } + + o_ptr->timeout = 35; + + break; + } + + case ACT_ERU: + { + if (!doit) return "healing(7000), curing every 500 turns"; + msg_print("Your sword glows an intense white..."); + hp_player(7000); + heal_insanity(50); + set_blind(0); + set_poisoned(0); + set_confused(0); + set_stun(0); + set_cut(0); + set_image(0); + + o_ptr->timeout = 500; + + break; + } + + case ACT_DAWN: + { + if (!doit) return "summon the Legion of the Dawn every 500+d500 turns"; + msg_print("You summon the Legion of the Dawn."); + (void)summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_DAWN, TRUE); + + o_ptr->timeout = 500 + randint(500); + + break; + } + + case ACT_FIRESTAR: + { + if (!doit) return "large fire ball (72) every 100 turns"; + msg_print("Your morning star rages in fire..."); + if (!get_aim_dir(&dir)) break; + fire_ball(GF_FIRE, dir, 72, 3); + + o_ptr->timeout = 100; + + break; + } + + case ACT_TURMIL: + { + if (!doit) return "drain life (90) every 70 turns"; + msg_print("Your hammer glows white..."); + if (!get_aim_dir(&dir)) break; + drain_life(dir, 90); + + o_ptr->timeout = 70; + + break; + } + + case ACT_CUBRAGOL: + { + if (!doit) return "fire branding of bolts every 999 turns"; + msg_print("Your crossbow glows deep red..."); + (void)brand_bolts(); + + o_ptr->timeout = 999; + + break; + } + + case ACT_ELESSAR: + { + if (!doit) return "heal and cure black breath every 200 turns"; + if (p_ptr->black_breath) + { + msg_print("The hold of the Black Breath on you is broken!"); + } + p_ptr->black_breath = FALSE; + hp_player(100); + + o_ptr->timeout = 200; + + break; + } + + case ACT_GANDALF: + { + if (!doit) return "restore mana every 666 turns"; + msg_print("Your mage staff glows deep blue..."); + if (p_ptr->csp < p_ptr->msp) + { + p_ptr->csp = p_ptr->msp; + p_ptr->csp_frac = 0; + msg_print("Your feel your head clear."); + p_ptr->redraw |= (PR_MANA); + p_ptr->window |= (PW_PLAYER); + } + + o_ptr->timeout = 666; + + break; + } + + case ACT_MARDA: + { + if (!doit) return "summon a thunderlord every 1000 turns"; + if (randint(3) == 1) + { + if (summon_specific(p_ptr->py, p_ptr->px, ((plev * 3) / 2), SUMMON_THUNDERLORD)) + { + msg_print("A Thunderlord comes from thin air!"); + msg_print("'I will burn you!'"); + } + } + else + { + if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2), + SUMMON_THUNDERLORD, (plev == 50 ? TRUE : FALSE))) + { + msg_print("A Thunderlord comes from thin air!"); + msg_print("'I will help you in your difficult task.'"); + } + } + + o_ptr->timeout = 1000; + + break; + } + + case ACT_PALANTIR: + { + if (!doit) return "clairvoyance every 100+d100 turns"; + msg_print("The stone glows a deep green..."); + wiz_lite_extra(); + (void)detect_traps(DEFAULT_RADIUS); + (void)detect_doors(DEFAULT_RADIUS); + (void)detect_stairs(DEFAULT_RADIUS); + + o_ptr->timeout = rand_int(100) + 100; + + break; + } + + case ACT_EREBOR: + { + if (!doit) return "open a secret passage every 75 turns"; + msg_print("Your pick twists in your hands."); + + if (!get_aim_dir(&dir)) break; + if (passwall(dir, TRUE)) + { + msg_print("A passage opens, and you step through."); + } + else + { + msg_print("There is no wall there!"); + } + + o_ptr->timeout = 75; + + break; + } + + case ACT_DRUEDAIN: + { + if (!doit) return "detection every 99 turns"; + msg_print("Your drum shows you the world."); + detect_all(DEFAULT_RADIUS); + + o_ptr->timeout = 99; + + break; + } + + case ACT_ROHAN: + { + if (!doit) return "heroism, berserker, and haste every 250 turns"; + msg_print("Your horn glows deep red."); + set_afraid(0); + set_shero(p_ptr->shero + damroll(5, 10) + 30); + set_afraid(0); + set_hero(p_ptr->hero + damroll(5, 10) + 30); + set_fast(p_ptr->fast + damroll(5, 10) + 30, 10); + hp_player(30); + + o_ptr->timeout = 250; + + break; + } + + case ACT_HELM: + { + if (!doit) return "sound ball (300) every 300 turns"; + msg_print("Your horn emits a loud sound."); + if (!get_aim_dir(&dir)) break; + fire_ball(GF_SOUND, dir, 300, 6); + + o_ptr->timeout = 300; + + break; + } + + case ACT_BOROMIR: + { + if (!doit) return "mass human summoning every 1000 turns"; + msg_print("Your horn calls for help."); + for (i = 0; i < 15; i++) + { + summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2), SUMMON_HUMAN, TRUE); + } + + o_ptr->timeout = 1000; + + break; + } + + case ACT_HURIN: + { + if (!doit) return "berserker and +10 to speed (50) every 100+d200 turns"; + if (!p_ptr->fast) + { + (void)set_fast(randint(50) + 50, 10); + } + else + { + (void)set_fast(p_ptr->fast + 5, 10); + } + hp_player(30); + set_afraid(0); + set_shero(p_ptr->shero + randint(50) + 50); + + o_ptr->timeout = rand_int(200) + 100; + + break; + } + + case ACT_AXE_GOTHMOG: + { + if (!doit) return "fire ball (300) every 200+d200 turns"; + msg_print("Your lochaber axe erupts in fire..."); + if (!get_aim_dir(&dir)) break; + fire_ball(GF_FIRE, dir, 300, 4); + + o_ptr->timeout = 200 + rand_int(200); + + break; + } + + case ACT_MELKOR: + { + if (!doit) return "darkness ball (150) every 100 turns"; + msg_print("Your spear is covered of darkness..."); + if (!get_aim_dir(&dir)) break; + fire_ball(GF_DARK, dir, 150, 3); + + o_ptr->timeout = 100; + + break; + } + + case ACT_GROND: + { + if (!doit) return "alter reality every 100 turns"; + msg_print("Your hammer hits the floor..."); + alter_reality(); + + o_ptr->timeout = 100; + + break; + } + + case ACT_NATUREBANE: + { + if (!doit) return "dispel monsters (300) every 200+d200 turns"; + msg_print("Your axe glows blood red..."); + dispel_monsters(300); + + o_ptr->timeout = 200 + randint(200); + + break; + } + + case ACT_NIGHT: + { + if (!doit) return "vampiric drain (3*100) every 250 turns"; + msg_print("Your axe emits a black aura..."); + if (!get_aim_dir(&dir)) break; + for (i = 0; i < 3; i++) + { + if (drain_life(dir, 100)) hp_player(100); + } + + o_ptr->timeout = 250; + + break; + } + + case ACT_ORCHAST: + { + if (!doit) return "detect orcs every 10 turns"; + msg_print("Your weapon glows brightly..."); + (void)detect_monsters_xxx(RF3_ORC, DEFAULT_RADIUS); + + o_ptr->timeout = 10; + + break; + } + case ACT_SUNLIGHT: + { + if (!doit) return "beam of sunlight every 10 turns"; + + if (!get_aim_dir(&dir)) break; + msg_print("A line of sunlight appears."); + lite_line(dir); + + o_ptr->timeout = 10; + + break; + } + + case ACT_BO_MISS_1: + { + if (!doit) return "magic missile (2d6) every 2 turns"; + msg_print("It glows extremely brightly..."); + if (!get_aim_dir(&dir)) break; + fire_bolt(GF_MISSILE, dir, damroll(2, 6)); + + o_ptr->timeout = 2; + + break; + } + + case ACT_BA_POIS_1: + { + if (!doit) return "stinking cloud (12), rad. 3, every 4+d4 turns"; + msg_print("It throbs deep green..."); + if (!get_aim_dir(&dir)) break; + fire_ball(GF_POIS, dir, 12, 3); + + o_ptr->timeout = rand_int(4) + 4; + + break; + } + + case ACT_BO_ELEC_1: + { + if (!doit) return "lightning bolt (4d8) every 6+d6 turns"; + msg_print("It is covered in sparks..."); + if (!get_aim_dir(&dir)) break; + fire_bolt(GF_ELEC, dir, damroll(4, 8)); + + o_ptr->timeout = rand_int(6) + 6; + + break; + } + + case ACT_BO_ACID_1: + { + if (!doit) return "acid bolt (5d8) every 5+d5 turns"; + msg_print("It is covered in acid..."); + if (!get_aim_dir(&dir)) break; + fire_bolt(GF_ACID, dir, damroll(5, 8)); + + o_ptr->timeout = rand_int(5) + 5; + + break; + } + + case ACT_BO_COLD_1: + { + if (!doit) return "frost bolt (6d8) every 7+d7 turns"; + msg_print("It is covered in frost..."); + if (!get_aim_dir(&dir)) break; + fire_bolt(GF_COLD, dir, damroll(6, 8)); + + o_ptr->timeout = rand_int(7) + 7; + + break; + } + + case ACT_BO_FIRE_1: + { + if (!doit) return "fire bolt (9d8) every 8+d8 turns"; + msg_print("It is covered in fire..."); + if (!get_aim_dir(&dir)) break; + fire_bolt(GF_FIRE, dir, damroll(9, 8)); + + o_ptr->timeout = rand_int(8) + 8; + + break; + } + + case ACT_BA_COLD_1: + { + if (!doit) return "ball of cold (48) every 400 turns"; + msg_print("It is covered in frost..."); + if (!get_aim_dir(&dir)) break; + fire_ball(GF_COLD, dir, 48, 2); + + o_ptr->timeout = 400; + + break; + } + + case ACT_BA_FIRE_1: + { + if (!doit) return "ball of fire (72) every 400 turns"; + msg_print("It glows an intense red..."); + if (!get_aim_dir(&dir)) break; + fire_ball(GF_FIRE, dir, 72, 2); + + o_ptr->timeout = 400; + + break; + } + + case ACT_DRAIN_1: + { + if (!doit) return "drain life (100) every 100+d100 turns"; + msg_print("It glows black..."); + if (!get_aim_dir(&dir)) break; + if (drain_life(dir, 100)) + + o_ptr->timeout = rand_int(100) + 100; + + break; + } + + case ACT_BA_COLD_2: + { + if (!doit) return "ball of cold (100) every 300 turns"; + msg_print("It glows an intense blue..."); + if (!get_aim_dir(&dir)) break; + fire_ball(GF_COLD, dir, 100, 2); + + o_ptr->timeout = 300; + + break; + } + + case ACT_BA_ELEC_2: + { + if (!doit) return "ball of lightning (100) every 500 turns"; + msg_print("It crackles with electricity..."); + if (!get_aim_dir(&dir)) break; + fire_ball(GF_ELEC, dir, 100, 3); + + o_ptr->timeout = 500; + + break; + } + + case ACT_DRAIN_2: + { + if (!doit) return "drain life (120) every 400 turns"; + msg_print("It glows black..."); + if (!get_aim_dir(&dir)) break; + drain_life(dir, 120); + + o_ptr->timeout = 400; + + break; + } + + case ACT_VAMPIRE_1: + { + if (!doit) return "vampiric drain (3*50) every 400 turns"; + if (!get_aim_dir(&dir)) break; + for (dummy = 0; dummy < 3; dummy++) + { + if (drain_life(dir, 50)) + hp_player(50); + } + + o_ptr->timeout = 400; + + break; + } + + case ACT_BO_MISS_2: + { + if (!doit) return "arrows (150) every 90+d90 turns"; + msg_print("It grows magical spikes..."); + if (!get_aim_dir(&dir)) break; + fire_bolt(GF_ARROW, dir, 150); + + o_ptr->timeout = rand_int(90) + 90; + + break; + } + + case ACT_BA_FIRE_2: + { + if (!doit) return "fire ball (120) every 225+d225 turns"; + msg_print("It glows deep red..."); + if (!get_aim_dir(&dir)) break; + fire_ball(GF_FIRE, dir, 120, 3); + + o_ptr->timeout = rand_int(225) + 225; + + break; + } + + case ACT_BA_COLD_3: + { + if (!doit) return "ball of cold (200) every 325+d325 turns"; + msg_print("It glows bright white..."); + if (!get_aim_dir(&dir)) break; + fire_ball(GF_COLD, dir, 200, 3); + + o_ptr->timeout = rand_int(325) + 325; + + break; + } + + case ACT_BA_ELEC_3: + { + if (!doit) return "Lightning Ball (250) every 425+d425 turns"; + msg_print("It glows deep blue..."); + if (!get_aim_dir(&dir)) break; + fire_ball(GF_ELEC, dir, 250, 3); + + o_ptr->timeout = rand_int(425) + 425; + + break; + } + + case ACT_WHIRLWIND: + { + int y = 0, x = 0; + cave_type *c_ptr; + monster_type *m_ptr; + if (!doit) return "whirlwind attack every 250 turns"; + + for (dir = 0; dir <= 9; dir++) + { + y = p_ptr->py + ddy[dir]; + x = p_ptr->px + ddx[dir]; + c_ptr = &cave[y][x]; + + /* Get the monster */ + m_ptr = &m_list[c_ptr->m_idx]; + + /* Hack -- attack monsters */ + if (c_ptr->m_idx && (m_ptr->ml || cave_floor_bold(y, x))) + { + py_attack(y, x, -1); + } + } + + o_ptr->timeout = 250; + + break; + } + + case ACT_VAMPIRE_2: + { + if (!doit) return "vampiric drain (3*100) every 400 turns"; + if (!get_aim_dir(&dir)) break; + for (dummy = 0; dummy < 3; dummy++) + { + if (drain_life(dir, 100)) + hp_player(100); + } + + o_ptr->timeout = 400; + + break; + } + + + case ACT_CALL_CHAOS: + { + if (!doit) return "call chaos every 350 turns"; + msg_print("It glows in scintillating colours..."); + call_chaos(); + + o_ptr->timeout = 350; + + break; + } + + case ACT_ROCKET: + { + if (!doit) return "launch rocket (120+level) every 400 turns"; + if (!get_aim_dir(&dir)) break; + msg_print("You launch a rocket!"); + fire_ball(GF_ROCKET, dir, 120 + (plev), 2); + + o_ptr->timeout = 400; + + break; + } + + case ACT_DISP_EVIL: + { + if (!doit) return "dispel evil (level*5) every 300+d300 turns"; + msg_print("It floods the area with goodness..."); + dispel_evil(p_ptr->lev * 5); + + o_ptr->timeout = rand_int(300) + 300; + + break; + } + + case ACT_DISP_GOOD: + { + if (!doit) return "dispel good (level*5) every 300+d300 turns"; + msg_print("It floods the area with evil..."); + dispel_good(p_ptr->lev * 5); + + o_ptr->timeout = rand_int(300) + 300; + + break; + } + + case ACT_BA_MISS_3: + { + if (!doit) return "elemental breath (300) every 500 turns"; + if (!get_aim_dir(&dir)) break; + msg_print("You breathe the elements."); + fire_ball(GF_MISSILE, dir, 300, 4); + + o_ptr->timeout = 500; + + break; + } + + /* Activate for other offensive action */ + + case ACT_CONFUSE: + { + if (!doit) return "confuse monster every 15 turns"; + msg_print("It glows in scintillating colours..."); + if (!get_aim_dir(&dir)) break; + confuse_monster(dir, 20); + + o_ptr->timeout = 15; + + break; + } + + case ACT_SLEEP: + { + if (!doit) return "sleep nearby monsters every 55 turns"; + msg_print("It glows deep blue..."); + sleep_monsters_touch(); + + o_ptr->timeout = 55; + + break; + } + + case ACT_QUAKE: + { + if (!doit) return "earthquake (rad 10) every 50 turns"; + /* Prevent destruction of quest levels and town */ + if (!is_quest(dun_level) && dun_level) + { + earthquake(p_ptr->py, p_ptr->px, 10); + o_ptr->timeout = 50; + } + + break; + } + + case ACT_TERROR: + { + if (!doit) return "terror every 3 * (level+10) turns"; + turn_monsters(40 + p_ptr->lev); + + o_ptr->timeout = 3 * (p_ptr->lev + 10); + + break; + } + + case ACT_TELE_AWAY: + { + if (!doit) return "teleport away every 200 turns"; + if (!get_aim_dir(&dir)) break; + (void)fire_beam(GF_AWAY_ALL, dir, plev); + + o_ptr->timeout = 200; + + break; + } + + case ACT_BANISH_EVIL: + { + if (!doit) return "banish evil every 250+d250 turns"; + if (banish_evil(100)) + { + msg_print("The power of the artifact banishes evil!"); + } + + o_ptr->timeout = 250 + randint(250); + + break; + } + + case ACT_GENOCIDE: + { + if (!doit) return "genocide every 500 turns"; + msg_print("It glows deep blue..."); + (void)genocide(TRUE); + + o_ptr->timeout = 500; + + break; + } + + case ACT_MASS_GENO: + { + if (!doit) return "mass genocide every 1000 turns"; + msg_print("It lets out a long, shrill note..."); + (void)mass_genocide(TRUE); + + o_ptr->timeout = 1000; + + break; + } + + /* Activate for summoning / charming */ + + case ACT_CHARM_ANIMAL: + { + if (!doit) return "charm animal every 300 turns"; + if (!get_aim_dir(&dir)) break; + (void) charm_animal(dir, plev); + + o_ptr->timeout = 300; + + break; + } + + case ACT_CHARM_UNDEAD: + { + if (!doit) return "enslave undead every 333 turns"; + if (!get_aim_dir(&dir)) break; + (void)control_one_undead(dir, plev); + + o_ptr->timeout = 333; + + break; + } + + case ACT_CHARM_OTHER: + { + if (!doit) return "charm monster every 400 turns"; + if (!get_aim_dir(&dir)) break; + (void) charm_monster(dir, plev); + + o_ptr->timeout = 400; + + break; + } + + case ACT_CHARM_ANIMALS: + { + if (!doit) return "animal friendship every 500 turns"; + (void) charm_animals(plev * 2); + + o_ptr->timeout = 500; + + break; + } + + case ACT_CHARM_OTHERS: + { + if (!doit) return "mass charm every 750 turns"; + charm_monsters(plev * 2); + + o_ptr->timeout = 750; + + break; + } + + case ACT_SUMMON_ANIMAL: + { + if (!doit) return "summon animal every 200+d300 turns"; + (void)summon_specific_friendly(p_ptr->py, p_ptr->px, plev, SUMMON_ANIMAL_RANGER, TRUE); + + o_ptr->timeout = 200 + randint(300); + + break; + } + + case ACT_SUMMON_PHANTOM: + { + if (!doit) return "summon phantasmal servant every 200+d200 turns"; + msg_print("You summon a phantasmal servant."); + (void)summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_PHANTOM, TRUE); + + o_ptr->timeout = 200 + randint(200); + + break; + } + + case ACT_SUMMON_ELEMENTAL: + { + if (!doit) return "summon elemental every 750 turns"; + if (randint(3) == 1) + { + if (summon_specific(p_ptr->py, p_ptr->px, ((plev * 3) / 2), SUMMON_ELEMENTAL)) + { + msg_print("An elemental materialises..."); + msg_print("You fail to control it!"); + } + } + else + { + if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2), + SUMMON_ELEMENTAL, (plev == 50 ? TRUE : FALSE))) + { + msg_print("An elemental materialises..."); + msg_print("It seems obedient to you."); + } + } + + o_ptr->timeout = 750; + + break; + } + + case ACT_SUMMON_DEMON: + { + if (!doit) return "summon demon every 666+d333 turns"; + if (randint(3) == 1) + { + if (summon_specific(p_ptr->py, p_ptr->px, ((plev * 3) / 2), SUMMON_DEMON)) + { + msg_print("The area fills with a stench of sulphur and brimstone."); + msg_print("'NON SERVIAM! Wretch! I shall feast on thy mortal soul!'"); + } + } + else + { + if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2), + SUMMON_DEMON, (plev == 50 ? TRUE : FALSE))) + { + msg_print("The area fills with a stench of sulphur and brimstone."); + msg_print("'What is thy bidding... Master?'"); + } + } + + o_ptr->timeout = 666 + randint(333); + + break; + } + + case ACT_SUMMON_UNDEAD: + { + if (!doit) return "summon undead every 666+d333 turns"; + if (randint(3) == 1) + { + if (summon_specific(p_ptr->py, p_ptr->px, ((plev * 3) / 2), + (plev > 47 ? SUMMON_HI_UNDEAD : SUMMON_UNDEAD))) + { + msg_print("Cold winds begin to blow around you, carrying with them the stench of decay..."); + msg_print("'The dead arise... to punish you for disturbing them!'"); + } + } + else + { + if (summon_specific_friendly(p_ptr->py, p_ptr->px, ((plev * 3) / 2), + (plev > 47 ? SUMMON_HI_UNDEAD_NO_UNIQUES : SUMMON_UNDEAD), + (((plev > 24) && (randint(3) == 1)) ? TRUE : FALSE))) + { + msg_print("Cold winds begin to blow around you, carrying with them the stench of decay..."); + msg_print("Ancient, long-dead forms arise from the ground to serve you!"); + } + } + + o_ptr->timeout = 666 + randint(333); + + break; + } + + /* Activate for healing */ + + case ACT_CURE_LW: + { + if (!doit) return format("cure light wounds every %d turns", (is_junkart ? 50 : 10)); + (void)set_afraid(0); + (void)hp_player(30); + + o_ptr->timeout = 10; + + break; + } + + case ACT_CURE_MW: + { + if (!doit) return format("cure serious wounds every %s turns", (is_junkart? "75" : "3+d3")); + msg_print("It radiates deep purple..."); + hp_player(damroll(4, 8)); + (void)set_cut((p_ptr->cut / 2) - 50); + + o_ptr->timeout = rand_int(3) + 3; + + break; + } + + case ACT_CURE_POISON: + { + if (!doit) return "remove fear and cure poison every 5 turns"; + msg_print("It glows deep blue..."); + (void)set_afraid(0); + (void)set_poisoned(0); + + o_ptr->timeout = 5; + + break; + } + + case ACT_REST_LIFE: + { + if (!doit) return "restore life levels every 450 turns"; + msg_print("It glows a deep red..."); + restore_level(); + + o_ptr->timeout = 450; + + break; + } + + case ACT_REST_ALL: + { + if (!doit) return format("restore stats and life levels every %d turns", (is_junkart ? 200 : 750)); + msg_print("It glows a deep green..."); + (void)do_res_stat(A_STR, TRUE); + (void)do_res_stat(A_INT, TRUE); + (void)do_res_stat(A_WIS, TRUE); + (void)do_res_stat(A_DEX, TRUE); + (void)do_res_stat(A_CON, TRUE); + (void)do_res_stat(A_CHR, TRUE); + (void)restore_level(); + + o_ptr->timeout = 750; + + break; + } + + case ACT_CURE_700: + { + if (!doit) return format("heal 700 hit points every %d turns", (is_junkart ? 100 : 250)); + msg_print("It glows deep blue..."); + msg_print("You feel a warm tingling inside..."); + (void)hp_player(700); + (void)set_cut(0); + + o_ptr->timeout = 250; + + break; + } + + case ACT_CURE_1000: + { + if (!doit) return "heal 1000 hit points every 888 turns"; + msg_print("It glows a bright white..."); + msg_print("You feel much better..."); + (void)hp_player(1000); + (void)set_cut(0); + + o_ptr->timeout = 888; + + break; + } + + case ACT_ESP: + { + if (!doit) return "temporary ESP (dur 25+d30) every 200 turns"; + (void)set_tim_esp(p_ptr->tim_esp + randint(30) + 25); + + o_ptr->timeout = 200; + + break; + } + + case ACT_BERSERK: + { + if (!doit) return "heroism and berserk (dur 50+d50) every 100+d100 turns"; + (void)set_shero(p_ptr->shero + randint(50) + 50); + (void)set_blessed(p_ptr->blessed + randint(50) + 50); + + o_ptr->timeout = 100 + randint(100); + + break; + } + + case ACT_PROT_EVIL: + { + if (!doit) return "protection from evil (dur level*3 + d25) every 225+d225 turns"; + msg_print("It lets out a shrill wail..."); + k = 3 * p_ptr->lev; + (void)set_protevil(p_ptr->protevil + randint(25) + k); + + o_ptr->timeout = rand_int(225) + 225; + + break; + } + + case ACT_RESIST_ALL: + { + if (!doit) return "resist elements (dur 40+d40) every 200 turns"; + msg_print("It glows many colours..."); + (void)set_oppose_acid(p_ptr->oppose_acid + randint(40) + 40); + (void)set_oppose_elec(p_ptr->oppose_elec + randint(40) + 40); + (void)set_oppose_fire(p_ptr->oppose_fire + randint(40) + 40); + (void)set_oppose_cold(p_ptr->oppose_cold + randint(40) + 40); + (void)set_oppose_pois(p_ptr->oppose_pois + randint(40) + 40); + + o_ptr->timeout = 200; + + break; + } + + case ACT_SPEED: + { + if (!doit) return "speed (dur 20+d20) every 250 turns"; + msg_print("It glows bright green..."); + if (!p_ptr->fast) + { + (void)set_fast(randint(20) + 20, 10); + } + else + { + (void)set_fast(p_ptr->fast + 5, 10); + } + + o_ptr->timeout = 250; + + break; + } + + case ACT_XTRA_SPEED: + { + if (!doit) return "speed (dur 75+d75) every 200+d200 turns"; + msg_print("It glows brightly..."); + if (!p_ptr->fast) + { + (void)set_fast(randint(75) + 75, 10); + } + else + { + (void)set_fast(p_ptr->fast + 5, 10); + } + + o_ptr->timeout = rand_int(200) + 200; + + break; + } + + case ACT_WRAITH: + { + if (!doit) return "wraith form (level/2 + d(level/2)) every 1000 turns"; + set_shadow(p_ptr->tim_wraith + randint(plev / 2) + (plev / 2)); + + o_ptr->timeout = 1000; + + break; + } + + case ACT_INVULN: + { + if (!doit) return "invulnerability (dur 8+d8) every 1000 turns"; + (void)set_invuln(p_ptr->invuln + randint(8) + 8); + + o_ptr->timeout = 1000; + + break; + } + + /* Activate for general purpose effect (detection etc.) */ + + case ACT_LIGHT: + { + if (!doit) return format("light area (dam 2d15) every %s turns", (is_junkart ? "100" : "10+d10")); + msg_print("It wells with clear light..."); + lite_area(damroll(2, 15), 3); + + o_ptr->timeout = rand_int(10) + 10; + + break; + } + + case ACT_MAP_LIGHT: + { + if (!doit) return "light (dam 2d15) & map area every 50+d50 turns"; + msg_print("It shines brightly..."); + map_area(); + lite_area(damroll(2, 15), 3); + + o_ptr->timeout = rand_int(50) + 50; + + break; + } + + case ACT_DETECT_ALL: + { + if (!doit) return "detection every 55+d55 turns"; + msg_print("It glows bright white..."); + msg_print("An image forms in your mind..."); + detect_all(DEFAULT_RADIUS); + + o_ptr->timeout = rand_int(55) + 55; + + break; + } + + case ACT_DETECT_XTRA: + { + if (!doit) return "detection, probing and identify true every 1000 turns"; + msg_print("It glows brightly..."); + detect_all(DEFAULT_RADIUS); + probing(); + identify_fully(); + + o_ptr->timeout = 1000; + + break; + } + + case ACT_ID_FULL: + { + if (!doit) return "identify true every 750 turns"; + msg_print("It glows yellow..."); + identify_fully(); + + o_ptr->timeout = 750; + + break; + } + + case ACT_ID_PLAIN: + { + if (!doit) return "identify spell every 10 turns"; + if (!ident_spell()) break; + + o_ptr->timeout = 10; + + break; + } + + case ACT_RUNE_EXPLO: + { + if (!doit) return "explosive rune every 200 turns"; + msg_print("It glows bright red..."); + explosive_rune(); + + o_ptr->timeout = 200; + + break; + } + + case ACT_RUNE_PROT: + { + if (!doit) return "rune of protection every 400 turns"; + msg_print("It glows light blue..."); + warding_glyph(); + + o_ptr->timeout = 400; + + break; + } + + case ACT_SATIATE: + { + if (!doit) return "satisfy hunger every 200 turns"; + (void)set_food(PY_FOOD_MAX - 1); + + o_ptr->timeout = 200; + + break; + } + + case ACT_DEST_DOOR: + { + if (!doit) return "destroy doors and traps every 10 turns"; + msg_print("It glows bright red..."); + destroy_doors_touch(); + + o_ptr->timeout = 10; + + break; + } + + case ACT_STONE_MUD: + { + if (!doit) return "stone to mud every 5 turns"; + msg_print("It pulsates..."); + if (!get_aim_dir(&dir)) break; + wall_to_mud(dir); + + o_ptr->timeout = 5; + + break; + } + + case ACT_RECHARGE: + { + if (!doit) return "recharging every 70 turns"; + recharge(60); + + o_ptr->timeout = 70; + + break; + } + + case ACT_ALCHEMY: + { + if (!doit) return "alchemy every 500 turns"; + msg_print("It glows bright yellow..."); + (void) alchemy(); + + o_ptr->timeout = 500; + + break; + } + + case ACT_DIM_DOOR: + { + if (!doit) return "dimension door every 100 turns"; + if (dungeon_flags2 & DF2_NO_TELEPORT) + { + msg_print("Not on special levels!"); + break; + } + + msg_print("You open a Void Jumpgate. Choose a destination."); + if (!tgt_pt(&ii, &ij)) break; + + p_ptr->energy -= 60 - plev; + + if (!cave_empty_bold(ij, ii) || (cave[ij][ii].info & CAVE_ICKY) || + (distance(ij, ii, p_ptr->py, p_ptr->px) > plev + 2) || + (!rand_int(plev * plev / 2))) + { + msg_print("You fail to exit the void correctly!"); + p_ptr->energy -= 100; + get_pos_player(10, &ij, &ii); + } + + cave_set_feat(p_ptr->py, p_ptr->px, FEAT_BETWEEN); + cave_set_feat(ij, ii, FEAT_BETWEEN); + cave[p_ptr->py][p_ptr->px].special = ii + (ij << 8); + cave[ij][ii].special = p_ptr->px + (p_ptr->py << 8); + + o_ptr->timeout = 100; + + break; + } + + case ACT_TELEPORT: + { + if (!doit) return format("teleport (range 100) every %d turns", (is_junkart? 100 : 45)); + msg_print("It twists space around you..."); + teleport_player(100); + + o_ptr->timeout = 45; + + break; + } + + case ACT_RECALL: + { + if (!(dungeon_flags2 & DF2_ASK_LEAVE) || ((dungeon_flags2 & DF2_ASK_LEAVE) && !get_check("Leave this unique level forever? "))) + { + if (!doit) return "word of recall every 200 turns"; + msg_print("It glows soft white..."); + recall_player(20,15); + + o_ptr->timeout = 200; + } + + break; + } + + case ACT_DEATH: + { + if (!doit) return "death"; + take_hit(5000, "activating a death spell"); + + /* Timeout is set before return */ + + break; + } + + case ACT_RUINATION: + { + if (!doit) return "Ruination"; + msg_print("Your nerves and muscles feel weak and lifeless!"); + + take_hit(damroll(10, 10), "activating Ruination"); + (void)dec_stat(A_DEX, 25, TRUE); + (void)dec_stat(A_WIS, 25, TRUE); + (void)dec_stat(A_CON, 25, TRUE); + (void)dec_stat(A_STR, 25, TRUE); + (void)dec_stat(A_CHR, 25, TRUE); + (void)dec_stat(A_INT, 25, TRUE); + + /* Timeout is set before return */ + + break; + } + + case ACT_DESTRUC: + { + if (!doit) return "Destruction every 100 turns"; + earthquake(p_ptr->py, p_ptr->px, 12); + + /* Timeout is set before return */ + + break; + } + + case ACT_UNINT: + { + if (!doit) return "decreasing Intelligence"; + (void)dec_stat(A_INT, 25, FALSE); + + /* Timeout is set before return */ + + break; + } + + case ACT_UNSTR: + { + if (!doit) return "decreasing Strength"; + (void)dec_stat(A_STR, 25, FALSE); + + /* Timeout is set before return */ + + break; + } + + case ACT_UNCON: + { + if (!doit) return "decreasing Constitution"; + (void)dec_stat(A_CON, 25, FALSE); + + /* Timeout is set before return */ + + break; + } + + case ACT_UNCHR: + { + if (!doit) return "decreasing Charisma"; + (void)dec_stat(A_CHR, 25, FALSE); + + /* Timeout is set before return */ + + break; + } + + case ACT_UNDEX: + { + if (!doit) return "decreasing Dexterity"; + (void)dec_stat(A_DEX, 25, FALSE); + + /* Timeout is set before return */ + + break; + } + + case ACT_UNWIS: + { + if (!doit) return "decreasing Wisdom"; + (void)dec_stat(A_WIS, 25, FALSE); + + /* Timeout is set before return */ + + break; + } + + case ACT_STATLOSS: + { + if (!doit) return "stat loss"; + (void)dec_stat(A_STR, 15, FALSE); + (void)dec_stat(A_INT, 15, FALSE); + (void)dec_stat(A_WIS, 15, FALSE); + (void)dec_stat(A_DEX, 15, FALSE); + (void)dec_stat(A_CON, 15, FALSE); + (void)dec_stat(A_CHR, 15, FALSE); + + /* Timeout is set before return */ + + break; + } + + case ACT_HISTATLOSS: + { + if (!doit) return "high stat loss"; + (void)dec_stat(A_STR, 25, FALSE); + (void)dec_stat(A_INT, 25, FALSE); + (void)dec_stat(A_WIS, 25, FALSE); + (void)dec_stat(A_DEX, 25, FALSE); + (void)dec_stat(A_CON, 25, FALSE); + (void)dec_stat(A_CHR, 25, FALSE); + + /* Timeout is set before return */ + + break; + } + + case ACT_EXPLOSS: + { + if (!doit) return "experience loss"; + lose_exp(p_ptr->exp / 20); + + /* Timeout is set before return */ + + break; + } + + case ACT_HIEXPLOSS: + { + if (!doit) return "high experience loss"; + lose_exp(p_ptr->exp / 10); + + /* Timeout is set before return */ + + break; + } + + case ACT_SUMMON_MONST: + { + if (!doit) return "summon monster"; + summon_specific(p_ptr->py, p_ptr->px, max_dlv[dungeon_type], 0); + + /* Timeout is set before return */ + + break; + } + + case ACT_PARALYZE: + { + if (!doit) return "paralyze"; + set_paralyzed(20 + randint(10)); + + /* Timeout is set before return */ + + break; + } + + case ACT_HALLU: + { + if (!doit) return "hallucination every 10 turns"; + set_image(p_ptr->image + 20 + randint(10)); + + /* Timeout is set before return */ + + break; + } + + case ACT_POISON: + { + if (!doit) return "poison"; + set_poisoned(p_ptr->poisoned + 20 + randint(10)); + + /* Timeout is set before return */ + + break; + } + + case ACT_HUNGER: + { + if (!doit) return "create hunger"; + (void)set_food(PY_FOOD_WEAK); + + /* Timeout is set before return */ + + break; + } + + case ACT_STUN: + { + if (!doit) return "stun"; + set_stun(p_ptr->stun + 20 + randint(10)); + + /* Timeout is set before return */ + + break; + } + + case ACT_CUTS: + { + if (!doit) return "cuts"; + set_cut(p_ptr->cut + 20 + randint(10)); + + /* Timeout is set before return */ + + break; + } + + case ACT_PARANO: + { + if (!doit) return "confusion"; + set_confused(p_ptr->confused + 30 + randint(10)); + + /* Timeout is set before return */ + + break; + } + + case ACT_CONFUSION: + { + if (!doit) return "confusion"; + set_confused(p_ptr->confused + 20 + randint(10)); + + /* Timeout is set before return */ + + break; + } + + case ACT_BLIND: + { + if (!doit) return "blindness"; + set_blind(p_ptr->blind + 20 + randint(10)); + + /* Timeout is set before return */ + + break; + } + + case ACT_PET_SUMMON: + { + if (!doit) return "summon pet every 101 turns"; + summon_specific_friendly(p_ptr->py, p_ptr->px, max_dlv[dungeon_type], 0, FALSE); + + /* Timeout is set before return */ + /*FINDME*/ + + break; + } + + case ACT_CURE_PARA: + { + if (!doit) return "cure confusion every 500 turns"; + set_confused(0); + + /* Timeout is set before return */ + + break; + } + + case ACT_CURE_HALLU: + { + if (!doit) return "cure hallucination every 100 turns"; + set_image(0); + + /* Timeout is set before return */ + + break; + } + + case ACT_CURE_POIS: + { + if (!doit) return "cure poison every 100 turns"; + set_poisoned(0); + + /* Timeout is set before return */ + + break; + } + + case ACT_CURE_HUNGER: + { + if (!doit) return "satisfy hunger every 100 turns"; + (void)set_food(PY_FOOD_MAX - 1); + + /* Timeout is set before return */ + + break; + } + + case ACT_CURE_STUN: + { + if (!doit) return "cure stun every 100 turns"; + set_stun(0); + + /* Timeout is set before return */ + + break; + } + + case ACT_CURE_CUTS: + { + if (!doit) return "cure cuts every 100 turns"; + set_cut(0); + + /* Timeout is set before return */ + + break; + } + + case ACT_CURE_FEAR: + { + if (!doit) return "cure fear every 100 turns"; + set_afraid(0); + + /* Timeout is set before return */ + + break; + } + + case ACT_CURE_CONF: + { + if (!doit) return "cure confusion every 100 turns"; + set_confused(0); + + /* Timeout is set before return */ + + break; + } + + case ACT_CURE_BLIND: + { + if (!doit) return "cure blindness every 100 turns"; + set_blind(0); + + /* Timeout is set before return */ + + break; + } + + case ACT_CURING: + { + if (!doit) return "curing every 110 turns"; + set_blind(0); + set_poisoned(0); + set_confused(0); + set_stun(0); + set_cut(0); + set_image(0); + + /* Timeout is set before return */ + + break; + } + + case ACT_DARKNESS: + { + if (!doit) return "darkness"; + unlite_area(damroll(2, 10), 10); + + /* Timeout is set before return */ + + break; + } + + case ACT_LEV_TELE: + { + if (!doit) return "teleport level every 50 turns"; + teleport_player_level(); + + /* Timeout is set before return */ + + break; + } + + case ACT_ACQUIREMENT: + { + if (!doit) return "acquirement every 3000 turns"; + acquirement(p_ptr->py, p_ptr->px, 1, FALSE, FALSE); + + /* Timeout is set before return */ + + break; + } + + case ACT_WEIRD: + { + if (!doit) return "something weird every 5 turns"; + /* It doesn't do anything */ + + /* Timeout is set before return */ + + break; + } + + case ACT_AGGRAVATE: + { + if (!doit) return "aggravate"; + aggravate_monsters(1); + + /* Timeout is set before return */ + + break; + } + + case ACT_MUT: + { + if (!doit) return "gain corruption every 10 turns"; + gain_random_corruption(); + /* Timeout is set before return */ + + break; + } + + case ACT_CURE_INSANITY: + { + if (!doit) return "cure insanity every 200 turns"; + heal_insanity(damroll(10, 10)); + + /* Timeout is set before return */ + + break; + } + + case ACT_CURE_MUT: + { + msg_print("Ahah, you wish."); + /* Timeout is set before return */ + + break; + } + + case ACT_LIGHT_ABSORBTION: + { + int y, x, light = 0, dir; + cave_type *c_ptr; + + if (!doit) return "light absorption every 80 turns"; + + for (y = p_ptr->py - 6; y <= p_ptr->py + 6; y++) + { + for (x = p_ptr->px - 6; x <= p_ptr->px + 6; x++) + { + if (!in_bounds(y, x)) continue; + + c_ptr = &cave[y][x]; + + if (distance(y, x, p_ptr->py, p_ptr->px) > 6) continue; + + if (c_ptr->info & CAVE_GLOW) + { + light++; + + /* No longer in the array */ + c_ptr->info &= ~(CAVE_TEMP); + + /* Darken the grid */ + c_ptr->info &= ~(CAVE_GLOW); + + /* Hack -- Forget "boring" grids */ + if (cave_plain_floor_grid(c_ptr) && + !(c_ptr->info & (CAVE_TRDT))) + { + /* Forget the grid */ + c_ptr->info &= ~(CAVE_MARK); + + /* Notice */ + note_spot(y, x); + } + + /* Process affected monsters */ + if (c_ptr->m_idx) + { + /* Update the monster */ + update_mon(c_ptr->m_idx, FALSE); + } + + /* Redraw */ + lite_spot(y, x); + } + } + } + + if (!get_aim_dir(&dir)) return (FALSE); + + msg_print("The light around you is absorbed... " + "and released in a powerful bolt!"); + fire_bolt(GF_LITE, dir, damroll(light, p_ptr->lev)); + + /* Timeout is set before return */ + + break; + } + /* Horns of DragonKind (Note that these are new egos)*/ + case ACT_BA_FIRE_H: + { + if (!doit) return "large fire ball (300) every 100 turns"; + fire_ball(GF_FIRE, 5, 300, 7); + + o_ptr->timeout = 100; + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP); + + break; + } + case ACT_BA_COLD_H: + { + if (!doit) return "large cold ball (300) every 100 turns"; + fire_ball(GF_COLD, 5, 300, 7); + + o_ptr->timeout = 100; + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP); + + break; + } + case ACT_BA_ELEC_H: + { + if (!doit) return "large lightning ball (300) every 100 turns"; + fire_ball(GF_ELEC, 5, 300, 7); + + o_ptr->timeout = 100; + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP); + + break; + } + case ACT_BA_ACID_H: + { + if (!doit) return "large acid ball (300) every 100 turns"; + fire_ball(GF_ACID, 5, 300, 7); + + o_ptr->timeout = 100; + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP); + + break; + } + + case ACT_SPIN: + { + if (!doit) return "spinning around every 50+d25 turns"; + do_spin(); + + o_ptr->timeout = 50 + randint(25); + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP); + + /* Done */ + break; + } + case ACT_NOLDOR: + { + if (!doit) return "detect treasure every 10+d20 turns"; + detect_treasure(DEFAULT_RADIUS); + + o_ptr->timeout = 10 + randint(20); + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP); + + /* Done */ + break; + } + case ACT_SPECTRAL: + { + if (!doit) return "wraith-form every 50+d50 turns"; + if (!p_ptr->wraith_form) + { + set_shadow(20 + randint(20)); + } + else + { + set_shadow(p_ptr->tim_wraith + randint(20)); + } + + o_ptr->timeout = 50 + randint(50); + + /* Window stuff */ + p_ptr->window |= PW_INVEN | PW_EQUIP; + + /* Done */ + break; + } + case ACT_JUMP: + { + if (!doit) return "phasing every 10+d10 turns"; + teleport_player(10); + o_ptr->timeout = 10 + randint(10); + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP); + + /* Done */ + break; + } + + case ACT_DEST_TELE: + { + if (!doit) return "teleportation and destruction of the ring"; + if (!item) + { + msg_print("You can't activate this when it's there!"); + } + if (get_check("This will destroy the ring. Do you wish to continue? ")) + { + msg_print("The ring explodes into a space distortion."); + teleport_player(200); + + /* It explodes, doesn't it ? */ + take_hit(damroll(2, 10), "an exploding ring"); + + inc_stack_size_ex(item, -255, OPTIMIZE, NO_DESCRIBE); + } + + break; + } + /*amulet of serpents dam 100, rad 2 timeout 40+d60 */ + case ACT_BA_POIS_4: + { + if (!doit) return "venom breathing every 40+d60 turns"; + /* Get a direction for breathing (or abort) */ + if (!get_aim_dir(&dir)) break; + + msg_print("You breathe venom..."); + fire_ball(GF_POIS, dir, 100, 2); + + o_ptr->timeout = rand_int(60) + 40; + + /* Window stuff */ + p_ptr->window |= PW_INVEN | PW_EQUIP; + + /* Done */ + break; + } + /*rings of X 50,50+d50 dur 20+d20 */ + case ACT_BA_COLD_4: + { + if (!doit) return "ball of cold and resist cold every 50+d50 turns"; + /* Get a direction for breathing (or abort) */ + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_COLD, dir, 50, 2); + (void)set_oppose_cold(p_ptr->oppose_cold + randint(20) + 20); + + o_ptr->timeout = rand_int(50) + 50; + + break; + } + + case ACT_BA_FIRE_4: + { + if (!doit) return "ball of fire and resist fire every 50+d50 turns"; + /* Get a direction for breathing (or abort) */ + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_FIRE, dir, 50, 2); + (void)set_oppose_fire(p_ptr->oppose_fire + randint(20) + 20); + + o_ptr->timeout = rand_int(50) + 50; + + break; + } + case ACT_BA_ACID_4: + { + if (!doit) return "ball of acid and resist acid every 50+d50 turns"; + /* Get a direction for breathing (or abort) */ + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_ACID, dir, 50, 2); + (void)set_oppose_acid(p_ptr->oppose_acid + randint(20) + 20); + + o_ptr->timeout = rand_int(50) + 50; + + break; + } + + case ACT_BA_ELEC_4: + { + if (!doit) return "ball of lightning and resist lightning every 50+d50 turns"; + /* Get a direction for breathing (or abort) */ + if (!get_aim_dir(&dir)) break; + + fire_ball(GF_ELEC, dir, 50, 2); + (void)set_oppose_elec(p_ptr->oppose_elec + randint(20) + 20); + + o_ptr->timeout = rand_int(50) + 50; + + break; + } + + case ACT_BR_ELEC: + { + if (!doit) return "breathe lightning (100) every 90+d90 turns"; + if (!get_aim_dir(&dir)) break; + msg_print("You breathe lightning."); + fire_ball(GF_ELEC, dir, 100, 2); + + o_ptr->timeout = rand_int(90) + 90; + + break; + } + + case ACT_BR_COLD: + { + if (!doit) return "breathe frost (110) every 90+d90 turns"; + if (!get_aim_dir(&dir)) break; + msg_print("You breathe frost."); + fire_ball(GF_COLD, dir, 110, 2); + + o_ptr->timeout = rand_int(90) + 90; + + break; + } + + case ACT_BR_FIRE: + { + if (!doit) return "breathe fire (200) every 90+d90 turns"; + if (!get_aim_dir(&dir)) break; + msg_print("You breathe fire."); + fire_ball(GF_FIRE, dir, 200, 2); + + o_ptr->timeout = rand_int(90) + 90; + + break; + } + + case ACT_BR_ACID: + { + if (!doit) return "breathe acid (130) every 90+d90 turns"; + if (!get_aim_dir(&dir)) break; + msg_print("You breathe acid."); + fire_ball(GF_ACID, dir, 130, 2); + + o_ptr->timeout = rand_int(90) + 90; + + break; + } + + case ACT_BR_POIS: + { + if (!doit) return "breathe poison gas (150) every 90+d90 turns"; + if (!get_aim_dir(&dir)) break; + msg_print("You breathe poison gas."); + fire_ball(GF_POIS, dir, 150, 2); + + o_ptr->timeout = rand_int(90) + 90; + + break; + } + + case ACT_BR_MANY: + { + if (!doit) return "breathe multi-hued (250) every 60+d60 turns"; + if (!get_aim_dir(&dir)) break; + chance = rand_int(5); + msg_format("You breathe %s.", + ((chance == 1) ? "lightning" : + ((chance == 2) ? "frost" : + ((chance == 3) ? "acid" : + ((chance == 4) ? "poison gas" : "fire"))))); + fire_ball(((chance == 1) ? GF_ELEC : + ((chance == 2) ? GF_COLD : + ((chance == 3) ? GF_ACID : + ((chance == 4) ? GF_POIS : GF_FIRE)))), + dir, 250, 2); + + o_ptr->timeout = rand_int(60) + 60; + + break; + } + + case ACT_BR_CONF: + { + if (!doit) return "breathe confusion (120) every 90+d90 turns"; + if (!get_aim_dir(&dir)) break; + msg_print("You breathe confusion."); + fire_ball(GF_CONFUSION, dir, 120, 2); + + o_ptr->timeout = rand_int(90) + 90; + + break; + } + + case ACT_BR_SOUND: + { + if (!doit) return "breathe sound (130) every 90+d90 turns"; + if (!get_aim_dir(&dir)) break; + msg_print("You breathe sound."); + fire_ball(GF_SOUND, dir, 130, 2); + + o_ptr->timeout = rand_int(90) + 90; + + break; + } + + case ACT_BR_CHAOS: + { + if (!doit) return "breathe chaos/disenchant (220) every 60+d90 turns"; + if (!get_aim_dir(&dir)) break; + chance = rand_int(2); + msg_format("You breathe %s.", + ((chance == 1 ? "chaos" : "disenchantment"))); + fire_ball((chance == 1 ? GF_CHAOS : GF_DISENCHANT), + dir, 220, 2); + + o_ptr->timeout = rand_int(90) + 60; + + break; + } + + case ACT_BR_SHARD: + { + if (!doit) return "breathe sound/shards (230) every 60+d90 turns"; + if (!get_aim_dir(&dir)) break; + chance = rand_int(2); + msg_format("You breathe %s.", + ((chance == 1 ? "sound" : "shards"))); + fire_ball((chance == 1 ? GF_SOUND : GF_SHARDS), + dir, 230, 2); + + o_ptr->timeout = rand_int(90) + 60; + + break; + } + + case ACT_BR_BALANCE: + { + if (!doit) return "breathe balance (250) every 60+d90 turns"; + if (!get_aim_dir(&dir)) break; + chance = rand_int(4); + msg_format("You breathe %s.", + ((chance == 1) ? "chaos" : + ((chance == 2) ? "disenchantment" : + ((chance == 3) ? "sound" : "shards")))); + fire_ball(((chance == 1) ? GF_CHAOS : + ((chance == 2) ? GF_DISENCHANT : + ((chance == 3) ? GF_SOUND : GF_SHARDS))), + dir, 250, 2); + + o_ptr->timeout = rand_int(90) + 60; + + break; + } + + case ACT_BR_LIGHT: + { + if (!doit) return "breathe light/darkness (200) every 60+d90 turns"; + if (!get_aim_dir(&dir)) break; + chance = rand_int(2); + msg_format("You breathe %s.", + ((chance == 0 ? "light" : "darkness"))); + fire_ball((chance == 0 ? GF_LITE : GF_DARK), dir, 200, 2); + + o_ptr->timeout = rand_int(90) + 60; + + break; + } + case ACT_BR_POWER: + { + if (!doit) return "breathe the elements (300) every 60+d90 turns"; + if (!get_aim_dir(&dir)) break; + msg_print("You breathe the elements."); + fire_ball(GF_MISSILE, dir, 300, 3); + + o_ptr->timeout = rand_int(90) + 60; + + break; + } + case ACT_GROW_MOLD: + { + if (!doit) return "grow mushrooms every 50+d50 turns"; + msg_print("You twirl and spores fly everywhere!"); + for (i = 0; i < 8; i++) + summon_specific_friendly(p_ptr->py, p_ptr->px, p_ptr->lev, SUMMON_BIZARRE1, FALSE); + + o_ptr->timeout = randint(50) + 50; + + break; + } + case ACT_MUSIC: + /* + fall through to unknown, as music should be + handled by calling procedure. + */ + + default: + { + msg_format("Unknown activation effect: %d.", spell); + if ( !doit ) return "Unknown Activation"; + return NULL; + } + } + } + + /* Set timeout for junkarts + * Note that I still need to set the timeouts for other + * (non-random) artifacts above + */ + if (is_junkart && doit) + o_ptr->timeout = activation_info[o_ptr->pval2].cost / 10; + + return NULL; +} + + +static bool_ activate_spell(object_type * o_ptr, byte choice) +{ + int mana = 0, gf = 0, mod = 0; + + rune_spell s_ptr; + + + if (choice == 1) + { + gf = o_ptr->pval & 0xFFFF; + mod = o_ptr->pval3 & 0xFFFF; + mana = o_ptr->pval2 & 0xFF; + } + else if (choice == 2) + { + gf = o_ptr->pval >> 16; + mod = o_ptr->pval3 >> 16; + mana = o_ptr->pval2 >> 8; + } + + s_ptr.type = gf; + s_ptr.rune2 = 1 << mod; + s_ptr.mana = mana; + + /* Execute */ + rune_exec(&s_ptr, 0); + + if (choice == 1) o_ptr->timeout = mana * 5; + if (choice == 2) o_ptr->xtra2 = mana * 5; + + return (TRUE); +} diff --git a/src/cmd7.c b/src/cmd7.c deleted file mode 100644 index c9be0c66..00000000 --- a/src/cmd7.c +++ /dev/null @@ -1,7632 +0,0 @@ -/* File: cmd7.c */ - -/* Purpose: More Class commands */ - -/* - * Copyright (c) 1999 Dark God - * - * This software may be copied and distributed for educational, research, and - * not for profit purposes provided that this copyright and statement are - * included in all such copies. - */ - - -#include "angband.h" - -#include "quark.h" -#include "hooks.h" - -/* - * Describe class powers of Mindcrafters - * - * 'p' points to a 80 byte long buffer - */ -void mindcraft_info(char *p, int power) -{ - int plev = get_skill(SKILL_MINDCRAFT); - - - /* Clear buffer */ - strcpy(p, ""); - - /* Fill the buffer with requested power description */ - switch (power) - { - case 0: - strnfmt(p, 80, " rad %d", DEFAULT_RADIUS); - break; - case 1: - strnfmt(p, 80, " dam %dd%d", 3 + ((plev - 1) / 4), 3 + plev / 15); - break; - case 2: - strnfmt(p, 80, " range %d", (plev < 25 ? 10 : plev + 2 + p_ptr->to_s * 3)); - break; - case 3: - strnfmt(p, 80, " range %d", plev * 5); - break; - case 4: - strnfmt(p, 80, " power %d", plev * (plev < 30 ? 1 : 2)); - break; - case 5: - if (plev > 20) - strnfmt(p, 80, " dam %dd8 rad %d", 8 + ((plev - 5) / 4), (plev - 20)/8 + 1); - else - strnfmt(p, 80, " dam %dd8", 8 + ((plev - 5) / 4)); - break; - case 6: - strnfmt(p, 80, " dur %d", plev); - break; - case 7: - break; - case 8: - if (plev < 25) - strnfmt(p, 80, " dam %d rad %d", (3 * plev) / 2, 2 + (plev / 10)); - else - strnfmt(p, 80, " dam %d", plev * ((plev - 5) / 10 + 1)); - break; - case 9: - strnfmt(p, 80, " dur 11-%d", 10 + plev + plev / 2); - break; - case 10: - strnfmt(p, 80, " dam %dd6 rad %d", plev / 2, 0 + (plev - 25) / 10); - break; - case 11: - strnfmt(p, 80, " dam %d rad %d", plev * (plev > 39 ? 4 : 3), 3 + plev / 10); - break; - } -} - - -/* - * Describe class powers of Mimics - * - * 'p' points to a 80 byte long buffer - */ -void mimic_info(char *p, int power) -{ - int plev = get_skill(SKILL_MIMICRY); - object_type *o_ptr = &p_ptr->inventory[INVEN_OUTER]; - - /* Clear the buffer */ - strcpy(p, ""); - - /* Fill the buffer with requested power description */ - switch (power) - { - case 0: - strnfmt(p, 80, " dur %d", k_info[o_ptr->k_idx].pval2 + get_skill_scale(SKILL_MIMICRY, 1000)); - break; - case 1: - strnfmt(p, 80, " dur %d+d20", 10 + plev); - break; - case 2: - strnfmt(p, 80, " dur 50+d%d", 50 + (2 * plev)); - break; - case 3: - strnfmt(p, 80, " dur 50+d%d", 50 + (2 * plev)); - break; - case 4: - strnfmt(p, 80, " dur 50+d%d", 50 + (2 * plev)); - break; - } -} - -/** - * Show magic powers that user can choose from - */ -static void display_magic_powers( - magic_power *powers, - int max_powers, - void (*power_info)(char *p, int power), - int plev, - int cast_stat, - int y, - int x) -{ - char psi_desc[80]; - magic_power spell; - int i; - int chance = 0; - int minfail = 0; - char comment[80]; - - /* Display a list of spells */ - prt("", 1, x); - prt("", y, x); - put_str("Name", y, x + 5); - put_str("Lv Mana Fail Info", y, x + 35); - - /* Dump the spells */ - for (i = 0; i < max_powers; i++) - { - /* Access the spell */ - spell = powers[i]; - if (spell.min_lev > plev) - { - break; - } - - chance = spell.fail; - /* Reduce failure rate by "effective" level adjustment */ - chance -= 3 * (plev - spell.min_lev); - - /* Reduce failure rate by INT/WIS adjustment */ - chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[cast_stat]] - 1); - - /* Not enough mana to cast */ - if (spell.mana_cost > p_ptr->csp) - { - chance += 5 * (spell.mana_cost - p_ptr->csp); - } - - /* Extract the minimum failure rate */ - minfail = adj_mag_fail[p_ptr->stat_ind[cast_stat]]; - - /* Failure rate */ - chance = clamp_failure_chance(chance, minfail); - - /* Get info */ - power_info(comment, i); - - /* Dump the spell --(-- */ - strnfmt(psi_desc, 80, " %c) %-30s%2d %4d %3d%%%s", - I2A(i), spell.name, - spell.min_lev, spell.mana_cost, chance, comment); - prt(psi_desc, y + i + 1, x); - } - - /* Clear the bottom line */ - prt("", y + i + 1, x); -} - -/* - * Allow user to choose a magic power. - * - * If a valid spell is chosen, saves it in '*sn' and returns TRUE - * If the user hits escape, returns FALSE, and set '*sn' to -1 - * If there are no legal choices, returns FALSE, and sets '*sn' to -2 - * - * The "prompt" should be "cast", "recite", or "study" - * The "known" should be TRUE for cast/pray, FALSE for study - * - * nb: This function has a (trivial) display bug which will be obvious - * when you run it. It's probably easy to fix but I haven't tried, - * sorry. - */ -static bool_ get_magic_power(int *sn, magic_power *powers, int max_powers, - void (*power_info)(char *p, int power), int plev, int cast_stat) -{ - int i; - - int num = 0; - - int y = 2; - - int x = 18; - - int info; - - char choice; - - char out_val[160]; - - cptr p = "power"; - - magic_power spell; - - bool_ flag; - - - /* Assume cancelled */ - *sn = ( -1); - - /* Get the spell, if available */ - if (repeat_pull(sn)) - { - /* Verify the spell */ - if (powers[*sn].min_lev <= plev) - { - /* Success */ - return (TRUE); - } - } - - /* Nothing chosen yet */ - flag = FALSE; - - /* Count number of powers that satisfies minimum plev requirement */ - for (i = 0; i < max_powers; i++) - { - if (powers[i].min_lev <= plev) - { - num++; - } - } - - /* Build a prompt (accept all spells) */ - strnfmt(out_val, 78, "(%^ss %c-%c, ESC=exit, %c-%c=Info) Use which %s? ", - p, I2A(0), I2A(num - 1), toupper(I2A(0)), toupper(I2A(num - 1)), p); - - /* Save the screen */ - character_icky = TRUE; - Term_save(); - - /* Show the list */ - display_magic_powers(powers, max_powers, power_info, plev, cast_stat, y, x); - - /* Get a spell from the user */ - while (!flag && get_com(out_val, &choice)) - { - /* Note verify */ - info = (isupper(choice)); - - /* Lowercase */ - if (info) choice = tolower(choice); - - /* Extract request */ - i = (islower(choice) ? A2I(choice) : -1); - - /* Totally Illegal */ - if ((i < 0) || (i >= num)) - { - bell(); - continue; - } - - /* Save the spell index */ - spell = powers[i]; - - /* Provides info */ - if (info) - { - c_prt(TERM_L_BLUE, spell.desc, 1, 0); - - /* Restore the screen */ - inkey(); - Term_load(); - character_icky = FALSE; - - /* Redisplay choices */ - display_magic_powers(powers, max_powers, power_info, plev, cast_stat, y, x); - continue; - } - - /* Stop the loop */ - flag = TRUE; - } - - /* Restore the screen */ - Term_load(); - character_icky = FALSE; - - /* Abort if needed */ - if (!flag) return (FALSE); - - /* Save the choice */ - (*sn) = i; - - - repeat_push(*sn); - - /* Success */ - return (TRUE); -} - - -/* - * do_cmd_cast calls this function if the player's class - * is 'mindcrafter'. - */ -void do_cmd_mindcraft(void) -{ - int n = 0, b = 0; - - int chance; - - int dir; - - int minfail = 0; - - int plev = get_skill(SKILL_MINDCRAFT); - - magic_power spell; - - - /* No magic */ - if (p_ptr->antimagic) - { - msg_print("Your anti-magic field disrupts any magic attempts."); - return; - } - - /* No magic */ - if (p_ptr->anti_magic) - { - msg_print("Your anti-magic shell disrupts any magic attempts."); - return; - } - - - /* not if confused */ - if (p_ptr->confused) - { - msg_print("You are too confused!"); - return; - } - - /* get power */ - if (!get_magic_power(&n, mindcraft_powers, MAX_MINDCRAFT_POWERS, - mindcraft_info, plev, A_WIS)) return; - - spell = mindcraft_powers[n]; - - /* Verify "dangerous" spells */ - if (spell.mana_cost > p_ptr->csp) - { - /* Warning */ - msg_print("You do not have enough mana to use this power."); - - /* Verify */ - if (!get_check("Attempt it anyway? ")) return; - } - - /* Spell failure chance */ - chance = spell.fail; - - /* Reduce failure rate by "effective" level adjustment */ - chance -= 3 * (get_skill(SKILL_MINDCRAFT) - spell.min_lev); - - /* Reduce failure rate by INT/WIS adjustment */ - chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[A_WIS]] - 1); - - /* Not enough mana to cast */ - if (spell.mana_cost > p_ptr->csp) - { - chance += 5 * (spell.mana_cost - p_ptr->csp); - } - - /* Extract the minimum failure rate */ - minfail = adj_mag_fail[p_ptr->stat_ind[A_WIS]]; - - /* Failure rate */ - chance = clamp_failure_chance(chance, minfail); - - /* Failed spell */ - if (rand_int(100) < chance) - { - if (flush_failure) flush(); - - msg_format("You failed to concentrate hard enough!"); - - sound(SOUND_FAIL); - - if (randint(100) < (chance / 2)) - { - /* Backfire */ - b = randint(100); - if (b < 5) - { - msg_print("Oh, no! Your mind has gone blank!"); - lose_all_info(); - } - else if (b < 15) - { - msg_print("Weird visions seem to dance before your eyes..."); - set_image(p_ptr->image + 5 + randint(10)); - } - else if (b < 45) - { - msg_print("Your brain is addled!"); - set_confused(p_ptr->confused + randint(8)); - } - else if (b < 90) - { - set_stun(p_ptr->stun + randint(8)); - } - else - { - /* Mana storm */ - msg_print("Your mind unleashes its power in an uncontrollable storm!"); - project(1, 2 + plev / 10, p_ptr->py, p_ptr->px, plev * 2, - GF_MANA, PROJECT_JUMP | PROJECT_KILL | PROJECT_GRID | PROJECT_ITEM); - p_ptr->csp = MAX(0, p_ptr->csp - plev * MAX(1, plev / 10)); - } - } - } - - /* Successful spells */ - else - { - sound(SOUND_ZAP); - - /* spell code */ - switch (n) - { - /* Precog */ - case 0: - { - /* Magic mapping */ - if (plev > 44) - { - wiz_lite(); - } - else if (plev > 19) - { - map_area(); - } - - /* Detection */ - if (plev < 30) - { - b = detect_monsters_normal(DEFAULT_RADIUS); - if (plev > 14) b |= detect_monsters_invis(DEFAULT_RADIUS); - if (plev > 4) b |= detect_traps(DEFAULT_RADIUS); - } - else - { - b = detect_all(DEFAULT_RADIUS); - } - - /* Telepathy */ - if (plev > 24) - { - set_tim_esp(p_ptr->tim_esp + plev); - - /* If plvl >= 40, we should have permanent ESP */ - } - - if (!b) msg_print("You feel safe."); - - break; - } - - /* Mindblast */ - case 1: - { - if (!get_aim_dir(&dir)) return; - - if (randint(100) < plev * 2) - { - fire_beam(GF_PSI, dir, damroll(3 + ((plev - 1) / 4), (3 + plev / 15))); - } - else - { - fire_ball(GF_PSI, dir, damroll(3 + ((plev - 1) / 4), (3 + plev / 15)), 0); - } - - break; - } - - /* Minor displace */ - case 2: - { - if (plev < 25) - { - teleport_player(10); - } - else - { - int ii, ij; - - if (dungeon_flags2 & DF2_NO_TELEPORT) - { - msg_print("Not on special levels!"); - break; - } - - msg_print("You open a Void Jumpgate. Choose a destination."); - - if (!tgt_pt(&ii, &ij)) return; - p_ptr->energy -= 60 - plev; - - if (!cave_empty_bold(ij, ii) || - (cave[ij][ii].info & CAVE_ICKY) || - (distance(ij, ii, p_ptr->py, p_ptr->px) > plev + 2 + (p_ptr->to_s*3)) || - (rand_int(plev * plev / 2) == 0)) - { - msg_print("You fail to exit the void correctly!"); - p_ptr->energy -= 100; - get_pos_player(10 + p_ptr->to_s / 2, &ij, &ii); - } - - cave_set_feat(p_ptr->py, p_ptr->px, FEAT_BETWEEN); - cave_set_feat(ij, ii, FEAT_BETWEEN); - cave[p_ptr->py][p_ptr->px].special = ii + (ij << 8); - cave[ij][ii].special = p_ptr->px + (p_ptr->py << 8); - } - - break; - } - - /* Major displace */ - case 3: - { - if (plev > 29) banish_monsters(plev); - teleport_player(plev * 5); - - break; - } - - /* Domination */ - case 4: - { - if (plev < 30) - { - if (!get_aim_dir(&dir)) return; - fire_ball(GF_DOMINATION, dir, plev, 0); - } - else - { - charm_monsters(plev * 2); - } - - break; - } - - /* Fist of Force --- not 'true' TK */ - case 5: - { - if (!get_aim_dir(&dir)) return; - fire_ball(GF_SOUND, dir, damroll(8 + ((plev - 5) / 4), 8), - (plev > 20 ? (plev - 20) / 8 + 1 : 0)); - - break; - } - - /* Character Armour */ - case 6: - { - set_shield(p_ptr->shield + plev, plev, 0, 0, 0); - if (plev > 14) set_oppose_acid(p_ptr->oppose_acid + plev); - if (plev > 19) set_oppose_fire(p_ptr->oppose_fire + plev); - if (plev > 24) set_oppose_cold(p_ptr->oppose_cold + plev); - if (plev > 29) set_oppose_elec(p_ptr->oppose_elec + plev); - if (plev > 34) set_oppose_pois(p_ptr->oppose_pois + plev); - - break; - } - - /* Psychometry */ - case 7: - { - ident_spell(); - break; - } - - /* Mindwave */ - case 8: - { - msg_print("Mind-warping forces emanate from your brain!"); - if (plev < 25) - { - project(0, 2 + plev / 10, p_ptr->py, p_ptr->px, - (plev*3) / 2, GF_PSI, PROJECT_KILL); - } - else - { - (void)mindblast_monsters(plev * ((plev - 5) / 10 + 1)); - } - - break; - } - - /* Adrenaline */ - case 9: - { - set_afraid(0); - set_stun(0); - hp_player(plev); - - b = 10 + randint((plev * 3) / 2); - - if (plev < 35) - { - set_hero(p_ptr->hero + b); - } - else - { - set_shero(p_ptr->shero + b); - } - - if (!p_ptr->fast) - { - /* Haste */ - (void)set_fast(b, plev / 5); - } - else - { - (void)set_fast(p_ptr->fast + b, plev / 5); - } - - break; - } - - /* Psychic Drain */ - case 10: - { - if (!get_aim_dir(&dir)) return; - - b = damroll(plev / 2, 6); - - if (fire_ball(GF_PSI_DRAIN, dir, b, 0 + (plev - 25) / 10)) - { - p_ptr->energy -= randint(150); - } - - break; - } - - /* Telekinesis */ - case 11: - { - msg_print("A wave of pure physical force radiates out from your body!"); - project(0, 3 + plev / 10, p_ptr->py, p_ptr->px, - plev * (plev > 39 ? 4 : 3), GF_TELEKINESIS, - PROJECT_KILL | PROJECT_ITEM | PROJECT_GRID); - - break; - } - - default: - { - msg_print("Zap?"); - - break; - } - } - } - - /* Take a turn */ - energy_use = 100; - - /* Sufficient mana */ - if (spell.mana_cost <= p_ptr->csp) - { - /* Use some mana */ - p_ptr->csp -= spell.mana_cost; - } - - /* Over-exert the player */ - else - { - int oops = spell.mana_cost - p_ptr->csp; - - /* No mana left */ - p_ptr->csp = 0; - p_ptr->csp_frac = 0; - - /* Message */ - msg_print("You faint from the effort!"); - - /* Hack -- Bypass free action */ - (void)set_paralyzed(randint(5 * oops + 1)); - - /* Damage WIS (possibly permanently) */ - if (rand_int(100) < 50) - { - bool_ perm = (rand_int(100) < 25); - - /* Message */ - msg_print("You have damaged your mind!"); - - /* Reduce constitution */ - (void)dec_stat(A_WIS, 15 + randint(10), perm); - } - } - - /* Redraw mana */ - p_ptr->redraw |= (PR_MANA); - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); -} - - -static int get_mimic_chance(int mimic) -{ - s32b chance; - - chance = get_mimic_level(mimic); - chance *= 3; - - chance -= get_skill_scale(SKILL_MIMICRY, 150); - chance -= 3 * adj_mag_stat[p_ptr->stat_ind[A_DEX]]; - - /* Return the chance */ - return clamp_failure_chance(chance, 2); -} - - -void do_cmd_mimic_lore() -{ - int fail; - - object_type *o_ptr; - - - /* Player has to be able to see */ - if (p_ptr->blind || no_lite()) - { - msg_print("You cannot see!"); - return; - } - - /* No transformations when confused */ - if (p_ptr->confused) - { - msg_print("You are too confused!"); - return; - } - - - /* Already in a mimic form -- Allow cancelling */ - if (p_ptr->mimic_form) - { - msg_print("You morph back to your natural form!"); - - set_mimic(0, 0, 0); - } - - /* Not in mimic forms -- Allow transformations */ - else - { - o_ptr = &p_ptr->inventory[INVEN_OUTER]; - - if ((o_ptr->tval != TV_CLOAK) || (o_ptr->sval != SV_MIMIC_CLOAK)) - { - msg_print("You are not wearing any cloaks of mimicry."); - return; - } - - /* Calculate failure rate */ - fail = get_mimic_chance(o_ptr->pval2); - - if (fail > 75) - { - msg_print("You feel uneasy with this shape-change."); - - if (!get_check("Try it anyway? ")) return; - } - - /* Fumble */ - if (randint(100) < fail) - { - msg_print("Your shape-change goes horribly wrong!"); - - if (randint(100) < p_ptr->skill_sav) - { - msg_print("You manage to wrest your body back under control."); - return; - } - - set_mimic(30, resolve_mimic_name("Abomination"), get_skill(SKILL_MIMICRY)); - } - - /* Success */ - else - { - set_mimic(k_info[o_ptr->k_idx].pval2 + get_skill_scale(SKILL_MIMICRY, 1000), o_ptr->pval2, get_skill(SKILL_MIMICRY)); - } - } - - - /* Redraw title */ - p_ptr->redraw |= (PR_TITLE); - - /* Recalculate bonuses */ - p_ptr->update |= (PU_BONUS); -} - -static bool_ mimic_forbid_travel(const char *fmt) -{ - u32b value = p_ptr->mimic_extra >> 16; - u32b att = p_ptr->mimic_extra & 0xFFFF; - - if(value > 0 && (att & CLASS_ARMS || att & CLASS_LEGS)) - { - msg_print("You had best not travel with your extra limbs."); - return TRUE; - } - - return FALSE; -} - -/* - * do_cmd_cast calls this function if the player's class - * is 'mimic'. - */ -void do_cmd_mimic(void) -{ - int n = 0, b = 0; - - int fail; - - int minfail = 0; - - int plev = get_skill(SKILL_MIMICRY); - - magic_power spell; - - static bool_ added_hooks = FALSE; - if(!added_hooks) - { - add_hook(HOOK_FORBID_TRAVEL, mimic_forbid_travel, "mimic_forbid_travel"); - added_hooks = TRUE; - } - - /* No magic */ - if (p_ptr->antimagic) - { - msg_print("Your anti-magic field disrupts any magic attempts."); - return; - } - - /* No magic */ - if (p_ptr->anti_magic) - { - msg_print("Your anti-magic shell disrupts any magic attempts."); - return; - } - - - /* not if confused */ - if (p_ptr->confused) - { - msg_print("You are too confused!"); - return; - } - - /* get power */ - if (!get_magic_power(&n, mimic_powers, MAX_MIMIC_POWERS, mimic_info, - plev, A_DEX)) return; - - spell = mimic_powers[n]; - - /* Verify "dangerous" spells */ - if (spell.mana_cost > p_ptr->csp) - { - /* Warning */ - msg_print("You do not have enough mana to use this power."); - - /* Verify */ - if (!get_check("Attempt it anyway? ")) return; - } - - /* Spell failure chance */ - fail = spell.fail; - - /* Reduce failure rate by "effective" level adjustment */ - fail -= 3 * (plev - spell.min_lev); - - /* Reduce failure rate by INT/WIS adjustment */ - fail -= 3 * (adj_mag_stat[p_ptr->stat_ind[A_DEX]] - 1); - - /* Not enough mana to cast */ - if (spell.mana_cost > p_ptr->csp) - { - fail += 5 * (spell.mana_cost - p_ptr->csp); - } - - /* Extract the minimum failure rate */ - minfail = adj_mag_fail[p_ptr->stat_ind[A_DEX]]; - - /* Minimum failure rate */ - if (fail < minfail) fail = minfail; - - /* Stunning makes spells harder */ - if (p_ptr->stun > 50) fail += 25; - else if (p_ptr->stun) fail += 15; - - /* Always a 5 percent chance of working */ - if (fail > 95) fail = 95; - - /* Failed spell */ - if (rand_int(100) < fail) - { - if (flush_failure) flush(); - - msg_format("You failed to concentrate hard enough!"); - - sound(SOUND_FAIL); - - if (randint(100) < (fail / 2)) - { - /* Backfire */ - b = randint(100); - - if (b < 5) - { - msg_print("Oh, no! Your mind has gone blank!"); - lose_all_info(); - } - else if (b < 15) - { - msg_print("Weird visions seem to dance before your eyes..."); - set_image(p_ptr->image + 5 + randint(10)); - } - else if (b < 45) - { - msg_print("Your brain is addled!"); - set_confused(p_ptr->confused + randint(8)); - } - else - { - set_stun(p_ptr->stun + randint(8)); - } - } - } - - /* Successful spells */ - else - { - sound(SOUND_ZAP); - - /* spell code */ - switch (n) - { - /* Mimic */ - case 0: - { - do_cmd_mimic_lore(); - - break; - } - - /* Invisibility */ - case 1: - { - int ii = 10 + plev + randint(20) + p_ptr->to_s; - - set_invis(p_ptr->tim_invisible + ii, 50); - set_tim_invis(p_ptr->tim_invisible + ii); - - break; - } - - /* Legs Mimicry */ - case 2: - { - /* Extract the value and the flags */ - u32b value = p_ptr->mimic_extra >> 16; - u32b att = p_ptr->mimic_extra & 0xFFFF; - - /* Clear useless things */ - att &= ~(CLASS_ARMS); - att &= ~(CLASS_WALL); - - if (att & CLASS_LEGS) - { - value += 50 + randint(50 + (2 * plev)); - } - else - { - msg_print("You mimic a new pair of legs."); - - value = 50 + randint(50 + (2 * plev)); - att |= (CLASS_LEGS); - } - - if (value > 10000) value = 10000; - - p_ptr->mimic_extra = att + (value << 16); - p_ptr->update |= (PU_BODY); - - break; - } - - /* Wall Mimicry */ - case 3: - { - /* Extract the value and the flags */ - u32b value = p_ptr->mimic_extra >> 16; - u32b att = p_ptr->mimic_extra & 0xFFFF; - - /* Clear useless things */ - att &= ~(CLASS_ARMS); - att &= ~(CLASS_LEGS); - - if (att & CLASS_WALL) - { - value += 50 + randint(50 + (2 * plev)); - } - else - { - msg_print("You grow an affinity for walls."); - - value = 50 + randint(50 + (2 * plev)); - att |= (CLASS_WALL); - } - - if (value > 10000) value = 10000; - - p_ptr->mimic_extra = att + (value << 16); - p_ptr->update |= (PU_BODY); - - break; - } - - case 4: /* Arms Mimicry */ - { - /* Extract the value and the flags */ - u32b value = p_ptr->mimic_extra >> 16; - u32b att = p_ptr->mimic_extra & 0xFFFF; - - /* Clear useless things */ - att &= ~(CLASS_LEGS); - att &= ~(CLASS_WALL); - - if (att & CLASS_ARMS) - { - value += 50 + randint(50 + (2 * plev)); - } - else - { - msg_print("You mimic a new pair of arms."); - - value = 50 + randint(50 + (2 * plev)); - att |= (CLASS_ARMS); - } - - if (value > 10000) value = 10000; - - p_ptr->mimic_extra = att + (value << 16); - p_ptr->update |= (PU_BODY); - - break; - } - - default: - { - msg_print("Zap?"); - - break; - } - } - } - - - /* Take a turn */ - energy_use = 100; - - /* Sufficient mana */ - if (spell.mana_cost <= p_ptr->csp) - { - /* Use some mana */ - p_ptr->csp -= spell.mana_cost; - } - - /* Over-exert the player */ - else - { - int oops = spell.mana_cost - p_ptr->csp; - - /* No mana left */ - p_ptr->csp = 0; - p_ptr->csp_frac = 0; - - /* Message */ - msg_print("You faint from the effort!"); - - /* Hack -- Bypass free action */ - (void)set_paralyzed(randint(5 * oops + 1)); - - /* Damage WIS (possibly permanently) */ - if (rand_int(100) < 50) - { - bool_ perm = (rand_int(100) < 25); - - /* Message */ - msg_print("You have damaged your mind!"); - - /* Reduce constitution */ - (void)dec_stat(A_DEX, 15 + randint(10), perm); - } - } - - /* Redraw mana */ - p_ptr->redraw |= (PR_MANA); - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); -} - - -/* - * do_cmd_cast calls this function if the player's class - * is 'beastmaster'. - */ -void do_cmd_beastmaster(void) -{ - int plev = p_ptr->lev, i, num; - - monster_type *m_ptr; - - - /* Process the monsters (backwards) */ - num = 0; - for (i = m_max - 1; i >= 1; i--) - { - /* Access the monster */ - m_ptr = &m_list[i]; - - if (m_ptr->status == MSTATUS_PET) - { - num++; - } - } - - if (num < plev * 2) - { - /* XXX XXX */ - if (rand_int(80-(plev) - p_ptr->stat_use[5]-p_ptr->to_s) < 20) - { - summon_specific_friendly(p_ptr->py, p_ptr->px, plev, rand_int(plev / 2), FALSE); - } - } - else msg_print("You can't summon more pets"); - - /* Take a turn */ - if (is_magestaff()) energy_use = 80; - else energy_use = 100; - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); -} - - -/* - * Set of variables and functions to create an artifact - */ - - -/* LOG2 is a constant (compile-time) method of converting a single - * set bit into a number. Works well, but for variable (runtime) - * expressions, use a loop instead.. much smaller code*/ -#define LOG2(x) ( (x) & 0xFFFF? BLOG16(x) : BLOG16((x)>>16) + 16 ) -#define BLOG16(x) ( (x) & 0xFF ? BLOG8(x) : BLOG8 ((x)>>8 ) + 8 ) -#define BLOG8(x) ( (x) & 0xF ? BLOG4(x) : BLOG4 ((x)>>4 ) + 4 ) -#define BLOG4(x) ( (x) & 0x3 ? BLOG2(x) : BLOG2 ((x)>>2 ) + 2 ) -#define BLOG2(x) ( (x) & 0x1 ? 0 : 1 ) - -int flags_select[32*5]; -int activation_select; - -/* Return true if the player is wielding the philosopher's stone - */ -bool_ alchemist_has_stone(void) -{ - if (p_ptr->inventory[INVEN_LITE].name1 == 209) - return TRUE; - else - return FALSE; -} - -/* - Display a group of flags from a_select flags, and return - the number of flags displayed (even invisible ones) - */ -int show_flags(byte group, int pval) -{ - int i, x, color = TERM_WHITE; - int items = 0; - - char ttt[80]; - - Term_clear(); - - group++; /* Adjust - no zero group */ - - for ( i = 0 ; a_select_flags[i].group ; i++) - { - if (a_select_flags[i].group != group) - continue; - - if (a_select_flags[i].xp == 0) - break; - else - { - sprintf(ttt, "%c) %s", - (items < 26) ? I2A(items) : ('0' + items - 26), - al_name + a_select_flags[i].desc); - if ( wizard || alchemist_has_stone()) - sprintf(ttt, "%c) %s (exp " FMTu32b ")", - (items < 26) ? I2A(items) : ('0' + items - 26), - al_name + a_select_flags[i].desc, - a_select_flags[i].xp); - - /* Note: Somebody is VERY clever, and it wasn't me. Text printed as - * TERM_DARK is actually printed as TERM_BLUE *SPACES* to prevent the - * player from using a 'cut-and-paste' enabled terminal to see - * what he shouldn't. Thus, simply setting the color to TERM_DARK - * will entirely prevent the unspoiled player from knowing that it's - * even possible. */ - - switch (flags_select[i]) - { - case 1: - color = TERM_YELLOW; - break; /* Flag was set by the player (just now)*/ - case 0: - color = TERM_WHITE; - break; /* This flag can be set, player is 'aware' of it*/ - case - 1: - color = TERM_L_GREEN; - break; /* Flag is already set*/ - case - 2: - color = TERM_DARK; - break; /* Invisible option */ - case - 3: - color = TERM_RED; - break; /* Flag is set, but player isn't 'aware' of it */ - case - 4: - color = TERM_L_DARK; - break; /* Flag is not set, player is 'aware', but it's beyond thier skill */ - default: - color = TERM_DARK; - break; /* Just in Case*/ - } - } - /* For alchemists who have the stone, at least show all the flags... */ - if ((alchemist_has_stone() || wizard) && color == TERM_DARK) - color = TERM_BLUE; - - if (items < 16) x = 5; - else x = 45; - c_prt(color, ttt, ((items < 16) ? items : items - 16) + 5, x); - items++; - - } - return items; -} - -void show_levels(void) -{ - Term_clear(); - c_prt(TERM_WHITE, "[a] Stats, sustains, luck, speed, vision, etc. ", 3, 10); - c_prt(TERM_WHITE, "[b] Misc. (Auras, light, see invis, etc) ", 4, 10); - c_prt(TERM_WHITE, "[c] Weapon Branding ", 5, 10); - c_prt(TERM_WHITE, "[d] Resistances and Immunities ", 6, 10); - c_prt(TERM_WHITE, "[e] ESP and Curses ", 7, 10); - c_prt(TERM_WHITE, "[f] Activation ", 8, 10); - c_prt(TERM_DARK , "[g] Abilities Gained ", 9, 10); - c_prt(TERM_WHITE, "[h] Display Required Essences and items ", 10, 10); - c_prt(TERM_WHITE, "[i] Done! Finalize and commit changes. ", 11, 10); - /*No need to return anything - if the valid selections change, it'll be a code level change.*/ -} - -s32b get_flags_exp(int pval, int oldpval) -{ - int i; - s32b exp = 0; - - for (i = 0 ; a_select_flags[i].group ; i++ ) - { - if (a_select_flags[i].xp == 0) - break; - else - { - if ( a_select_flags[i].group <= 5 && flags_select[i] ) - { - s32b xp = a_select_flags[i].xp; - int factor = 1, oldfactor = 0; - - /* don't even look at flags which the user can't set - * because they also can't change the pval when a pval- - * dependant flag is set, flags which they can't set - * cannot effect the exp in any way, whether their set or not - */ - if ( flags_select[i] < -1 ) - continue; - if ( flags_select[i] == -1 ) - oldfactor = 1; - - if (a_select_flags[i].pval) - { - /* (1/4)x^2 + x - * I wanted something smaller than x^2 or x^x - * this is because although a ring of speed +10 is - * more than 10 times better than a ring of speed +1, - * I don't think it's 100 times better. More like 30. - * this function yields: - * 1=1 * 2=3 * 3=5 * 4=8 * 5=11 * 6=15 * 7=21 - * 8=24 * 9=29 * 10=35 * 11=41 * 12=48 * 13=55 - * 14=63 * 15=71 * 20=120 * 25=181 * 30=255 - * which I think is acceptable. - * briefly, to get a +30 speed ring, it would be: - * 255*50000 or over 12 million experience - * points. For reference, a level 50 human requires - * 5 million xp. I'm sure it's doable, but it'd be - * *HARD* - * a speed+10 artifact would require 1.75 million. - * much more doable, but not too easily. - */ - factor = (pval * pval / 4 + pval); - if ( flags_select[i] == -1 ) - { - oldfactor = oldpval * oldpval / 4 + oldpval; - } - } - exp += xp * factor - xp * oldfactor; - } - if ( a_select_flags[i].group == 88 && a_select_flags[i].flag == -activation_select ) - { - exp += a_select_flags[i].xp; - } - } - } - if ( alchemist_has_stone() ) exp = exp / 4; - return exp; -} - -/* returns the 'real quantity' of items needed to empower - * a particular flag to a particular pval. - * Note that this routine returns zero for any flag that - * doesn't require some sort of action. - */ -int calc_rqty(int i, int pval, int oldpval) -{ - /* return 0 if flag is greater than size of flags_select && ! activation */ - if ( a_select_flags[i].group > 5 ) - { - if ( activation_select == a_select_flags[i].flag) - return 1; - else - return 0; - } - - /* return 0 if the flag wasn't set */ - if ( flags_select[i] < -1 || flags_select[i] == 0 ) - return 0; - - /* Return change in pval if the flag was already set */ - if ( flags_select[i] == -1 && a_select_flags[i].pval) - return pval - oldpval; - - /* Return pval if the flag will be set this time */ - else if ( a_select_flags[i].pval ) - return pval; - - /* Return 0 if the flag is unknown */ - else if ( flags_select[i] == -1 ) - return 0; - return 1; -} - -/* Handle the various items that creating artifacts requires. - * Mode = 0 to print a description, - * 1 to use up the items - * -1 to check to see if the items exist - * Note that this function is called ONLY from the - * other artifact item helper function. - */ - - -int check_artifact_items(int pval, int oldpval, int mode) -{ - int i, j, k, row = 1 , col = 15, rqty, orqty, trqty; - bool_ good = TRUE; - int temporary = -1; - char ch; - - /* For temporary items, waive the item requirements, - * except for the corpse... */ - for ( j = 0 ; a_select_flags[j].group ; j++) - if (a_select_flags[j].flag == 4*32 && flags_select[j] == 1 ) - temporary = j; - /* Check for enough items */ - for (i = 0; a_select_flags[i].group ; i++) - { - /* For temporary items, ignore - everything except the one item - */ - if (temporary != -1 && i != temporary) - continue; - - /* Calc quantity is done per flag, because - some have a pval, some don't, some where already - set at pval=2, etc - */ - rqty = orqty = calc_rqty(i, pval, oldpval); - - /* If no item is associated with this flag, - or this flag wasn't set or didn't change */ - if ( !a_select_flags[i].rtval || !rqty) - continue; - - for ( k = 0 ; k < INVEN_WIELD ; k++ ) - { - object_type *o_ptr = &p_ptr->inventory[k]; - - /* Note here that an rsval of -1 (which is read is 0xff - for a byte..) matches anything. */ - if (o_ptr->tval == a_select_flags[i].rtval - && (o_ptr->sval == a_select_flags[i].rsval - || a_select_flags[i].rsval == (byte) - 1 ) ) - { - /* Corpse validation is COMPLICATED! - * But at least we don't have to do this twice. - */ - if ( a_select_flags[i].rtval == TV_CORPSE ) - { - bool_ itemgood = TRUE; - - /*Specified race not this one */ - if ( o_ptr->pval2 != a_select_flags[i].rpval && a_select_flags[i].rpval) - continue; - - /* Race flag (any monster who...)*/ - for ( j = 0 ; !a_select_flags[i].rpval && a_select_flags[i].rflag[j] && j < 6 && itemgood ; j++) - { - int flag = a_select_flags[i].rflag[j] / 32; - u32b mask = 1 << (a_select_flags[i].rflag[j] % 32); - - switch (flag) - { - case 0: - if ( !(r_info[o_ptr->pval2].flags1 & mask) ) itemgood = FALSE; - break; - case 1: - if ( !(r_info[o_ptr->pval2].flags2 & mask) ) itemgood = FALSE; - break; - case 2: - if ( !(r_info[o_ptr->pval2].flags3 & mask) ) itemgood = FALSE; - break; - case 3: - if ( !(r_info[o_ptr->pval2].flags4 & mask) ) itemgood = FALSE; - break; - case 4: - if ( !(r_info[o_ptr->pval2].flags5 & mask) ) itemgood = FALSE; - break; - case 5: - if ( !(r_info[o_ptr->pval2].flags6 & mask) ) itemgood = FALSE; - break; - case 6: - if ( !(r_info[o_ptr->pval2].flags7 & mask) ) itemgood = FALSE; - break; - case 7: - if ( !(r_info[o_ptr->pval2].flags8 & mask) ) itemgood = FALSE; - break; - case 8: - if ( !(r_info[o_ptr->pval2].flags9 & mask) ) itemgood = FALSE; - break; - default: - msg_print("This code should never be hit!"); - } - } - if ( ! itemgood ) - continue; - - } - /* Validate pval of good item */ - else if ( a_select_flags[i].rpval) - { - /* Must have matching signs */ - if ( (o_ptr->pval < 0) != (a_select_flags[i].rpval < 0)) - continue; - /* Must be greater than */ - if ( abs(o_ptr->pval) < abs(a_select_flags[i].rpval)) - continue; - } - - trqty = MIN(o_ptr->number, rqty); - rqty -= trqty; - - if ( mode == 1 ) - { - inc_stack_size_ex(k, -trqty, NO_OPTIMIZE, DESCRIBE); - } - }/* if p_ptr->inventory item is acceptable */ - - } /*end of looping through the p_ptr->inventory*/ - - if (rqty) - { - good = FALSE; - /* Oops, we didn't have enough of this object - when actually creating the artifact. - unset this flag - */ - if ( mode == 1 ) - { - flags_select[i] = -4; - } - /* we only return false for mode -1, - * for mode 0 we display stuff, and for - * mode 1 we want to continue destroying things - * even if the player is missing one small item, - * because there's no way to change things now. - * We may have already destroyed a unique corpse, - * or some other hard-to-find item. - */ - if ( mode == -1 ) - return FALSE; - } - - /* Display a description of the required object, if needed */ - /* Note that the tests for good items HAVE to be in a different - place, because otherwise we don't know how many the player - has, as opposed to how many they need. - */ - if ( mode == 0 ) - { - char *o_name = al_name + a_select_flags[i].item_desc; - if (orqty > 1 && a_select_flags[i].pval && a_select_flags[i].item_descp) - o_name = al_name + a_select_flags[i].item_descp; - - if ( rqty ) - { - if ( orqty > 1 ) - c_prt(TERM_RED, format(" you are missing %d of the %d %s", rqty, orqty, o_name), row++, col); - else if ( is_a_vowel(o_name[0])) - c_prt(TERM_RED, format(" you are missing an %s", o_name), row++, col); - else - c_prt(TERM_RED, format(" you are missing a %s", o_name), row++, col); - } - else - { - if ( orqty > 1 ) - c_prt(TERM_GREEN, format(" you have the %d %s", orqty, o_name), row++, col); - else if ( is_a_vowel(o_name[0])) - c_prt(TERM_GREEN, format(" you have an %s", o_name), row++, col); - else - c_prt(TERM_GREEN, format(" you have a %s", o_name), row++, col); - } - - if ( row > 21 ) - { - row = 1; - if (!good) - (void)get_com("You are missing some items:", &ch); - else - (void)get_com("You have these needed items on hand:", &ch); - } - - } - - } /* End of group associated with this a_select_flags entry */ - - if ( mode == 0 ) - { - while ( row < 22 ) - c_prt(TERM_GREEN, " ", row++, col); - if (!good) - (void)get_com("You are missing some items:", &ch); - else - (void)get_com("You have these needed items on hand:", &ch); - } - return good; -} - -/* Display a list of required essences, - * and/or use up the essences. */ -bool_ artifact_display_or_use(int pval, int oldpval, bool_ use) -{ - int essence[MAX_BATERIE_SVAL]; - int essenceh[MAX_BATERIE_SVAL]; - int al_idx, i, j, k; - bool_ enough; - - /* Temporary Items require only one item, and no essences. */ - for ( i = 0 ; a_select_flags[i].group ; i++) - if ( a_select_flags[i].flag == 32*4) - { - if ( use ) - return check_artifact_items(pval, oldpval, 1); - else - return check_artifact_items(pval, oldpval, 0); - } - - for ( i = 0 ; i < MAX_BATERIE_SVAL ; i++ ) - essence[i] = essenceh[i] = 0; - - /* Accumulate a list of required essences */ - for ( al_idx = 0; al_idx < max_al_idx ; al_idx++ ) - if ( alchemist_recipes[al_idx].tval == 0 ) - for ( i = 0 ; a_select_flags[i].group ; i++) - { - int rqty = calc_rqty(i, pval, oldpval); - - /* If the flag isn't being set, rqty will be zero */ - if ( !rqty) - continue; - - if ( alchemist_recipes[al_idx].sval == a_select_flags[i].flag ) - essence[alchemist_recipes[al_idx].sval_essence] += - alchemist_recipes[al_idx].qty * rqty; - } - - /* The essence array now contains a list of all essences - * that will be consumed in the creation of this artifact */ - - /* Check for existence of required quatities of essences. */ - for ( i = 0 ; i < INVEN_WIELD ; i++ ) - { - for ( j = 0 ; j < MAX_BATERIE_SVAL ; j++) - if ( p_ptr->inventory[i].tval == TV_BATERIE && p_ptr->inventory[i].sval == j + 1) - { - essenceh[j] += p_ptr->inventory[i].number; - } - } - - /* Check for enough essences */ - enough = TRUE; - for ( i = 0 ; i < MAX_BATERIE_SVAL ; i++) - if ( essenceh[i] < essence[i] ) - { - enough = FALSE; - break; - } - - /* Check for items */ - if ( enough ) - enough = check_artifact_items(pval, oldpval, -1); - - - /* Display recipe list if they don't have enough, or not enough exp */ - if (!enough || !use ) - { - int row = 1 , col = 15; - bool_ good = FALSE; - char ch; - - /* display of list of required essences */ - /* Note: there are only 12 or so essences, so this list - * will ALWAYS fit on the screen */ - for ( i = 0 ; i < MAX_BATERIE_SVAL ; i++) - if ( essence[i] ) - { - int missing = -MIN(essenceh[i] - essence[i], 0); - good = TRUE; - if ( missing ) - c_prt(TERM_RED, format("%d of the required %d essences of %s", - missing, essence[i], - k_name + k_info[lookup_kind(TV_BATERIE, i + 1)].name ), - row++, col); - else - c_prt(TERM_GREEN, format("you have the needed %d essences of %s", - essence[i], - k_name + k_info[lookup_kind(TV_BATERIE, i + 1)].name ), - row++, col); - } - - if (good) - { - /* blank the bottom row */ - c_prt(TERM_WHITE, " ", row++, col); - - /* and wait for a key */ - (void)get_com("You are currently missing:", &ch); - } - - /* Display a list of needed items as well */ - check_artifact_items(pval, oldpval, 0); - - return FALSE; - } - - /* If we get to this point in the code, then the player - * has the required essences and items in their p_ptr->inventory */ - - /* If they do have enough, and they have enough exp, consume them */ - for (i = 0 ; i < MAX_BATERIE_SVAL ; i++) - for ( k = 0 ; k < INVEN_WIELD && essence[i] > 0 ; k++) - if (p_ptr->inventory[k].tval == TV_BATERIE - && p_ptr->inventory[k].sval == i + 1 - && essence[i]) - { - int num = p_ptr->inventory[k].number; - - inc_stack_size_ex(k, MAX( -essence[i], -num), NO_OPTIMIZE, DESCRIBE); - - essence[i] -= MIN(num, essence[i]); - } - - /* Destroy the items needed */ - check_artifact_items(pval, oldpval, 1); - - return TRUE; -} - - -void display_activation_info(int num) -{ - object_type forge; - int i; - - - /* find the a_select_flags number of this activation type... */ - for ( i = 0 ; a_select_flags[i].group ; i++) - if (a_select_flags[i].group == 88 && a_select_flags[i].flag == -num ) - break; - - object_wipe(&forge); - forge.xtra2 = num; - /* Print out various information about this activation... */ - /* min level, experience, required items (and essences) - full description (from activation_aux) */ - if (wizard) - c_prt(TERM_WHITE, format(" number:%d ", num), 5, 5); - else - c_prt(TERM_WHITE, " ", 5, 5); - c_prt(TERM_WHITE, format(" Level:%d ", a_select_flags[i].level), 6, 5); - c_prt(TERM_WHITE, format(" Exp :%d ", a_select_flags[i].xp), 7, 5); - c_prt(TERM_WHITE, format(" Item :%s ", al_name + a_select_flags[i].item_desc), 8, 5); - c_prt(TERM_WHITE, " ", 9, 5); - c_prt(TERM_WHITE, format(" %s ", activation_aux(&forge, 0, 0)), 9, 5); - c_prt(TERM_WHITE, " ", 10, 5); - inkey(); -} - -void select_an_activation(void) -{ - int i, lev, wid, hgt, begin = 0, sel = 0; - u32b max; - cptr act_list[150]; /* currently, ~127 hardcoded activations */ - int act_ref[150]; - char c; - /* How do we want to do this? */ - /* Ideally, we let them select from a list, which includes all the activations that they've ecountered in any form. - Problems with this idea include mainly the lack of any (current) place to store which activations they've seen, and - that they'll not get credit for any seen before we start tracking it. - - So - list is everything. If they select one which they're to low-level for - or if the explicitly request it, we'll display info about this item. - We'll also get our descriptions from the activation_aux(ACT_CONSTANT) - function, because they are more complete, and include even lua-scripted ones. - msg_print("Since the code to actually let you select one isn't here"); - msg_print("You will automatically get the activation 'Dawn'"); - activation_select = ACT_DAWN; - */ - - /* Build a list of available activations at the player's level */ - lev = get_skill(SKILL_ALCHEMY); - for ( i = max = 0 ; max < (sizeof(act_list) / sizeof(cptr)) && a_select_flags[i].group ; i++) - if (a_select_flags[i].group == 88 && a_select_flags[i].level <= lev ) - { - act_ref[max] = -a_select_flags[i].flag; /* Activation number */ - act_list[max++] = al_name + a_select_flags[i].desc; /* Description */ - } - - /* Select from that list, using the util.c function display_list to display the scrolled list */ - /* Note: I think that there is only one other place that uses this function. Should be more! */ - while (1) - { - Term_clear(); - Term_get_size(&wid, &hgt); - - c_prt(TERM_WHITE, "Enter to select, ? for more information, 2 and 8 to scroll ", 0, 0); - display_list(1, 0, hgt - 2, wid - 2, "Select an Activation", act_list, max, begin, sel, TERM_L_GREEN); - - c = inkey(); - - if (c == ESCAPE) break; - else if (c == '8') - { - sel--; - if (sel < 0) - { - sel = max - 1; - begin = max - hgt; - if (begin < 0) begin = 0; - } - if (sel < begin) begin = sel; - } - else if (c == '2') - { - sel++; - if (sel >= (s32b)max) - { - sel = 0; - begin = 0; - } - if (sel >= begin + hgt - 1) begin++; - } - else if (c == '?') - { - display_activation_info(act_ref[sel]); - } - else if (c == '\r') - { - display_activation_info(act_ref[sel]); - activation_select = act_ref[sel]; - return; - } - } - activation_select = 0; -} - - -/* Consume 'num' magic essences and return true. - * If there aren't enough essences, return false */ - -bool_ magic_essence(int num) -{ - int i; - int j = 0; - - for (i = 0; i < INVEN_WIELD; i++) - { - object_type *o_ptr = &p_ptr->inventory[i]; - - /* Count the magic essences */ - if (o_ptr->k_idx && (o_ptr->tval == TV_BATERIE) && (o_ptr->sval == SV_BATERIE_MAGIC)) j += o_ptr->number; - } - - /* Abort if not enough essences. */ - if (j < num) return FALSE; - - /* Consume them */ - i = 0; - j = num; - while (i < INVEN_WIELD) - { - object_type *o_ptr = &p_ptr->inventory[i]; - - if (o_ptr->k_idx && (o_ptr->tval == TV_BATERIE) && (o_ptr->sval == SV_BATERIE_MAGIC)) - { - /* This can lead to invalid object pointer for objects - * that come after the magic essences. Therefore, every - * artifactable object should come before the essences. - */ - j -= o_ptr->number; - inc_stack_size(i, -num); - num = j; - if (num <= 0) break; - /* Stay on this slot; do not increment i. */ - } - else - { - /* Move on to the next slot. */ - i++; - } - } - - /* Sanity check. */ - if (num > 0) - { - msg_format("ERROR: Couldn't destroy %d essences!", num); - return FALSE; - } - - return TRUE; -} - - -void do_cmd_create_artifact(object_type *q_ptr) -{ - int max, i = 0, j, cur_set = 0, abord = FALSE, done = FALSE; - int skill; - s32b exp = 0; - - char out_val[160]; - char choice = 0; - bool_ lockpval = FALSE; - int pval; - int oldpval; - energy_use = 100; - - pval = q_ptr->pval; - oldpval = pval; - skill = get_skill(SKILL_ALCHEMY); - - if ( !pval ) - pval = 1; - /* No activation added on this round */ - activation_select = 0; - - /* Save the current flags */ - for (i = 0 ; a_select_flags[i].group ; i++) - { - if ( a_select_flags[i].flag < 0 || a_select_flags[i].group > 5) - continue; - - flags_select[i] = 0; - - switch (a_select_flags[i].flag / 32) - { - case 0: - if (q_ptr->art_flags1 & 1 << (a_select_flags[i].flag % 32)) flags_select[i] = -1; - break; - case 1: - if (q_ptr->art_flags2 & 1 << (a_select_flags[i].flag % 32)) flags_select[i] = -1; - break; - case 2: - if (q_ptr->art_flags3 & 1 << (a_select_flags[i].flag % 32)) flags_select[i] = -1; - break; - case 3: - if (q_ptr->art_flags4 & 1 << (a_select_flags[i].flag % 32)) flags_select[i] = -1; - break; - case 4: - if (q_ptr->art_flags5 & 1 << (a_select_flags[i].flag % 32)) flags_select[i] = -1; - break; - case 5: - if (q_ptr->art_esp & 1 << (a_select_flags[i].flag % 32)) flags_select[i] = -1; - break; - default: - /*This will not be hit, inspite of activations, because of the <= 5 above...*/ - break; - } - /* - this would learn about ALL flags.... - if(wizard) - alchemist_known_artifacts[a_select_flags[i].flag/32] = 0xffffffffL; - */ - - /* Set various flags if they haven't *ID*'d an artifact with this flag set.*/ - if ( !(alchemist_known_artifacts[a_select_flags[i].flag / 32] & (1 << (a_select_flags[i].flag % 32)) )) - { - /* If this item has an ability that depends on pval which the player - * cannot set, don't allow them to change the pval either. */ - if ( a_select_flags[i].pval && flags_select[i]) - lockpval = TRUE; - - /* Set the color and set-ablitity of this flag */ - if ( flags_select[i] ) - flags_select[i] = -3; - else - flags_select[i] = -2; - continue; - } - else if ( skill < a_select_flags[i].level ) - { - /* If the alchemist has not passed the skill level for this flag, - Set this flag as unsettable. - */ - if ( flags_select[i]) - lockpval = TRUE; - else - flags_select[i] = -4; - } - } - - /* Save the screen */ - character_icky = TRUE; - Term_save(); - Term_clear(); - - - /* Everlasting love ... ... nevermind :) */ - while ( !done && !abord) - { - c_prt((q_ptr->exp - exp > 0) ? TERM_L_GREEN : TERM_L_RED, format("Experience left: %ld", q_ptr->exp - exp), 2, 0); - - /* Display the menu, but don't display it if we just - * displayed a message (it erases the screen, creating a blink message */ - if ( cur_set < 6 || cur_set == 7 ) - show_levels(); - - c_prt((q_ptr->exp - exp > 0) ? TERM_L_GREEN : TERM_L_RED, format("Experience left: %ld", q_ptr->exp - exp), 2, 0); - - prt("Enter to accept, Escape to abort", 1, 0); - - abord = !get_com("Play around with which group of powers?[a-g]", &choice); - - if ( choice == ESCAPE) - abord = TRUE; - - if ( abord ) - continue; /*or break, same diff */ - - if ( isalpha(choice)) - { - if (isupper(choice)) - choice = tolower(choice); - cur_set = A2I(choice); - } - else - { - bell(); - continue; - } - - if ( cur_set == 5 ) - { - if (q_ptr->xtra2 && !activation_select - && !get_check("This item already activates! Choose a different activation?")) continue; - select_an_activation(); - exp = get_flags_exp(pval, oldpval); - continue; - } - if ( cur_set == 6 ) - { - msg_print("This option is not available"); - continue; - } - if ( cur_set == 7 ) - { - artifact_display_or_use(pval, oldpval, FALSE); - continue; - } - if ( cur_set == 8 ) - { - if (q_ptr->exp - exp < 0) - msg_print("Not enough experience for the flags you've selected."); - else - done = TRUE; - continue; - } - - if (cur_set < 0 || cur_set > 4 ) - { - bell(); - continue; - } - - - while (!done && !abord) - { - /* Chose the flags */ - exp = 0; - max = show_flags(cur_set, pval); - exp = get_flags_exp(pval, oldpval); - c_prt((q_ptr->exp - exp > 0) ? TERM_L_GREEN : TERM_L_RED, format("Experience left: %ld", q_ptr->exp - exp), 2, 0); - - /* Build a prompt (accept all flags) */ - if (max <= 26) - { - /* Build a prompt (accept all flags) */ - strnfmt(out_val, 78, "(Flags %c-%c, I,D to change power level) Add/Remove which flag? ", - I2A(0), I2A(max - 1)); - } - else - { - strnfmt(out_val, 78, "(Flags %c-%c, I,D to change power level) Add/Remove which flag? ", - I2A(0), '0' + max - 27); - } - c_prt(TERM_L_BLUE, format("Power(I/D to increase/decrease): %d", pval), 3, 0); - - /* Get a spell from the user */ - while (!(done = !get_com(out_val, &choice))) - { - if (choice == 'I') - { - if ( lockpval ) - { - msg_print("You cannot do that - you don't know how!"); - continue; - } - if (q_ptr->exp - exp < 0) - { - msg_print("Not enough experience. Decrease power or deselect flags."); - continue; - } - pval++; - break; - } - else if (choice == 'D') - { - if ( lockpval ) - { - msg_print("You cannot do that - you don't know how!"); - continue; - } - pval--; - if (pval < oldpval) pval = oldpval; - break; - } - else if (choice == '\r' || choice == ESCAPE || choice == ' ') - { - done = TRUE; - break; - } - else if (isalpha(choice)) - { - /* Lowercase */ - if (isupper(choice)) choice = tolower(choice); - - /* Extract request */ - i = (islower(choice) ? A2I(choice) : -1); - } - else - { - i = D2I(choice) + 26; - - /* Illegal */ - if (i < 26) i = -1; - } - - /* Totally Illegal */ - if ((i < 0) || (i >= max)) - { - bell(); - continue; - } - else - { - /*Find the i'th flag in group cur_set...*/ - for ( j = 0 ; a_select_flags[j].group ; j++) - if (a_select_flags[j].group == cur_set + 1) - if (!i--) break; - - if ( flags_select[j] == -4 ) - { - msg_format("You need at least %d skill in alchemy.", - a_select_flags[j].level); - continue; - } - if ( flags_select[j] != 0 && flags_select[j] != 1) - { - bell(); - continue; - } - if (flags_select[j]) flags_select[j] = 0; - else if (!flags_select[j]) - { - if (q_ptr->exp - exp < 0) - { - msg_print("Not enough experience. Decrease power or deselect flags."); - continue; - } - flags_select[j] = 1; - } - break; - } - } - }/*sub-screen select and redraw loop*/ - done = FALSE; - Term_clear(); - }/* main screen (flag select screen) select and redraw loop*/ - - /* Abort if not enough experience, or no flags added */ - if ( q_ptr->exp - exp < 0 || exp == 0 ) - abord = TRUE; - - /* Display the recipe, or use up the essences. - * Note that this has to be done before the screen - * is restored. This is because it's also called from - * within the loop to display the required items. */ - if ( !abord ) - if (!artifact_display_or_use(pval, oldpval, TRUE)) - abord = TRUE; - - /* Restore the screen */ - Term_load(); - character_icky = FALSE; - - /* Return if abort, or missing ingredients */ - if ( abord ) - return; - - /* Actually create the artifact */ - q_ptr->exp -= exp; - q_ptr->art_flags4 &= ~TR4_ART_EXP; - q_ptr->pval = pval; - - /* Just to be sure */ - q_ptr->art_flags3 |= ( TR3_IGNORE_ACID | TR3_IGNORE_ELEC | - TR3_IGNORE_FIRE | TR3_IGNORE_COLD ); - - { - int now = 0, before = 0; - char dummy_name[80]; - char new_name[80]; - - /* Apply the flags */ - for (i = 0; a_select_flags[i].group ; i++) - { - if (flags_select[i] < 0) - before++; - else if ( flags_select[i] == 1) - { - now++; - switch (a_select_flags[i].flag / 32) - { - case 0: - q_ptr->art_flags1 |= 1 << (a_select_flags[i].flag % 32); - break; - case 1: - q_ptr->art_flags2 |= 1 << (a_select_flags[i].flag % 32); - break; - case 2: - q_ptr->art_flags3 |= 1 << (a_select_flags[i].flag % 32); - break; - case 3: - q_ptr->art_flags4 |= 1 << (a_select_flags[i].flag % 32); - break; - case 4: - q_ptr->art_flags5 |= 1 << (a_select_flags[i].flag % 32); - break; - case 5: - q_ptr->art_esp |= 1 << (a_select_flags[i].flag % 32); - break; - default: - msg_print("error: this code can't ever be hit!"); - } - } - } - - if ( activation_select ) - { - q_ptr->art_flags3 |= TR3_ACTIVATE; - q_ptr->xtra2 = activation_select; - } - - - /* Set the 'show modifier' flag */ - q_ptr->art_flags3 |= TR3_SHOW_MODS; - - /* For temporary items, set a timeout. - * alchemist_skill^2 for now */ - if ( q_ptr->art_flags5 & TR5_TEMPORARY ) - { - int lev = get_skill(SKILL_ALCHEMY); - q_ptr->timeout = lev * lev * 3; - } - - /* Describe the new artifact */ - object_out_desc(q_ptr, NULL, FALSE, TRUE); - - - /* Name the new artifact */ - strcpy(dummy_name, "of an Alchemist"); - if (!(get_string("What do you want to call the artifact? ", dummy_name, 80))) - strcpy(new_name, "of an Alchemist"); - else - { - if ((strncmp(dummy_name, "of ", 3) == 0) || - (strncmp(dummy_name, "Of ", 3) == 0) || - ((dummy_name[0] == '\'') && - (dummy_name[strlen(dummy_name) - 1] == '\''))) - { - strcpy(new_name, dummy_name); - } - else - { - strcpy(new_name, "called '"); - strcat(new_name, dummy_name); - strcat(new_name, "'"); - } - } - /* Identify it fully */ - object_aware(q_ptr); - object_known(q_ptr); - - /* Mark the item as fully known */ - q_ptr->ident |= (IDENT_MENTAL); - q_ptr->ident |= IDENT_STOREB; /* This will be used later on... */ - - /* Save the inscription */ - q_ptr->art_name = quark_add(new_name); - q_ptr->found = OBJ_FOUND_SELFMADE; - - done = FALSE; - while (!done && get_com("Do you want to let this item continue to gain experience?", &choice)) - { - switch (choice) - { - case 'y': - case 'Y': - if (magic_essence(get_skill(SKILL_ALCHEMY))) - q_ptr->art_flags4 |= TR4_ART_EXP; - else - msg_format("Oh, NO! You don't have enough magic essences. You needed %d.", get_skill(SKILL_ALCHEMY)); - done = TRUE; - break; - case 'n': - case 'N': - q_ptr->exp = 0; - done = TRUE; - break; - } - } - - /* Cycle through the p_ptr->inventory, and optimize everything. - * This wasn't done earlier, because if we had, then - * things in the p_ptr->inventory would shift around, and q_ptr - * wouldn't point to the right thing. BUT, at this point - * we don't need q_ptr anymore, so optimizing the p_ptr->inventory - * becomes sane. Sticky bug to figure out, let me tell you. - * Note also that this is cycling backwards - this is so - * that the same effect doesn't cause us to skip items. */ - for ( i = INVEN_WIELD - 1 ; i >= 0 ; i-- ) - inven_item_optimize(i); - } - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP); -} - -/* - * Test to see if this tval/sval combo is in the alchemists' - * recipes as a createable item. Used to determine if we - * should extract from it. - */ -bool_ alchemist_exists(int tval, int sval, int ego, int artifact) -{ - int al_idx; - - /* To prevent conflicts with recipes for ego-items. - * artifact not used, simplifies the loop below. */ - if ((tval == 1) || artifact) - return FALSE; - - /*Search for recipes with this tval/sval combo as the final result*/ - for (al_idx = 0 ; al_idx < max_al_idx ; al_idx++) - { - int rtval = alchemist_recipes[al_idx].tval; - int rsval = alchemist_recipes[al_idx].sval; - - /* Accept ego wands and staves since ego is extracted last */ - if (((!ego || tval == TV_WAND || tval == TV_STAFF) && rtval == tval && rsval == sval) || - ( ego && rtval == 1 && rsval == ego)) - { - return TRUE; - } - } - return FALSE; -} - - -/* - * Hook to determine if an object can have things extracted from it. - */ -bool_ item_tester_hook_extractable(object_type *o_ptr) -{ - - /* No artifacts */ - if (artifact_p(o_ptr)) return (FALSE); - - /* No cursed things */ - if (cursed_p(o_ptr)) return (FALSE); - - /* If we REALLY wanted to rebalance alchemists, - * we'd test for 'fully identified this object kind' here. - */ - - return ((o_ptr->tval == TV_ROD_MAIN && o_ptr->pval != 0) - || alchemist_exists(o_ptr->tval, o_ptr->sval, o_ptr->name2, o_ptr->name1)); -} - -/* - * Hook to determine if an object is empowerable (NOT rechargeable) - */ -bool_ item_tester_hook_empower(object_type *o_ptr) -{ - int sval = -1; - int lev = get_skill(SKILL_ALCHEMY); - /* after level 25, can empower ego items to create artifacts - * and double ego items. - * after level 50, can empower artifacts to create powerful artifacts - */ - - /* Never Empower a cursed item */ - if ( cursed_p(o_ptr)) - { - return FALSE; - } - - /* Allow finalizing a self created artifact */ - if (artifact_p(o_ptr) - && (o_ptr->art_flags4 & TR4_ART_EXP) - && !(o_ptr->art_flags4 & TR4_ULTIMATE)) - return TRUE; - - switch ( o_ptr->tval) - { - /* Empowerable objects: Traditional alchemist stuff */ - case TV_WAND: - sval = SV_WAND_NOTHING; - break; - case TV_RING: - sval = SV_RING_NOTHING; - break; - case TV_STAFF: - sval = SV_STAFF_NOTHING; - break; - case TV_BOTTLE: - sval = 1; - break; - case TV_AMULET: - sval = SV_AMULET_NOTHING; - break; - case TV_SCROLL: - sval = SV_SCROLL_NOTHING; - break; - case TV_ROD: - sval = SV_ROD_NOTHING; - break; - case TV_ROD_MAIN: - sval = -1; - break; - case TV_BOOK: - sval = -1; - break; - - /* Ego item stuff */ - /* Disallow ego dragon armour before you can create artifacts.*/ - case TV_DRAG_ARMOR: - if ( lev < 25) - return FALSE; - /* FALL THROUGH! no break here. */ - - /* weapons */ - - case TV_DAEMON_BOOK: - case TV_SWORD: - case TV_HAFTED: - case TV_POLEARM: - case TV_AXE: - case TV_MSTAFF: - - /* misc other items */ - case TV_BOW: - case TV_BOOMERANG: - case TV_INSTRUMENT: - case TV_DIGGING: - case TV_LITE: - - /* Ammo */ - case TV_SHOT: - case TV_ARROW: - case TV_BOLT: - - /* Armor of various sorts */ - case TV_BOOTS: - case TV_GLOVES: - case TV_HELM: - case TV_CROWN: - case TV_SHIELD: - case TV_CLOAK: - case TV_SOFT_ARMOR: - case TV_HARD_ARMOR: - - /* Disallow ANY creation of ego items below level 5*/ - if ( lev < 5) - return FALSE; - - /* empowering an ego item creates an artifact or a - * double ego item, disallow below level 25 */ - if ( lev < 25 && o_ptr->name2) - return FALSE; - - /* Disallow double-ego and artifact unless the character has - * the artifact creation ability. */ - if (!has_ability(AB_CREATE_ART) && - (artifact_p(o_ptr) || (o_ptr->name2 && o_ptr->name2b))) - return FALSE; - - /* Otherwise... */ - return TRUE; - - default: - return FALSE; - } - - /* Return to the traditional alchemist objects. - * All ego items and artifacts returning TRUE are accepted as artifactable - * at level 25. If we want double ego non wieldable items (Fireproof Staff - * of Plenty) the artifactable test in do_cmd_alchemist() must be changed, - * e.g. checking if the item is wearable. - * For now, we disallow non-wearable ego-items and artifacts here. - */ - - if ((o_ptr->name2 || artifact_p(o_ptr)) && - o_ptr->tval != TV_RING && o_ptr->tval != TV_AMULET) - return FALSE; - - /* return true if it's a 'of nothing' item; - * does nothing for TV_ROD_MAIN and TV_BOOK - */ - return (sval == o_ptr->sval - - /* or if it's artifactable */ - || ((lev >= 50 || (lev >= 25 && !artifact_p(o_ptr))) && - (o_ptr->tval == TV_RING || o_ptr->tval == TV_AMULET)) - - /* or if it's egoable (note that normal egos start at level 5, wands and such start at 15) */ - || (!o_ptr->name2 && lev >= 15)); -} - -/* Extract a rod tip from a rod */ -void rod_tip_extract(object_type *o_ptr) -{ - object_type *q_ptr; - object_type forge; - - /* Get local object */ - q_ptr = &forge; - - /* Paranoia, return if it's a rod of nothing */ - if (o_ptr->pval == SV_ROD_NOTHING) - return; - - /* Extract the rod tip */ - object_prep(q_ptr, lookup_kind(TV_ROD, o_ptr->pval)); - - q_ptr->number = o_ptr->number; - - object_aware(q_ptr); - object_known(q_ptr); - (void)inven_carry(q_ptr, FALSE); - - /* Remove it from the rod */ - o_ptr->pval = SV_ROD_NOTHING; - - /* Window stuff */ - p_ptr->window |= (PW_INVEN); -} - - -/* Begin & finish an art */ -void do_cmd_toggle_artifact(object_type *o_ptr) -{ - char o_name[80]; - - if (!(o_ptr->art_flags4 & TR4_ART_EXP)) - { - bool_ okay = TRUE; - - if ( !alchemist_has_stone()) - { - msg_print("Creating an artifact will result into a permanent loss of 10 hp."); - if (!get_check("Are you sure you want to do that?")) return; - } - - if (!magic_essence(get_skill(SKILL_ALCHEMY))) - { - msg_format("You need %d magic essences.", get_skill(SKILL_ALCHEMY)); - return; - } - - /* Description */ - object_desc(o_name, o_ptr, FALSE, 0); - - if (o_ptr->number > 1) - { - msg_print("Not enough energy to enchant more than one object!"); - msg_format("%d of your %s %s destroyed!", (o_ptr->number) - 1, o_name, (o_ptr->number > 2 ? "were" : "was")); - o_ptr->number = 1; - } - okay = TRUE; - - if (!okay) return; - - /* he/she got warned */ - p_ptr->hp_mod -= 10; - - /* Ok toggle it */ - o_ptr->art_flags4 |= TR4_ART_EXP; - o_ptr->name2 = 0; - o_ptr->name2b = 0; - o_ptr->art_name = quark_add("Becoming"); - - /* Copy the object_kind flags to the artifact flags. - * Note that this is only needed so that flags set in the - * 'kind' area are visible when finalizing the artifact. - */ - { - u32b f1, f2, f3, f4, f5, esp; - - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - o_ptr->art_flags1 |= f1; - o_ptr->art_flags2 |= f2; - o_ptr->art_flags3 |= f3; - o_ptr->art_flags4 |= f4; - o_ptr->art_flags5 |= f5; - o_ptr->art_esp |= esp; - } - - p_ptr->update |= (PU_HP); - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - } - else - { - do_cmd_create_artifact(o_ptr); - } -} - -/* - * Test to see if they have all the ingredients to create an item. - * (doesn't count base item) - * creates 'tocreate' items (may be -1, but no more than that!) - * if tocreate=0, will return true if the player has enough - * in their p_ptr->inventory to empower that item. - */ -bool_ alchemist_items_check(int tval, int sval, int ego, int tocreate, bool_ message) -{ - int al_idx, j; - bool_ exists = FALSE; - - - for ( al_idx = 0 ; al_idx < max_al_idx ; al_idx++ ) - if ((ego && alchemist_recipes[al_idx].sval == ego - && alchemist_recipes[al_idx].tval == 1 ) - || (!ego && alchemist_recipes[al_idx].sval == sval - && alchemist_recipes[al_idx].tval == tval)) - { - exists = TRUE; - /* Create the essences */ - if (tocreate > 0) - { - object_type forge; - object_type *o_ptr = &forge; - - object_wipe(o_ptr); - object_prep(o_ptr, lookup_kind(TV_BATERIE, alchemist_recipes[al_idx].sval_essence)); - o_ptr->number = alchemist_recipes[al_idx].qty * tocreate; - /* Don't bother with apply_magic */ - - /* Randomly decrease the number of essences created */ - if ( randint(3) == 1 - && randint(52) > get_skill(SKILL_ALCHEMY) - && !alchemist_has_stone()) - o_ptr->number /= randint(2) + 1; - if ( o_ptr->number == 0) - continue; - object_aware(o_ptr); - object_known(o_ptr); - if (inven_carry_okay(o_ptr)) - { - int i; - inven_carry(o_ptr, FALSE); - for (i = 0; i < INVEN_WIELD ; i++) - if (p_ptr->inventory[i].tval == o_ptr->tval && p_ptr->inventory[i].sval == o_ptr->sval) - { - if ( message ) - inven_item_describe(i); - break; - } - - } - else - drop_near(o_ptr, 0, p_ptr->py, p_ptr->px); - - o_ptr->ident |= IDENT_STOREB; - } - else if ( tocreate < -1) - { - /*It's not valid to create more than one - * thing at a time, so if it's less than -1, - * it must be time to display a recipe - */ - msg_format("%d essences of %d", - alchemist_recipes[al_idx].qty, - al_idx); - } - else /* Destroy the essences (tocreate == -1) - * or check for existence(tocreate == 0)*/ - { - int rqty = alchemist_recipes[al_idx].qty; - for (j = 0; j < INVEN_WIELD; j++) - { - object_type *o_ptr = &p_ptr->inventory[j]; - if (o_ptr->k_idx - && (o_ptr->tval == TV_BATERIE ) - && (o_ptr->sval == alchemist_recipes[al_idx].sval_essence ) - && (o_ptr->number >= rqty )) - { - /* At this point, the item is required, destroy it. */ - if ( tocreate ) - { - inc_stack_size_ex(j, 0 - rqty, OPTIMIZE, message ? DESCRIBE : NO_DESCRIBE); - } - - /* When we find enough of the item, break out of the - * 'search through the p_ptr->inventory' loop */ - break; - } - } - if ( j == INVEN_WIELD) - /* This ingredient was not found, cannot do recipe */ - return FALSE; - }/*destroying items, or just checking for existence */ - } - return exists; -} - -/* This function lists all the ingredients - * needed to create something. - */ -void alchemist_display_recipe(int tval, int sval, int ego) -{ - int al_idx; - int row = 1, col = 15; - char o_name[80]; - char ch; - object_type *o_ptr, forge; - - /* Display the ingredients for a recipe */ - for ( al_idx = 0 ; al_idx < max_al_idx ; al_idx++ ) - if ((ego && alchemist_recipes[al_idx].sval == ego - && alchemist_recipes[al_idx].tval == 1 ) - || (!ego && alchemist_recipes[al_idx].sval == sval - && alchemist_recipes[al_idx].tval == tval)) - { - int qty = alchemist_recipes[al_idx].qty; - c_prt(TERM_GREEN, - format(" %d essence%s %s ", qty, - qty > 1 ? "s" : "", - k_name + k_info[lookup_kind(TV_BATERIE, alchemist_recipes[al_idx].sval_essence)].name ), - row++, col); - } - - c_prt(TERM_WHITE, " ", row++, col); - - if (!ego) - { - /* Find the name of that object */ - o_ptr = &forge; - object_prep(o_ptr, lookup_kind(tval, sval)); - o_ptr->name2 = ego; - hack_apply_magic_power = -99; - apply_magic(o_ptr, get_skill(SKILL_ALCHEMY) * 2, FALSE, FALSE, FALSE); - object_aware(o_ptr); - object_known(o_ptr); - /* the 0 mode means only the text, leaving off any numbers */ - object_desc(o_name, o_ptr, FALSE, 0); - } - else - { - /* Display the ego item name */ - strcpy(o_name, e_name + e_info[ego].name); - } - - /* Display a short message about it, and wait for a key. */ - (void)get_com(format("ingredients needed to create a %s", o_name), &ch); - -} - -/* - * - * The alchemist_recipe_select was copied from - * wiz_create_itemtype - * and then changed quite a bit. - * - */ - -/* - The select array is a simple array of 'use this char to select item x' - It has 88 items (three columns of 20 each) - selectitem is initilized with the reverse mappings: - selectitem[selectchar[x]] == x is always true. - */ -char selectchar[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*():;,.<=>[]{}/=?+'~"; -byte selectitem[256]; - -void strip_and_print(const char *str, int color, int num) -{ - int row = 2 + (num % 20), col = 40 * (num / 20); - int ch, max_len = 0; - char buf[80]; - char *string; - - if (num > 60) - { - msg_print("Attempting to display too many items!"); - return; - } - ch = selectchar[num]; - if (selectitem[ch] != num) - { - int i; - for ( i = 0 ; i < 256 ; i++) - selectitem[i] = 0xff; - for ( i = 0 ; selectchar[i] ; i++) - selectitem[(byte)selectchar[i]] = i; - } - - /* Skip past leading characters */ - while ((*str == ' ') || (*str == '&')) str++; - - /* Copy useful chars */ - for (string = buf; *str; str++) - if (*str != '~') *string++ = *str; - - /* Terminate the new name */ - *string = '\0'; - - /* strip the name down to size - if (76-col < (signed)max_len) - max_len = 76-col; - else - max_len = 30-6;*/ - max_len = 39; - - string = buf; - if (strlen(string) > (unsigned)max_len) - string = string + (strlen(string) - max_len); - - /* Print it */ - c_prt(color, format("[%c] %s", ch, string), row, col); -} - -/* Display a list of recipes that need a particular essence. - * Note that we display a list of essences first, - * so in effect, this is the alchemist's recipe book. - */ -void alchemist_recipe_book(void) -{ - int num, max_num, i, al_idx, bat, kidx; - int choice[61], choice2[61]; - int mod40; - bool_ essence[MAX_BATERIE_SVAL + 1]; - char ch; - - /* Save and clear the screen */ - character_icky = TRUE; - Term_save(); - - while ( TRUE ) - { - Term_clear(); - - num = 0; - - /* Display bateries */ - - /* start with assumption that the alchemist knows about no recipes */ - for (i = 0; i < MAX_BATERIE_SVAL + 1 ; i++) - essence[i] = FALSE; - - /* cycle through all alchemist recipes */ - for (al_idx = 0 ; al_idx < max_al_idx ; al_idx++) - /* if we aren't already going to display this essence */ - if (!essence[alchemist_recipes[al_idx].sval_essence]) - { - - /*Note that we don't display artifact recipes here...*/ - /*This is partially because artifacts often require exotic - ingredients as well */ - - if (!alchemist_recipes[al_idx].tval) - continue; - - if (alchemist_recipes[al_idx].tval == 1) - { - if (alchemist_known_egos[alchemist_recipes[al_idx].sval / 32] - & (1 << (alchemist_recipes[al_idx].sval % 32)) ) - essence[alchemist_recipes[al_idx].sval_essence] = TRUE; - continue; - } - - kidx = lookup_kind(alchemist_recipes[al_idx].tval, alchemist_recipes[al_idx].sval); - if (alchemist_recipes[al_idx].tval != 1 && k_info[kidx].know) - essence[alchemist_recipes[al_idx].sval_essence] = TRUE; - - } - for (num = 0, i = 0; i < MAX_BATERIE_SVAL + 7 ; i++) - if (essence[i] || i > MAX_BATERIE_SVAL) - { - int kidx = lookup_kind(TV_BATERIE, i); - if (i > MAX_BATERIE_SVAL) - { - switch (i) - { - case (MAX_BATERIE_SVAL + 1): strip_and_print("Scrolls", TERM_WHITE, num); - break; - case (MAX_BATERIE_SVAL + 2): strip_and_print("Potions", TERM_WHITE, num); - break; - case (MAX_BATERIE_SVAL + 3): strip_and_print("Wands", TERM_WHITE, num); - break; - case (MAX_BATERIE_SVAL + 4): strip_and_print("Rings", TERM_WHITE, num); - break; - case (MAX_BATERIE_SVAL + 5): strip_and_print("Staves", TERM_WHITE, num); - break; - case (MAX_BATERIE_SVAL + 6): strip_and_print("Amulets", TERM_WHITE, num); - break; - default: - continue; - } - } - else - /* add this essence to the list*/ - strip_and_print(k_name + k_info[kidx].name, TERM_WHITE, num); - - choice[num++] = i; - } - max_num = num; - if ( max_num == 0) - { - /*Note that this should never actually happen, as any skill - at alchemy automatically gets you some recipes, and this - procedure shouldn't be called for players without alchemist skill - */ - msg_print("You don't know any recipes!"); - msg_print("You can't be an alchemist without recipes!"); - break; - } - - while (num == 0xff || num >= max_num) - { - ch = selectchar[max_num - 1]; - /* Choose! */ - if ( max_num == 0 || - !get_com(format("Which Type of Recipe?[a-%c]", selectchar[max_num - 1]), &ch)) - break; - - /* Analyze choice - note that the cast to byte prevents overflow*/ - num = selectitem[(byte)ch]; - - } - /* This break, and the break for no recipes above, - are the only exits from this procedure. - */ - if ( num == 0xff || num >= max_num) - break; - - /* Save the baterie index */ - bat = choice[num]; - num = 0; - - /*Display the 'type of object' recipe screen*/ - if (bat > MAX_BATERIE_SVAL) - { - int tval; - switch (bat) - { - case MAX_BATERIE_SVAL + 1: - tval = TV_SCROLL; - break; - case MAX_BATERIE_SVAL + 2: - tval = TV_POTION; - break; - case MAX_BATERIE_SVAL + 3: - tval = TV_WAND; - break; - case MAX_BATERIE_SVAL + 4: - tval = TV_RING; - break; - case MAX_BATERIE_SVAL + 5: - tval = TV_STAFF; - break; - case MAX_BATERIE_SVAL + 6: - tval = TV_AMULET; - break; - } - Term_load(); - alchemist_recipe_select(&tval, 0, FALSE, TRUE); - Term_save(); - continue; - } - mod40 = 0; - while ( TRUE ) - { - int skipped; - - Term_clear(); - num = 0; - - if (mod40) - { - strip_and_print("--MORE--", TERM_WHITE, num); - choice[num] = -2; - choice2[num++] = 0; - } - - /* Display all items made with this essence */ - for ( al_idx = 0 , skipped = 0 ; al_idx < max_al_idx ; al_idx++) - if ( alchemist_recipes[al_idx].sval_essence == bat) - { - int sval = alchemist_recipes[al_idx].sval; - int tval = alchemist_recipes[al_idx].tval; - char names[200] = ""; - - if (alchemist_recipes[al_idx].tval == 1) - { - /* Ego items */ - ego_item_type *e_ptr = &e_info[sval]; - int j, k; - - if ( !(alchemist_known_egos[sval / 32] & (1 << (sval % 32)))) - continue; - - for ( j = 0 ; j < 6 && e_ptr->tval[j] ; j ++ ) - { - if ( j > 0 && e_ptr->tval[j] == e_ptr->tval[j - 1]) - continue; - for ( k = 0; tvals[k].tval; k++) - if (tvals[k].tval == e_ptr->tval[j]) - { - strcat(names, tvals[k].desc); - strcat(names, ", "); - break; - } - } - strcat(names, e_name + e_ptr->name); - } - else - { - /* Normal Items */ - int kidx = lookup_kind(tval, sval); - int k; - if ( !k_info[kidx].know ) - continue; - - for ( k = 0; tvals[k].tval; k++) - if (tvals[k].tval == tval) - { - strcat(names, tvals[k].desc); - break; - } - strcat(names, " of "); - strcat(names, k_name + k_info[kidx].name); - - } - - /*Skip the first mod40 pages of recipes*/ - if (skipped++ < mod40*38) - continue; - - /* add this object kind to the list*/ - strip_and_print(names, TERM_WHITE, num); - choice[num] = tval; - choice2[num++] = sval; - if (num > 38) - { - strip_and_print("--MORE--", TERM_WHITE, num); - choice[num] = -1; - choice2[num++] = 0; - break; - } - - }/*Loop through tidx/sidx*/ - - max_num = num; - while (num == 0xff || num >= max_num) - { - ch = selectchar[max_num - 1]; - /* Choose! */ - if ( max_num == 0 || !get_com( - format("Examine which recipe?[%c-%c]", selectchar[0], ch) - , &ch)) - { - break; - } - - /* Analyze choice */ - num = selectitem[(byte)ch]; - } - - if ( choice[num] < 0) - { - if (choice[num] < -1) - mod40--; - else - mod40++; - continue; - } - - if ( num == 0xff || num >= max_num) - break; - - /* Display the recipe */ - if (choice[num] == 1) - alchemist_display_recipe(0, 0, choice2[num]); - else - alchemist_display_recipe(choice[num], choice2[num], 0); - } - /* - break is at top of loop, after essence list - if( num < 0 || num >= max_num) - break; - */ - - }/*show recipes*/ - - /* Restore screen contents */ - Term_load(); - character_icky = FALSE; -} - -/* Display a list of known recipies that can be made with - * materials on hand (including the passed tval). Also - * calls the recipe_display function, if requested by the - * player or there aren't enough essences to make the - * requested object. - * - * Note: sval is ignored if !ego, tval is the only determinant - * of what recipies are available otherwise. - * - * This function needs to be able to scroll a list, because - * there are SO MANY potions. :) - */ -int alchemist_recipe_select(int *tval, int sval, int ego, bool_ recipe) -{ - int i, mod40 = 0, num, max_num = 0; - - cptr tval_desc2 = ""; - char ch; - bool_ done = FALSE; - - int choice[60]; - int validc[60]; - - const char *string; - - - /* Save and clear the screen */ - character_icky = TRUE; - Term_save(); - Term_clear(); - - /* Base object type chosen, fill in tval */ - for ( num = 0 ; num < 40 ; num ++) - if (tvals[num].tval == *tval) - { - tval_desc2 = tvals[num].desc; - } - - while (!done) - { - Term_clear(); - if (ego) - { - /* Find matching ego items */ - for (num = 0, i = 1; (num < 40) && (i < max_e_idx) ; i++) - { - int j; - ego_item_type *e_ptr = &e_info[i]; - - /* Skip if unknown ego type */ - if ( !(alchemist_known_egos[i / 32] & (1 << (i % 32)))) - continue; - - /* search in permitted tvals/svals for allowed egos */ - for ( j = 0 ; j < 6 ; j ++ ) - if ( e_ptr->tval[j] == *tval - && sval >= e_ptr->min_sval[j] - && sval <= e_ptr->max_sval[j]) - { - int color = TERM_GREEN; - - /*Reject if not opposite end of name - prefixes only on postfix egos, - postfixes only on prefix egos. - */ - if (ego != -1 && e_ptr->before == e_info[ego].before) - continue; - - /*Color it red of the alchemist doesn't have the essences to create it*/ - if (!alchemist_items_check(*tval, 0, i, 0, TRUE)) - color = TERM_RED; - - /* add this ego to the list*/ - strip_and_print(e_name + e_info[i].name, color, num); - validc[num] = color; - choice[num++] = i; - break; - } - } - } - else - { - char skipped = 0; - num = 0; - if (mod40 != 0) - { - strip_and_print("--MORE--", TERM_WHITE, num); - validc[num] = TERM_WHITE; - choice[num++] = -1; - } - - for (i = 1; (num < 39) && (i < max_k_idx); i++) - { - object_kind *k_ptr = &k_info[i]; - - /* Analyze matching items */ - if (k_ptr->tval == *tval || (k_ptr->tval == TV_POTION2 && *tval == TV_POTION)) - { - char color = TERM_GREEN; - /* Hack -- Skip instant artifacts */ - if (k_ptr->flags3 & (TR3_INSTA_ART)) continue; - - /*Don't display recipes that the alchemist doesn't know about*/ - if (!k_ptr->know && !wizard) continue; - - /*Skip recipes that are somehow known, but don't exist*/ - if (!alchemist_exists(k_ptr->tval, k_ptr->sval, 0, 0)) - continue; - - /* Skip the first 39 if they hit 'more' */ - if (skipped++ < mod40*39) - continue; - - /* Color 'unable to create' items different */ - if (!alchemist_items_check(k_ptr->tval, k_ptr->sval, 0, 0, TRUE)) - color = TERM_RED; - - /* Acquire the "name" of object "i" */ - /* and print it in it's place */ - strip_and_print(k_name + k_ptr->name, color, num); - - /* Remember the object index */ - validc[num] = color; - choice[num++] = i; - } - } - if (num == 39) - { - strip_and_print("--MORE--", TERM_WHITE, num); - validc[num] = TERM_WHITE; - choice[num++] = -1; - } - } - - /* We need to know the maximal possible remembered object_index */ - max_num = num; - string = "What Kind of %s? (* to see recipe) [%c-%c,*]"; - num = 0xff; - - /* Pretend they're all undoable if we where called to display recipes */ - if (recipe) - { - for ( num = 0 ; num < max_num ; num++) - if (validc[num] != TERM_WHITE) validc[num] = TERM_RED; - string = "show which %s recipe? [%c-%c]"; - } - - while (num == 0xff || num >= max_num) - { - ch = selectchar[max_num - 1]; - /* Choose! */ - if ( max_num == 0 || !get_com(format(string, tval_desc2, selectchar[0], ch), &ch)) - { - break; - } - - /* Extra breaks for recipe */ - if (recipe && (ch == '\r' || ch == ' ' || ch == ESCAPE )) - break; - - /* Analyze choice */ - num = selectitem[(byte)ch]; - - /* Pretend that we don't have enough essences for anything */ - if (ch == '*' ) - { - for ( num = 0 ; num < max_num ; num++) - if (validc[num] != TERM_WHITE) validc[num] = TERM_RED; - string = "Show which %s recipe? [%c-%c]"; - } - } - if ( num == 0xff || max_num == 0 || num >= max_num) - break; - - if ( validc[num] == TERM_WHITE ) - { - if (num == 0) - mod40--; - else - mod40++; - if ( mod40 < 0) - mod40 = 0; - continue; - } - - /* If we don't have enough essences, or user asked for recipes */ - if ( validc[num] != TERM_GREEN ) - { - /* Display the recipe */ - if (ego) - alchemist_display_recipe(*tval, sval, choice[num]); - else - alchemist_display_recipe(k_info[choice[num]].tval, k_info[choice[num]].sval, 0); - } - else - done = TRUE; - - }/*while(!done)*/ - - /* Restore screen contents */ - Term_load(); - character_icky = FALSE; - - /* User abort, or no choices */ - if (max_num == 0 || num == 0xff || num >= max_num) - { - if (max_num == 0) - msg_print("You don't know of anything you can make using that."); - return ( -1); - } - if ( validc[num] != TERM_GREEN ) - return ( -1); - - /* And return successful */ - if ( ego ) - return choice[num]; - - /* Set the tval, should be the same unless they selected a potion2 */ - if (*tval != k_info[choice[num]].tval && *tval != TV_POTION) - msg_print("Coding error: tval != TV_POTION"); - *tval = k_info[choice[num]].tval; - return ( k_info[choice[num]].sval ); -} - -/* Set the 'known' flags for all objects with a level <= lev - * This lets the budding alchemist create basic items. - */ -void alchemist_learn_all(int lev) -{ - int i; - - if ( !get_skill(SKILL_ALCHEMY) ) - return; - - /* msg_format("You learn about level %d items",lev); */ - - for ( i = 0 ; i < max_k_idx ; i++ ) - if ( k_info[i].level <= lev ) - if (alchemist_exists(k_info[i].tval, k_info[i].sval, 0, 0)) - k_info[i].know = TRUE; -} - -void alchemist_learn_ego(int ego) -{ - char *name; - int i; - - /* some Paranoia*/ - if ( !ego || ego >= max_e_idx ) - return; - - /* Get the ego items name */ - name = e_name + e_info[ego].name; - while (strchr(name, ' ')) - name = strchr(name, ' ') + 1; - - /* Don't learn about egos without recipes, and - * always learn about the passed ego item. */ - if (alchemist_exists(0, 0, ego, 0)) - { - alchemist_known_egos[ego / 32] |= (1 << (ego % 32)); - /* msg_format("You learn about '%s' ego items.",e_name+e_info[ego].name); */ - } - else - { - return; - } - - /* Don't mass learn about egos that have no name. */ - if ( name[0] == 0 ) - { - return; - } - - /* Look through all ego's for matching name */ - /* Note that the original ego is marked here too */ - for ( i = 0 ; i < max_e_idx ; i++ ) - if ( strstr(e_name + e_info[i].name, name) != NULL /*Last word of name exists in this ego's name*/ - && alchemist_exists(0, 0, i, 0) /*There exists a recipe for this*/ - && !(alchemist_known_egos[i / 32] & (1 << (i % 32)) ) ) /*Not already known*/ - /*&& (e_name+e_info[i].name)[0])non-blank name*/ - { - alchemist_known_egos[i / 32] |= (1 << (i % 32)); - /* msg_format("You learn about '%s' ego items.",e_name+e_info[i].name); */ - } - - return; -} - -/* Alchemist has learned about a new item. - * Learn about not only it, but ALL egos with the - * same name. - */ -int alchemist_learn_object(object_type *o_ptr) -{ - - /* Allow alchemist to create this item, - and.. learn about it even if the player - doesn't currently have the alchemy skill - */ - k_info[o_ptr->k_idx].know = TRUE; - - /* Not Paranoia, identify_fully calls this always */ - if ( !get_skill(SKILL_ALCHEMY) ) - return FALSE; - - if ( artifact_p(o_ptr) ) - { - char o_name[80]; - u32b f1, f2, f3, f4, f5, esp; - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* Randarts and normal artifacts both*/ - alchemist_known_artifacts[0] |= f1; - alchemist_known_artifacts[1] |= f2; - alchemist_known_artifacts[2] |= f3; - alchemist_known_artifacts[3] |= f4; - alchemist_known_artifacts[4] |= f5; - alchemist_known_artifacts[5] |= esp; - - object_desc(o_name, o_ptr, 1, 0); - msg_format("You learn all about the abilities of %s!", o_name); - } - if (o_ptr->name2) - alchemist_learn_ego(o_ptr->name2); - - if (o_ptr->name2b) - alchemist_learn_ego(o_ptr->name2b); - - return (TRUE); -} - -/* Alchemist has gained a level - set the ego flags - * for all egos <= lev/4. - */ -void alchemist_gain_level(int lev) -{ - object_type forge; - object_type *o_ptr = &forge; - - if ( lev == 0) - { - /* Learn about potions of Detonation */ - k_info[417].know = TRUE; - } - if ( lev == 5) - { - int ego; - int egos[] = { - 7/*armor of resist fire*/ - , 18/*shield of resist fire*/ - , 74/*shocking weapon*/ - , 75/*fiery weapon*/ - , 76/*frozen weapon*/ - , 77/*Venomous weapon*/ - , 78/*Chaotic weapon*/ - , 115/*projectile of venom*/ - , 116/*projectile of Acid*/ - , 122/*projectile of flame*/ - , 123/*projectile of frost*/ - , 137/*Lite of fearlessness*/ - , 0 /*terminator*/ - }; - object_wipe(o_ptr); - /* learn about some basic ego items */ - /* Note that this is just to get you started. */ - for ( ego = 0 ; egos[ego] ; ego++) - { - o_ptr->name2 = egos[ego]; - alchemist_learn_object(o_ptr); - } - msg_print("You recall your old master teaching you about elemental item infusing."); - } - if ( lev == 10) - { - /*For 'hard rooms' Players only, learn about diggers.*/ - if (ironman_rooms) - { - msg_print("There's gotta be an easier way to get into all these vaults!"); - object_wipe(o_ptr); - o_ptr->name2 = 101; /* Ego item, 'of digging' */ - alchemist_learn_object(o_ptr); - } - } - if ( lev == 25) - { - msg_print("You recall your old master reminiscing about legendary infusings"); - msg_print("and the Philosophers' stone."); - - /* No auto-learn on artifacts - by this level, you'll have *ID*'d several */ - } - if ( lev == 25) - { - msg_print("You wonder about shocking daggers of slay evil."); - } - if ( lev == 50) - { - /* learn about Temporary item creation */ - /* Note that this is the ONLY way to learn this, - because spells which create a temporary item - also fully ID it. */ - alchemist_known_artifacts[4] |= TR5_TEMPORARY; - msg_print("It suddenly occurs to you that artifacts don't *HAVE* to be permanent..."); - } - - /* Every Four Levels, learn about items that are - * less than that. - * Note that this isn't a significant effect after the - * first few levels, as the level at which you are learning - * things here quickly drops behind the level at which you - * are finding items. - */ - if ( (lev & 0x3) != 0 ) - return; - lev = (lev >> 2) + 1; - alchemist_learn_all(lev); - -} - -/* This, in combination with some code in loadsave.c, - insures that alchemist_gain_level is called EXACTLY - once with each possible value during the characters - lifetime. - */ -void alchemist_check_level() -{ - u32b lev = get_skill(SKILL_ALCHEMY); - if ( alchemist_gained > lev ) - return; - /*Paranoia*/ - if ( !lev ) - return; - while ( alchemist_gained <= lev ) - alchemist_gain_level(alchemist_gained++); -} - -/* - * do_cmd_cast calls this function if the player's class - * is 'alchemist'. - */ -void do_cmd_alchemist(void) -{ - int item, ext = 0; - int value, basechance; - int askill; - bool_ repeat = 0; - char ch; - - object_type *o_ptr, *q_ptr; - object_type forge, forge2; - byte carry_o_ptr = FALSE; - - cptr q, s; - - /* With the new skill system, we can no longer depend on - * check_exp to handle the changes and learning involved in - * gaining levels. - * So we'll have to check for it here. - */ - alchemist_check_level(); - askill = get_skill(SKILL_ALCHEMY); - - - q_ptr = &forge; - - o_ptr = &p_ptr->inventory[INVEN_HANDS]; - if ((o_ptr->tval != TV_GLOVES) || (o_ptr->sval != SV_SET_OF_LEATHER_GLOVES)) - { - msg_print("You must wear gloves in order to do alchemy."); - return; - } - - if (p_ptr->confused) - { - msg_print("You are too confused!"); - return; - } - - while (TRUE) - { - if (!get_com("[P]ower, [R]echarge or [L]eech an item, [E]xtract essences, or recipe [B]ook?", &ch)) - { - ext = 0; - break; - } - if (ch == ' ' ) - { - ext = 0; - break; - } - if (ch == 'P' || ch == 'p') - { - ext = 1; - break; - } - if (ch == 'E' || ch == 'e') - { - ext = 2; - break; - } - if (ch == 'R' || ch == 'r') - { - ext = 3; - break; - } - if (ch == 'L' || ch == 'l') - { - ext = 2; - repeat = 1; - break; - } - if (ch == 'B' || ch == 'b') - { - ext = 4; - break; - } - } - - /**********Add a power*********/ - if (ext == 1) - { - int i, qty, tval, sval = 0, ego = 0; - char o_name[200]; - - /* Get an item */ - q = "Empower which item? "; - s = "You have no empowerable items."; - item_tester_hook = item_tester_hook_empower; - - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - /* Get the item */ - o_ptr = get_object(item); - - /* Create an artifact from an ego or double ego item, - * from a previous artifact, or finish an artifact - */ - if ((askill >= 25) && (artifact_p(o_ptr) || o_ptr->name2) && has_ability(AB_CREATE_ART)) - { - if (get_check("Create an artifact?")) - { - do_cmd_toggle_artifact(o_ptr); - return; - } - /* Don't change artifacts or double ego items further */ - else if (artifact_p(o_ptr) || (o_ptr->name2 && o_ptr->name2b)) - return; - } - /*Ok, now we have the item, so we can now pick recipes. - Note: No recipe is known unless we have 'extracted' from - that object type. I.E. the 'know' flag (also greater identify) - is set. - */ - - /* Here we're not setting what kind of ego item it IS, - * where' just deciding that it CAN be an ego item */ - if ( o_ptr->name2 ) /* creating a DUAL ego */ - ego = TRUE; - if ( o_ptr->tval < 40 && o_ptr->tval != TV_BOTTLE) - ego = TRUE; - if ( o_ptr->tval == TV_ROD_MAIN || o_ptr->tval == TV_DAEMON_BOOK || o_ptr->tval == TV_BOOK) - ego = TRUE; - - sval = o_ptr->sval; - if (!ego) - { - switch ( o_ptr->tval) - { - case TV_WAND: - sval = SV_WAND_NOTHING; - break; - case TV_RING: - sval = SV_RING_NOTHING; - break; - case TV_STAFF: - sval = SV_STAFF_NOTHING; - break; - case TV_BOTTLE: - sval = 1; - break; - case TV_AMULET: - sval = SV_AMULET_NOTHING; - break; - case TV_SCROLL: - sval = SV_SCROLL_NOTHING; - break; - case TV_ROD: - sval = SV_ROD_NOTHING; - break; - } - } - if ( o_ptr->sval != sval ) - ego = TRUE; - - tval = o_ptr->tval; - sval = o_ptr->sval; - - /*HACK - bottles don't have the same tval as potions*/ - /*Everything else will have the same tval after empowering*/ - if (tval == TV_BOTTLE) tval = TV_POTION; - if (ego) - if (o_ptr->name2) - ego = alchemist_recipe_select(&tval, sval, o_ptr->name2, FALSE); - else - ego = alchemist_recipe_select(&tval, sval, -1, FALSE); - else - sval = alchemist_recipe_select(&tval, 0, 0, FALSE); - - if ( sval < 0 || ego < 0) - return; - - /* Check to make sure we have enough essences */ - /* theoretically this is taken care of by recipe_select*/ - /* but we'll double check just for paranoia. */ - if (!alchemist_items_check(tval, sval, ego, 0, TRUE)) - { - msg_print("You do not have enough essences."); - return; - } - - /* Take a turn */ - energy_use = 100; - - /* Use up the essences */ - (void)alchemist_items_check(tval, sval, ego, -1, TRUE); - - /* Enchant stacks of ammunition at a time */ - if ( o_ptr->tval == TV_SHOT || o_ptr->tval == TV_ARROW || o_ptr->tval == TV_BOLT ) - { - qty = 1; - while (qty < o_ptr->number && alchemist_items_check(tval, sval, ego, -1, FALSE)) - qty++; - } - else - qty = 1; - - /* Copy the object */ - q_ptr = &forge; - object_copy(q_ptr, o_ptr); - - if ( o_ptr->tval == TV_WAND) - { - /* distribute charges on wands */ - q_ptr->pval = o_ptr->pval / o_ptr->number; - o_ptr->pval -= q_ptr->pval; - } - - o_ptr = q_ptr; - o_ptr->number = qty; - carry_o_ptr = TRUE; - - /* Destroy the initial object */ - inc_stack_size(item, -qty); - - - if ( ego ) - { - int pval, pval2; - s32b pval3; - - pval = o_ptr->pval; - pval2 = o_ptr->pval2; - pval3 = o_ptr->pval3; - - if (o_ptr->name2) - o_ptr->name2b = ego; - else - o_ptr->name2 = ego; - o_ptr->pval = randint(e_info[ego].max_pval - 1) + 1; - /* dilemma - how to prevent creation of cursed items, - * without allowing the creation of artifacts? - * We can't, unless we want to finalize the ego flags ourselves. - */ - apply_magic(o_ptr, askill * 2, FALSE, FALSE, FALSE); - /* Remember what the old pval was, so that we can re-apply it. */ - if ( o_ptr->tval == TV_WAND - || o_ptr->tval == TV_RING - || o_ptr->tval == TV_AMULET - || o_ptr->tval == TV_STAFF) - { - o_ptr->pval = pval; - o_ptr->pval2 = pval2; - o_ptr->pval3 = pval3; - } - else if (o_ptr->tval == TV_ROD_MAIN) - { - o_ptr->pval = pval; - } - else if ((o_ptr->tval == TV_BOOK) && (o_ptr->sval == 255)) - { - o_ptr->pval = pval; - } - else if (o_ptr->tval == TV_SHOT - || o_ptr->tval == TV_ARROW - || o_ptr->tval == TV_BOLT) - { - o_ptr->pval2 = pval2; - } - else if (o_ptr->tval == TV_INSTRUMENT) - { - o_ptr->pval2 = pval2; - } - - /* Calculate failure rate, lev=val/2500+5 */ - value = MIN(e_info[o_ptr->name2].cost, 50000); - if (o_ptr->name2b) value += MIN(e_info[o_ptr->name2b].cost, 50000); - basechance = (value / 1000 + 5 - get_skill_scale(SKILL_ALCHEMY, 100) ) * 10; - if ( basechance < 0) basechance = 0; - if ( basechance > 100) basechance = 100; - - value = object_value_real(o_ptr); - - } - else /* not an ego item */ - { - o_ptr = &forge; - object_wipe(o_ptr); - object_prep(o_ptr, lookup_kind(tval, sval)); - hack_apply_magic_power = -99; - apply_magic(o_ptr, askill * 2, FALSE, FALSE, FALSE); - if ( o_ptr->tval == TV_WAND || o_ptr->tval == TV_STAFF) - o_ptr->pval = 0; - value = object_value_real(o_ptr); - - basechance = k_info[o_ptr->k_idx].level - askill * 2; - basechance *= 10; - - /* Can't fail more that 100% of the time... */ - if (basechance > 100) - basechance = 100; - /* Always success in creation of potion of detonations */ - if (o_ptr->tval == TV_POTION && o_ptr->sval == SV_POTION_DETONATIONS) - { - basechance /= 10; - } - } - - /* Use up gold to create items */ - /* this has the effect of making the alchemist - chronically short of funds, unless he finds the - philosopher's stone. It also means the easiest - things to make are 'bad', like a potion of - detonations... - */ - /* Problem - to restrictive. We need something - which requires less money. But at the same time, - we don't want an 'easy cash' situation. Maybe something - like '10% * level difference', meaning at skill level 5, - level one items are free? But egos are frequently level - zero! Maybe egos are forced to level 25? with a cost ceiling? - I mean, Potions and scrolls are really the problem causing the - 'easy cash' situation, it's ego items. Ego items require - relatively few essences, and the rewards are HUGE. Most powerful - potions and scrolls require rare essences. Maybe force all egos - to require a magic essence? But then you'd get lots of magic - from distilling them. Maybe consumed in the creation? then when - you got a powerful item, you could make one ego item... - But if making things doesn't take gold, what about the cash - does the Philosopher's stone do? - Time*/ - - /* 0% failure if you have the stone */ - if ( alchemist_has_stone()) - basechance = 0; - - if (basechance > 0 && value) - { - char string[80]; - string[0] = '0'; - string[1] = 0; - - msg_format("The chance of success is only %d%%!", 100-basechance); - get_string("How much gold do you want to add?", string, 50); - i = atoi(string); - /* Note: don't trust the user to enter a positive number... */ - if ( i < 0) - i = 0; - if ( i > p_ptr->au) - i = p_ptr->au; - - if (i) - { - basechance = basechance - (i * 20) / value; - msg_format("The chance of success improved to %d%%.", 100-basechance); - } - - if (randint(100) < basechance ) - /*creation failed, even with the extra gold...*/ - carry_o_ptr = FALSE; - - /* Redraw gold */ - p_ptr->au -= i; - p_ptr->redraw |= (PR_GOLD); - } - - /* Set fully identified - * After all, the player just made it... - */ - object_aware(o_ptr); - object_known(o_ptr); - o_ptr->ident |= IDENT_MENTAL; - o_ptr->found = OBJ_FOUND_SELFMADE; - - object_desc(o_name, o_ptr, FALSE, 0); - - if ( carry_o_ptr) - { - msg_format("You have successfully created %s %s", - (o_ptr->number > 1 ? "some" : (is_a_vowel(o_name[0]) ? "an" : "a")), - o_name); - - if (inven_carry_okay(o_ptr)) - inven_carry(o_ptr, FALSE); - else - { - drop_near(o_ptr, 0, p_ptr->py, p_ptr->px); - msg_format("You drop the %s", o_name); - } - carry_o_ptr = FALSE; - } - else /* don't carry, or in other words... */ - { - int level = k_info[o_ptr->k_idx].level; - if (o_ptr->name1) /* created ego item */ - level += e_info[o_ptr->name2].level; - - msg_format("Your attempt backfires! Your %s explodes!", o_name); - take_hit(damroll(3, level - askill ) , "Alchemical Explosion"); - p_ptr->redraw |= (PR_HP); - } - - /* Combine / Reorder the pack (later) */ - p_ptr->notice |= (PN_COMBINE | PN_REORDER); - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - - /* Optimize the entire p_ptr->inventory - needed because we - don't know how many essences where used, and we may - have 'used up' a wielded item as well. - */ - for ( item = 0 ; item < INVEN_TOTAL ; item++ ) - inven_item_optimize(item); - - /**********Extract a power*********/ - } - else if (ext == 2) - { - int ego; - bool_ discharge_stick = FALSE; - - /* s_ptr holds the empty items */ - object_type *s_ptr = NULL; - bool_ carry_s_ptr = FALSE; - - item_tester_hook = item_tester_hook_extractable; - - /* Get an item */ - q = "Extract from which item? "; - s = "You have no item to extract power from."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - /* Get the item */ - o_ptr = get_object(item); - - /* This is to prevent creating magic essences by extracting - * from a recharged wand of dragon breath or something. - */ - if (( o_ptr->tval == TV_WAND || o_ptr->tval == TV_STAFF ) - && o_ptr->art_flags4 & TR4_RECHARGED) - { - msg_print("You cannot extract essences after it's been magically recharged."); - return; - } - - /* Take a turn */ - energy_use = 100; - - /* Handle Rods before the loop, since they don't stack */ - if (o_ptr->tval == TV_ROD_MAIN && o_ptr->pval != SV_ROD_NOTHING) - { - rod_tip_extract(o_ptr); - return; - } - - do - { /* Repeat (for leech command) */ - - /* Create the items. - * we don't care if they drop to the ground, - * and if no action was taken, return - */ - ego = 0; - if ( o_ptr->name2) - ego = o_ptr->name2; - - /* For ego staves and wands (not of nothing), discharge before extracting the ego */ - discharge_stick = (o_ptr->pval > 0 && - ((o_ptr->tval == TV_STAFF && o_ptr->sval != SV_STAFF_NOTHING) || - (o_ptr->tval == TV_WAND && o_ptr->sval != SV_WAND_NOTHING))); - if (discharge_stick) - ego = 0; - - if (!alchemist_items_check(o_ptr->tval, o_ptr->sval, ego, 1, TRUE)) - { - msg_print("You cannot extract anything from that item."); - return; - } - - if (o_ptr->name2b && !alchemist_items_check(o_ptr->tval, o_ptr->sval, o_ptr->name2b, 1, TRUE)) - { - /* do nothing - if the second ego can't be extracted - because there is no recipe for it, simply destroy it - */ - } - - /* Once in three times, learn how to make the item */ - /* Sorry for the complicated if! Basically, if it's an - * unknown regular item or an unknown ego item, there's - * a one in 3 chance that it'll be id'd */ - if (((!ego && !k_info[o_ptr->k_idx].know) - || (ego && !(alchemist_known_egos[ego / 32] & (1 << (ego % 32))))) - && randint(3) == 1) - { - msg_print("While destroying it, you gain insight into this item."); - /* If over level 10, the player has a chance of 'greater ID' - * on extracted items - */ - if (askill > 9) - object_out_desc(o_ptr, NULL, FALSE, TRUE); - alchemist_learn_object(o_ptr); - } - - /* Always learn what kind of thing it is */ - object_known(o_ptr); - object_aware(o_ptr); - - /* If it's a wand or staff with charges (but not of nothing), - * decrease number of charges, unstacking if needed. - * Otherwise, create the 'of nothing' item and destroy the old one. - */ - if (discharge_stick) - { - /* Unstack staves */ - if ((o_ptr->tval == TV_STAFF) && (o_ptr->number > 1)) - { - /* Create one local copy of the staff */ - q_ptr = &forge2; - object_copy(q_ptr, o_ptr); - - /* Modify quantity */ - q_ptr->number = 1; - - /* Unstack the copied staff */ - o_ptr->number--; - - /* Use the local copy of the staff */ - o_ptr = q_ptr; - carry_o_ptr = TRUE; - } - /* remove one charge */ - o_ptr->pval--; - } - else - { - /* Create the empty, plain item */ - /* If the item was already created, increase the number */ - if (carry_s_ptr) - { - s_ptr->number++; - } - else - { - /* Otherwise we must create a local copy of the empty item */ - int tval, sval; - bool_ create_item = TRUE; - - tval = o_ptr->tval; - if ( !ego && (tval == TV_POTION || tval == TV_POTION2)) - tval = TV_BOTTLE; - - sval = o_ptr->sval; - - if (!ego) - { - switch ( tval) - { - case TV_WAND: - sval = SV_WAND_NOTHING; - break; - case TV_RING: - sval = SV_RING_NOTHING; - break; - case TV_STAFF: - sval = SV_STAFF_NOTHING; - break; - case TV_BOTTLE: - sval = 1; - break; - case TV_AMULET: - sval = SV_AMULET_NOTHING; - break; - case TV_SCROLL: - sval = SV_SCROLL_NOTHING; - break; - case TV_ROD: - sval = SV_ROD_NOTHING; - break; - default: - create_item = FALSE; - } - } - - if (create_item) - { - /* Create the empty item */ - s_ptr = &forge; - object_wipe(s_ptr); - object_prep(s_ptr, lookup_kind(tval, sval)); - s_ptr->number = 1; - - /* Force creation of non ego non cursed */ - hack_apply_magic_power = -99; - apply_magic(s_ptr, 0, FALSE, FALSE, FALSE); - - /* Hack -- remove possible curse */ - if (cursed_p(s_ptr)) - { - s_ptr->art_flags3 &= ~(TR3_CURSED | TR3_HEAVY_CURSE); - s_ptr->ident &= ~(IDENT_CURSED); - } - - /* Restore pvals (e.g. charges ==0) of the item */ - if (ego && ((tval == TV_WAND) || (tval == TV_STAFF) || - (tval == TV_RING) || (tval == TV_AMULET))) - { - s_ptr->pval = o_ptr->pval; - s_ptr->pval2 = o_ptr->pval2; - s_ptr->pval3 = o_ptr->pval3; - } - /* Restore the spell stored in a random book */ - else if ((o_ptr->tval == TV_BOOK) && (o_ptr->sval == 255)) - { - s_ptr->pval = o_ptr->pval; - } - /* Restore the type of explosive ammo */ - else if (o_ptr->tval == TV_SHOT || o_ptr->tval == TV_ARROW - || o_ptr->tval == TV_BOLT) - { - s_ptr->pval2 = o_ptr->pval2; - } - /* Restore the music stored in an instrument */ - else if (o_ptr->tval == TV_INSTRUMENT) - { - s_ptr->pval2 = o_ptr->pval2; - } - - object_aware(s_ptr); - object_known(s_ptr); - s_ptr->ident |= IDENT_STOREB; - - /* The empty item will be added to the p_ptr->inventory later */ - carry_s_ptr = TRUE; - } - } - - /* Now, we can delete the original (leeched) object. - * Is o_ptr an p_ptr->inventory / floor item or a local copy? - */ - if (!carry_o_ptr) - { - /* Break the leech-loop if it was the last item */ - if (o_ptr->number == 1) - repeat = 0; - - inc_stack_size(item, -1); - } - else - { - /* Forget the local object */ - carry_o_ptr = FALSE; - - /* reset o_ptr to the original stack, - * which contains at least another item */ - o_ptr = get_object(item); - } - } - } - while ( repeat == 1); - - /* If we carry empty items, add them to the p_ptr->inventory */ - if (carry_s_ptr) - inven_carry(s_ptr, TRUE); - - /* Combine / Reorder the pack (later) */ - p_ptr->notice |= (PN_COMBINE | PN_REORDER); - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - - /******* Recharge an item *******/ - } - else if (ext == 3) - { - int item; - - cptr q, s; - - item_tester_hook = item_tester_hook_recharge; - - /* Get an item */ - q = "Recharge which item? "; - s = "You have no rechargable items."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR ))) return; - - /* Get the item */ - o_ptr = get_object(item); - - /* Make sure we have enough essences to recharge this */ - if (!alchemist_items_check(o_ptr->tval, o_ptr->sval, 0, 0, TRUE)) - { - msg_print("You don't have the essences to recharge this item."); - return; - } - - /* Take a turn */ - energy_use = 100; - - /* Destroy the essences */ - (void)alchemist_items_check(o_ptr->tval, o_ptr->sval, 0, -1, TRUE); - - if ((o_ptr->tval == TV_STAFF) && (o_ptr->number > 1)) - { - /* Unstack staves */ - /* Get local object */ - q_ptr = &forge2; - - /* Obtain a local object */ - object_copy(q_ptr, o_ptr); - - /* Modify quantity */ - q_ptr->number = 1; - - /* Unstack the used item */ - o_ptr->number--; - - o_ptr = q_ptr; - carry_o_ptr = TRUE; - } - o_ptr->pval++; - } - else if ( ext == 4) - { - alchemist_recipe_book(); - } - /* Just in case - */ - if (carry_o_ptr) - { - /* the o_ptr item was probably an unstacked staff - * Anyway, we need to add it to the p_ptr->inventory */ - if (inven_carry_okay(o_ptr)) - inven_carry(o_ptr, TRUE); - else - drop_near(o_ptr, 0, p_ptr->py, p_ptr->px); - } -} - - -/* - * Command to ask favors from your god. - */ -void do_cmd_pray(void) -{ - if (p_ptr->pgod == GOD_NONE) - { - msg_print("Pray hard enough and your prayers might be answered."); - return; - } - else - { - if (!p_ptr->praying) - msg_format("You start praying to %s.", deity_info[p_ptr->pgod].name); - else - msg_format("You stop praying to %s.", deity_info[p_ptr->pgod].name); - p_ptr->praying = !p_ptr->praying; - - /* Update stuffs */ - p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS | PU_POWERS | - PU_SANITY | PU_BODY); - - p_ptr->redraw |= PR_PIETY | PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP; - energy_use = 100; - } -} - - -/* - * Return percentage chance of spell failure. - */ -int spell_chance_random(random_spell* rspell) -{ - int chance, minfail; - - - /* Extract the base spell failure rate */ - chance = rspell->level + 10; - - /* Reduce failure rate by "effective" level adjustment */ - chance -= 3 * (get_skill(SKILL_THAUMATURGY) - rspell->level); - - /* Reduce failure rate by INT/WIS adjustment */ - chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[A_INT]] - 1); - - /* Not enough mana to cast */ - if (rspell->mana > p_ptr->csp) - { - chance += 5 * (rspell->mana - p_ptr->csp); - } - - /* Extract the minimum failure rate */ - minfail = adj_mag_fail[p_ptr->stat_ind[A_INT]]; - - /* Failure rate */ - return clamp_failure_chance(chance, minfail); -} - - - - -/* - * Print a batch of spells. - */ -static void print_spell_batch(int batch, int max) -{ - char buff[80]; - - random_spell* rspell; - - int i; - - - prt(format(" %-30s Lev Fail Mana Damage ", "Name"), 1, 20); - - for (i = 0; i < max; i++) - { - rspell = &random_spells[batch * 10 + i]; - - if (rspell->untried) - { - strnfmt(buff, 80, " %c) %-30s (Spell untried) ", - I2A(i), rspell->name); - - } - else - { - strnfmt(buff, 80, " %c) %-30s %3d %4d%% %3d %3dd%d ", - I2A(i), rspell->name, - rspell->level, spell_chance_random(rspell), rspell->mana, - rspell->dam_dice, rspell->dam_sides); - } - - prt(buff, 2 + i, 20); - } - - prt("", 2 + i, 20); -} - - - -/* - * List ten random spells and ask to pick one. - */ -static random_spell* select_spell_from_batch(int batch) -{ - char tmp[160]; - - char out_val[30]; - - char which; - - int mut_max = 10; - - random_spell* ret; - - - /* Enter "icky" mode */ - character_icky = TRUE; - - /* Save the screen */ - Term_save(); - - if (spell_num < (batch + 1) * 10) - { - mut_max = spell_num - batch * 10; - } - - strnfmt(tmp, 160, "(a-%c, A-%cto browse, / to rename, - to comment) Select a power: ", - I2A(mut_max - 1), I2A(mut_max - 1) - 'a' + 'A'); - - prt(tmp, 0, 0); - - while (1) - { - /* Print power list */ - print_spell_batch(batch, mut_max); - - /* Get a command */ - which = inkey(); - - /* Abort */ - if (which == ESCAPE) - { - /* No selection */ - ret = NULL; - - /* Leave the command loop */ - break; - - } - - /* Accept default */ - if (which == '\r') - { - /* There are no other choices */ - if (mut_max == 1) - { - ret = &random_spells[batch * 10]; - - /* Leave the command loop */ - break; - } - - /* Wait for next command */ - continue; - } - - /* Rename */ - if (which == '/') - { - prt("Rename which power: ", 0, 0); - which = tolower(inkey()); - - if (isalpha(which) && (A2I(which) <= mut_max)) - { - strcpy(out_val, random_spells[batch*10 + A2I(which)].name); - if (get_string("Name this power: ", out_val, 29)) - { - strcpy(random_spells[batch*10 + A2I(which)].name, out_val); - } - prt(tmp, 0, 0); - } - else - { - bell(); - prt(tmp, 0, 0); - } - - /* Wait for next command */ - continue; - } - - /* Comment */ - if (which == '-') - { - prt("Comment which power: ", 0, 0); - which = tolower(inkey()); - - if (isalpha(which) && (A2I(which) <= mut_max)) - { - strcpy(out_val, random_spells[batch*10 + A2I(which)].desc); - if (get_string("Comment this power: ", out_val, 29)) - { - strcpy(random_spells[batch*10 + A2I(which)].desc, out_val); - } - prt(tmp, 0, 0); - } - else - { - bell(); - prt(tmp, 0, 0); - } - - /* Wait for next command */ - continue; - } - - if (isalpha(which) && isupper(which)) - { - which = tolower(which); - c_prt(TERM_L_BLUE, format("%s : %s", random_spells[batch*10 + A2I(which)].name, random_spells[batch*10 + A2I(which)].desc), 0, 0); - inkey(); - prt(tmp, 0, 0); - continue; - } - else if (isalpha(which) && (A2I(which) < mut_max)) - { - /* Pick the power */ - ret = &random_spells[batch * 10 + A2I(which)]; - - /* Leave the command loop */ - break; - } - else - { - bell(); - } - } - - /* Restore the screen */ - Term_load(); - - /* Leave "icky" mode */ - character_icky = FALSE; - - /* Return selection */ - return (ret); -} - - -/* - * Pick a random spell from a menu - */ -static random_spell* select_spell() -{ - char tmp[160]; - - char which; - - int batch_max = (spell_num - 1) / 10; - - random_spell *ret; - - - /* Too confused */ - if (p_ptr->confused) - { - msg_print("You can't use your powers while confused!"); - return NULL; - } - - /* No spells available */ - if (spell_num == 0) - { - msg_print("There are no spells you can cast."); - return NULL; - } - - /* Enter "icky" mode */ - character_icky = TRUE; - - /* Save the screen */ - Term_save(); - - strnfmt(tmp, 160, "(a-%c) Select batch of powers: ", I2A(batch_max)); - - prt(tmp, 0, 0); - - while (1) - { - which = inkey(); - - if (which == ESCAPE) - { - Term_load(); - - ret = NULL; - - break; - } - - if (which == '\r') - { - if (batch_max == 0) - { - Term_load(); - - ret = select_spell_from_batch(0); - - break; - } - - continue; - } - - which = tolower(which); - if (isalpha(which) && (A2I(which) <= batch_max)) - { - Term_load(); - - ret = select_spell_from_batch(A2I(which)); - - break; - } - else - { - bell(); - } - } - - /* Leave "icky" mode */ - character_icky = FALSE; - - return (ret); -} - - -void do_cmd_powermage(void) -{ - random_spell *s_ptr; - - u32b proj_flags; - - int dir, chance; - - int ty = 0, tx = 0; - - - /* No magic */ - if (p_ptr->antimagic) - { - msg_print("Your anti-magic field disrupts any magic attempts."); - return; - } - - /* No magic */ - if (p_ptr->anti_magic) - { - msg_print("Your anti-magic shell disrupts any magic attempts."); - return; - } - - - s_ptr = select_spell(); - - if (s_ptr == NULL) return; - - if (p_ptr->csp < s_ptr->mana) - { - msg_print("You do not have enough mana."); - return; - } - - /* Spell failure chance */ - chance = spell_chance_random(s_ptr); - - /* Failed spell */ - if (rand_int(100) < chance) - { - int insanity = (p_ptr->msane - p_ptr->csane) * 100 / p_ptr->msane; - char sfail[80]; - - /* Flush input if told so */ - if (flush_failure) flush(); - - /* Insane players can see something strange */ - if (rand_int(100) < insanity) - { - get_rnd_line("sfail.txt", sfail); - msg_format("A cloud of %s appears above you.", sfail); - } - - /* Normal failure messages */ - else - { - msg_print("You failed to get the spell off!"); - } - - sound(SOUND_FAIL); - - /* Let time pass */ - if (is_magestaff()) energy_use = 80; - else energy_use = 100; - - /* Mana is spent anyway */ - p_ptr->csp -= s_ptr->mana; - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - p_ptr->redraw |= (PR_MANA); - - return; - } - - - p_ptr->csp -= s_ptr->mana; - - s_ptr->untried = FALSE; - proj_flags = s_ptr->proj_flags; - - /* Hack -- Spell needs a target */ - if ((s_ptr->proj_flags & PROJECT_BEAM) || - (s_ptr->proj_flags & PROJECT_STOP)) - { - if (!get_aim_dir(&dir)) return; - - /* Hack -- Use an actual "target" */ - if ((dir == 5) && target_okay()) - { - tx = target_col; - ty = target_row; - - /* Mega-Hack -- Beam spells should continue through - * the target; bolt spells should stop at the - * target. --dsb */ - if (s_ptr->proj_flags & PROJECT_BEAM) - proj_flags |= PROJECT_THRU; - } - else - { - /* Use the given direction */ - ty = p_ptr->py + ddy[dir]; - tx = p_ptr->px + ddx[dir]; - - /* Mega-Hack -- Both beam and bolt spells should - * continue through this fake target. --dsb */ - proj_flags |= PROJECT_THRU; - } - } - - if (s_ptr->proj_flags & PROJECT_BLAST) - { - ty = p_ptr->py; - tx = p_ptr->px; - } - - if (s_ptr->proj_flags & PROJECT_VIEWABLE) - { - project_hack(s_ptr->GF, damroll(s_ptr->dam_dice, s_ptr->dam_sides)); - } - else if (s_ptr->proj_flags & PROJECT_METEOR_SHOWER) - { - project_meteor(s_ptr->radius, s_ptr->GF, - damroll(s_ptr->dam_dice, s_ptr->dam_sides), - s_ptr->proj_flags); - } - else - { - project(0, s_ptr->radius, ty, tx, - damroll(s_ptr->dam_dice, s_ptr->dam_sides), - s_ptr->GF, proj_flags); - } - - /* Take a turn */ - if (is_magestaff()) energy_use = 80; - else energy_use = 100; - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - p_ptr->redraw |= (PR_MANA); -} - - -/* - * Brand some ammunition. Used by Cubragol and a mage spell. The spell was - * moved here from cmd6.c where it used to be for Cubragol only. I've also - * expanded it to do either frost, fire or venom, at random. -GJW -KMW- - */ -void brand_ammo(int brand_type, int bolts_only) -{ - int a; - - for (a = 0; a < INVEN_PACK; a++) - { - object_type *o_ptr = &p_ptr->inventory[a]; - - if (bolts_only && (o_ptr->tval != TV_BOLT)) continue; - - if (!bolts_only && (o_ptr->tval != TV_BOLT) && - (o_ptr->tval != TV_ARROW) && (o_ptr->tval != TV_SHOT)) - continue; - - if (!artifact_p(o_ptr) && !ego_item_p(o_ptr) && - !cursed_p(o_ptr)) - break; - } - - /* Enchant the ammo (or fail) */ - if ((a < INVEN_PACK) && (rand_int(100) < 50)) - { - object_type *o_ptr = &p_ptr->inventory[a]; - const char *ammo_name; - const char *aura_name; - char msg[48]; - int aura_type, r; - - /* fire only */ - if (brand_type == 1) r = 0; - - /* cold only */ - else if (brand_type == 2) r = 99; - - /* No bias */ - else r = rand_int(100); - - if (r < 50) - { - aura_name = "fiery"; - aura_type = EGO_FLAME; - } - else - { - aura_name = "frosty"; - aura_type = EGO_FROST; - } - - if (o_ptr->tval == TV_BOLT) - { - ammo_name = "bolts"; - } - else if (o_ptr->tval == TV_ARROW) - { - ammo_name = "arrows"; - } - else - { - ammo_name = "shots"; - } - - strnfmt(msg, 48, "Your %s are covered in a %s aura!", - ammo_name, aura_name); - msg_print(msg); - - o_ptr->name2 = aura_type; - - /* Apply the ego */ - apply_magic(o_ptr, dun_level, FALSE, FALSE, FALSE); - o_ptr->discount = 100; - - enchant(o_ptr, rand_int(3) + 4, ENCH_TOHIT | ENCH_TODAM); - } - else - { - if (flush_failure) flush(); - msg_print("The enchantment failed."); - } -} - - -/* - * From Kamband by Ivan Tkatchev - */ -void summon_monster(int sumtype) -{ - /* Take a turn */ - energy_use = 100; - - if (p_ptr->inside_arena) - { - msg_print("This place seems devoid of life."); - msg_print(NULL); - return; - } - - if (summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level + randint(5), sumtype, TRUE)) - { - msg_print("You summon some help."); - } - else - { - msg_print("You called, but no help came."); - } -} - - - -/* - * Use a class power of Possessor - */ -void do_cmd_possessor() -{ - char ch, ext; - - - /* No magic */ - if (p_ptr->antimagic) - { - msg_print("Your anti-magic field disrupts any magic attempts."); - return; - } - - /* No magic */ - if (p_ptr->anti_magic) - { - msg_print("Your anti-magic shell disrupts any magic attempts."); - return; - } - - - while (TRUE) - { - if (!get_com("Use your [R]ace powers or your [I]ncarnating powers?", &ch)) - { - ext = 0; - break; - } - if ((ch == 'R') || (ch == 'r')) - { - ext = 1; - break; - } - if ((ch == 'I') || (ch == 'i')) - { - ext = 2; - break; - } - } - - if (ext == 1) - { - bool_ use_great = FALSE; - - if (p_ptr->disembodied) - { - msg_print("You don't currently own a body to use."); - return; - } - - /* Do we have access to all the powers ? */ - if (get_skill_scale(SKILL_POSSESSION, 100) >= r_info[p_ptr->body_monster].level) - use_great = TRUE; - - use_symbiotic_power(p_ptr->body_monster, use_great, FALSE, FALSE); - - if (p_ptr->csp < 0) - { - msg_print("You lose control of your body!"); - if (!do_cmd_leave_body(FALSE)) - { - cmsg_print(TERM_VIOLET, - "You are forced back into your body by your cursed items, " - "you suffer a system shock!"); - - p_ptr->chp = 1; - - /* Display the hitpoints */ - p_ptr->redraw |= (PR_HP); - } - } - } - else if (ext == 2) - { - if (p_ptr->disembodied) - { - do_cmd_integrate_body(); - } - else - { - do_cmd_leave_body(TRUE); - } - } - else - { - return; - } - - /* Take a turn */ - energy_use = 100; -} - - -/* - * Hook to determine if an object is contertible in an arrow/bolt - */ -static bool_ item_tester_hook_convertible(object_type *o_ptr) -{ - if ((o_ptr->tval == TV_JUNK) || (o_ptr->tval == TV_SKELETON)) return TRUE; - - /* Assume not */ - return (FALSE); -} - - -/* - * do_cmd_cast calls this function if the player's class - * is 'archer'. - */ -void do_cmd_archer(void) -{ - int ext = 0; - char ch; - - object_type forge; - object_type *q_ptr; - - char com[80]; - - - if (p_ptr->confused) - { - msg_print("You are too confused!"); - return; - } - - if (p_ptr->blind) - { - msg_print("You are blind!"); - return; - } - - - if (get_skill(SKILL_ARCHERY) >= 20) - { - strnfmt(com, 80, "Create [S]hots, [A]rrows or [B]olts? "); - } - else if (get_skill(SKILL_ARCHERY) >= 10) - { - strnfmt(com, 80, "Create [S]hots or [A]rrows? "); - } - else - { - strnfmt(com, 80, "Create [S]hots? "); - } - - while (TRUE) - { - if (!get_com(com, &ch)) - { - ext = 0; - break; - } - if ((ch == 'S') || (ch == 's')) - { - ext = 1; - break; - } - if (((ch == 'A') || (ch == 'a')) && (get_skill(SKILL_ARCHERY) >= 10)) - { - ext = 2; - break; - } - if (((ch == 'B') || (ch == 'b')) && (get_skill(SKILL_ARCHERY) >= 20)) - { - ext = 3; - break; - } - } - - /* Prepare for object creation */ - q_ptr = &forge; - - /**********Create shots*********/ - if (ext == 1) - { - int x, y, dir; - cave_type *c_ptr; - - if (!get_rep_dir(&dir)) return; - y = p_ptr->py + ddy[dir]; - x = p_ptr->px + ddx[dir]; - c_ptr = &cave[y][x]; - if (c_ptr->feat == FEAT_RUBBLE) - { - /* Get local object */ - q_ptr = &forge; - - /* Hack -- Give the player some shots */ - object_prep(q_ptr, lookup_kind(TV_SHOT, m_bonus(2, dun_level))); - if (!artifact_p(q_ptr)) - q_ptr->number = (byte)rand_range(15, 30); - else - q_ptr->number = 1; - object_aware(q_ptr); - object_known(q_ptr); - q_ptr->ident |= IDENT_MENTAL; - apply_magic(q_ptr, dun_level, TRUE, TRUE, (magik(20)) ? TRUE : FALSE); - q_ptr->discount = 90; - q_ptr->found = OBJ_FOUND_SELFMADE; - - (void)inven_carry(q_ptr, FALSE); - - msg_print("You make some ammo."); - - (void)wall_to_mud(dir); - p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE); - p_ptr->window |= (PW_OVERHEAD); - } - } - - /**********Create arrows*********/ - else if (ext == 2) - { - int item; - - cptr q, s; - - item_tester_hook = item_tester_hook_convertible; - - /* Get an item */ - q = "Convert which item? "; - s = "You have no item to convert."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - /* Get local object */ - q_ptr = &forge; - - /* Hack -- Give the player some arrows */ - object_prep(q_ptr, lookup_kind(TV_ARROW, m_bonus(1, dun_level) + 1)); - q_ptr->number = (byte)rand_range(15, 25); - if (!artifact_p(q_ptr)) - q_ptr->number = (byte)rand_range(15, 30); - else - q_ptr->number = 1; - object_aware(q_ptr); - object_known(q_ptr); - q_ptr->ident |= IDENT_MENTAL; - apply_magic(q_ptr, dun_level, TRUE, TRUE, (magik(20)) ? TRUE : FALSE); - q_ptr->discount = 90; - q_ptr->found = OBJ_FOUND_SELFMADE; - - msg_print("You make some ammo."); - - inc_stack_size(item, -1); - - (void)inven_carry(q_ptr, FALSE); - } - - /**********Create bolts*********/ - else if (ext == 3) - { - int item; - - cptr q, s; - - item_tester_hook = item_tester_hook_convertible; - - /* Get an item */ - q = "Convert which item? "; - s = "You have no item to convert."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - /* Get local object */ - q_ptr = &forge; - - /* Hack -- Give the player some bolts */ - object_prep(q_ptr, lookup_kind(TV_BOLT, m_bonus(1, dun_level) + 1)); - q_ptr->number = (byte)rand_range(15, 25); - if (!artifact_p(q_ptr)) - q_ptr->number = (byte)rand_range(15, 30); - else - q_ptr->number = 1; - object_aware(q_ptr); - object_known(q_ptr); - q_ptr->ident |= IDENT_MENTAL; - apply_magic(q_ptr, dun_level, TRUE, TRUE, (magik(20)) ? TRUE : FALSE); - q_ptr->discount = 90; - q_ptr->found = OBJ_FOUND_SELFMADE; - - msg_print("You make some ammo."); - - inc_stack_size(item, -1); - - (void)inven_carry(q_ptr, FALSE); - } -} - -/* - * Control whether shots are allowed to pierce - */ -void do_cmd_set_piercing(void) -{ - char ch; - char com[80]; - - if ((get_skill(SKILL_BOW) <= 25) && (get_skill(SKILL_XBOW) <= 25) && - (get_skill(SKILL_SLING) <= 25)) - { - msg_print("You can't fire piercing shots yet."); - return; - } - - strnfmt(com, 80, "Allow shots to pierce? "); - - while (TRUE) - { - if (!get_com(com, &ch)) - { - break; - } - if ((ch == 'Y') || (ch == 'y')) - { - p_ptr->use_piercing_shots = 1; - msg_print("Piercing shots activated."); - break; - } - if ((ch == 'N') || (ch == 'n')) - { - p_ptr->use_piercing_shots = 0; - msg_print("Piercing shots deactivated."); - break; - } - } -} -/* - * Helper function to describe necro powers - */ -void necro_info(char *p, int power) -{ - int plev = get_skill(SKILL_NECROMANCY); - - strcpy(p, ""); - - switch (power) - { - case 0: - { - if (p_ptr->to_s) - strnfmt(p, 80, " power %dd%d+%d", 2 + (plev * 2 / 3), 4, (p_ptr->to_s * 2)); - else - strnfmt(p, 80, " power %dd%d", 2 + (plev * 2 / 3), 4); - break; - } - case 2: - { - strnfmt(p, 80, " dur d%d+%d", 100 + (plev * 4), 200 + (plev * 3)); - break; - } - case 3: - { - strnfmt(p, 80, " dur d%d+%d", 30 + (plev * 2), 50 + plev); - break; - } - } -} - - -/* - * Cast a Necromancy spell - */ -void do_cmd_necromancer(void) -{ - int n = 0, b = 0; - int chance; - int dir; - int minfail = 0; - int plev = get_skill(SKILL_NECROMANCY); - magic_power spell; - int to_s2 = p_ptr->to_s / 2; - int mto_s2 = p_ptr->to_s / 2; - - - if (mto_s2 == 0) mto_s2 = 1; - - /* No magic */ - if (p_ptr->antimagic) - { - msg_print("Your anti-magic field disrupts any magic attempts."); - return; - } - - /* No magic */ - if (p_ptr->anti_magic) - { - msg_print("Your anti-magic shell disrupts any magic attempts."); - return; - } - - /* not if confused */ - if (p_ptr->confused) - { - msg_print("You are too confused!"); - return; - } - - /* get power */ - if (!get_magic_power(&n, necro_powers, MAX_NECRO_POWERS, necro_info, - get_skill(SKILL_NECROMANCY), A_CON)) return; - - spell = necro_powers[n]; - - /* Verify "dangerous" spells */ - if (spell.mana_cost > p_ptr->csp) - { - /* Warning */ - msg_print("You do not have enough mana to use this power."); - - /* Verify */ - if (!get_check("Attempt it anyway? ")) return; - } - - /* Spell failure chance */ - chance = spell.fail; - - /* Reduce failure rate by "effective" level adjustment */ - chance -= 3 * (plev - spell.min_lev); - - /* Reduce failure rate by INT/WIS adjustment */ - chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[A_CON]] - 1); - - /* Not enough mana to cast */ - if (spell.mana_cost > p_ptr->csp) - { - chance += 5 * (spell.mana_cost - p_ptr->csp); - } - - /* Extract the minimum failure rate */ - minfail = adj_mag_fail[p_ptr->stat_ind[A_CON]]; - - /* Failure rate */ - chance = clamp_failure_chance(chance, minfail); - - /* Failed spell */ - if (rand_int(100) < chance) - { - if (flush_failure) flush(); - msg_format("You failed to concentrate hard enough!"); - sound(SOUND_FAIL); - - if (randint(100) < (chance / 2)) - { - /* Backfire */ - b = randint(100); - if (b < 10) - { - msg_print("Oh, no! You become undead!"); - - p_ptr->necro_extra |= CLASS_UNDEAD; - p_ptr->necro_extra2 = 2 * plev; - msg_format("You have to kill %d monster%s to be brought back to life.", - p_ptr->necro_extra2, - (p_ptr->necro_extra2 == 1) ? "" : "s"); - - /* MEGA-HACK !!! */ - calc_hitpoints(); - - /* Enforce maximum */ - p_ptr->chp = p_ptr->mhp; - p_ptr->chp_frac = 0; - - /* Display the hitpoints */ - p_ptr->redraw |= (PR_HP); - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - } - else if (b < 40) - { - msg_print("Suddenly you feel that you're in a bad situation..."); - summon_specific(p_ptr->py, p_ptr->px, max_dlv[dungeon_type], - (plev >= 30) ? SUMMON_HI_UNDEAD : SUMMON_UNDEAD); - } - else - { - msg_print("Your body is damaged by the horrible forces of the spell!"); - take_hit(damroll(5, plev), "using necromancy unwisely"); - } - } - } - else - { - sound(SOUND_ZAP); - - /* spell code */ - switch (n) - { - /* Horrify */ - case 0: - { - int dam = damroll(2 + (plev * 2 / 3), 4) + (p_ptr->to_s * 2); - - if (plev > 45) - { - project_hack(GF_STUN, dam); - project_hack(GF_TURN_ALL, dam); - } - else if (plev > 35) - { - if (!get_aim_dir(&dir)) return; - fire_ball(GF_STUN, dir, dam, 3 + (plev / 10)); - fire_ball(GF_TURN_ALL, dir, dam, 3 + (plev / 10)); - } - else if (plev > 20) - { - if (!get_aim_dir(&dir)) return; - fire_beam(GF_STUN, dir, dam); - fire_beam(GF_TURN_ALL, dir, dam); - } - else - { - if (!get_aim_dir(&dir)) return; - fire_bolt(GF_STUN, dir, dam); - fire_bolt(GF_TURN_ALL, dir, dam); - } - - break; - } - - /* Raise Death */ - case 1: - { - fire_ball(GF_RAISE, 0, plev * 3, 1 + to_s2 + (plev / 10)); - - break; - } - - /* Conjures temporary weapon */ - case 2: - { - int dur = randint(100 + (plev * 4)) + 200 + (plev * 3); - object_type forge, *o_ptr = &forge; - int k_idx = test_item_name("& Necromantic Teeth~"); - - k_allow_special[k_idx] = TRUE; - - object_prep(o_ptr, k_idx); - apply_magic(o_ptr, plev * 2, TRUE, TRUE, TRUE); - - o_ptr->art_flags5 |= TR5_TEMPORARY; - o_ptr->timeout = dur; - - /* These objects are "storebought" */ - o_ptr->ident |= IDENT_MENTAL; - o_ptr->number = 1; - - object_aware(o_ptr); - object_known(o_ptr); - (void)inven_carry(o_ptr, FALSE); - - k_allow_special[k_idx] = FALSE; - - break; - } - - /* Absorb souls */ - case 3: - { - set_absorb_soul(randint(30 + (plev * 2)) + 50 + plev); - break; - } - - /* Vampirism */ - case 4: - { - int i; - if (!get_aim_dir(&dir)) return; - for (i = 0; i < 1 + to_s2 + (plev / 15); i++) - { - if (drain_life(dir, 100)) - hp_player(100); - } - - break; - } - - /* Death */ - case 5: - { - if (get_check("Using the Death word will leave you undead, with 1 DP. Do you *really* want to use it? ")) - { - if (!get_aim_dir(&dir)) return; - fire_bolt(GF_DEATH, dir, 1); - - p_ptr->necro_extra |= CLASS_UNDEAD; - p_ptr->necro_extra2 = plev + (rand_int(plev / 2) - (plev / 4)); - msg_format("You have to kill %d monster%s to be brought back to life.", p_ptr->necro_extra2, (p_ptr->necro_extra2 == 1) ? "" : "s"); - - /* MEGA-HACK !!! */ - calc_hitpoints(); - - /* Enforce 1 DP */ - p_ptr->chp = p_ptr->mhp; - p_ptr->chp_frac = 0; - - /* Display the hitpoints */ - p_ptr->redraw |= (PR_HP); - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - } - - break; - } - - default: - { - msg_print("Zap?"); - - break; - } - } - } - - /* Take a turn */ - if (is_magestaff()) energy_use = 80; - else energy_use = 100; - - /* Sufficient mana */ - if (spell.mana_cost <= p_ptr->csp) - { - /* Use some mana */ - p_ptr->csp -= spell.mana_cost; - } - - /* Over-exert the player */ - else - { - int oops = spell.mana_cost - p_ptr->csp; - - /* No mana left */ - p_ptr->csp = 0; - p_ptr->csp_frac = 0; - - /* Message */ - msg_print("You faint from the effort!"); - - /* Hack -- Bypass free action */ - (void)set_paralyzed(randint(5 * oops + 1)); - - /* Damage CON (possibly permanently) */ - if (rand_int(100) < 50) - { - bool_ perm = (rand_int(100) < 25); - - /* Message */ - msg_print("You have damaged your body!"); - - /* Reduce constitution */ - (void)dec_stat(A_CON, 15 + randint(10), perm); - } - } - - /* Redraw mana */ - p_ptr->redraw |= (PR_MANA); - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); -} - -/* Runecrafters -- Move this into variable.c XXX XXX XXX */ -static s32b rune_combine = 0; - -/* - * Hook to determine if an object is "runestone" - */ -static bool_ item_tester_hook_runestone(object_type *o_ptr) -{ - if (o_ptr->tval != TV_RUNE2) return (FALSE); - - if (o_ptr->sval != RUNE_STONE) return (FALSE); - - if (o_ptr->pval != 0) return (FALSE); - - /* Assume yes */ - return (TRUE); -} - - -static bool_ item_tester_hook_runestone_full(object_type *o_ptr) -{ - if (o_ptr->tval != TV_RUNE2) return (FALSE); - - if (o_ptr->sval != RUNE_STONE) return (FALSE); - - if (o_ptr->pval == 0) return (FALSE); - - /* Assume yes */ - return (TRUE); -} - - -/* - * Hook to determine if an object is "rune-able" - */ -static bool_ item_tester_hook_runeable1(object_type *o_ptr) -{ - if (o_ptr->tval != TV_RUNE1) return (FALSE); - - /* Assume yes */ - return (TRUE); -} - - -/* - * Hook to determine if an object is "rune-able" - */ -static bool_ item_tester_hook_runeable2(object_type *o_ptr) -{ - if (o_ptr->tval != TV_RUNE2) return (FALSE); - - if (o_ptr->sval == RUNE_STONE) return (FALSE); - - if (rune_combine & BIT(o_ptr->sval)) return (FALSE); - - /* Assume yes */ - return (TRUE); -} - - -/* - * math.h(sqrt) is banned of angband so ... :) - */ -s32b sroot(s32b n) -{ - s32b i = n / 2; - - if (n < 2) return (n); - - while (1) - { - s32b err = (i - n / (i + 1)) / 2; - - if (!err) break; - - i -= err; - } - - return ((n / i < i) ? (i - 1) : i); -} - - -/* - * Damage formula, for runes - */ -void rune_calc_power(s32b *power, s32b *powerdiv) -{ - /* Not too weak power(paranoia) */ - *power = (*power < 1) ? 1 : *power; - *power += 3; - - *power = 37 * sroot(*power) / 10; - - /* To reduce the high level power, while increasing the low levels */ - *powerdiv = *power / 3; - if (*powerdiv < 1) *powerdiv = 1; - - /* Use the spell multiplicator */ - *power *= (p_ptr->to_s / 2) ? (p_ptr->to_s / 2) : 1; -} - - -/* - * Return percentage chance of runespell failure. - */ -int spell_chance_rune(rune_spell* spell) -{ - int chance, minfail; - - s32b power = spell->mana, power_rune = 0, powerdiv = 0; - - - if (spell->rune2 & RUNE_POWER_SURGE) - { - power_rune += 4; - } - if (spell->rune2 & RUNE_ARMAGEDDON) - { - power_rune += 3; - } - if (spell->rune2 & RUNE_SPHERE) - { - power_rune += 2; - } - if (spell->rune2 & RUNE_RAY) - { - power_rune += 1; - } - - rune_calc_power(&power, &powerdiv); - - chance = (5 * power_rune) + (power); - - /* Reduce failure rate by INT/WIS adjustment */ - chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[A_DEX]] - 1); - - /* Extract the minimum failure rate */ - minfail = adj_mag_fail[p_ptr->stat_ind[A_DEX]]; - - /* Return the chance */ - return clamp_failure_chance(chance, minfail); -} - - -/* - * Combine the Runes - */ -int rune_exec(rune_spell *spell, int cost) -{ - int dir, power_rune = 0, mana_used, plev = get_skill(SKILL_RUNECRAFT); - - int chance; - - s32b power, powerdiv; - - int rad = 0, ty = -1, tx = -1, dam = 0, flg = 0; - - - if (spell->rune2 & RUNE_POWER_SURGE) - { - power_rune += 4; - } - if (spell->rune2 & RUNE_ARMAGEDDON) - { - power_rune += 3; - } - if (spell->rune2 & RUNE_SPHERE) - { - power_rune += 2; - } - if (spell->rune2 & RUNE_RAY) - { - power_rune += 1; - } - - - power = spell->mana; - - if (cost && ((power * cost / 100) > p_ptr->csp - (power_rune * (plev / 5)))) - { - power = p_ptr->csp - (power_rune * (plev / 5)); - mana_used = power + (power_rune * (plev / 5)); - } - else - { - mana_used = (power * cost / 100) + (power_rune * (plev / 5)); - } - - rune_calc_power(&power, &powerdiv); - - dam = damroll(powerdiv, power); - - if (wizard) msg_format("Rune %dd%d = dam %d", powerdiv, power, dam); - - /* Extract the base spell failure rate */ - chance = spell_chance_rune(spell); - - /* Failure ? */ - if (rand_int(100) < chance) - { - int insanity = (p_ptr->msane - p_ptr->csane) * 100 / p_ptr->msane; - char sfail[80]; - - /* Flush input if told so */ - if (flush_failure) flush(); - - /* Insane players can see something strange */ - if (rand_int(100) < insanity) - { - get_rnd_line("sfail.txt", sfail); - msg_format("A cloud of %s appears above you.", sfail); - } - - /* Normal failure messages */ - else - { - msg_print("You failed to get the spell off!"); - } - - sound(SOUND_FAIL); - - if (is_magestaff()) energy_use = 80; - else energy_use = 100; - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - p_ptr->redraw |= (PR_MANA); - return (mana_used); - } - - if (spell->rune2 & RUNE_POWER_SURGE) - { - flg |= (PROJECT_VIEWABLE); - ty = p_ptr->py; - tx = p_ptr->px; - } - - if (spell->rune2 & RUNE_ARMAGEDDON) - { - flg |= (PROJECT_THRU); - flg |= (PROJECT_KILL); - flg |= (PROJECT_ITEM); - flg |= (PROJECT_GRID); - flg |= (PROJECT_METEOR_SHOWER); - rad = (power / 8 == 0) ? 1 : power / 8; - rad = (rad > 10) ? 10 : rad; - ty = p_ptr->py; - tx = p_ptr->px; - } - - if (spell->rune2 & RUNE_SPHERE) - { - flg |= (PROJECT_THRU); - flg |= (PROJECT_KILL); - flg |= (PROJECT_ITEM); - flg |= (PROJECT_GRID); - rad = (power / 8 == 0) ? 1 : power / 8; - rad = (rad > 10) ? 10 : rad; - ty = p_ptr->py; - tx = p_ptr->px; - } - - if (spell->rune2 & RUNE_RAY) - { - flg |= (PROJECT_THRU); - flg |= (PROJECT_KILL); - flg |= (PROJECT_BEAM); - ty = -1; - tx = -1; - } - if (spell->rune2 & RUNE_ARROW) - { - flg |= (PROJECT_THRU); - flg |= (PROJECT_STOP); - flg |= (PROJECT_KILL); - ty = -1; - tx = -1; - } - if (spell->rune2 & RUNE_SELF) - { - flg |= (PROJECT_THRU); - flg |= (PROJECT_STOP); - flg |= (PROJECT_KILL); - ty = p_ptr->py; - tx = p_ptr->px; - unsafe = TRUE; - } - - if ((ty == -1) && (tx == -1)) - { - if (!get_aim_dir(&dir)) return (mana_used); - - /* Use the given direction */ - tx = p_ptr->px + ddx[dir]; - ty = p_ptr->py + ddy[dir]; - - /* Hack -- Use an actual "target" */ - if ((dir == 5) && target_okay()) - { - tx = target_col; - ty = target_row; - } - } - - if (flg & PROJECT_VIEWABLE) - { - project_hack(spell->type, dam); - } - else if (flg & PROJECT_METEOR_SHOWER) - { - project_meteor(rad, spell->type, dam, flg); - } - else project(0, rad, ty, tx, dam, spell->type, flg); - - if (unsafe) unsafe = FALSE; - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - p_ptr->redraw |= (PR_MANA); - - return (mana_used); -} - - -/* - * Test if all runes needed at in the player p_ptr->inventory - */ -bool_ test_runespell(rune_spell *spell) -{ - int i; - - object_type *o_ptr; - - bool_ typeok = FALSE; - - int rune2 = 0; - - - for (i = 0; i < INVEN_WIELD; i++) - { - o_ptr = &p_ptr->inventory[i]; - - if (!o_ptr->k_idx) continue; - - /* Does the rune1(type) match ? */ - if ((o_ptr->tval == TV_RUNE1) && (o_ptr->sval == spell->type)) - { - typeok = TRUE; - } - - if ((o_ptr->tval == TV_RUNE2) && (o_ptr->sval != RUNE_STONE)) - { - /* Add it to the list */ - rune2 |= 1 << o_ptr->sval; - } - } - - /* Need all runes to be present */ - return (typeok && ((rune2 & spell->rune2) == spell->rune2)); -} - - -/* - * Ask for rune, rune2 and mana - */ -bool_ get_runespell(rune_spell *spell) -{ - int item, power_rune = 0, rune2 = 0, plev = get_skill(SKILL_RUNECRAFT); - - s32b power; - - int type = 0; - - object_type *o_ptr; - - cptr q, s; - - bool_ OK = FALSE; - - - rune_combine = 0; - - /* Restrict choices to unused runes */ - item_tester_hook = item_tester_hook_runeable1; - - /* Get an item */ - q = "Use which rune? "; - s = "You have no rune to use."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return FALSE; - - /* Get the item */ - o_ptr = get_object(item); - type = o_ptr->sval; - - while (1) - { - /* Restrict choices to unused secondary runes */ - item_tester_hook = item_tester_hook_runeable2; - - OK = !get_item(&item, q, s, (USE_INVEN | USE_FLOOR)); - - if (OK) break; - - /* Get the item */ - o_ptr = get_object(item); - - rune_combine |= 1 << o_ptr->sval; - rune2 |= 1 << o_ptr->sval; - } - - if (!rune2) - { - msg_print("You have not selected a second rune!"); - return (FALSE); - } - - power = get_quantity("Which amount of Mana?", - p_ptr->csp - (power_rune * (plev / 5))); - if (power < 1) power = 1; - - spell->mana = power; - spell->type = type; - spell->rune2 = rune2; - - return (TRUE); -} - - -void do_cmd_rune(void) -{ - rune_spell spell; - - - /* Require some mana */ - if (p_ptr->csp <= 0) - { - msg_print("You have no mana!"); - return; - } - - /* Require lite */ - if (p_ptr->blind || no_lite()) - { - msg_print("You cannot see!"); - return; - } - - /* Not when confused */ - if (p_ptr->confused) - { - msg_print("You are too confused!"); - return; - } - - if (!get_runespell(&spell)) return; - - /* Execute at normal mana cost */ - p_ptr->csp -= rune_exec(&spell, 100); - - /* Safety :) */ - if (p_ptr->csp < 0) p_ptr->csp = 0; - - /* Take a turn */ - if (is_magestaff()) energy_use = 80; - else energy_use = 100; - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - p_ptr->redraw |= (PR_MANA); -} - - -/* - * Print a batch of runespells. - */ -static void print_runespell_batch(int batch, int max) -{ - char buff[80]; - - rune_spell* spell; - - int i; - - s32b power, powerdiv; - - int p, dp; - - - prt(format(" %-30s Fail Mana Power", "Name"), 1, 20); - - for (i = 0; i < max; i++) - { - spell = &rune_spells[batch * 10 + i]; - - power = spell->mana; - rune_calc_power(&power, &powerdiv); - p = power; - dp = powerdiv; - - strnfmt(buff, 80, " %c) %-30s %4d%% %4d %dd%d ", I2A(i), spell->name, - spell_chance_rune(spell), spell->mana, dp, p); - - prt(buff, 2 + i, 20); - } - prt("", 2 + i, 20); -} - - - -/* - * List ten random spells and ask to pick one. - */ - -static rune_spell* select_runespell_from_batch(int batch, int *s_idx) -{ - char tmp[160]; - - char out_val[30]; - - char which; - - int mut_max = 10; - - rune_spell* ret; - - - character_icky = TRUE; - - if (rune_num < (batch + 1) * 10) - { - mut_max = rune_num - batch * 10; - } - - strnfmt(tmp, 160, "(a-%c, * to list, / to rename, - to comment) Select a power: ", - I2A(mut_max - 1)); - - prt(tmp, 0, 0); - - while (1) - { - Term_save(); - - print_runespell_batch(batch, mut_max); - - which = inkey(); - - Term_load(); - - if (which == ESCAPE) - { - *s_idx = -1; - ret = NULL; - break; - } - else if ((which == '*') || (which == '?') || (which == ' ')) - { - print_runespell_batch(batch, mut_max); - } - else if ((which == '\r') && (mut_max == 1)) - { - *s_idx = batch * 10; - ret = &rune_spells[batch * 10]; - break; - } - else if (which == '/') - { - prt("Rename which power: ", 0, 0); - which = tolower(inkey()); - - if (isalpha(which) && (A2I(which) <= mut_max)) - { - strcpy(out_val, rune_spells[batch*10 + A2I(which)].name); - if (get_string("Name this power: ", out_val, 29)) - { - strcpy(rune_spells[batch*10 + A2I(which)].name, out_val); - } - prt(tmp, 0, 0); - } - else - { - bell(); - prt(tmp, 0, 0); - } - } - else - { - which = tolower(which); - if (isalpha(which) && (A2I(which) < mut_max)) - { - *s_idx = batch * 10 + A2I(which); - ret = &rune_spells[batch * 10 + A2I(which)]; - break; - } - else - { - bell(); - } - } - } - - character_icky = FALSE; - - return (ret); -} - - -/* - * Pick a random spell from a menu - */ - -rune_spell* select_runespell(int *s_idx) -{ - char tmp[160]; - - char which; - - int batch_max = (rune_num - 1) / 10; - - if (rune_num == 0) - { - msg_print("There are no runespells you can cast."); - return (NULL); - } - - character_icky = TRUE; - Term_save(); - - strnfmt(tmp, 160, "(a-%c) Select batch of powers: ", I2A(batch_max)); - - prt(tmp, 0, 0); - - while (1) - { - which = inkey(); - - if (which == ESCAPE) - { - Term_load(); - character_icky = FALSE; - return (NULL); - } - else if ((which == '\r') && (batch_max == 0)) - { - Term_load(); - character_icky = FALSE; - return (select_runespell_from_batch(0, s_idx)); - - } - else - { - which = tolower(which); - if (isalpha(which) && (A2I(which) <= batch_max)) - { - Term_load(); - character_icky = FALSE; - return (select_runespell_from_batch(A2I(which), s_idx)); - } - else - { - bell(); - } - } - } -} - - -/* - * Cast a memorized runespell - * Note that the only limits are antimagic & conf, NOT blind - */ -void do_cmd_rune_cast() -{ - rune_spell *s_ptr; - - int s_idx; - - - /* Require some mana */ - if (p_ptr->csp <= 0) - { - msg_print("You have no mana!"); - return; - } - - /* No magic */ - if (p_ptr->antimagic) - { - msg_print("Your anti-magic field disrupts any magic attempts."); - return; - } - - /* No magic */ - if (p_ptr->anti_magic) - { - msg_print("Your anti-magic shell disrupts any magic attempts."); - return; - } - - /* Not when confused */ - if (p_ptr->confused) - { - msg_print("You are too confused!"); - return; - } - - s_ptr = select_runespell(&s_idx); - - if (s_ptr == NULL) return; - - /* Need the runes */ - if (!test_runespell(s_ptr)) - { - msg_print("You lack some essential rune(s) for this runespell!"); - return; - } - - /* Execute at normal mana cost */ - p_ptr->csp -= rune_exec(s_ptr, 100); - - /* Safety :) */ - if (p_ptr->csp < 0) p_ptr->csp = 0; - - /* Take a turn */ - if (is_magestaff()) energy_use = 80; - else energy_use = 100; - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - p_ptr->redraw |= (PR_MANA); -} - - -/* - * Cast a runespell from a carved runestone - */ -void do_cmd_runestone() -{ - rune_spell s_ptr; - - object_type *o_ptr; - - cptr q, s; - - int item; - - - /* Require some mana */ - if (p_ptr->csp <= 0) - { - msg_print("You have no mana!"); - return; - } - - /* Require lite */ - if (p_ptr->blind || no_lite()) - { - msg_print("You cannot see!"); - return; - } - - /* Not when confused */ - if (p_ptr->confused) - { - msg_print("You are too confused!"); - return; - } - - /* No magic */ - if (p_ptr->antimagic) - { - msg_print("Your anti-magic field disrupts any magic attempts."); - return; - } - - /* No magic */ - if (p_ptr->anti_magic) - { - msg_print("Your anti-magic shell disrupts any magic attempts."); - return; - } - - /* Restrict choices to unused runes */ - item_tester_hook = item_tester_hook_runestone_full; - - /* Get an item */ - q = "Cast from which runestone? "; - s = "You have no runestone to cast from."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - /* Get the item */ - o_ptr = get_object(item); - - s_ptr.type = o_ptr->pval; - s_ptr.rune2 = o_ptr->pval2; - s_ptr.mana = o_ptr->pval3; - - /* Execute less mana */ - p_ptr->csp -= rune_exec(&s_ptr, 75); - - /* Safety :) */ - if (p_ptr->csp < 0) p_ptr->csp = 0; - - /* Take a turn */ - energy_use = 100; - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - p_ptr->redraw |= (PR_MANA); -} - - -/* - * Add a runespell to the list - */ -void do_cmd_rune_add_mem() -{ - rune_spell s_ptr; - - rune_spell *ds_ptr = &rune_spells[rune_num]; - - - /* Not when confused */ - if (p_ptr->confused) - { - msg_print("You are too confused!"); - return; - } - - - if (rune_num >= MAX_RUNES) - { - msg_print("You have already learn the maximun number of runespells!"); - return; - } - - if (!get_runespell(&s_ptr)) return; - - ds_ptr->type = s_ptr.type; - ds_ptr->rune2 = s_ptr.rune2; - ds_ptr->mana = s_ptr.mana; - strcpy(ds_ptr->name, "Unnamed Runespell"); - - get_string("Name this runespell: ", ds_ptr->name, 29); - - rune_num++; - - /* Take a turn */ - energy_use = 100; - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - p_ptr->redraw |= (PR_MANA); -} - - -/* - * Carve a runespell onto a Runestone - */ -void do_cmd_rune_carve() -{ - rune_spell s_ptr; - - object_type *o_ptr; - - cptr q, s; - - int item, i; - - char out_val[80]; - - - /* Not when confused */ - if (p_ptr->confused) - { - msg_print("You are too confused!"); - return; - } - - /* Require lite */ - if (p_ptr->blind || no_lite()) - { - msg_print("You cannot see!"); - return; - } - - if (!get_check("Beware, this will destroy the involved runes, continue?")) - { - return; - } - - if (!get_runespell(&s_ptr)) return; - - /* Restrict choices to unused runes */ - item_tester_hook = item_tester_hook_runestone; - - /* Get an item */ - q = "Use which runestone? "; - s = "You have no runestone to use."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - /* Get the item */ - o_ptr = get_object(item); - - o_ptr->pval = s_ptr.type; - o_ptr->pval2 = s_ptr.rune2; - o_ptr->pval3 = s_ptr.mana; - - /* Start with nothing */ - strcpy(out_val, ""); - - /* Use old inscription */ - if (o_ptr->note) - { - /* Start with the old inscription */ - strcpy(out_val, quark_str(o_ptr->note)); - } - - /* Get a new inscription (possibly empty) */ - if (get_string("Name this runestone: ", out_val, 80)) - { - /* Save the inscription */ - o_ptr->note = quark_add(out_val); - - /* Combine the pack */ - p_ptr->notice |= (PN_COMBINE); - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP); - } - - /* Delete the runes */ - for (i = 0; i < INVEN_WIELD; i++) - { - o_ptr = &p_ptr->inventory[i]; - - if (o_ptr->k_idx) - { - bool_ do_del = FALSE; - - if ((o_ptr->tval == TV_RUNE1) && (o_ptr->sval == s_ptr.type)) do_del = TRUE; - if ((o_ptr->tval == TV_RUNE2) && (BIT(o_ptr->sval) & s_ptr.rune2)) do_del = TRUE; - - if (do_del) - { - inc_stack_size_ex(i, -1, OPTIMIZE, NO_DESCRIBE); - } - } - } - - /* Take a turn -- Carving takes a LONG time */ - energy_use = 400; - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - p_ptr->redraw |= (PR_MANA); -} - - -/* - * Remove a runespell - */ -void do_cmd_rune_del() -{ - rune_spell *s_ptr; - - int s_idx; - - int i; - - - /* Not when confused */ - if (p_ptr->confused) - { - msg_print("You are too confused!"); - return; - } - - s_ptr = select_runespell(&s_idx); - - if (s_ptr == NULL) return; - - /* Delete and move */ - for (i = s_idx + 1; i < rune_num; i++) - { - rune_spells[i - 1].type = rune_spells[i].type; - rune_spells[i - 1].rune2 = rune_spells[i].rune2; - rune_spells[i - 1].mana = rune_spells[i].mana; - strcpy(rune_spells[i - 1].name, rune_spells[i].name); - } - rune_num--; - - /* Take a turn */ - energy_use = 100; - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - p_ptr->redraw |= (PR_MANA); -} - - -void do_cmd_rune_add() -{ - int ext = 0; - - char ch; - - - /* Select what to do */ - while (TRUE) - { - if (!get_com("Add to [M]emory(need runes to cast) or " - "Carve a [R]unestone(less mana to cast)", &ch)) - { - ext = 0; - break; - } - if ((ch == 'M') || (ch == 'm')) - { - ext = 1; - break; - } - if ((ch == 'R') || (ch == 'r')) - { - ext = 2; - break; - } - } - - switch (ext) - { - /* Create a Spell in memory */ - case 1: - { - do_cmd_rune_add_mem(); - break; - } - - /* Carve a Runestone */ - case 2: - { - do_cmd_rune_carve(); - break; - } - } -} - - -void do_cmd_runecrafter() -{ - int ext = 0; - - char ch; - - - /* Select what to do */ - while (TRUE) - { - if (!get_com("Rune Spell:[C]reate, [D]elete, C[a]st, D[i]rectly Cast " - "or Use [R]unestone", &ch)) - { - ext = 0; - break; - } - if ((ch == 'C') || (ch == 'c')) - { - ext = 1; - break; - } - if ((ch == 'D') || (ch == 'd')) - { - ext = 2; - break; - } - if ((ch == 'A') || (ch == 'a')) - { - ext = 3; - break; - } - if ((ch == 'I') || (ch == 'i')) - { - ext = 4; - break; - } - if ((ch == 'R') || (ch == 'r')) - { - ext = 5; - break; - } - } - - switch (ext) - { - /* Create a Spell */ - case 1: - { - do_cmd_rune_add(); - break; - } - - /* Delete a Spell */ - case 2: - { - do_cmd_rune_del(); - break; - } - - /* Cast a Spell */ - case 3: - { - do_cmd_rune_cast(); - break; - } - - /* Directly Cast a Spell */ - case 4: - { - do_cmd_rune(); - break; - } - - /* Cast a Runestone */ - case 5: - { - do_cmd_runestone(); - break; - } - } -} - - -void do_cmd_unbeliever_antimagic() -{ - if (get_skill(SKILL_ANTIMAGIC) < 20) - { - msg_print("You must have at least a level 20 antimagic skill " - "to be able to disrupt the magic continuum."); - return; - } - - if (p_ptr->antimagic_extra & CLASS_ANTIMAGIC) - { - p_ptr->antimagic_extra &= ~CLASS_ANTIMAGIC; - msg_print("You stop disrupting the magic continuum."); - } - else - { - p_ptr->antimagic_extra |= CLASS_ANTIMAGIC; - msg_print("You start disrupting the magic continuum."); - } - - /* Recalculate bonuses */ - p_ptr->update |= (PU_BONUS); -} - - -/* - * Detect traps + kill traps - */ -void do_cmd_unbeliever() -{ - int ext = 0; - - char ch; - - - /* Select what to do */ - while (TRUE) - { - if (!get_com("Disrupt [C]ontinuum or [D]etect Traps", &ch)) - { - ext = 0; - break; - } - if ((ch == 'C') || (ch == 'c')) - { - ext = 1; - break; - } - if ((ch == 'D') || (ch == 'd')) - { - ext = 2; - break; - } - } - - switch (ext) - { - /* Disrupt Continuum */ - case 1: - { - do_cmd_unbeliever_antimagic(); - break; - } - - /* Detect Traps */ - case 2: - { - s16b skill = get_skill(SKILL_ANTIMAGIC); - - if (skill < 25) - { - msg_print("You cannot use your detection abilities yet."); - break; - } - - detect_traps(DEFAULT_RADIUS); - - if (skill >= 35) destroy_doors_touch(); - - break; - } - } -} - -/* - * Hook to determine if an object is totemable - */ -static bool_ item_tester_hook_totemable(object_type *o_ptr) -{ - /* Only full corpse */ - if ((o_ptr->tval == TV_CORPSE) && - ((o_ptr->sval == SV_CORPSE_CORPSE) || (o_ptr->sval == SV_CORPSE_SKELETON))) - { - return (TRUE); - } - - /* Assume not */ - return (FALSE); -} - - -/* - * Summoners - */ -void do_cmd_summoner_extract() -{ - object_type *o_ptr, forge, *q_ptr; - - cptr q, s; - - int item, r; - - bool_ partial; - - - /* Not when confused */ - if (p_ptr->confused) - { - msg_print("You are too confused!"); - return; - } - - /* Require lite */ - if (p_ptr->blind || no_lite()) - { - msg_print("You cannot see!"); - return; - } - - item_tester_hook = item_tester_hook_totemable; - - /* Get an item */ - q = "Use which corpse? "; - s = "You have no corpse to use."; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - /* Get the item */ - o_ptr = get_object(item); - - - if (r_info[o_ptr->pval2].flags1 & RF1_UNIQUE) - { - partial = FALSE; - } - else - { - partial = get_check("Do you want to create a partial totem?"); - } - - r = o_ptr->pval2; - - inc_stack_size(item, -1); - - if (magik(r_info[o_ptr->pval2].level - get_skill(SKILL_SUMMON))) - { - msg_print("You failed to extract a totem."); - energy_use += 100; - return; - } - - /* Prepare for object creation */ - q_ptr = &forge; - - /* Create the object */ - object_prep(q_ptr, lookup_kind(TV_TOTEM, partial ? 1 : 2)); - q_ptr->pval = r; - q_ptr->pval2 = 0; - q_ptr->number = 1; - q_ptr->found = OBJ_FOUND_SELFMADE; - object_aware(q_ptr); - object_known(q_ptr); - q_ptr->ident |= IDENT_MENTAL; - (void)inven_carry(q_ptr, FALSE); - - msg_print("You extract a totem from the dead corpse."); - energy_use += 100; -} - - -void summon_true(int r_idx, int item) -{ - int i, status, x = 1, y = 1, rx, ry = 0, chance; - - bool_ used; - - monster_race *r_ptr = &r_info[r_idx]; - - - /* Uniques are less likely to be nice */ - if (r_ptr->flags1 & (RF1_UNIQUE)) - { - /* Because it's unique, it will always be destroyed */ - used = TRUE; - - /* About twice as hard as non-uniques */ - chance = (get_skill(SKILL_SUMMON) * 70 / (r_ptr->level + 1)); - - if (magik(chance)) - { - status = MSTATUS_PET; - } - else - { - status = MSTATUS_ENEMY; - } - } - - /* Non-uniques are easier to handle */ - else - { - if (get_skill(SKILL_SUMMON) == 0) - { - used = TRUE; - } - else - { - /* It can be used multiple times */ - used = FALSE; - - /* But it is not 100% sure (note: skill > 0) */ - chance = (r_ptr->level * 25 / get_skill(SKILL_SUMMON)); - if (magik(chance)) used = TRUE; - } - - chance = (get_skill(SKILL_SUMMON) * 130 / (r_ptr->level + 1)); - - if (magik(chance)) - { - status = MSTATUS_PET; - } - else - { - status = MSTATUS_ENEMY; - } - } - - /* Find a grid where the monster is summoned */ - for (i = 0; i < 40; i++) - { - rx = (rand_int(8) - 4) + p_ptr->px; - ry = (rand_int(8) - 4) + p_ptr->py; - if (in_bounds(ry, rx) && cave_empty_bold(ry, rx)) - { - x = rx; - y = ry; - break; - } - } - - /* No room found */ - if (i == 40) - { - msg_print("The summoning fails due to lack of room."); - return; - } - - /* Summon the monster */ - bypass_r_ptr_max_num = TRUE; - if (!(i = place_monster_one (y, x, r_idx, 0, 0, status))) - { - msg_print("The summoning fails."); - } - else - { - m_list[i].status = status; - m_list[i].mflag |= MFLAG_NO_DROP; - } - bypass_r_ptr_max_num = FALSE; - - /* Destroy the totem if the used flag is set */ - if (used) - { - /* Eliminate the totem */ - inc_stack_size(item, -1); - } - - /* Done */ - return; -} - - -void do_cmd_summoner_summon() -{ - int item, x = 1, y = 1, rx, ry, m_idx = 0, i; - - cptr q, s; - - object_type *o_ptr; - - monster_type *m_ptr; - - - /* Which Totem? */ - item_tester_tval = TV_TOTEM; - - q = "Summon from which Totem?"; - s = "There are no totems to summon from!"; - if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; - - /* Access the item */ - o_ptr = get_object(item); - - /* Take a turn */ - energy_use = 100; - - /* True Totems have their own function. */ - if (o_ptr->sval == 2) - { - summon_true(o_ptr->pval, item); - return; - } - - /* Handle partial totems */ - - /* Find a grid where the monster is summoned */ - for (i = 0; i < 40; i++) - { - rx = (rand_int(8) - 4) + p_ptr->px; - ry = (rand_int(8) - 4) + p_ptr->py; - if (in_bounds(ry, rx) && cave_empty_bold(ry, rx)) - { - x = rx; - y = ry; - break; - } - } - - /* No room found */ - if (i == 40) - { - msg_print("The summoning fails due to lack of room."); - return; - } - - /* Summon the monster */ - bypass_r_ptr_max_num = TRUE; - place_monster_one_no_drop = TRUE; - m_idx = place_monster_one(y, x, o_ptr->pval, 0, 0, MSTATUS_PET); - bypass_r_ptr_max_num = FALSE; - - /* Failure. */ - if (!m_idx) - { - msg_print("The summoning fails."); - } - - /* Mark the monster as a "partial" ally */ - m_ptr = &m_list[m_idx]; - m_ptr->mflag |= MFLAG_PARTIAL | MFLAG_NO_DROP; -} - - -void do_cmd_summoner(void) -{ - int ext = 0; - - char ch; - - /* No magic */ - if (p_ptr->antimagic) - { - msg_print("Your anti-magic field disrupts any magic attempts."); - return; - } - - /* No magic */ - if (p_ptr->anti_magic) - { - msg_print("Your anti-magic shell disrupts any magic attempts."); - return; - } - - /* not if confused */ - if (p_ptr->confused) - { - msg_print("You are too confused!"); - return; - } - - /* not if blind */ - if (p_ptr->blind || no_lite()) - { - msg_print("You cannot see!"); - return; - } - - /* Select what to do */ - while (TRUE) - { - if (!get_com("[E]xtract a totem, [S]ummon", &ch)) - { - ext = 0; - break; - } - if ((ch == 'E') || (ch == 'e')) - { - ext = 1; - break; - } - if ((ch == 's') || (ch == 'S')) - { - ext = 2; - break; - } - } - - switch (ext) - { - case 1: - { - do_cmd_summoner_extract(); - break; - } - - case 2: - { - do_cmd_summoner_summon(); - break; - } - } -} - - -/* - * Fighters may invoke The Rush. - */ -void do_cmd_blade(void) -{ - /* Are we already Rushed? */ - if (p_ptr->rush) - { - msg_format("You have %d turns of The Rush remaining", p_ptr->rush); - return; - } - - /* Are you sure? */ - if (!get_check("Are you sure you want to invoke The Rush?")) return; - - /* Let's Rush! */ - set_rush(2 + p_ptr->lev / 2 + randint(p_ptr->lev / 2)); -} - - -/* - * Dodge Chance Feedback. - */ -void use_ability_blade(void) -{ - int chance = p_ptr->dodge_chance - ((dun_level * 5) / 6); - - if (chance < 0) chance = 0; - if (wizard) - { - msg_format("You have exactly %d chances of dodging a level %d monster.", chance, dun_level); - } - - if (chance < 5) - { - msg_format("You have almost no chance of dodging a level %d monster.", dun_level); - } - else if (chance < 10) - { - msg_format("You have a slight chance of dodging a level %d monster.", dun_level); - } - else if (chance < 20) - { - msg_format("You have a significant chance of dodging a level %d monster.", dun_level); - } - else if (chance < 40) - { - msg_format("You have a large chance of dodging a level %d monster.", dun_level); - } - else if (chance < 70) - { - msg_format("You have a high chance of dodging a level %d monster.", dun_level); - } - else - { - msg_format("You will usually dodge successfully a level %d monster.", dun_level); - } - - return; -} - -/* - * Helper function to describe symbiotic powers - */ -void symbiotic_info(char *p, int power) -{ - int plev = get_skill(SKILL_SYMBIOTIC); - - strcpy(p, ""); - - switch (power) - { - case 2: - { - strnfmt(p, 80, " power %d", plev * 3); - break; - } - case 5: - { - strnfmt(p, 80, " heal %d%%", 15 + get_skill_scale(SKILL_SYMBIOTIC, 35)); - break; - } - } -} - - -/* - * Cast a symbiotic spell - */ -void do_cmd_symbiotic(void) -{ - int n = 0; - int chance; - int minfail = 0; - int plev = get_skill(SKILL_SYMBIOTIC); - magic_power spell; - - /* Get the carried monster */ - object_type *o_ptr = &p_ptr->inventory[INVEN_CARRY]; - - /* No magic */ - if (p_ptr->antimagic) - { - msg_print("Your anti-magic field disrupts any magic attempts."); - return; - } - - /* No magic */ - if (p_ptr->anti_magic) - { - msg_print("Your anti-magic shell disrupts any magic attempts."); - return; - } - - /* not if confused */ - if (p_ptr->confused) - { - msg_print("You are too confused!"); - return; - } - - /* get power */ - if (!get_magic_power(&n, symbiotic_powers, MAX_SYMBIOTIC_POWERS, symbiotic_info, - get_skill(SKILL_SYMBIOTIC), A_INT)) return; - - spell = symbiotic_powers[n]; - - /* Verify "dangerous" spells */ - if (spell.mana_cost > p_ptr->csp) - { - /* Warning */ - msg_print("You do not have enough mana to use this power."); - - /* Verify */ - if (!get_check("Attempt it anyway? ")) return; - } - - /* Spell failure chance */ - chance = spell.fail; - - /* Reduce failure rate by "effective" level adjustment */ - chance -= 3 * (plev - spell.min_lev); - - /* Reduce failure rate by INT/WIS adjustment */ - chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[A_INT]] - 1); - - /* Not enough mana to cast */ - if (spell.mana_cost > p_ptr->csp) - { - chance += 5 * (spell.mana_cost - p_ptr->csp); - } - - /* Extract the minimum failure rate */ - minfail = adj_mag_fail[p_ptr->stat_ind[A_INT]]; - - /* Failure rate */ - chance = clamp_failure_chance(chance, minfail); - - /* Failed spell */ - if (rand_int(100) < chance) - { - if (flush_failure) flush(); - msg_format("You failed to concentrate hard enough!"); - sound(SOUND_FAIL); - } - else - { - sound(SOUND_ZAP); - - /* spell code */ - switch (n) - { - case 0: - { - int dir, x, y; - cave_type *c_ptr; - monster_type *m_ptr; - monster_race *r_ptr; - object_type *q_ptr; - object_type forge; - - msg_print("Hypnotise which pet?"); - if (!get_rep_dir(&dir)) return; - y = p_ptr->py + ddy[dir]; - x = p_ptr->px + ddx[dir]; - c_ptr = &cave[y][x]; - if (c_ptr->m_idx) - { - m_ptr = &m_list[c_ptr->m_idx]; - r_ptr = race_inf(m_ptr); - - if (!(r_ptr->flags1 & RF1_NEVER_MOVE)) - { - msg_print("You can only hypnotise monsters that cannot move."); - } - else if (m_ptr->status < MSTATUS_PET) - { - msg_print("You can only hypnotise pets and companions."); - } - else if (r_ptr->flags9 & RF9_SPECIAL_GENE) - { - msg_print("You cannot hypnotise this monster."); - } - else - { - /* TODO fix this hack hack hack hackity hack with ToME 3 flags */ - q_ptr = &forge; - object_prep(q_ptr, lookup_kind(TV_HYPNOS, 1)); - q_ptr->number = 1; - q_ptr->pval = m_ptr->r_idx; - q_ptr->pval2 = m_ptr->hp; - q_ptr->pval3 = m_ptr->maxhp; - /* overflow alert */ - q_ptr->exp = m_ptr->exp; - q_ptr->elevel = m_ptr->level; - object_aware(q_ptr); - object_known(q_ptr); - - q_ptr->ident |= IDENT_STOREB; - - drop_near(q_ptr, 0, y, x); - - delete_monster(y, x); - health_who = 0; - } - } - else - { - msg_print("There is no pet here !"); - } - - break; - } - - case 1: - { - monster_type *m_ptr; - int m_idx; - int item, x, y, d; - object_type *o_ptr; - - cptr q, s; - - /* Restrict choices to monsters */ - item_tester_tval = TV_HYPNOS; - - /* Get an item */ - q = "Awaken which monster? "; - s = "You have no monster to awaken."; - if (!get_item(&item, q, s, (USE_FLOOR))) return; - - o_ptr = &o_list[0 - item]; - - d = 2; - while (d < 100) - { - scatter(&y, &x, p_ptr->py, p_ptr->px, d); - - if (cave_floor_bold(y, x) && (!cave[y][x].m_idx)) break; - - d++; - } - - if (d >= 100) return; - - if ((m_idx = place_monster_one(y, x, o_ptr->pval, 0, FALSE, MSTATUS_PET)) == 0) return; - - /* TODO fix this hack hack hack hackity hack with ToME 3 flags */ - /* Have to be careful here; releasing the symbiote into a - * dungeon with leveled monsters will level the symbiote - * before we can get hold of it. We'll be nice and use the - * larger of the saved exp and the exp that the newly-generated - * monster starts with. */ - m_ptr = &m_list[m_idx]; - if (m_ptr->exp < o_ptr->exp) - { - m_ptr->exp = o_ptr->exp; - monster_check_experience(m_idx, TRUE); - if (m_ptr->level != o_ptr->elevel) - cmsg_format(TERM_VIOLET, "ERROR: level-%d HYPNOS becomes level-%d symbiote", o_ptr->elevel, m_ptr->level); - } - m_ptr->hp = o_ptr->pval2; - m_ptr->maxhp = o_ptr->pval3; - - floor_item_increase(0 - item, -1); - floor_item_describe(0 - item); - floor_item_optimize(0 - item); - break; - } - - /* Charm */ - case 2: - { - int dir; - - if (!get_aim_dir(&dir)) return; - - fire_bolt(GF_CHARM_UNMOVING, dir, plev * 3); - - break; - } - - /* Life Share */ - case 3: - { - s32b percent1, percent2; - - if (!o_ptr->k_idx) - { - msg_print("You are not in symbiosis."); - break; - } - - percent1 = p_ptr->chp; - percent1 = (percent1 * 100) / p_ptr->mhp; - - percent2 = o_ptr->pval2; - percent2 = (percent2 * 100) / o_ptr->pval3; - - /* Now get the average */ - percent1 = (percent1 + percent2) / 2; - - /* And set the hp of monster & player to it */ - p_ptr->chp = (percent1 * p_ptr->mhp) / 100; - o_ptr->pval2 = (percent1 * o_ptr->pval3) / 100; - - /* Redraw */ - p_ptr->redraw |= (PR_HP); - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - - /* Display the monster hitpoints */ - p_ptr->redraw |= (PR_MH); - - break; - } - - /* Minor Symbiotic Powers */ - case 4: - { - if (!o_ptr->k_idx) - { - msg_print("You are not in symbiosis."); - break; - } - - if (0 > use_symbiotic_power(o_ptr->pval, FALSE, FALSE, TRUE)) - return; - - break; - } - - /* Heal Symbiote */ - case 5: - { - int hp; - - if (!o_ptr->k_idx) - { - msg_print("You are not in symbiosis."); - break; - } - - hp = o_ptr->pval3 * (15 + get_skill_scale(SKILL_SYMBIOTIC, 35)) / 100; - o_ptr->pval2 += hp; - if (o_ptr->pval2 > o_ptr->pval3) o_ptr->pval2 = o_ptr->pval3; - - msg_format("%s is healed.", symbiote_name(TRUE)); - - /* Display the monster hitpoints */ - p_ptr->redraw |= (PR_MH); - - break; - } - - - /* Major Symbiotic Powers */ - case 6: - { - if (!o_ptr->k_idx) - { - msg_print("You are not in symbiosis."); - break; - } - - if(0 > use_symbiotic_power(o_ptr->pval, TRUE, FALSE, TRUE)) - return; - - break; - } - - /* Summon never-moving pet */ - case 7: - { - summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_MINE, FALSE); - - break; - } - - /* Force Symbiosis */ - case 8: - { - int y, x; - cave_type *c_ptr; - monster_type *m_ptr; - - if (!tgt_pt(&x, &y)) return; - - c_ptr = &cave[y][x]; - - if (!c_ptr->m_idx) break; - - m_ptr = &m_list[c_ptr->m_idx]; - use_symbiotic_power(m_ptr->r_idx, TRUE, FALSE, TRUE); - - break; - } - - - default: - { - msg_print("Zap?"); - - break; - } - } - } - - /* Take a turn */ - energy_use = 100; - - /* Sufficient mana */ - if (spell.mana_cost <= p_ptr->csp) - { - /* Use some mana */ - p_ptr->csp -= spell.mana_cost; - } - - /* Over-exert the player */ - else - { - int oops = spell.mana_cost - p_ptr->csp; - - /* No mana left */ - p_ptr->csp = 0; - p_ptr->csp_frac = 0; - - /* Message */ - msg_print("You faint from the effort!"); - - /* Hack -- Bypass free action */ - (void)set_paralyzed(randint(5 * oops + 1)); - - /* Damage CON (possibly permanently) */ - if (rand_int(100) < 50) - { - bool_ perm = (rand_int(100) < 25); - - /* Message */ - msg_print("You have damaged your body!"); - - /* Reduce constitution */ - (void)dec_stat(A_CHR, 15 + randint(10), perm); - } - } - - /* Redraw mana */ - p_ptr->redraw |= (PR_MANA); - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); -} - -/* - * Boulder creation .. sorry :) - */ -void do_cmd_create_boulder() -{ - int x, y, dir; - cave_type *c_ptr; - - if (!get_rep_dir(&dir)) return; - y = p_ptr->py + ddy[dir]; - x = p_ptr->px + ddx[dir]; - c_ptr = &cave[y][x]; - - /* Granite -- How about other wall types? */ - if (((c_ptr->feat >= FEAT_WALL_EXTRA) && (c_ptr->feat <= FEAT_WALL_SOLID)) || - ((c_ptr->feat >= FEAT_MAGMA_H) && (c_ptr->feat <= FEAT_QUARTZ_K)) || - ((c_ptr->feat == FEAT_MAGMA) || - (c_ptr->feat == FEAT_QUARTZ))) - { - object_type forge; - object_type *q_ptr; - - (void)wall_to_mud(dir); - - /* Get local object */ - q_ptr = &forge; - - /* Hack -- Give the player some shots */ - object_prep(q_ptr, lookup_kind(TV_JUNK, SV_BOULDER)); - q_ptr->number = (byte)rand_range(2, 5); - object_aware(q_ptr); - object_known(q_ptr); - q_ptr->ident |= IDENT_MENTAL; - q_ptr->discount = 90; - q_ptr->found = OBJ_FOUND_SELFMADE; - - (void)inven_carry(q_ptr, FALSE); - - msg_print("You make some boulders."); - - p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE); - p_ptr->window |= (PW_OVERHEAD); - - /* Take a turn */ - energy_use = 100; - } -} - -/* - * Clamp failure chance - */ -extern int clamp_failure_chance(int chance, int minfail) -{ - if (minfail < 0) minfail = 0; - - /* Minimum failure rate */ - if (chance < minfail) chance = minfail; - - /* Stunning makes spells harder */ - if (p_ptr->stun > 50) chance += 25; - else if (p_ptr->stun) chance += 15; - - /* Always a 5 percent chance of working */ - if (chance > 95) chance = 95; - - return chance; -} diff --git a/src/cmd7.cc b/src/cmd7.cc new file mode 100644 index 00000000..c9be0c66 --- /dev/null +++ b/src/cmd7.cc @@ -0,0 +1,7632 @@ +/* File: cmd7.c */ + +/* Purpose: More Class commands */ + +/* + * Copyright (c) 1999 Dark God + * + * This software may be copied and distributed for educational, research, and + * not for profit purposes provided that this copyright and statement are + * included in all such copies. + */ + + +#include "angband.h" + +#include "quark.h" +#include "hooks.h" + +/* + * Describe class powers of Mindcrafters + * + * 'p' points to a 80 byte long buffer + */ +void mindcraft_info(char *p, int power) +{ + int plev = get_skill(SKILL_MINDCRAFT); + + + /* Clear buffer */ + strcpy(p, ""); + + /* Fill the buffer with requested power description */ + switch (power) + { + case 0: + strnfmt(p, 80, " rad %d", DEFAULT_RADIUS); + break; + case 1: + strnfmt(p, 80, " dam %dd%d", 3 + ((plev - 1) / 4), 3 + plev / 15); + break; + case 2: + strnfmt(p, 80, " range %d", (plev < 25 ? 10 : plev + 2 + p_ptr->to_s * 3)); + break; + case 3: + strnfmt(p, 80, " range %d", plev * 5); + break; + case 4: + strnfmt(p, 80, " power %d", plev * (plev < 30 ? 1 : 2)); + break; + case 5: + if (plev > 20) + strnfmt(p, 80, " dam %dd8 rad %d", 8 + ((plev - 5) / 4), (plev - 20)/8 + 1); + else + strnfmt(p, 80, " dam %dd8", 8 + ((plev - 5) / 4)); + break; + case 6: + strnfmt(p, 80, " dur %d", plev); + break; + case 7: + break; + case 8: + if (plev < 25) + strnfmt(p, 80, " dam %d rad %d", (3 * plev) / 2, 2 + (plev / 10)); + else + strnfmt(p, 80, " dam %d", plev * ((plev - 5) / 10 + 1)); + break; + case 9: + strnfmt(p, 80, " dur 11-%d", 10 + plev + plev / 2); + break; + case 10: + strnfmt(p, 80, " dam %dd6 rad %d", plev / 2, 0 + (plev - 25) / 10); + break; + case 11: + strnfmt(p, 80, " dam %d rad %d", plev * (plev > 39 ? 4 : 3), 3 + plev / 10); + break; + } +} + + +/* + * Describe class powers of Mimics + * + * 'p' points to a 80 byte long buffer + */ +void mimic_info(char *p, int power) +{ + int plev = get_skill(SKILL_MIMICRY); + object_type *o_ptr = &p_ptr->inventory[INVEN_OUTER]; + + /* Clear the buffer */ + strcpy(p, ""); + + /* Fill the buffer with requested power description */ + switch (power) + { + case 0: + strnfmt(p, 80, " dur %d", k_info[o_ptr->k_idx].pval2 + get_skill_scale(SKILL_MIMICRY, 1000)); + break; + case 1: + strnfmt(p, 80, " dur %d+d20", 10 + plev); + break; + case 2: + strnfmt(p, 80, " dur 50+d%d", 50 + (2 * plev)); + break; + case 3: + strnfmt(p, 80, " dur 50+d%d", 50 + (2 * plev)); + break; + case 4: + strnfmt(p, 80, " dur 50+d%d", 50 + (2 * plev)); + break; + } +} + +/** + * Show magic powers that user can choose from + */ +static void display_magic_powers( + magic_power *powers, + int max_powers, + void (*power_info)(char *p, int power), + int plev, + int cast_stat, + int y, + int x) +{ + char psi_desc[80]; + magic_power spell; + int i; + int chance = 0; + int minfail = 0; + char comment[80]; + + /* Display a list of spells */ + prt("", 1, x); + prt("", y, x); + put_str("Name", y, x + 5); + put_str("Lv Mana Fail Info", y, x + 35); + + /* Dump the spells */ + for (i = 0; i < max_powers; i++) + { + /* Access the spell */ + spell = powers[i]; + if (spell.min_lev > plev) + { + break; + } + + chance = spell.fail; + /* Reduce failure rate by "effective" level adjustment */ + chance -= 3 * (plev - spell.min_lev); + + /* Reduce failure rate by INT/WIS adjustment */ + chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[cast_stat]] - 1); + + /* Not enough mana to cast */ + if (spell.mana_cost > p_ptr->csp) + { + chance += 5 * (spell.mana_cost - p_ptr->csp); + } + + /* Extract the minimum failure rate */ + minfail = adj_mag_fail[p_ptr->stat_ind[cast_stat]]; + + /* Failure rate */ + chance = clamp_failure_chance(chance, minfail); + + /* Get info */ + power_info(comment, i); + + /* Dump the spell --(-- */ + strnfmt(psi_desc, 80, " %c) %-30s%2d %4d %3d%%%s", + I2A(i), spell.name, + spell.min_lev, spell.mana_cost, chance, comment); + prt(psi_desc, y + i + 1, x); + } + + /* Clear the bottom line */ + prt("", y + i + 1, x); +} + +/* + * Allow user to choose a magic power. + * + * If a valid spell is chosen, saves it in '*sn' and returns TRUE + * If the user hits escape, returns FALSE, and set '*sn' to -1 + * If there are no legal choices, returns FALSE, and sets '*sn' to -2 + * + * The "prompt" should be "cast", "recite", or "study" + * The "known" should be TRUE for cast/pray, FALSE for study + * + * nb: This function has a (trivial) display bug which will be obvious + * when you run it. It's probably easy to fix but I haven't tried, + * sorry. + */ +static bool_ get_magic_power(int *sn, magic_power *powers, int max_powers, + void (*power_info)(char *p, int power), int plev, int cast_stat) +{ + int i; + + int num = 0; + + int y = 2; + + int x = 18; + + int info; + + char choice; + + char out_val[160]; + + cptr p = "power"; + + magic_power spell; + + bool_ flag; + + + /* Assume cancelled */ + *sn = ( -1); + + /* Get the spell, if available */ + if (repeat_pull(sn)) + { + /* Verify the spell */ + if (powers[*sn].min_lev <= plev) + { + /* Success */ + return (TRUE); + } + } + + /* Nothing chosen yet */ + flag = FALSE; + + /* Count number of powers that satisfies minimum plev requirement */ + for (i = 0; i < max_powers; i++) + { + if (powers[i].min_lev <= plev) + { + num++; + } + } + + /* Build a prompt (accept all spells) */ + strnfmt(out_val, 78, "(%^ss %c-%c, ESC=exit, %c-%c=Info) Use which %s? ", + p, I2A(0), I2A(num - 1), toupper(I2A(0)), toupper(I2A(num - 1)), p); + + /* Save the screen */ + character_icky = TRUE; + Term_save(); + + /* Show the list */ + display_magic_powers(powers, max_powers, power_info, plev, cast_stat, y, x); + + /* Get a spell from the user */ + while (!flag && get_com(out_val, &choice)) + { + /* Note verify */ + info = (isupper(choice)); + + /* Lowercase */ + if (info) choice = tolower(choice); + + /* Extract request */ + i = (islower(choice) ? A2I(choice) : -1); + + /* Totally Illegal */ + if ((i < 0) || (i >= num)) + { + bell(); + continue; + } + + /* Save the spell index */ + spell = powers[i]; + + /* Provides info */ + if (info) + { + c_prt(TERM_L_BLUE, spell.desc, 1, 0); + + /* Restore the screen */ + inkey(); + Term_load(); + character_icky = FALSE; + + /* Redisplay choices */ + display_magic_powers(powers, max_powers, power_info, plev, cast_stat, y, x); + continue; + } + + /* Stop the loop */ + flag = TRUE; + } + + /* Restore the screen */ + Term_load(); + character_icky = FALSE; + + /* Abort if needed */ + if (!flag) return (FALSE); + + /* Save the choice */ + (*sn) = i; + + + repeat_push(*sn); + + /* Success */ + return (TRUE); +} + + +/* + * do_cmd_cast calls this function if the player's class + * is 'mindcrafter'. + */ +void do_cmd_mindcraft(void) +{ + int n = 0, b = 0; + + int chance; + + int dir; + + int minfail = 0; + + int plev = get_skill(SKILL_MINDCRAFT); + + magic_power spell; + + + /* No magic */ + if (p_ptr->antimagic) + { + msg_print("Your anti-magic field disrupts any magic attempts."); + return; + } + + /* No magic */ + if (p_ptr->anti_magic) + { + msg_print("Your anti-magic shell disrupts any magic attempts."); + return; + } + + + /* not if confused */ + if (p_ptr->confused) + { + msg_print("You are too confused!"); + return; + } + + /* get power */ + if (!get_magic_power(&n, mindcraft_powers, MAX_MINDCRAFT_POWERS, + mindcraft_info, plev, A_WIS)) return; + + spell = mindcraft_powers[n]; + + /* Verify "dangerous" spells */ + if (spell.mana_cost > p_ptr->csp) + { + /* Warning */ + msg_print("You do not have enough mana to use this power."); + + /* Verify */ + if (!get_check("Attempt it anyway? ")) return; + } + + /* Spell failure chance */ + chance = spell.fail; + + /* Reduce failure rate by "effective" level adjustment */ + chance -= 3 * (get_skill(SKILL_MINDCRAFT) - spell.min_lev); + + /* Reduce failure rate by INT/WIS adjustment */ + chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[A_WIS]] - 1); + + /* Not enough mana to cast */ + if (spell.mana_cost > p_ptr->csp) + { + chance += 5 * (spell.mana_cost - p_ptr->csp); + } + + /* Extract the minimum failure rate */ + minfail = adj_mag_fail[p_ptr->stat_ind[A_WIS]]; + + /* Failure rate */ + chance = clamp_failure_chance(chance, minfail); + + /* Failed spell */ + if (rand_int(100) < chance) + { + if (flush_failure) flush(); + + msg_format("You failed to concentrate hard enough!"); + + sound(SOUND_FAIL); + + if (randint(100) < (chance / 2)) + { + /* Backfire */ + b = randint(100); + if (b < 5) + { + msg_print("Oh, no! Your mind has gone blank!"); + lose_all_info(); + } + else if (b < 15) + { + msg_print("Weird visions seem to dance before your eyes..."); + set_image(p_ptr->image + 5 + randint(10)); + } + else if (b < 45) + { + msg_print("Your brain is addled!"); + set_confused(p_ptr->confused + randint(8)); + } + else if (b < 90) + { + set_stun(p_ptr->stun + randint(8)); + } + else + { + /* Mana storm */ + msg_print("Your mind unleashes its power in an uncontrollable storm!"); + project(1, 2 + plev / 10, p_ptr->py, p_ptr->px, plev * 2, + GF_MANA, PROJECT_JUMP | PROJECT_KILL | PROJECT_GRID | PROJECT_ITEM); + p_ptr->csp = MAX(0, p_ptr->csp - plev * MAX(1, plev / 10)); + } + } + } + + /* Successful spells */ + else + { + sound(SOUND_ZAP); + + /* spell code */ + switch (n) + { + /* Precog */ + case 0: + { + /* Magic mapping */ + if (plev > 44) + { + wiz_lite(); + } + else if (plev > 19) + { + map_area(); + } + + /* Detection */ + if (plev < 30) + { + b = detect_monsters_normal(DEFAULT_RADIUS); + if (plev > 14) b |= detect_monsters_invis(DEFAULT_RADIUS); + if (plev > 4) b |= detect_traps(DEFAULT_RADIUS); + } + else + { + b = detect_all(DEFAULT_RADIUS); + } + + /* Telepathy */ + if (plev > 24) + { + set_tim_esp(p_ptr->tim_esp + plev); + + /* If plvl >= 40, we should have permanent ESP */ + } + + if (!b) msg_print("You feel safe."); + + break; + } + + /* Mindblast */ + case 1: + { + if (!get_aim_dir(&dir)) return; + + if (randint(100) < plev * 2) + { + fire_beam(GF_PSI, dir, damroll(3 + ((plev - 1) / 4), (3 + plev / 15))); + } + else + { + fire_ball(GF_PSI, dir, damroll(3 + ((plev - 1) / 4), (3 + plev / 15)), 0); + } + + break; + } + + /* Minor displace */ + case 2: + { + if (plev < 25) + { + teleport_player(10); + } + else + { + int ii, ij; + + if (dungeon_flags2 & DF2_NO_TELEPORT) + { + msg_print("Not on special levels!"); + break; + } + + msg_print("You open a Void Jumpgate. Choose a destination."); + + if (!tgt_pt(&ii, &ij)) return; + p_ptr->energy -= 60 - plev; + + if (!cave_empty_bold(ij, ii) || + (cave[ij][ii].info & CAVE_ICKY) || + (distance(ij, ii, p_ptr->py, p_ptr->px) > plev + 2 + (p_ptr->to_s*3)) || + (rand_int(plev * plev / 2) == 0)) + { + msg_print("You fail to exit the void correctly!"); + p_ptr->energy -= 100; + get_pos_player(10 + p_ptr->to_s / 2, &ij, &ii); + } + + cave_set_feat(p_ptr->py, p_ptr->px, FEAT_BETWEEN); + cave_set_feat(ij, ii, FEAT_BETWEEN); + cave[p_ptr->py][p_ptr->px].special = ii + (ij << 8); + cave[ij][ii].special = p_ptr->px + (p_ptr->py << 8); + } + + break; + } + + /* Major displace */ + case 3: + { + if (plev > 29) banish_monsters(plev); + teleport_player(plev * 5); + + break; + } + + /* Domination */ + case 4: + { + if (plev < 30) + { + if (!get_aim_dir(&dir)) return; + fire_ball(GF_DOMINATION, dir, plev, 0); + } + else + { + charm_monsters(plev * 2); + } + + break; + } + + /* Fist of Force --- not 'true' TK */ + case 5: + { + if (!get_aim_dir(&dir)) return; + fire_ball(GF_SOUND, dir, damroll(8 + ((plev - 5) / 4), 8), + (plev > 20 ? (plev - 20) / 8 + 1 : 0)); + + break; + } + + /* Character Armour */ + case 6: + { + set_shield(p_ptr->shield + plev, plev, 0, 0, 0); + if (plev > 14) set_oppose_acid(p_ptr->oppose_acid + plev); + if (plev > 19) set_oppose_fire(p_ptr->oppose_fire + plev); + if (plev > 24) set_oppose_cold(p_ptr->oppose_cold + plev); + if (plev > 29) set_oppose_elec(p_ptr->oppose_elec + plev); + if (plev > 34) set_oppose_pois(p_ptr->oppose_pois + plev); + + break; + } + + /* Psychometry */ + case 7: + { + ident_spell(); + break; + } + + /* Mindwave */ + case 8: + { + msg_print("Mind-warping forces emanate from your brain!"); + if (plev < 25) + { + project(0, 2 + plev / 10, p_ptr->py, p_ptr->px, + (plev*3) / 2, GF_PSI, PROJECT_KILL); + } + else + { + (void)mindblast_monsters(plev * ((plev - 5) / 10 + 1)); + } + + break; + } + + /* Adrenaline */ + case 9: + { + set_afraid(0); + set_stun(0); + hp_player(plev); + + b = 10 + randint((plev * 3) / 2); + + if (plev < 35) + { + set_hero(p_ptr->hero + b); + } + else + { + set_shero(p_ptr->shero + b); + } + + if (!p_ptr->fast) + { + /* Haste */ + (void)set_fast(b, plev / 5); + } + else + { + (void)set_fast(p_ptr->fast + b, plev / 5); + } + + break; + } + + /* Psychic Drain */ + case 10: + { + if (!get_aim_dir(&dir)) return; + + b = damroll(plev / 2, 6); + + if (fire_ball(GF_PSI_DRAIN, dir, b, 0 + (plev - 25) / 10)) + { + p_ptr->energy -= randint(150); + } + + break; + } + + /* Telekinesis */ + case 11: + { + msg_print("A wave of pure physical force radiates out from your body!"); + project(0, 3 + plev / 10, p_ptr->py, p_ptr->px, + plev * (plev > 39 ? 4 : 3), GF_TELEKINESIS, + PROJECT_KILL | PROJECT_ITEM | PROJECT_GRID); + + break; + } + + default: + { + msg_print("Zap?"); + + break; + } + } + } + + /* Take a turn */ + energy_use = 100; + + /* Sufficient mana */ + if (spell.mana_cost <= p_ptr->csp) + { + /* Use some mana */ + p_ptr->csp -= spell.mana_cost; + } + + /* Over-exert the player */ + else + { + int oops = spell.mana_cost - p_ptr->csp; + + /* No mana left */ + p_ptr->csp = 0; + p_ptr->csp_frac = 0; + + /* Message */ + msg_print("You faint from the effort!"); + + /* Hack -- Bypass free action */ + (void)set_paralyzed(randint(5 * oops + 1)); + + /* Damage WIS (possibly permanently) */ + if (rand_int(100) < 50) + { + bool_ perm = (rand_int(100) < 25); + + /* Message */ + msg_print("You have damaged your mind!"); + + /* Reduce constitution */ + (void)dec_stat(A_WIS, 15 + randint(10), perm); + } + } + + /* Redraw mana */ + p_ptr->redraw |= (PR_MANA); + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); +} + + +static int get_mimic_chance(int mimic) +{ + s32b chance; + + chance = get_mimic_level(mimic); + chance *= 3; + + chance -= get_skill_scale(SKILL_MIMICRY, 150); + chance -= 3 * adj_mag_stat[p_ptr->stat_ind[A_DEX]]; + + /* Return the chance */ + return clamp_failure_chance(chance, 2); +} + + +void do_cmd_mimic_lore() +{ + int fail; + + object_type *o_ptr; + + + /* Player has to be able to see */ + if (p_ptr->blind || no_lite()) + { + msg_print("You cannot see!"); + return; + } + + /* No transformations when confused */ + if (p_ptr->confused) + { + msg_print("You are too confused!"); + return; + } + + + /* Already in a mimic form -- Allow cancelling */ + if (p_ptr->mimic_form) + { + msg_print("You morph back to your natural form!"); + + set_mimic(0, 0, 0); + } + + /* Not in mimic forms -- Allow transformations */ + else + { + o_ptr = &p_ptr->inventory[INVEN_OUTER]; + + if ((o_ptr->tval != TV_CLOAK) || (o_ptr->sval != SV_MIMIC_CLOAK)) + { + msg_print("You are not wearing any cloaks of mimicry."); + return; + } + + /* Calculate failure rate */ + fail = get_mimic_chance(o_ptr->pval2); + + if (fail > 75) + { + msg_print("You feel uneasy with this shape-change."); + + if (!get_check("Try it anyway? ")) return; + } + + /* Fumble */ + if (randint(100) < fail) + { + msg_print("Your shape-change goes horribly wrong!"); + + if (randint(100) < p_ptr->skill_sav) + { + msg_print("You manage to wrest your body back under control."); + return; + } + + set_mimic(30, resolve_mimic_name("Abomination"), get_skill(SKILL_MIMICRY)); + } + + /* Success */ + else + { + set_mimic(k_info[o_ptr->k_idx].pval2 + get_skill_scale(SKILL_MIMICRY, 1000), o_ptr->pval2, get_skill(SKILL_MIMICRY)); + } + } + + + /* Redraw title */ + p_ptr->redraw |= (PR_TITLE); + + /* Recalculate bonuses */ + p_ptr->update |= (PU_BONUS); +} + +static bool_ mimic_forbid_travel(const char *fmt) +{ + u32b value = p_ptr->mimic_extra >> 16; + u32b att = p_ptr->mimic_extra & 0xFFFF; + + if(value > 0 && (att & CLASS_ARMS || att & CLASS_LEGS)) + { + msg_print("You had best not travel with your extra limbs."); + return TRUE; + } + + return FALSE; +} + +/* + * do_cmd_cast calls this function if the player's class + * is 'mimic'. + */ +void do_cmd_mimic(void) +{ + int n = 0, b = 0; + + int fail; + + int minfail = 0; + + int plev = get_skill(SKILL_MIMICRY); + + magic_power spell; + + static bool_ added_hooks = FALSE; + if(!added_hooks) + { + add_hook(HOOK_FORBID_TRAVEL, mimic_forbid_travel, "mimic_forbid_travel"); + added_hooks = TRUE; + } + + /* No magic */ + if (p_ptr->antimagic) + { + msg_print("Your anti-magic field disrupts any magic attempts."); + return; + } + + /* No magic */ + if (p_ptr->anti_magic) + { + msg_print("Your anti-magic shell disrupts any magic attempts."); + return; + } + + + /* not if confused */ + if (p_ptr->confused) + { + msg_print("You are too confused!"); + return; + } + + /* get power */ + if (!get_magic_power(&n, mimic_powers, MAX_MIMIC_POWERS, mimic_info, + plev, A_DEX)) return; + + spell = mimic_powers[n]; + + /* Verify "dangerous" spells */ + if (spell.mana_cost > p_ptr->csp) + { + /* Warning */ + msg_print("You do not have enough mana to use this power."); + + /* Verify */ + if (!get_check("Attempt it anyway? ")) return; + } + + /* Spell failure chance */ + fail = spell.fail; + + /* Reduce failure rate by "effective" level adjustment */ + fail -= 3 * (plev - spell.min_lev); + + /* Reduce failure rate by INT/WIS adjustment */ + fail -= 3 * (adj_mag_stat[p_ptr->stat_ind[A_DEX]] - 1); + + /* Not enough mana to cast */ + if (spell.mana_cost > p_ptr->csp) + { + fail += 5 * (spell.mana_cost - p_ptr->csp); + } + + /* Extract the minimum failure rate */ + minfail = adj_mag_fail[p_ptr->stat_ind[A_DEX]]; + + /* Minimum failure rate */ + if (fail < minfail) fail = minfail; + + /* Stunning makes spells harder */ + if (p_ptr->stun > 50) fail += 25; + else if (p_ptr->stun) fail += 15; + + /* Always a 5 percent chance of working */ + if (fail > 95) fail = 95; + + /* Failed spell */ + if (rand_int(100) < fail) + { + if (flush_failure) flush(); + + msg_format("You failed to concentrate hard enough!"); + + sound(SOUND_FAIL); + + if (randint(100) < (fail / 2)) + { + /* Backfire */ + b = randint(100); + + if (b < 5) + { + msg_print("Oh, no! Your mind has gone blank!"); + lose_all_info(); + } + else if (b < 15) + { + msg_print("Weird visions seem to dance before your eyes..."); + set_image(p_ptr->image + 5 + randint(10)); + } + else if (b < 45) + { + msg_print("Your brain is addled!"); + set_confused(p_ptr->confused + randint(8)); + } + else + { + set_stun(p_ptr->stun + randint(8)); + } + } + } + + /* Successful spells */ + else + { + sound(SOUND_ZAP); + + /* spell code */ + switch (n) + { + /* Mimic */ + case 0: + { + do_cmd_mimic_lore(); + + break; + } + + /* Invisibility */ + case 1: + { + int ii = 10 + plev + randint(20) + p_ptr->to_s; + + set_invis(p_ptr->tim_invisible + ii, 50); + set_tim_invis(p_ptr->tim_invisible + ii); + + break; + } + + /* Legs Mimicry */ + case 2: + { + /* Extract the value and the flags */ + u32b value = p_ptr->mimic_extra >> 16; + u32b att = p_ptr->mimic_extra & 0xFFFF; + + /* Clear useless things */ + att &= ~(CLASS_ARMS); + att &= ~(CLASS_WALL); + + if (att & CLASS_LEGS) + { + value += 50 + randint(50 + (2 * plev)); + } + else + { + msg_print("You mimic a new pair of legs."); + + value = 50 + randint(50 + (2 * plev)); + att |= (CLASS_LEGS); + } + + if (value > 10000) value = 10000; + + p_ptr->mimic_extra = att + (value << 16); + p_ptr->update |= (PU_BODY); + + break; + } + + /* Wall Mimicry */ + case 3: + { + /* Extract the value and the flags */ + u32b value = p_ptr->mimic_extra >> 16; + u32b att = p_ptr->mimic_extra & 0xFFFF; + + /* Clear useless things */ + att &= ~(CLASS_ARMS); + att &= ~(CLASS_LEGS); + + if (att & CLASS_WALL) + { + value += 50 + randint(50 + (2 * plev)); + } + else + { + msg_print("You grow an affinity for walls."); + + value = 50 + randint(50 + (2 * plev)); + att |= (CLASS_WALL); + } + + if (value > 10000) value = 10000; + + p_ptr->mimic_extra = att + (value << 16); + p_ptr->update |= (PU_BODY); + + break; + } + + case 4: /* Arms Mimicry */ + { + /* Extract the value and the flags */ + u32b value = p_ptr->mimic_extra >> 16; + u32b att = p_ptr->mimic_extra & 0xFFFF; + + /* Clear useless things */ + att &= ~(CLASS_LEGS); + att &= ~(CLASS_WALL); + + if (att & CLASS_ARMS) + { + value += 50 + randint(50 + (2 * plev)); + } + else + { + msg_print("You mimic a new pair of arms."); + + value = 50 + randint(50 + (2 * plev)); + att |= (CLASS_ARMS); + } + + if (value > 10000) value = 10000; + + p_ptr->mimic_extra = att + (value << 16); + p_ptr->update |= (PU_BODY); + + break; + } + + default: + { + msg_print("Zap?"); + + break; + } + } + } + + + /* Take a turn */ + energy_use = 100; + + /* Sufficient mana */ + if (spell.mana_cost <= p_ptr->csp) + { + /* Use some mana */ + p_ptr->csp -= spell.mana_cost; + } + + /* Over-exert the player */ + else + { + int oops = spell.mana_cost - p_ptr->csp; + + /* No mana left */ + p_ptr->csp = 0; + p_ptr->csp_frac = 0; + + /* Message */ + msg_print("You faint from the effort!"); + + /* Hack -- Bypass free action */ + (void)set_paralyzed(randint(5 * oops + 1)); + + /* Damage WIS (possibly permanently) */ + if (rand_int(100) < 50) + { + bool_ perm = (rand_int(100) < 25); + + /* Message */ + msg_print("You have damaged your mind!"); + + /* Reduce constitution */ + (void)dec_stat(A_DEX, 15 + randint(10), perm); + } + } + + /* Redraw mana */ + p_ptr->redraw |= (PR_MANA); + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); +} + + +/* + * do_cmd_cast calls this function if the player's class + * is 'beastmaster'. + */ +void do_cmd_beastmaster(void) +{ + int plev = p_ptr->lev, i, num; + + monster_type *m_ptr; + + + /* Process the monsters (backwards) */ + num = 0; + for (i = m_max - 1; i >= 1; i--) + { + /* Access the monster */ + m_ptr = &m_list[i]; + + if (m_ptr->status == MSTATUS_PET) + { + num++; + } + } + + if (num < plev * 2) + { + /* XXX XXX */ + if (rand_int(80-(plev) - p_ptr->stat_use[5]-p_ptr->to_s) < 20) + { + summon_specific_friendly(p_ptr->py, p_ptr->px, plev, rand_int(plev / 2), FALSE); + } + } + else msg_print("You can't summon more pets"); + + /* Take a turn */ + if (is_magestaff()) energy_use = 80; + else energy_use = 100; + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); +} + + +/* + * Set of variables and functions to create an artifact + */ + + +/* LOG2 is a constant (compile-time) method of converting a single + * set bit into a number. Works well, but for variable (runtime) + * expressions, use a loop instead.. much smaller code*/ +#define LOG2(x) ( (x) & 0xFFFF? BLOG16(x) : BLOG16((x)>>16) + 16 ) +#define BLOG16(x) ( (x) & 0xFF ? BLOG8(x) : BLOG8 ((x)>>8 ) + 8 ) +#define BLOG8(x) ( (x) & 0xF ? BLOG4(x) : BLOG4 ((x)>>4 ) + 4 ) +#define BLOG4(x) ( (x) & 0x3 ? BLOG2(x) : BLOG2 ((x)>>2 ) + 2 ) +#define BLOG2(x) ( (x) & 0x1 ? 0 : 1 ) + +int flags_select[32*5]; +int activation_select; + +/* Return true if the player is wielding the philosopher's stone + */ +bool_ alchemist_has_stone(void) +{ + if (p_ptr->inventory[INVEN_LITE].name1 == 209) + return TRUE; + else + return FALSE; +} + +/* + Display a group of flags from a_select flags, and return + the number of flags displayed (even invisible ones) + */ +int show_flags(byte group, int pval) +{ + int i, x, color = TERM_WHITE; + int items = 0; + + char ttt[80]; + + Term_clear(); + + group++; /* Adjust - no zero group */ + + for ( i = 0 ; a_select_flags[i].group ; i++) + { + if (a_select_flags[i].group != group) + continue; + + if (a_select_flags[i].xp == 0) + break; + else + { + sprintf(ttt, "%c) %s", + (items < 26) ? I2A(items) : ('0' + items - 26), + al_name + a_select_flags[i].desc); + if ( wizard || alchemist_has_stone()) + sprintf(ttt, "%c) %s (exp " FMTu32b ")", + (items < 26) ? I2A(items) : ('0' + items - 26), + al_name + a_select_flags[i].desc, + a_select_flags[i].xp); + + /* Note: Somebody is VERY clever, and it wasn't me. Text printed as + * TERM_DARK is actually printed as TERM_BLUE *SPACES* to prevent the + * player from using a 'cut-and-paste' enabled terminal to see + * what he shouldn't. Thus, simply setting the color to TERM_DARK + * will entirely prevent the unspoiled player from knowing that it's + * even possible. */ + + switch (flags_select[i]) + { + case 1: + color = TERM_YELLOW; + break; /* Flag was set by the player (just now)*/ + case 0: + color = TERM_WHITE; + break; /* This flag can be set, player is 'aware' of it*/ + case - 1: + color = TERM_L_GREEN; + break; /* Flag is already set*/ + case - 2: + color = TERM_DARK; + break; /* Invisible option */ + case - 3: + color = TERM_RED; + break; /* Flag is set, but player isn't 'aware' of it */ + case - 4: + color = TERM_L_DARK; + break; /* Flag is not set, player is 'aware', but it's beyond thier skill */ + default: + color = TERM_DARK; + break; /* Just in Case*/ + } + } + /* For alchemists who have the stone, at least show all the flags... */ + if ((alchemist_has_stone() || wizard) && color == TERM_DARK) + color = TERM_BLUE; + + if (items < 16) x = 5; + else x = 45; + c_prt(color, ttt, ((items < 16) ? items : items - 16) + 5, x); + items++; + + } + return items; +} + +void show_levels(void) +{ + Term_clear(); + c_prt(TERM_WHITE, "[a] Stats, sustains, luck, speed, vision, etc. ", 3, 10); + c_prt(TERM_WHITE, "[b] Misc. (Auras, light, see invis, etc) ", 4, 10); + c_prt(TERM_WHITE, "[c] Weapon Branding ", 5, 10); + c_prt(TERM_WHITE, "[d] Resistances and Immunities ", 6, 10); + c_prt(TERM_WHITE, "[e] ESP and Curses ", 7, 10); + c_prt(TERM_WHITE, "[f] Activation ", 8, 10); + c_prt(TERM_DARK , "[g] Abilities Gained ", 9, 10); + c_prt(TERM_WHITE, "[h] Display Required Essences and items ", 10, 10); + c_prt(TERM_WHITE, "[i] Done! Finalize and commit changes. ", 11, 10); + /*No need to return anything - if the valid selections change, it'll be a code level change.*/ +} + +s32b get_flags_exp(int pval, int oldpval) +{ + int i; + s32b exp = 0; + + for (i = 0 ; a_select_flags[i].group ; i++ ) + { + if (a_select_flags[i].xp == 0) + break; + else + { + if ( a_select_flags[i].group <= 5 && flags_select[i] ) + { + s32b xp = a_select_flags[i].xp; + int factor = 1, oldfactor = 0; + + /* don't even look at flags which the user can't set + * because they also can't change the pval when a pval- + * dependant flag is set, flags which they can't set + * cannot effect the exp in any way, whether their set or not + */ + if ( flags_select[i] < -1 ) + continue; + if ( flags_select[i] == -1 ) + oldfactor = 1; + + if (a_select_flags[i].pval) + { + /* (1/4)x^2 + x + * I wanted something smaller than x^2 or x^x + * this is because although a ring of speed +10 is + * more than 10 times better than a ring of speed +1, + * I don't think it's 100 times better. More like 30. + * this function yields: + * 1=1 * 2=3 * 3=5 * 4=8 * 5=11 * 6=15 * 7=21 + * 8=24 * 9=29 * 10=35 * 11=41 * 12=48 * 13=55 + * 14=63 * 15=71 * 20=120 * 25=181 * 30=255 + * which I think is acceptable. + * briefly, to get a +30 speed ring, it would be: + * 255*50000 or over 12 million experience + * points. For reference, a level 50 human requires + * 5 million xp. I'm sure it's doable, but it'd be + * *HARD* + * a speed+10 artifact would require 1.75 million. + * much more doable, but not too easily. + */ + factor = (pval * pval / 4 + pval); + if ( flags_select[i] == -1 ) + { + oldfactor = oldpval * oldpval / 4 + oldpval; + } + } + exp += xp * factor - xp * oldfactor; + } + if ( a_select_flags[i].group == 88 && a_select_flags[i].flag == -activation_select ) + { + exp += a_select_flags[i].xp; + } + } + } + if ( alchemist_has_stone() ) exp = exp / 4; + return exp; +} + +/* returns the 'real quantity' of items needed to empower + * a particular flag to a particular pval. + * Note that this routine returns zero for any flag that + * doesn't require some sort of action. + */ +int calc_rqty(int i, int pval, int oldpval) +{ + /* return 0 if flag is greater than size of flags_select && ! activation */ + if ( a_select_flags[i].group > 5 ) + { + if ( activation_select == a_select_flags[i].flag) + return 1; + else + return 0; + } + + /* return 0 if the flag wasn't set */ + if ( flags_select[i] < -1 || flags_select[i] == 0 ) + return 0; + + /* Return change in pval if the flag was already set */ + if ( flags_select[i] == -1 && a_select_flags[i].pval) + return pval - oldpval; + + /* Return pval if the flag will be set this time */ + else if ( a_select_flags[i].pval ) + return pval; + + /* Return 0 if the flag is unknown */ + else if ( flags_select[i] == -1 ) + return 0; + return 1; +} + +/* Handle the various items that creating artifacts requires. + * Mode = 0 to print a description, + * 1 to use up the items + * -1 to check to see if the items exist + * Note that this function is called ONLY from the + * other artifact item helper function. + */ + + +int check_artifact_items(int pval, int oldpval, int mode) +{ + int i, j, k, row = 1 , col = 15, rqty, orqty, trqty; + bool_ good = TRUE; + int temporary = -1; + char ch; + + /* For temporary items, waive the item requirements, + * except for the corpse... */ + for ( j = 0 ; a_select_flags[j].group ; j++) + if (a_select_flags[j].flag == 4*32 && flags_select[j] == 1 ) + temporary = j; + /* Check for enough items */ + for (i = 0; a_select_flags[i].group ; i++) + { + /* For temporary items, ignore + everything except the one item + */ + if (temporary != -1 && i != temporary) + continue; + + /* Calc quantity is done per flag, because + some have a pval, some don't, some where already + set at pval=2, etc + */ + rqty = orqty = calc_rqty(i, pval, oldpval); + + /* If no item is associated with this flag, + or this flag wasn't set or didn't change */ + if ( !a_select_flags[i].rtval || !rqty) + continue; + + for ( k = 0 ; k < INVEN_WIELD ; k++ ) + { + object_type *o_ptr = &p_ptr->inventory[k]; + + /* Note here that an rsval of -1 (which is read is 0xff + for a byte..) matches anything. */ + if (o_ptr->tval == a_select_flags[i].rtval + && (o_ptr->sval == a_select_flags[i].rsval + || a_select_flags[i].rsval == (byte) - 1 ) ) + { + /* Corpse validation is COMPLICATED! + * But at least we don't have to do this twice. + */ + if ( a_select_flags[i].rtval == TV_CORPSE ) + { + bool_ itemgood = TRUE; + + /*Specified race not this one */ + if ( o_ptr->pval2 != a_select_flags[i].rpval && a_select_flags[i].rpval) + continue; + + /* Race flag (any monster who...)*/ + for ( j = 0 ; !a_select_flags[i].rpval && a_select_flags[i].rflag[j] && j < 6 && itemgood ; j++) + { + int flag = a_select_flags[i].rflag[j] / 32; + u32b mask = 1 << (a_select_flags[i].rflag[j] % 32); + + switch (flag) + { + case 0: + if ( !(r_info[o_ptr->pval2].flags1 & mask) ) itemgood = FALSE; + break; + case 1: + if ( !(r_info[o_ptr->pval2].flags2 & mask) ) itemgood = FALSE; + break; + case 2: + if ( !(r_info[o_ptr->pval2].flags3 & mask) ) itemgood = FALSE; + break; + case 3: + if ( !(r_info[o_ptr->pval2].flags4 & mask) ) itemgood = FALSE; + break; + case 4: + if ( !(r_info[o_ptr->pval2].flags5 & mask) ) itemgood = FALSE; + break; + case 5: + if ( !(r_info[o_ptr->pval2].flags6 & mask) ) itemgood = FALSE; + break; + case 6: + if ( !(r_info[o_ptr->pval2].flags7 & mask) ) itemgood = FALSE; + break; + case 7: + if ( !(r_info[o_ptr->pval2].flags8 & mask) ) itemgood = FALSE; + break; + case 8: + if ( !(r_info[o_ptr->pval2].flags9 & mask) ) itemgood = FALSE; + break; + default: + msg_print("This code should never be hit!"); + } + } + if ( ! itemgood ) + continue; + + } + /* Validate pval of good item */ + else if ( a_select_flags[i].rpval) + { + /* Must have matching signs */ + if ( (o_ptr->pval < 0) != (a_select_flags[i].rpval < 0)) + continue; + /* Must be greater than */ + if ( abs(o_ptr->pval) < abs(a_select_flags[i].rpval)) + continue; + } + + trqty = MIN(o_ptr->number, rqty); + rqty -= trqty; + + if ( mode == 1 ) + { + inc_stack_size_ex(k, -trqty, NO_OPTIMIZE, DESCRIBE); + } + }/* if p_ptr->inventory item is acceptable */ + + } /*end of looping through the p_ptr->inventory*/ + + if (rqty) + { + good = FALSE; + /* Oops, we didn't have enough of this object + when actually creating the artifact. + unset this flag + */ + if ( mode == 1 ) + { + flags_select[i] = -4; + } + /* we only return false for mode -1, + * for mode 0 we display stuff, and for + * mode 1 we want to continue destroying things + * even if the player is missing one small item, + * because there's no way to change things now. + * We may have already destroyed a unique corpse, + * or some other hard-to-find item. + */ + if ( mode == -1 ) + return FALSE; + } + + /* Display a description of the required object, if needed */ + /* Note that the tests for good items HAVE to be in a different + place, because otherwise we don't know how many the player + has, as opposed to how many they need. + */ + if ( mode == 0 ) + { + char *o_name = al_name + a_select_flags[i].item_desc; + if (orqty > 1 && a_select_flags[i].pval && a_select_flags[i].item_descp) + o_name = al_name + a_select_flags[i].item_descp; + + if ( rqty ) + { + if ( orqty > 1 ) + c_prt(TERM_RED, format(" you are missing %d of the %d %s", rqty, orqty, o_name), row++, col); + else if ( is_a_vowel(o_name[0])) + c_prt(TERM_RED, format(" you are missing an %s", o_name), row++, col); + else + c_prt(TERM_RED, format(" you are missing a %s", o_name), row++, col); + } + else + { + if ( orqty > 1 ) + c_prt(TERM_GREEN, format(" you have the %d %s", orqty, o_name), row++, col); + else if ( is_a_vowel(o_name[0])) + c_prt(TERM_GREEN, format(" you have an %s", o_name), row++, col); + else + c_prt(TERM_GREEN, format(" you have a %s", o_name), row++, col); + } + + if ( row > 21 ) + { + row = 1; + if (!good) + (void)get_com("You are missing some items:", &ch); + else + (void)get_com("You have these needed items on hand:", &ch); + } + + } + + } /* End of group associated with this a_select_flags entry */ + + if ( mode == 0 ) + { + while ( row < 22 ) + c_prt(TERM_GREEN, " ", row++, col); + if (!good) + (void)get_com("You are missing some items:", &ch); + else + (void)get_com("You have these needed items on hand:", &ch); + } + return good; +} + +/* Display a list of required essences, + * and/or use up the essences. */ +bool_ artifact_display_or_use(int pval, int oldpval, bool_ use) +{ + int essence[MAX_BATERIE_SVAL]; + int essenceh[MAX_BATERIE_SVAL]; + int al_idx, i, j, k; + bool_ enough; + + /* Temporary Items require only one item, and no essences. */ + for ( i = 0 ; a_select_flags[i].group ; i++) + if ( a_select_flags[i].flag == 32*4) + { + if ( use ) + return check_artifact_items(pval, oldpval, 1); + else + return check_artifact_items(pval, oldpval, 0); + } + + for ( i = 0 ; i < MAX_BATERIE_SVAL ; i++ ) + essence[i] = essenceh[i] = 0; + + /* Accumulate a list of required essences */ + for ( al_idx = 0; al_idx < max_al_idx ; al_idx++ ) + if ( alchemist_recipes[al_idx].tval == 0 ) + for ( i = 0 ; a_select_flags[i].group ; i++) + { + int rqty = calc_rqty(i, pval, oldpval); + + /* If the flag isn't being set, rqty will be zero */ + if ( !rqty) + continue; + + if ( alchemist_recipes[al_idx].sval == a_select_flags[i].flag ) + essence[alchemist_recipes[al_idx].sval_essence] += + alchemist_recipes[al_idx].qty * rqty; + } + + /* The essence array now contains a list of all essences + * that will be consumed in the creation of this artifact */ + + /* Check for existence of required quatities of essences. */ + for ( i = 0 ; i < INVEN_WIELD ; i++ ) + { + for ( j = 0 ; j < MAX_BATERIE_SVAL ; j++) + if ( p_ptr->inventory[i].tval == TV_BATERIE && p_ptr->inventory[i].sval == j + 1) + { + essenceh[j] += p_ptr->inventory[i].number; + } + } + + /* Check for enough essences */ + enough = TRUE; + for ( i = 0 ; i < MAX_BATERIE_SVAL ; i++) + if ( essenceh[i] < essence[i] ) + { + enough = FALSE; + break; + } + + /* Check for items */ + if ( enough ) + enough = check_artifact_items(pval, oldpval, -1); + + + /* Display recipe list if they don't have enough, or not enough exp */ + if (!enough || !use ) + { + int row = 1 , col = 15; + bool_ good = FALSE; + char ch; + + /* display of list of required essences */ + /* Note: there are only 12 or so essences, so this list + * will ALWAYS fit on the screen */ + for ( i = 0 ; i < MAX_BATERIE_SVAL ; i++) + if ( essence[i] ) + { + int missing = -MIN(essenceh[i] - essence[i], 0); + good = TRUE; + if ( missing ) + c_prt(TERM_RED, format("%d of the required %d essences of %s", + missing, essence[i], + k_name + k_info[lookup_kind(TV_BATERIE, i + 1)].name ), + row++, col); + else + c_prt(TERM_GREEN, format("you have the needed %d essences of %s", + essence[i], + k_name + k_info[lookup_kind(TV_BATERIE, i + 1)].name ), + row++, col); + } + + if (good) + { + /* blank the bottom row */ + c_prt(TERM_WHITE, " ", row++, col); + + /* and wait for a key */ + (void)get_com("You are currently missing:", &ch); + } + + /* Display a list of needed items as well */ + check_artifact_items(pval, oldpval, 0); + + return FALSE; + } + + /* If we get to this point in the code, then the player + * has the required essences and items in their p_ptr->inventory */ + + /* If they do have enough, and they have enough exp, consume them */ + for (i = 0 ; i < MAX_BATERIE_SVAL ; i++) + for ( k = 0 ; k < INVEN_WIELD && essence[i] > 0 ; k++) + if (p_ptr->inventory[k].tval == TV_BATERIE + && p_ptr->inventory[k].sval == i + 1 + && essence[i]) + { + int num = p_ptr->inventory[k].number; + + inc_stack_size_ex(k, MAX( -essence[i], -num), NO_OPTIMIZE, DESCRIBE); + + essence[i] -= MIN(num, essence[i]); + } + + /* Destroy the items needed */ + check_artifact_items(pval, oldpval, 1); + + return TRUE; +} + + +void display_activation_info(int num) +{ + object_type forge; + int i; + + + /* find the a_select_flags number of this activation type... */ + for ( i = 0 ; a_select_flags[i].group ; i++) + if (a_select_flags[i].group == 88 && a_select_flags[i].flag == -num ) + break; + + object_wipe(&forge); + forge.xtra2 = num; + /* Print out various information about this activation... */ + /* min level, experience, required items (and essences) + full description (from activation_aux) */ + if (wizard) + c_prt(TERM_WHITE, format(" number:%d ", num), 5, 5); + else + c_prt(TERM_WHITE, " ", 5, 5); + c_prt(TERM_WHITE, format(" Level:%d ", a_select_flags[i].level), 6, 5); + c_prt(TERM_WHITE, format(" Exp :%d ", a_select_flags[i].xp), 7, 5); + c_prt(TERM_WHITE, format(" Item :%s ", al_name + a_select_flags[i].item_desc), 8, 5); + c_prt(TERM_WHITE, " ", 9, 5); + c_prt(TERM_WHITE, format(" %s ", activation_aux(&forge, 0, 0)), 9, 5); + c_prt(TERM_WHITE, " ", 10, 5); + inkey(); +} + +void select_an_activation(void) +{ + int i, lev, wid, hgt, begin = 0, sel = 0; + u32b max; + cptr act_list[150]; /* currently, ~127 hardcoded activations */ + int act_ref[150]; + char c; + /* How do we want to do this? */ + /* Ideally, we let them select from a list, which includes all the activations that they've ecountered in any form. + Problems with this idea include mainly the lack of any (current) place to store which activations they've seen, and + that they'll not get credit for any seen before we start tracking it. + + So - list is everything. If they select one which they're to low-level for + or if the explicitly request it, we'll display info about this item. + We'll also get our descriptions from the activation_aux(ACT_CONSTANT) + function, because they are more complete, and include even lua-scripted ones. + msg_print("Since the code to actually let you select one isn't here"); + msg_print("You will automatically get the activation 'Dawn'"); + activation_select = ACT_DAWN; + */ + + /* Build a list of available activations at the player's level */ + lev = get_skill(SKILL_ALCHEMY); + for ( i = max = 0 ; max < (sizeof(act_list) / sizeof(cptr)) && a_select_flags[i].group ; i++) + if (a_select_flags[i].group == 88 && a_select_flags[i].level <= lev ) + { + act_ref[max] = -a_select_flags[i].flag; /* Activation number */ + act_list[max++] = al_name + a_select_flags[i].desc; /* Description */ + } + + /* Select from that list, using the util.c function display_list to display the scrolled list */ + /* Note: I think that there is only one other place that uses this function. Should be more! */ + while (1) + { + Term_clear(); + Term_get_size(&wid, &hgt); + + c_prt(TERM_WHITE, "Enter to select, ? for more information, 2 and 8 to scroll ", 0, 0); + display_list(1, 0, hgt - 2, wid - 2, "Select an Activation", act_list, max, begin, sel, TERM_L_GREEN); + + c = inkey(); + + if (c == ESCAPE) break; + else if (c == '8') + { + sel--; + if (sel < 0) + { + sel = max - 1; + begin = max - hgt; + if (begin < 0) begin = 0; + } + if (sel < begin) begin = sel; + } + else if (c == '2') + { + sel++; + if (sel >= (s32b)max) + { + sel = 0; + begin = 0; + } + if (sel >= begin + hgt - 1) begin++; + } + else if (c == '?') + { + display_activation_info(act_ref[sel]); + } + else if (c == '\r') + { + display_activation_info(act_ref[sel]); + activation_select = act_ref[sel]; + return; + } + } + activation_select = 0; +} + + +/* Consume 'num' magic essences and return true. + * If there aren't enough essences, return false */ + +bool_ magic_essence(int num) +{ + int i; + int j = 0; + + for (i = 0; i < INVEN_WIELD; i++) + { + object_type *o_ptr = &p_ptr->inventory[i]; + + /* Count the magic essences */ + if (o_ptr->k_idx && (o_ptr->tval == TV_BATERIE) && (o_ptr->sval == SV_BATERIE_MAGIC)) j += o_ptr->number; + } + + /* Abort if not enough essences. */ + if (j < num) return FALSE; + + /* Consume them */ + i = 0; + j = num; + while (i < INVEN_WIELD) + { + object_type *o_ptr = &p_ptr->inventory[i]; + + if (o_ptr->k_idx && (o_ptr->tval == TV_BATERIE) && (o_ptr->sval == SV_BATERIE_MAGIC)) + { + /* This can lead to invalid object pointer for objects + * that come after the magic essences. Therefore, every + * artifactable object should come before the essences. + */ + j -= o_ptr->number; + inc_stack_size(i, -num); + num = j; + if (num <= 0) break; + /* Stay on this slot; do not increment i. */ + } + else + { + /* Move on to the next slot. */ + i++; + } + } + + /* Sanity check. */ + if (num > 0) + { + msg_format("ERROR: Couldn't destroy %d essences!", num); + return FALSE; + } + + return TRUE; +} + + +void do_cmd_create_artifact(object_type *q_ptr) +{ + int max, i = 0, j, cur_set = 0, abord = FALSE, done = FALSE; + int skill; + s32b exp = 0; + + char out_val[160]; + char choice = 0; + bool_ lockpval = FALSE; + int pval; + int oldpval; + energy_use = 100; + + pval = q_ptr->pval; + oldpval = pval; + skill = get_skill(SKILL_ALCHEMY); + + if ( !pval ) + pval = 1; + /* No activation added on this round */ + activation_select = 0; + + /* Save the current flags */ + for (i = 0 ; a_select_flags[i].group ; i++) + { + if ( a_select_flags[i].flag < 0 || a_select_flags[i].group > 5) + continue; + + flags_select[i] = 0; + + switch (a_select_flags[i].flag / 32) + { + case 0: + if (q_ptr->art_flags1 & 1 << (a_select_flags[i].flag % 32)) flags_select[i] = -1; + break; + case 1: + if (q_ptr->art_flags2 & 1 << (a_select_flags[i].flag % 32)) flags_select[i] = -1; + break; + case 2: + if (q_ptr->art_flags3 & 1 << (a_select_flags[i].flag % 32)) flags_select[i] = -1; + break; + case 3: + if (q_ptr->art_flags4 & 1 << (a_select_flags[i].flag % 32)) flags_select[i] = -1; + break; + case 4: + if (q_ptr->art_flags5 & 1 << (a_select_flags[i].flag % 32)) flags_select[i] = -1; + break; + case 5: + if (q_ptr->art_esp & 1 << (a_select_flags[i].flag % 32)) flags_select[i] = -1; + break; + default: + /*This will not be hit, inspite of activations, because of the <= 5 above...*/ + break; + } + /* + this would learn about ALL flags.... + if(wizard) + alchemist_known_artifacts[a_select_flags[i].flag/32] = 0xffffffffL; + */ + + /* Set various flags if they haven't *ID*'d an artifact with this flag set.*/ + if ( !(alchemist_known_artifacts[a_select_flags[i].flag / 32] & (1 << (a_select_flags[i].flag % 32)) )) + { + /* If this item has an ability that depends on pval which the player + * cannot set, don't allow them to change the pval either. */ + if ( a_select_flags[i].pval && flags_select[i]) + lockpval = TRUE; + + /* Set the color and set-ablitity of this flag */ + if ( flags_select[i] ) + flags_select[i] = -3; + else + flags_select[i] = -2; + continue; + } + else if ( skill < a_select_flags[i].level ) + { + /* If the alchemist has not passed the skill level for this flag, + Set this flag as unsettable. + */ + if ( flags_select[i]) + lockpval = TRUE; + else + flags_select[i] = -4; + } + } + + /* Save the screen */ + character_icky = TRUE; + Term_save(); + Term_clear(); + + + /* Everlasting love ... ... nevermind :) */ + while ( !done && !abord) + { + c_prt((q_ptr->exp - exp > 0) ? TERM_L_GREEN : TERM_L_RED, format("Experience left: %ld", q_ptr->exp - exp), 2, 0); + + /* Display the menu, but don't display it if we just + * displayed a message (it erases the screen, creating a blink message */ + if ( cur_set < 6 || cur_set == 7 ) + show_levels(); + + c_prt((q_ptr->exp - exp > 0) ? TERM_L_GREEN : TERM_L_RED, format("Experience left: %ld", q_ptr->exp - exp), 2, 0); + + prt("Enter to accept, Escape to abort", 1, 0); + + abord = !get_com("Play around with which group of powers?[a-g]", &choice); + + if ( choice == ESCAPE) + abord = TRUE; + + if ( abord ) + continue; /*or break, same diff */ + + if ( isalpha(choice)) + { + if (isupper(choice)) + choice = tolower(choice); + cur_set = A2I(choice); + } + else + { + bell(); + continue; + } + + if ( cur_set == 5 ) + { + if (q_ptr->xtra2 && !activation_select + && !get_check("This item already activates! Choose a different activation?")) continue; + select_an_activation(); + exp = get_flags_exp(pval, oldpval); + continue; + } + if ( cur_set == 6 ) + { + msg_print("This option is not available"); + continue; + } + if ( cur_set == 7 ) + { + artifact_display_or_use(pval, oldpval, FALSE); + continue; + } + if ( cur_set == 8 ) + { + if (q_ptr->exp - exp < 0) + msg_print("Not enough experience for the flags you've selected."); + else + done = TRUE; + continue; + } + + if (cur_set < 0 || cur_set > 4 ) + { + bell(); + continue; + } + + + while (!done && !abord) + { + /* Chose the flags */ + exp = 0; + max = show_flags(cur_set, pval); + exp = get_flags_exp(pval, oldpval); + c_prt((q_ptr->exp - exp > 0) ? TERM_L_GREEN : TERM_L_RED, format("Experience left: %ld", q_ptr->exp - exp), 2, 0); + + /* Build a prompt (accept all flags) */ + if (max <= 26) + { + /* Build a prompt (accept all flags) */ + strnfmt(out_val, 78, "(Flags %c-%c, I,D to change power level) Add/Remove which flag? ", + I2A(0), I2A(max - 1)); + } + else + { + strnfmt(out_val, 78, "(Flags %c-%c, I,D to change power level) Add/Remove which flag? ", + I2A(0), '0' + max - 27); + } + c_prt(TERM_L_BLUE, format("Power(I/D to increase/decrease): %d", pval), 3, 0); + + /* Get a spell from the user */ + while (!(done = !get_com(out_val, &choice))) + { + if (choice == 'I') + { + if ( lockpval ) + { + msg_print("You cannot do that - you don't know how!"); + continue; + } + if (q_ptr->exp - exp < 0) + { + msg_print("Not enough experience. Decrease power or deselect flags."); + continue; + } + pval++; + break; + } + else if (choice == 'D') + { + if ( lockpval ) + { + msg_print("You cannot do that - you don't know how!"); + continue; + } + pval--; + if (pval < oldpval) pval = oldpval; + break; + } + else if (choice == '\r' || choice == ESCAPE || choice == ' ') + { + done = TRUE; + break; + } + else if (isalpha(choice)) + { + /* Lowercase */ + if (isupper(choice)) choice = tolower(choice); + + /* Extract request */ + i = (islower(choice) ? A2I(choice) : -1); + } + else + { + i = D2I(choice) + 26; + + /* Illegal */ + if (i < 26) i = -1; + } + + /* Totally Illegal */ + if ((i < 0) || (i >= max)) + { + bell(); + continue; + } + else + { + /*Find the i'th flag in group cur_set...*/ + for ( j = 0 ; a_select_flags[j].group ; j++) + if (a_select_flags[j].group == cur_set + 1) + if (!i--) break; + + if ( flags_select[j] == -4 ) + { + msg_format("You need at least %d skill in alchemy.", + a_select_flags[j].level); + continue; + } + if ( flags_select[j] != 0 && flags_select[j] != 1) + { + bell(); + continue; + } + if (flags_select[j]) flags_select[j] = 0; + else if (!flags_select[j]) + { + if (q_ptr->exp - exp < 0) + { + msg_print("Not enough experience. Decrease power or deselect flags."); + continue; + } + flags_select[j] = 1; + } + break; + } + } + }/*sub-screen select and redraw loop*/ + done = FALSE; + Term_clear(); + }/* main screen (flag select screen) select and redraw loop*/ + + /* Abort if not enough experience, or no flags added */ + if ( q_ptr->exp - exp < 0 || exp == 0 ) + abord = TRUE; + + /* Display the recipe, or use up the essences. + * Note that this has to be done before the screen + * is restored. This is because it's also called from + * within the loop to display the required items. */ + if ( !abord ) + if (!artifact_display_or_use(pval, oldpval, TRUE)) + abord = TRUE; + + /* Restore the screen */ + Term_load(); + character_icky = FALSE; + + /* Return if abort, or missing ingredients */ + if ( abord ) + return; + + /* Actually create the artifact */ + q_ptr->exp -= exp; + q_ptr->art_flags4 &= ~TR4_ART_EXP; + q_ptr->pval = pval; + + /* Just to be sure */ + q_ptr->art_flags3 |= ( TR3_IGNORE_ACID | TR3_IGNORE_ELEC | + TR3_IGNORE_FIRE | TR3_IGNORE_COLD ); + + { + int now = 0, before = 0; + char dummy_name[80]; + char new_name[80]; + + /* Apply the flags */ + for (i = 0; a_select_flags[i].group ; i++) + { + if (flags_select[i] < 0) + before++; + else if ( flags_select[i] == 1) + { + now++; + switch (a_select_flags[i].flag / 32) + { + case 0: + q_ptr->art_flags1 |= 1 << (a_select_flags[i].flag % 32); + break; + case 1: + q_ptr->art_flags2 |= 1 << (a_select_flags[i].flag % 32); + break; + case 2: + q_ptr->art_flags3 |= 1 << (a_select_flags[i].flag % 32); + break; + case 3: + q_ptr->art_flags4 |= 1 << (a_select_flags[i].flag % 32); + break; + case 4: + q_ptr->art_flags5 |= 1 << (a_select_flags[i].flag % 32); + break; + case 5: + q_ptr->art_esp |= 1 << (a_select_flags[i].flag % 32); + break; + default: + msg_print("error: this code can't ever be hit!"); + } + } + } + + if ( activation_select ) + { + q_ptr->art_flags3 |= TR3_ACTIVATE; + q_ptr->xtra2 = activation_select; + } + + + /* Set the 'show modifier' flag */ + q_ptr->art_flags3 |= TR3_SHOW_MODS; + + /* For temporary items, set a timeout. + * alchemist_skill^2 for now */ + if ( q_ptr->art_flags5 & TR5_TEMPORARY ) + { + int lev = get_skill(SKILL_ALCHEMY); + q_ptr->timeout = lev * lev * 3; + } + + /* Describe the new artifact */ + object_out_desc(q_ptr, NULL, FALSE, TRUE); + + + /* Name the new artifact */ + strcpy(dummy_name, "of an Alchemist"); + if (!(get_string("What do you want to call the artifact? ", dummy_name, 80))) + strcpy(new_name, "of an Alchemist"); + else + { + if ((strncmp(dummy_name, "of ", 3) == 0) || + (strncmp(dummy_name, "Of ", 3) == 0) || + ((dummy_name[0] == '\'') && + (dummy_name[strlen(dummy_name) - 1] == '\''))) + { + strcpy(new_name, dummy_name); + } + else + { + strcpy(new_name, "called '"); + strcat(new_name, dummy_name); + strcat(new_name, "'"); + } + } + /* Identify it fully */ + object_aware(q_ptr); + object_known(q_ptr); + + /* Mark the item as fully known */ + q_ptr->ident |= (IDENT_MENTAL); + q_ptr->ident |= IDENT_STOREB; /* This will be used later on... */ + + /* Save the inscription */ + q_ptr->art_name = quark_add(new_name); + q_ptr->found = OBJ_FOUND_SELFMADE; + + done = FALSE; + while (!done && get_com("Do you want to let this item continue to gain experience?", &choice)) + { + switch (choice) + { + case 'y': + case 'Y': + if (magic_essence(get_skill(SKILL_ALCHEMY))) + q_ptr->art_flags4 |= TR4_ART_EXP; + else + msg_format("Oh, NO! You don't have enough magic essences. You needed %d.", get_skill(SKILL_ALCHEMY)); + done = TRUE; + break; + case 'n': + case 'N': + q_ptr->exp = 0; + done = TRUE; + break; + } + } + + /* Cycle through the p_ptr->inventory, and optimize everything. + * This wasn't done earlier, because if we had, then + * things in the p_ptr->inventory would shift around, and q_ptr + * wouldn't point to the right thing. BUT, at this point + * we don't need q_ptr anymore, so optimizing the p_ptr->inventory + * becomes sane. Sticky bug to figure out, let me tell you. + * Note also that this is cycling backwards - this is so + * that the same effect doesn't cause us to skip items. */ + for ( i = INVEN_WIELD - 1 ; i >= 0 ; i-- ) + inven_item_optimize(i); + } + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP); +} + +/* + * Test to see if this tval/sval combo is in the alchemists' + * recipes as a createable item. Used to determine if we + * should extract from it. + */ +bool_ alchemist_exists(int tval, int sval, int ego, int artifact) +{ + int al_idx; + + /* To prevent conflicts with recipes for ego-items. + * artifact not used, simplifies the loop below. */ + if ((tval == 1) || artifact) + return FALSE; + + /*Search for recipes with this tval/sval combo as the final result*/ + for (al_idx = 0 ; al_idx < max_al_idx ; al_idx++) + { + int rtval = alchemist_recipes[al_idx].tval; + int rsval = alchemist_recipes[al_idx].sval; + + /* Accept ego wands and staves since ego is extracted last */ + if (((!ego || tval == TV_WAND || tval == TV_STAFF) && rtval == tval && rsval == sval) || + ( ego && rtval == 1 && rsval == ego)) + { + return TRUE; + } + } + return FALSE; +} + + +/* + * Hook to determine if an object can have things extracted from it. + */ +bool_ item_tester_hook_extractable(object_type *o_ptr) +{ + + /* No artifacts */ + if (artifact_p(o_ptr)) return (FALSE); + + /* No cursed things */ + if (cursed_p(o_ptr)) return (FALSE); + + /* If we REALLY wanted to rebalance alchemists, + * we'd test for 'fully identified this object kind' here. + */ + + return ((o_ptr->tval == TV_ROD_MAIN && o_ptr->pval != 0) + || alchemist_exists(o_ptr->tval, o_ptr->sval, o_ptr->name2, o_ptr->name1)); +} + +/* + * Hook to determine if an object is empowerable (NOT rechargeable) + */ +bool_ item_tester_hook_empower(object_type *o_ptr) +{ + int sval = -1; + int lev = get_skill(SKILL_ALCHEMY); + /* after level 25, can empower ego items to create artifacts + * and double ego items. + * after level 50, can empower artifacts to create powerful artifacts + */ + + /* Never Empower a cursed item */ + if ( cursed_p(o_ptr)) + { + return FALSE; + } + + /* Allow finalizing a self created artifact */ + if (artifact_p(o_ptr) + && (o_ptr->art_flags4 & TR4_ART_EXP) + && !(o_ptr->art_flags4 & TR4_ULTIMATE)) + return TRUE; + + switch ( o_ptr->tval) + { + /* Empowerable objects: Traditional alchemist stuff */ + case TV_WAND: + sval = SV_WAND_NOTHING; + break; + case TV_RING: + sval = SV_RING_NOTHING; + break; + case TV_STAFF: + sval = SV_STAFF_NOTHING; + break; + case TV_BOTTLE: + sval = 1; + break; + case TV_AMULET: + sval = SV_AMULET_NOTHING; + break; + case TV_SCROLL: + sval = SV_SCROLL_NOTHING; + break; + case TV_ROD: + sval = SV_ROD_NOTHING; + break; + case TV_ROD_MAIN: + sval = -1; + break; + case TV_BOOK: + sval = -1; + break; + + /* Ego item stuff */ + /* Disallow ego dragon armour before you can create artifacts.*/ + case TV_DRAG_ARMOR: + if ( lev < 25) + return FALSE; + /* FALL THROUGH! no break here. */ + + /* weapons */ + + case TV_DAEMON_BOOK: + case TV_SWORD: + case TV_HAFTED: + case TV_POLEARM: + case TV_AXE: + case TV_MSTAFF: + + /* misc other items */ + case TV_BOW: + case TV_BOOMERANG: + case TV_INSTRUMENT: + case TV_DIGGING: + case TV_LITE: + + /* Ammo */ + case TV_SHOT: + case TV_ARROW: + case TV_BOLT: + + /* Armor of various sorts */ + case TV_BOOTS: + case TV_GLOVES: + case TV_HELM: + case TV_CROWN: + case TV_SHIELD: + case TV_CLOAK: + case TV_SOFT_ARMOR: + case TV_HARD_ARMOR: + + /* Disallow ANY creation of ego items below level 5*/ + if ( lev < 5) + return FALSE; + + /* empowering an ego item creates an artifact or a + * double ego item, disallow below level 25 */ + if ( lev < 25 && o_ptr->name2) + return FALSE; + + /* Disallow double-ego and artifact unless the character has + * the artifact creation ability. */ + if (!has_ability(AB_CREATE_ART) && + (artifact_p(o_ptr) || (o_ptr->name2 && o_ptr->name2b))) + return FALSE; + + /* Otherwise... */ + return TRUE; + + default: + return FALSE; + } + + /* Return to the traditional alchemist objects. + * All ego items and artifacts returning TRUE are accepted as artifactable + * at level 25. If we want double ego non wieldable items (Fireproof Staff + * of Plenty) the artifactable test in do_cmd_alchemist() must be changed, + * e.g. checking if the item is wearable. + * For now, we disallow non-wearable ego-items and artifacts here. + */ + + if ((o_ptr->name2 || artifact_p(o_ptr)) && + o_ptr->tval != TV_RING && o_ptr->tval != TV_AMULET) + return FALSE; + + /* return true if it's a 'of nothing' item; + * does nothing for TV_ROD_MAIN and TV_BOOK + */ + return (sval == o_ptr->sval + + /* or if it's artifactable */ + || ((lev >= 50 || (lev >= 25 && !artifact_p(o_ptr))) && + (o_ptr->tval == TV_RING || o_ptr->tval == TV_AMULET)) + + /* or if it's egoable (note that normal egos start at level 5, wands and such start at 15) */ + || (!o_ptr->name2 && lev >= 15)); +} + +/* Extract a rod tip from a rod */ +void rod_tip_extract(object_type *o_ptr) +{ + object_type *q_ptr; + object_type forge; + + /* Get local object */ + q_ptr = &forge; + + /* Paranoia, return if it's a rod of nothing */ + if (o_ptr->pval == SV_ROD_NOTHING) + return; + + /* Extract the rod tip */ + object_prep(q_ptr, lookup_kind(TV_ROD, o_ptr->pval)); + + q_ptr->number = o_ptr->number; + + object_aware(q_ptr); + object_known(q_ptr); + (void)inven_carry(q_ptr, FALSE); + + /* Remove it from the rod */ + o_ptr->pval = SV_ROD_NOTHING; + + /* Window stuff */ + p_ptr->window |= (PW_INVEN); +} + + +/* Begin & finish an art */ +void do_cmd_toggle_artifact(object_type *o_ptr) +{ + char o_name[80]; + + if (!(o_ptr->art_flags4 & TR4_ART_EXP)) + { + bool_ okay = TRUE; + + if ( !alchemist_has_stone()) + { + msg_print("Creating an artifact will result into a permanent loss of 10 hp."); + if (!get_check("Are you sure you want to do that?")) return; + } + + if (!magic_essence(get_skill(SKILL_ALCHEMY))) + { + msg_format("You need %d magic essences.", get_skill(SKILL_ALCHEMY)); + return; + } + + /* Description */ + object_desc(o_name, o_ptr, FALSE, 0); + + if (o_ptr->number > 1) + { + msg_print("Not enough energy to enchant more than one object!"); + msg_format("%d of your %s %s destroyed!", (o_ptr->number) - 1, o_name, (o_ptr->number > 2 ? "were" : "was")); + o_ptr->number = 1; + } + okay = TRUE; + + if (!okay) return; + + /* he/she got warned */ + p_ptr->hp_mod -= 10; + + /* Ok toggle it */ + o_ptr->art_flags4 |= TR4_ART_EXP; + o_ptr->name2 = 0; + o_ptr->name2b = 0; + o_ptr->art_name = quark_add("Becoming"); + + /* Copy the object_kind flags to the artifact flags. + * Note that this is only needed so that flags set in the + * 'kind' area are visible when finalizing the artifact. + */ + { + u32b f1, f2, f3, f4, f5, esp; + + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + o_ptr->art_flags1 |= f1; + o_ptr->art_flags2 |= f2; + o_ptr->art_flags3 |= f3; + o_ptr->art_flags4 |= f4; + o_ptr->art_flags5 |= f5; + o_ptr->art_esp |= esp; + } + + p_ptr->update |= (PU_HP); + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + } + else + { + do_cmd_create_artifact(o_ptr); + } +} + +/* + * Test to see if they have all the ingredients to create an item. + * (doesn't count base item) + * creates 'tocreate' items (may be -1, but no more than that!) + * if tocreate=0, will return true if the player has enough + * in their p_ptr->inventory to empower that item. + */ +bool_ alchemist_items_check(int tval, int sval, int ego, int tocreate, bool_ message) +{ + int al_idx, j; + bool_ exists = FALSE; + + + for ( al_idx = 0 ; al_idx < max_al_idx ; al_idx++ ) + if ((ego && alchemist_recipes[al_idx].sval == ego + && alchemist_recipes[al_idx].tval == 1 ) + || (!ego && alchemist_recipes[al_idx].sval == sval + && alchemist_recipes[al_idx].tval == tval)) + { + exists = TRUE; + /* Create the essences */ + if (tocreate > 0) + { + object_type forge; + object_type *o_ptr = &forge; + + object_wipe(o_ptr); + object_prep(o_ptr, lookup_kind(TV_BATERIE, alchemist_recipes[al_idx].sval_essence)); + o_ptr->number = alchemist_recipes[al_idx].qty * tocreate; + /* Don't bother with apply_magic */ + + /* Randomly decrease the number of essences created */ + if ( randint(3) == 1 + && randint(52) > get_skill(SKILL_ALCHEMY) + && !alchemist_has_stone()) + o_ptr->number /= randint(2) + 1; + if ( o_ptr->number == 0) + continue; + object_aware(o_ptr); + object_known(o_ptr); + if (inven_carry_okay(o_ptr)) + { + int i; + inven_carry(o_ptr, FALSE); + for (i = 0; i < INVEN_WIELD ; i++) + if (p_ptr->inventory[i].tval == o_ptr->tval && p_ptr->inventory[i].sval == o_ptr->sval) + { + if ( message ) + inven_item_describe(i); + break; + } + + } + else + drop_near(o_ptr, 0, p_ptr->py, p_ptr->px); + + o_ptr->ident |= IDENT_STOREB; + } + else if ( tocreate < -1) + { + /*It's not valid to create more than one + * thing at a time, so if it's less than -1, + * it must be time to display a recipe + */ + msg_format("%d essences of %d", + alchemist_recipes[al_idx].qty, + al_idx); + } + else /* Destroy the essences (tocreate == -1) + * or check for existence(tocreate == 0)*/ + { + int rqty = alchemist_recipes[al_idx].qty; + for (j = 0; j < INVEN_WIELD; j++) + { + object_type *o_ptr = &p_ptr->inventory[j]; + if (o_ptr->k_idx + && (o_ptr->tval == TV_BATERIE ) + && (o_ptr->sval == alchemist_recipes[al_idx].sval_essence ) + && (o_ptr->number >= rqty )) + { + /* At this point, the item is required, destroy it. */ + if ( tocreate ) + { + inc_stack_size_ex(j, 0 - rqty, OPTIMIZE, message ? DESCRIBE : NO_DESCRIBE); + } + + /* When we find enough of the item, break out of the + * 'search through the p_ptr->inventory' loop */ + break; + } + } + if ( j == INVEN_WIELD) + /* This ingredient was not found, cannot do recipe */ + return FALSE; + }/*destroying items, or just checking for existence */ + } + return exists; +} + +/* This function lists all the ingredients + * needed to create something. + */ +void alchemist_display_recipe(int tval, int sval, int ego) +{ + int al_idx; + int row = 1, col = 15; + char o_name[80]; + char ch; + object_type *o_ptr, forge; + + /* Display the ingredients for a recipe */ + for ( al_idx = 0 ; al_idx < max_al_idx ; al_idx++ ) + if ((ego && alchemist_recipes[al_idx].sval == ego + && alchemist_recipes[al_idx].tval == 1 ) + || (!ego && alchemist_recipes[al_idx].sval == sval + && alchemist_recipes[al_idx].tval == tval)) + { + int qty = alchemist_recipes[al_idx].qty; + c_prt(TERM_GREEN, + format(" %d essence%s %s ", qty, + qty > 1 ? "s" : "", + k_name + k_info[lookup_kind(TV_BATERIE, alchemist_recipes[al_idx].sval_essence)].name ), + row++, col); + } + + c_prt(TERM_WHITE, " ", row++, col); + + if (!ego) + { + /* Find the name of that object */ + o_ptr = &forge; + object_prep(o_ptr, lookup_kind(tval, sval)); + o_ptr->name2 = ego; + hack_apply_magic_power = -99; + apply_magic(o_ptr, get_skill(SKILL_ALCHEMY) * 2, FALSE, FALSE, FALSE); + object_aware(o_ptr); + object_known(o_ptr); + /* the 0 mode means only the text, leaving off any numbers */ + object_desc(o_name, o_ptr, FALSE, 0); + } + else + { + /* Display the ego item name */ + strcpy(o_name, e_name + e_info[ego].name); + } + + /* Display a short message about it, and wait for a key. */ + (void)get_com(format("ingredients needed to create a %s", o_name), &ch); + +} + +/* + * + * The alchemist_recipe_select was copied from + * wiz_create_itemtype + * and then changed quite a bit. + * + */ + +/* + The select array is a simple array of 'use this char to select item x' + It has 88 items (three columns of 20 each) + selectitem is initilized with the reverse mappings: + selectitem[selectchar[x]] == x is always true. + */ +char selectchar[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*():;,.<=>[]{}/=?+'~"; +byte selectitem[256]; + +void strip_and_print(const char *str, int color, int num) +{ + int row = 2 + (num % 20), col = 40 * (num / 20); + int ch, max_len = 0; + char buf[80]; + char *string; + + if (num > 60) + { + msg_print("Attempting to display too many items!"); + return; + } + ch = selectchar[num]; + if (selectitem[ch] != num) + { + int i; + for ( i = 0 ; i < 256 ; i++) + selectitem[i] = 0xff; + for ( i = 0 ; selectchar[i] ; i++) + selectitem[(byte)selectchar[i]] = i; + } + + /* Skip past leading characters */ + while ((*str == ' ') || (*str == '&')) str++; + + /* Copy useful chars */ + for (string = buf; *str; str++) + if (*str != '~') *string++ = *str; + + /* Terminate the new name */ + *string = '\0'; + + /* strip the name down to size + if (76-col < (signed)max_len) + max_len = 76-col; + else + max_len = 30-6;*/ + max_len = 39; + + string = buf; + if (strlen(string) > (unsigned)max_len) + string = string + (strlen(string) - max_len); + + /* Print it */ + c_prt(color, format("[%c] %s", ch, string), row, col); +} + +/* Display a list of recipes that need a particular essence. + * Note that we display a list of essences first, + * so in effect, this is the alchemist's recipe book. + */ +void alchemist_recipe_book(void) +{ + int num, max_num, i, al_idx, bat, kidx; + int choice[61], choice2[61]; + int mod40; + bool_ essence[MAX_BATERIE_SVAL + 1]; + char ch; + + /* Save and clear the screen */ + character_icky = TRUE; + Term_save(); + + while ( TRUE ) + { + Term_clear(); + + num = 0; + + /* Display bateries */ + + /* start with assumption that the alchemist knows about no recipes */ + for (i = 0; i < MAX_BATERIE_SVAL + 1 ; i++) + essence[i] = FALSE; + + /* cycle through all alchemist recipes */ + for (al_idx = 0 ; al_idx < max_al_idx ; al_idx++) + /* if we aren't already going to display this essence */ + if (!essence[alchemist_recipes[al_idx].sval_essence]) + { + + /*Note that we don't display artifact recipes here...*/ + /*This is partially because artifacts often require exotic + ingredients as well */ + + if (!alchemist_recipes[al_idx].tval) + continue; + + if (alchemist_recipes[al_idx].tval == 1) + { + if (alchemist_known_egos[alchemist_recipes[al_idx].sval / 32] + & (1 << (alchemist_recipes[al_idx].sval % 32)) ) + essence[alchemist_recipes[al_idx].sval_essence] = TRUE; + continue; + } + + kidx = lookup_kind(alchemist_recipes[al_idx].tval, alchemist_recipes[al_idx].sval); + if (alchemist_recipes[al_idx].tval != 1 && k_info[kidx].know) + essence[alchemist_recipes[al_idx].sval_essence] = TRUE; + + } + for (num = 0, i = 0; i < MAX_BATERIE_SVAL + 7 ; i++) + if (essence[i] || i > MAX_BATERIE_SVAL) + { + int kidx = lookup_kind(TV_BATERIE, i); + if (i > MAX_BATERIE_SVAL) + { + switch (i) + { + case (MAX_BATERIE_SVAL + 1): strip_and_print("Scrolls", TERM_WHITE, num); + break; + case (MAX_BATERIE_SVAL + 2): strip_and_print("Potions", TERM_WHITE, num); + break; + case (MAX_BATERIE_SVAL + 3): strip_and_print("Wands", TERM_WHITE, num); + break; + case (MAX_BATERIE_SVAL + 4): strip_and_print("Rings", TERM_WHITE, num); + break; + case (MAX_BATERIE_SVAL + 5): strip_and_print("Staves", TERM_WHITE, num); + break; + case (MAX_BATERIE_SVAL + 6): strip_and_print("Amulets", TERM_WHITE, num); + break; + default: + continue; + } + } + else + /* add this essence to the list*/ + strip_and_print(k_name + k_info[kidx].name, TERM_WHITE, num); + + choice[num++] = i; + } + max_num = num; + if ( max_num == 0) + { + /*Note that this should never actually happen, as any skill + at alchemy automatically gets you some recipes, and this + procedure shouldn't be called for players without alchemist skill + */ + msg_print("You don't know any recipes!"); + msg_print("You can't be an alchemist without recipes!"); + break; + } + + while (num == 0xff || num >= max_num) + { + ch = selectchar[max_num - 1]; + /* Choose! */ + if ( max_num == 0 || + !get_com(format("Which Type of Recipe?[a-%c]", selectchar[max_num - 1]), &ch)) + break; + + /* Analyze choice - note that the cast to byte prevents overflow*/ + num = selectitem[(byte)ch]; + + } + /* This break, and the break for no recipes above, + are the only exits from this procedure. + */ + if ( num == 0xff || num >= max_num) + break; + + /* Save the baterie index */ + bat = choice[num]; + num = 0; + + /*Display the 'type of object' recipe screen*/ + if (bat > MAX_BATERIE_SVAL) + { + int tval; + switch (bat) + { + case MAX_BATERIE_SVAL + 1: + tval = TV_SCROLL; + break; + case MAX_BATERIE_SVAL + 2: + tval = TV_POTION; + break; + case MAX_BATERIE_SVAL + 3: + tval = TV_WAND; + break; + case MAX_BATERIE_SVAL + 4: + tval = TV_RING; + break; + case MAX_BATERIE_SVAL + 5: + tval = TV_STAFF; + break; + case MAX_BATERIE_SVAL + 6: + tval = TV_AMULET; + break; + } + Term_load(); + alchemist_recipe_select(&tval, 0, FALSE, TRUE); + Term_save(); + continue; + } + mod40 = 0; + while ( TRUE ) + { + int skipped; + + Term_clear(); + num = 0; + + if (mod40) + { + strip_and_print("--MORE--", TERM_WHITE, num); + choice[num] = -2; + choice2[num++] = 0; + } + + /* Display all items made with this essence */ + for ( al_idx = 0 , skipped = 0 ; al_idx < max_al_idx ; al_idx++) + if ( alchemist_recipes[al_idx].sval_essence == bat) + { + int sval = alchemist_recipes[al_idx].sval; + int tval = alchemist_recipes[al_idx].tval; + char names[200] = ""; + + if (alchemist_recipes[al_idx].tval == 1) + { + /* Ego items */ + ego_item_type *e_ptr = &e_info[sval]; + int j, k; + + if ( !(alchemist_known_egos[sval / 32] & (1 << (sval % 32)))) + continue; + + for ( j = 0 ; j < 6 && e_ptr->tval[j] ; j ++ ) + { + if ( j > 0 && e_ptr->tval[j] == e_ptr->tval[j - 1]) + continue; + for ( k = 0; tvals[k].tval; k++) + if (tvals[k].tval == e_ptr->tval[j]) + { + strcat(names, tvals[k].desc); + strcat(names, ", "); + break; + } + } + strcat(names, e_name + e_ptr->name); + } + else + { + /* Normal Items */ + int kidx = lookup_kind(tval, sval); + int k; + if ( !k_info[kidx].know ) + continue; + + for ( k = 0; tvals[k].tval; k++) + if (tvals[k].tval == tval) + { + strcat(names, tvals[k].desc); + break; + } + strcat(names, " of "); + strcat(names, k_name + k_info[kidx].name); + + } + + /*Skip the first mod40 pages of recipes*/ + if (skipped++ < mod40*38) + continue; + + /* add this object kind to the list*/ + strip_and_print(names, TERM_WHITE, num); + choice[num] = tval; + choice2[num++] = sval; + if (num > 38) + { + strip_and_print("--MORE--", TERM_WHITE, num); + choice[num] = -1; + choice2[num++] = 0; + break; + } + + }/*Loop through tidx/sidx*/ + + max_num = num; + while (num == 0xff || num >= max_num) + { + ch = selectchar[max_num - 1]; + /* Choose! */ + if ( max_num == 0 || !get_com( + format("Examine which recipe?[%c-%c]", selectchar[0], ch) + , &ch)) + { + break; + } + + /* Analyze choice */ + num = selectitem[(byte)ch]; + } + + if ( choice[num] < 0) + { + if (choice[num] < -1) + mod40--; + else + mod40++; + continue; + } + + if ( num == 0xff || num >= max_num) + break; + + /* Display the recipe */ + if (choice[num] == 1) + alchemist_display_recipe(0, 0, choice2[num]); + else + alchemist_display_recipe(choice[num], choice2[num], 0); + } + /* + break is at top of loop, after essence list + if( num < 0 || num >= max_num) + break; + */ + + }/*show recipes*/ + + /* Restore screen contents */ + Term_load(); + character_icky = FALSE; +} + +/* Display a list of known recipies that can be made with + * materials on hand (including the passed tval). Also + * calls the recipe_display function, if requested by the + * player or there aren't enough essences to make the + * requested object. + * + * Note: sval is ignored if !ego, tval is the only determinant + * of what recipies are available otherwise. + * + * This function needs to be able to scroll a list, because + * there are SO MANY potions. :) + */ +int alchemist_recipe_select(int *tval, int sval, int ego, bool_ recipe) +{ + int i, mod40 = 0, num, max_num = 0; + + cptr tval_desc2 = ""; + char ch; + bool_ done = FALSE; + + int choice[60]; + int validc[60]; + + const char *string; + + + /* Save and clear the screen */ + character_icky = TRUE; + Term_save(); + Term_clear(); + + /* Base object type chosen, fill in tval */ + for ( num = 0 ; num < 40 ; num ++) + if (tvals[num].tval == *tval) + { + tval_desc2 = tvals[num].desc; + } + + while (!done) + { + Term_clear(); + if (ego) + { + /* Find matching ego items */ + for (num = 0, i = 1; (num < 40) && (i < max_e_idx) ; i++) + { + int j; + ego_item_type *e_ptr = &e_info[i]; + + /* Skip if unknown ego type */ + if ( !(alchemist_known_egos[i / 32] & (1 << (i % 32)))) + continue; + + /* search in permitted tvals/svals for allowed egos */ + for ( j = 0 ; j < 6 ; j ++ ) + if ( e_ptr->tval[j] == *tval + && sval >= e_ptr->min_sval[j] + && sval <= e_ptr->max_sval[j]) + { + int color = TERM_GREEN; + + /*Reject if not opposite end of name + prefixes only on postfix egos, + postfixes only on prefix egos. + */ + if (ego != -1 && e_ptr->before == e_info[ego].before) + continue; + + /*Color it red of the alchemist doesn't have the essences to create it*/ + if (!alchemist_items_check(*tval, 0, i, 0, TRUE)) + color = TERM_RED; + + /* add this ego to the list*/ + strip_and_print(e_name + e_info[i].name, color, num); + validc[num] = color; + choice[num++] = i; + break; + } + } + } + else + { + char skipped = 0; + num = 0; + if (mod40 != 0) + { + strip_and_print("--MORE--", TERM_WHITE, num); + validc[num] = TERM_WHITE; + choice[num++] = -1; + } + + for (i = 1; (num < 39) && (i < max_k_idx); i++) + { + object_kind *k_ptr = &k_info[i]; + + /* Analyze matching items */ + if (k_ptr->tval == *tval || (k_ptr->tval == TV_POTION2 && *tval == TV_POTION)) + { + char color = TERM_GREEN; + /* Hack -- Skip instant artifacts */ + if (k_ptr->flags3 & (TR3_INSTA_ART)) continue; + + /*Don't display recipes that the alchemist doesn't know about*/ + if (!k_ptr->know && !wizard) continue; + + /*Skip recipes that are somehow known, but don't exist*/ + if (!alchemist_exists(k_ptr->tval, k_ptr->sval, 0, 0)) + continue; + + /* Skip the first 39 if they hit 'more' */ + if (skipped++ < mod40*39) + continue; + + /* Color 'unable to create' items different */ + if (!alchemist_items_check(k_ptr->tval, k_ptr->sval, 0, 0, TRUE)) + color = TERM_RED; + + /* Acquire the "name" of object "i" */ + /* and print it in it's place */ + strip_and_print(k_name + k_ptr->name, color, num); + + /* Remember the object index */ + validc[num] = color; + choice[num++] = i; + } + } + if (num == 39) + { + strip_and_print("--MORE--", TERM_WHITE, num); + validc[num] = TERM_WHITE; + choice[num++] = -1; + } + } + + /* We need to know the maximal possible remembered object_index */ + max_num = num; + string = "What Kind of %s? (* to see recipe) [%c-%c,*]"; + num = 0xff; + + /* Pretend they're all undoable if we where called to display recipes */ + if (recipe) + { + for ( num = 0 ; num < max_num ; num++) + if (validc[num] != TERM_WHITE) validc[num] = TERM_RED; + string = "show which %s recipe? [%c-%c]"; + } + + while (num == 0xff || num >= max_num) + { + ch = selectchar[max_num - 1]; + /* Choose! */ + if ( max_num == 0 || !get_com(format(string, tval_desc2, selectchar[0], ch), &ch)) + { + break; + } + + /* Extra breaks for recipe */ + if (recipe && (ch == '\r' || ch == ' ' || ch == ESCAPE )) + break; + + /* Analyze choice */ + num = selectitem[(byte)ch]; + + /* Pretend that we don't have enough essences for anything */ + if (ch == '*' ) + { + for ( num = 0 ; num < max_num ; num++) + if (validc[num] != TERM_WHITE) validc[num] = TERM_RED; + string = "Show which %s recipe? [%c-%c]"; + } + } + if ( num == 0xff || max_num == 0 || num >= max_num) + break; + + if ( validc[num] == TERM_WHITE ) + { + if (num == 0) + mod40--; + else + mod40++; + if ( mod40 < 0) + mod40 = 0; + continue; + } + + /* If we don't have enough essences, or user asked for recipes */ + if ( validc[num] != TERM_GREEN ) + { + /* Display the recipe */ + if (ego) + alchemist_display_recipe(*tval, sval, choice[num]); + else + alchemist_display_recipe(k_info[choice[num]].tval, k_info[choice[num]].sval, 0); + } + else + done = TRUE; + + }/*while(!done)*/ + + /* Restore screen contents */ + Term_load(); + character_icky = FALSE; + + /* User abort, or no choices */ + if (max_num == 0 || num == 0xff || num >= max_num) + { + if (max_num == 0) + msg_print("You don't know of anything you can make using that."); + return ( -1); + } + if ( validc[num] != TERM_GREEN ) + return ( -1); + + /* And return successful */ + if ( ego ) + return choice[num]; + + /* Set the tval, should be the same unless they selected a potion2 */ + if (*tval != k_info[choice[num]].tval && *tval != TV_POTION) + msg_print("Coding error: tval != TV_POTION"); + *tval = k_info[choice[num]].tval; + return ( k_info[choice[num]].sval ); +} + +/* Set the 'known' flags for all objects with a level <= lev + * This lets the budding alchemist create basic items. + */ +void alchemist_learn_all(int lev) +{ + int i; + + if ( !get_skill(SKILL_ALCHEMY) ) + return; + + /* msg_format("You learn about level %d items",lev); */ + + for ( i = 0 ; i < max_k_idx ; i++ ) + if ( k_info[i].level <= lev ) + if (alchemist_exists(k_info[i].tval, k_info[i].sval, 0, 0)) + k_info[i].know = TRUE; +} + +void alchemist_learn_ego(int ego) +{ + char *name; + int i; + + /* some Paranoia*/ + if ( !ego || ego >= max_e_idx ) + return; + + /* Get the ego items name */ + name = e_name + e_info[ego].name; + while (strchr(name, ' ')) + name = strchr(name, ' ') + 1; + + /* Don't learn about egos without recipes, and + * always learn about the passed ego item. */ + if (alchemist_exists(0, 0, ego, 0)) + { + alchemist_known_egos[ego / 32] |= (1 << (ego % 32)); + /* msg_format("You learn about '%s' ego items.",e_name+e_info[ego].name); */ + } + else + { + return; + } + + /* Don't mass learn about egos that have no name. */ + if ( name[0] == 0 ) + { + return; + } + + /* Look through all ego's for matching name */ + /* Note that the original ego is marked here too */ + for ( i = 0 ; i < max_e_idx ; i++ ) + if ( strstr(e_name + e_info[i].name, name) != NULL /*Last word of name exists in this ego's name*/ + && alchemist_exists(0, 0, i, 0) /*There exists a recipe for this*/ + && !(alchemist_known_egos[i / 32] & (1 << (i % 32)) ) ) /*Not already known*/ + /*&& (e_name+e_info[i].name)[0])non-blank name*/ + { + alchemist_known_egos[i / 32] |= (1 << (i % 32)); + /* msg_format("You learn about '%s' ego items.",e_name+e_info[i].name); */ + } + + return; +} + +/* Alchemist has learned about a new item. + * Learn about not only it, but ALL egos with the + * same name. + */ +int alchemist_learn_object(object_type *o_ptr) +{ + + /* Allow alchemist to create this item, + and.. learn about it even if the player + doesn't currently have the alchemy skill + */ + k_info[o_ptr->k_idx].know = TRUE; + + /* Not Paranoia, identify_fully calls this always */ + if ( !get_skill(SKILL_ALCHEMY) ) + return FALSE; + + if ( artifact_p(o_ptr) ) + { + char o_name[80]; + u32b f1, f2, f3, f4, f5, esp; + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* Randarts and normal artifacts both*/ + alchemist_known_artifacts[0] |= f1; + alchemist_known_artifacts[1] |= f2; + alchemist_known_artifacts[2] |= f3; + alchemist_known_artifacts[3] |= f4; + alchemist_known_artifacts[4] |= f5; + alchemist_known_artifacts[5] |= esp; + + object_desc(o_name, o_ptr, 1, 0); + msg_format("You learn all about the abilities of %s!", o_name); + } + if (o_ptr->name2) + alchemist_learn_ego(o_ptr->name2); + + if (o_ptr->name2b) + alchemist_learn_ego(o_ptr->name2b); + + return (TRUE); +} + +/* Alchemist has gained a level - set the ego flags + * for all egos <= lev/4. + */ +void alchemist_gain_level(int lev) +{ + object_type forge; + object_type *o_ptr = &forge; + + if ( lev == 0) + { + /* Learn about potions of Detonation */ + k_info[417].know = TRUE; + } + if ( lev == 5) + { + int ego; + int egos[] = { + 7/*armor of resist fire*/ + , 18/*shield of resist fire*/ + , 74/*shocking weapon*/ + , 75/*fiery weapon*/ + , 76/*frozen weapon*/ + , 77/*Venomous weapon*/ + , 78/*Chaotic weapon*/ + , 115/*projectile of venom*/ + , 116/*projectile of Acid*/ + , 122/*projectile of flame*/ + , 123/*projectile of frost*/ + , 137/*Lite of fearlessness*/ + , 0 /*terminator*/ + }; + object_wipe(o_ptr); + /* learn about some basic ego items */ + /* Note that this is just to get you started. */ + for ( ego = 0 ; egos[ego] ; ego++) + { + o_ptr->name2 = egos[ego]; + alchemist_learn_object(o_ptr); + } + msg_print("You recall your old master teaching you about elemental item infusing."); + } + if ( lev == 10) + { + /*For 'hard rooms' Players only, learn about diggers.*/ + if (ironman_rooms) + { + msg_print("There's gotta be an easier way to get into all these vaults!"); + object_wipe(o_ptr); + o_ptr->name2 = 101; /* Ego item, 'of digging' */ + alchemist_learn_object(o_ptr); + } + } + if ( lev == 25) + { + msg_print("You recall your old master reminiscing about legendary infusings"); + msg_print("and the Philosophers' stone."); + + /* No auto-learn on artifacts - by this level, you'll have *ID*'d several */ + } + if ( lev == 25) + { + msg_print("You wonder about shocking daggers of slay evil."); + } + if ( lev == 50) + { + /* learn about Temporary item creation */ + /* Note that this is the ONLY way to learn this, + because spells which create a temporary item + also fully ID it. */ + alchemist_known_artifacts[4] |= TR5_TEMPORARY; + msg_print("It suddenly occurs to you that artifacts don't *HAVE* to be permanent..."); + } + + /* Every Four Levels, learn about items that are + * less than that. + * Note that this isn't a significant effect after the + * first few levels, as the level at which you are learning + * things here quickly drops behind the level at which you + * are finding items. + */ + if ( (lev & 0x3) != 0 ) + return; + lev = (lev >> 2) + 1; + alchemist_learn_all(lev); + +} + +/* This, in combination with some code in loadsave.c, + insures that alchemist_gain_level is called EXACTLY + once with each possible value during the characters + lifetime. + */ +void alchemist_check_level() +{ + u32b lev = get_skill(SKILL_ALCHEMY); + if ( alchemist_gained > lev ) + return; + /*Paranoia*/ + if ( !lev ) + return; + while ( alchemist_gained <= lev ) + alchemist_gain_level(alchemist_gained++); +} + +/* + * do_cmd_cast calls this function if the player's class + * is 'alchemist'. + */ +void do_cmd_alchemist(void) +{ + int item, ext = 0; + int value, basechance; + int askill; + bool_ repeat = 0; + char ch; + + object_type *o_ptr, *q_ptr; + object_type forge, forge2; + byte carry_o_ptr = FALSE; + + cptr q, s; + + /* With the new skill system, we can no longer depend on + * check_exp to handle the changes and learning involved in + * gaining levels. + * So we'll have to check for it here. + */ + alchemist_check_level(); + askill = get_skill(SKILL_ALCHEMY); + + + q_ptr = &forge; + + o_ptr = &p_ptr->inventory[INVEN_HANDS]; + if ((o_ptr->tval != TV_GLOVES) || (o_ptr->sval != SV_SET_OF_LEATHER_GLOVES)) + { + msg_print("You must wear gloves in order to do alchemy."); + return; + } + + if (p_ptr->confused) + { + msg_print("You are too confused!"); + return; + } + + while (TRUE) + { + if (!get_com("[P]ower, [R]echarge or [L]eech an item, [E]xtract essences, or recipe [B]ook?", &ch)) + { + ext = 0; + break; + } + if (ch == ' ' ) + { + ext = 0; + break; + } + if (ch == 'P' || ch == 'p') + { + ext = 1; + break; + } + if (ch == 'E' || ch == 'e') + { + ext = 2; + break; + } + if (ch == 'R' || ch == 'r') + { + ext = 3; + break; + } + if (ch == 'L' || ch == 'l') + { + ext = 2; + repeat = 1; + break; + } + if (ch == 'B' || ch == 'b') + { + ext = 4; + break; + } + } + + /**********Add a power*********/ + if (ext == 1) + { + int i, qty, tval, sval = 0, ego = 0; + char o_name[200]; + + /* Get an item */ + q = "Empower which item? "; + s = "You have no empowerable items."; + item_tester_hook = item_tester_hook_empower; + + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; + + /* Get the item */ + o_ptr = get_object(item); + + /* Create an artifact from an ego or double ego item, + * from a previous artifact, or finish an artifact + */ + if ((askill >= 25) && (artifact_p(o_ptr) || o_ptr->name2) && has_ability(AB_CREATE_ART)) + { + if (get_check("Create an artifact?")) + { + do_cmd_toggle_artifact(o_ptr); + return; + } + /* Don't change artifacts or double ego items further */ + else if (artifact_p(o_ptr) || (o_ptr->name2 && o_ptr->name2b)) + return; + } + /*Ok, now we have the item, so we can now pick recipes. + Note: No recipe is known unless we have 'extracted' from + that object type. I.E. the 'know' flag (also greater identify) + is set. + */ + + /* Here we're not setting what kind of ego item it IS, + * where' just deciding that it CAN be an ego item */ + if ( o_ptr->name2 ) /* creating a DUAL ego */ + ego = TRUE; + if ( o_ptr->tval < 40 && o_ptr->tval != TV_BOTTLE) + ego = TRUE; + if ( o_ptr->tval == TV_ROD_MAIN || o_ptr->tval == TV_DAEMON_BOOK || o_ptr->tval == TV_BOOK) + ego = TRUE; + + sval = o_ptr->sval; + if (!ego) + { + switch ( o_ptr->tval) + { + case TV_WAND: + sval = SV_WAND_NOTHING; + break; + case TV_RING: + sval = SV_RING_NOTHING; + break; + case TV_STAFF: + sval = SV_STAFF_NOTHING; + break; + case TV_BOTTLE: + sval = 1; + break; + case TV_AMULET: + sval = SV_AMULET_NOTHING; + break; + case TV_SCROLL: + sval = SV_SCROLL_NOTHING; + break; + case TV_ROD: + sval = SV_ROD_NOTHING; + break; + } + } + if ( o_ptr->sval != sval ) + ego = TRUE; + + tval = o_ptr->tval; + sval = o_ptr->sval; + + /*HACK - bottles don't have the same tval as potions*/ + /*Everything else will have the same tval after empowering*/ + if (tval == TV_BOTTLE) tval = TV_POTION; + if (ego) + if (o_ptr->name2) + ego = alchemist_recipe_select(&tval, sval, o_ptr->name2, FALSE); + else + ego = alchemist_recipe_select(&tval, sval, -1, FALSE); + else + sval = alchemist_recipe_select(&tval, 0, 0, FALSE); + + if ( sval < 0 || ego < 0) + return; + + /* Check to make sure we have enough essences */ + /* theoretically this is taken care of by recipe_select*/ + /* but we'll double check just for paranoia. */ + if (!alchemist_items_check(tval, sval, ego, 0, TRUE)) + { + msg_print("You do not have enough essences."); + return; + } + + /* Take a turn */ + energy_use = 100; + + /* Use up the essences */ + (void)alchemist_items_check(tval, sval, ego, -1, TRUE); + + /* Enchant stacks of ammunition at a time */ + if ( o_ptr->tval == TV_SHOT || o_ptr->tval == TV_ARROW || o_ptr->tval == TV_BOLT ) + { + qty = 1; + while (qty < o_ptr->number && alchemist_items_check(tval, sval, ego, -1, FALSE)) + qty++; + } + else + qty = 1; + + /* Copy the object */ + q_ptr = &forge; + object_copy(q_ptr, o_ptr); + + if ( o_ptr->tval == TV_WAND) + { + /* distribute charges on wands */ + q_ptr->pval = o_ptr->pval / o_ptr->number; + o_ptr->pval -= q_ptr->pval; + } + + o_ptr = q_ptr; + o_ptr->number = qty; + carry_o_ptr = TRUE; + + /* Destroy the initial object */ + inc_stack_size(item, -qty); + + + if ( ego ) + { + int pval, pval2; + s32b pval3; + + pval = o_ptr->pval; + pval2 = o_ptr->pval2; + pval3 = o_ptr->pval3; + + if (o_ptr->name2) + o_ptr->name2b = ego; + else + o_ptr->name2 = ego; + o_ptr->pval = randint(e_info[ego].max_pval - 1) + 1; + /* dilemma - how to prevent creation of cursed items, + * without allowing the creation of artifacts? + * We can't, unless we want to finalize the ego flags ourselves. + */ + apply_magic(o_ptr, askill * 2, FALSE, FALSE, FALSE); + /* Remember what the old pval was, so that we can re-apply it. */ + if ( o_ptr->tval == TV_WAND + || o_ptr->tval == TV_RING + || o_ptr->tval == TV_AMULET + || o_ptr->tval == TV_STAFF) + { + o_ptr->pval = pval; + o_ptr->pval2 = pval2; + o_ptr->pval3 = pval3; + } + else if (o_ptr->tval == TV_ROD_MAIN) + { + o_ptr->pval = pval; + } + else if ((o_ptr->tval == TV_BOOK) && (o_ptr->sval == 255)) + { + o_ptr->pval = pval; + } + else if (o_ptr->tval == TV_SHOT + || o_ptr->tval == TV_ARROW + || o_ptr->tval == TV_BOLT) + { + o_ptr->pval2 = pval2; + } + else if (o_ptr->tval == TV_INSTRUMENT) + { + o_ptr->pval2 = pval2; + } + + /* Calculate failure rate, lev=val/2500+5 */ + value = MIN(e_info[o_ptr->name2].cost, 50000); + if (o_ptr->name2b) value += MIN(e_info[o_ptr->name2b].cost, 50000); + basechance = (value / 1000 + 5 - get_skill_scale(SKILL_ALCHEMY, 100) ) * 10; + if ( basechance < 0) basechance = 0; + if ( basechance > 100) basechance = 100; + + value = object_value_real(o_ptr); + + } + else /* not an ego item */ + { + o_ptr = &forge; + object_wipe(o_ptr); + object_prep(o_ptr, lookup_kind(tval, sval)); + hack_apply_magic_power = -99; + apply_magic(o_ptr, askill * 2, FALSE, FALSE, FALSE); + if ( o_ptr->tval == TV_WAND || o_ptr->tval == TV_STAFF) + o_ptr->pval = 0; + value = object_value_real(o_ptr); + + basechance = k_info[o_ptr->k_idx].level - askill * 2; + basechance *= 10; + + /* Can't fail more that 100% of the time... */ + if (basechance > 100) + basechance = 100; + /* Always success in creation of potion of detonations */ + if (o_ptr->tval == TV_POTION && o_ptr->sval == SV_POTION_DETONATIONS) + { + basechance /= 10; + } + } + + /* Use up gold to create items */ + /* this has the effect of making the alchemist + chronically short of funds, unless he finds the + philosopher's stone. It also means the easiest + things to make are 'bad', like a potion of + detonations... + */ + /* Problem - to restrictive. We need something + which requires less money. But at the same time, + we don't want an 'easy cash' situation. Maybe something + like '10% * level difference', meaning at skill level 5, + level one items are free? But egos are frequently level + zero! Maybe egos are forced to level 25? with a cost ceiling? + I mean, Potions and scrolls are really the problem causing the + 'easy cash' situation, it's ego items. Ego items require + relatively few essences, and the rewards are HUGE. Most powerful + potions and scrolls require rare essences. Maybe force all egos + to require a magic essence? But then you'd get lots of magic + from distilling them. Maybe consumed in the creation? then when + you got a powerful item, you could make one ego item... + But if making things doesn't take gold, what about the cash + does the Philosopher's stone do? + Time*/ + + /* 0% failure if you have the stone */ + if ( alchemist_has_stone()) + basechance = 0; + + if (basechance > 0 && value) + { + char string[80]; + string[0] = '0'; + string[1] = 0; + + msg_format("The chance of success is only %d%%!", 100-basechance); + get_string("How much gold do you want to add?", string, 50); + i = atoi(string); + /* Note: don't trust the user to enter a positive number... */ + if ( i < 0) + i = 0; + if ( i > p_ptr->au) + i = p_ptr->au; + + if (i) + { + basechance = basechance - (i * 20) / value; + msg_format("The chance of success improved to %d%%.", 100-basechance); + } + + if (randint(100) < basechance ) + /*creation failed, even with the extra gold...*/ + carry_o_ptr = FALSE; + + /* Redraw gold */ + p_ptr->au -= i; + p_ptr->redraw |= (PR_GOLD); + } + + /* Set fully identified + * After all, the player just made it... + */ + object_aware(o_ptr); + object_known(o_ptr); + o_ptr->ident |= IDENT_MENTAL; + o_ptr->found = OBJ_FOUND_SELFMADE; + + object_desc(o_name, o_ptr, FALSE, 0); + + if ( carry_o_ptr) + { + msg_format("You have successfully created %s %s", + (o_ptr->number > 1 ? "some" : (is_a_vowel(o_name[0]) ? "an" : "a")), + o_name); + + if (inven_carry_okay(o_ptr)) + inven_carry(o_ptr, FALSE); + else + { + drop_near(o_ptr, 0, p_ptr->py, p_ptr->px); + msg_format("You drop the %s", o_name); + } + carry_o_ptr = FALSE; + } + else /* don't carry, or in other words... */ + { + int level = k_info[o_ptr->k_idx].level; + if (o_ptr->name1) /* created ego item */ + level += e_info[o_ptr->name2].level; + + msg_format("Your attempt backfires! Your %s explodes!", o_name); + take_hit(damroll(3, level - askill ) , "Alchemical Explosion"); + p_ptr->redraw |= (PR_HP); + } + + /* Combine / Reorder the pack (later) */ + p_ptr->notice |= (PN_COMBINE | PN_REORDER); + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + + /* Optimize the entire p_ptr->inventory - needed because we + don't know how many essences where used, and we may + have 'used up' a wielded item as well. + */ + for ( item = 0 ; item < INVEN_TOTAL ; item++ ) + inven_item_optimize(item); + + /**********Extract a power*********/ + } + else if (ext == 2) + { + int ego; + bool_ discharge_stick = FALSE; + + /* s_ptr holds the empty items */ + object_type *s_ptr = NULL; + bool_ carry_s_ptr = FALSE; + + item_tester_hook = item_tester_hook_extractable; + + /* Get an item */ + q = "Extract from which item? "; + s = "You have no item to extract power from."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; + + /* Get the item */ + o_ptr = get_object(item); + + /* This is to prevent creating magic essences by extracting + * from a recharged wand of dragon breath or something. + */ + if (( o_ptr->tval == TV_WAND || o_ptr->tval == TV_STAFF ) + && o_ptr->art_flags4 & TR4_RECHARGED) + { + msg_print("You cannot extract essences after it's been magically recharged."); + return; + } + + /* Take a turn */ + energy_use = 100; + + /* Handle Rods before the loop, since they don't stack */ + if (o_ptr->tval == TV_ROD_MAIN && o_ptr->pval != SV_ROD_NOTHING) + { + rod_tip_extract(o_ptr); + return; + } + + do + { /* Repeat (for leech command) */ + + /* Create the items. + * we don't care if they drop to the ground, + * and if no action was taken, return + */ + ego = 0; + if ( o_ptr->name2) + ego = o_ptr->name2; + + /* For ego staves and wands (not of nothing), discharge before extracting the ego */ + discharge_stick = (o_ptr->pval > 0 && + ((o_ptr->tval == TV_STAFF && o_ptr->sval != SV_STAFF_NOTHING) || + (o_ptr->tval == TV_WAND && o_ptr->sval != SV_WAND_NOTHING))); + if (discharge_stick) + ego = 0; + + if (!alchemist_items_check(o_ptr->tval, o_ptr->sval, ego, 1, TRUE)) + { + msg_print("You cannot extract anything from that item."); + return; + } + + if (o_ptr->name2b && !alchemist_items_check(o_ptr->tval, o_ptr->sval, o_ptr->name2b, 1, TRUE)) + { + /* do nothing - if the second ego can't be extracted + because there is no recipe for it, simply destroy it + */ + } + + /* Once in three times, learn how to make the item */ + /* Sorry for the complicated if! Basically, if it's an + * unknown regular item or an unknown ego item, there's + * a one in 3 chance that it'll be id'd */ + if (((!ego && !k_info[o_ptr->k_idx].know) + || (ego && !(alchemist_known_egos[ego / 32] & (1 << (ego % 32))))) + && randint(3) == 1) + { + msg_print("While destroying it, you gain insight into this item."); + /* If over level 10, the player has a chance of 'greater ID' + * on extracted items + */ + if (askill > 9) + object_out_desc(o_ptr, NULL, FALSE, TRUE); + alchemist_learn_object(o_ptr); + } + + /* Always learn what kind of thing it is */ + object_known(o_ptr); + object_aware(o_ptr); + + /* If it's a wand or staff with charges (but not of nothing), + * decrease number of charges, unstacking if needed. + * Otherwise, create the 'of nothing' item and destroy the old one. + */ + if (discharge_stick) + { + /* Unstack staves */ + if ((o_ptr->tval == TV_STAFF) && (o_ptr->number > 1)) + { + /* Create one local copy of the staff */ + q_ptr = &forge2; + object_copy(q_ptr, o_ptr); + + /* Modify quantity */ + q_ptr->number = 1; + + /* Unstack the copied staff */ + o_ptr->number--; + + /* Use the local copy of the staff */ + o_ptr = q_ptr; + carry_o_ptr = TRUE; + } + /* remove one charge */ + o_ptr->pval--; + } + else + { + /* Create the empty, plain item */ + /* If the item was already created, increase the number */ + if (carry_s_ptr) + { + s_ptr->number++; + } + else + { + /* Otherwise we must create a local copy of the empty item */ + int tval, sval; + bool_ create_item = TRUE; + + tval = o_ptr->tval; + if ( !ego && (tval == TV_POTION || tval == TV_POTION2)) + tval = TV_BOTTLE; + + sval = o_ptr->sval; + + if (!ego) + { + switch ( tval) + { + case TV_WAND: + sval = SV_WAND_NOTHING; + break; + case TV_RING: + sval = SV_RING_NOTHING; + break; + case TV_STAFF: + sval = SV_STAFF_NOTHING; + break; + case TV_BOTTLE: + sval = 1; + break; + case TV_AMULET: + sval = SV_AMULET_NOTHING; + break; + case TV_SCROLL: + sval = SV_SCROLL_NOTHING; + break; + case TV_ROD: + sval = SV_ROD_NOTHING; + break; + default: + create_item = FALSE; + } + } + + if (create_item) + { + /* Create the empty item */ + s_ptr = &forge; + object_wipe(s_ptr); + object_prep(s_ptr, lookup_kind(tval, sval)); + s_ptr->number = 1; + + /* Force creation of non ego non cursed */ + hack_apply_magic_power = -99; + apply_magic(s_ptr, 0, FALSE, FALSE, FALSE); + + /* Hack -- remove possible curse */ + if (cursed_p(s_ptr)) + { + s_ptr->art_flags3 &= ~(TR3_CURSED | TR3_HEAVY_CURSE); + s_ptr->ident &= ~(IDENT_CURSED); + } + + /* Restore pvals (e.g. charges ==0) of the item */ + if (ego && ((tval == TV_WAND) || (tval == TV_STAFF) || + (tval == TV_RING) || (tval == TV_AMULET))) + { + s_ptr->pval = o_ptr->pval; + s_ptr->pval2 = o_ptr->pval2; + s_ptr->pval3 = o_ptr->pval3; + } + /* Restore the spell stored in a random book */ + else if ((o_ptr->tval == TV_BOOK) && (o_ptr->sval == 255)) + { + s_ptr->pval = o_ptr->pval; + } + /* Restore the type of explosive ammo */ + else if (o_ptr->tval == TV_SHOT || o_ptr->tval == TV_ARROW + || o_ptr->tval == TV_BOLT) + { + s_ptr->pval2 = o_ptr->pval2; + } + /* Restore the music stored in an instrument */ + else if (o_ptr->tval == TV_INSTRUMENT) + { + s_ptr->pval2 = o_ptr->pval2; + } + + object_aware(s_ptr); + object_known(s_ptr); + s_ptr->ident |= IDENT_STOREB; + + /* The empty item will be added to the p_ptr->inventory later */ + carry_s_ptr = TRUE; + } + } + + /* Now, we can delete the original (leeched) object. + * Is o_ptr an p_ptr->inventory / floor item or a local copy? + */ + if (!carry_o_ptr) + { + /* Break the leech-loop if it was the last item */ + if (o_ptr->number == 1) + repeat = 0; + + inc_stack_size(item, -1); + } + else + { + /* Forget the local object */ + carry_o_ptr = FALSE; + + /* reset o_ptr to the original stack, + * which contains at least another item */ + o_ptr = get_object(item); + } + } + } + while ( repeat == 1); + + /* If we carry empty items, add them to the p_ptr->inventory */ + if (carry_s_ptr) + inven_carry(s_ptr, TRUE); + + /* Combine / Reorder the pack (later) */ + p_ptr->notice |= (PN_COMBINE | PN_REORDER); + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + + /******* Recharge an item *******/ + } + else if (ext == 3) + { + int item; + + cptr q, s; + + item_tester_hook = item_tester_hook_recharge; + + /* Get an item */ + q = "Recharge which item? "; + s = "You have no rechargable items."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR ))) return; + + /* Get the item */ + o_ptr = get_object(item); + + /* Make sure we have enough essences to recharge this */ + if (!alchemist_items_check(o_ptr->tval, o_ptr->sval, 0, 0, TRUE)) + { + msg_print("You don't have the essences to recharge this item."); + return; + } + + /* Take a turn */ + energy_use = 100; + + /* Destroy the essences */ + (void)alchemist_items_check(o_ptr->tval, o_ptr->sval, 0, -1, TRUE); + + if ((o_ptr->tval == TV_STAFF) && (o_ptr->number > 1)) + { + /* Unstack staves */ + /* Get local object */ + q_ptr = &forge2; + + /* Obtain a local object */ + object_copy(q_ptr, o_ptr); + + /* Modify quantity */ + q_ptr->number = 1; + + /* Unstack the used item */ + o_ptr->number--; + + o_ptr = q_ptr; + carry_o_ptr = TRUE; + } + o_ptr->pval++; + } + else if ( ext == 4) + { + alchemist_recipe_book(); + } + /* Just in case - */ + if (carry_o_ptr) + { + /* the o_ptr item was probably an unstacked staff + * Anyway, we need to add it to the p_ptr->inventory */ + if (inven_carry_okay(o_ptr)) + inven_carry(o_ptr, TRUE); + else + drop_near(o_ptr, 0, p_ptr->py, p_ptr->px); + } +} + + +/* + * Command to ask favors from your god. + */ +void do_cmd_pray(void) +{ + if (p_ptr->pgod == GOD_NONE) + { + msg_print("Pray hard enough and your prayers might be answered."); + return; + } + else + { + if (!p_ptr->praying) + msg_format("You start praying to %s.", deity_info[p_ptr->pgod].name); + else + msg_format("You stop praying to %s.", deity_info[p_ptr->pgod].name); + p_ptr->praying = !p_ptr->praying; + + /* Update stuffs */ + p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS | PU_POWERS | + PU_SANITY | PU_BODY); + + p_ptr->redraw |= PR_PIETY | PR_WIPE | PR_BASIC | PR_EXTRA | PR_MAP; + energy_use = 100; + } +} + + +/* + * Return percentage chance of spell failure. + */ +int spell_chance_random(random_spell* rspell) +{ + int chance, minfail; + + + /* Extract the base spell failure rate */ + chance = rspell->level + 10; + + /* Reduce failure rate by "effective" level adjustment */ + chance -= 3 * (get_skill(SKILL_THAUMATURGY) - rspell->level); + + /* Reduce failure rate by INT/WIS adjustment */ + chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[A_INT]] - 1); + + /* Not enough mana to cast */ + if (rspell->mana > p_ptr->csp) + { + chance += 5 * (rspell->mana - p_ptr->csp); + } + + /* Extract the minimum failure rate */ + minfail = adj_mag_fail[p_ptr->stat_ind[A_INT]]; + + /* Failure rate */ + return clamp_failure_chance(chance, minfail); +} + + + + +/* + * Print a batch of spells. + */ +static void print_spell_batch(int batch, int max) +{ + char buff[80]; + + random_spell* rspell; + + int i; + + + prt(format(" %-30s Lev Fail Mana Damage ", "Name"), 1, 20); + + for (i = 0; i < max; i++) + { + rspell = &random_spells[batch * 10 + i]; + + if (rspell->untried) + { + strnfmt(buff, 80, " %c) %-30s (Spell untried) ", + I2A(i), rspell->name); + + } + else + { + strnfmt(buff, 80, " %c) %-30s %3d %4d%% %3d %3dd%d ", + I2A(i), rspell->name, + rspell->level, spell_chance_random(rspell), rspell->mana, + rspell->dam_dice, rspell->dam_sides); + } + + prt(buff, 2 + i, 20); + } + + prt("", 2 + i, 20); +} + + + +/* + * List ten random spells and ask to pick one. + */ +static random_spell* select_spell_from_batch(int batch) +{ + char tmp[160]; + + char out_val[30]; + + char which; + + int mut_max = 10; + + random_spell* ret; + + + /* Enter "icky" mode */ + character_icky = TRUE; + + /* Save the screen */ + Term_save(); + + if (spell_num < (batch + 1) * 10) + { + mut_max = spell_num - batch * 10; + } + + strnfmt(tmp, 160, "(a-%c, A-%cto browse, / to rename, - to comment) Select a power: ", + I2A(mut_max - 1), I2A(mut_max - 1) - 'a' + 'A'); + + prt(tmp, 0, 0); + + while (1) + { + /* Print power list */ + print_spell_batch(batch, mut_max); + + /* Get a command */ + which = inkey(); + + /* Abort */ + if (which == ESCAPE) + { + /* No selection */ + ret = NULL; + + /* Leave the command loop */ + break; + + } + + /* Accept default */ + if (which == '\r') + { + /* There are no other choices */ + if (mut_max == 1) + { + ret = &random_spells[batch * 10]; + + /* Leave the command loop */ + break; + } + + /* Wait for next command */ + continue; + } + + /* Rename */ + if (which == '/') + { + prt("Rename which power: ", 0, 0); + which = tolower(inkey()); + + if (isalpha(which) && (A2I(which) <= mut_max)) + { + strcpy(out_val, random_spells[batch*10 + A2I(which)].name); + if (get_string("Name this power: ", out_val, 29)) + { + strcpy(random_spells[batch*10 + A2I(which)].name, out_val); + } + prt(tmp, 0, 0); + } + else + { + bell(); + prt(tmp, 0, 0); + } + + /* Wait for next command */ + continue; + } + + /* Comment */ + if (which == '-') + { + prt("Comment which power: ", 0, 0); + which = tolower(inkey()); + + if (isalpha(which) && (A2I(which) <= mut_max)) + { + strcpy(out_val, random_spells[batch*10 + A2I(which)].desc); + if (get_string("Comment this power: ", out_val, 29)) + { + strcpy(random_spells[batch*10 + A2I(which)].desc, out_val); + } + prt(tmp, 0, 0); + } + else + { + bell(); + prt(tmp, 0, 0); + } + + /* Wait for next command */ + continue; + } + + if (isalpha(which) && isupper(which)) + { + which = tolower(which); + c_prt(TERM_L_BLUE, format("%s : %s", random_spells[batch*10 + A2I(which)].name, random_spells[batch*10 + A2I(which)].desc), 0, 0); + inkey(); + prt(tmp, 0, 0); + continue; + } + else if (isalpha(which) && (A2I(which) < mut_max)) + { + /* Pick the power */ + ret = &random_spells[batch * 10 + A2I(which)]; + + /* Leave the command loop */ + break; + } + else + { + bell(); + } + } + + /* Restore the screen */ + Term_load(); + + /* Leave "icky" mode */ + character_icky = FALSE; + + /* Return selection */ + return (ret); +} + + +/* + * Pick a random spell from a menu + */ +static random_spell* select_spell() +{ + char tmp[160]; + + char which; + + int batch_max = (spell_num - 1) / 10; + + random_spell *ret; + + + /* Too confused */ + if (p_ptr->confused) + { + msg_print("You can't use your powers while confused!"); + return NULL; + } + + /* No spells available */ + if (spell_num == 0) + { + msg_print("There are no spells you can cast."); + return NULL; + } + + /* Enter "icky" mode */ + character_icky = TRUE; + + /* Save the screen */ + Term_save(); + + strnfmt(tmp, 160, "(a-%c) Select batch of powers: ", I2A(batch_max)); + + prt(tmp, 0, 0); + + while (1) + { + which = inkey(); + + if (which == ESCAPE) + { + Term_load(); + + ret = NULL; + + break; + } + + if (which == '\r') + { + if (batch_max == 0) + { + Term_load(); + + ret = select_spell_from_batch(0); + + break; + } + + continue; + } + + which = tolower(which); + if (isalpha(which) && (A2I(which) <= batch_max)) + { + Term_load(); + + ret = select_spell_from_batch(A2I(which)); + + break; + } + else + { + bell(); + } + } + + /* Leave "icky" mode */ + character_icky = FALSE; + + return (ret); +} + + +void do_cmd_powermage(void) +{ + random_spell *s_ptr; + + u32b proj_flags; + + int dir, chance; + + int ty = 0, tx = 0; + + + /* No magic */ + if (p_ptr->antimagic) + { + msg_print("Your anti-magic field disrupts any magic attempts."); + return; + } + + /* No magic */ + if (p_ptr->anti_magic) + { + msg_print("Your anti-magic shell disrupts any magic attempts."); + return; + } + + + s_ptr = select_spell(); + + if (s_ptr == NULL) return; + + if (p_ptr->csp < s_ptr->mana) + { + msg_print("You do not have enough mana."); + return; + } + + /* Spell failure chance */ + chance = spell_chance_random(s_ptr); + + /* Failed spell */ + if (rand_int(100) < chance) + { + int insanity = (p_ptr->msane - p_ptr->csane) * 100 / p_ptr->msane; + char sfail[80]; + + /* Flush input if told so */ + if (flush_failure) flush(); + + /* Insane players can see something strange */ + if (rand_int(100) < insanity) + { + get_rnd_line("sfail.txt", sfail); + msg_format("A cloud of %s appears above you.", sfail); + } + + /* Normal failure messages */ + else + { + msg_print("You failed to get the spell off!"); + } + + sound(SOUND_FAIL); + + /* Let time pass */ + if (is_magestaff()) energy_use = 80; + else energy_use = 100; + + /* Mana is spent anyway */ + p_ptr->csp -= s_ptr->mana; + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + p_ptr->redraw |= (PR_MANA); + + return; + } + + + p_ptr->csp -= s_ptr->mana; + + s_ptr->untried = FALSE; + proj_flags = s_ptr->proj_flags; + + /* Hack -- Spell needs a target */ + if ((s_ptr->proj_flags & PROJECT_BEAM) || + (s_ptr->proj_flags & PROJECT_STOP)) + { + if (!get_aim_dir(&dir)) return; + + /* Hack -- Use an actual "target" */ + if ((dir == 5) && target_okay()) + { + tx = target_col; + ty = target_row; + + /* Mega-Hack -- Beam spells should continue through + * the target; bolt spells should stop at the + * target. --dsb */ + if (s_ptr->proj_flags & PROJECT_BEAM) + proj_flags |= PROJECT_THRU; + } + else + { + /* Use the given direction */ + ty = p_ptr->py + ddy[dir]; + tx = p_ptr->px + ddx[dir]; + + /* Mega-Hack -- Both beam and bolt spells should + * continue through this fake target. --dsb */ + proj_flags |= PROJECT_THRU; + } + } + + if (s_ptr->proj_flags & PROJECT_BLAST) + { + ty = p_ptr->py; + tx = p_ptr->px; + } + + if (s_ptr->proj_flags & PROJECT_VIEWABLE) + { + project_hack(s_ptr->GF, damroll(s_ptr->dam_dice, s_ptr->dam_sides)); + } + else if (s_ptr->proj_flags & PROJECT_METEOR_SHOWER) + { + project_meteor(s_ptr->radius, s_ptr->GF, + damroll(s_ptr->dam_dice, s_ptr->dam_sides), + s_ptr->proj_flags); + } + else + { + project(0, s_ptr->radius, ty, tx, + damroll(s_ptr->dam_dice, s_ptr->dam_sides), + s_ptr->GF, proj_flags); + } + + /* Take a turn */ + if (is_magestaff()) energy_use = 80; + else energy_use = 100; + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + p_ptr->redraw |= (PR_MANA); +} + + +/* + * Brand some ammunition. Used by Cubragol and a mage spell. The spell was + * moved here from cmd6.c where it used to be for Cubragol only. I've also + * expanded it to do either frost, fire or venom, at random. -GJW -KMW- + */ +void brand_ammo(int brand_type, int bolts_only) +{ + int a; + + for (a = 0; a < INVEN_PACK; a++) + { + object_type *o_ptr = &p_ptr->inventory[a]; + + if (bolts_only && (o_ptr->tval != TV_BOLT)) continue; + + if (!bolts_only && (o_ptr->tval != TV_BOLT) && + (o_ptr->tval != TV_ARROW) && (o_ptr->tval != TV_SHOT)) + continue; + + if (!artifact_p(o_ptr) && !ego_item_p(o_ptr) && + !cursed_p(o_ptr)) + break; + } + + /* Enchant the ammo (or fail) */ + if ((a < INVEN_PACK) && (rand_int(100) < 50)) + { + object_type *o_ptr = &p_ptr->inventory[a]; + const char *ammo_name; + const char *aura_name; + char msg[48]; + int aura_type, r; + + /* fire only */ + if (brand_type == 1) r = 0; + + /* cold only */ + else if (brand_type == 2) r = 99; + + /* No bias */ + else r = rand_int(100); + + if (r < 50) + { + aura_name = "fiery"; + aura_type = EGO_FLAME; + } + else + { + aura_name = "frosty"; + aura_type = EGO_FROST; + } + + if (o_ptr->tval == TV_BOLT) + { + ammo_name = "bolts"; + } + else if (o_ptr->tval == TV_ARROW) + { + ammo_name = "arrows"; + } + else + { + ammo_name = "shots"; + } + + strnfmt(msg, 48, "Your %s are covered in a %s aura!", + ammo_name, aura_name); + msg_print(msg); + + o_ptr->name2 = aura_type; + + /* Apply the ego */ + apply_magic(o_ptr, dun_level, FALSE, FALSE, FALSE); + o_ptr->discount = 100; + + enchant(o_ptr, rand_int(3) + 4, ENCH_TOHIT | ENCH_TODAM); + } + else + { + if (flush_failure) flush(); + msg_print("The enchantment failed."); + } +} + + +/* + * From Kamband by Ivan Tkatchev + */ +void summon_monster(int sumtype) +{ + /* Take a turn */ + energy_use = 100; + + if (p_ptr->inside_arena) + { + msg_print("This place seems devoid of life."); + msg_print(NULL); + return; + } + + if (summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level + randint(5), sumtype, TRUE)) + { + msg_print("You summon some help."); + } + else + { + msg_print("You called, but no help came."); + } +} + + + +/* + * Use a class power of Possessor + */ +void do_cmd_possessor() +{ + char ch, ext; + + + /* No magic */ + if (p_ptr->antimagic) + { + msg_print("Your anti-magic field disrupts any magic attempts."); + return; + } + + /* No magic */ + if (p_ptr->anti_magic) + { + msg_print("Your anti-magic shell disrupts any magic attempts."); + return; + } + + + while (TRUE) + { + if (!get_com("Use your [R]ace powers or your [I]ncarnating powers?", &ch)) + { + ext = 0; + break; + } + if ((ch == 'R') || (ch == 'r')) + { + ext = 1; + break; + } + if ((ch == 'I') || (ch == 'i')) + { + ext = 2; + break; + } + } + + if (ext == 1) + { + bool_ use_great = FALSE; + + if (p_ptr->disembodied) + { + msg_print("You don't currently own a body to use."); + return; + } + + /* Do we have access to all the powers ? */ + if (get_skill_scale(SKILL_POSSESSION, 100) >= r_info[p_ptr->body_monster].level) + use_great = TRUE; + + use_symbiotic_power(p_ptr->body_monster, use_great, FALSE, FALSE); + + if (p_ptr->csp < 0) + { + msg_print("You lose control of your body!"); + if (!do_cmd_leave_body(FALSE)) + { + cmsg_print(TERM_VIOLET, + "You are forced back into your body by your cursed items, " + "you suffer a system shock!"); + + p_ptr->chp = 1; + + /* Display the hitpoints */ + p_ptr->redraw |= (PR_HP); + } + } + } + else if (ext == 2) + { + if (p_ptr->disembodied) + { + do_cmd_integrate_body(); + } + else + { + do_cmd_leave_body(TRUE); + } + } + else + { + return; + } + + /* Take a turn */ + energy_use = 100; +} + + +/* + * Hook to determine if an object is contertible in an arrow/bolt + */ +static bool_ item_tester_hook_convertible(object_type *o_ptr) +{ + if ((o_ptr->tval == TV_JUNK) || (o_ptr->tval == TV_SKELETON)) return TRUE; + + /* Assume not */ + return (FALSE); +} + + +/* + * do_cmd_cast calls this function if the player's class + * is 'archer'. + */ +void do_cmd_archer(void) +{ + int ext = 0; + char ch; + + object_type forge; + object_type *q_ptr; + + char com[80]; + + + if (p_ptr->confused) + { + msg_print("You are too confused!"); + return; + } + + if (p_ptr->blind) + { + msg_print("You are blind!"); + return; + } + + + if (get_skill(SKILL_ARCHERY) >= 20) + { + strnfmt(com, 80, "Create [S]hots, [A]rrows or [B]olts? "); + } + else if (get_skill(SKILL_ARCHERY) >= 10) + { + strnfmt(com, 80, "Create [S]hots or [A]rrows? "); + } + else + { + strnfmt(com, 80, "Create [S]hots? "); + } + + while (TRUE) + { + if (!get_com(com, &ch)) + { + ext = 0; + break; + } + if ((ch == 'S') || (ch == 's')) + { + ext = 1; + break; + } + if (((ch == 'A') || (ch == 'a')) && (get_skill(SKILL_ARCHERY) >= 10)) + { + ext = 2; + break; + } + if (((ch == 'B') || (ch == 'b')) && (get_skill(SKILL_ARCHERY) >= 20)) + { + ext = 3; + break; + } + } + + /* Prepare for object creation */ + q_ptr = &forge; + + /**********Create shots*********/ + if (ext == 1) + { + int x, y, dir; + cave_type *c_ptr; + + if (!get_rep_dir(&dir)) return; + y = p_ptr->py + ddy[dir]; + x = p_ptr->px + ddx[dir]; + c_ptr = &cave[y][x]; + if (c_ptr->feat == FEAT_RUBBLE) + { + /* Get local object */ + q_ptr = &forge; + + /* Hack -- Give the player some shots */ + object_prep(q_ptr, lookup_kind(TV_SHOT, m_bonus(2, dun_level))); + if (!artifact_p(q_ptr)) + q_ptr->number = (byte)rand_range(15, 30); + else + q_ptr->number = 1; + object_aware(q_ptr); + object_known(q_ptr); + q_ptr->ident |= IDENT_MENTAL; + apply_magic(q_ptr, dun_level, TRUE, TRUE, (magik(20)) ? TRUE : FALSE); + q_ptr->discount = 90; + q_ptr->found = OBJ_FOUND_SELFMADE; + + (void)inven_carry(q_ptr, FALSE); + + msg_print("You make some ammo."); + + (void)wall_to_mud(dir); + p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE); + p_ptr->window |= (PW_OVERHEAD); + } + } + + /**********Create arrows*********/ + else if (ext == 2) + { + int item; + + cptr q, s; + + item_tester_hook = item_tester_hook_convertible; + + /* Get an item */ + q = "Convert which item? "; + s = "You have no item to convert."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; + + /* Get local object */ + q_ptr = &forge; + + /* Hack -- Give the player some arrows */ + object_prep(q_ptr, lookup_kind(TV_ARROW, m_bonus(1, dun_level) + 1)); + q_ptr->number = (byte)rand_range(15, 25); + if (!artifact_p(q_ptr)) + q_ptr->number = (byte)rand_range(15, 30); + else + q_ptr->number = 1; + object_aware(q_ptr); + object_known(q_ptr); + q_ptr->ident |= IDENT_MENTAL; + apply_magic(q_ptr, dun_level, TRUE, TRUE, (magik(20)) ? TRUE : FALSE); + q_ptr->discount = 90; + q_ptr->found = OBJ_FOUND_SELFMADE; + + msg_print("You make some ammo."); + + inc_stack_size(item, -1); + + (void)inven_carry(q_ptr, FALSE); + } + + /**********Create bolts*********/ + else if (ext == 3) + { + int item; + + cptr q, s; + + item_tester_hook = item_tester_hook_convertible; + + /* Get an item */ + q = "Convert which item? "; + s = "You have no item to convert."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; + + /* Get local object */ + q_ptr = &forge; + + /* Hack -- Give the player some bolts */ + object_prep(q_ptr, lookup_kind(TV_BOLT, m_bonus(1, dun_level) + 1)); + q_ptr->number = (byte)rand_range(15, 25); + if (!artifact_p(q_ptr)) + q_ptr->number = (byte)rand_range(15, 30); + else + q_ptr->number = 1; + object_aware(q_ptr); + object_known(q_ptr); + q_ptr->ident |= IDENT_MENTAL; + apply_magic(q_ptr, dun_level, TRUE, TRUE, (magik(20)) ? TRUE : FALSE); + q_ptr->discount = 90; + q_ptr->found = OBJ_FOUND_SELFMADE; + + msg_print("You make some ammo."); + + inc_stack_size(item, -1); + + (void)inven_carry(q_ptr, FALSE); + } +} + +/* + * Control whether shots are allowed to pierce + */ +void do_cmd_set_piercing(void) +{ + char ch; + char com[80]; + + if ((get_skill(SKILL_BOW) <= 25) && (get_skill(SKILL_XBOW) <= 25) && + (get_skill(SKILL_SLING) <= 25)) + { + msg_print("You can't fire piercing shots yet."); + return; + } + + strnfmt(com, 80, "Allow shots to pierce? "); + + while (TRUE) + { + if (!get_com(com, &ch)) + { + break; + } + if ((ch == 'Y') || (ch == 'y')) + { + p_ptr->use_piercing_shots = 1; + msg_print("Piercing shots activated."); + break; + } + if ((ch == 'N') || (ch == 'n')) + { + p_ptr->use_piercing_shots = 0; + msg_print("Piercing shots deactivated."); + break; + } + } +} +/* + * Helper function to describe necro powers + */ +void necro_info(char *p, int power) +{ + int plev = get_skill(SKILL_NECROMANCY); + + strcpy(p, ""); + + switch (power) + { + case 0: + { + if (p_ptr->to_s) + strnfmt(p, 80, " power %dd%d+%d", 2 + (plev * 2 / 3), 4, (p_ptr->to_s * 2)); + else + strnfmt(p, 80, " power %dd%d", 2 + (plev * 2 / 3), 4); + break; + } + case 2: + { + strnfmt(p, 80, " dur d%d+%d", 100 + (plev * 4), 200 + (plev * 3)); + break; + } + case 3: + { + strnfmt(p, 80, " dur d%d+%d", 30 + (plev * 2), 50 + plev); + break; + } + } +} + + +/* + * Cast a Necromancy spell + */ +void do_cmd_necromancer(void) +{ + int n = 0, b = 0; + int chance; + int dir; + int minfail = 0; + int plev = get_skill(SKILL_NECROMANCY); + magic_power spell; + int to_s2 = p_ptr->to_s / 2; + int mto_s2 = p_ptr->to_s / 2; + + + if (mto_s2 == 0) mto_s2 = 1; + + /* No magic */ + if (p_ptr->antimagic) + { + msg_print("Your anti-magic field disrupts any magic attempts."); + return; + } + + /* No magic */ + if (p_ptr->anti_magic) + { + msg_print("Your anti-magic shell disrupts any magic attempts."); + return; + } + + /* not if confused */ + if (p_ptr->confused) + { + msg_print("You are too confused!"); + return; + } + + /* get power */ + if (!get_magic_power(&n, necro_powers, MAX_NECRO_POWERS, necro_info, + get_skill(SKILL_NECROMANCY), A_CON)) return; + + spell = necro_powers[n]; + + /* Verify "dangerous" spells */ + if (spell.mana_cost > p_ptr->csp) + { + /* Warning */ + msg_print("You do not have enough mana to use this power."); + + /* Verify */ + if (!get_check("Attempt it anyway? ")) return; + } + + /* Spell failure chance */ + chance = spell.fail; + + /* Reduce failure rate by "effective" level adjustment */ + chance -= 3 * (plev - spell.min_lev); + + /* Reduce failure rate by INT/WIS adjustment */ + chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[A_CON]] - 1); + + /* Not enough mana to cast */ + if (spell.mana_cost > p_ptr->csp) + { + chance += 5 * (spell.mana_cost - p_ptr->csp); + } + + /* Extract the minimum failure rate */ + minfail = adj_mag_fail[p_ptr->stat_ind[A_CON]]; + + /* Failure rate */ + chance = clamp_failure_chance(chance, minfail); + + /* Failed spell */ + if (rand_int(100) < chance) + { + if (flush_failure) flush(); + msg_format("You failed to concentrate hard enough!"); + sound(SOUND_FAIL); + + if (randint(100) < (chance / 2)) + { + /* Backfire */ + b = randint(100); + if (b < 10) + { + msg_print("Oh, no! You become undead!"); + + p_ptr->necro_extra |= CLASS_UNDEAD; + p_ptr->necro_extra2 = 2 * plev; + msg_format("You have to kill %d monster%s to be brought back to life.", + p_ptr->necro_extra2, + (p_ptr->necro_extra2 == 1) ? "" : "s"); + + /* MEGA-HACK !!! */ + calc_hitpoints(); + + /* Enforce maximum */ + p_ptr->chp = p_ptr->mhp; + p_ptr->chp_frac = 0; + + /* Display the hitpoints */ + p_ptr->redraw |= (PR_HP); + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + } + else if (b < 40) + { + msg_print("Suddenly you feel that you're in a bad situation..."); + summon_specific(p_ptr->py, p_ptr->px, max_dlv[dungeon_type], + (plev >= 30) ? SUMMON_HI_UNDEAD : SUMMON_UNDEAD); + } + else + { + msg_print("Your body is damaged by the horrible forces of the spell!"); + take_hit(damroll(5, plev), "using necromancy unwisely"); + } + } + } + else + { + sound(SOUND_ZAP); + + /* spell code */ + switch (n) + { + /* Horrify */ + case 0: + { + int dam = damroll(2 + (plev * 2 / 3), 4) + (p_ptr->to_s * 2); + + if (plev > 45) + { + project_hack(GF_STUN, dam); + project_hack(GF_TURN_ALL, dam); + } + else if (plev > 35) + { + if (!get_aim_dir(&dir)) return; + fire_ball(GF_STUN, dir, dam, 3 + (plev / 10)); + fire_ball(GF_TURN_ALL, dir, dam, 3 + (plev / 10)); + } + else if (plev > 20) + { + if (!get_aim_dir(&dir)) return; + fire_beam(GF_STUN, dir, dam); + fire_beam(GF_TURN_ALL, dir, dam); + } + else + { + if (!get_aim_dir(&dir)) return; + fire_bolt(GF_STUN, dir, dam); + fire_bolt(GF_TURN_ALL, dir, dam); + } + + break; + } + + /* Raise Death */ + case 1: + { + fire_ball(GF_RAISE, 0, plev * 3, 1 + to_s2 + (plev / 10)); + + break; + } + + /* Conjures temporary weapon */ + case 2: + { + int dur = randint(100 + (plev * 4)) + 200 + (plev * 3); + object_type forge, *o_ptr = &forge; + int k_idx = test_item_name("& Necromantic Teeth~"); + + k_allow_special[k_idx] = TRUE; + + object_prep(o_ptr, k_idx); + apply_magic(o_ptr, plev * 2, TRUE, TRUE, TRUE); + + o_ptr->art_flags5 |= TR5_TEMPORARY; + o_ptr->timeout = dur; + + /* These objects are "storebought" */ + o_ptr->ident |= IDENT_MENTAL; + o_ptr->number = 1; + + object_aware(o_ptr); + object_known(o_ptr); + (void)inven_carry(o_ptr, FALSE); + + k_allow_special[k_idx] = FALSE; + + break; + } + + /* Absorb souls */ + case 3: + { + set_absorb_soul(randint(30 + (plev * 2)) + 50 + plev); + break; + } + + /* Vampirism */ + case 4: + { + int i; + if (!get_aim_dir(&dir)) return; + for (i = 0; i < 1 + to_s2 + (plev / 15); i++) + { + if (drain_life(dir, 100)) + hp_player(100); + } + + break; + } + + /* Death */ + case 5: + { + if (get_check("Using the Death word will leave you undead, with 1 DP. Do you *really* want to use it? ")) + { + if (!get_aim_dir(&dir)) return; + fire_bolt(GF_DEATH, dir, 1); + + p_ptr->necro_extra |= CLASS_UNDEAD; + p_ptr->necro_extra2 = plev + (rand_int(plev / 2) - (plev / 4)); + msg_format("You have to kill %d monster%s to be brought back to life.", p_ptr->necro_extra2, (p_ptr->necro_extra2 == 1) ? "" : "s"); + + /* MEGA-HACK !!! */ + calc_hitpoints(); + + /* Enforce 1 DP */ + p_ptr->chp = p_ptr->mhp; + p_ptr->chp_frac = 0; + + /* Display the hitpoints */ + p_ptr->redraw |= (PR_HP); + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + } + + break; + } + + default: + { + msg_print("Zap?"); + + break; + } + } + } + + /* Take a turn */ + if (is_magestaff()) energy_use = 80; + else energy_use = 100; + + /* Sufficient mana */ + if (spell.mana_cost <= p_ptr->csp) + { + /* Use some mana */ + p_ptr->csp -= spell.mana_cost; + } + + /* Over-exert the player */ + else + { + int oops = spell.mana_cost - p_ptr->csp; + + /* No mana left */ + p_ptr->csp = 0; + p_ptr->csp_frac = 0; + + /* Message */ + msg_print("You faint from the effort!"); + + /* Hack -- Bypass free action */ + (void)set_paralyzed(randint(5 * oops + 1)); + + /* Damage CON (possibly permanently) */ + if (rand_int(100) < 50) + { + bool_ perm = (rand_int(100) < 25); + + /* Message */ + msg_print("You have damaged your body!"); + + /* Reduce constitution */ + (void)dec_stat(A_CON, 15 + randint(10), perm); + } + } + + /* Redraw mana */ + p_ptr->redraw |= (PR_MANA); + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); +} + +/* Runecrafters -- Move this into variable.c XXX XXX XXX */ +static s32b rune_combine = 0; + +/* + * Hook to determine if an object is "runestone" + */ +static bool_ item_tester_hook_runestone(object_type *o_ptr) +{ + if (o_ptr->tval != TV_RUNE2) return (FALSE); + + if (o_ptr->sval != RUNE_STONE) return (FALSE); + + if (o_ptr->pval != 0) return (FALSE); + + /* Assume yes */ + return (TRUE); +} + + +static bool_ item_tester_hook_runestone_full(object_type *o_ptr) +{ + if (o_ptr->tval != TV_RUNE2) return (FALSE); + + if (o_ptr->sval != RUNE_STONE) return (FALSE); + + if (o_ptr->pval == 0) return (FALSE); + + /* Assume yes */ + return (TRUE); +} + + +/* + * Hook to determine if an object is "rune-able" + */ +static bool_ item_tester_hook_runeable1(object_type *o_ptr) +{ + if (o_ptr->tval != TV_RUNE1) return (FALSE); + + /* Assume yes */ + return (TRUE); +} + + +/* + * Hook to determine if an object is "rune-able" + */ +static bool_ item_tester_hook_runeable2(object_type *o_ptr) +{ + if (o_ptr->tval != TV_RUNE2) return (FALSE); + + if (o_ptr->sval == RUNE_STONE) return (FALSE); + + if (rune_combine & BIT(o_ptr->sval)) return (FALSE); + + /* Assume yes */ + return (TRUE); +} + + +/* + * math.h(sqrt) is banned of angband so ... :) + */ +s32b sroot(s32b n) +{ + s32b i = n / 2; + + if (n < 2) return (n); + + while (1) + { + s32b err = (i - n / (i + 1)) / 2; + + if (!err) break; + + i -= err; + } + + return ((n / i < i) ? (i - 1) : i); +} + + +/* + * Damage formula, for runes + */ +void rune_calc_power(s32b *power, s32b *powerdiv) +{ + /* Not too weak power(paranoia) */ + *power = (*power < 1) ? 1 : *power; + *power += 3; + + *power = 37 * sroot(*power) / 10; + + /* To reduce the high level power, while increasing the low levels */ + *powerdiv = *power / 3; + if (*powerdiv < 1) *powerdiv = 1; + + /* Use the spell multiplicator */ + *power *= (p_ptr->to_s / 2) ? (p_ptr->to_s / 2) : 1; +} + + +/* + * Return percentage chance of runespell failure. + */ +int spell_chance_rune(rune_spell* spell) +{ + int chance, minfail; + + s32b power = spell->mana, power_rune = 0, powerdiv = 0; + + + if (spell->rune2 & RUNE_POWER_SURGE) + { + power_rune += 4; + } + if (spell->rune2 & RUNE_ARMAGEDDON) + { + power_rune += 3; + } + if (spell->rune2 & RUNE_SPHERE) + { + power_rune += 2; + } + if (spell->rune2 & RUNE_RAY) + { + power_rune += 1; + } + + rune_calc_power(&power, &powerdiv); + + chance = (5 * power_rune) + (power); + + /* Reduce failure rate by INT/WIS adjustment */ + chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[A_DEX]] - 1); + + /* Extract the minimum failure rate */ + minfail = adj_mag_fail[p_ptr->stat_ind[A_DEX]]; + + /* Return the chance */ + return clamp_failure_chance(chance, minfail); +} + + +/* + * Combine the Runes + */ +int rune_exec(rune_spell *spell, int cost) +{ + int dir, power_rune = 0, mana_used, plev = get_skill(SKILL_RUNECRAFT); + + int chance; + + s32b power, powerdiv; + + int rad = 0, ty = -1, tx = -1, dam = 0, flg = 0; + + + if (spell->rune2 & RUNE_POWER_SURGE) + { + power_rune += 4; + } + if (spell->rune2 & RUNE_ARMAGEDDON) + { + power_rune += 3; + } + if (spell->rune2 & RUNE_SPHERE) + { + power_rune += 2; + } + if (spell->rune2 & RUNE_RAY) + { + power_rune += 1; + } + + + power = spell->mana; + + if (cost && ((power * cost / 100) > p_ptr->csp - (power_rune * (plev / 5)))) + { + power = p_ptr->csp - (power_rune * (plev / 5)); + mana_used = power + (power_rune * (plev / 5)); + } + else + { + mana_used = (power * cost / 100) + (power_rune * (plev / 5)); + } + + rune_calc_power(&power, &powerdiv); + + dam = damroll(powerdiv, power); + + if (wizard) msg_format("Rune %dd%d = dam %d", powerdiv, power, dam); + + /* Extract the base spell failure rate */ + chance = spell_chance_rune(spell); + + /* Failure ? */ + if (rand_int(100) < chance) + { + int insanity = (p_ptr->msane - p_ptr->csane) * 100 / p_ptr->msane; + char sfail[80]; + + /* Flush input if told so */ + if (flush_failure) flush(); + + /* Insane players can see something strange */ + if (rand_int(100) < insanity) + { + get_rnd_line("sfail.txt", sfail); + msg_format("A cloud of %s appears above you.", sfail); + } + + /* Normal failure messages */ + else + { + msg_print("You failed to get the spell off!"); + } + + sound(SOUND_FAIL); + + if (is_magestaff()) energy_use = 80; + else energy_use = 100; + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + p_ptr->redraw |= (PR_MANA); + return (mana_used); + } + + if (spell->rune2 & RUNE_POWER_SURGE) + { + flg |= (PROJECT_VIEWABLE); + ty = p_ptr->py; + tx = p_ptr->px; + } + + if (spell->rune2 & RUNE_ARMAGEDDON) + { + flg |= (PROJECT_THRU); + flg |= (PROJECT_KILL); + flg |= (PROJECT_ITEM); + flg |= (PROJECT_GRID); + flg |= (PROJECT_METEOR_SHOWER); + rad = (power / 8 == 0) ? 1 : power / 8; + rad = (rad > 10) ? 10 : rad; + ty = p_ptr->py; + tx = p_ptr->px; + } + + if (spell->rune2 & RUNE_SPHERE) + { + flg |= (PROJECT_THRU); + flg |= (PROJECT_KILL); + flg |= (PROJECT_ITEM); + flg |= (PROJECT_GRID); + rad = (power / 8 == 0) ? 1 : power / 8; + rad = (rad > 10) ? 10 : rad; + ty = p_ptr->py; + tx = p_ptr->px; + } + + if (spell->rune2 & RUNE_RAY) + { + flg |= (PROJECT_THRU); + flg |= (PROJECT_KILL); + flg |= (PROJECT_BEAM); + ty = -1; + tx = -1; + } + if (spell->rune2 & RUNE_ARROW) + { + flg |= (PROJECT_THRU); + flg |= (PROJECT_STOP); + flg |= (PROJECT_KILL); + ty = -1; + tx = -1; + } + if (spell->rune2 & RUNE_SELF) + { + flg |= (PROJECT_THRU); + flg |= (PROJECT_STOP); + flg |= (PROJECT_KILL); + ty = p_ptr->py; + tx = p_ptr->px; + unsafe = TRUE; + } + + if ((ty == -1) && (tx == -1)) + { + if (!get_aim_dir(&dir)) return (mana_used); + + /* Use the given direction */ + tx = p_ptr->px + ddx[dir]; + ty = p_ptr->py + ddy[dir]; + + /* Hack -- Use an actual "target" */ + if ((dir == 5) && target_okay()) + { + tx = target_col; + ty = target_row; + } + } + + if (flg & PROJECT_VIEWABLE) + { + project_hack(spell->type, dam); + } + else if (flg & PROJECT_METEOR_SHOWER) + { + project_meteor(rad, spell->type, dam, flg); + } + else project(0, rad, ty, tx, dam, spell->type, flg); + + if (unsafe) unsafe = FALSE; + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + p_ptr->redraw |= (PR_MANA); + + return (mana_used); +} + + +/* + * Test if all runes needed at in the player p_ptr->inventory + */ +bool_ test_runespell(rune_spell *spell) +{ + int i; + + object_type *o_ptr; + + bool_ typeok = FALSE; + + int rune2 = 0; + + + for (i = 0; i < INVEN_WIELD; i++) + { + o_ptr = &p_ptr->inventory[i]; + + if (!o_ptr->k_idx) continue; + + /* Does the rune1(type) match ? */ + if ((o_ptr->tval == TV_RUNE1) && (o_ptr->sval == spell->type)) + { + typeok = TRUE; + } + + if ((o_ptr->tval == TV_RUNE2) && (o_ptr->sval != RUNE_STONE)) + { + /* Add it to the list */ + rune2 |= 1 << o_ptr->sval; + } + } + + /* Need all runes to be present */ + return (typeok && ((rune2 & spell->rune2) == spell->rune2)); +} + + +/* + * Ask for rune, rune2 and mana + */ +bool_ get_runespell(rune_spell *spell) +{ + int item, power_rune = 0, rune2 = 0, plev = get_skill(SKILL_RUNECRAFT); + + s32b power; + + int type = 0; + + object_type *o_ptr; + + cptr q, s; + + bool_ OK = FALSE; + + + rune_combine = 0; + + /* Restrict choices to unused runes */ + item_tester_hook = item_tester_hook_runeable1; + + /* Get an item */ + q = "Use which rune? "; + s = "You have no rune to use."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return FALSE; + + /* Get the item */ + o_ptr = get_object(item); + type = o_ptr->sval; + + while (1) + { + /* Restrict choices to unused secondary runes */ + item_tester_hook = item_tester_hook_runeable2; + + OK = !get_item(&item, q, s, (USE_INVEN | USE_FLOOR)); + + if (OK) break; + + /* Get the item */ + o_ptr = get_object(item); + + rune_combine |= 1 << o_ptr->sval; + rune2 |= 1 << o_ptr->sval; + } + + if (!rune2) + { + msg_print("You have not selected a second rune!"); + return (FALSE); + } + + power = get_quantity("Which amount of Mana?", + p_ptr->csp - (power_rune * (plev / 5))); + if (power < 1) power = 1; + + spell->mana = power; + spell->type = type; + spell->rune2 = rune2; + + return (TRUE); +} + + +void do_cmd_rune(void) +{ + rune_spell spell; + + + /* Require some mana */ + if (p_ptr->csp <= 0) + { + msg_print("You have no mana!"); + return; + } + + /* Require lite */ + if (p_ptr->blind || no_lite()) + { + msg_print("You cannot see!"); + return; + } + + /* Not when confused */ + if (p_ptr->confused) + { + msg_print("You are too confused!"); + return; + } + + if (!get_runespell(&spell)) return; + + /* Execute at normal mana cost */ + p_ptr->csp -= rune_exec(&spell, 100); + + /* Safety :) */ + if (p_ptr->csp < 0) p_ptr->csp = 0; + + /* Take a turn */ + if (is_magestaff()) energy_use = 80; + else energy_use = 100; + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + p_ptr->redraw |= (PR_MANA); +} + + +/* + * Print a batch of runespells. + */ +static void print_runespell_batch(int batch, int max) +{ + char buff[80]; + + rune_spell* spell; + + int i; + + s32b power, powerdiv; + + int p, dp; + + + prt(format(" %-30s Fail Mana Power", "Name"), 1, 20); + + for (i = 0; i < max; i++) + { + spell = &rune_spells[batch * 10 + i]; + + power = spell->mana; + rune_calc_power(&power, &powerdiv); + p = power; + dp = powerdiv; + + strnfmt(buff, 80, " %c) %-30s %4d%% %4d %dd%d ", I2A(i), spell->name, + spell_chance_rune(spell), spell->mana, dp, p); + + prt(buff, 2 + i, 20); + } + prt("", 2 + i, 20); +} + + + +/* + * List ten random spells and ask to pick one. + */ + +static rune_spell* select_runespell_from_batch(int batch, int *s_idx) +{ + char tmp[160]; + + char out_val[30]; + + char which; + + int mut_max = 10; + + rune_spell* ret; + + + character_icky = TRUE; + + if (rune_num < (batch + 1) * 10) + { + mut_max = rune_num - batch * 10; + } + + strnfmt(tmp, 160, "(a-%c, * to list, / to rename, - to comment) Select a power: ", + I2A(mut_max - 1)); + + prt(tmp, 0, 0); + + while (1) + { + Term_save(); + + print_runespell_batch(batch, mut_max); + + which = inkey(); + + Term_load(); + + if (which == ESCAPE) + { + *s_idx = -1; + ret = NULL; + break; + } + else if ((which == '*') || (which == '?') || (which == ' ')) + { + print_runespell_batch(batch, mut_max); + } + else if ((which == '\r') && (mut_max == 1)) + { + *s_idx = batch * 10; + ret = &rune_spells[batch * 10]; + break; + } + else if (which == '/') + { + prt("Rename which power: ", 0, 0); + which = tolower(inkey()); + + if (isalpha(which) && (A2I(which) <= mut_max)) + { + strcpy(out_val, rune_spells[batch*10 + A2I(which)].name); + if (get_string("Name this power: ", out_val, 29)) + { + strcpy(rune_spells[batch*10 + A2I(which)].name, out_val); + } + prt(tmp, 0, 0); + } + else + { + bell(); + prt(tmp, 0, 0); + } + } + else + { + which = tolower(which); + if (isalpha(which) && (A2I(which) < mut_max)) + { + *s_idx = batch * 10 + A2I(which); + ret = &rune_spells[batch * 10 + A2I(which)]; + break; + } + else + { + bell(); + } + } + } + + character_icky = FALSE; + + return (ret); +} + + +/* + * Pick a random spell from a menu + */ + +rune_spell* select_runespell(int *s_idx) +{ + char tmp[160]; + + char which; + + int batch_max = (rune_num - 1) / 10; + + if (rune_num == 0) + { + msg_print("There are no runespells you can cast."); + return (NULL); + } + + character_icky = TRUE; + Term_save(); + + strnfmt(tmp, 160, "(a-%c) Select batch of powers: ", I2A(batch_max)); + + prt(tmp, 0, 0); + + while (1) + { + which = inkey(); + + if (which == ESCAPE) + { + Term_load(); + character_icky = FALSE; + return (NULL); + } + else if ((which == '\r') && (batch_max == 0)) + { + Term_load(); + character_icky = FALSE; + return (select_runespell_from_batch(0, s_idx)); + + } + else + { + which = tolower(which); + if (isalpha(which) && (A2I(which) <= batch_max)) + { + Term_load(); + character_icky = FALSE; + return (select_runespell_from_batch(A2I(which), s_idx)); + } + else + { + bell(); + } + } + } +} + + +/* + * Cast a memorized runespell + * Note that the only limits are antimagic & conf, NOT blind + */ +void do_cmd_rune_cast() +{ + rune_spell *s_ptr; + + int s_idx; + + + /* Require some mana */ + if (p_ptr->csp <= 0) + { + msg_print("You have no mana!"); + return; + } + + /* No magic */ + if (p_ptr->antimagic) + { + msg_print("Your anti-magic field disrupts any magic attempts."); + return; + } + + /* No magic */ + if (p_ptr->anti_magic) + { + msg_print("Your anti-magic shell disrupts any magic attempts."); + return; + } + + /* Not when confused */ + if (p_ptr->confused) + { + msg_print("You are too confused!"); + return; + } + + s_ptr = select_runespell(&s_idx); + + if (s_ptr == NULL) return; + + /* Need the runes */ + if (!test_runespell(s_ptr)) + { + msg_print("You lack some essential rune(s) for this runespell!"); + return; + } + + /* Execute at normal mana cost */ + p_ptr->csp -= rune_exec(s_ptr, 100); + + /* Safety :) */ + if (p_ptr->csp < 0) p_ptr->csp = 0; + + /* Take a turn */ + if (is_magestaff()) energy_use = 80; + else energy_use = 100; + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + p_ptr->redraw |= (PR_MANA); +} + + +/* + * Cast a runespell from a carved runestone + */ +void do_cmd_runestone() +{ + rune_spell s_ptr; + + object_type *o_ptr; + + cptr q, s; + + int item; + + + /* Require some mana */ + if (p_ptr->csp <= 0) + { + msg_print("You have no mana!"); + return; + } + + /* Require lite */ + if (p_ptr->blind || no_lite()) + { + msg_print("You cannot see!"); + return; + } + + /* Not when confused */ + if (p_ptr->confused) + { + msg_print("You are too confused!"); + return; + } + + /* No magic */ + if (p_ptr->antimagic) + { + msg_print("Your anti-magic field disrupts any magic attempts."); + return; + } + + /* No magic */ + if (p_ptr->anti_magic) + { + msg_print("Your anti-magic shell disrupts any magic attempts."); + return; + } + + /* Restrict choices to unused runes */ + item_tester_hook = item_tester_hook_runestone_full; + + /* Get an item */ + q = "Cast from which runestone? "; + s = "You have no runestone to cast from."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; + + /* Get the item */ + o_ptr = get_object(item); + + s_ptr.type = o_ptr->pval; + s_ptr.rune2 = o_ptr->pval2; + s_ptr.mana = o_ptr->pval3; + + /* Execute less mana */ + p_ptr->csp -= rune_exec(&s_ptr, 75); + + /* Safety :) */ + if (p_ptr->csp < 0) p_ptr->csp = 0; + + /* Take a turn */ + energy_use = 100; + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + p_ptr->redraw |= (PR_MANA); +} + + +/* + * Add a runespell to the list + */ +void do_cmd_rune_add_mem() +{ + rune_spell s_ptr; + + rune_spell *ds_ptr = &rune_spells[rune_num]; + + + /* Not when confused */ + if (p_ptr->confused) + { + msg_print("You are too confused!"); + return; + } + + + if (rune_num >= MAX_RUNES) + { + msg_print("You have already learn the maximun number of runespells!"); + return; + } + + if (!get_runespell(&s_ptr)) return; + + ds_ptr->type = s_ptr.type; + ds_ptr->rune2 = s_ptr.rune2; + ds_ptr->mana = s_ptr.mana; + strcpy(ds_ptr->name, "Unnamed Runespell"); + + get_string("Name this runespell: ", ds_ptr->name, 29); + + rune_num++; + + /* Take a turn */ + energy_use = 100; + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + p_ptr->redraw |= (PR_MANA); +} + + +/* + * Carve a runespell onto a Runestone + */ +void do_cmd_rune_carve() +{ + rune_spell s_ptr; + + object_type *o_ptr; + + cptr q, s; + + int item, i; + + char out_val[80]; + + + /* Not when confused */ + if (p_ptr->confused) + { + msg_print("You are too confused!"); + return; + } + + /* Require lite */ + if (p_ptr->blind || no_lite()) + { + msg_print("You cannot see!"); + return; + } + + if (!get_check("Beware, this will destroy the involved runes, continue?")) + { + return; + } + + if (!get_runespell(&s_ptr)) return; + + /* Restrict choices to unused runes */ + item_tester_hook = item_tester_hook_runestone; + + /* Get an item */ + q = "Use which runestone? "; + s = "You have no runestone to use."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; + + /* Get the item */ + o_ptr = get_object(item); + + o_ptr->pval = s_ptr.type; + o_ptr->pval2 = s_ptr.rune2; + o_ptr->pval3 = s_ptr.mana; + + /* Start with nothing */ + strcpy(out_val, ""); + + /* Use old inscription */ + if (o_ptr->note) + { + /* Start with the old inscription */ + strcpy(out_val, quark_str(o_ptr->note)); + } + + /* Get a new inscription (possibly empty) */ + if (get_string("Name this runestone: ", out_val, 80)) + { + /* Save the inscription */ + o_ptr->note = quark_add(out_val); + + /* Combine the pack */ + p_ptr->notice |= (PN_COMBINE); + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP); + } + + /* Delete the runes */ + for (i = 0; i < INVEN_WIELD; i++) + { + o_ptr = &p_ptr->inventory[i]; + + if (o_ptr->k_idx) + { + bool_ do_del = FALSE; + + if ((o_ptr->tval == TV_RUNE1) && (o_ptr->sval == s_ptr.type)) do_del = TRUE; + if ((o_ptr->tval == TV_RUNE2) && (BIT(o_ptr->sval) & s_ptr.rune2)) do_del = TRUE; + + if (do_del) + { + inc_stack_size_ex(i, -1, OPTIMIZE, NO_DESCRIBE); + } + } + } + + /* Take a turn -- Carving takes a LONG time */ + energy_use = 400; + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + p_ptr->redraw |= (PR_MANA); +} + + +/* + * Remove a runespell + */ +void do_cmd_rune_del() +{ + rune_spell *s_ptr; + + int s_idx; + + int i; + + + /* Not when confused */ + if (p_ptr->confused) + { + msg_print("You are too confused!"); + return; + } + + s_ptr = select_runespell(&s_idx); + + if (s_ptr == NULL) return; + + /* Delete and move */ + for (i = s_idx + 1; i < rune_num; i++) + { + rune_spells[i - 1].type = rune_spells[i].type; + rune_spells[i - 1].rune2 = rune_spells[i].rune2; + rune_spells[i - 1].mana = rune_spells[i].mana; + strcpy(rune_spells[i - 1].name, rune_spells[i].name); + } + rune_num--; + + /* Take a turn */ + energy_use = 100; + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + p_ptr->redraw |= (PR_MANA); +} + + +void do_cmd_rune_add() +{ + int ext = 0; + + char ch; + + + /* Select what to do */ + while (TRUE) + { + if (!get_com("Add to [M]emory(need runes to cast) or " + "Carve a [R]unestone(less mana to cast)", &ch)) + { + ext = 0; + break; + } + if ((ch == 'M') || (ch == 'm')) + { + ext = 1; + break; + } + if ((ch == 'R') || (ch == 'r')) + { + ext = 2; + break; + } + } + + switch (ext) + { + /* Create a Spell in memory */ + case 1: + { + do_cmd_rune_add_mem(); + break; + } + + /* Carve a Runestone */ + case 2: + { + do_cmd_rune_carve(); + break; + } + } +} + + +void do_cmd_runecrafter() +{ + int ext = 0; + + char ch; + + + /* Select what to do */ + while (TRUE) + { + if (!get_com("Rune Spell:[C]reate, [D]elete, C[a]st, D[i]rectly Cast " + "or Use [R]unestone", &ch)) + { + ext = 0; + break; + } + if ((ch == 'C') || (ch == 'c')) + { + ext = 1; + break; + } + if ((ch == 'D') || (ch == 'd')) + { + ext = 2; + break; + } + if ((ch == 'A') || (ch == 'a')) + { + ext = 3; + break; + } + if ((ch == 'I') || (ch == 'i')) + { + ext = 4; + break; + } + if ((ch == 'R') || (ch == 'r')) + { + ext = 5; + break; + } + } + + switch (ext) + { + /* Create a Spell */ + case 1: + { + do_cmd_rune_add(); + break; + } + + /* Delete a Spell */ + case 2: + { + do_cmd_rune_del(); + break; + } + + /* Cast a Spell */ + case 3: + { + do_cmd_rune_cast(); + break; + } + + /* Directly Cast a Spell */ + case 4: + { + do_cmd_rune(); + break; + } + + /* Cast a Runestone */ + case 5: + { + do_cmd_runestone(); + break; + } + } +} + + +void do_cmd_unbeliever_antimagic() +{ + if (get_skill(SKILL_ANTIMAGIC) < 20) + { + msg_print("You must have at least a level 20 antimagic skill " + "to be able to disrupt the magic continuum."); + return; + } + + if (p_ptr->antimagic_extra & CLASS_ANTIMAGIC) + { + p_ptr->antimagic_extra &= ~CLASS_ANTIMAGIC; + msg_print("You stop disrupting the magic continuum."); + } + else + { + p_ptr->antimagic_extra |= CLASS_ANTIMAGIC; + msg_print("You start disrupting the magic continuum."); + } + + /* Recalculate bonuses */ + p_ptr->update |= (PU_BONUS); +} + + +/* + * Detect traps + kill traps + */ +void do_cmd_unbeliever() +{ + int ext = 0; + + char ch; + + + /* Select what to do */ + while (TRUE) + { + if (!get_com("Disrupt [C]ontinuum or [D]etect Traps", &ch)) + { + ext = 0; + break; + } + if ((ch == 'C') || (ch == 'c')) + { + ext = 1; + break; + } + if ((ch == 'D') || (ch == 'd')) + { + ext = 2; + break; + } + } + + switch (ext) + { + /* Disrupt Continuum */ + case 1: + { + do_cmd_unbeliever_antimagic(); + break; + } + + /* Detect Traps */ + case 2: + { + s16b skill = get_skill(SKILL_ANTIMAGIC); + + if (skill < 25) + { + msg_print("You cannot use your detection abilities yet."); + break; + } + + detect_traps(DEFAULT_RADIUS); + + if (skill >= 35) destroy_doors_touch(); + + break; + } + } +} + +/* + * Hook to determine if an object is totemable + */ +static bool_ item_tester_hook_totemable(object_type *o_ptr) +{ + /* Only full corpse */ + if ((o_ptr->tval == TV_CORPSE) && + ((o_ptr->sval == SV_CORPSE_CORPSE) || (o_ptr->sval == SV_CORPSE_SKELETON))) + { + return (TRUE); + } + + /* Assume not */ + return (FALSE); +} + + +/* + * Summoners + */ +void do_cmd_summoner_extract() +{ + object_type *o_ptr, forge, *q_ptr; + + cptr q, s; + + int item, r; + + bool_ partial; + + + /* Not when confused */ + if (p_ptr->confused) + { + msg_print("You are too confused!"); + return; + } + + /* Require lite */ + if (p_ptr->blind || no_lite()) + { + msg_print("You cannot see!"); + return; + } + + item_tester_hook = item_tester_hook_totemable; + + /* Get an item */ + q = "Use which corpse? "; + s = "You have no corpse to use."; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; + + /* Get the item */ + o_ptr = get_object(item); + + + if (r_info[o_ptr->pval2].flags1 & RF1_UNIQUE) + { + partial = FALSE; + } + else + { + partial = get_check("Do you want to create a partial totem?"); + } + + r = o_ptr->pval2; + + inc_stack_size(item, -1); + + if (magik(r_info[o_ptr->pval2].level - get_skill(SKILL_SUMMON))) + { + msg_print("You failed to extract a totem."); + energy_use += 100; + return; + } + + /* Prepare for object creation */ + q_ptr = &forge; + + /* Create the object */ + object_prep(q_ptr, lookup_kind(TV_TOTEM, partial ? 1 : 2)); + q_ptr->pval = r; + q_ptr->pval2 = 0; + q_ptr->number = 1; + q_ptr->found = OBJ_FOUND_SELFMADE; + object_aware(q_ptr); + object_known(q_ptr); + q_ptr->ident |= IDENT_MENTAL; + (void)inven_carry(q_ptr, FALSE); + + msg_print("You extract a totem from the dead corpse."); + energy_use += 100; +} + + +void summon_true(int r_idx, int item) +{ + int i, status, x = 1, y = 1, rx, ry = 0, chance; + + bool_ used; + + monster_race *r_ptr = &r_info[r_idx]; + + + /* Uniques are less likely to be nice */ + if (r_ptr->flags1 & (RF1_UNIQUE)) + { + /* Because it's unique, it will always be destroyed */ + used = TRUE; + + /* About twice as hard as non-uniques */ + chance = (get_skill(SKILL_SUMMON) * 70 / (r_ptr->level + 1)); + + if (magik(chance)) + { + status = MSTATUS_PET; + } + else + { + status = MSTATUS_ENEMY; + } + } + + /* Non-uniques are easier to handle */ + else + { + if (get_skill(SKILL_SUMMON) == 0) + { + used = TRUE; + } + else + { + /* It can be used multiple times */ + used = FALSE; + + /* But it is not 100% sure (note: skill > 0) */ + chance = (r_ptr->level * 25 / get_skill(SKILL_SUMMON)); + if (magik(chance)) used = TRUE; + } + + chance = (get_skill(SKILL_SUMMON) * 130 / (r_ptr->level + 1)); + + if (magik(chance)) + { + status = MSTATUS_PET; + } + else + { + status = MSTATUS_ENEMY; + } + } + + /* Find a grid where the monster is summoned */ + for (i = 0; i < 40; i++) + { + rx = (rand_int(8) - 4) + p_ptr->px; + ry = (rand_int(8) - 4) + p_ptr->py; + if (in_bounds(ry, rx) && cave_empty_bold(ry, rx)) + { + x = rx; + y = ry; + break; + } + } + + /* No room found */ + if (i == 40) + { + msg_print("The summoning fails due to lack of room."); + return; + } + + /* Summon the monster */ + bypass_r_ptr_max_num = TRUE; + if (!(i = place_monster_one (y, x, r_idx, 0, 0, status))) + { + msg_print("The summoning fails."); + } + else + { + m_list[i].status = status; + m_list[i].mflag |= MFLAG_NO_DROP; + } + bypass_r_ptr_max_num = FALSE; + + /* Destroy the totem if the used flag is set */ + if (used) + { + /* Eliminate the totem */ + inc_stack_size(item, -1); + } + + /* Done */ + return; +} + + +void do_cmd_summoner_summon() +{ + int item, x = 1, y = 1, rx, ry, m_idx = 0, i; + + cptr q, s; + + object_type *o_ptr; + + monster_type *m_ptr; + + + /* Which Totem? */ + item_tester_tval = TV_TOTEM; + + q = "Summon from which Totem?"; + s = "There are no totems to summon from!"; + if (!get_item(&item, q, s, (USE_INVEN | USE_FLOOR))) return; + + /* Access the item */ + o_ptr = get_object(item); + + /* Take a turn */ + energy_use = 100; + + /* True Totems have their own function. */ + if (o_ptr->sval == 2) + { + summon_true(o_ptr->pval, item); + return; + } + + /* Handle partial totems */ + + /* Find a grid where the monster is summoned */ + for (i = 0; i < 40; i++) + { + rx = (rand_int(8) - 4) + p_ptr->px; + ry = (rand_int(8) - 4) + p_ptr->py; + if (in_bounds(ry, rx) && cave_empty_bold(ry, rx)) + { + x = rx; + y = ry; + break; + } + } + + /* No room found */ + if (i == 40) + { + msg_print("The summoning fails due to lack of room."); + return; + } + + /* Summon the monster */ + bypass_r_ptr_max_num = TRUE; + place_monster_one_no_drop = TRUE; + m_idx = place_monster_one(y, x, o_ptr->pval, 0, 0, MSTATUS_PET); + bypass_r_ptr_max_num = FALSE; + + /* Failure. */ + if (!m_idx) + { + msg_print("The summoning fails."); + } + + /* Mark the monster as a "partial" ally */ + m_ptr = &m_list[m_idx]; + m_ptr->mflag |= MFLAG_PARTIAL | MFLAG_NO_DROP; +} + + +void do_cmd_summoner(void) +{ + int ext = 0; + + char ch; + + /* No magic */ + if (p_ptr->antimagic) + { + msg_print("Your anti-magic field disrupts any magic attempts."); + return; + } + + /* No magic */ + if (p_ptr->anti_magic) + { + msg_print("Your anti-magic shell disrupts any magic attempts."); + return; + } + + /* not if confused */ + if (p_ptr->confused) + { + msg_print("You are too confused!"); + return; + } + + /* not if blind */ + if (p_ptr->blind || no_lite()) + { + msg_print("You cannot see!"); + return; + } + + /* Select what to do */ + while (TRUE) + { + if (!get_com("[E]xtract a totem, [S]ummon", &ch)) + { + ext = 0; + break; + } + if ((ch == 'E') || (ch == 'e')) + { + ext = 1; + break; + } + if ((ch == 's') || (ch == 'S')) + { + ext = 2; + break; + } + } + + switch (ext) + { + case 1: + { + do_cmd_summoner_extract(); + break; + } + + case 2: + { + do_cmd_summoner_summon(); + break; + } + } +} + + +/* + * Fighters may invoke The Rush. + */ +void do_cmd_blade(void) +{ + /* Are we already Rushed? */ + if (p_ptr->rush) + { + msg_format("You have %d turns of The Rush remaining", p_ptr->rush); + return; + } + + /* Are you sure? */ + if (!get_check("Are you sure you want to invoke The Rush?")) return; + + /* Let's Rush! */ + set_rush(2 + p_ptr->lev / 2 + randint(p_ptr->lev / 2)); +} + + +/* + * Dodge Chance Feedback. + */ +void use_ability_blade(void) +{ + int chance = p_ptr->dodge_chance - ((dun_level * 5) / 6); + + if (chance < 0) chance = 0; + if (wizard) + { + msg_format("You have exactly %d chances of dodging a level %d monster.", chance, dun_level); + } + + if (chance < 5) + { + msg_format("You have almost no chance of dodging a level %d monster.", dun_level); + } + else if (chance < 10) + { + msg_format("You have a slight chance of dodging a level %d monster.", dun_level); + } + else if (chance < 20) + { + msg_format("You have a significant chance of dodging a level %d monster.", dun_level); + } + else if (chance < 40) + { + msg_format("You have a large chance of dodging a level %d monster.", dun_level); + } + else if (chance < 70) + { + msg_format("You have a high chance of dodging a level %d monster.", dun_level); + } + else + { + msg_format("You will usually dodge successfully a level %d monster.", dun_level); + } + + return; +} + +/* + * Helper function to describe symbiotic powers + */ +void symbiotic_info(char *p, int power) +{ + int plev = get_skill(SKILL_SYMBIOTIC); + + strcpy(p, ""); + + switch (power) + { + case 2: + { + strnfmt(p, 80, " power %d", plev * 3); + break; + } + case 5: + { + strnfmt(p, 80, " heal %d%%", 15 + get_skill_scale(SKILL_SYMBIOTIC, 35)); + break; + } + } +} + + +/* + * Cast a symbiotic spell + */ +void do_cmd_symbiotic(void) +{ + int n = 0; + int chance; + int minfail = 0; + int plev = get_skill(SKILL_SYMBIOTIC); + magic_power spell; + + /* Get the carried monster */ + object_type *o_ptr = &p_ptr->inventory[INVEN_CARRY]; + + /* No magic */ + if (p_ptr->antimagic) + { + msg_print("Your anti-magic field disrupts any magic attempts."); + return; + } + + /* No magic */ + if (p_ptr->anti_magic) + { + msg_print("Your anti-magic shell disrupts any magic attempts."); + return; + } + + /* not if confused */ + if (p_ptr->confused) + { + msg_print("You are too confused!"); + return; + } + + /* get power */ + if (!get_magic_power(&n, symbiotic_powers, MAX_SYMBIOTIC_POWERS, symbiotic_info, + get_skill(SKILL_SYMBIOTIC), A_INT)) return; + + spell = symbiotic_powers[n]; + + /* Verify "dangerous" spells */ + if (spell.mana_cost > p_ptr->csp) + { + /* Warning */ + msg_print("You do not have enough mana to use this power."); + + /* Verify */ + if (!get_check("Attempt it anyway? ")) return; + } + + /* Spell failure chance */ + chance = spell.fail; + + /* Reduce failure rate by "effective" level adjustment */ + chance -= 3 * (plev - spell.min_lev); + + /* Reduce failure rate by INT/WIS adjustment */ + chance -= 3 * (adj_mag_stat[p_ptr->stat_ind[A_INT]] - 1); + + /* Not enough mana to cast */ + if (spell.mana_cost > p_ptr->csp) + { + chance += 5 * (spell.mana_cost - p_ptr->csp); + } + + /* Extract the minimum failure rate */ + minfail = adj_mag_fail[p_ptr->stat_ind[A_INT]]; + + /* Failure rate */ + chance = clamp_failure_chance(chance, minfail); + + /* Failed spell */ + if (rand_int(100) < chance) + { + if (flush_failure) flush(); + msg_format("You failed to concentrate hard enough!"); + sound(SOUND_FAIL); + } + else + { + sound(SOUND_ZAP); + + /* spell code */ + switch (n) + { + case 0: + { + int dir, x, y; + cave_type *c_ptr; + monster_type *m_ptr; + monster_race *r_ptr; + object_type *q_ptr; + object_type forge; + + msg_print("Hypnotise which pet?"); + if (!get_rep_dir(&dir)) return; + y = p_ptr->py + ddy[dir]; + x = p_ptr->px + ddx[dir]; + c_ptr = &cave[y][x]; + if (c_ptr->m_idx) + { + m_ptr = &m_list[c_ptr->m_idx]; + r_ptr = race_inf(m_ptr); + + if (!(r_ptr->flags1 & RF1_NEVER_MOVE)) + { + msg_print("You can only hypnotise monsters that cannot move."); + } + else if (m_ptr->status < MSTATUS_PET) + { + msg_print("You can only hypnotise pets and companions."); + } + else if (r_ptr->flags9 & RF9_SPECIAL_GENE) + { + msg_print("You cannot hypnotise this monster."); + } + else + { + /* TODO fix this hack hack hack hackity hack with ToME 3 flags */ + q_ptr = &forge; + object_prep(q_ptr, lookup_kind(TV_HYPNOS, 1)); + q_ptr->number = 1; + q_ptr->pval = m_ptr->r_idx; + q_ptr->pval2 = m_ptr->hp; + q_ptr->pval3 = m_ptr->maxhp; + /* overflow alert */ + q_ptr->exp = m_ptr->exp; + q_ptr->elevel = m_ptr->level; + object_aware(q_ptr); + object_known(q_ptr); + + q_ptr->ident |= IDENT_STOREB; + + drop_near(q_ptr, 0, y, x); + + delete_monster(y, x); + health_who = 0; + } + } + else + { + msg_print("There is no pet here !"); + } + + break; + } + + case 1: + { + monster_type *m_ptr; + int m_idx; + int item, x, y, d; + object_type *o_ptr; + + cptr q, s; + + /* Restrict choices to monsters */ + item_tester_tval = TV_HYPNOS; + + /* Get an item */ + q = "Awaken which monster? "; + s = "You have no monster to awaken."; + if (!get_item(&item, q, s, (USE_FLOOR))) return; + + o_ptr = &o_list[0 - item]; + + d = 2; + while (d < 100) + { + scatter(&y, &x, p_ptr->py, p_ptr->px, d); + + if (cave_floor_bold(y, x) && (!cave[y][x].m_idx)) break; + + d++; + } + + if (d >= 100) return; + + if ((m_idx = place_monster_one(y, x, o_ptr->pval, 0, FALSE, MSTATUS_PET)) == 0) return; + + /* TODO fix this hack hack hack hackity hack with ToME 3 flags */ + /* Have to be careful here; releasing the symbiote into a + * dungeon with leveled monsters will level the symbiote + * before we can get hold of it. We'll be nice and use the + * larger of the saved exp and the exp that the newly-generated + * monster starts with. */ + m_ptr = &m_list[m_idx]; + if (m_ptr->exp < o_ptr->exp) + { + m_ptr->exp = o_ptr->exp; + monster_check_experience(m_idx, TRUE); + if (m_ptr->level != o_ptr->elevel) + cmsg_format(TERM_VIOLET, "ERROR: level-%d HYPNOS becomes level-%d symbiote", o_ptr->elevel, m_ptr->level); + } + m_ptr->hp = o_ptr->pval2; + m_ptr->maxhp = o_ptr->pval3; + + floor_item_increase(0 - item, -1); + floor_item_describe(0 - item); + floor_item_optimize(0 - item); + break; + } + + /* Charm */ + case 2: + { + int dir; + + if (!get_aim_dir(&dir)) return; + + fire_bolt(GF_CHARM_UNMOVING, dir, plev * 3); + + break; + } + + /* Life Share */ + case 3: + { + s32b percent1, percent2; + + if (!o_ptr->k_idx) + { + msg_print("You are not in symbiosis."); + break; + } + + percent1 = p_ptr->chp; + percent1 = (percent1 * 100) / p_ptr->mhp; + + percent2 = o_ptr->pval2; + percent2 = (percent2 * 100) / o_ptr->pval3; + + /* Now get the average */ + percent1 = (percent1 + percent2) / 2; + + /* And set the hp of monster & player to it */ + p_ptr->chp = (percent1 * p_ptr->mhp) / 100; + o_ptr->pval2 = (percent1 * o_ptr->pval3) / 100; + + /* Redraw */ + p_ptr->redraw |= (PR_HP); + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + + /* Display the monster hitpoints */ + p_ptr->redraw |= (PR_MH); + + break; + } + + /* Minor Symbiotic Powers */ + case 4: + { + if (!o_ptr->k_idx) + { + msg_print("You are not in symbiosis."); + break; + } + + if (0 > use_symbiotic_power(o_ptr->pval, FALSE, FALSE, TRUE)) + return; + + break; + } + + /* Heal Symbiote */ + case 5: + { + int hp; + + if (!o_ptr->k_idx) + { + msg_print("You are not in symbiosis."); + break; + } + + hp = o_ptr->pval3 * (15 + get_skill_scale(SKILL_SYMBIOTIC, 35)) / 100; + o_ptr->pval2 += hp; + if (o_ptr->pval2 > o_ptr->pval3) o_ptr->pval2 = o_ptr->pval3; + + msg_format("%s is healed.", symbiote_name(TRUE)); + + /* Display the monster hitpoints */ + p_ptr->redraw |= (PR_MH); + + break; + } + + + /* Major Symbiotic Powers */ + case 6: + { + if (!o_ptr->k_idx) + { + msg_print("You are not in symbiosis."); + break; + } + + if(0 > use_symbiotic_power(o_ptr->pval, TRUE, FALSE, TRUE)) + return; + + break; + } + + /* Summon never-moving pet */ + case 7: + { + summon_specific_friendly(p_ptr->py, p_ptr->px, dun_level, SUMMON_MINE, FALSE); + + break; + } + + /* Force Symbiosis */ + case 8: + { + int y, x; + cave_type *c_ptr; + monster_type *m_ptr; + + if (!tgt_pt(&x, &y)) return; + + c_ptr = &cave[y][x]; + + if (!c_ptr->m_idx) break; + + m_ptr = &m_list[c_ptr->m_idx]; + use_symbiotic_power(m_ptr->r_idx, TRUE, FALSE, TRUE); + + break; + } + + + default: + { + msg_print("Zap?"); + + break; + } + } + } + + /* Take a turn */ + energy_use = 100; + + /* Sufficient mana */ + if (spell.mana_cost <= p_ptr->csp) + { + /* Use some mana */ + p_ptr->csp -= spell.mana_cost; + } + + /* Over-exert the player */ + else + { + int oops = spell.mana_cost - p_ptr->csp; + + /* No mana left */ + p_ptr->csp = 0; + p_ptr->csp_frac = 0; + + /* Message */ + msg_print("You faint from the effort!"); + + /* Hack -- Bypass free action */ + (void)set_paralyzed(randint(5 * oops + 1)); + + /* Damage CON (possibly permanently) */ + if (rand_int(100) < 50) + { + bool_ perm = (rand_int(100) < 25); + + /* Message */ + msg_print("You have damaged your body!"); + + /* Reduce constitution */ + (void)dec_stat(A_CHR, 15 + randint(10), perm); + } + } + + /* Redraw mana */ + p_ptr->redraw |= (PR_MANA); + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); +} + +/* + * Boulder creation .. sorry :) + */ +void do_cmd_create_boulder() +{ + int x, y, dir; + cave_type *c_ptr; + + if (!get_rep_dir(&dir)) return; + y = p_ptr->py + ddy[dir]; + x = p_ptr->px + ddx[dir]; + c_ptr = &cave[y][x]; + + /* Granite -- How about other wall types? */ + if (((c_ptr->feat >= FEAT_WALL_EXTRA) && (c_ptr->feat <= FEAT_WALL_SOLID)) || + ((c_ptr->feat >= FEAT_MAGMA_H) && (c_ptr->feat <= FEAT_QUARTZ_K)) || + ((c_ptr->feat == FEAT_MAGMA) || + (c_ptr->feat == FEAT_QUARTZ))) + { + object_type forge; + object_type *q_ptr; + + (void)wall_to_mud(dir); + + /* Get local object */ + q_ptr = &forge; + + /* Hack -- Give the player some shots */ + object_prep(q_ptr, lookup_kind(TV_JUNK, SV_BOULDER)); + q_ptr->number = (byte)rand_range(2, 5); + object_aware(q_ptr); + object_known(q_ptr); + q_ptr->ident |= IDENT_MENTAL; + q_ptr->discount = 90; + q_ptr->found = OBJ_FOUND_SELFMADE; + + (void)inven_carry(q_ptr, FALSE); + + msg_print("You make some boulders."); + + p_ptr->update |= (PU_VIEW | PU_FLOW | PU_MON_LITE); + p_ptr->window |= (PW_OVERHEAD); + + /* Take a turn */ + energy_use = 100; + } +} + +/* + * Clamp failure chance + */ +extern int clamp_failure_chance(int chance, int minfail) +{ + if (minfail < 0) minfail = 0; + + /* Minimum failure rate */ + if (chance < minfail) chance = minfail; + + /* Stunning makes spells harder */ + if (p_ptr->stun > 50) chance += 25; + else if (p_ptr->stun) chance += 15; + + /* Always a 5 percent chance of working */ + if (chance > 95) chance = 95; + + return chance; +} diff --git a/src/cmovie.c b/src/cmovie.c deleted file mode 100644 index d1459e02..00000000 --- a/src/cmovie.c +++ /dev/null @@ -1,496 +0,0 @@ -/* File: cmovie.c */ - -/* Purpose: play cmovie files -DarkGod-Improv- */ - -#include "angband.h" - -/* - * Play a given cmovie - */ -s16b do_play_cmovie(cptr cmov_file) -{ - FILE *fff; - - int y, line = 0, x; - int delay; - - char *s; - - char buf[1024]; - char cbuf[90]; - char ch; - - char mode = 0; - - - /* Cmovie files are moved to the user directory on the multiuser systems */ - - /* Build the filename */ - path_build(buf, 1024, ANGBAND_DIR_CMOV, cmov_file); - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - /* Read the file */ - fff = my_fopen(buf, "r"); - - /* Failure */ - if (!fff) return ( -1); - - /* Save screen */ - character_icky = TRUE; - Term_save(); - Term_clear(); - - /* Give some usefull info */ - prt("While viewing the movie you can press Escape to exit, t/Space to switch between", 0, 0); - prt("fluid more and step by step mode and any other key to step a frame in step by", 1, 0); - prt("step mode.", 2, 0); - prt("You can press D to do an html screenshot of the current frame.", 3, 0); - prt("You can also use + and - to speed up/down the playing speed.", 5, 0); - prt("Press any key when ready.", 8, 0); - - inkey(); - - Term_clear(); - - line = -1; - - delay = 1; - - /* Init to white */ - for (x = 0; x < 80; x++) - { - cbuf[x] = 'w'; - } - - /* Parse */ - while (0 == my_fgets(fff, buf, 1024)) - { - /* Do not wait */ - inkey_scan = TRUE; - ch = inkey(); - - /* Stop */ - if (ch == ESCAPE) break; - - /* Change mode */ - else if (ch == 't') - { - mode = FALSE; - } - else if (ch == ' ') - { - mode = TRUE; - } - - /* Change speed */ - else if (ch == '+') - { - delay--; - if (delay < 0) delay = 0; - } - else if (ch == '-') - { - delay++; - if (delay > 5) delay = 5; - } - else if (ch == 'D') - { - do_cmd_html_dump(); - } - - line++; - - /* Skip comments and blank lines */ - if (!buf[0] || (buf[0] == '#')) continue; - - /* Verify correct "colon" format */ - if (buf[1] != ':') break; - - /* Clean screen */ - if (buf[0] == 'C') - { - Term_clear(); - - /* Next */ - continue; - } - - /* Displays a textbox */ - if (buf[0] == 'B') - { - int len = strlen(buf + 2); - - /* Clear the line */ - Term_erase(0, 0, 255); - - /* Display the message */ - c_put_str(TERM_VIOLET, "###", 0, 0); - c_put_str(TERM_ORANGE, buf + 2, 0, 3); - c_put_str(TERM_VIOLET, "###", 0, 3 + len); - c_put_str(TERM_WHITE, "(more)", 0, 6 + len); - - /* Next */ - continue; - } - - /* Wait a key */ - if (buf[0] == 'W') - { - inkey(); - - /* Next */ - continue; - } - - /* Sleep */ - if (buf[0] == 'S') - { - long msec; - - /* Scan for the values */ - if (1 != sscanf(buf + 2, "%ld:", &msec)) - { - return ( -2); - } - - if (!mode) - { - Term_xtra(TERM_XTRA_DELAY, msec); - } - else - { - bool_ stop = FALSE; - - while (TRUE) - { - ch = inkey(); - - /* Stop */ - if (ch == ESCAPE) - { - stop = TRUE; - break; - } - /* Change mode */ - else if (ch == 't') - { - mode = FALSE; - break; - } - /* Change mode */ - else if (ch == ' ') - { - if (mode) continue; - mode = TRUE; - break; - } - /* Change speed */ - else if (ch == '+') - { - delay--; - if (delay < 0) delay = 0; - } - else if (ch == '-') - { - delay++; - if (delay > 5) delay = 5; - } - else if (ch == 'D') - { - do_cmd_html_dump(); - } - else break; - } - if (stop) break; - } - - /* Next */ - continue; - } - - /* Get color for the NEXT L line */ - if (buf[0] == 'E') - { - /* Find the colon before the name */ - s = strchr(buf + 2, ':'); - - /* Verify that colon */ - if (!s) return ( -2); - - /* Nuke the colon, advance to the name */ - *s++ = '\0'; - - /* Paranoia -- require a name */ - if (!*s) return ( -2); - - /* Get the index */ - y = atoi(buf + 2); - - C_COPY(cbuf, s, 80, char); - - /* Next... */ - continue; - } - - /* Print a line */ - if (buf[0] == 'L') - { - /* Find the colon before the name */ - s = strchr(buf + 2, ':'); - - /* Verify that colon */ - if (!s) return ( -2); - - /* Nuke the colon, advance to the name */ - *s++ = '\0'; - - /* Paranoia -- require a name */ - if (!*s) return ( -2); - - /* Get the index */ - y = atoi(buf + 2); - - for (x = 0; x < 80; x++) - { - Term_putch(x, y, color_char_to_attr(cbuf[x]), s[x]); - - /* Reinit to white */ - cbuf[x] = 'w'; - } - Term_redraw_section(0, y, 79, y); - - /* Next... */ - continue; - } - - /* Update 1 char */ - if (buf[0] == 'P') - { - int x, y, a, c; - - /* Scan for the values */ - if (4 != sscanf(buf + 2, "%d:%d:%d:%d", - &x, &y, &c, &a)) - { - a = 'w'; - if (3 != sscanf(buf + 2, "%d:%d:%d", - &x, &y, &c)) return ( -2); - } - - Term_putch(x, y, color_char_to_attr(cbuf[x]), c); - Term_redraw_section(x, y, x + 1, y + 1); - - /* Next... */ - continue; - } - } - - /* Load screen */ - Term_load(); - character_icky = FALSE; - - /* Close */ - my_fclose(fff); - - return (0); -} - - -/* - * Start the recording of a cmovie - */ -void do_record_cmovie(cptr cmovie) -{ - char buf[1024]; - int fd = -1; - int y; - - - /* Build the filename */ - path_build(buf, 1024, ANGBAND_DIR_CMOV, cmovie); - - /* File type is "TEXT" */ - FILE_TYPE(FILE_TYPE_TEXT); - - /* Check for existing file */ - fd = fd_open(buf, O_RDONLY); - - /* Existing file */ - if (fd >= 0) - { - char out_val[160]; - - /* Close the file */ - (void)fd_close(fd); - - /* Build query */ - (void)sprintf(out_val, "Replace existing file %s? ", cmovie); - - /* Ask */ - if (get_check(out_val)) fd = -1; - } - - /* Be sure */ - if (!get_check("Ready to record(Press ctrl+D to enter a textual note while recording)?")) return; - - /* Open the non-existing file */ - if (fd < 0) movfile = my_fopen(buf, "w"); - - /* Invalid file */ - if (movfile == NULL) - { - msg_format("Cmovie recording failed!"); - - return; - } - - /* First thing: Record clear screen then enable the recording */ - fprintf(movfile, "# Generated by %s\n", - get_version_string()); - fprintf(movfile, "C:\n"); - last_paused = 0; - do_movies = 1; - cmovie_init_second(); - - /* Mega Hack, get the screen */ - for (y = 0; y < Term->hgt; y++) - { - cmovie_record_line(y); - } -} - - -/* - * Stop the recording - */ -void do_stop_cmovie() -{ - if (do_movies == 1) - { - do_movies = 0; - my_fclose(movfile); - } -} - - -/* - * Start a cmovie - */ -void do_start_cmovie() -{ - char name[90], rname[94]; - - - /* Should never happen */ - if (do_movies == 1) return; - - /* Default */ - sprintf(name, "%s", player_base); - - if (get_string("Cmovie name: ", name, 80)) - { - if (name[0] && (name[0] != ' ')) - { - sprintf(rname, "%s.cmv", name); - - if (get_check("Record(y), Play(n)?")) do_record_cmovie(rname); - else do_play_cmovie(rname); - } - } -} - - -void cmovie_clean_line(int y, char *abuf, char *cbuf) -{ - const byte *ap = Term->scr->a[y]; - const char *cp = Term->scr->c[y]; - - byte a; - char c; - - int x; - int wid, hgt; - int screen_wid, screen_hgt; - - - /* Retrieve current screen size */ - Term_get_size(&wid, &hgt); - - /* Calculate the size of dungeon map area */ - screen_wid = wid - (COL_MAP + 1); - screen_hgt = hgt - (ROW_MAP + 1); - - /* For the time being, assume 80 column display XXX XXX XXX */ - for (x = 0; x < wid; x++) - { - /* Convert dungeon map into default attr/chars */ - if (!character_icky && - ((x - COL_MAP) >= 0) && - ((x - COL_MAP) < screen_wid) && - ((y - ROW_MAP) >= 0) && - ((y - ROW_MAP) < screen_hgt)) - { - /* Retrieve default attr/char */ - map_info_default(y + panel_row_prt, x + panel_col_prt, &a, &c); - - abuf[x] = conv_color[a & 0xf]; - - if (c == '\0') cbuf[x] = ' '; - else cbuf[x] = c; - } - - else - { - abuf[x] = conv_color[ap[x] & 0xf]; - cbuf[x] = cp[x]; - } - } - - /* Null-terminate the prepared strings */ - abuf[x] = '\0'; - cbuf[x] = '\0'; -} - - -/* - * Write a record of a screen row into a cmovie file - */ -void cmovie_record_line(int y) -{ - char abuf[256]; - char cbuf[256]; - - cmovie_clean_line(y, abuf, cbuf); - - /* Write a colour record */ - fprintf(movfile, "E:%d:%.80s\n", y, abuf); - - /* Write a char record */ - fprintf(movfile, "L:%d:%.80s\n", y, cbuf); -} - - -/* - * Record a "text box" - */ -void do_cmovie_insert() -{ - char buf[81] = ""; - - /* Dont record */ - do_movies = 2; - - while (get_string("Textbox(ESC to end): ", buf, 80)) - { - fprintf(movfile, "B:%s\nW:\n", buf); - buf[0] = '\0'; - } - - /* We reinit the time as to not count the time the user needed ot enter the text */ - cmovie_init_second(); - - /* Continue recording */ - do_movies = 1; -} diff --git a/src/cmovie.cc b/src/cmovie.cc new file mode 100644 index 00000000..85db2a32 --- /dev/null +++ b/src/cmovie.cc @@ -0,0 +1,500 @@ +/* File: cmovie.c */ + +/* Purpose: play cmovie files -DarkGod-Improv- */ + +#include "angband.h" + +/* + * Play a given cmovie + */ +s16b do_play_cmovie(cptr cmov_file) +{ + FILE *fff; + + int y, line = 0, x; + int delay; + + char *s; + + char buf[1024]; + char cbuf[90]; + char ch; + + char mode = 0; + + + /* Cmovie files are moved to the user directory on the multiuser systems */ + + /* Build the filename */ + path_build(buf, 1024, ANGBAND_DIR_CMOV, cmov_file); + + /* File type is "TEXT" */ + FILE_TYPE(FILE_TYPE_TEXT); + + /* Read the file */ + fff = my_fopen(buf, "r"); + + /* Failure */ + if (!fff) return ( -1); + + /* Save screen */ + character_icky = TRUE; + Term_save(); + Term_clear(); + + /* Give some usefull info */ + prt("While viewing the movie you can press Escape to exit, t/Space to switch between", 0, 0); + prt("fluid more and step by step mode and any other key to step a frame in step by", 1, 0); + prt("step mode.", 2, 0); + prt("You can press D to do an html screenshot of the current frame.", 3, 0); + prt("You can also use + and - to speed up/down the playing speed.", 5, 0); + prt("Press any key when ready.", 8, 0); + + inkey(); + + Term_clear(); + + line = -1; + + delay = 1; + + /* Init to white */ + for (x = 0; x < 80; x++) + { + cbuf[x] = 'w'; + } + + /* Parse */ + while (0 == my_fgets(fff, buf, 1024)) + { + /* Do not wait */ + inkey_scan = TRUE; + ch = inkey(); + + /* Stop */ + if (ch == ESCAPE) break; + + /* Change mode */ + else if (ch == 't') + { + mode = FALSE; + } + else if (ch == ' ') + { + mode = TRUE; + } + + /* Change speed */ + else if (ch == '+') + { + delay--; + if (delay < 0) delay = 0; + } + else if (ch == '-') + { + delay++; + if (delay > 5) delay = 5; + } + else if (ch == 'D') + { + do_cmd_html_dump(); + } + + line++; + + /* Skip comments and blank lines */ + if (!buf[0] || (buf[0] == '#')) continue; + + /* Verify correct "colon" format */ + if (buf[1] != ':') break; + + /* Clean screen */ + if (buf[0] == 'C') + { + Term_clear(); + + /* Next */ + continue; + } + + /* Displays a textbox */ + if (buf[0] == 'B') + { + int len = strlen(buf + 2); + + /* Clear the line */ + Term_erase(0, 0, 255); + + /* Display the message */ + c_put_str(TERM_VIOLET, "###", 0, 0); + c_put_str(TERM_ORANGE, buf + 2, 0, 3); + c_put_str(TERM_VIOLET, "###", 0, 3 + len); + c_put_str(TERM_WHITE, "(more)", 0, 6 + len); + + /* Next */ + continue; + } + + /* Wait a key */ + if (buf[0] == 'W') + { + inkey(); + + /* Next */ + continue; + } + + /* Sleep */ + if (buf[0] == 'S') + { + long msec; + + /* Scan for the values */ + if (1 != sscanf(buf + 2, "%ld:", &msec)) + { + return ( -2); + } + + if (!mode) + { + Term_xtra(TERM_XTRA_DELAY, msec); + } + else + { + bool_ stop = FALSE; + + while (TRUE) + { + ch = inkey(); + + /* Stop */ + if (ch == ESCAPE) + { + stop = TRUE; + break; + } + /* Change mode */ + else if (ch == 't') + { + mode = FALSE; + break; + } + /* Change mode */ + else if (ch == ' ') + { + if (mode) continue; + mode = TRUE; + break; + } + /* Change speed */ + else if (ch == '+') + { + delay--; + if (delay < 0) delay = 0; + } + else if (ch == '-') + { + delay++; + if (delay > 5) delay = 5; + } + else if (ch == 'D') + { + do_cmd_html_dump(); + } + else break; + } + if (stop) break; + } + + /* Next */ + continue; + } + + /* Get color for the NEXT L line */ + if (buf[0] == 'E') + { + /* Find the colon before the name */ + s = strchr(buf + 2, ':'); + + /* Verify that colon */ + if (!s) return ( -2); + + /* Nuke the colon, advance to the name */ + *s++ = '\0'; + + /* Paranoia -- require a name */ + if (!*s) return ( -2); + + /* Get the index */ + y = atoi(buf + 2); + + /* Copy */ + for (int i = 0; i < 80; i++) + { + cbuf[i] = s[i]; + } + + /* Next... */ + continue; + } + + /* Print a line */ + if (buf[0] == 'L') + { + /* Find the colon before the name */ + s = strchr(buf + 2, ':'); + + /* Verify that colon */ + if (!s) return ( -2); + + /* Nuke the colon, advance to the name */ + *s++ = '\0'; + + /* Paranoia -- require a name */ + if (!*s) return ( -2); + + /* Get the index */ + y = atoi(buf + 2); + + for (x = 0; x < 80; x++) + { + Term_putch(x, y, color_char_to_attr(cbuf[x]), s[x]); + + /* Reinit to white */ + cbuf[x] = 'w'; + } + Term_redraw_section(0, y, 79, y); + + /* Next... */ + continue; + } + + /* Update 1 char */ + if (buf[0] == 'P') + { + int x, y, a, c; + + /* Scan for the values */ + if (4 != sscanf(buf + 2, "%d:%d:%d:%d", + &x, &y, &c, &a)) + { + a = 'w'; + if (3 != sscanf(buf + 2, "%d:%d:%d", + &x, &y, &c)) return ( -2); + } + + Term_putch(x, y, color_char_to_attr(cbuf[x]), c); + Term_redraw_section(x, y, x + 1, y + 1); + + /* Next... */ + continue; + } + } + + /* Load screen */ + Term_load(); + character_icky = FALSE; + + /* Close */ + my_fclose(fff); + + return (0); +} + + +/* + * Start the recording of a cmovie + */ +void do_record_cmovie(cptr cmovie) +{ + char buf[1024]; + int fd = -1; + int y; + + + /* Build the filename */ + path_build(buf, 1024, ANGBAND_DIR_CMOV, cmovie); + + /* File type is "TEXT" */ + FILE_TYPE(FILE_TYPE_TEXT); + + /* Check for existing file */ + fd = fd_open(buf, O_RDONLY); + + /* Existing file */ + if (fd >= 0) + { + char out_val[160]; + + /* Close the file */ + (void)fd_close(fd); + + /* Build query */ + (void)sprintf(out_val, "Replace existing file %s? ", cmovie); + + /* Ask */ + if (get_check(out_val)) fd = -1; + } + + /* Be sure */ + if (!get_check("Ready to record(Press ctrl+D to enter a textual note while recording)?")) return; + + /* Open the non-existing file */ + if (fd < 0) movfile = my_fopen(buf, "w"); + + /* Invalid file */ + if (movfile == NULL) + { + msg_format("Cmovie recording failed!"); + + return; + } + + /* First thing: Record clear screen then enable the recording */ + fprintf(movfile, "# Generated by %s\n", + get_version_string()); + fprintf(movfile, "C:\n"); + last_paused = 0; + do_movies = 1; + cmovie_init_second(); + + /* Mega Hack, get the screen */ + for (y = 0; y < Term->hgt; y++) + { + cmovie_record_line(y); + } +} + + +/* + * Stop the recording + */ +void do_stop_cmovie() +{ + if (do_movies == 1) + { + do_movies = 0; + my_fclose(movfile); + } +} + + +/* + * Start a cmovie + */ +void do_start_cmovie() +{ + char name[90], rname[94]; + + + /* Should never happen */ + if (do_movies == 1) return; + + /* Default */ + sprintf(name, "%s", player_base); + + if (get_string("Cmovie name: ", name, 80)) + { + if (name[0] && (name[0] != ' ')) + { + sprintf(rname, "%s.cmv", name); + + if (get_check("Record(y), Play(n)?")) do_record_cmovie(rname); + else do_play_cmovie(rname); + } + } +} + + +void cmovie_clean_line(int y, char *abuf, char *cbuf) +{ + const byte *ap = Term->scr->a[y]; + const char *cp = Term->scr->c[y]; + + byte a; + char c; + + int x; + int wid, hgt; + int screen_wid, screen_hgt; + + + /* Retrieve current screen size */ + Term_get_size(&wid, &hgt); + + /* Calculate the size of dungeon map area */ + screen_wid = wid - (COL_MAP + 1); + screen_hgt = hgt - (ROW_MAP + 1); + + /* For the time being, assume 80 column display XXX XXX XXX */ + for (x = 0; x < wid; x++) + { + /* Convert dungeon map into default attr/chars */ + if (!character_icky && + ((x - COL_MAP) >= 0) && + ((x - COL_MAP) < screen_wid) && + ((y - ROW_MAP) >= 0) && + ((y - ROW_MAP) < screen_hgt)) + { + /* Retrieve default attr/char */ + map_info_default(y + panel_row_prt, x + panel_col_prt, &a, &c); + + abuf[x] = conv_color[a & 0xf]; + + if (c == '\0') cbuf[x] = ' '; + else cbuf[x] = c; + } + + else + { + abuf[x] = conv_color[ap[x] & 0xf]; + cbuf[x] = cp[x]; + } + } + + /* Null-terminate the prepared strings */ + abuf[x] = '\0'; + cbuf[x] = '\0'; +} + + +/* + * Write a record of a screen row into a cmovie file + */ +void cmovie_record_line(int y) +{ + char abuf[256]; + char cbuf[256]; + + cmovie_clean_line(y, abuf, cbuf); + + /* Write a colour record */ + fprintf(movfile, "E:%d:%.80s\n", y, abuf); + + /* Write a char record */ + fprintf(movfile, "L:%d:%.80s\n", y, cbuf); +} + + +/* + * Record a "text box" + */ +void do_cmovie_insert() +{ + char buf[81] = ""; + + /* Dont record */ + do_movies = 2; + + while (get_string("Textbox(ESC to end): ", buf, 80)) + { + fprintf(movfile, "B:%s\nW:\n", buf); + buf[0] = '\0'; + } + + /* We reinit the time as to not count the time the user needed ot enter the text */ + cmovie_init_second(); + + /* Continue recording */ + do_movies = 1; +} diff --git a/src/corrupt.c b/src/corrupt.c deleted file mode 100644 index a4c579d4..00000000 --- a/src/corrupt.c +++ /dev/null @@ -1,973 +0,0 @@ -#include "angband.h" -#include - -/** - * Vampire corruption helpers - */ - -static void subrace_add_power(player_race_mod *rmp_ptr, int power) -{ - int i; - - for (i=0; i<4; i++) - { - if (rmp_ptr->powers[i] == -1) - { - rmp_ptr->powers[i] = power; - return; - } - } -} - -static void player_gain_vampire_teeth() -{ - player_race_mod *rmp_ptr = NULL; - - switch_subrace(SUBRACE_SAVE, TRUE); - - rmp_ptr = &race_mod_info[SUBRACE_SAVE]; - subrace_add_power(rmp_ptr, PWR_VAMPIRISM); - rmp_ptr->flags1 = rmp_ptr->flags1 - | PR1_VAMPIRE - | PR1_UNDEAD - | PR1_NO_SUBRACE_CHANGE; -} - -static void player_gain_vampire_strength() -{ - player_race_mod *rmp_ptr = &race_mod_info[SUBRACE_SAVE]; - /* Apply the bonuses/penalities */ - rmp_ptr->r_mhp = rmp_ptr->r_mhp + 1; - rmp_ptr->r_exp = rmp_ptr->r_exp + 100; - - rmp_ptr->r_adj[A_STR] = rmp_ptr->r_adj[A_STR] + 3; - rmp_ptr->r_adj[A_INT] = rmp_ptr->r_adj[A_INT] + 2; - rmp_ptr->r_adj[A_WIS] = rmp_ptr->r_adj[A_WIS] - 3; - rmp_ptr->r_adj[A_DEX] = rmp_ptr->r_adj[A_DEX] - 2; - rmp_ptr->r_adj[A_CON] = rmp_ptr->r_adj[A_CON] + 1; - rmp_ptr->r_adj[A_CHR] = rmp_ptr->r_adj[A_CHR] - 4; - - /* be reborn! */ - do_rebirth(); - cmsg_print(TERM_L_DARK, "You feel death slipping inside."); -} - -static void player_gain_vampire() -{ - player_race_mod *rmp_ptr = &race_mod_info[SUBRACE_SAVE]; - - /* Be a Vampire and be proud of it */ - cptr title = get_subrace_title(SUBRACE_SAVE); - if (streq(title, " ") || streq(title, "Vampire")) - { - title = "Vampire"; - rmp_ptr->place = FALSE; - set_subrace_title(SUBRACE_SAVE, title); - } - else - { - char buf[512]; - sprintf(buf, "Vampire %s", title); - set_subrace_title(SUBRACE_SAVE, buf); - } - - /* Bonus/and .. not bonus :) */ - rmp_ptr->flags1 = rmp_ptr->flags1 | PR1_HURT_LITE; - rmp_ptr->oflags2[2] = rmp_ptr->oflags2[2] - | TR2_RES_POIS - | TR2_RES_NETHER - | TR2_RES_COLD - | TR2_RES_DARK - | TR2_HOLD_LIFE; - rmp_ptr->oflags3[2] = rmp_ptr->oflags3[2] - | TR3_LITE1; -} - -/** - * Corruptions - */ -corruption_type corruptions[CORRUPTIONS_MAX] = -{ - /* - * BALROG corruptions - */ - - { /* 0 */ - { MODULE_TOME, MODULE_THEME, -1 }, - TERM_ORANGE, - NULL /* no group */, - "Balrog Aura", - "A corrupted wall of flames surrounds you.", - "The wall of corrupted flames abandons you.", - " Surrounds you with a fiery aura\n" - " But it can burn scrolls when you read them", - { -1 }, - { -1 }, - NULL, - -1, - }, - - { /* 1 */ - { MODULE_TOME, MODULE_THEME, -1 }, - TERM_ORANGE, - NULL /* no group */, - "Balrog Wings", - "Wings of shadow grow in your back.", - "The wings in your back fall apart.", - " Creates ugly, but working, wings allowing you to fly\n" - " But it reduces charisma by 4 and dexterity by 2", - { -1 }, - { -1 }, - NULL, - -1, - }, - - { /* 2 */ - { MODULE_TOME, MODULE_THEME, -1 }, - TERM_ORANGE, - NULL /* no group */, - "Balrog Strength", - "Your muscles get unnatural strength.", - "Your muscles get weaker again.", - " Provides 3 strength and 1 constitution\n" - " But it reduces charisma by 1 and dexterity by 3", - { -1 }, - { -1 }, - NULL, - -1, - }, - - { /* 3 */ - { MODULE_TOME, MODULE_THEME, -1 }, - TERM_YELLOW, - NULL /* no group */, - "Balrog Form", - "You feel the might of a Balrog inside you.", - "The presence of the Balrog seems to abandon you.", - " Allows you to turn into a Balrog at will\n" - " You need Balrog Wings, Balrog Aura and Balrog Strength to activate it", - { CORRUPT_BALROG_AURA, CORRUPT_BALROG_WINGS, CORRUPT_BALROG_STRENGTH }, - { -1 }, - NULL, - PWR_BALROG, - }, - - /* - * DEMON corruptions - */ - { /* 4 */ - { MODULE_TOME, MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Demon Spirit", - "Your spirit opens to corrupted thoughts.", - "Your spirit closes again to the corrupted thoughts.", - " Increases your intelligence by 1\n" - " But reduce your charisma by 2", - { -1 }, - { -1 }, - NULL, - -1, - }, - - { /* 5 */ - { MODULE_TOME, MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Demon Hide", - "Your skin grows into a thick hide.", - "Your skin returns to a natural state.", - " Increases your armour class by your level\n" - " Provides immunity to fire at level 40\n" - " But reduces speed by your level / 7", - { -1 }, - { -1 }, - NULL, - -1, - }, - - { /* 6 */ - { MODULE_TOME, MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Demon Breath", - "Your breath becomes mephitic.", - "Your breath is once again normal.", - " Provides fire breath\n" - " But gives a small chance to spoil potions when you quaff them", - { -1 }, - { -1 }, - NULL, - PWR_BR_FIRE, - }, - - { /* 7 */ - { MODULE_TOME, MODULE_THEME, -1 }, - TERM_L_RED, - NULL /* no group */, - "Demon Realm", - "You feel more attuned to the demon realm.", - "You lose your attunement to the demon realm.", - " Provides access to the demon school skill and the use of demonic equipment\n" - " You need Demon Spirit, Demon Hide and Demon Breath to activate it", - { CORRUPT_DEMON_SPIRIT, CORRUPT_DEMON_HIDE, CORRUPT_DEMON_BREATH }, - { -1 }, - NULL, - -1, - }, - - /* - * Teleportation corruptions - */ - - { /* 8 */ - { MODULE_TOME, MODULE_THEME, -1 }, - TERM_GREEN, - NULL /* no group */, - "Random teleportation", - "Space seems to fizzle around you.", - "Space solidify again around you.", - " Randomly teleports you around", - { -1 }, - { CORRUPT_ANTI_TELEPORT, -1 }, - NULL, - -1, - }, - - { /* 9 */ - { MODULE_TOME, MODULE_THEME, -1 }, - TERM_GREEN, - NULL /* no group */, - "Anti-teleportation", - "Space continuum freezes around you.", - "Space continuum can once more be altered around you.", - " Prevents all teleportations, be it of you or monsters", - { -1 }, - { CORRUPT_RANDOM_TELEPORT, -1 }, - NULL, - POWER_COR_SPACE_TIME, - }, - - /* - * Troll blood - */ - - { /* 10 */ - { MODULE_TOME, MODULE_THEME, -1 }, - TERM_GREEN, - NULL /* no group */, - "Troll Blood", - "Your blood thickens, you sense corruption in it.", - "Your blood returns to a normal state.", - " Troll blood flows in your veins, granting increased regeneration\n" - " It also enables you to feel the presence of other troll beings\n" - " But it will make your presence more noticeable and aggravating", - { -1 }, - { -1 }, - NULL, - -1, - }, - - /* - * The vampire corruption set - */ - - { /* 11 */ - { MODULE_TOME, MODULE_THEME, -1 }, - TERM_L_DARK, - "Vampire", - "Vampiric Teeth", - "You grow vampiric teeth!", - NULL, /* cannot lose */ - " Your teeth allow you to drain blood to feed yourself\n" - " However your stomach now only accepts blood.", - { -1 }, - { -1 }, - player_gain_vampire_teeth, - -1, - }, - - { /* 12 */ - { MODULE_TOME, MODULE_THEME, -1 }, - TERM_L_DARK, - "Vampire", - "Vampiric Strength", - "Your body seems more dead than alive.", - NULL, /* cannot lose */ - " Your body seems somewhat dead\n" - " In this near undead state it has improved strength, constitution and intelligence\n" - " But reduced dexterity, wisdom and charisma.", - { CORRUPT_VAMPIRE_TEETH, -1 }, - { -1 }, - player_gain_vampire_strength, - -1, - }, - - { /* 13 */ - { MODULE_TOME, MODULE_THEME, -1 }, - TERM_L_DARK, - "Vampire", - "Vampire", - "You die to be reborn in a Vampire form.", - NULL, /* cannot lose */ - " You are a Vampire. As such you resist cold, poison, darkness and nether.\n" - " Your life is sustained, but you cannot stand the light of the sun.", - { CORRUPT_VAMPIRE_STRENGTH, -1 }, - { -1 }, - player_gain_vampire, - -1, - }, - - /* - * Activatable corruptions (mutations) - */ - - { /* 14 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Ancalagon's Breath", - "You gain the ability to spit acid.", - "You lose the ability to spit acid.", - " Fires an acid ball.\n" - " Damage=level Radius 1+(level/30)\n" - " Level=9, Cost=9, Stat=DEX, Difficulty=15", - { -1 }, - { -1 }, - NULL, - PWR_SPIT_ACID, - }, - - { /* 15 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Smaug's Breath", - "You gain the ability to breathe fire.", - "You lose the ability to breathe fire.", - " Fires a fire ball.\n" - " Damage=2*level Radius 1+(level/20)\n" - " Level=20, Cost=10, Stat=CON, Difficulty=18", - { -1 }, - { -1 }, - NULL, - PWR_BR_FIRE, - }, - - { /* 16 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Glaurung's Gaze", - "Your eyes look mesmerizing...", - "Your eyes look uninteresting.", - " Tries to make a monster your pet.\n" - " Power=level\n" - " Level=12, Cost=12, Stat=CHR, Difficulty=18", - { -1 }, - { -1 }, - NULL, - PWR_HYPN_GAZE, - }, - - { /* 17 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Saruman's Power", - "You gain the ability to move objects telekinetically.", - "You lose the ability to move objects telekinetically.", - " Move an object in line of sight to you.\n" - " Max weight equal to (level) pounds\n" - " Level=9, Cost=9, Stat=WIS, Difficulty=14", - { -1 }, - { -1 }, - NULL, - PWR_TELEKINES, - }, - - { /* 18 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Teleport", - "You gain the power of teleportation at will.", - "You lose the power of teleportation at will.", - " Teleports the player at will.\n" - " Distance 10+4*level squares\n" - " Level=7, Cost=7, Stat=WIS, Difficulty=15", - { -1 }, - { -1 }, - NULL, - PWR_VTELEPORT, - }, - - { /* 19 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Glaurung's Spell", - "You gain the power of Mind Blast.", - "You lose the power of Mind Blast.", - " Fires a mind blasting bolt (psi damage).\n" - " Psi Damage (3+(level-1)/5)d3\n" - " Level=5, Cost=3, Stat=WIS, Difficulty=15", - { -1 }, - { -1 }, - NULL, - PWR_MIND_BLST, - }, - - { /* 20 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Vampiric Drain", - "You become vampiric.", - "You are no longer vampiric.", - " You can drain life from a foe like a vampire.\n" - " Drains (level+1d(level))*(level/10) hitpoints,\n" - " heals you and satiates you. Doesn't work on all monsters\n" - " Level=4, Cost=5, Stat=CON, Difficulty=9", - { -1 }, - { -1 }, - NULL, - PWR_VAMPIRISM, - }, - - { /* 21 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Carcharoth's Nose", - "You smell a metallic odour.", - "You no longer smell a metallic odour.", - " You can detect nearby precious metal (treasure).\n" - " Radius 25\n" - " Level=3, Cost=2, Stat=INT, Difficulty=12", - { -1 }, - { -1 }, - NULL, - PWR_SMELL_MET, - }, - - { /* 22 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Huan's Nose", - "You smell filthy monsters.", - "You no longer smell filthy monsters.", - " You can detect nearby monsters.\n" - " Radius 25\n" - " Level=5, Cost=4, Stat=INT, Difficulty=15", - { -1 }, - { -1 }, - NULL, - PWR_SMELL_MON, - }, - - { /* 23 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Blink", - "You gain the power of minor teleportation.", - "You lose the power of minor teleportation.", - " You can teleport yourself short distances (10 squares).\n" - " Level=3, Cost=3, Stat=WIS, Difficulty=12", - { -1 }, - { -1 }, - NULL, - PWR_BLINK, - }, - - { /* 24 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Eat Rock", - "The walls look delicious.", - "The walls look unappetizing.", - " You can consume solid rock with food benefit,\n" - " leaving an empty space behind.\n" - " Level=8, Cost=12, Stat=CON, Difficulty=18", - { -1 }, - { -1 }, - NULL, - PWR_EAT_ROCK, - }, - - { /* 25 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Swap Position", - "You feel like walking a mile in someone else's shoes.", - "You feel like staying in your own shoes.", - " You can switch locations with another being,\n" - " unless it resists teleportation.\n" - " Level=15, Cost=12, Stat=DEX, Difficulty=16", - { -1 }, - { -1 }, - NULL, - PWR_SWAP_POS, - }, - - { /* 26 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Shriek", - "Your vocal cords get much tougher.", - "Your vocal cords get much weaker.", - " Fires a sound ball and aggravates monsters.\n" - " Damage=level*4, Radius=8, centered on player\n" - " Level=4, Cost=4, Stat=CON, Difficulty=6", - { -1 }, - { -1 }, - NULL, - PWR_SHRIEK, - }, - - { /* 27 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Illuminate", - "You can light up rooms with your presence.", - "You can no longer light up rooms with your presence.", - " You can emit bright light that illuminates an area.\n" - " Damage=2d(level/2) Radius=(level/10)+1\n" - " Level=3, Cost=2, Stat=INT, Difficulty=10", - { -1 }, - { -1 }, - NULL, - PWR_ILLUMINE, - }, - - { /* 28 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Detect Curses", - "You can feel evil magics.", - "You can no longer feel evil magics.", - " You can feel the danger of evil magic.\n" - " It detects cursed items in the inventory\n" - " Level=7, Cost=14, Stat=WIS, Difficulty=14", - { -1 }, - { -1 }, - NULL, - PWR_DET_CURSE, - }, - - { /* 29 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Berserk", - "You feel a controlled rage.", - "You no longer feel a controlled rage.", - " You can drive yourself into a berserk frenzy.\n" - " It grants super-heroism. Duration=10+1d(level)\n" - " Level=8, Cost=8, Stat=STR, Difficulty=14", - { -1 }, - { -1 }, - NULL, - PWR_BERSERK, - }, - - { /* 30 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Midas touch", - "You gain the Midas touch.", - "You lose the Midas touch.", - " You can turn ordinary items to gold.\n" - " Turns a non-artifact object into 1/3 its value in gold\n" - " Level=10, Cost=5, Stat=INT, Difficulty=12", - { -1 }, - { -1 }, - NULL, - PWR_MIDAS_TCH, - }, - - { /* 31 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Grow Mold", - "You feel a sudden affinity for mold.", - "You feel a sudden dislike for mold.", - " You can cause mold to grow near you.\n" - " Summons up to 8 molds around the player\n" - " Level=1, Cost=6, Stat=CON, Difficulty=14", - { -1 }, - { -1 }, - NULL, - PWR_GROW_MOLD, - }, - - { /* 32 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Resist Elements", - "You feel like you can protect yourself.", - "You feel like you might be vulnerable.", - " You can harden yourself to the ravages of the elements.\n" - " Level-dependent chance of gaining resistances to the four \n" - " elements and poison. Duration=20 + d20\n" - " Level=10, Cost=12, Stat=CON, Difficulty=12", - { -1 }, - { -1 }, - NULL, - PWR_RESIST, - }, - - { /* 33 */ - { MODULE_THEME, -1 }, - TERM_RED, - NULL /* no group */, - "Earthquake", - "You gain the ability to wreck the dungeon.", - "You lose the ability to wreck the dungeon.", - " You can bring down the dungeon around your ears.\n" - " Radius=10, center on the player\n" - " Level=12, Cost=12, Stat=STR, Difficulty=16", - { -1 }, - { -1 }, - NULL, - PWR_EARTHQUAKE, - }, - -}; - -/** - * Initialize corruptions - */ -void init_corruptions() -{ - /* Nothing needed currently */ -} - -/* - * Corruptions - */ -bool_ player_has_corruption(int corruption_idx) -{ - if (corruption_idx < 0) - { - return FALSE; - } - - return (p_ptr->corruptions[corruption_idx]); -} - -static bool_ player_can_gain_corruption(int corruption_idx) -{ - cptr r_name = rp_ptr->title + rp_name; - bool_ allowed = TRUE; /* Allowed by default */ - - assert(corruption_idx >= 0); - - if (corruption_idx == CORRUPT_TROLL_BLOOD) - { - /* Ok trolls should not get this one. never. */ - if (streq(r_name, "Troll")) - { - allowed = FALSE; - } - } - - /* Theme module adds additional restrictions for Maiar */ - - if (game_module_idx == MODULE_THEME) - { - if (streq(r_name, "Maia")) - { - /* We use a whitelist of corruptions for Maiar */ - bool_ allow = FALSE; - if ((corruption_idx == CORRUPT_BALROG_AURA) || - (corruption_idx == CORRUPT_BALROG_WINGS) || - (corruption_idx == CORRUPT_BALROG_STRENGTH) || - (corruption_idx == CORRUPT_BALROG_FORM) || - (corruption_idx == CORRUPT_DEMON_BREATH)) - { - allow = TRUE; - }; - - /* Mix result into 'allowed' flag */ - allowed = allowed & allow; - } - } - - /* Result */ - return allowed; -} - -static bool_ player_allow_corruption(int corruption_idx) -{ - int i; - bool_ found = FALSE; - corruption_type *c_ptr = NULL; - - assert(corruption_idx < CORRUPTIONS_MAX); - c_ptr = &corruptions[corruption_idx]; - - /* Must be allowed by module */ - for (i = 0; c_ptr->modules[i] >= 0; i++) - { - if (c_ptr->modules[i] == game_module_idx) - { - found = TRUE; - } - } - - if (!found) - { - return FALSE; - } - - /* Vampire teeth is special */ - if (corruption_idx == CORRUPT_VAMPIRE_TEETH) - { - if (PRACE_FLAG(PR1_NO_SUBRACE_CHANGE)) - { - return TRUE; - } - else - { - return FALSE; - } - } - - return TRUE; -} - -static void player_set_corruption(int c, bool_ set) -{ - p_ptr->corruptions[c] = set; - p_ptr->redraw = p_ptr->redraw | PR_BASIC; - p_ptr->update = p_ptr->update | PU_BONUS | PU_TORCH | PU_BODY | PU_POWERS; - -} - -void player_gain_corruption(int corruption_idx) -{ - corruption_type *c_ptr = NULL; - assert(corruption_idx >= 0); - assert(corruption_idx < CORRUPTIONS_MAX); - c_ptr = &corruptions[corruption_idx]; - - /* Set the player's corruption flag */ - player_set_corruption(corruption_idx, TRUE); - - /* Invoke callback if necessary */ - if (c_ptr->gain_callback) - { - c_ptr->gain_callback(); - } -} - -static void player_lose_corruption(int corruption_idx) -{ - assert(corruption_idx >= 0); - assert(corruption_idx < CORRUPTIONS_MAX); - - player_set_corruption(corruption_idx, FALSE); - - /* Currently no corruptions need any special handling when lost */ -} - -/* - * Test if we have that corruption - * We must: - * 1) have it or be willing to get it - * 2) have all its dependancies - * 3) have none of its opposing corruptions - * 4) pass the possible tests - */ -static bool_ test_depend_corrupt(s16b corrupt_idx, bool_ can_gain) -{ - s16b i; - corruption_type *c_ptr = NULL; - - assert(corrupt_idx >= 0); - assert(corrupt_idx < CORRUPTIONS_MAX); - - c_ptr = &corruptions[corrupt_idx]; - - if (can_gain) - { - if (p_ptr->corruptions[corrupt_idx]) - { - return FALSE; - } - } else { - if (!p_ptr->corruptions[corrupt_idx]) - { - return FALSE; - } - } - - /* Go through all dependencies */ - for (i=0; c_ptr->depends[i] >= 0; i++) - { - if (!test_depend_corrupt(c_ptr->depends[i], FALSE)) - { - return FALSE; - } - } - - /* Go through all opposers */ - for (i=0; c_ptr->opposes[i] >= 0; i++) - { - if (test_depend_corrupt(c_ptr->opposes[i], FALSE)) - { - return FALSE; - } - } - - /* are we even allowed to get it? */ - return player_can_gain_corruption(corrupt_idx); -} - -void gain_random_corruption() -{ - s16b i, max; - s16b pos[CORRUPTIONS_MAX]; - - /* Get the list of all possible ones */ - max = 0; - for (i=0; i < CORRUPTIONS_MAX; i++) - { - if (test_depend_corrupt(i, TRUE) && - player_allow_corruption(i)) - { - pos[max] = i; - max = max + 1; - } - } - - /* Ok now get one of them */ - if (max > 0) - { - s16b ret = rand_int(max); - int c_idx = pos[ret]; - assert(c_idx < CORRUPTIONS_MAX); - - player_gain_corruption(c_idx); - cmsg_print(TERM_L_RED, corruptions[c_idx].get_text); - } -} - -static void remove_corruption(int c_idx) -{ - assert(c_idx >= 0 && c_idx < CORRUPTIONS_MAX); - assert(corruptions[c_idx].lose_text); - - player_lose_corruption(c_idx); - cmsg_print(TERM_L_RED, corruptions[c_idx].lose_text); -} - -void lose_corruption() -{ - s16b i, max; - s16b pos[CORRUPTIONS_MAX]; - - /* Get the list of all possible ones */ - max = 0; - for (i = 0; i < CORRUPTIONS_MAX; i++) - { - bool_ is_removable = (corruptions[i].lose_text != NULL); - if (test_depend_corrupt(i, FALSE) && is_removable) - { - pos[max] = i; - max = max + 1; - } - } - - /* Ok now get one of them */ - if (max > 0) - { - s16b ret = rand_int(max); - int c_idx = pos[ret]; - - /* Remove the corruption */ - remove_corruption(c_idx); - - /* Ok now lets see if it broke some dependencies */ - for (i = 0; i < max - 1; i++) - { - if (p_ptr->corruptions[pos[i]] != test_depend_corrupt(pos[i], FALSE)) - { - remove_corruption(pos[i]); - } - } - } -} - - -/* - * Dump the corruption list - */ -void dump_corruptions(FILE *fff, bool_ color, bool_ header) -{ - int i; - - assert(fff != NULL); - - for (i = 0; i < CORRUPTIONS_MAX; i++) - { - corruption_type *c_ptr = &corruptions[i]; - - if (header) - { - fprintf(fff, "\n Corruption list:\n"); - header = FALSE; - } - - if (p_ptr->corruptions[i]) - { - byte c = c_ptr->color; - - if (color) - { - fprintf(fff, "#####%c%s:\n", conv_color[c], c_ptr->name); - } - else - { - fprintf(fff, "%s:\n", c_ptr->name); - } - - fprintf(fff, "%s\n", c_ptr->desc); - } - } -} - -/* - * Get the power granted by a corruption. Returns -1 - * if the given corruption does not grant a power. - */ -s16b get_corruption_power(int corruption_idx) -{ - corruption_type *c_ptr = NULL; - - assert(corruption_idx >= 0); - assert(corruption_idx < CORRUPTIONS_MAX); - - c_ptr = &corruptions[corruption_idx]; - - if ((c_ptr->power >= 0) && (c_ptr->power < POWER_MAX)) - { - return c_ptr->power; - } - else - { - assert(c_ptr->power == -1); /* Sanity check: Should always be the case. */ - return -1; - } -} diff --git a/src/corrupt.cc b/src/corrupt.cc new file mode 100644 index 00000000..a4c579d4 --- /dev/null +++ b/src/corrupt.cc @@ -0,0 +1,973 @@ +#include "angband.h" +#include + +/** + * Vampire corruption helpers + */ + +static void subrace_add_power(player_race_mod *rmp_ptr, int power) +{ + int i; + + for (i=0; i<4; i++) + { + if (rmp_ptr->powers[i] == -1) + { + rmp_ptr->powers[i] = power; + return; + } + } +} + +static void player_gain_vampire_teeth() +{ + player_race_mod *rmp_ptr = NULL; + + switch_subrace(SUBRACE_SAVE, TRUE); + + rmp_ptr = &race_mod_info[SUBRACE_SAVE]; + subrace_add_power(rmp_ptr, PWR_VAMPIRISM); + rmp_ptr->flags1 = rmp_ptr->flags1 + | PR1_VAMPIRE + | PR1_UNDEAD + | PR1_NO_SUBRACE_CHANGE; +} + +static void player_gain_vampire_strength() +{ + player_race_mod *rmp_ptr = &race_mod_info[SUBRACE_SAVE]; + /* Apply the bonuses/penalities */ + rmp_ptr->r_mhp = rmp_ptr->r_mhp + 1; + rmp_ptr->r_exp = rmp_ptr->r_exp + 100; + + rmp_ptr->r_adj[A_STR] = rmp_ptr->r_adj[A_STR] + 3; + rmp_ptr->r_adj[A_INT] = rmp_ptr->r_adj[A_INT] + 2; + rmp_ptr->r_adj[A_WIS] = rmp_ptr->r_adj[A_WIS] - 3; + rmp_ptr->r_adj[A_DEX] = rmp_ptr->r_adj[A_DEX] - 2; + rmp_ptr->r_adj[A_CON] = rmp_ptr->r_adj[A_CON] + 1; + rmp_ptr->r_adj[A_CHR] = rmp_ptr->r_adj[A_CHR] - 4; + + /* be reborn! */ + do_rebirth(); + cmsg_print(TERM_L_DARK, "You feel death slipping inside."); +} + +static void player_gain_vampire() +{ + player_race_mod *rmp_ptr = &race_mod_info[SUBRACE_SAVE]; + + /* Be a Vampire and be proud of it */ + cptr title = get_subrace_title(SUBRACE_SAVE); + if (streq(title, " ") || streq(title, "Vampire")) + { + title = "Vampire"; + rmp_ptr->place = FALSE; + set_subrace_title(SUBRACE_SAVE, title); + } + else + { + char buf[512]; + sprintf(buf, "Vampire %s", title); + set_subrace_title(SUBRACE_SAVE, buf); + } + + /* Bonus/and .. not bonus :) */ + rmp_ptr->flags1 = rmp_ptr->flags1 | PR1_HURT_LITE; + rmp_ptr->oflags2[2] = rmp_ptr->oflags2[2] + | TR2_RES_POIS + | TR2_RES_NETHER + | TR2_RES_COLD + | TR2_RES_DARK + | TR2_HOLD_LIFE; + rmp_ptr->oflags3[2] = rmp_ptr->oflags3[2] + | TR3_LITE1; +} + +/** + * Corruptions + */ +corruption_type corruptions[CORRUPTIONS_MAX] = +{ + /* + * BALROG corruptions + */ + + { /* 0 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_ORANGE, + NULL /* no group */, + "Balrog Aura", + "A corrupted wall of flames surrounds you.", + "The wall of corrupted flames abandons you.", + " Surrounds you with a fiery aura\n" + " But it can burn scrolls when you read them", + { -1 }, + { -1 }, + NULL, + -1, + }, + + { /* 1 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_ORANGE, + NULL /* no group */, + "Balrog Wings", + "Wings of shadow grow in your back.", + "The wings in your back fall apart.", + " Creates ugly, but working, wings allowing you to fly\n" + " But it reduces charisma by 4 and dexterity by 2", + { -1 }, + { -1 }, + NULL, + -1, + }, + + { /* 2 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_ORANGE, + NULL /* no group */, + "Balrog Strength", + "Your muscles get unnatural strength.", + "Your muscles get weaker again.", + " Provides 3 strength and 1 constitution\n" + " But it reduces charisma by 1 and dexterity by 3", + { -1 }, + { -1 }, + NULL, + -1, + }, + + { /* 3 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_YELLOW, + NULL /* no group */, + "Balrog Form", + "You feel the might of a Balrog inside you.", + "The presence of the Balrog seems to abandon you.", + " Allows you to turn into a Balrog at will\n" + " You need Balrog Wings, Balrog Aura and Balrog Strength to activate it", + { CORRUPT_BALROG_AURA, CORRUPT_BALROG_WINGS, CORRUPT_BALROG_STRENGTH }, + { -1 }, + NULL, + PWR_BALROG, + }, + + /* + * DEMON corruptions + */ + { /* 4 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Demon Spirit", + "Your spirit opens to corrupted thoughts.", + "Your spirit closes again to the corrupted thoughts.", + " Increases your intelligence by 1\n" + " But reduce your charisma by 2", + { -1 }, + { -1 }, + NULL, + -1, + }, + + { /* 5 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Demon Hide", + "Your skin grows into a thick hide.", + "Your skin returns to a natural state.", + " Increases your armour class by your level\n" + " Provides immunity to fire at level 40\n" + " But reduces speed by your level / 7", + { -1 }, + { -1 }, + NULL, + -1, + }, + + { /* 6 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Demon Breath", + "Your breath becomes mephitic.", + "Your breath is once again normal.", + " Provides fire breath\n" + " But gives a small chance to spoil potions when you quaff them", + { -1 }, + { -1 }, + NULL, + PWR_BR_FIRE, + }, + + { /* 7 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_L_RED, + NULL /* no group */, + "Demon Realm", + "You feel more attuned to the demon realm.", + "You lose your attunement to the demon realm.", + " Provides access to the demon school skill and the use of demonic equipment\n" + " You need Demon Spirit, Demon Hide and Demon Breath to activate it", + { CORRUPT_DEMON_SPIRIT, CORRUPT_DEMON_HIDE, CORRUPT_DEMON_BREATH }, + { -1 }, + NULL, + -1, + }, + + /* + * Teleportation corruptions + */ + + { /* 8 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_GREEN, + NULL /* no group */, + "Random teleportation", + "Space seems to fizzle around you.", + "Space solidify again around you.", + " Randomly teleports you around", + { -1 }, + { CORRUPT_ANTI_TELEPORT, -1 }, + NULL, + -1, + }, + + { /* 9 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_GREEN, + NULL /* no group */, + "Anti-teleportation", + "Space continuum freezes around you.", + "Space continuum can once more be altered around you.", + " Prevents all teleportations, be it of you or monsters", + { -1 }, + { CORRUPT_RANDOM_TELEPORT, -1 }, + NULL, + POWER_COR_SPACE_TIME, + }, + + /* + * Troll blood + */ + + { /* 10 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_GREEN, + NULL /* no group */, + "Troll Blood", + "Your blood thickens, you sense corruption in it.", + "Your blood returns to a normal state.", + " Troll blood flows in your veins, granting increased regeneration\n" + " It also enables you to feel the presence of other troll beings\n" + " But it will make your presence more noticeable and aggravating", + { -1 }, + { -1 }, + NULL, + -1, + }, + + /* + * The vampire corruption set + */ + + { /* 11 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_L_DARK, + "Vampire", + "Vampiric Teeth", + "You grow vampiric teeth!", + NULL, /* cannot lose */ + " Your teeth allow you to drain blood to feed yourself\n" + " However your stomach now only accepts blood.", + { -1 }, + { -1 }, + player_gain_vampire_teeth, + -1, + }, + + { /* 12 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_L_DARK, + "Vampire", + "Vampiric Strength", + "Your body seems more dead than alive.", + NULL, /* cannot lose */ + " Your body seems somewhat dead\n" + " In this near undead state it has improved strength, constitution and intelligence\n" + " But reduced dexterity, wisdom and charisma.", + { CORRUPT_VAMPIRE_TEETH, -1 }, + { -1 }, + player_gain_vampire_strength, + -1, + }, + + { /* 13 */ + { MODULE_TOME, MODULE_THEME, -1 }, + TERM_L_DARK, + "Vampire", + "Vampire", + "You die to be reborn in a Vampire form.", + NULL, /* cannot lose */ + " You are a Vampire. As such you resist cold, poison, darkness and nether.\n" + " Your life is sustained, but you cannot stand the light of the sun.", + { CORRUPT_VAMPIRE_STRENGTH, -1 }, + { -1 }, + player_gain_vampire, + -1, + }, + + /* + * Activatable corruptions (mutations) + */ + + { /* 14 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Ancalagon's Breath", + "You gain the ability to spit acid.", + "You lose the ability to spit acid.", + " Fires an acid ball.\n" + " Damage=level Radius 1+(level/30)\n" + " Level=9, Cost=9, Stat=DEX, Difficulty=15", + { -1 }, + { -1 }, + NULL, + PWR_SPIT_ACID, + }, + + { /* 15 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Smaug's Breath", + "You gain the ability to breathe fire.", + "You lose the ability to breathe fire.", + " Fires a fire ball.\n" + " Damage=2*level Radius 1+(level/20)\n" + " Level=20, Cost=10, Stat=CON, Difficulty=18", + { -1 }, + { -1 }, + NULL, + PWR_BR_FIRE, + }, + + { /* 16 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Glaurung's Gaze", + "Your eyes look mesmerizing...", + "Your eyes look uninteresting.", + " Tries to make a monster your pet.\n" + " Power=level\n" + " Level=12, Cost=12, Stat=CHR, Difficulty=18", + { -1 }, + { -1 }, + NULL, + PWR_HYPN_GAZE, + }, + + { /* 17 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Saruman's Power", + "You gain the ability to move objects telekinetically.", + "You lose the ability to move objects telekinetically.", + " Move an object in line of sight to you.\n" + " Max weight equal to (level) pounds\n" + " Level=9, Cost=9, Stat=WIS, Difficulty=14", + { -1 }, + { -1 }, + NULL, + PWR_TELEKINES, + }, + + { /* 18 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Teleport", + "You gain the power of teleportation at will.", + "You lose the power of teleportation at will.", + " Teleports the player at will.\n" + " Distance 10+4*level squares\n" + " Level=7, Cost=7, Stat=WIS, Difficulty=15", + { -1 }, + { -1 }, + NULL, + PWR_VTELEPORT, + }, + + { /* 19 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Glaurung's Spell", + "You gain the power of Mind Blast.", + "You lose the power of Mind Blast.", + " Fires a mind blasting bolt (psi damage).\n" + " Psi Damage (3+(level-1)/5)d3\n" + " Level=5, Cost=3, Stat=WIS, Difficulty=15", + { -1 }, + { -1 }, + NULL, + PWR_MIND_BLST, + }, + + { /* 20 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Vampiric Drain", + "You become vampiric.", + "You are no longer vampiric.", + " You can drain life from a foe like a vampire.\n" + " Drains (level+1d(level))*(level/10) hitpoints,\n" + " heals you and satiates you. Doesn't work on all monsters\n" + " Level=4, Cost=5, Stat=CON, Difficulty=9", + { -1 }, + { -1 }, + NULL, + PWR_VAMPIRISM, + }, + + { /* 21 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Carcharoth's Nose", + "You smell a metallic odour.", + "You no longer smell a metallic odour.", + " You can detect nearby precious metal (treasure).\n" + " Radius 25\n" + " Level=3, Cost=2, Stat=INT, Difficulty=12", + { -1 }, + { -1 }, + NULL, + PWR_SMELL_MET, + }, + + { /* 22 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Huan's Nose", + "You smell filthy monsters.", + "You no longer smell filthy monsters.", + " You can detect nearby monsters.\n" + " Radius 25\n" + " Level=5, Cost=4, Stat=INT, Difficulty=15", + { -1 }, + { -1 }, + NULL, + PWR_SMELL_MON, + }, + + { /* 23 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Blink", + "You gain the power of minor teleportation.", + "You lose the power of minor teleportation.", + " You can teleport yourself short distances (10 squares).\n" + " Level=3, Cost=3, Stat=WIS, Difficulty=12", + { -1 }, + { -1 }, + NULL, + PWR_BLINK, + }, + + { /* 24 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Eat Rock", + "The walls look delicious.", + "The walls look unappetizing.", + " You can consume solid rock with food benefit,\n" + " leaving an empty space behind.\n" + " Level=8, Cost=12, Stat=CON, Difficulty=18", + { -1 }, + { -1 }, + NULL, + PWR_EAT_ROCK, + }, + + { /* 25 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Swap Position", + "You feel like walking a mile in someone else's shoes.", + "You feel like staying in your own shoes.", + " You can switch locations with another being,\n" + " unless it resists teleportation.\n" + " Level=15, Cost=12, Stat=DEX, Difficulty=16", + { -1 }, + { -1 }, + NULL, + PWR_SWAP_POS, + }, + + { /* 26 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Shriek", + "Your vocal cords get much tougher.", + "Your vocal cords get much weaker.", + " Fires a sound ball and aggravates monsters.\n" + " Damage=level*4, Radius=8, centered on player\n" + " Level=4, Cost=4, Stat=CON, Difficulty=6", + { -1 }, + { -1 }, + NULL, + PWR_SHRIEK, + }, + + { /* 27 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Illuminate", + "You can light up rooms with your presence.", + "You can no longer light up rooms with your presence.", + " You can emit bright light that illuminates an area.\n" + " Damage=2d(level/2) Radius=(level/10)+1\n" + " Level=3, Cost=2, Stat=INT, Difficulty=10", + { -1 }, + { -1 }, + NULL, + PWR_ILLUMINE, + }, + + { /* 28 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Detect Curses", + "You can feel evil magics.", + "You can no longer feel evil magics.", + " You can feel the danger of evil magic.\n" + " It detects cursed items in the inventory\n" + " Level=7, Cost=14, Stat=WIS, Difficulty=14", + { -1 }, + { -1 }, + NULL, + PWR_DET_CURSE, + }, + + { /* 29 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Berserk", + "You feel a controlled rage.", + "You no longer feel a controlled rage.", + " You can drive yourself into a berserk frenzy.\n" + " It grants super-heroism. Duration=10+1d(level)\n" + " Level=8, Cost=8, Stat=STR, Difficulty=14", + { -1 }, + { -1 }, + NULL, + PWR_BERSERK, + }, + + { /* 30 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Midas touch", + "You gain the Midas touch.", + "You lose the Midas touch.", + " You can turn ordinary items to gold.\n" + " Turns a non-artifact object into 1/3 its value in gold\n" + " Level=10, Cost=5, Stat=INT, Difficulty=12", + { -1 }, + { -1 }, + NULL, + PWR_MIDAS_TCH, + }, + + { /* 31 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Grow Mold", + "You feel a sudden affinity for mold.", + "You feel a sudden dislike for mold.", + " You can cause mold to grow near you.\n" + " Summons up to 8 molds around the player\n" + " Level=1, Cost=6, Stat=CON, Difficulty=14", + { -1 }, + { -1 }, + NULL, + PWR_GROW_MOLD, + }, + + { /* 32 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Resist Elements", + "You feel like you can protect yourself.", + "You feel like you might be vulnerable.", + " You can harden yourself to the ravages of the elements.\n" + " Level-dependent chance of gaining resistances to the four \n" + " elements and poison. Duration=20 + d20\n" + " Level=10, Cost=12, Stat=CON, Difficulty=12", + { -1 }, + { -1 }, + NULL, + PWR_RESIST, + }, + + { /* 33 */ + { MODULE_THEME, -1 }, + TERM_RED, + NULL /* no group */, + "Earthquake", + "You gain the ability to wreck the dungeon.", + "You lose the ability to wreck the dungeon.", + " You can bring down the dungeon around your ears.\n" + " Radius=10, center on the player\n" + " Level=12, Cost=12, Stat=STR, Difficulty=16", + { -1 }, + { -1 }, + NULL, + PWR_EARTHQUAKE, + }, + +}; + +/** + * Initialize corruptions + */ +void init_corruptions() +{ + /* Nothing needed currently */ +} + +/* + * Corruptions + */ +bool_ player_has_corruption(int corruption_idx) +{ + if (corruption_idx < 0) + { + return FALSE; + } + + return (p_ptr->corruptions[corruption_idx]); +} + +static bool_ player_can_gain_corruption(int corruption_idx) +{ + cptr r_name = rp_ptr->title + rp_name; + bool_ allowed = TRUE; /* Allowed by default */ + + assert(corruption_idx >= 0); + + if (corruption_idx == CORRUPT_TROLL_BLOOD) + { + /* Ok trolls should not get this one. never. */ + if (streq(r_name, "Troll")) + { + allowed = FALSE; + } + } + + /* Theme module adds additional restrictions for Maiar */ + + if (game_module_idx == MODULE_THEME) + { + if (streq(r_name, "Maia")) + { + /* We use a whitelist of corruptions for Maiar */ + bool_ allow = FALSE; + if ((corruption_idx == CORRUPT_BALROG_AURA) || + (corruption_idx == CORRUPT_BALROG_WINGS) || + (corruption_idx == CORRUPT_BALROG_STRENGTH) || + (corruption_idx == CORRUPT_BALROG_FORM) || + (corruption_idx == CORRUPT_DEMON_BREATH)) + { + allow = TRUE; + }; + + /* Mix result into 'allowed' flag */ + allowed = allowed & allow; + } + } + + /* Result */ + return allowed; +} + +static bool_ player_allow_corruption(int corruption_idx) +{ + int i; + bool_ found = FALSE; + corruption_type *c_ptr = NULL; + + assert(corruption_idx < CORRUPTIONS_MAX); + c_ptr = &corruptions[corruption_idx]; + + /* Must be allowed by module */ + for (i = 0; c_ptr->modules[i] >= 0; i++) + { + if (c_ptr->modules[i] == game_module_idx) + { + found = TRUE; + } + } + + if (!found) + { + return FALSE; + } + + /* Vampire teeth is special */ + if (corruption_idx == CORRUPT_VAMPIRE_TEETH) + { + if (PRACE_FLAG(PR1_NO_SUBRACE_CHANGE)) + { + return TRUE; + } + else + { + return FALSE; + } + } + + return TRUE; +} + +static void player_set_corruption(int c, bool_ set) +{ + p_ptr->corruptions[c] = set; + p_ptr->redraw = p_ptr->redraw | PR_BASIC; + p_ptr->update = p_ptr->update | PU_BONUS | PU_TORCH | PU_BODY | PU_POWERS; + +} + +void player_gain_corruption(int corruption_idx) +{ + corruption_type *c_ptr = NULL; + assert(corruption_idx >= 0); + assert(corruption_idx < CORRUPTIONS_MAX); + c_ptr = &corruptions[corruption_idx]; + + /* Set the player's corruption flag */ + player_set_corruption(corruption_idx, TRUE); + + /* Invoke callback if necessary */ + if (c_ptr->gain_callback) + { + c_ptr->gain_callback(); + } +} + +static void player_lose_corruption(int corruption_idx) +{ + assert(corruption_idx >= 0); + assert(corruption_idx < CORRUPTIONS_MAX); + + player_set_corruption(corruption_idx, FALSE); + + /* Currently no corruptions need any special handling when lost */ +} + +/* + * Test if we have that corruption + * We must: + * 1) have it or be willing to get it + * 2) have all its dependancies + * 3) have none of its opposing corruptions + * 4) pass the possible tests + */ +static bool_ test_depend_corrupt(s16b corrupt_idx, bool_ can_gain) +{ + s16b i; + corruption_type *c_ptr = NULL; + + assert(corrupt_idx >= 0); + assert(corrupt_idx < CORRUPTIONS_MAX); + + c_ptr = &corruptions[corrupt_idx]; + + if (can_gain) + { + if (p_ptr->corruptions[corrupt_idx]) + { + return FALSE; + } + } else { + if (!p_ptr->corruptions[corrupt_idx]) + { + return FALSE; + } + } + + /* Go through all dependencies */ + for (i=0; c_ptr->depends[i] >= 0; i++) + { + if (!test_depend_corrupt(c_ptr->depends[i], FALSE)) + { + return FALSE; + } + } + + /* Go through all opposers */ + for (i=0; c_ptr->opposes[i] >= 0; i++) + { + if (test_depend_corrupt(c_ptr->opposes[i], FALSE)) + { + return FALSE; + } + } + + /* are we even allowed to get it? */ + return player_can_gain_corruption(corrupt_idx); +} + +void gain_random_corruption() +{ + s16b i, max; + s16b pos[CORRUPTIONS_MAX]; + + /* Get the list of all possible ones */ + max = 0; + for (i=0; i < CORRUPTIONS_MAX; i++) + { + if (test_depend_corrupt(i, TRUE) && + player_allow_corruption(i)) + { + pos[max] = i; + max = max + 1; + } + } + + /* Ok now get one of them */ + if (max > 0) + { + s16b ret = rand_int(max); + int c_idx = pos[ret]; + assert(c_idx < CORRUPTIONS_MAX); + + player_gain_corruption(c_idx); + cmsg_print(TERM_L_RED, corruptions[c_idx].get_text); + } +} + +static void remove_corruption(int c_idx) +{ + assert(c_idx >= 0 && c_idx < CORRUPTIONS_MAX); + assert(corruptions[c_idx].lose_text); + + player_lose_corruption(c_idx); + cmsg_print(TERM_L_RED, corruptions[c_idx].lose_text); +} + +void lose_corruption() +{ + s16b i, max; + s16b pos[CORRUPTIONS_MAX]; + + /* Get the list of all possible ones */ + max = 0; + for (i = 0; i < CORRUPTIONS_MAX; i++) + { + bool_ is_removable = (corruptions[i].lose_text != NULL); + if (test_depend_corrupt(i, FALSE) && is_removable) + { + pos[max] = i; + max = max + 1; + } + } + + /* Ok now get one of them */ + if (max > 0) + { + s16b ret = rand_int(max); + int c_idx = pos[ret]; + + /* Remove the corruption */ + remove_corruption(c_idx); + + /* Ok now lets see if it broke some dependencies */ + for (i = 0; i < max - 1; i++) + { + if (p_ptr->corruptions[pos[i]] != test_depend_corrupt(pos[i], FALSE)) + { + remove_corruption(pos[i]); + } + } + } +} + + +/* + * Dump the corruption list + */ +void dump_corruptions(FILE *fff, bool_ color, bool_ header) +{ + int i; + + assert(fff != NULL); + + for (i = 0; i < CORRUPTIONS_MAX; i++) + { + corruption_type *c_ptr = &corruptions[i]; + + if (header) + { + fprintf(fff, "\n Corruption list:\n"); + header = FALSE; + } + + if (p_ptr->corruptions[i]) + { + byte c = c_ptr->color; + + if (color) + { + fprintf(fff, "#####%c%s:\n", conv_color[c], c_ptr->name); + } + else + { + fprintf(fff, "%s:\n", c_ptr->name); + } + + fprintf(fff, "%s\n", c_ptr->desc); + } + } +} + +/* + * Get the power granted by a corruption. Returns -1 + * if the given corruption does not grant a power. + */ +s16b get_corruption_power(int corruption_idx) +{ + corruption_type *c_ptr = NULL; + + assert(corruption_idx >= 0); + assert(corruption_idx < CORRUPTIONS_MAX); + + c_ptr = &corruptions[corruption_idx]; + + if ((c_ptr->power >= 0) && (c_ptr->power < POWER_MAX)) + { + return c_ptr->power; + } + else + { + assert(c_ptr->power == -1); /* Sanity check: Should always be the case. */ + return -1; + } +} diff --git a/src/device_allocation.c b/src/device_allocation.c deleted file mode 100644 index e64f0401..00000000 --- a/src/device_allocation.c +++ /dev/null @@ -1,26 +0,0 @@ -#include "device_allocation.h" - -int compare_device_allocation(device_allocation *a, device_allocation *b) -{ - return SGLIB_NUMERIC_COMPARATOR(a->tval, b->tval); -} - -SGLIB_DEFINE_LIST_FUNCTIONS(device_allocation, compare_device_allocation, next); - -void device_allocation_init(device_allocation *device_allocation, byte tval) -{ - assert(device_allocation != NULL); - - device_allocation->tval = tval; - device_allocation->rarity = 0; - range_init(&device_allocation->base_level, 0, 0); - range_init(&device_allocation->max_level, 0, 0); - device_allocation->next = NULL; -} - -device_allocation *device_allocation_new(byte tval) -{ - device_allocation *d = malloc(sizeof(device_allocation)); - device_allocation_init(d, tval); - return d; -} diff --git a/src/device_allocation.cc b/src/device_allocation.cc new file mode 100644 index 00000000..f97de2ec --- /dev/null +++ b/src/device_allocation.cc @@ -0,0 +1,26 @@ +#include "device_allocation.h" + +int compare_device_allocation(device_allocation *a, device_allocation *b) +{ + return SGLIB_NUMERIC_COMPARATOR(a->tval, b->tval); +} + +SGLIB_DEFINE_LIST_FUNCTIONS(device_allocation, compare_device_allocation, next); + +void device_allocation_init(device_allocation *device_allocation, byte tval) +{ + assert(device_allocation != NULL); + + device_allocation->tval = tval; + device_allocation->rarity = 0; + range_init(&device_allocation->base_level, 0, 0); + range_init(&device_allocation->max_level, 0, 0); + device_allocation->next = NULL; +} + +device_allocation *device_allocation_new(byte tval) +{ + device_allocation *d = new device_allocation; + device_allocation_init(d, tval); + return d; +} diff --git a/src/dice.c b/src/dice.c deleted file mode 100644 index ea9b7533..00000000 --- a/src/dice.c +++ /dev/null @@ -1,94 +0,0 @@ -#include "dice.h" - -void dice_init(dice_type *dice, long base, long num, long sides) -{ - assert(dice != NULL); - - dice->base = base; - dice->num = num; - dice->sides = sides; -} - -bool_ dice_parse(dice_type *dice, cptr s) -{ - long base, num, sides; - - if (sscanf(s, "%ld+%ldd%ld", &base, &num, &sides) == 3) - { - dice_init(dice, base, num, sides); - return TRUE; - } - - if (sscanf(s, "%ld+d%ld", &base, &sides) == 2) - { - dice_init(dice, base, 1, sides); - return TRUE; - } - - if (sscanf(s, "d%ld", &sides) == 1) - { - dice_init(dice, 0, 1, sides); - return TRUE; - } - - if (sscanf(s, "%ldd%ld", &num, &sides) == 2) - { - dice_init(dice, 0, num, sides); - return TRUE; - } - - if (sscanf(s, "%ld", &base) == 1) - { - dice_init(dice, base, 0, 0); - return TRUE; - } - - return FALSE; -} - -void dice_parse_checked(dice_type *dice, cptr s) -{ - bool_ result = dice_parse(dice, s); - if (!result) - { - abort(); - } -} - -long dice_roll(dice_type *dice) -{ - assert(dice != NULL); - return dice->base + damroll(dice->num, dice->sides); -} - -void dice_print(dice_type *dice, char *output) -{ - char buf[16]; - - output[0] = '\0'; - - if (dice->base > 0) - { - sprintf(buf, "%ld", dice->base); - strcat(output, buf); - } - - if ((dice->num > 0) || (dice->sides > 0)) - { - if (dice->base > 0) - { - strcat(output, "+"); - } - - if (dice->num > 1) - { - sprintf(buf, "%ld", dice->num); - strcat(output, buf); - } - - strcat(output, "d"); - - sprintf(buf, "%ld", dice->sides); - strcat(output, buf); - } -} diff --git a/src/dice.cc b/src/dice.cc new file mode 100644 index 00000000..ea9b7533 --- /dev/null +++ b/src/dice.cc @@ -0,0 +1,94 @@ +#include "dice.h" + +void dice_init(dice_type *dice, long base, long num, long sides) +{ + assert(dice != NULL); + + dice->base = base; + dice->num = num; + dice->sides = sides; +} + +bool_ dice_parse(dice_type *dice, cptr s) +{ + long base, num, sides; + + if (sscanf(s, "%ld+%ldd%ld", &base, &num, &sides) == 3) + { + dice_init(dice, base, num, sides); + return TRUE; + } + + if (sscanf(s, "%ld+d%ld", &base, &sides) == 2) + { + dice_init(dice, base, 1, sides); + return TRUE; + } + + if (sscanf(s, "d%ld", &sides) == 1) + { + dice_init(dice, 0, 1, sides); + return TRUE; + } + + if (sscanf(s, "%ldd%ld", &num, &sides) == 2) + { + dice_init(dice, 0, num, sides); + return TRUE; + } + + if (sscanf(s, "%ld", &base) == 1) + { + dice_init(dice, base, 0, 0); + return TRUE; + } + + return FALSE; +} + +void dice_parse_checked(dice_type *dice, cptr s) +{ + bool_ result = dice_parse(dice, s); + if (!result) + { + abort(); + } +} + +long dice_roll(dice_type *dice) +{ + assert(dice != NULL); + return dice->base + damroll(dice->num, dice->sides); +} + +void dice_print(dice_type *dice, char *output) +{ + char buf[16]; + + output[0] = '\0'; + + if (dice->base > 0) + { + sprintf(buf, "%ld", dice->base); + strcat(output, buf); + } + + if ((dice->num > 0) || (dice->sides > 0)) + { + if (dice->base > 0) + { + strcat(output, "+"); + } + + if (dice->num > 1) + { + sprintf(buf, "%ld", dice->num); + strcat(output, buf); + } + + strcat(output, "d"); + + sprintf(buf, "%ld", dice->sides); + strcat(output, buf); + } +} diff --git a/src/dungeon.c b/src/dungeon.c deleted file mode 100644 index df3b41aa..00000000 --- a/src/dungeon.c +++ /dev/null @@ -1,5849 +0,0 @@ -/* File: dungeon.c */ - -/* Purpose: Angband game engine */ - -/* - * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke - * - * This software may be copied and distributed for educational, research, and - * not for profit purposes provided that this copyright and statement are - * included in all such copies. - */ - -#include "angband.h" - -#include - -#include "quark.h" -#include "hooks.h" -#include "spell_type.h" - -#define TY_CURSE_CHANCE 100 -#define DG_CURSE_CHANCE 50 -#define AUTO_CURSE_CHANCE 15 -#define CHAINSWORD_NOISE 100 - - -/* - * Return a "feeling" (or NULL) about an item. Method 1 (Heavy). - */ -byte value_check_aux1(object_type *o_ptr) -{ - /* Artifacts */ - if (artifact_p(o_ptr)) - { - /* Cursed/Broken */ - if (cursed_p(o_ptr)) return (SENSE_TERRIBLE); - - /* Normal */ - return (SENSE_SPECIAL); - } - - /* Ego-Items */ - if (ego_item_p(o_ptr)) - { - /* Cursed/Broken */ - if (cursed_p(o_ptr)) return (SENSE_WORTHLESS); - - /* Normal */ - return (SENSE_EXCELLENT); - } - - /* Cursed items */ - if (cursed_p(o_ptr)) return (SENSE_CURSED); - - /* Good "armor" bonus */ - if (o_ptr->to_a > 0) return (SENSE_GOOD_HEAVY); - - /* Good "weapon" bonus */ - if (o_ptr->to_h + o_ptr->to_d > 0) return (SENSE_GOOD_HEAVY); - - /* Default to "average" */ - return (SENSE_AVERAGE); -} - -byte value_check_aux1_magic(object_type *o_ptr) -{ - object_kind *k_ptr = &k_info[o_ptr->k_idx]; - - - switch (o_ptr->tval) - { - /* Scrolls, Potions, Wands, Staves and Rods */ - case TV_SCROLL: - case TV_POTION: - case TV_POTION2: - case TV_WAND: - case TV_STAFF: - case TV_ROD: - case TV_ROD_MAIN: - { - /* "Cursed" scrolls/potions have a cost of 0 */ - if (k_ptr->cost == 0) return (SENSE_TERRIBLE); - - /* Artifacts */ - if (artifact_p(o_ptr)) return (SENSE_SPECIAL); - - /* Scroll of Nothing, Apple Juice, etc. */ - if (k_ptr->cost < 3) return (SENSE_WORTHLESS); - - /* - * Identify, Phase Door, Cure Light Wounds, etc. are - * just average - */ - if (k_ptr->cost < 100) return (SENSE_AVERAGE); - - /* Enchant Armor, *Identify*, Restore Stat, etc. */ - if (k_ptr->cost < 10000) return (SENSE_GOOD_HEAVY); - - /* Acquirement, Deincarnation, Strength, Blood of Life, ... */ - if (k_ptr->cost >= 10000) return (SENSE_EXCELLENT); - - break; - } - - /* Food */ - case TV_FOOD: - { - /* "Cursed" food */ - if (k_ptr->cost == 0) return (SENSE_TERRIBLE); - - /* Artifacts */ - if (artifact_p(o_ptr)) return (SENSE_SPECIAL); - - /* Normal food (no magical properties) */ - if (k_ptr->cost <= 10) return (SENSE_AVERAGE); - - /* Everything else is good */ - if (k_ptr->cost > 10) return (SENSE_GOOD_HEAVY); - - break; - } - } - - /* No feeling */ - return (SENSE_NONE); -} - - -/* - * Return a "feeling" (or NULL) about an item. Method 2 (Light). - */ -byte value_check_aux2(object_type *o_ptr) -{ - /* Cursed items (all of them) */ - if (cursed_p(o_ptr)) return (SENSE_CURSED); - - /* Artifacts -- except cursed/broken ones */ - if (artifact_p(o_ptr)) return (SENSE_GOOD_LIGHT); - - /* Ego-Items -- except cursed/broken ones */ - if (ego_item_p(o_ptr)) return (SENSE_GOOD_LIGHT); - - /* Good armor bonus */ - if (o_ptr->to_a > 0) return (SENSE_GOOD_LIGHT); - - /* Good weapon bonuses */ - if (o_ptr->to_h + o_ptr->to_d > 0) return (SENSE_GOOD_LIGHT); - - /* Default to "average" */ - return (SENSE_AVERAGE); -} - - -byte value_check_aux2_magic(object_type *o_ptr) -{ - object_kind *k_ptr = &k_info[o_ptr->k_idx]; - - - switch (o_ptr->tval) - { - /* Scrolls, Potions, Wands, Staves and Rods */ - case TV_SCROLL: - case TV_POTION: - case TV_POTION2: - case TV_WAND: - case TV_STAFF: - case TV_ROD: - case TV_ROD_MAIN: - { - /* "Cursed" scrolls/potions have a cost of 0 */ - if (k_ptr->cost == 0) return (SENSE_CURSED); - - /* Artifacts */ - if (artifact_p(o_ptr)) return (SENSE_GOOD_LIGHT); - - /* Scroll of Nothing, Apple Juice, etc. */ - if (k_ptr->cost < 3) return (SENSE_AVERAGE); - - /* - * Identify, Phase Door, Cure Light Wounds, etc. are - * just average - */ - if (k_ptr->cost < 100) return (SENSE_AVERAGE); - - /* Enchant Armor, *Identify*, Restore Stat, etc. */ - if (k_ptr->cost < 10000) return (SENSE_GOOD_LIGHT); - - /* Acquirement, Deincarnation, Strength, Blood of Life, ... */ - if (k_ptr->cost >= 10000) return (SENSE_GOOD_LIGHT); - - break; - } - - /* Food */ - case TV_FOOD: - { - /* "Cursed" food */ - if (k_ptr->cost == 0) return (SENSE_CURSED); - - /* Artifacts */ - if (artifact_p(o_ptr)) return (SENSE_GOOD_LIGHT); - - /* Normal food (no magical properties) */ - if (k_ptr->cost <= 10) return (SENSE_AVERAGE); - - /* Everything else is good */ - if (k_ptr->cost > 10) return (SENSE_GOOD_LIGHT); - - break; - } - } - - /* No feeling */ - return (SENSE_NONE); -} - - -/* - * Can a player be resurrected? - */ -static bool_ granted_resurrection(void) -{ - PRAY_GOD(GOD_ERU) - { - if (p_ptr->grace > 100000) - { - if (magik(70)) return (TRUE); - else return (FALSE); - } - } - return (FALSE); -} - -static byte select_sense(object_type *o_ptr) -{ - /* Valid "tval" codes */ - switch (o_ptr->tval) - { - case TV_SHOT: - case TV_ARROW: - case TV_BOLT: - case TV_BOW: - case TV_DIGGING: - case TV_HAFTED: - case TV_POLEARM: - case TV_SWORD: - case TV_MSTAFF: - case TV_AXE: - case TV_BOOTS: - case TV_GLOVES: - case TV_HELM: - case TV_CROWN: - case TV_SHIELD: - case TV_CLOAK: - case TV_SOFT_ARMOR: - case TV_HARD_ARMOR: - case TV_DRAG_ARMOR: - case TV_BOOMERANG: - case TV_TRAPKIT: - { - return 1; - break; - } - - case TV_POTION: - case TV_POTION2: - case TV_SCROLL: - case TV_WAND: - case TV_STAFF: - case TV_ROD: - case TV_ROD_MAIN: - { - return 2; - break; - } - - /* Dual use? */ - case TV_DAEMON_BOOK: - { - return 1; - break; - } - } - return 0; -} - -/* - * Sense the inventory - * - * Combat items (weapons and armour) - Fast, weak if combat skill < 10, strong - * otherwise. - * - * Magic items (scrolls, staffs, wands, potions etc) - Slow, weak if - * magic skill < 10, strong otherwise. - * - * It shouldn't matter a lot to discriminate against magic users, because - * they learn one form of ID or another, and because most magic items are - * easy_know. - */ -void sense_inventory(void) -{ - int i, combat_lev, magic_lev; - - bool_ heavy_combat, heavy_magic; - - byte feel; - - object_type *o_ptr; - - char o_name[80]; - - - /*** Check for "sensing" ***/ - - /* No sensing when confused */ - if (p_ptr->confused) return; - - /* - * In Angband, the chance of pseudo-id uses two different formulae: - * - * (1) Fast. 0 == rand_int(BASE / (plev * plev + 40) - * (2) Slow. 0 == rand_int(BASE / (plev + 5) - * - * Warriors: Fase with BASE == 9000 - * Magi: Slow with BASE == 240000 - * Priests: Fast with BASE == 10000 - * Rogues: Fase with BASE == 20000 - * Rangers: Slow with BASE == 120000 - * Paladins: Fast with BASE == 80000 - * - * In other words, those who have identify spells are penalised. - * The problems with Pern/Tome since it externalised player classes - * is that it uses the same and slow formula for spellcasters and - * fighters. - * - * In the following code, combat item pseudo-ID improves exponentially, - * (fast with BASE 9000) and magic one linear (slow with base 60000 -- - * twice faster than V rangers). - * - * I hope this makes it closer to the original model -- pelpel - */ - - /* The combat skill affects weapon/armour pseudo-ID */ - combat_lev = get_skill(SKILL_COMBAT); - - /* The magic skill affects magic item pseudo-ID */ - magic_lev = get_skill(SKILL_MAGIC); - - /* Higher skill levels give the player better sense of items */ - heavy_combat = (combat_lev > 10) ? TRUE : FALSE; - heavy_magic = (magic_lev > 10) ? TRUE : FALSE; - - - /*** Sense everything ***/ - - /* Check everything */ - for (i = 0; i < INVEN_TOTAL; i++) - { - byte okay = 0; - - o_ptr = &p_ptr->inventory[i]; - - /* Skip empty slots */ - if (!o_ptr->k_idx) continue; - - /* We know about it already, do not tell us again */ - if (o_ptr->ident & (IDENT_SENSE)) continue; - - /* It is fully known, no information needed */ - if (object_known_p(o_ptr)) continue; - - /* Valid "tval" codes */ - okay = select_sense(o_ptr); - - /* Skip non-sense machines */ - if (!okay) continue; - - /* Check for a feeling */ - if (okay == 1) - { - feel = (heavy_combat ? value_check_aux1(o_ptr) : value_check_aux2(o_ptr)); - } - else - { - feel = (heavy_magic ? value_check_aux1_magic(o_ptr) : value_check_aux2_magic(o_ptr)); - } - - /* Skip non-feelings */ - if (feel == SENSE_NONE) continue; - - /* Get an object description */ - object_desc(o_name, o_ptr, FALSE, 0); - - /* Message (equipment) */ - if (i >= INVEN_WIELD) - { - msg_format("You feel the %s (%c) you are %s %s %s...", - o_name, index_to_label(i), describe_use(i), - ((o_ptr->number == 1) ? "is" : "are"), sense_desc[feel]); - } - - /* Message (inventory) */ - else - { - msg_format("You feel the %s (%c) in your pack %s %s...", - o_name, index_to_label(i), - ((o_ptr->number == 1) ? "is" : "are"), sense_desc[feel]); - } - - /* We have "felt" it */ - o_ptr->ident |= (IDENT_SENSE); - - /* Set sense property */ - o_ptr->sense = feel; - - /* Combine / Reorder the pack (later) */ - p_ptr->notice |= (PN_COMBINE | PN_REORDER); - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP); - } - - /* Squelch ! */ - squeltch_inventory(); -} - - -/* - * Go to any level (ripped off from wiz_jump) - */ -static void pattern_teleport(void) -{ - /* Ask for level */ - if (get_check("Teleport level? ")) - { - char ppp[80]; - - char tmp_val[160]; - - /* Prompt */ - sprintf(ppp, "Teleport to level (0-%d): ", 99); - - /* Default */ - sprintf(tmp_val, "%d", dun_level); - - /* Ask for a level */ - if (!get_string(ppp, tmp_val, 10)) return; - - /* Extract request */ - command_arg = atoi(tmp_val); - } - else if (get_check("Normal teleport? ")) - { - teleport_player(200); - return; - } - else - { - return; - } - - /* Paranoia */ - if (command_arg < 0) command_arg = 0; - - /* Paranoia */ - if (command_arg > 99) command_arg = 99; - - /* Accept request */ - msg_format("You teleport to dungeon level %d.", command_arg); - - autosave_checkpoint(); - - /* Change level */ - dun_level = command_arg; - - /* Leaving */ - p_ptr->leaving = TRUE; -} - - -/* - * Returns TRUE if we are on the Straight Road... - */ -static bool_ pattern_effect(void) -{ - if ((cave[p_ptr->py][p_ptr->px].feat < FEAT_PATTERN_START) || - (cave[p_ptr->py][p_ptr->px].feat > FEAT_PATTERN_XTRA2)) return (FALSE); - - if (cave[p_ptr->py][p_ptr->px].feat == FEAT_PATTERN_END) - { - (void)set_poisoned(0); - (void)set_image(0); - (void)set_stun(0); - (void)set_cut(0); - (void)set_blind(0); - (void)set_afraid(0); - (void)do_res_stat(A_STR, TRUE); - (void)do_res_stat(A_INT, TRUE); - (void)do_res_stat(A_WIS, TRUE); - (void)do_res_stat(A_DEX, TRUE); - (void)do_res_stat(A_CON, TRUE); - (void)do_res_stat(A_CHR, TRUE); - (void)restore_level(); - (void)hp_player(1000); - cave_set_feat(p_ptr->py, p_ptr->px, FEAT_PATTERN_OLD); - msg_print("This section of the Straight Road looks less powerful."); - } - - - /* - * We could make the healing effect of the - * Pattern center one-time only to avoid various kinds - * of abuse, like luring the win monster into fighting you - * in the middle of the pattern... - */ - else if (cave[p_ptr->py][p_ptr->px].feat == FEAT_PATTERN_OLD) - { - /* No effect */ - } - else if (cave[p_ptr->py][p_ptr->px].feat == FEAT_PATTERN_XTRA1) - { - pattern_teleport(); - } - else if (cave[p_ptr->py][p_ptr->px].feat == FEAT_PATTERN_XTRA2) - { - if (!(p_ptr->invuln)) - take_hit(200, "walking the corrupted Straight Road"); - } - - else - { - if (!(p_ptr->invuln)) - take_hit(damroll(1, 3), "walking the Straight Road"); - } - - return (TRUE); -} - - -/* - * If player has inscribed the object with "!!", let him know when it's - * recharged. -LM- - */ -static void recharged_notice(object_type *o_ptr) -{ - char o_name[80]; - - cptr s; - - - /* No inscription */ - if (!o_ptr->note) return; - - /* Find a '!' */ - s = strchr(quark_str(o_ptr->note), '!'); - - /* Process notification request. */ - while (s) - { - /* Find another '!' */ - if (s[1] == '!') - { - /* Describe (briefly) */ - object_desc(o_name, o_ptr, FALSE, 0); - - /* Notify the player */ - if (o_ptr->number > 1) - { - msg_format("Your %s are recharged.", o_name); - } - else - { - msg_format("Your %s is recharged.", o_name); - } - - /* Done. */ - return; - } - - /* Keep looking for '!'s */ - s = strchr(s + 1, '!'); - } -} - - - -/* - * Regenerate hit points -RAK- - */ -static void regenhp(int percent) -{ - s32b new_chp, new_chp_frac; - - int old_chp; - - - /* Only if alive */ - if (!(p_ptr->necro_extra & CLASS_UNDEAD)) - { - /* Save the old hitpoints */ - old_chp = p_ptr->chp; - - /* Extract the new hitpoints */ - new_chp = ((long)p_ptr->mhp) * percent + PY_REGEN_HPBASE; - - /* div 65536 */ - p_ptr->chp += new_chp >> 16; - - /* check for overflow */ - if ((p_ptr->chp < 0) && (old_chp > 0)) p_ptr->chp = MAX_SHORT; - - /* mod 65536 */ - new_chp_frac = (new_chp & 0xFFFF) + p_ptr->chp_frac; - - if (new_chp_frac >= 0x10000L) - { - p_ptr->chp_frac = new_chp_frac - 0x10000L; - p_ptr->chp++; - } - else - { - p_ptr->chp_frac = new_chp_frac; - } - - /* Fully healed */ - if (p_ptr->chp >= p_ptr->mhp) - { - p_ptr->chp = p_ptr->mhp; - p_ptr->chp_frac = 0; - } - - /* Notice changes */ - if (old_chp != p_ptr->chp) - { - /* Redraw */ - p_ptr->redraw |= (PR_HP); - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - } - } -} - - -/* - * Regenerate mana points -RAK- - */ -static void regenmana(int percent) -{ - s32b new_mana, new_mana_frac; - - int old_csp; - - /* Incraese regen with int */ - percent += adj_str_blow[p_ptr->stat_ind[A_INT]] * 3; - - old_csp = p_ptr->csp; - new_mana = ((long)p_ptr->msp) * percent + PY_REGEN_MNBASE; - - /* div 65536 */ - p_ptr->csp += new_mana >> 16; - - /* check for overflow */ - if ((p_ptr->csp < 0) && (old_csp > 0)) - { - p_ptr->csp = MAX_SHORT; - } - - /* mod 65536 */ - new_mana_frac = (new_mana & 0xFFFF) + p_ptr->csp_frac; - - if (new_mana_frac >= 0x10000L) - { - p_ptr->csp_frac = new_mana_frac - 0x10000L; - p_ptr->csp++; - } - else - { - p_ptr->csp_frac = new_mana_frac; - } - - /* Must set frac to zero even if equal */ - if (p_ptr->csp >= p_ptr->msp) - { - p_ptr->csp = p_ptr->msp; - p_ptr->csp_frac = 0; - } - - /* Redraw mana */ - if (old_csp != p_ptr->csp) - { - /* Redraw */ - p_ptr->redraw |= (PR_MANA); - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - } -} - - - - - - -/* - * Regenerate the monsters (once per 100 game turns) - * - * XXX XXX XXX Should probably be done during monster turns. - */ -static void regen_monsters(void) -{ - int i, frac; - - object_type *o_ptr = &p_ptr->inventory[INVEN_CARRY]; - - - if (o_ptr->k_idx) - { - monster_race *r_ptr = &r_info[o_ptr->pval]; - - /* Allow regeneration (if needed) */ - if (o_ptr->pval2 < o_ptr->pval3) - { - /* Hack -- Base regeneration */ - frac = o_ptr->pval3 / 100; - - /* Hack -- Minimal regeneration rate */ - if (!frac) frac = 1; - - /* Hack -- Some monsters regenerate quickly */ - if (r_ptr->flags2 & (RF2_REGENERATE)) frac *= 2; - - - /* Hack -- Regenerate */ - o_ptr->pval2 += frac; - - /* Do not over-regenerate */ - if (o_ptr->pval2 > o_ptr->pval3) o_ptr->pval2 = o_ptr->pval3; - - /* Redraw (later) */ - p_ptr->redraw |= (PR_MH); - } - } - - /* Regenerate everyone */ - for (i = 1; i < m_max; i++) - { - /* Check the i'th monster */ - monster_type *m_ptr = &m_list[i]; - monster_race *r_ptr = race_inf(m_ptr); - - /* Skip dead monsters */ - if (!m_ptr->r_idx) continue; - - /* Dont regen bleeding/poisonned monsters */ - if (m_ptr->bleeding || m_ptr->poisoned) continue; - - /* Allow regeneration (if needed) */ - if (m_ptr->hp < m_ptr->maxhp) - { - /* Hack -- Base regeneration */ - frac = m_ptr->maxhp / 100; - - /* Hack -- Minimal regeneration rate */ - if (!frac) frac = 1; - - /* Hack -- Some monsters regenerate quickly */ - if (r_ptr->flags2 & (RF2_REGENERATE)) frac *= 2; - - - /* Hack -- Regenerate */ - m_ptr->hp += frac; - - /* Do not over-regenerate */ - if (m_ptr->hp > m_ptr->maxhp) m_ptr->hp = m_ptr->maxhp; - - /* Redraw (later) if needed */ - if (health_who == i) p_ptr->redraw |= (PR_HEALTH); - } - } -} - - -/* - * Does an object decay? - * - * Should belong to object1.c, renamed to object_decays() -- pelpel - */ -bool_ decays(object_type *o_ptr) -{ - u32b f1, f2, f3, f4, f5, esp; - - - /* Extract some flags */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - if (f3 & TR3_DECAY) return (TRUE); - - return (FALSE); -} - - -static int process_lasting_spell(s16b music) -{ - spell_type *spell = spell_at(-music); - return spell_type_produce_effect_lasting(spell); -} - -static void gere_class_special() -{ - switch (p_ptr->druid_extra2) - { - /* Lay a path of mana on the floor */ - case CLASS_MANA_PATH: - { - /* Does the player have enought mana ? */ - if (p_ptr->csp < (s32b)(p_ptr->druid_extra & 255)) - { - p_ptr->druid_extra = 0; - p_ptr->druid_extra2 = CLASS_NONE; - msg_print("You stop laying a mana path."); - } - else - { - /* Use some mana */ - p_ptr->csp -= (p_ptr->druid_extra & 255); - - if ((p_ptr->druid_extra >> 8) & CLASS_MANA_PATH_ERASE) - { - /* Absorb some of the mana of the grid */ - p_ptr->csp += cave[p_ptr->py][p_ptr->px].mana / 50; - if (p_ptr->csp > p_ptr->msp) p_ptr->csp = p_ptr->msp; - - /* Set the new grid mana */ - cave[p_ptr->py][p_ptr->px].mana = p_ptr->druid_extra & 255; - } - else - { - int m = cave[p_ptr->py][p_ptr->px].mana; - - if (m + (p_ptr->druid_extra & 255) > 255) - { - cave[p_ptr->py][p_ptr->px].mana = 255; - } - else - { - cave[p_ptr->py][p_ptr->px].mana += p_ptr->druid_extra & 255; - } - } - } - - break; - } - - /* Lay a path of mana on the floor */ - case CLASS_WINDS_MANA: - { - /* Does the player have enought mana ? */ - if (p_ptr->csp < (s32b)(p_ptr->druid_extra & 255)) - { - p_ptr->druid_extra = CLASS_NONE; - msg_print("You stop expulsing mana winds."); - } - else - { - int dam = 0; - - /* Use some mana */ - p_ptr->csp -= (p_ptr->druid_extra & 255); - - if ((p_ptr->druid_extra >> 8) & CLASS_MANA_PATH_ERASE) - { - dam = (p_ptr->druid_extra & 255) + 256; - } - else - { - dam = (p_ptr->druid_extra & 255); - } - - fire_explosion(p_ptr->py, p_ptr->px, GF_WINDS_MANA, 2, dam); - } - - break; - } - - case CLASS_CANALIZE_MANA: - { - if (p_ptr->druid_extra & CLASS_CANALIZE_MANA_EXTRA) - { - p_ptr->csp += cave[p_ptr->py][p_ptr->px].mana / 10; - } - else - { - p_ptr->csp += cave[p_ptr->py][p_ptr->px].mana / 20; - } - - if (p_ptr->csp > p_ptr->msp) p_ptr->csp = p_ptr->msp; - - cave[p_ptr->py][p_ptr->px].mana = 0; - - break; - } - - /* CLASS_NONE, possibly others? */ - default: - { - /* No mana update */ - return; - } - } - - /* Redraw mana */ - p_ptr->update |= (PU_BONUS); - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); -} - - -static void check_music() -{ - int use_mana; - - /* Music sung by player */ - if (!p_ptr->music_extra) return; - - use_mana = process_lasting_spell(p_ptr->music_extra); - - if (p_ptr->csp < use_mana) - { - msg_print("You stop your spell."); - p_ptr->music_extra = 0; - p_ptr->music_extra2 = 0; - } - else - { - p_ptr->csp -= use_mana; - - /* Redraw mana */ - p_ptr->redraw |= (PR_MANA); - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - } -} - - -/* - * Generate the feature effect - */ -void apply_effect(int y, int x) -{ - cave_type *c_ptr = &cave[y][x]; - - feature_type *f_ptr = &f_info[c_ptr->feat]; - - - if (f_ptr->d_frequency[0] != 0) - { - int i; - - for (i = 0; i < 4; i++) - { - /* Check the frequency */ - if (f_ptr->d_frequency[i] == 0) continue; - - if (((turn % f_ptr->d_frequency[i]) == 0) && - ((f_ptr->d_side[i] != 0) || (f_ptr->d_dice[i] != 0))) - { - int l, dam = 0; - int d = f_ptr->d_dice[i], s = f_ptr->d_side[i]; - - if (d == -1) d = p_ptr->lev; - if (s == -1) s = p_ptr->lev; - - /* Roll damage */ - for (l = 0; l < d; l++) - { - dam += randint(s); - } - - /* Apply damage */ - project( -100, 0, y, x, dam, f_ptr->d_type[i], - PROJECT_KILL | PROJECT_HIDE); - - /* Hack -- notice death */ - if (!alive || death) return; - } - } - } -} - - - -/* XXX XXX XXX */ -bool_ is_recall = FALSE; - - -/* - * Hook for corruptions - */ -static void process_world_corruptions() -{ - if (player_has_corruption(CORRUPT_RANDOM_TELEPORT)) - { - if (rand_int(300) == 1) - { - if (magik(70)) - { - if (get_check("Teleport?")) - { - teleport_player(50); - } - else - { - disturb(0); - msg_print("Your corruption takes over you, you teleport!"); - teleport_player(50); - } - } - } - } - - if (player_has_corruption(CORRUPT_ANTI_TELEPORT)) - { - if (p_ptr->corrupt_anti_teleport_stopped) - { - int amt = p_ptr->msp + p_ptr->csp; - amt = amt / 100; - if (amt < 1) { - amt = 1; - } - increase_mana(-amt); - if (p_ptr->csp == 0) - { - p_ptr->corrupt_anti_teleport_stopped = FALSE; - msg_print("You stop controlling your corruption."); - p_ptr->update = p_ptr->update | PU_BONUS; - } - } - } -} - - -/* - * Shim for accessing Lua variable. - */ -static bool_ grace_delay_trigger() -{ - p_ptr->grace_delay++; - - if (p_ptr->grace_delay >= 15) - { - /* reset */ - p_ptr->grace_delay = 0; - /* triggered */ - return TRUE; - } - else - { - /* not triggered */ - return FALSE; - } -} - -/* - * Hook for gods - */ -static void process_world_gods() -{ - const char *race_name = rp_ptr->title + rp_name; - const char *subrace_name = rmp_ptr->title + rmp_name; - - GOD(GOD_VARDA) - { - if (grace_delay_trigger()) - { - /* Piety increases if in light. */ - if (cave[p_ptr->py][p_ptr->px].info & CAVE_GLOW) - { - inc_piety(GOD_ALL, 2); - } - - if (streq(race_name, "Orc") || - streq(race_name, "Troll") || - streq(race_name, "Dragon") || - streq(race_name, "Demon")) - { - /* Varda hates evil races */ - inc_piety(GOD_ALL, -2); - } else { - /* ... and everyone slightly less */ - inc_piety(GOD_ALL, -1); - } - - /* Prayer uses piety */ - if (p_ptr->praying) - { - inc_piety(GOD_ALL, -1); - } - } - } - - GOD(GOD_ULMO) - { - if (grace_delay_trigger()) - { - int i; - /* Ulmo likes the Edain (except Easterlings) */ - if (streq(race_name, "Human") || - streq(race_name, "Dunadan") || - streq(race_name, "Druadan") || - streq(race_name, "RohanKnight")) - { - inc_piety(GOD_ALL, 2); - } - else if (streq(race_name, "Easterling") || - streq(race_name, "Demon") || - streq(race_name, "Orc")) - { - /* hated races */ - inc_piety(GOD_ALL, -2); - } - else - { - inc_piety(GOD_ALL, 1); - } - - if (p_ptr->praying) - { - inc_piety(GOD_ALL, -1); - } - - /* Gain 1 point for each trident in inventory */ - for (i = 0; i < INVEN_TOTAL; i++) - { - if ((p_ptr->inventory[i].tval == TV_POLEARM) && - (p_ptr->inventory[i].sval == SV_TRIDENT)) - { - inc_piety(GOD_ALL, 1); - } - } - } - } - - GOD(GOD_AULE) - { - if (grace_delay_trigger()) - { - int i; - - /* Aule likes Dwarves and Dark Elves (Eol's - * influence here) */ - if (!(streq(race_name, "Dwarf") || - streq(race_name, "Petty-dwarf") || - streq(race_name, "Gnome") || - streq(race_name, "Dark-Elf"))) - { - inc_piety(GOD_ALL, -1); - } - - /* Search inventory for axe or hammer - Gain 1 - * point of grace for each hammer or axe */ - for (i = 0; i < INVEN_TOTAL; i++) - { - int tval = p_ptr->inventory[i].tval; - int sval = p_ptr->inventory[i].sval; - - switch (tval) - { - case TV_AXE: - inc_piety(GOD_ALL, 1); - break; - - case TV_HAFTED: - if ((sval == SV_WAR_HAMMER) || - (sval == SV_LUCERN_HAMMER) || - (sval == SV_GREAT_HAMMER)) - { - inc_piety(GOD_ALL, 1); - } - break; - } - } - - /* Praying may grant you a free stone skin - * once in a while */ - if (p_ptr->praying) - { - int chance; - s32b grace; - - inc_piety(GOD_ALL, -2); - grace = p_ptr->grace; /* shorthand */ - - chance = 1; - if (grace >= 50000) - { - chance = 50000; - } - else - { - chance = 50000 - grace; - } - - if (randint(100000) <= 100000 / chance) - { - s16b type = 0; - - if (grace >= 10000) - { - type = SHIELD_COUNTER; - } - - set_shield( - randint(10) + 10 + (grace / 100), - 10 + (grace / 100), - type, - 2 + (grace / 200), - 3 + (grace / 400)); - - msg_print("Aule casts Stone Skin on you."); - } - } - } - } - - GOD(GOD_MANDOS) - { - if (grace_delay_trigger()) - { - /* He loves astral beings */ - if (streq(subrace_name, "LostSoul")) - { - inc_piety(GOD_ALL, 1); - } - - /* He likes High Elves only, though, as races */ - if (!streq(race_name, "High-Elf")) - { - inc_piety(GOD_ALL, -1); - } - - /* Really hates vampires and demons */ - if (streq(subrace_name, "Vampire") || - streq(race_name, "Demon")) - { - inc_piety(GOD_ALL, -10); - } - else - { - inc_piety(GOD_ALL, 2); - } - /* he really doesn't like to be disturbed */ - if (p_ptr->praying) - { - inc_piety(GOD_ALL, -5); - } - } - } - -} - -/* - * Handle certain things once every 10 game turns - * - * Note that a single movement in the overhead wilderness mode - * consumes 132 times as much energy as a normal one... - */ -static void process_world(void) -{ - timer_type *t_ptr; - - int x, y, i, j; - - int regen_amount; - bool_ cave_no_regen = FALSE; - int upkeep_factor = 0; - - dungeon_info_type *d_ptr = &d_info[dungeon_type]; - - cave_type *c_ptr; - - object_type *o_ptr; - u32b f1 = 0 , f2 = 0 , f3 = 0, f4 = 0, f5 = 0, esp = 0; - - - /* - * Every 10 game turns -- which means this section is invoked once - * in a player turn under the normal speed, and 132 times in a move - * in the reduced map mode. - */ - if (turn % 10) return; - - /* - * I don't know if this is the right thing to do because I'm totally - * ignorant (yes, I must admit that...) about the scripting part of - * the game, but since there have been complaints telling us it - * runs terribly slow in the reduced map mode... -- pelpel - * - * Note to coders: if it is desirable to make this active in the - * reduced map mode, remove the if condition surrounding the line - * and move the code inside into every 1000 game turns section. - */ - if (dun_level || (!p_ptr->wild_mode)) - { - /* Handle corruptions */ - process_world_corruptions(); - - /* Handle gods */ - process_world_gods(); - - /* Handle the player song */ - check_music(); - } - - /* Handle the timers */ - for (t_ptr = gl_timers; t_ptr != NULL; t_ptr = t_ptr->next) - { - if (!t_ptr->enabled) continue; - - t_ptr->countdown--; - if (!t_ptr->countdown) - { - t_ptr->countdown = t_ptr->delay; - assert(t_ptr->callback != NULL); - t_ptr->callback(); - } - } - - /* Handle class special actions */ - gere_class_special(); - - /* Check the fate */ - if (fate_option && (p_ptr->lev > 10)) - { - /* - * WAS: == 666 against randint(50000). - * Since CPU's don't know Judeo-Christian / Cabalistic traditions, - * and since comparisons with zero is more efficient in many - * architectures... - */ - if (rand_int(50000) == 0) gain_fate(0); - } - - /*** Is the wielded monsters still hypnotised ***/ - o_ptr = &p_ptr->inventory[INVEN_CARRY]; - - if (o_ptr->k_idx) - { - monster_race *r_ptr = &r_info[o_ptr->pval]; - - if ((randint(1000) < r_ptr->level - ((p_ptr->lev * 2) + get_skill(SKILL_SYMBIOTIC)))) - { - msg_format("%s breaks free from hypnosis!", - symbiote_name(TRUE)); - carried_make_attack_normal(o_ptr->pval); - } - } - - /*** Attempt timed autosave ***/ - if (autosave_t && autosave_freq) - { - if ((turn % ((s32b)autosave_freq * 10)) == 0) - { - is_autosave = TRUE; - msg_print("Autosaving the game..."); - do_cmd_save_game(); - is_autosave = FALSE; - } - } - - - /*** Handle the wilderness/town (sunshine) ***/ - - /* While in town/wilderness and not in the overworld mode */ - if (!dun_level && !p_ptr->wild_mode) - { - /* Hack -- Daybreak/Nighfall in town */ - if ((turn % ((10L * DAY) / 2)) == 0) - { - bool_ dawn; - - /* Check for dawn */ - dawn = ((turn % (10L * DAY)) == 0); - - /* Day breaks */ - if (dawn) - { - /* Message */ - msg_print("The sun has risen."); - - /* Hack -- Scan the town */ - for (y = 0; y < cur_hgt; y++) - { - for (x = 0; x < cur_wid; x++) - { - /* Get the cave grid */ - c_ptr = &cave[y][x]; - - /* Assume lit */ - c_ptr->info |= (CAVE_GLOW); - - /* Hack -- Memorize lit grids if allowed */ - if (view_perma_grids) c_ptr->info |= (CAVE_MARK); - - /* Hack -- Notice spot */ - note_spot(y, x); - } - } - } - - /* Night falls */ - else - { - /* Message */ - msg_print("The sun has set."); - - /* Hack -- Scan the town */ - for (y = 0; y < cur_hgt; y++) - { - for (x = 0; x < cur_wid; x++) - { - /* Get the cave grid */ - c_ptr = &cave[y][x]; - - /* Darken "boring" features */ - if (cave_plain_floor_grid(c_ptr)) - { - /* Forget the grid */ - c_ptr->info &= ~(CAVE_GLOW | CAVE_MARK); - - /* Hack -- Notice spot */ - note_spot(y, x); - } - } - } - } - - /* Update the monsters */ - p_ptr->update |= (PU_MONSTERS); - - /* Redraw map */ - p_ptr->redraw |= (PR_MAP); - - /* Window stuff */ - p_ptr->window |= (PW_OVERHEAD); - } - } - - /* Tell a day passed */ - if (((turn + (DAY_START * 10L)) % (10L * DAY)) == 0) - { - char buf[20]; - - sprintf(buf, "%s", get_day(bst(YEAR, turn) + START_YEAR)); - cmsg_format(TERM_L_GREEN, - "Today it is %s of the %s year of the third age.", - get_month_name(bst(DAY, turn), wizard, FALSE), buf); - } - - /* Set back the rewards once a day */ - if ((turn % (10L * STORE_TURNS)) == 0) - { - /* Select new bounties. */ - if (magik(20)) select_bounties(); - } - - /* Modify loan */ - if (p_ptr->loan) - { - if (p_ptr->loan_time) p_ptr->loan_time--; - - if (((turn % 5000) == 0) && !p_ptr->loan_time) - { - cmsg_print(TERM_RED, "You should pay your loan..."); - - p_ptr->loan += p_ptr->loan / 12; - - if (p_ptr->loan > PY_MAX_GOLD) p_ptr->loan = PY_MAX_GOLD; - - /* Do a nasty stuff */ - if (p_ptr->wild_mode && rand_int(2)) - { - /* Discount player items */ - int z = 0, tries = 200; - object_type *o_ptr = NULL; - - while (tries--) - { - z = rand_int(INVEN_TOTAL); - o_ptr = &p_ptr->inventory[z]; - - if (!o_ptr->k_idx) continue; - - if (o_ptr->discount >= 100) continue; - - break; - } - - if (tries) - { - o_ptr->discount += 70; - if (o_ptr->discount >= 100) o_ptr->discount = 100; - - inven_item_optimize(z); - inven_item_describe(z); - - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - } - } - - else - { - int merc = test_monster_name("Mean-looking mercenary"); - int agent = test_monster_name("Agent of the black market"); - int num = 5 + (p_ptr->lev / 3), z; - - for (z = 0; z < num; z++) - { - int yy, xx, attempts = 200, m_idx; - - /* Summon */ - while (1) - { - scatter(&yy, &xx, p_ptr->py, p_ptr->px, 6); - - /* Accept an empty grid within the boundary */ - if (in_bounds(yy, xx) && cave_floor_bold(yy, xx)) break; - - /* Max number of retries reached */ - if (--attempts == 0) break; - } - - /* All the attempts failed */ - if (attempts == 0) continue; - - /* Summon a monster */ - m_idx = place_monster_one(yy, xx, magik(80) ? merc : agent, - 0, FALSE, MSTATUS_ENEMY); - - /* Level it */ - if (m_idx) - { - monster_type *m_ptr = &m_list[m_idx]; - - m_ptr->exp = MONSTER_EXP(p_ptr->lev * 2); - monster_check_experience(m_idx, TRUE); - } - } - } - } - } - - /*** Process the monsters ***/ - - /* Check for creature generation. */ - if (!p_ptr->wild_mode && - !p_ptr->inside_arena && - !p_ptr->inside_quest && - (rand_int(d_info[(dun_level) ? dungeon_type : DUNGEON_WILDERNESS].max_m_alloc_chance) == 0)) - { - /* Make a new monster */ - if (!(dungeon_flags2 & DF2_NO_NEW_MONSTER)) - { - (void)alloc_monster(MAX_SIGHT + 5, FALSE); - } - } - - /* Hack -- Check for creature regeneration */ - if (!p_ptr->wild_mode && ((turn % 100) == 0)) regen_monsters(); - - - /*** Damage over Time ***/ - - /* Take damage from poison */ - if (p_ptr->poisoned && !p_ptr->invuln) - { - /* Take damage */ - take_hit(1, "poison"); - } - - - /* Vampires take damage from sunlight */ - if (p_ptr->sensible_lite) - { - if ((!dun_level) && (((turn / ((10L * DAY) / 2)) % 2) == 0)) - { - if (cave[p_ptr->py][p_ptr->px].info & (CAVE_GLOW)) - { - /* Take damage */ - msg_print("The sun's rays scorch your undead flesh!"); - take_hit(1, "sunlight"); - cave_no_regen = TRUE; - drop_from_wild(); - } - } - - if ((p_ptr->inventory[INVEN_LITE].tval != 0) && - (p_ptr->inventory[INVEN_LITE].sval >= SV_LITE_GALADRIEL) && - (p_ptr->inventory[INVEN_LITE].sval <= SV_STONE_LORE) && - (p_ptr->inventory[INVEN_LITE].sval != SV_LITE_UNDEATH)) - { - object_type * o_ptr = &p_ptr->inventory[INVEN_LITE]; - char o_name [80]; - char ouch [80]; - - /* Get an object description */ - object_desc(o_name, o_ptr, FALSE, 0); - - msg_format("The %s scorches your undead flesh!", o_name); - - cave_no_regen = TRUE; - - /* Get an object description */ - object_desc(o_name, o_ptr, TRUE, 0); - - sprintf(ouch, "wielding %s", o_name); - take_hit(1, ouch); - } - } - - /* Drown in deep water unless the player have levitation, water walking - water breathing, or magic breathing.*/ - if (!p_ptr->ffall && !p_ptr->walk_water && !p_ptr->magical_breath && - !p_ptr->water_breath && - (cave[p_ptr->py][p_ptr->px].feat == FEAT_DEEP_WATER)) - { - if (calc_total_weight() > ((weight_limit()) / 2)) - { - /* Take damage */ - msg_print("You are drowning!"); - take_hit(randint(p_ptr->lev), "drowning"); - cave_no_regen = TRUE; - } - } - - - /* Spectres -- take damage when moving through walls */ - - /* - * Added: ANYBODY takes damage if inside through walls - * without wraith form -- NOTE: Spectres will never be - * reduced below 0 hp by being inside a stone wall; others - * WILL BE! - */ - if (!cave_floor_bold(p_ptr->py, p_ptr->px)) - { - int feature = cave[p_ptr->py][p_ptr->px].feat; - - /* Player can walk through or fly over trees */ - if ((has_ability(AB_TREE_WALK) || p_ptr->fly) && (feature == FEAT_TREES)) - { - /* Do nothing */ - } - /* Player can climb over mountains */ - else if ((p_ptr->climb) && (f_info[feature].flags1 & FF1_CAN_CLIMB)) - { - /* Do nothing */ - } - else if (PRACE_FLAG(PR1_SEMI_WRAITH) && (!p_ptr->wraith_form) && (f_info[cave[p_ptr->py][p_ptr->px].feat].flags1 & FF1_CAN_PASS)) - { - int amt = 1 + ((p_ptr->lev) / 5); - - cave_no_regen = TRUE; - if (amt > p_ptr->chp - 1) amt = p_ptr->chp - 1; - take_hit(amt, " walls ..."); - } - } - - - /* Take damage from cuts */ - if ((p_ptr->cut) && !(p_ptr->invuln)) - { - /* Mortal wound or Deep Gash */ - if (p_ptr->cut > 200) - { - i = 3; - } - - /* Severe cut */ - else if (p_ptr->cut > 100) - { - i = 2; - } - - /* Other cuts */ - else - { - i = 1; - } - - /* Take damage */ - take_hit(i, "a fatal wound"); - } - - - /*** Check the Food, and Regenerate ***/ - - /* Digest normally */ - if (p_ptr->food < PY_FOOD_MAX) - { - /* Every 100 game turns */ - if ((turn % 100) == 0) - { - int speed_use = p_ptr->pspeed; - - /* Maximum */ - if (speed_use > 199) - { - speed_use = 199; - } - - /* Minimum */ - else if (speed_use < 0) - { - speed_use = 0; - } - - /* Basic digestion rate based on speed */ - i = extract_energy[speed_use] * 2; - - /* Regeneration takes more food */ - if (p_ptr->regenerate) i += 30; - - /* Regeneration takes more food */ - if (p_ptr->tim_regen) i += p_ptr->tim_regen_pow / 10; - - /* Invisibility consume a lot of food */ - i += p_ptr->invis / 2; - - /* Invulnerability consume a lot of food */ - if (p_ptr->invuln) i += 40; - - /* Wraith Form consume a lot of food */ - if (p_ptr->wraith_form) i += 30; - - /* Get the weapon */ - o_ptr = &p_ptr->inventory[INVEN_WIELD]; - - /* Examine the sword */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* Hitpoints multiplier consume a lot of food */ - if (o_ptr->k_idx && (f2 & (TR2_LIFE))) i += o_ptr->pval * 5; - - /* Slow digestion takes less food */ - if (p_ptr->slow_digest) i -= 10; - - /* Minimal digestion */ - if (i < 1) i = 1; - - /* Digest some food */ - (void)set_food(p_ptr->food - i); - } - } - - /* Digest quickly when gorged */ - else - { - /* Digest a lot of food */ - (void)set_food(p_ptr->food - 100); - } - - /* Starve to death (slowly) */ - if (p_ptr->food < PY_FOOD_STARVE) - { - /* Calculate damage */ - i = (PY_FOOD_STARVE - p_ptr->food) / 10; - - /* Take damage */ - if (!(p_ptr->invuln)) take_hit(i, "starvation"); - } - - /* Default regeneration */ - regen_amount = PY_REGEN_NORMAL; - - /* Getting Weak */ - if (p_ptr->food < PY_FOOD_WEAK) - { - /* Lower regeneration */ - if (p_ptr->food < PY_FOOD_STARVE) - { - regen_amount = 0; - } - else if (p_ptr->food < PY_FOOD_FAINT) - { - regen_amount = PY_REGEN_FAINT; - } - else - { - regen_amount = PY_REGEN_WEAK; - } - - /* Getting Faint */ - if (p_ptr->food < PY_FOOD_FAINT) - { - /* Faint occasionally */ - if (!p_ptr->paralyzed && (rand_int(100) < 10)) - { - /* Message */ - msg_print("You faint from the lack of food."); - disturb(1); - - /* Hack -- faint (bypass free action) */ - (void)set_paralyzed(1 + rand_int(5)); - } - } - } - - /* Are we walking the pattern? */ - if (!p_ptr->wild_mode && pattern_effect()) - { - cave_no_regen = TRUE; - } - else - { - /* Regeneration ability */ - if (p_ptr->regenerate) - { - regen_amount = regen_amount * 2; - } - } - - - /* Searching or Resting */ - if (p_ptr->searching || resting) - { - regen_amount = regen_amount * 2; - } - - if (total_friends) - { - int upkeep_divider = 20; - - if (has_ability(AB_PERFECT_CASTING)) - upkeep_divider = 15; - - if (total_friends > 1 + (p_ptr->lev / (upkeep_divider))) - { - upkeep_factor = (total_friend_levels); - - if (upkeep_factor > 100) upkeep_factor = 100; - else if (upkeep_factor < 10) upkeep_factor = 10; - } - } - - /* Regenerate the mana */ - if (p_ptr->csp < p_ptr->msp) - { - if (upkeep_factor) - { - s16b upkeep_regen = (((100 - upkeep_factor) * regen_amount) / 100); - regenmana(upkeep_regen); - } - else - { - regenmana(regen_amount); - } - } - - /* Eru piety incraese with time */ - if (((turn % 100) == 0) && (!p_ptr->did_nothing) && (!p_ptr->wild_mode)) - { - NOT_PRAY_GOD(GOD_ERU) - { - int inc = wisdom_scale(10); - - /* Increase by wisdom/4 */ - if (!inc) inc = 1; - inc_piety(GOD_ERU, inc); - } - } - /* Most gods piety decrease with time */ - if (((turn % 300) == 0) && (!p_ptr->did_nothing) && (!p_ptr->wild_mode) && (dun_level)) - { - GOD(GOD_MANWE) - { - int dec = 4 - wisdom_scale(3); - - PRAY_GOD(GOD_MANWE) - dec++; - if (PRACE_FLAG(PR1_ELF)) - dec -= wisdom_scale(2); - if (dec < 1) dec = 1; - inc_piety(GOD_MANWE, -dec); - } - GOD(GOD_MELKOR) - { - int dec = 8 - wisdom_scale(6); - - PRAY_GOD(GOD_MELKOR) - dec++; - if (PRACE_FLAG(PR1_ELF)) - dec += 5 - wisdom_scale(4); - if (dec < 1) dec = 1; - inc_piety(GOD_MELKOR, -dec); - } - PRAY_GOD(GOD_TULKAS) - { - int dec = 4 - wisdom_scale(3); - - if (dec < 1) dec = 1; - inc_piety(GOD_TULKAS, -dec); - } - } - /* Yavanna piety decrease with time */ - if (((turn % 400) == 0) && (!p_ptr->did_nothing) && (!p_ptr->wild_mode) && (dun_level)) - { - GOD(GOD_YAVANNA) - { - int dec = 5 - wisdom_scale(3); - - /* Blech what an hideous hack */ - if (!strcmp(rp_ptr->title + rp_name, "Ent")) - dec -= wisdom_scale(2); - if (dec < 1) dec = 1; - inc_piety(GOD_YAVANNA, -dec); - } - } - p_ptr->did_nothing = FALSE; - - /* Increase regen by tim regen */ - if (p_ptr->tim_regen) regen_amount += p_ptr->tim_regen_pow; - - /* Poisoned or cut yields no healing */ - if (p_ptr->poisoned) regen_amount = 0; - if (p_ptr->cut) regen_amount = 0; - - /* Special floor -- Pattern, in a wall -- yields no healing */ - if (cave_no_regen) regen_amount = 0; - - /* Being over grass allows Yavanna to regen you */ - PRAY_GOD(GOD_YAVANNA) - { - if (cave[p_ptr->py][p_ptr->px].feat == FEAT_GRASS) - { - regen_amount += 200 + wisdom_scale(800); - } - } - - /* Regenerate Hit Points if needed */ - if ((p_ptr->chp < p_ptr->mhp) && !cave_no_regen) - { - if ((cave[p_ptr->py][p_ptr->px].feat < FEAT_PATTERN_END) && - (cave[p_ptr->py][p_ptr->px].feat >= FEAT_PATTERN_START)) - { - /* Hmmm. this should never happen? */ - regenhp(regen_amount / 5); - } - else - { - regenhp(regen_amount); - } - } - - - /*** Timeout Various Things ***/ - - /* Handle temporary stat drains */ - for (i = 0; i < 6; i++) - { - if (p_ptr->stat_cnt[i] > 0) - { - p_ptr->stat_cnt[i]--; - if (p_ptr->stat_cnt[i] == 0) - { - do_res_stat(i, FALSE); - } - } - } - - /* Hack -- Hallucinating */ - if (p_ptr->image) - { - (void)set_image(p_ptr->image - 1); - } - - /* Holy Aura */ - if (p_ptr->holy) - { - (void)set_holy(p_ptr->holy - 1); - } - - /* Soul absorbtion */ - if (p_ptr->absorb_soul) - { - (void)set_absorb_soul(p_ptr->absorb_soul - 1); - } - - /* Undead loose Death Points */ - if (p_ptr->necro_extra & CLASS_UNDEAD) - { - int old_chp = p_ptr->chp; - int warning = (p_ptr->mhp * hitpoint_warn / 10); - - /* Bypass invulnerability and wraithform */ - p_ptr->chp--; - - /* Display the hitpoints */ - p_ptr->redraw |= (PR_HP); - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - - /* Dead player */ - if (p_ptr->chp < 0) - { - bool_ old_quick = quick_messages; - - /* Sound */ - sound(SOUND_DEATH); - - /* Hack -- Note death */ - if (!last_words) - { - msg_print("You die."); - msg_print(NULL); - } - else - { - char death_message[80]; - - (void)get_rnd_line("death.txt", death_message); - msg_print(death_message); - } - - /* Note cause of death */ - (void)strcpy(died_from, "being undead too long"); - - if (p_ptr->image) strcat(died_from, "(?)"); - - /* No longer a winner */ - total_winner = FALSE; - - /* Leaving */ - p_ptr->leaving = TRUE; - - /* Note death */ - death = TRUE; - - quick_messages = FALSE; - if (get_check("Make a last screenshot? ")) - { - do_cmd_html_dump(); - } - quick_messages = old_quick; - - /* Dead */ - return; - } - - /* Hitpoint warning */ - if (p_ptr->chp < warning) - { - /* Hack -- bell on first notice */ - if (alert_hitpoint && (old_chp > warning)) bell(); - - sound(SOUND_WARN); - - /* Message */ - msg_print("*** LOW DEATHPOINT WARNING! ***"); - msg_print(NULL); - } - } - - /* Walk water */ - if (p_ptr->walk_water) - { - (void)set_walk_water(p_ptr->walk_water - 1); - } - - /* True Strike */ - if (p_ptr->strike) - { - (void)set_strike(p_ptr->strike - 1); - } - - /* Meditation */ - if (p_ptr->meditation) - { - (void)set_meditation(p_ptr->meditation - 1); - } - - /* Timed project */ - if (p_ptr->tim_project) - { - (void)set_project(p_ptr->tim_project - 1, p_ptr->tim_project_gf, p_ptr->tim_project_dam, p_ptr->tim_project_rad, p_ptr->tim_project_flag); - } - - /* Timed roots */ - if (p_ptr->tim_roots) - { - (void)set_roots(p_ptr->tim_roots - 1, p_ptr->tim_roots_ac, p_ptr->tim_roots_dam); - } - - /* Timed breath */ - if (p_ptr->tim_water_breath) - { - (void)set_tim_breath(p_ptr->tim_water_breath - 1, FALSE); - } - if (p_ptr->tim_magic_breath) - { - (void)set_tim_breath(p_ptr->tim_magic_breath - 1, TRUE); - } - - /* Timed precognition */ - if (p_ptr->tim_precognition > 0) - { - set_tim_precognition(p_ptr->tim_precognition - 1); - } - - /* Timed regen */ - if (p_ptr->tim_regen) - { - (void)set_tim_regen(p_ptr->tim_regen - 1, p_ptr->tim_regen_pow); - } - - /* Timed Disrupt shield */ - if (p_ptr->disrupt_shield) - { - (void)set_disrupt_shield(p_ptr->disrupt_shield - 1); - } - - /* Timed Parasite */ - if (p_ptr->parasite) - { - (void)set_parasite(p_ptr->parasite - 1, p_ptr->parasite_r_idx); - } - - /* Timed Reflection */ - if (p_ptr->tim_reflect) - { - (void)set_tim_reflect(p_ptr->tim_reflect - 1); - } - - /* Timed Prob Travel */ - if (p_ptr->prob_travel) - { - (void)set_prob_travel(p_ptr->prob_travel - 1); - } - - /* Timed Time Resistance */ - if (p_ptr->tim_res_time) - { - (void)set_tim_res_time(p_ptr->tim_res_time - 1); - } - - /* Timed Levitation */ - if (p_ptr->tim_ffall) - { - (void)set_tim_ffall(p_ptr->tim_ffall - 1); - } - if (p_ptr->tim_fly) - { - (void)set_tim_fly(p_ptr->tim_fly - 1); - } - - /* Thunderstorm */ - if (p_ptr->tim_thunder) - { - int dam = damroll(p_ptr->tim_thunder_p1, p_ptr->tim_thunder_p2); - int i, tries = 600; - monster_type *m_ptr = NULL; - - while (tries) - { - /* Access the monster */ - m_ptr = &m_list[i = rand_range(1, m_max - 1)]; - - tries--; - - /* Ignore "dead" monsters */ - if (!m_ptr->r_idx) continue; - - /* Cant see ? cant hit */ - if (!los(p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx)) continue; - - /* Do not hurt friends! */ - if (is_friend(m_ptr) >= 0) continue; - break; - } - - if (tries) - { - char m_name[80]; - - monster_desc(m_name, m_ptr, 0); - msg_format("Lightning strikes %s.", m_name); - project(0, 0, m_ptr->fy, m_ptr->fx, dam / 3, GF_ELEC, - PROJECT_KILL | PROJECT_ITEM | PROJECT_HIDE); - project(0, 0, m_ptr->fy, m_ptr->fx, dam / 3, GF_LITE, - PROJECT_KILL | PROJECT_ITEM | PROJECT_HIDE); - project(0, 0, m_ptr->fy, m_ptr->fx, dam / 3, GF_SOUND, - PROJECT_KILL | PROJECT_ITEM | PROJECT_HIDE); - } - - (void)set_tim_thunder(p_ptr->tim_thunder - 1, p_ptr->tim_thunder_p1, p_ptr->tim_thunder_p2); - } - - /* Poisonned hands */ - if (p_ptr->tim_poison) - { - (void)set_poison(p_ptr->tim_poison - 1); - } - - /* Timed Fire Aura */ - if (p_ptr->tim_fire_aura) - { - (void)set_tim_fire_aura(p_ptr->tim_fire_aura - 1); - } - - /* Brightness */ - if (p_ptr->tim_lite) - { - (void)set_lite(p_ptr->tim_lite - 1); - } - - /* Blindness */ - if (p_ptr->blind) - { - (void)set_blind(p_ptr->blind - 1); - } - - /* Timed no_breeds */ - if (no_breeds) - { - (void)set_no_breeders(no_breeds - 1); - } - - /* Timed mimic */ - if (p_ptr->tim_mimic) - { - (void)set_mimic(p_ptr->tim_mimic - 1, p_ptr->mimic_form, p_ptr->mimic_level); - } - - /* Timed special move commands */ - if (p_ptr->immov_cntr) - { - p_ptr->immov_cntr--; - } - - /* Timed invisibility */ - if (p_ptr->tim_invisible) - { - (void)set_invis(p_ptr->tim_invisible - 1, p_ptr->tim_inv_pow); - } - - /* Times see-invisible */ - if (p_ptr->tim_invis) - { - (void)set_tim_invis(p_ptr->tim_invis - 1); - } - - /* Timed esp */ - if (p_ptr->tim_esp) - { - (void)set_tim_esp(p_ptr->tim_esp - 1); - } - - /* Timed infra-vision */ - if (p_ptr->tim_infra) - { - (void)set_tim_infra(p_ptr->tim_infra - 1); - } - - /* Paralysis */ - if (p_ptr->paralyzed) - { - dec_paralyzed(); - } - - /* Confusion */ - if (p_ptr->confused) - { - (void)set_confused(p_ptr->confused - 1); - } - - /* Afraid */ - if (p_ptr->afraid) - { - (void)set_afraid(p_ptr->afraid - 1); - } - - /* Fast */ - if (p_ptr->fast) - { - (void)set_fast(p_ptr->fast - 1, p_ptr->speed_factor); - } - - /* Light speed */ - if (p_ptr->lightspeed) - { - (void)set_light_speed(p_ptr->lightspeed - 1); - } - - /* Slow */ - if (p_ptr->slow) - { - (void)set_slow(p_ptr->slow - 1); - } - - /* Protection from evil */ - if (p_ptr->protevil) - { - (void)set_protevil(p_ptr->protevil - 1); - } - - /* Protection from good */ - if (p_ptr->protgood) - { - (void)set_protgood(p_ptr->protgood - 1); - } - - /* Protection from undead */ - if (p_ptr->protundead) - { - (void)set_protundead(p_ptr->protundead - 1); - } - - /* Invulnerability */ - if (p_ptr->invuln) - { - (void)set_invuln(p_ptr->invuln - 1); - } - - /* Wraith form */ - if (p_ptr->tim_wraith) - { - (void)set_shadow(p_ptr->tim_wraith - 1); - } - - /* Heroism */ - if (p_ptr->hero) - { - (void)set_hero(p_ptr->hero - 1); - } - - /* Super Heroism */ - if (p_ptr->shero) - { - (void)set_shero(p_ptr->shero - 1); - } - - /* Blessed */ - if (p_ptr->blessed) - { - (void)set_blessed(p_ptr->blessed - 1); - } - - /* Shield */ - if (p_ptr->shield) - { - (void)set_shield(p_ptr->shield - 1, p_ptr->shield_power, p_ptr->shield_opt, p_ptr->shield_power_opt, p_ptr->shield_power_opt2); - } - - /* Oppose Acid */ - if (p_ptr->oppose_acid) - { - (void)set_oppose_acid(p_ptr->oppose_acid - 1); - } - - /* Oppose Lightning */ - if (p_ptr->oppose_elec) - { - (void)set_oppose_elec(p_ptr->oppose_elec - 1); - } - - /* Oppose Fire */ - if (p_ptr->oppose_fire) - { - (void)set_oppose_fire(p_ptr->oppose_fire - 1); - } - - /* Oppose Cold */ - if (p_ptr->oppose_cold) - { - (void)set_oppose_cold(p_ptr->oppose_cold - 1); - } - - /* Oppose Poison */ - if (p_ptr->oppose_pois) - { - (void)set_oppose_pois(p_ptr->oppose_pois - 1); - } - - /* Oppose Light & Dark */ - if (p_ptr->oppose_ld) - { - (void)set_oppose_ld(p_ptr->oppose_ld - 1); - } - - /* Oppose Chaos & Confusion */ - if (p_ptr->oppose_cc) - { - (void)set_oppose_cc(p_ptr->oppose_cc - 1); - } - - /* Oppose Sound & Shards */ - if (p_ptr->oppose_ss) - { - (void)set_oppose_ss(p_ptr->oppose_ss - 1); - } - - /* Oppose Nexus */ - if (p_ptr->oppose_nex) - { - (void)set_oppose_nex(p_ptr->oppose_nex - 1); - } - - /* Mental Barrier */ - if (p_ptr->tim_mental_barrier) - { - (void)set_mental_barrier(p_ptr->tim_mental_barrier - 1); - } - - /* The rush */ - if (p_ptr->rush) - { - (void)set_rush(p_ptr->rush - 1); - } - - - /* Timed mimicry */ - if (get_skill(SKILL_MIMICRY)) - { - /* Extract the value and the flags */ - u32b value = p_ptr->mimic_extra >> 16; - - u32b att = p_ptr->mimic_extra & 0xFFFF; - - if ((att & CLASS_LEGS) || (att & CLASS_WALL) || (att & CLASS_ARMS)) - { - value--; - - if (!value) - { - if (att & CLASS_LEGS) msg_print("You lose your extra pair of legs."); - if (att & CLASS_ARMS) msg_print("You lose your extra pair of arms."); - if (att & CLASS_WALL) msg_print("You lose your affinity for walls."); - - att &= ~(CLASS_ARMS); - att &= ~(CLASS_LEGS); - att &= ~(CLASS_WALL); - - if (disturb_state) disturb(0); - } - - p_ptr->update |= (PU_BODY); - p_ptr->mimic_extra = att + (value << 16); - } - } - - - /*** Poison and Stun and Cut ***/ - - /* Poison */ - if (p_ptr->poisoned) - { - int adjust = (adj_con_fix[p_ptr->stat_ind[A_CON]] + 1); - - /* Apply some healing */ - (void)set_poisoned(p_ptr->poisoned - adjust); - } - - /* Stun */ - if (p_ptr->stun) - { - int adjust = (adj_con_fix[p_ptr->stat_ind[A_CON]] + 1); - - /* Apply some healing */ - (void)set_stun(p_ptr->stun - adjust); - } - - /* Cut */ - if (p_ptr->cut) - { - int adjust = (adj_con_fix[p_ptr->stat_ind[A_CON]] + 1); - - /* Hack -- Truly "mortal" wound */ - if (p_ptr->cut > 1000) adjust = 0; - - /* Apply some healing */ - (void)set_cut(p_ptr->cut - adjust); - } - - /* Hack - damage done by the dungeon -SC- */ - if ((dun_level != 0) && (d_ptr->d_frequency[0] != 0)) - { - int i, j, k; - - /* Apply damage to every grid in the dungeon */ - for (i = 0; i < 4; i++) - { - /* Check the frequency */ - if (d_ptr->d_frequency[i] == 0) continue; - - if (((turn % d_ptr->d_frequency[i]) == 0) && - ((d_ptr->d_side[i] != 0) || (d_ptr->d_dice[i] != 0))) - { - for (j = 0; j < cur_hgt - 1; j++) - { - for (k = 0; k < cur_wid - 1; k++) - { - int l, dam = 0; - - if (!(dungeon_flags1 & DF1_DAMAGE_FEAT)) - { - /* If the grid is empty, skip it */ - if ((cave[j][k].o_idx == 0) && - ((j != p_ptr->py) && (i != p_ptr->px))) continue; - } - - /* Let's not hurt poor monsters */ - if (cave[j][k].m_idx) continue; - - /* Roll damage */ - for (l = 0; l < d_ptr->d_dice[i]; l++) - { - dam += randint(d_ptr->d_side[i]); - } - - /* Apply damage */ - project( -100, 0, j, k, dam, d_ptr->d_type[i], - PROJECT_KILL | PROJECT_ITEM | PROJECT_HIDE); - } - } - } - } - } - - /* handle spell effects */ - if (!p_ptr->wild_mode) - { - /* - * I noticed significant performance degrade after the introduction - * of staying spell effects. I believe serious optimisation effort - * is required before another release. - * - * More important is to fix that display weirdness... - * - * It seems that the game never expects that monster deaths and - * terrain feature changes should happen here... Moving these - * to process_player() [before resting code, with "every 10 game turn" - * 'if'] may or may not fix the problem... -- pelpel to DG - */ - for (j = 0; j < cur_hgt - 1; j++) - { - for (i = 0; i < cur_wid - 1; i++) - { - int e = cave[j][i].effect; - - if (e) - { - effect_type *e_ptr = &effects[e]; - - if (e_ptr->time) - { - /* Apply damage */ - project(0, 0, j, i, e_ptr->dam, e_ptr->type, - PROJECT_KILL | PROJECT_ITEM | PROJECT_HIDE); - } - else - { - cave[j][i].effect = 0; - } - - if ((e_ptr->flags & EFF_WAVE) && !(e_ptr->flags & EFF_LAST)) - { - if (distance(e_ptr->cy, e_ptr->cx, j, i) < e_ptr->rad - 1) - cave[j][i].effect = 0; - } - else if ((e_ptr->flags & EFF_STORM) && !(e_ptr->flags & EFF_LAST)) - { - cave[j][i].effect = 0; - } - - lite_spot(j, i); - } - } - } - - /* Reduce & handle effects */ - for (i = 0; i < MAX_EFFECTS; i++) - { - /* Skip empty slots */ - if (effects[i].time == 0) continue; - - /* Reduce duration */ - effects[i].time--; - - /* Creates a "wave" effect*/ - if (effects[i].flags & EFF_WAVE) - { - effect_type *e_ptr = &effects[i]; - int x, y, z; - - e_ptr->rad++; - - /* What a frelling ugly line of ifs ... */ - if (effects[i].flags & EFF_DIR8) - for (y = e_ptr->cy - e_ptr->rad, z = 0; y <= e_ptr->cy; y++, z++) - { - for (x = e_ptr->cx - (e_ptr->rad - z); x <= e_ptr->cx + (e_ptr->rad - z); x++) - { - if (!in_bounds(y, x)) continue; - - if (los(e_ptr->cy, e_ptr->cx, y, x) && - (distance(e_ptr->cy, e_ptr->cx, y, x) == e_ptr->rad)) - cave[y][x].effect = i; - } - } - else if (effects[i].flags & EFF_DIR2) - for (y = e_ptr->cy, z = e_ptr->rad; y <= e_ptr->cy + e_ptr->rad; y++, z--) - { - for (x = e_ptr->cx - (e_ptr->rad - z); x <= e_ptr->cx + (e_ptr->rad - z); x++) - { - if (!in_bounds(y, x)) continue; - - if (los(e_ptr->cy, e_ptr->cx, y, x) && - (distance(e_ptr->cy, e_ptr->cx, y, x) == e_ptr->rad)) - cave[y][x].effect = i; - } - } - else if (effects[i].flags & EFF_DIR6) - for (x = e_ptr->cx, z = e_ptr->rad; x <= e_ptr->cx + e_ptr->rad; x++, z--) - { - for (y = e_ptr->cy - (e_ptr->rad - z); y <= e_ptr->cy + (e_ptr->rad - z); y++) - { - if (!in_bounds(y, x)) continue; - - if (los(e_ptr->cy, e_ptr->cx, y, x) && - (distance(e_ptr->cy, e_ptr->cx, y, x) == e_ptr->rad)) - cave[y][x].effect = i; - } - } - else if (effects[i].flags & EFF_DIR4) - for (x = e_ptr->cx - e_ptr->rad, z = 0; x <= e_ptr->cx; x++, z++) - { - for (y = e_ptr->cy - (e_ptr->rad - z); y <= e_ptr->cy + (e_ptr->rad - z); y++) - { - if (!in_bounds(y, x)) continue; - - if (los(e_ptr->cy, e_ptr->cx, y, x) && - (distance(e_ptr->cy, e_ptr->cx, y, x) == e_ptr->rad)) - cave[y][x].effect = i; - } - } - else if (effects[i].flags & EFF_DIR9) - for (y = e_ptr->cy - e_ptr->rad; y <= e_ptr->cy; y++) - { - for (x = e_ptr->cx; x <= e_ptr->cx + e_ptr->rad; x++) - { - if (!in_bounds(y, x)) continue; - - if (los(e_ptr->cy, e_ptr->cx, y, x) && - (distance(e_ptr->cy, e_ptr->cx, y, x) == e_ptr->rad)) - cave[y][x].effect = i; - } - } - else if (effects[i].flags & EFF_DIR1) - for (y = e_ptr->cy; y <= e_ptr->cy + e_ptr->rad; y++) - { - for (x = e_ptr->cx - e_ptr->rad; x <= e_ptr->cx; x++) - { - if (!in_bounds(y, x)) continue; - - if (los(e_ptr->cy, e_ptr->cx, y, x) && - (distance(e_ptr->cy, e_ptr->cx, y, x) == e_ptr->rad)) - cave[y][x].effect = i; - } - } - else if (effects[i].flags & EFF_DIR7) - for (y = e_ptr->cy - e_ptr->rad; y <= e_ptr->cy; y++) - { - for (x = e_ptr->cx - e_ptr->rad; x <= e_ptr->cx; x++) - { - if (!in_bounds(y, x)) continue; - - if (los(e_ptr->cy, e_ptr->cx, y, x) && - (distance(e_ptr->cy, e_ptr->cx, y, x) == e_ptr->rad)) - cave[y][x].effect = i; - } - } - else if (effects[i].flags & EFF_DIR3) - for (y = e_ptr->cy; y <= e_ptr->cy + e_ptr->rad; y++) - { - for (x = e_ptr->cx; x <= e_ptr->cx + e_ptr->rad; x++) - { - if (!in_bounds(y, x)) continue; - - if (los(e_ptr->cy, e_ptr->cx, y, x) && - (distance(e_ptr->cy, e_ptr->cx, y, x) == e_ptr->rad)) - cave[y][x].effect = i; - } - } - else - for (y = e_ptr->cy - e_ptr->rad; y <= e_ptr->cy + e_ptr->rad; y++) - { - for (x = e_ptr->cx - e_ptr->rad; x <= e_ptr->cx + e_ptr->rad; x++) - { - if (!in_bounds(y, x)) continue; - - /* This is *slow* -- pelpel */ - if (los(e_ptr->cy, e_ptr->cx, y, x) && - (distance(e_ptr->cy, e_ptr->cx, y, x) == e_ptr->rad)) - cave[y][x].effect = i; - } - } - } - /* Creates a "storm" effect*/ - else if (effects[i].flags & EFF_STORM) - { - effect_type *e_ptr = &effects[i]; - int x, y; - - e_ptr->cy = p_ptr->py; - e_ptr->cx = p_ptr->px; - for (y = e_ptr->cy - e_ptr->rad; y <= e_ptr->cy + e_ptr->rad; y++) - { - for (x = e_ptr->cx - e_ptr->rad; x <= e_ptr->cx + e_ptr->rad; x++) - { - if (!in_bounds(y, x)) continue; - - if (los(e_ptr->cy, e_ptr->cx, y, x) && - (distance(e_ptr->cy, e_ptr->cx, y, x) <= e_ptr->rad)) - { - cave[y][x].effect = i; - lite_spot(y, x); - } - } - } - } - } - - apply_effect(p_ptr->py, p_ptr->px); - } - - /* Arg cannot breath? */ - if ((dungeon_flags2 & DF2_WATER_BREATH) && (!p_ptr->water_breath)) - { - cmsg_print(TERM_L_RED, "You cannot breathe water! You suffocate!"); - take_hit(damroll(3, p_ptr->lev), "suffocating"); - } - if ((dungeon_flags2 & DF2_NO_BREATH) && (!p_ptr->magical_breath)) - { - cmsg_print(TERM_L_RED, "There is no air there! You suffocate!"); - take_hit(damroll(3, p_ptr->lev), "suffocating"); - } - - /* - * Every 1500 turns, warn about any Black Breath not gotten from - * an equipped object, and stop any resting. -LM- - * - * It's apparent that someone has halved the frequency... -- pelpel - */ - if (((turn % 3000) == 0) && p_ptr->black_breath) - { - u32b f1, f2, f3, f4, f5; - - bool_ be_silent = FALSE; - - /* check all equipment for the Black Breath flag. */ - for (i = INVEN_WIELD; i < INVEN_TOTAL; i++) - { - o_ptr = &p_ptr->inventory[i]; - - /* Skip non-objects */ - if (!o_ptr->k_idx) continue; - - /* Extract the item flags */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* No messages if object has the flag, to avoid annoyance. */ - if (f4 & (TR4_BLACK_BREATH)) be_silent = TRUE; - - } - /* If we are allowed to speak, warn and disturb. */ - - if (!be_silent) - { - cmsg_print(TERM_L_DARK, "The Black Breath saps your soul!"); - disturb(0); - } - } - - - /*** Process Light ***/ - - /* Check for light being wielded */ - o_ptr = &p_ptr->inventory[INVEN_LITE]; - - /* Burn some fuel in the current lite */ - if (o_ptr->tval == TV_LITE) - { - /* Extract the item flags */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* Hack -- Use some fuel */ - if ((f4 & TR4_FUEL_LITE) && (o_ptr->timeout > 0)) - { - /* Decrease life-span */ - o_ptr->timeout--; - - /* Hack -- notice interesting fuel steps */ - if ((o_ptr->timeout < 100) || ((o_ptr->timeout % 100) == 0)) - { - /* Window stuff */ - p_ptr->window |= (PW_EQUIP); - } - - /* Hack -- Special treatment when blind */ - if (p_ptr->blind) - { - /* Hack -- save some light for later */ - if (o_ptr->timeout == 0) o_ptr->timeout++; - } - - /* The light is now out */ - else if (o_ptr->timeout < 1) - { - disturb(0); - cmsg_print(TERM_YELLOW, "Your light has gone out!"); - } - - /* The light is getting dim */ - else if ((o_ptr->timeout < 100) && (o_ptr->timeout % 10 == 0)) - { - if (disturb_minor) disturb(0); - cmsg_print(TERM_YELLOW, "Your light is growing faint."); - } - } - } - - /* Calculate torch radius */ - p_ptr->update |= (PU_TORCH); - - - /*** Process Inventory ***/ - - /* - * Handle experience draining. In Oangband, the effect is worse, - * especially for high-level characters. As per Tolkien, hobbits - * are resistant. - */ - if (p_ptr->black_breath) - { - byte chance = 0; - int plev = p_ptr->lev; - - if (PRACE_FLAG(PR1_RESIST_BLACK_BREATH)) chance = 2; - else chance = 5; - - if ((rand_int(100) < chance) && (p_ptr->exp > 0)) - { - p_ptr->exp -= 1 + plev / 5; - p_ptr->max_exp -= 1 + plev / 5; - (void)do_dec_stat(rand_int(6), STAT_DEC_NORMAL); - check_experience(); - } - } - - /* Drain Mana */ - if (p_ptr->drain_mana && p_ptr->csp) - { - p_ptr->csp -= p_ptr->drain_mana; - if (magik(30)) p_ptr->csp -= p_ptr->drain_mana; - - if (p_ptr->csp < 0) - { - p_ptr->csp = 0; - disturb(0); - } - - /* Redraw */ - p_ptr->redraw |= (PR_MANA); - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - } - - /* Partial summons drain mana */ - if (p_ptr->maintain_sum) - { - u32b oldcsp = p_ptr->csp; - p_ptr->csp -= p_ptr->maintain_sum / 10000; - - if (p_ptr->csp < 0) - { - p_ptr->csp = 0; - disturb(0); - - p_ptr->maintain_sum = 0; - } - else - { - /* Leave behind any fractional sp */ - p_ptr->maintain_sum -= (oldcsp - p_ptr->csp) * 10000; - } - - /* Redraw */ - p_ptr->redraw |= (PR_MANA); - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - - } - - /* Drain Hitpoints */ - if (p_ptr->drain_life) - { - int drain = p_ptr->drain_life + rand_int(p_ptr->mhp / 100); - - p_ptr->chp -= (drain < p_ptr->chp ? drain : p_ptr->chp); - - if (p_ptr->chp == 0) - { - disturb(0); - } - - /* Redraw */ - p_ptr->redraw |= (PR_HP); - - /* Window stuff */ - p_ptr->window |= (PW_PLAYER); - - } - - /* Handle experience draining */ - if (p_ptr->exp_drain) - { - if ((rand_int(100) < 10) && (p_ptr->exp > 0)) - { - p_ptr->exp--; - p_ptr->max_exp--; - check_experience(); - } - } - - /* Process equipment */ - for (j = 0, i = INVEN_WIELD; i < INVEN_TOTAL; i++) - { - /* Get the object */ - o_ptr = &p_ptr->inventory[i]; - - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - - /* TY Curse */ - if ((f3 & TR3_TY_CURSE) && (rand_int(TY_CURSE_CHANCE) == 0)) - { - activate_ty_curse(); - } - - /* DG Curse */ - if ((f4 & TR4_DG_CURSE) && (rand_int(DG_CURSE_CHANCE) == 0)) - { - activate_dg_curse(); - - /* The object recurse itself ! */ - o_ptr->ident |= IDENT_CURSED; - } - - /* Auto Curse */ - if ((f3 & TR3_AUTO_CURSE) && (rand_int(AUTO_CURSE_CHANCE) == 0)) - { - /* The object recurse itself ! */ - o_ptr->ident |= IDENT_CURSED; - } - - /* - * Hack: Uncursed teleporting items (e.g. Dragon Weapons) - * can actually be useful! - */ - if ((f3 & TR3_TELEPORT) && (rand_int(100) < 1)) - { - if ((o_ptr->ident & IDENT_CURSED) && !p_ptr->anti_tele) - { - disturb(0); - - /* Teleport player */ - teleport_player(40); - } - else - { - if (p_ptr->wild_mode || - (o_ptr->note && strchr(quark_str(o_ptr->note), '.'))) - { - /* Do nothing */ - /* msg_print("Teleport aborted.") */; - } - else if (get_check("Teleport? ")) - { - disturb(0); - teleport_player(50); - } - } - } - - - /* Skip non-objects */ - if (!o_ptr->k_idx) continue; - - /* Hack: Skip wielded lights that need fuel (already handled above) */ - if ((i == INVEN_LITE) && (o_ptr->tval == TV_LITE) && (f4 & TR4_FUEL_LITE)) continue; - - /* Recharge activatable objects */ - if (o_ptr->timeout > 0) - { - /* Recharge */ - o_ptr->timeout--; - - /* Notice changes */ - if (o_ptr->timeout == 0) - { - recharged_notice(o_ptr); - j++; - } - } - - /* Recharge second spell in Mage Staffs of Spells */ - if (is_ego_p(o_ptr, EGO_MSTAFF_SPELL) && (o_ptr->xtra2 > 0)) - { - /* Recharge */ - o_ptr->xtra2--; - - /* Notice changes */ - if (o_ptr->xtra2 == 0) j++; - } - } - - /* Notice changes */ - if (j) - { - /* Window stuff */ - p_ptr->window |= (PW_EQUIP); - } - - /* Recharge rods */ - for (j = 0, i = 0; i < INVEN_TOTAL; i++) - { - o_ptr = &p_ptr->inventory[i]; - - /* Skip non-objects */ - if (!o_ptr->k_idx) continue; - - /* Examine the rod */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* Temporary items are destroyed */ - if (f5 & TR5_TEMPORARY) - { - o_ptr->timeout--; - - if (o_ptr->timeout <= 0) - { - inc_stack_size(i, -99); - - /* Combine and Reorder pack */ - p_ptr->notice |= (PN_COMBINE | PN_REORDER); - } - } - - /* Examine all charging rods or stacks of charging rods. */ - if ((o_ptr->tval == TV_ROD_MAIN) && (o_ptr->timeout < o_ptr->pval2)) - { - /* Increase the rod's mana. */ - o_ptr->timeout += (f4 & TR4_CHARGING) ? 2 : 1; - - /* Always notice */ - j++; - - /* Notice changes, provide message if object is inscribed. */ - if (o_ptr->timeout >= o_ptr->pval2) - { - o_ptr->timeout = o_ptr->pval2; - recharged_notice(o_ptr); - } - } - - /* Examine all charging random artifacts */ - if ((f5 & TR5_ACTIVATE_NO_WIELD) && (o_ptr->timeout > 0)) - { - /* Charge it */ - o_ptr->timeout--; - - /* Notice changes */ - if (o_ptr->timeout == 0) - { - j++; - recharged_notice(o_ptr); - } - } - - /* Decay objects in pack */ - if (decays(o_ptr)) - { - /* Decay it */ - if (o_ptr->pval != 0) - { - if (o_ptr->timeout > 0) - { - if (dungeon_flags1 & DF1_HOT) - { - o_ptr->pval -= 2; - } - else if ((dungeon_flags1 & DF1_COLD) && rand_int(2)) - { - if (magik(50)) o_ptr->pval--; - } - else - { - o_ptr->pval--; - } - } - - if ((o_ptr->timeout > 0) && o_ptr->timeout < o_ptr->weight) o_ptr->timeout--; - - /* Notice changes */ - if (o_ptr->pval <= 0) - { - pack_decay(i); - j++; - } - } - } - - /* Hatch eggs */ - if (o_ptr->tval == TV_EGG) - { - int mx, my; - - if (o_ptr->timeout == 0) - { - o_ptr->pval--; - - /* Notice changes */ - if (o_ptr->pval <= 0) - { - monster_type *m_ptr; - monster_race *r_ptr; - - mx = p_ptr->px; - my = p_ptr->py + 1; - get_pos_player(5, &my, &mx); - msg_print("Your egg hatches!"); - place_monster_aux(my, mx, o_ptr->pval2, FALSE, FALSE, MSTATUS_PET); - - m_ptr = &m_list[cave[my][mx].m_idx]; - r_ptr = race_inf(m_ptr); - - if ((r_ptr->flags9 & RF9_IMPRESED) && can_create_companion()) - { - msg_format("And you have given the imprint to your %s!", - r_name + r_ptr->name); - m_ptr->status = MSTATUS_COMPANION; - } - - inc_stack_size(i, -1); - - j++; - } - } - } - } - - /* Notice changes */ - if (j) - { - /* Combine pack */ - p_ptr->notice |= (PN_COMBINE); - - /* Window stuff */ - p_ptr->window |= (PW_INVEN); - } - - /*** Process Objects ***/ - - /* Process objects */ - for (i = 1; i < o_max; i++) - { - /* Access object */ - o_ptr = &o_list[i]; - - /* Skip dead objects */ - if (!o_ptr->k_idx) continue; - - /* Examine the rod */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* Temporary items are destroyed */ - if (f5 & TR5_TEMPORARY) - { - o_ptr->timeout--; - - if (o_ptr->timeout <= 0) - { - floor_item_increase(i, -99); - floor_item_optimize(i); - - /* Combine and Reorder pack */ - p_ptr->notice |= (PN_COMBINE | PN_REORDER); - } - } - - /* Recharge rods on the ground. No messages. */ - if ((o_ptr->tval == TV_ROD_MAIN) && (o_ptr->timeout < o_ptr->pval2)) - { - /* Increase the rod's mana. */ - o_ptr->timeout += (f4 & TR4_CHARGING) ? 2 : 1; - - /* Do not overflow */ - if (o_ptr->timeout >= o_ptr->pval2) - { - o_ptr->timeout = o_ptr->pval2; - } - } - - /* Decay objects on the ground*/ - if (decays(o_ptr)) - { - /* Decay it */ - if (o_ptr->pval != 0) - { - if (o_ptr->timeout > 0) - { - if (dungeon_flags1 & DF1_HOT) - { - o_ptr->pval -= 2; - } - else if ((dungeon_flags1 & DF1_COLD) && rand_int(2)) - { - if (magik(50)) o_ptr->pval--; - } - else - { - o_ptr->pval--; - } - } - - if ((o_ptr->timeout > 0) && o_ptr->timeout < o_ptr->weight) o_ptr->timeout--; - - /* Turn it into a skeleton */ - if (o_ptr->pval <= 0) - { - floor_decay(i); - } - } - } - - /* Hatch eggs */ - if (o_ptr->tval == TV_EGG) - { - int mx, my; - if (o_ptr->timeout > 0) o_ptr->pval--; - - /* Notice changes */ - if (o_ptr->pval <= 0) - { - mx = o_ptr->ix; - my = o_ptr->iy; - get_pos_player(5, &my, &mx); - msg_print("An egg hatches!"); - place_monster_one(my, mx, o_ptr->pval2, 0, FALSE, MSTATUS_ENEMY); - floor_item_increase(i, -1); - floor_item_describe(i); - floor_item_optimize(i); - } - } - } - - - /*** Involuntary Movement ***/ - - /* Delayed Word-of-Recall */ - if (p_ptr->word_recall) - { - /* Can we ? */ - if (process_hooks(HOOK_RECALL, "()", "")) - { - p_ptr->word_recall = 0; - } - - /* No recall. sorry */ - else if (dungeon_flags2 & DF2_NO_RECALL_OUT) - { - cmsg_print(TERM_L_DARK, "You cannot recall from here."); - p_ptr->word_recall = 0; - } - - /* Cannot WoR out of death fate levels */ - else if (dungeon_type == DUNGEON_DEATH) - { - cmsg_print(TERM_L_DARK, "You are fated to die here. FIGHT for your life!"); - p_ptr->word_recall = 0; - } - - /* I think the 'inside_quest' code belongs here -- pelpel */ - - /* They cannot use word of recall until reaching surface */ - else if (p_ptr->astral) - { - msg_print("As an astral being you can't recall."); - p_ptr->word_recall = 0; - } - - /* Normal WoR */ - else - { - /* - * HACK: Autosave BEFORE resetting the recall counter (rr9) - * The player is yanked up/down as soon as - * he loads the autosaved game. - */ - if (p_ptr->word_recall == 1) - { - autosave_checkpoint(); - } - - /* Make SURE that persistent levels are saved - * I don't know if this is needed, but I'm getting reports, - * so I'm adding this extra save -- Neil - */ - save_dungeon(); - - /* Count down towards recall */ - p_ptr->word_recall--; - - /* Activate the recall */ - if (p_ptr->word_recall == 0) - { - /* Disturbing! */ - disturb(0); - - /* Determine the level */ - if (p_ptr->inside_quest) - { - msg_print("The recall is cancelled by a powerful magic force!"); - } - else if (dun_level) - { - msg_print("You feel yourself yanked upwards!"); - - p_ptr->recall_dungeon = dungeon_type; - dungeon_type = DUNGEON_WILDERNESS; - dun_level = 0; - - is_recall = TRUE; - - p_ptr->inside_quest = 0; - p_ptr->leaving = TRUE; - } - else - { - msg_print("You feel yourself yanked downwards!"); - - /* New depth */ - dungeon_type = p_ptr->recall_dungeon; - dun_level = max_dlv[dungeon_type]; - if (dun_level < 1) dun_level = 1; - - /* Reset player position */ - p_ptr->oldpx = p_ptr->px; - p_ptr->oldpy = p_ptr->py; - - /* Leaving */ - is_recall = TRUE; - - p_ptr->leaving = TRUE; - p_ptr->wild_mode = FALSE; - } - - /* Sound */ - sound(SOUND_TPLEVEL); - } - } - } -} - - -/* - * Verify use of "wizard" mode - */ -static bool_ enter_wizard_mode(void) -{ - /* Ask first time, but not while loading a dead char with the -w option */ - if (!noscore && !(p_ptr->chp < 0)) - { - /* Mention effects */ - msg_print("Wizard mode is for debugging and experimenting."); - msg_print("The game will not be scored if you enter wizard mode."); - msg_print(NULL); - - /* Verify request */ - if (!get_check("Are you sure you want to enter wizard mode? ")) - { - return (FALSE); - } - - /* Mark savefile */ - noscore |= 0x0002; - } - - /* Success */ - return (TRUE); -} - - -/* - * Verify use of "debug" commands - */ -static bool_ enter_debug_mode(void) -{ - /* Ask first time */ - if (!noscore && !wizard) - { - /* Mention effects */ - msg_print("The debug commands are for debugging and experimenting."); - msg_print("The game will not be scored if you use debug commands."); - msg_print(NULL); - - /* Verify request */ - if (!get_check("Are you sure you want to use debug commands? ")) - { - return (FALSE); - } - - /* Mark savefile */ - noscore |= 0x0008; - } - - /* Success */ - return (TRUE); -} - - -/* - * Parse and execute the current command - * Give "Warning" on illegal commands. - * - * XXX XXX XXX Make some "blocks" - */ -static void process_command(void) -{ - char error_m[80]; - - /* Handle repeating the last command */ - repeat_check(); - - /* Process the appropriate hooks */ - if (process_hooks(HOOK_KEYPRESS, "(d)", command_cmd)) return; - - /* Parse the command */ - switch (command_cmd) - { - /* Ignore */ - case ESCAPE: - case ' ': - case 0: - { - break; - } - - /* Ignore return */ - case '\r': - { - break; - } - - - - /*** Wizard Commands ***/ - - /* Toggle Wizard Mode */ - case KTRL('W'): - { - if (wizard) - { - wizard = FALSE; - msg_print("Wizard mode off."); - } - else if (enter_wizard_mode()) - { - wizard = TRUE; - msg_print("Wizard mode on."); - } - - /* Update monsters */ - p_ptr->update |= (PU_MONSTERS); - - /* Redraw "title" */ - p_ptr->redraw |= (PR_TITLE); - - break; - } - - /* Special "debug" commands */ - case KTRL('A'): - { - /* Enter debug mode */ - if (enter_debug_mode()) - { - do_cmd_debug(); - } - break; - } - - - /*** Inventory Commands ***/ - - /* Wear/wield equipment */ - case 'w': - { - if (p_ptr->control) break; - if (!p_ptr->wild_mode) do_cmd_wield(); - break; - } - - /* Take off equipment */ - case 't': - { - if (p_ptr->control) break; - if (!p_ptr->wild_mode) do_cmd_takeoff(); - p_ptr->redraw |= (PR_MH); - break; - } - - /* Drop an item */ - case 'd': - { - if (do_control_drop()) break; - if (!p_ptr->wild_mode) do_cmd_drop(); - break; - } - - /* Destroy an item */ - case 'k': - { - if (p_ptr->control) break; - do_cmd_destroy(); - break; - } - - /* Equipment list */ - case 'e': - { - if (p_ptr->control) break; - do_cmd_equip(); - break; - } - - /* Inventory list */ - case 'i': - { - if (do_control_inven()) break; - do_cmd_inven(); - break; - } - - - /*** Various commands ***/ - - /* Identify an object */ - case 'I': - { - do_cmd_observe(); - break; - } - - /* Hack -- toggle windows */ - case KTRL('I'): - { - toggle_inven_equip(); - break; - } - - - /*** Standard "Movement" Commands ***/ - - /* Alter a grid */ - case '+': - { - if (p_ptr->control) break; - if (!p_ptr->wild_mode) do_cmd_alter(); - break; - } - - /* Dig a tunnel */ - case 'T': - { - if (p_ptr->control) break; - if (!p_ptr->wild_mode) do_cmd_tunnel(); - break; - } - - /* Move (usually pick up things) */ - case ';': - { - if (do_control_walk()) break; - - do_cmd_walk(always_pickup, TRUE); - - break; - } - - /* Move (usually do not pick up) */ - case '-': - { - if (do_control_walk()) break; - - do_cmd_walk(!always_pickup, TRUE); - - break; - } - - - /*** Running, Resting, Searching, Staying */ - - /* Begin Running -- Arg is Max Distance */ - case '.': - { - if (p_ptr->control || p_ptr->wild_mode) break; - do_cmd_run(); - break; - } - - /* Stay still (usually pick things up) */ - case ',': - { - if (do_control_pickup()) break; - do_cmd_stay(always_pickup); - break; - } - - /* Stay still (usually do not pick up) */ - case 'g': - { - if (p_ptr->control) break; - do_cmd_stay(!always_pickup); - break; - } - - /* Rest -- Arg is time */ - case 'R': - { - if (p_ptr->control) break; - do_cmd_rest(); - break; - } - - /* Search for traps/doors */ - case 's': - { - if (p_ptr->control) break; - do_cmd_search(); - break; - } - - /* Toggle search mode */ - case 'S': - { - if (p_ptr->control) break; - do_cmd_toggle_search(); - break; - } - - - /*** Stairs and Doors and Chests and Traps ***/ - - /* Enter store */ - case '_': - { - if (p_ptr->control) break; - if (!p_ptr->wild_mode) do_cmd_store(); - break; - } - - /* Go up staircase */ - case '<': - { - object_type *o_ptr; - u32b f1 = 0 , f2 = 0 , f3 = 0, f4 = 0, f5 = 0, esp = 0; - - - /* Check for light being wielded */ - o_ptr = &p_ptr->inventory[INVEN_LITE]; - /* Burn some fuel in the current lite */ - if (o_ptr->tval == TV_LITE) - /* Extract the item flags */ - object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); - - /* Cannot move if rooted in place */ - if (p_ptr->tim_roots) break; - - if (p_ptr->control) break; - /* Normal cases */ - if (p_ptr->wild_mode || dun_level || is_quest(dun_level)) - { - do_cmd_go_up(); - } - /* Don't let the player < when he'd just drop right back down */ - else if (p_ptr->food < PY_FOOD_ALERT) - { - msg_print("You are too hungry to travel."); - } - else if (p_ptr->sensible_lite && - (((turn / ((10L * DAY) / 2)) % 2) == 0)) - { - /* Burn vampires! burn! */ - msg_print("You can't travel during the day!"); - } - else if (p_ptr->sensible_lite && - (o_ptr->tval != 0) && - (o_ptr->sval >= SV_LITE_GALADRIEL) && - (o_ptr->sval <= SV_STONE_LORE) && - (o_ptr->sval != SV_LITE_UNDEATH)) - { - msg_print("Travel with your present light would be unsafe."); - } - else if (p_ptr->cut || p_ptr->poisoned) - { - /* I actually died this way once -- neil */ - msg_print("You are too injured to travel."); - } - else if (ambush_flag) - { - msg_print("To flee the ambush you have to reach the edge of the map."); - } - /* TODO: make the above stuff use this hook */ - else if (!process_hooks(HOOK_FORBID_TRAVEL, "()")) - { - p_ptr->oldpx = p_ptr->px; - p_ptr->oldpy = p_ptr->py; - change_wild_mode(); - - /* Update the known wilderness */ - reveal_wilderness_around_player(p_ptr->wilderness_y, - p_ptr->wilderness_x, - 0, WILDERNESS_SEE_RADIUS); - } - - break; - } - - /* Go down staircase */ - case '>': - { - /* Cannot move if rooted in place */ - if (p_ptr->tim_roots) break; - - if (p_ptr->control) break; - /* Normal cases */ - if (!p_ptr->wild_mode) - { - do_cmd_go_down(); - } - - /* Special cases */ - else - { - if ((wf_info[wild_map[p_ptr->py][p_ptr->px].feat].entrance >= 1000) || - (wild_map[p_ptr->py][p_ptr->px].entrance > 1000)) - { - p_ptr->wilderness_x = p_ptr->px; - p_ptr->wilderness_y = p_ptr->py; - p_ptr->wild_mode = !p_ptr->wild_mode; - do_cmd_go_down(); - - if (dun_level == 0) - { - p_ptr->wild_mode = !p_ptr->wild_mode; - } - else - { - p_ptr->wilderness_x = p_ptr->px; - p_ptr->wilderness_y = p_ptr->py; - change_wild_mode(); - } - } - else - { - p_ptr->wilderness_x = p_ptr->px; - p_ptr->wilderness_y = p_ptr->py; - change_wild_mode(); - } - } - - break; - } - - /* Open a door or chest */ - case 'o': - { - if (p_ptr->control) break; - if (!p_ptr->wild_mode) do_cmd_open(); - break; - } - - /* Close a door */ - case 'c': - { - if (p_ptr->control) break; - if (!p_ptr->wild_mode) do_cmd_close(); - break; - } - - /* Give an item */ - case 'y': - { - if (p_ptr->control) break; - if (!p_ptr->wild_mode) do_cmd_give(); - break; - } - - /* Chat */ - case 'Y': - { - if (p_ptr->control) break; - if (!p_ptr->wild_mode) do_cmd_chat(); - break; - } - - /* Jam a door with spikes */ - case 'j': - { - if (p_ptr->control) break; - if (!p_ptr->wild_mode) do_cmd_spike(); - break; - } - - /* Bash a door */ - case 'B': - { - if (p_ptr->control) break; - if (!p_ptr->wild_mode) do_cmd_bash(); - break; - } - - /* Disarm a trap or chest */ - case 'D': - { - if (p_ptr->control) break; - if (!p_ptr->wild_mode) do_cmd_disarm(); - break; - } - - - /*** Magic and Prayers ***/ - - /* Interact with skills */ - case 'G': - { - if (p_ptr->control) break; - do_cmd_skill(); - break; - } - - /* Interact with abilities */ - case 'N': - { - if (p_ptr->control) break; - do_cmd_ability(); - break; - } - - /* Browse a book */ - case 'b': - { - if (p_ptr->control) break; - do_cmd_browse(); - break; - } - - /* Cast a spell */ - case 'm': - { - if (do_control_magic()) break; - - /* No magic in the overworld map */ - if (p_ptr->wild_mode) break; - - /* Neither in the Arena */ - if (p_ptr->inside_arena) - { - msg_print("The arena absorbs all attempted magic!"); - - break; - } - do_cmd_activate_skill(); - squeltch_inventory(); - squeltch_grid(); - break; - } - - /* Pray a prayer */ - case 'p': - { - if (p_ptr->control || p_ptr->wild_mode) break; - do_cmd_pray(); - squeltch_inventory(); - squeltch_grid(); - break; - } - - /* Issue commands to pets */ - case 'P': - { - if (p_ptr->control) break; - if (!p_ptr->wild_mode) do_cmd_pet(); - break; - } - - /* Cut up a corpse */ - case 'h': - { - if (p_ptr->control || p_ptr->wild_mode) break; - do_cmd_cut_corpse(); - squeltch_inventory(); - squeltch_grid(); - break; - } - - /* Cure some meat */ - case 'K': - { - if (p_ptr->control) break; - do_cmd_cure_meat(); - squeltch_inventory(); - squeltch_grid(); - break; - } - - /* Steal an item form a monster */ - case 'Z': - { - if (p_ptr->control || p_ptr->wild_mode) break; - do_cmd_steal(); - squeltch_inventory(); - squeltch_grid(); - break; - } - - /*** Use various objects ***/ - - /* Inscribe an object */ - case '{': - { - if (p_ptr->control) break; - do_cmd_inscribe(); - break; - } - - /* Uninscribe an object */ - case '}': - { - if (p_ptr->control) break; - do_cmd_uninscribe(); - break; - } - - /* Activate an artifact */ - case 'A': - { - if (p_ptr->control) break; - if (p_ptr->wild_mode) break; - - if (p_ptr->inside_arena) - { - msg_print("The arena absorbs all attempted magic!"); - msg_print(NULL); - break; - } - - do_cmd_activate(); - squeltch_inventory(); - squeltch_grid(); - break; - } - - /* Eat some food */ - case 'E': - { - if (p_ptr->control) break; - do_cmd_eat_food(); - break; - } - - /* Fuel your lantern/torch */ - case 'F': - { - if (p_ptr->control) break; - do_cmd_refill(); - break; - } - - /* Fire an item */ - case 'f': - { - object_type *j_ptr; - - if (p_ptr->control) break; - if (p_ptr->wild_mode) break; - - if (p_ptr->inside_arena) - { - msg_print("You're in the arena now. This is hand-to-hand!"); - msg_print(NULL); - break; - } - - j_ptr = &p_ptr->inventory[INVEN_BOW]; - - if (process_hooks(HOOK_FIRE, "(O)", j_ptr)) - break; - - if (j_ptr->tval == TV_BOOMERANG) - { - do_cmd_boomerang(); - } - else - { - do_cmd_fire(); - } - - break; - } - - /* Throw an item */ - case 'v': - { - if (p_ptr->control) break; - if (p_ptr->wild_mode) break; - - if (p_ptr->inside_arena) - { - msg_print("You're in the arena now. This is hand-to-hand!"); - msg_print(NULL); - break; - } - - do_cmd_throw(); - break; - } - - /* Aim a wand */ - case 'a': - { - if (p_ptr->control) break; - if (p_ptr->wild_mode) break; - - if (p_ptr->inside_arena) - { - msg_print("The arena absorbs all attempted magic!"); - msg_print(NULL); - break; - } - - do_cmd_aim_wand(); - squeltch_inventory(); - squeltch_grid(); - break; - } - - /* Zap a rod */ - case 'z': - { - if (p_ptr->control) break; - if (p_ptr->wild_mode) break; - - if (p_ptr->inside_arena) - { - msg_print("The arena absorbs all attempted magic!"); - msg_print(NULL); - break; - } - - do_cmd_zap_rod(); - squeltch_inventory(); - squeltch_grid(); - break; - } - - /* Quaff a potion */ - case 'q': - { - if (p_ptr->control) break; - if (p_ptr->wild_mode) break; - - if (p_ptr->inside_arena) - { - msg_print("The arena absorbs all attempted magic!"); - msg_print(NULL); - break; - } - - do_cmd_quaff_potion(); - squeltch_inventory(); - squeltch_grid(); - break; - } - - /* Drink from a fountain -SC- */ - case 'H': - { - cave_type *c_ptr = &cave[p_ptr->py][p_ptr->px]; - - if (p_ptr->control) break; - if ((c_ptr->feat == FEAT_FOUNTAIN) || - (c_ptr->feat == FEAT_EMPTY_FOUNTAIN)) - { - do_cmd_drink_fountain(); - squeltch_inventory(); - squeltch_grid(); - } - else - { - msg_print("You see no fountain here."); - } - - break; - } - - /* Read a scroll */ - case 'r': - { - if (p_ptr->control) break; - if (p_ptr->wild_mode) break; - - if (p_ptr->inside_arena) - { - msg_print("The arena absorbs all attempted magic!"); - msg_print(NULL); - break; - } - - do_cmd_read_scroll(); - squeltch_inventory(); - squeltch_grid(); - break; - } - - /* Use a staff */ - case 'u': - { - if (p_ptr->control) break; - if (p_ptr->wild_mode) break; - - if (p_ptr->inside_arena) - { - msg_print("The arena absorbs all attempted magic!"); - msg_print(NULL); - break; - } - - do_cmd_use_staff(); - squeltch_inventory(); - squeltch_grid(); - break; - } - - /* Use racial power */ - case 'U': - { - if (p_ptr->control) break; - if (p_ptr->wild_mode) break; - - if (p_ptr->inside_arena) - { - msg_print("The arena absorbs all attempted magic!"); - msg_print(NULL); - break; - } - - do_cmd_power(); - squeltch_inventory(); - squeltch_grid(); - break; - } - - /* Sacrifice at an altar */ - case 'O': - { - if (p_ptr->control) break; - if (p_ptr->wild_mode) break; - - if (PRACE_FLAG(PR1_NO_GOD)) - { - msg_print("You cannot worship gods."); - } - else - { - do_cmd_sacrifice(); - } - - break; - } - - /*** Looking at Things (nearby or on map) ***/ - - /* Full dungeon map */ - case 'M': - { - if (!p_ptr->wild_mode) do_cmd_view_map(); - break; - } - - /* Locate player on map */ - case 'L': - { - do_cmd_locate(); - break; - } - - /* Look around */ - case 'l': - { - do_cmd_look(); - break; - } - - /* Target monster or location */ - case '*': - { - if (p_ptr->control) break; - if (!p_ptr->wild_mode) do_cmd_target(); - break; - } - - /* Engrave the floor */ - case 'x': - { - if (p_ptr->control) break; - if (p_ptr->wild_mode) break; - - /* No point in engraving if there isn't any mana on this grid. */ - /* DG - actualy there is, it doesnt break macros */ - do_cmd_sense_grid_mana(); - do_cmd_engrave(); - - break; - } - - /*** Help and Such ***/ - - /* Help */ - case '?': - { - do_cmd_help(); - break; - } - - /* Identify symbol */ - case '/': - { - do_cmd_query_symbol(); - break; - } - - /* Character description */ - case 'C': - { - do_cmd_change_name(); - break; - } - - - /*** System Commands ***/ - - /* Hack -- User interface */ - case '!': - { - (void)Term_user(0); - break; - } - - /* Single line from a pref file */ - case '"': - { - do_cmd_pref(); - break; - } - - /* Interact with macros */ - case '@': - { - do_cmd_macros(); - break; - } - - /* Interact with visuals */ - case '%': - { - do_cmd_visuals(); - break; - } - - /* Interact with colors */ - case '&': - { - do_cmd_colors(); - break; - } - - /* Interact with options */ - case '=': - { - do_cmd_options(); - break; - } - - - /*** Misc Commands ***/ - - /* Take notes */ - case ':': - { - do_cmd_note(); - break; - } - - /* Version info */ - case 'V': - { - do_cmd_version(); - break; - } - - /* Repeat level feeling */ - case KTRL('F'): - { - if (!p_ptr->wild_mode) - do_cmd_feeling(); - break; - } - - /* Show previous message */ - case KTRL('O'): - { - do_cmd_message_one(); - break; - } - - /* Show previous messages */ - case KTRL('P'): - { - do_cmd_messages(); - break; - } - - /* Show quest status -KMW- */ - case KTRL('Q'): - case CMD_QUEST: -{ - do_cmd_checkquest(); - break; - } - - /* Redraw the screen */ - case KTRL('R'): - { - do_cmd_redraw(); - break; - } - - /* Hack -- Save and don't quit */ - case KTRL('S'): - { - is_autosave = FALSE; - do_cmd_save_game(); - break; - } - - case KTRL('T'): - { - do_cmd_time(); - } - break; - - /* Save and quit */ - case KTRL('X'): - { - alive = FALSE; - - /* Leaving */ - p_ptr->leaving = TRUE; - - break; - } - - /* Quit (commit suicide) */ - case 'Q': - { - do_cmd_suicide(); - break; - } - - /* Activate cmovie */ - case '|': - { - /* Stop ? */ - if (do_movies == 1) - { - do_stop_cmovie(); - msg_print("Cmovie recording stopped."); - } - else - { - do_start_cmovie(); - } - break; - } - - /* Extended command */ - case '#': - { - do_cmd_cli(); - break; - } - - /* Check artifacts, uniques, objects */ - case '~': - { - do_cmd_knowledge(); - break; - } - - /* Commands only available as extended commands: */ - - /* Extended command help. */ - case CMD_CLI_HELP: - { - do_cmd_cli_help(); - break; - } - - /* Game time. */ - case CMD_SHOW_TIME: - { - do_cmd_time(); - break; - } - - /* Check skills. */ - case CMD_SHOW_SKILL: - { - do_cmd_skill(); - break; - } - - /* Check abilities. */ - case CMD_SHOW_ABILITY: - { - do_cmd_ability(); - break; - } - - /* Save a html screenshot. */ - case CMD_DUMP_HTML: - { - do_cmd_html_dump(); - break; - } - - /* Record a macro. */ - case '$': - case CMD_MACRO: - { - do_cmd_macro_recorder(); - break; - } - case CMD_BLUNDER: - { - if (do_control_walk()) break; - do_cmd_walk(always_pickup, FALSE); - break; - } - /* Hack -- Unknown command */ - default: - { - int insanity = (p_ptr->msane - p_ptr->csane) * 100 / p_ptr->msane; - - /* Would like to have an option disabling this -- pelpel */ - if (rand_int(100) < insanity) - { - get_rnd_line("error.txt", error_m); - sound(SOUND_ILLEGAL); - msg_print(error_m); - } - else - { - prt("Type '?' for help.", 0, 0); - } - - break; - } - } -} - - - - -/* - * Process the player - * - * Notice the annoying code to handle "pack overflow", which - * must come first just in case somebody manages to corrupt - * the savefiles by clever use of menu commands or something. - */ -void process_player(void) -{ - int i, j; - - int speed_use; - - - /*** Apply energy ***/ - - /* Obtain current speed */ - speed_use = p_ptr->pspeed; - - /* Maximum value */ - if (speed_use > 199) - { - speed_use = 199; - } - - /* Minimum value */ - else if (speed_use < 0) - { - speed_use = 0; - } - - /* Give the player some energy */ - p_ptr->energy += extract_energy[speed_use]; - - /* No turn yet */ - if (p_ptr->energy < 100) return; - - - /*** Check for interupts ***/ - - /* Complete resting */ - if (resting < 0) - { - /* Basic resting */ - if (resting == -1) - { - /* Stop resting */ - if ((p_ptr->chp == p_ptr->mhp) && (p_ptr->csp >= p_ptr->msp)) - { - disturb(0); - } - } - - /* Complete resting */ - else if (resting == -2) - { - bool_ stop = TRUE; - object_type *o_ptr; - - /* Get the carried monster */ - o_ptr = &p_ptr->inventory[INVEN_CARRY]; - - /* Stop resting */ - if ((!p_ptr->drain_life) && (p_ptr->chp != p_ptr->mhp)) stop = FALSE; - if ((!p_ptr->drain_mana) && (p_ptr->csp != p_ptr->msp)) stop = FALSE; - if (o_ptr->pval2 < o_ptr->pval3) stop = FALSE; - if (p_ptr->blind || p_ptr->confused) stop = FALSE; - if (p_ptr->poisoned || p_ptr->afraid) stop = FALSE; - if (p_ptr->stun || p_ptr->cut) stop = FALSE; - if (p_ptr->slow || p_ptr->paralyzed) stop = FALSE; - if (p_ptr->image || p_ptr->word_recall) stop = FALSE; - if (p_ptr->immov_cntr != 0) stop = FALSE; - - for (i = 0; i < 6; i++) - { - if (p_ptr->stat_cnt[i] > 0) stop = FALSE; - } - - if (stop) - { - disturb(0); - } - p_ptr->redraw |= (PR_STATE); - } - } - - /* Handle "abort" */ - if (!avoid_abort) - { - /* Check for "player abort" (semi-efficiently for resting) */ - if (running || command_rep || (resting && !(resting & 0x0F))) - { - /* Do not wait */ - inkey_scan = TRUE; - - /* Check for a key */ - if (inkey()) - { - /* Flush input */ - flush(); - - /* Disturb */ - disturb(0); - - /* Hack -- Show a Message */ - msg_print("Cancelled."); - } - } - } - - - /*** Handle actual user input ***/ - - /* Repeat until out of energy */ - while (p_ptr->energy >= 100) - { - /* Notice stuff (if needed) */ - if (p_ptr->notice) notice_stuff(); - - /* Update stuff (if needed) */ - if (p_ptr->update) update_stuff(); - - /* Redraw stuff (if needed) */ - if (p_ptr->redraw) redraw_stuff(); - - /* Redraw stuff (if needed) */ - if (p_ptr->window) window_stuff(); - - /* Hack -- mark current wilderness location as known */ - if (!p_ptr->wild_mode && dun_level == 0) - wild_map[p_ptr->wilderness_y][p_ptr->wilderness_x].known = TRUE; - - - /* Place the cursor on the player */ - move_cursor_relative(p_ptr->py, p_ptr->px); - - /* Refresh (optional) */ - if (fresh_before) Term_fresh(); - - /* Hack -- Pack Overflow */ - if (p_ptr->inventory[INVEN_PACK].k_idx) - { - int item = INVEN_PACK; - - char o_name[80]; - - object_type *o_ptr; - - /* Access the slot to be dropped */ - o_ptr = &p_ptr->inventory[item]; - - /* Disturbing */ - disturb(0); - - /* Warning */ - msg_print("Your pack overflows!"); - - /* Describe */ - object_desc(o_name, o_ptr, TRUE, 3); - - /* Message */ - msg_format("You drop %s (%c).", o_name, index_to_label(item)); - - /* Drop it (carefully) near the player */ - drop_near(o_ptr, 0, p_ptr->py, p_ptr->px); - - /* Modify, Describe, Optimize */ - inc_stack_size(item, -255); - - /* Notice stuff (if needed) */ - if (p_ptr->notice) notice_stuff(); - - /* Update stuff (if needed) */ - if (p_ptr->update) update_stuff(); - - /* Redraw stuff (if needed) */ - if (p_ptr->redraw) redraw_stuff(); - - /* Redraw stuff (if needed) */ - if (p_ptr->window) window_stuff(); - } - - - /* Assume free turn */ - energy_use = 0; - - - /* Paralyzed or Knocked Out */ - if ((p_ptr->paralyzed) || (p_ptr->stun >= 100)) - { - /* Take a turn */ - energy_use = 100; - } - - /* Resting */ - else if (resting) - { - /* Timed rest */ - if (resting > 0) - { - /* Reduce rest count */ - resting--; - - /* Redraw the state */ - p_ptr->redraw |= (PR_STATE); - } - - p_ptr->did_nothing = TRUE; - - /* Take a turn */ - energy_use = 100; - } - - /* Running */ - else if (running) - { - /* Take a step */ - run_step(0); - - /* - * Commented out because it doesn't make any sense - * to require a player holding down direction keys - * instead of using running commands when s/he follows - * Eru and do the opposite for the other deities -- pelpel - */ - /* p_ptr->did_nothing = TRUE; */ - } - - /* Repeated command */ - else if (command_rep) - { - /* Count this execution */ - command_rep--; - - /* Redraw the state */ - p_ptr->redraw |= (PR_STATE); - - /* Redraw stuff */ - redraw_stuff(); - - /* Hack -- Assume messages were seen */ - msg_flag = FALSE; - - /* Clear the top line */ - prt("", 0, 0); - - /* Process the command */ - process_command(); - - p_ptr->did_nothing = TRUE; - } - - /* Normal command */ - else - { - /* Place the cursor on the player */ - move_cursor_relative(p_ptr->py, p_ptr->px); - - /* Get a command (normal) */ - request_command(FALSE); - - /* Process the command */ - process_command(); - } - - - /*** Clean up ***/ - - /* Significant */ - if (energy_use) - { - /* Use some energy */ - p_ptr->energy -= energy_use; - - - /* Hack -- constant hallucination */ - if (p_ptr->image) p_ptr->redraw |= (PR_MAP); - - - /* Shimmer monsters if needed */ - if (!avoid_other && !use_graphics && shimmer_monsters) - { - /* Clear the flag */ - shimmer_monsters = FALSE; - - /* Shimmer multi-hued monsters */ - for (i = 1; i < m_max; i++) - { - monster_type *m_ptr; - monster_race *r_ptr; - - /* Access monster */ - m_ptr = &m_list[i]; - - /* Skip dead monsters */ - if (!m_ptr->r_idx) continue; - - /* Access the monster race */ - r_ptr = race_inf(m_ptr); - - /* Skip non-multi-hued monsters */ - if (!(r_ptr->flags1 & (RF1_ATTR_MULTI))) continue; - - /* Reset the flag */ - shimmer_monsters = TRUE; - - /* Redraw regardless */ - lite_spot(m_ptr->fy, m_ptr->fx); - } - } - - /* Shimmer objects if needed and requested */ - if (!avoid_other && !avoid_shimmer && !use_graphics && - shimmer_objects) - { - /* Clear the flag */ - shimmer_objects = FALSE; - - /* Shimmer multi-hued objects */ - for (i = 1; i < o_max; i++) - { - /* Acquire object -- for speed only base items are allowed to shimmer */ - object_type *o_ptr = &o_list[i]; - object_kind *k_ptr = &k_info[o_ptr->k_idx]; - - /* Skip dead or carried objects */ - if ((!o_ptr->k_idx) || (!o_ptr->ix)) continue; - - /* Skip non-multi-hued monsters */ - if (!(k_ptr->flags5 & (TR5_ATTR_MULTI))) continue; - - /* Reset the flag */ - shimmer_objects = TRUE; - - /* Redraw regardless */ - lite_spot(o_ptr->iy, o_ptr->ix); - } - } - - /* - * Shimmer features if needed and requested - * - * Note: this can be unbearably slow when a player chooses - * to use a REALLY big screen in levels filled with shallow - * water. I believe this also hurts a lot on multiuser systems. - * However fast modern processors are, I/O cannot be made that - * fast, and that's why shimmering has been limited to small - * number of monsters -- pelpel - */ - if (!avoid_other && !avoid_shimmer && !use_graphics && - !resting && !running) - { - for (j = panel_row_min; j <= panel_row_max; j++) - { - for (i = panel_col_min; i <= panel_col_max; i++) - { - cave_type *c_ptr = &cave[j][i]; - feature_type *f_ptr; - - /* Apply terrain feature mimics */ - if (c_ptr->mimic) - { - f_ptr = &f_info[c_ptr->mimic]; - } - else - { - f_ptr = &f_info[f_info[c_ptr->feat].mimic]; - } - - /* Skip normal features */ - if (!(f_ptr->flags1 & (FF1_ATTR_MULTI))) continue; - - /* Redraw a shimmering spot */ - lite_spot(j, i); - } - } - } - - - /* Handle monster detection */ - if (repair_monsters) - { - /* Reset the flag */ - repair_monsters = FALSE; - - /* Rotate detection flags */ - for (i = 1; i < m_max; i++) - { - monster_type *m_ptr; - - /* Access monster */ - m_ptr = &m_list[i]; - - /* Skip dead monsters */ - if (!m_ptr->r_idx) continue; - - /* Nice monsters get mean */ - if (m_ptr->mflag & (MFLAG_NICE)) - { - /* Nice monsters get mean */ - m_ptr->mflag &= ~(MFLAG_NICE); - } - - /* Handle memorized monsters */ - if (m_ptr->mflag & (MFLAG_MARK)) - { - /* Maintain detection */ - if (m_ptr->mflag & (MFLAG_SHOW)) - { - /* Forget flag */ - m_ptr->mflag &= ~(MFLAG_SHOW); - - /* Still need repairs */ - repair_monsters = TRUE; - } - - /* Remove detection */ - else - { - /* Forget flag */ - m_ptr->mflag &= ~(MFLAG_MARK); - - /* Assume invisible */ - m_ptr->ml = FALSE; - - /* Update the monster */ - update_mon(i, FALSE); - - /* Redraw regardless */ - lite_spot(m_ptr->fy, m_ptr->fx); - } - } - } - } - - /* - * Moved from dungeon() -- It'll get called whenever player - * spends energy, so that maze isn't incredibly easy for - * Sorcerors and alike any longer -- pelpel - * - * Forget everything when requested hehe I'm *NASTY* - */ - if (dun_level && (dungeon_flags1 & DF1_FORGET)) - { - wiz_dark(); - } - } - - - /* Hack -- notice death */ - if (!alive || death) break; - - /* Handle "leaving" */ - if (p_ptr->leaving) break; - } -} - - - -/* - * Interact with the current dungeon level. - * - * This function will not exit until the level is completed, - * the user dies, or the game is terminated. - */ -static void dungeon(void) -{ - /* Reset various flags */ - hack_mind = FALSE; - - /* Not leaving */ - p_ptr->leaving = FALSE; - - /* Reset the "command" vars */ - command_cmd = 0; - command_new = 0; - command_rep = 0; - command_arg = 0; - command_dir = 0; - - /* Make sure partial summoning counter is initialized. */ - p_ptr->maintain_sum = 0; - - /* Cancel the target */ - target_who = 0; - - /* Cancel the health bar */ - health_track(0); - - - /* Check visual effects */ - shimmer_monsters = TRUE; - shimmer_objects = TRUE; - repair_monsters = TRUE; - repair_objects = TRUE; - - - /* Disturb */ - disturb(1); - - /* Track maximum player level */ - if (p_ptr->max_plv < p_ptr->lev) - { - p_ptr->max_plv = p_ptr->lev; - } - - /* Track maximum dungeon level (if not in quest -KMW-) */ - if ((max_dlv[dungeon_type] < dun_level) && !p_ptr->inside_quest) - { - max_dlv[dungeon_type] = dun_level; - } - - /* No stairs down from Quest */ - if (is_quest(dun_level) && !p_ptr->astral) - { - create_down_stair = FALSE; - create_down_shaft = FALSE; - } - - /* Paranoia -- no stairs from town or wilderness */ - if (!dun_level) create_down_stair = create_up_stair = FALSE; - if (!dun_level) create_down_shaft = create_up_shaft = FALSE; - - /* Option -- no connected stairs */ - if (!dungeon_stair) create_down_stair = create_up_stair = FALSE; - if (!dungeon_stair) create_down_shaft = create_up_shaft = FALSE; - - /* no connecting stairs on special levels */ - if (!(dungeon_flags2 & DF2_NO_STAIR)) create_down_stair = create_up_stair = FALSE; - if (!(dungeon_flags2 & DF2_NO_STAIR)) create_down_shaft = create_up_shaft = FALSE; - - /* Make a stairway. */ - if ((create_up_stair || create_down_stair || - create_up_shaft || create_down_shaft) && - !get_fbranch()) - { - /* Place a stairway */ - if (cave_valid_bold(p_ptr->py, p_ptr->px)) - { - /* XXX XXX XXX */ - delete_object(p_ptr->py, p_ptr->px); - - /* Make stairs */ - if (create_down_stair) - { - cave_set_feat(p_ptr->py, p_ptr->px, (dungeon_flags1 & DF1_FLAT) ? FEAT_WAY_MORE : FEAT_MORE); - } - else if (create_down_shaft) - { - cave_set_feat(p_ptr->py, p_ptr->px, (dungeon_flags1 & DF1_FLAT) ? FEAT_WAY_MORE : FEAT_SHAFT_DOWN); - } - else if (create_up_shaft) - { - cave_set_feat(p_ptr->py, p_ptr->px, (dungeon_flags1 & DF1_FLAT) ? FEAT_WAY_LESS : FEAT_SHAFT_UP); - } - else - { - cave_set_feat(p_ptr->py, p_ptr->px, (dungeon_flags1 & DF1_FLAT) ? FEAT_WAY_LESS : FEAT_LESS); - } - } - - /* Cancel the stair request */ - create_down_stair = create_up_stair = FALSE; - create_down_shaft = create_up_shaft = FALSE; - } - - /* Hack - Assume invalid panel */ - panel_row_min = cur_hgt; - panel_row_max = 0; - panel_col_min = cur_wid; - panel_col_max = 0; - - /* Center the panel */ - verify_panel(); - - /* Flush messages */ - msg_print(NULL); - - - /* Enter "xtra" mode */ - character_xtra = TRUE; - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - - /* Window stuff */ - p_ptr->window |= (PW_MONSTER); - - /* Redraw dungeon */ - p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA); - - /* Redraw map */ - p_ptr->redraw |= (PR_MAP); - - /* Window stuff */ - p_ptr->window |= (PW_OVERHEAD); - - /* Update stuff */ - p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS | PU_POWERS | PU_SANITY | PU_BODY); - - /* Calculate torch radius */ - p_ptr->update |= (PU_TORCH); - - /* Update stuff */ - update_stuff(); - - /* Redraw stuff */ - redraw_stuff(); - - /* Redraw stuff */ - window_stuff(); - - /* Update stuff */ - p_ptr->update |= (PU_VIEW | PU_FLOW | PU_DISTANCE | PU_MON_LITE); - - /* Update stuff */ - update_stuff(); - - /* Redraw stuff */ - redraw_stuff(); - - /* Leave "xtra" mode */ - character_xtra = FALSE; - - /* Update stuff */ - p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS | PU_POWERS | PU_BODY); - - /* Combine / Reorder the pack */ - p_ptr->notice |= (PN_COMBINE | PN_REORDER); - - /* Notice stuff */ - notice_stuff(); - - /* Update stuff */ - update_stuff(); - - /* Redraw stuff */ - redraw_stuff(); - - /* Window stuff */ - window_stuff(); - - /* Refresh */ - Term_fresh(); - - - /* Announce (or repeat) the feeling */ - if (dun_level) do_cmd_feeling(); - - - /* Hack -- notice death or departure */ - if (!alive || death) return; - - /*** Process this dungeon level ***/ - - /* Reset the monster generation level */ - monster_level = dun_level; - - /* Reset the object generation level */ - object_level = dun_level; - - hack_mind = TRUE; - - /* Mega Hack, if needed wipe all stairs */ - if (dungeon_type == DUNGEON_DEATH) - { - int i, j; - - for (i = 0; i < cur_wid; i++) - { - for (j = 0; j < cur_hgt; j++) - { - cave_type *c_ptr = &cave[j][i]; - - switch (c_ptr->feat) - { - case FEAT_MORE: - case FEAT_LESS: - case FEAT_SHAFT_UP: - case FEAT_SHAFT_DOWN: - { - cave_set_feat(j, i, FEAT_FLOOR); - break; - } - } - } - } - - /* Reset the monster generation level */ - monster_level = 127; - - /* Reset the object generation level */ - object_level = 0; - } - - /* Main loop */ - while (TRUE) - { - /* Hack -- Compact the monster list occasionally */ - if (m_cnt + 32 > max_m_idx) compact_monsters(64); - - /* Hack -- Compress the monster list occasionally */ - if (m_cnt + 32 < m_max) compact_monsters(0); - - - /* Hack -- Compact the object list occasionally */ - if (o_cnt + 32 > max_o_idx) compact_objects(64); - - /* Hack -- Compress the object list occasionally */ - if (o_cnt + 32 < o_max) compact_objects(0); - - - - /* Process the player */ - process_player(); - - /* Notice stuff */ - if (p_ptr->notice) notice_stuff(); - - /* Update stuff */ - if (p_ptr->update) update_stuff(); - - /* Redraw stuff */ - if (p_ptr->redraw) redraw_stuff(); - - /* Redraw stuff */ - if (p_ptr->window) window_stuff(); - - /* Hack -- Hilite the player */ - move_cursor_relative(p_ptr->py, p_ptr->px); - - /* Optional fresh */ - if (fresh_after) Term_fresh(); - - /* Hack -- Notice death or departure */ - if (!alive || death) break; - - - total_friends = 0; - total_friend_levels = 0; - - /* Process all of the monsters */ - process_monsters(); - - /* Notice stuff */ - if (p_ptr->notice) notice_stuff(); - - /* Update stuff */ - if (p_ptr->update) update_stuff(); - - /* Redraw stuff */ - if (p_ptr->redraw) redraw_stuff(); - - /* Redraw stuff */ - if (p_ptr->window) window_stuff(); - - /* Hack -- Hilite the player */ - move_cursor_relative(p_ptr->py, p_ptr->px); - - /* Optional fresh */ - if (fresh_after) Term_fresh(); - - /* Hack -- Notice death or departure */ - if (!alive || death) break; - - - /* Process the world */ - process_world(); - - /* Process the appropriate hooks */ - process_hooks(HOOK_END_TURN, "(d)", is_quest(dun_level)); - - /* Make it pulsate and live !!!! */ - if ((dungeon_flags1 & DF1_EVOLVE) && dun_level) - { - if (!(turn % 10)) evolve_level(TRUE); - } - - /* Notice stuff */ - if (p_ptr->notice) notice_stuff(); - - /* Update stuff */ - if (p_ptr->update) update_stuff(); - - /* Redraw stuff */ - if (p_ptr->redraw) redraw_stuff(); - - /* Window stuff */ - if (p_ptr->window) window_stuff(); - - /* Hack -- Hilite the player */ - move_cursor_relative(p_ptr->py, p_ptr->px); - - /* Optional fresh */ - if (fresh_after) Term_fresh(); - - /* Hack -- Notice death or departure */ - if (!alive || death) break; - - /* Handle "leaving" */ - if (p_ptr->leaving) break; - - /* Count game turns */ - turn++; - } - - /* Did we leave a dungeon ? */ - if ((dun_level < d_info[dungeon_type].mindepth) && !is_recall) - { - dun_level = 0; - - if (d_info[dungeon_type].ix > -1) - { - p_ptr->wilderness_x = d_info[dungeon_type].ix; - p_ptr->wilderness_y = d_info[dungeon_type].iy; - } - - dungeon_type = DUNGEON_WILDERNESS; - } - - if (dun_level > d_info[dungeon_type].maxdepth) - { - dun_level = 0; - - if (d_info[dungeon_type].ox > -1) - { - p_ptr->wilderness_x = d_info[dungeon_type].ox; - p_ptr->wilderness_y = d_info[dungeon_type].oy; - } - - dungeon_type = DUNGEON_WILDERNESS; - } - - is_recall = FALSE; -} - - - - -/* - * Load some "user pref files" - */ -static void load_all_pref_files(void) -{ - char buf[1024]; - - - /* Access the "race" pref file */ - sprintf(buf, "%s.prf", rp_ptr->title + rp_name); - - /* Process that file */ - process_pref_file(buf); - - /* Access the "class" pref file */ - sprintf(buf, "%s.prf", spp_ptr->title + c_name); - - /* Process that file */ - process_pref_file(buf); - - /* Access the "character" pref file */ - sprintf(buf, "%s.prf", player_name); - - /* Process that file */ - process_pref_file(buf); - - /* Process player specific automatizer sets */ - /* TODO: Disabled temporarily because it causes duplicate - * rules on save and subsequent game load. */ - /* sprintf(buf2, "%s.atm", player_name); */ - /* path_build(buf, sizeof(buf), ANGBAND_DIR_USER, buf2); */ - /* automatizer_load(buf); */ -} - -/* - * Actually play a game - * - * If the "new_game" parameter is true, then, after loading the - * savefile, we will commit suicide, if necessary, to allow the - * player to start a new game. - */ -void play_game(bool_ new_game) -{ - int i, tmp_dun; - - bool_ cheat_death = FALSE; - - /* Hack -- Character is "icky" */ - character_icky = TRUE; - - - /* Make sure main term is active */ - Term_activate(angband_term[0]); - - /* Initialise the resize hook XXX XXX XXX */ - angband_term[0]->resize_hook = resize_map; - - /* XXX XXX XXX hardcoded number of terms */ - for (i = 1; i < 8; i++) - { - if (angband_term[i]) - { - /* Add redraw hook */ - angband_term[i]->resize_hook = resize_window; - } - } - - - /* Hack -- turn off the cursor */ - (void)Term_set_cursor(0); - - /* Character list */ - if (!new_game && !no_begin_screen) new_game = begin_screen(); - no_begin_screen = FALSE; - - /* Attempt to load */ - if (!load_player()) - { - /* Oops */ - quit("broken savefile"); - } - - /* Nothing loaded */ - if (!character_loaded) - { - /* Make new player */ - new_game = TRUE; - - /* The dungeon is not ready */ - character_dungeon = FALSE; - } - else - { - int i; - - /* Init new skills to their defaults */ - for (i = old_max_s_idx; i < max_s_idx; i++) - { - s32b value = 0, mod = 0; - - compute_skills(&value, &mod, i); - - init_skill(value, mod, i); - } - } - - /* Process old character */ - if (!new_game) - { - /* Process the player name */ - process_player_name(FALSE); - } - - /* Init the RNG */ - if (Rand_quick) - { - u32b seed; - - /* Basic seed */ - seed = (time(NULL)); - -#ifdef SET_UID - - /* Mutate the seed on Unix machines */ - seed = ((seed >> 3) * (getpid() << 1)); - -#endif - - /* Use the complex RNG */ - Rand_quick = FALSE; - - /* Seed the "complex" RNG */ - Rand_state_init(seed); - } - - /* Extract the options */ - for (i = 0; option_info[i].o_desc; i++) - { - int os = option_info[i].o_page; - int ob = option_info[i].o_bit; - - /* Set the "default" options */ - if (option_info[i].o_var) - { - /* Set */ - if (option_flag[os] & (1L << ob)) - { - /* Set */ - (*option_info[i].o_var) = TRUE; - } - - /* Clear */ - else - { - /* Clear */ - (*option_info[i].o_var) = FALSE; - } - } - } - - /* Roll new character */ - if (new_game) - { - /* Show intro */ - modules[game_module_idx].intro(); - - /* The dungeon is not ready */ - character_dungeon = FALSE; - - /* Hack -- seed for flavors */ - seed_flavor = rand_int(0x10000000); - - /* Roll up a new character */ - player_birth(); - - /* Start in town, or not */ - if (p_ptr->astral) dun_level = 98; - else dun_level = 0; - p_ptr->inside_quest = 0; - p_ptr->inside_arena = 0; - - /* Hack -- enter the world */ - /* Mega-hack Vampires and Spectres start in the dungeon */ - if (PRACE_FLAG(PR1_UNDEAD)) - { - turn = (10L * DAY / 2) + (START_DAY * 10) + 1; - } - else - { - turn = (START_DAY * 10) + 1; - } - } - - /* Flash a message */ - prt("Please wait...", 0, 0); - - /* Flush the message */ - Term_fresh(); - - /* Be sure to not bother the player */ - calc_powers_silent = TRUE; - - /* Hack -- Enter wizard mode */ - if (arg_wizard && enter_wizard_mode()) wizard = TRUE; - - /* Flavor the objects */ - flavor_init(); - - /* Reset the visual mappings */ - reset_visuals(); - - /* Window stuff */ - p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); - - /* Window stuff */ - p_ptr->window |= (PW_MONSTER); - - /* Window stuff */ - window_stuff(); - - /* load user file */ - process_pref_file("user.prf"); - - /* Load the "pref" files */ - load_all_pref_files(); - - /* Set or clear "rogue_like_commands" if requested */ - if (arg_force_original) rogue_like_commands = FALSE; - if (arg_force_roguelike) rogue_like_commands = TRUE; - - /* Initialize vault info */ - if (init_v_info()) quit("Cannot initialize vaults"); - - /* Initialize hooks */ - init_hooks(); - init_hooks_help(); - init_hooks_module(); - - /* React to changes */ - Term_xtra(TERM_XTRA_REACT, 0); - - /* Mega hack, prevent lots of bugs */ - if ((p_ptr->px == 0) || (p_ptr->py == 0)) - { - p_ptr->px = 1; - p_ptr->py = 1; - }; - - /* Hack - if note file exists, load it */ - if (!new_game) - { - add_note_type(NOTE_ENTER_DUNGEON); - } - - /* Generate a dungeon level if needed */ - if (!character_dungeon) generate_cave(); - - /* Ok tell the scripts that the game is about to start */ - process_hooks(HOOK_GAME_START, "()"); - process_hooks_new(HOOK_GAME_START, NULL, NULL); - - /* Character is now "complete" */ - character_generated = TRUE; - - - /* Hack -- Character is no longer "icky" */ - character_icky = FALSE; - - - /* Start game */ - alive = TRUE; - - /* Hack -- Enforce "delayed death" */ - if (p_ptr->chp < 0) death = TRUE; - - /* Process */ - while (TRUE) - { - /* Save the level */ - old_dun_level = dun_level; - p_ptr->old_wild_mode = p_ptr->wild_mode; - - /* We reached surface ? good, lets go down again !! */ - if (p_ptr->astral && !dun_level) - { - p_ptr->astral = FALSE; - cmsg_print(TERM_L_GREEN, - "Well done ! You reached the town ! " - "You can now go down again."); - } - - /* Update monster list window */ - p_ptr->window |= (PW_M_LIST); - - /* Process the level */ - dungeon(); - - /* Save the current level if in a persistent level */ - tmp_dun = dun_level; - dun_level = old_dun_level; - save_dungeon(); - dun_level = tmp_dun; - - /* A death fate affects level generation */ - for (i = 0; i < MAX_FATES; i++) - { - /* Ignore empty slots */ - if (!fates[i].fate) continue; - - /* Ignore non-applicable fates */ - if (fates[i].level != dun_level) continue; - - /* Non-serious fate fails to fire 50% of time */ - if (!fates[i].serious && (rand_int(2) == 0)) continue; - - /* Analyse fate */ - switch (fates[i].fate) - { - /* You are doomed */ - case FATE_DIE: - { - cmsg_print(TERM_L_DARK, "You were fated to die here. DIE!"); - - /* You shall perish there */ - dungeon_type = DUNGEON_DEATH; - dun_level = d_info[dungeon_type].mindepth; /* was 1 */ - - fates[i].fate = FATE_NONE; - break; - } - } - } - - /* Notice stuff */ - if (p_ptr->notice) notice_stuff(); - - /* Update stuff */ - if (p_ptr->update) update_stuff(); - - /* Redraw stuff */ - if (p_ptr->redraw) redraw_stuff(); - - /* Window stuff */ - if (p_ptr->window) window_stuff(); - - /* Cancel the target */ - target_who = 0; - - /* Cancel the health bar */ - health_track(0); - - - /* Forget the lite */ - forget_mon_lite(); - - /* Forget the view */ - forget_view(); - - /* Handle "quit and save" */ - if (!alive && !death) break; - - - /* Erase the old cave */ - wipe_o_list(); - - - /* XXX XXX XXX */ - msg_print(NULL); - - /* Accidental Death */ - if (alive && death) - { - cheat_death = FALSE; - - /* Can we die ? please let us die ! */ - if (process_hooks(HOOK_DIE, "()")) - { - cheat_death = TRUE; - } - - /* Deus ex machina */ - else if (granted_resurrection()) - { - cheat_death = TRUE; - p_ptr->grace = -200000; - cmsg_format(TERM_L_GREEN, - "The power of %s raises you back from the grave!", - deity_info[p_ptr->pgod].name); - msg_print(NULL); - } - - /* Blood of life */ - else if (p_ptr->allow_one_death > 0) - { - cheat_death = TRUE; - - /* Lose one extra life */ - p_ptr->allow_one_death--; - - cmsg_print(TERM_L_GREEN, - "You have been saved by the Blood of Life!"); - msg_print(NULL); - } - - /* Cheat death option */ - else if ((wizard || cheat_live) && !get_check("Die? ")) - { - cheat_death = TRUE; - - /* Mark social class, reset age, if needed */ - if (p_ptr->sc) p_ptr->sc = p_ptr->age = 0; - - /* Increase age */ - p_ptr->age++; - - /* Mark savefile */ - noscore |= 0x0001; - msg_print("You invoke wizard mode and cheat death."); - msg_print(NULL); - } - - if (cheat_death) - { - /* Restore the winner status */ - total_winner = has_won; - - /* One more life spent */ - p_ptr->lives++; - - /* Restore hit points */ - p_ptr->chp = p_ptr->mhp; - p_ptr->chp_frac = 0; - - /* Heal sanity */ - p_ptr->csane = p_ptr->msane; - p_ptr->csane_frac = 0; - - /* Restore spell points */ - p_ptr->csp = p_ptr->msp; - p_ptr->csp_frac = 0; - - /* Hack -- Healing */ - (void)set_blind(0); - (void)set_confused(0); - (void)set_poisoned(0); - (void)set_afraid(0); - (void)set_paralyzed(0); - (void)set_image(0); - (void)set_stun(0); - (void)set_cut(0); - - /* accounting for a new ailment. -LM- */ - p_ptr->black_breath = FALSE; - - /* Hack -- don't go to undead form */ - p_ptr->necro_extra &= ~CLASS_UNDEAD; - - /* Hack -- Prevent starvation */ - (void)set_food(PY_FOOD_MAX - 1); - - /* Hack -- cancel recall */ - if (p_ptr->word_recall) - { - /* Message */ - msg_print("A tension leaves the air around you..."); - msg_print(NULL); - - /* Hack -- Prevent recall */ - p_ptr->word_recall = 0; - } - - /* Note cause of death XXX XXX XXX */ - (void)strcpy(died_from, "Cheating death"); - - /* Do not die */ - death = FALSE; - - /* New depth -KMW- */ - /* dun_level = 0; */ - p_ptr->inside_arena = 0; - leaving_quest = 0; - p_ptr->inside_quest = 0; - - /* Leaving */ - p_ptr->leaving = TRUE; - } - } - - /* Handle "death" */ - if (death) - { - break; - } - - /* Mega hack */ - if (dun_level) p_ptr->wild_mode = FALSE; - - /* Make a new level */ - process_hooks(HOOK_NEW_LEVEL, "(d)", is_quest(dun_level)); - generate_cave(); - } - - /* Close stuff */ - close_game(); - - /* Quit */ - quit(NULL); -} - diff --git a/src/dungeon.cc b/src/dungeon.cc new file mode 100644 index 00000000..df3b41aa --- /dev/null +++ b/src/dungeon.cc @@ -0,0 +1,5849 @@ +/* File: dungeon.c */ + +/* Purpose: Angband game engine */ + +/* + * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke + * + * This software may be copied and distributed for educational, research, and + * not for profit purposes provided that this copyright and statement are + * included in all such copies. + */ + +#include "angband.h" + +#include + +#include "quark.h" +#include "hooks.h" +#include "spell_type.h" + +#define TY_CURSE_CHANCE 100 +#define DG_CURSE_CHANCE 50 +#define AUTO_CURSE_CHANCE 15 +#define CHAINSWORD_NOISE 100 + + +/* + * Return a "feeling" (or NULL) about an item. Method 1 (Heavy). + */ +byte value_check_aux1(object_type *o_ptr) +{ + /* Artifacts */ + if (artifact_p(o_ptr)) + { + /* Cursed/Broken */ + if (cursed_p(o_ptr)) return (SENSE_TERRIBLE); + + /* Normal */ + return (SENSE_SPECIAL); + } + + /* Ego-Items */ + if (ego_item_p(o_ptr)) + { + /* Cursed/Broken */ + if (cursed_p(o_ptr)) return (SENSE_WORTHLESS); + + /* Normal */ + return (SENSE_EXCELLENT); + } + + /* Cursed items */ + if (cursed_p(o_ptr)) return (SENSE_CURSED); + + /* Good "armor" bonus */ + if (o_ptr->to_a > 0) return (SENSE_GOOD_HEAVY); + + /* Good "weapon" bonus */ + if (o_ptr->to_h + o_ptr->to_d > 0) return (SENSE_GOOD_HEAVY); + + /* Default to "average" */ + return (SENSE_AVERAGE); +} + +byte value_check_aux1_magic(object_type *o_ptr) +{ + object_kind *k_ptr = &k_info[o_ptr->k_idx]; + + + switch (o_ptr->tval) + { + /* Scrolls, Potions, Wands, Staves and Rods */ + case TV_SCROLL: + case TV_POTION: + case TV_POTION2: + case TV_WAND: + case TV_STAFF: + case TV_ROD: + case TV_ROD_MAIN: + { + /* "Cursed" scrolls/potions have a cost of 0 */ + if (k_ptr->cost == 0) return (SENSE_TERRIBLE); + + /* Artifacts */ + if (artifact_p(o_ptr)) return (SENSE_SPECIAL); + + /* Scroll of Nothing, Apple Juice, etc. */ + if (k_ptr->cost < 3) return (SENSE_WORTHLESS); + + /* + * Identify, Phase Door, Cure Light Wounds, etc. are + * just average + */ + if (k_ptr->cost < 100) return (SENSE_AVERAGE); + + /* Enchant Armor, *Identify*, Restore Stat, etc. */ + if (k_ptr->cost < 10000) return (SENSE_GOOD_HEAVY); + + /* Acquirement, Deincarnation, Strength, Blood of Life, ... */ + if (k_ptr->cost >= 10000) return (SENSE_EXCELLENT); + + break; + } + + /* Food */ + case TV_FOOD: + { + /* "Cursed" food */ + if (k_ptr->cost == 0) return (SENSE_TERRIBLE); + + /* Artifacts */ + if (artifact_p(o_ptr)) return (SENSE_SPECIAL); + + /* Normal food (no magical properties) */ + if (k_ptr->cost <= 10) return (SENSE_AVERAGE); + + /* Everything else is good */ + if (k_ptr->cost > 10) return (SENSE_GOOD_HEAVY); + + break; + } + } + + /* No feeling */ + return (SENSE_NONE); +} + + +/* + * Return a "feeling" (or NULL) about an item. Method 2 (Light). + */ +byte value_check_aux2(object_type *o_ptr) +{ + /* Cursed items (all of them) */ + if (cursed_p(o_ptr)) return (SENSE_CURSED); + + /* Artifacts -- except cursed/broken ones */ + if (artifact_p(o_ptr)) return (SENSE_GOOD_LIGHT); + + /* Ego-Items -- except cursed/broken ones */ + if (ego_item_p(o_ptr)) return (SENSE_GOOD_LIGHT); + + /* Good armor bonus */ + if (o_ptr->to_a > 0) return (SENSE_GOOD_LIGHT); + + /* Good weapon bonuses */ + if (o_ptr->to_h + o_ptr->to_d > 0) return (SENSE_GOOD_LIGHT); + + /* Default to "average" */ + return (SENSE_AVERAGE); +} + + +byte value_check_aux2_magic(object_type *o_ptr) +{ + object_kind *k_ptr = &k_info[o_ptr->k_idx]; + + + switch (o_ptr->tval) + { + /* Scrolls, Potions, Wands, Staves and Rods */ + case TV_SCROLL: + case TV_POTION: + case TV_POTION2: + case TV_WAND: + case TV_STAFF: + case TV_ROD: + case TV_ROD_MAIN: + { + /* "Cursed" scrolls/potions have a cost of 0 */ + if (k_ptr->cost == 0) return (SENSE_CURSED); + + /* Artifacts */ + if (artifact_p(o_ptr)) return (SENSE_GOOD_LIGHT); + + /* Scroll of Nothing, Apple Juice, etc. */ + if (k_ptr->cost < 3) return (SENSE_AVERAGE); + + /* + * Identify, Phase Door, Cure Light Wounds, etc. are + * just average + */ + if (k_ptr->cost < 100) return (SENSE_AVERAGE); + + /* Enchant Armor, *Identify*, Restore Stat, etc. */ + if (k_ptr->cost < 10000) return (SENSE_GOOD_LIGHT); + + /* Acquirement, Deincarnation, Strength, Blood of Life, ... */ + if (k_ptr->cost >= 10000) return (SENSE_GOOD_LIGHT); + + break; + } + + /* Food */ + case TV_FOOD: + { + /* "Cursed" food */ + if (k_ptr->cost == 0) return (SENSE_CURSED); + + /* Artifacts */ + if (artifact_p(o_ptr)) return (SENSE_GOOD_LIGHT); + + /* Normal food (no magical properties) */ + if (k_ptr->cost <= 10) return (SENSE_AVERAGE); + + /* Everything else is good */ + if (k_ptr->cost > 10) return (SENSE_GOOD_LIGHT); + + break; + } + } + + /* No feeling */ + return (SENSE_NONE); +} + + +/* + * Can a player be resurrected? + */ +static bool_ granted_resurrection(void) +{ + PRAY_GOD(GOD_ERU) + { + if (p_ptr->grace > 100000) + { + if (magik(70)) return (TRUE); + else return (FALSE); + } + } + return (FALSE); +} + +static byte select_sense(object_type *o_ptr) +{ + /* Valid "tval" codes */ + switch (o_ptr->tval) + { + case TV_SHOT: + case TV_ARROW: + case TV_BOLT: + case TV_BOW: + case TV_DIGGING: + case TV_HAFTED: + case TV_POLEARM: + case TV_SWORD: + case TV_MSTAFF: + case TV_AXE: + case TV_BOOTS: + case TV_GLOVES: + case TV_HELM: + case TV_CROWN: + case TV_SHIELD: + case TV_CLOAK: + case TV_SOFT_ARMOR: + case TV_HARD_ARMOR: + case TV_DRAG_ARMOR: + case TV_BOOMERANG: + case TV_TRAPKIT: + { + return 1; + break; + } + + case TV_POTION: + case TV_POTION2: + case TV_SCROLL: + case TV_WAND: + case TV_STAFF: + case TV_ROD: + case TV_ROD_MAIN: + { + return 2; + break; + } + + /* Dual use? */ + case TV_DAEMON_BOOK: + { + return 1; + break; + } + } + return 0; +} + +/* + * Sense the inventory + * + * Combat items (weapons and armour) - Fast, weak if combat skill < 10, strong + * otherwise. + * + * Magic items (scrolls, staffs, wands, potions etc) - Slow, weak if + * magic skill < 10, strong otherwise. + * + * It shouldn't matter a lot to discriminate against magic users, because + * they learn one form of ID or another, and because most magic items are + * easy_know. + */ +void sense_inventory(void) +{ + int i, combat_lev, magic_lev; + + bool_ heavy_combat, heavy_magic; + + byte feel; + + object_type *o_ptr; + + char o_name[80]; + + + /*** Check for "sensing" ***/ + + /* No sensing when confused */ + if (p_ptr->confused) return; + + /* + * In Angband, the chance of pseudo-id uses two different formulae: + * + * (1) Fast. 0 == rand_int(BASE / (plev * plev + 40) + * (2) Slow. 0 == rand_int(BASE / (plev + 5) + * + * Warriors: Fase with BASE == 9000 + * Magi: Slow with BASE == 240000 + * Priests: Fast with BASE == 10000 + * Rogues: Fase with BASE == 20000 + * Rangers: Slow with BASE == 120000 + * Paladins: Fast with BASE == 80000 + * + * In other words, those who have identify spells are penalised. + * The problems with Pern/Tome since it externalised player classes + * is that it uses the same and slow formula for spellcasters and + * fighters. + * + * In the following code, combat item pseudo-ID improves exponentially, + * (fast with BASE 9000) and magic one linear (slow with base 60000 -- + * twice faster than V rangers). + * + * I hope this makes it closer to the original model -- pelpel + */ + + /* The combat skill affects weapon/armour pseudo-ID */ + combat_lev = get_skill(SKILL_COMBAT); + + /* The magic skill affects magic item pseudo-ID */ + magic_lev = get_skill(SKILL_MAGIC); + + /* Higher skill levels give the player better sense of items */ + heavy_combat = (combat_lev > 10) ? TRUE : FALSE; + heavy_magic = (magic_lev > 10) ? TRUE : FALSE; + + + /*** Sense everything ***/ + + /* Check everything */ + for (i = 0; i < INVEN_TOTAL; i++) + { + byte okay = 0; + + o_ptr = &p_ptr->inventory[i]; + + /* Skip empty slots */ + if (!o_ptr->k_idx) continue; + + /* We know about it already, do not tell us again */ + if (o_ptr->ident & (IDENT_SENSE)) continue; + + /* It is fully known, no information needed */ + if (object_known_p(o_ptr)) continue; + + /* Valid "tval" codes */ + okay = select_sense(o_ptr); + + /* Skip non-sense machines */ + if (!okay) continue; + + /* Check for a feeling */ + if (okay == 1) + { + feel = (heavy_combat ? value_check_aux1(o_ptr) : value_check_aux2(o_ptr)); + } + else + { + feel = (heavy_magic ? value_check_aux1_magic(o_ptr) : value_check_aux2_magic(o_ptr)); + } + + /* Skip non-feelings */ + if (feel == SENSE_NONE) continue; + + /* Get an object description */ + object_desc(o_name, o_ptr, FALSE, 0); + + /* Message (equipment) */ + if (i >= INVEN_WIELD) + { + msg_format("You feel the %s (%c) you are %s %s %s...", + o_name, index_to_label(i), describe_use(i), + ((o_ptr->number == 1) ? "is" : "are"), sense_desc[feel]); + } + + /* Message (inventory) */ + else + { + msg_format("You feel the %s (%c) in your pack %s %s...", + o_name, index_to_label(i), + ((o_ptr->number == 1) ? "is" : "are"), sense_desc[feel]); + } + + /* We have "felt" it */ + o_ptr->ident |= (IDENT_SENSE); + + /* Set sense property */ + o_ptr->sense = feel; + + /* Combine / Reorder the pack (later) */ + p_ptr->notice |= (PN_COMBINE | PN_REORDER); + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP); + } + + /* Squelch ! */ + squeltch_inventory(); +} + + +/* + * Go to any level (ripped off from wiz_jump) + */ +static void pattern_teleport(void) +{ + /* Ask for level */ + if (get_check("Teleport level? ")) + { + char ppp[80]; + + char tmp_val[160]; + + /* Prompt */ + sprintf(ppp, "Teleport to level (0-%d): ", 99); + + /* Default */ + sprintf(tmp_val, "%d", dun_level); + + /* Ask for a level */ + if (!get_string(ppp, tmp_val, 10)) return; + + /* Extract request */ + command_arg = atoi(tmp_val); + } + else if (get_check("Normal teleport? ")) + { + teleport_player(200); + return; + } + else + { + return; + } + + /* Paranoia */ + if (command_arg < 0) command_arg = 0; + + /* Paranoia */ + if (command_arg > 99) command_arg = 99; + + /* Accept request */ + msg_format("You teleport to dungeon level %d.", command_arg); + + autosave_checkpoint(); + + /* Change level */ + dun_level = command_arg; + + /* Leaving */ + p_ptr->leaving = TRUE; +} + + +/* + * Returns TRUE if we are on the Straight Road... + */ +static bool_ pattern_effect(void) +{ + if ((cave[p_ptr->py][p_ptr->px].feat < FEAT_PATTERN_START) || + (cave[p_ptr->py][p_ptr->px].feat > FEAT_PATTERN_XTRA2)) return (FALSE); + + if (cave[p_ptr->py][p_ptr->px].feat == FEAT_PATTERN_END) + { + (void)set_poisoned(0); + (void)set_image(0); + (void)set_stun(0); + (void)set_cut(0); + (void)set_blind(0); + (void)set_afraid(0); + (void)do_res_stat(A_STR, TRUE); + (void)do_res_stat(A_INT, TRUE); + (void)do_res_stat(A_WIS, TRUE); + (void)do_res_stat(A_DEX, TRUE); + (void)do_res_stat(A_CON, TRUE); + (void)do_res_stat(A_CHR, TRUE); + (void)restore_level(); + (void)hp_player(1000); + cave_set_feat(p_ptr->py, p_ptr->px, FEAT_PATTERN_OLD); + msg_print("This section of the Straight Road looks less powerful."); + } + + + /* + * We could make the healing effect of the + * Pattern center one-time only to avoid various kinds + * of abuse, like luring the win monster into fighting you + * in the middle of the pattern... + */ + else if (cave[p_ptr->py][p_ptr->px].feat == FEAT_PATTERN_OLD) + { + /* No effect */ + } + else if (cave[p_ptr->py][p_ptr->px].feat == FEAT_PATTERN_XTRA1) + { + pattern_teleport(); + } + else if (cave[p_ptr->py][p_ptr->px].feat == FEAT_PATTERN_XTRA2) + { + if (!(p_ptr->invuln)) + take_hit(200, "walking the corrupted Straight Road"); + } + + else + { + if (!(p_ptr->invuln)) + take_hit(damroll(1, 3), "walking the Straight Road"); + } + + return (TRUE); +} + + +/* + * If player has inscribed the object with "!!", let him know when it's + * recharged. -LM- + */ +static void recharged_notice(object_type *o_ptr) +{ + char o_name[80]; + + cptr s; + + + /* No inscription */ + if (!o_ptr->note) return; + + /* Find a '!' */ + s = strchr(quark_str(o_ptr->note), '!'); + + /* Process notification request. */ + while (s) + { + /* Find another '!' */ + if (s[1] == '!') + { + /* Describe (briefly) */ + object_desc(o_name, o_ptr, FALSE, 0); + + /* Notify the player */ + if (o_ptr->number > 1) + { + msg_format("Your %s are recharged.", o_name); + } + else + { + msg_format("Your %s is recharged.", o_name); + } + + /* Done. */ + return; + } + + /* Keep looking for '!'s */ + s = strchr(s + 1, '!'); + } +} + + + +/* + * Regenerate hit points -RAK- + */ +static void regenhp(int percent) +{ + s32b new_chp, new_chp_frac; + + int old_chp; + + + /* Only if alive */ + if (!(p_ptr->necro_extra & CLASS_UNDEAD)) + { + /* Save the old hitpoints */ + old_chp = p_ptr->chp; + + /* Extract the new hitpoints */ + new_chp = ((long)p_ptr->mhp) * percent + PY_REGEN_HPBASE; + + /* div 65536 */ + p_ptr->chp += new_chp >> 16; + + /* check for overflow */ + if ((p_ptr->chp < 0) && (old_chp > 0)) p_ptr->chp = MAX_SHORT; + + /* mod 65536 */ + new_chp_frac = (new_chp & 0xFFFF) + p_ptr->chp_frac; + + if (new_chp_frac >= 0x10000L) + { + p_ptr->chp_frac = new_chp_frac - 0x10000L; + p_ptr->chp++; + } + else + { + p_ptr->chp_frac = new_chp_frac; + } + + /* Fully healed */ + if (p_ptr->chp >= p_ptr->mhp) + { + p_ptr->chp = p_ptr->mhp; + p_ptr->chp_frac = 0; + } + + /* Notice changes */ + if (old_chp != p_ptr->chp) + { + /* Redraw */ + p_ptr->redraw |= (PR_HP); + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + } + } +} + + +/* + * Regenerate mana points -RAK- + */ +static void regenmana(int percent) +{ + s32b new_mana, new_mana_frac; + + int old_csp; + + /* Incraese regen with int */ + percent += adj_str_blow[p_ptr->stat_ind[A_INT]] * 3; + + old_csp = p_ptr->csp; + new_mana = ((long)p_ptr->msp) * percent + PY_REGEN_MNBASE; + + /* div 65536 */ + p_ptr->csp += new_mana >> 16; + + /* check for overflow */ + if ((p_ptr->csp < 0) && (old_csp > 0)) + { + p_ptr->csp = MAX_SHORT; + } + + /* mod 65536 */ + new_mana_frac = (new_mana & 0xFFFF) + p_ptr->csp_frac; + + if (new_mana_frac >= 0x10000L) + { + p_ptr->csp_frac = new_mana_frac - 0x10000L; + p_ptr->csp++; + } + else + { + p_ptr->csp_frac = new_mana_frac; + } + + /* Must set frac to zero even if equal */ + if (p_ptr->csp >= p_ptr->msp) + { + p_ptr->csp = p_ptr->msp; + p_ptr->csp_frac = 0; + } + + /* Redraw mana */ + if (old_csp != p_ptr->csp) + { + /* Redraw */ + p_ptr->redraw |= (PR_MANA); + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + } +} + + + + + + +/* + * Regenerate the monsters (once per 100 game turns) + * + * XXX XXX XXX Should probably be done during monster turns. + */ +static void regen_monsters(void) +{ + int i, frac; + + object_type *o_ptr = &p_ptr->inventory[INVEN_CARRY]; + + + if (o_ptr->k_idx) + { + monster_race *r_ptr = &r_info[o_ptr->pval]; + + /* Allow regeneration (if needed) */ + if (o_ptr->pval2 < o_ptr->pval3) + { + /* Hack -- Base regeneration */ + frac = o_ptr->pval3 / 100; + + /* Hack -- Minimal regeneration rate */ + if (!frac) frac = 1; + + /* Hack -- Some monsters regenerate quickly */ + if (r_ptr->flags2 & (RF2_REGENERATE)) frac *= 2; + + + /* Hack -- Regenerate */ + o_ptr->pval2 += frac; + + /* Do not over-regenerate */ + if (o_ptr->pval2 > o_ptr->pval3) o_ptr->pval2 = o_ptr->pval3; + + /* Redraw (later) */ + p_ptr->redraw |= (PR_MH); + } + } + + /* Regenerate everyone */ + for (i = 1; i < m_max; i++) + { + /* Check the i'th monster */ + monster_type *m_ptr = &m_list[i]; + monster_race *r_ptr = race_inf(m_ptr); + + /* Skip dead monsters */ + if (!m_ptr->r_idx) continue; + + /* Dont regen bleeding/poisonned monsters */ + if (m_ptr->bleeding || m_ptr->poisoned) continue; + + /* Allow regeneration (if needed) */ + if (m_ptr->hp < m_ptr->maxhp) + { + /* Hack -- Base regeneration */ + frac = m_ptr->maxhp / 100; + + /* Hack -- Minimal regeneration rate */ + if (!frac) frac = 1; + + /* Hack -- Some monsters regenerate quickly */ + if (r_ptr->flags2 & (RF2_REGENERATE)) frac *= 2; + + + /* Hack -- Regenerate */ + m_ptr->hp += frac; + + /* Do not over-regenerate */ + if (m_ptr->hp > m_ptr->maxhp) m_ptr->hp = m_ptr->maxhp; + + /* Redraw (later) if needed */ + if (health_who == i) p_ptr->redraw |= (PR_HEALTH); + } + } +} + + +/* + * Does an object decay? + * + * Should belong to object1.c, renamed to object_decays() -- pelpel + */ +bool_ decays(object_type *o_ptr) +{ + u32b f1, f2, f3, f4, f5, esp; + + + /* Extract some flags */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + if (f3 & TR3_DECAY) return (TRUE); + + return (FALSE); +} + + +static int process_lasting_spell(s16b music) +{ + spell_type *spell = spell_at(-music); + return spell_type_produce_effect_lasting(spell); +} + +static void gere_class_special() +{ + switch (p_ptr->druid_extra2) + { + /* Lay a path of mana on the floor */ + case CLASS_MANA_PATH: + { + /* Does the player have enought mana ? */ + if (p_ptr->csp < (s32b)(p_ptr->druid_extra & 255)) + { + p_ptr->druid_extra = 0; + p_ptr->druid_extra2 = CLASS_NONE; + msg_print("You stop laying a mana path."); + } + else + { + /* Use some mana */ + p_ptr->csp -= (p_ptr->druid_extra & 255); + + if ((p_ptr->druid_extra >> 8) & CLASS_MANA_PATH_ERASE) + { + /* Absorb some of the mana of the grid */ + p_ptr->csp += cave[p_ptr->py][p_ptr->px].mana / 50; + if (p_ptr->csp > p_ptr->msp) p_ptr->csp = p_ptr->msp; + + /* Set the new grid mana */ + cave[p_ptr->py][p_ptr->px].mana = p_ptr->druid_extra & 255; + } + else + { + int m = cave[p_ptr->py][p_ptr->px].mana; + + if (m + (p_ptr->druid_extra & 255) > 255) + { + cave[p_ptr->py][p_ptr->px].mana = 255; + } + else + { + cave[p_ptr->py][p_ptr->px].mana += p_ptr->druid_extra & 255; + } + } + } + + break; + } + + /* Lay a path of mana on the floor */ + case CLASS_WINDS_MANA: + { + /* Does the player have enought mana ? */ + if (p_ptr->csp < (s32b)(p_ptr->druid_extra & 255)) + { + p_ptr->druid_extra = CLASS_NONE; + msg_print("You stop expulsing mana winds."); + } + else + { + int dam = 0; + + /* Use some mana */ + p_ptr->csp -= (p_ptr->druid_extra & 255); + + if ((p_ptr->druid_extra >> 8) & CLASS_MANA_PATH_ERASE) + { + dam = (p_ptr->druid_extra & 255) + 256; + } + else + { + dam = (p_ptr->druid_extra & 255); + } + + fire_explosion(p_ptr->py, p_ptr->px, GF_WINDS_MANA, 2, dam); + } + + break; + } + + case CLASS_CANALIZE_MANA: + { + if (p_ptr->druid_extra & CLASS_CANALIZE_MANA_EXTRA) + { + p_ptr->csp += cave[p_ptr->py][p_ptr->px].mana / 10; + } + else + { + p_ptr->csp += cave[p_ptr->py][p_ptr->px].mana / 20; + } + + if (p_ptr->csp > p_ptr->msp) p_ptr->csp = p_ptr->msp; + + cave[p_ptr->py][p_ptr->px].mana = 0; + + break; + } + + /* CLASS_NONE, possibly others? */ + default: + { + /* No mana update */ + return; + } + } + + /* Redraw mana */ + p_ptr->update |= (PU_BONUS); + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); +} + + +static void check_music() +{ + int use_mana; + + /* Music sung by player */ + if (!p_ptr->music_extra) return; + + use_mana = process_lasting_spell(p_ptr->music_extra); + + if (p_ptr->csp < use_mana) + { + msg_print("You stop your spell."); + p_ptr->music_extra = 0; + p_ptr->music_extra2 = 0; + } + else + { + p_ptr->csp -= use_mana; + + /* Redraw mana */ + p_ptr->redraw |= (PR_MANA); + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + } +} + + +/* + * Generate the feature effect + */ +void apply_effect(int y, int x) +{ + cave_type *c_ptr = &cave[y][x]; + + feature_type *f_ptr = &f_info[c_ptr->feat]; + + + if (f_ptr->d_frequency[0] != 0) + { + int i; + + for (i = 0; i < 4; i++) + { + /* Check the frequency */ + if (f_ptr->d_frequency[i] == 0) continue; + + if (((turn % f_ptr->d_frequency[i]) == 0) && + ((f_ptr->d_side[i] != 0) || (f_ptr->d_dice[i] != 0))) + { + int l, dam = 0; + int d = f_ptr->d_dice[i], s = f_ptr->d_side[i]; + + if (d == -1) d = p_ptr->lev; + if (s == -1) s = p_ptr->lev; + + /* Roll damage */ + for (l = 0; l < d; l++) + { + dam += randint(s); + } + + /* Apply damage */ + project( -100, 0, y, x, dam, f_ptr->d_type[i], + PROJECT_KILL | PROJECT_HIDE); + + /* Hack -- notice death */ + if (!alive || death) return; + } + } + } +} + + + +/* XXX XXX XXX */ +bool_ is_recall = FALSE; + + +/* + * Hook for corruptions + */ +static void process_world_corruptions() +{ + if (player_has_corruption(CORRUPT_RANDOM_TELEPORT)) + { + if (rand_int(300) == 1) + { + if (magik(70)) + { + if (get_check("Teleport?")) + { + teleport_player(50); + } + else + { + disturb(0); + msg_print("Your corruption takes over you, you teleport!"); + teleport_player(50); + } + } + } + } + + if (player_has_corruption(CORRUPT_ANTI_TELEPORT)) + { + if (p_ptr->corrupt_anti_teleport_stopped) + { + int amt = p_ptr->msp + p_ptr->csp; + amt = amt / 100; + if (amt < 1) { + amt = 1; + } + increase_mana(-amt); + if (p_ptr->csp == 0) + { + p_ptr->corrupt_anti_teleport_stopped = FALSE; + msg_print("You stop controlling your corruption."); + p_ptr->update = p_ptr->update | PU_BONUS; + } + } + } +} + + +/* + * Shim for accessing Lua variable. + */ +static bool_ grace_delay_trigger() +{ + p_ptr->grace_delay++; + + if (p_ptr->grace_delay >= 15) + { + /* reset */ + p_ptr->grace_delay = 0; + /* triggered */ + return TRUE; + } + else + { + /* not triggered */ + return FALSE; + } +} + +/* + * Hook for gods + */ +static void process_world_gods() +{ + const char *race_name = rp_ptr->title + rp_name; + const char *subrace_name = rmp_ptr->title + rmp_name; + + GOD(GOD_VARDA) + { + if (grace_delay_trigger()) + { + /* Piety increases if in light. */ + if (cave[p_ptr->py][p_ptr->px].info & CAVE_GLOW) + { + inc_piety(GOD_ALL, 2); + } + + if (streq(race_name, "Orc") || + streq(race_name, "Troll") || + streq(race_name, "Dragon") || + streq(race_name, "Demon")) + { + /* Varda hates evil races */ + inc_piety(GOD_ALL, -2); + } else { + /* ... and everyone slightly less */ + inc_piety(GOD_ALL, -1); + } + + /* Prayer uses piety */ + if (p_ptr->praying) + { + inc_piety(GOD_ALL, -1); + } + } + } + + GOD(GOD_ULMO) + { + if (grace_delay_trigger()) + { + int i; + /* Ulmo likes the Edain (except Easterlings) */ + if (streq(race_name, "Human") || + streq(race_name, "Dunadan") || + streq(race_name, "Druadan") || + streq(race_name, "RohanKnight")) + { + inc_piety(GOD_ALL, 2); + } + else if (streq(race_name, "Easterling") || + streq(race_name, "Demon") || + streq(race_name, "Orc")) + { + /* hated races */ + inc_piety(GOD_ALL, -2); + } + else + { + inc_piety(GOD_ALL, 1); + } + + if (p_ptr->praying) + { + inc_piety(GOD_ALL, -1); + } + + /* Gain 1 point for each trident in inventory */ + for (i = 0; i < INVEN_TOTAL; i++) + { + if ((p_ptr->inventory[i].tval == TV_POLEARM) && + (p_ptr->inventory[i].sval == SV_TRIDENT)) + { + inc_piety(GOD_ALL, 1); + } + } + } + } + + GOD(GOD_AULE) + { + if (grace_delay_trigger()) + { + int i; + + /* Aule likes Dwarves and Dark Elves (Eol's + * influence here) */ + if (!(streq(race_name, "Dwarf") || + streq(race_name, "Petty-dwarf") || + streq(race_name, "Gnome") || + streq(race_name, "Dark-Elf"))) + { + inc_piety(GOD_ALL, -1); + } + + /* Search inventory for axe or hammer - Gain 1 + * point of grace for each hammer or axe */ + for (i = 0; i < INVEN_TOTAL; i++) + { + int tval = p_ptr->inventory[i].tval; + int sval = p_ptr->inventory[i].sval; + + switch (tval) + { + case TV_AXE: + inc_piety(GOD_ALL, 1); + break; + + case TV_HAFTED: + if ((sval == SV_WAR_HAMMER) || + (sval == SV_LUCERN_HAMMER) || + (sval == SV_GREAT_HAMMER)) + { + inc_piety(GOD_ALL, 1); + } + break; + } + } + + /* Praying may grant you a free stone skin + * once in a while */ + if (p_ptr->praying) + { + int chance; + s32b grace; + + inc_piety(GOD_ALL, -2); + grace = p_ptr->grace; /* shorthand */ + + chance = 1; + if (grace >= 50000) + { + chance = 50000; + } + else + { + chance = 50000 - grace; + } + + if (randint(100000) <= 100000 / chance) + { + s16b type = 0; + + if (grace >= 10000) + { + type = SHIELD_COUNTER; + } + + set_shield( + randint(10) + 10 + (grace / 100), + 10 + (grace / 100), + type, + 2 + (grace / 200), + 3 + (grace / 400)); + + msg_print("Aule casts Stone Skin on you."); + } + } + } + } + + GOD(GOD_MANDOS) + { + if (grace_delay_trigger()) + { + /* He loves astral beings */ + if (streq(subrace_name, "LostSoul")) + { + inc_piety(GOD_ALL, 1); + } + + /* He likes High Elves only, though, as races */ + if (!streq(race_name, "High-Elf")) + { + inc_piety(GOD_ALL, -1); + } + + /* Really hates vampires and demons */ + if (streq(subrace_name, "Vampire") || + streq(race_name, "Demon")) + { + inc_piety(GOD_ALL, -10); + } + else + { + inc_piety(GOD_ALL, 2); + } + /* he really doesn't like to be disturbed */ + if (p_ptr->praying) + { + inc_piety(GOD_ALL, -5); + } + } + } + +} + +/* + * Handle certain things once every 10 game turns + * + * Note that a single movement in the overhead wilderness mode + * consumes 132 times as much energy as a normal one... + */ +static void process_world(void) +{ + timer_type *t_ptr; + + int x, y, i, j; + + int regen_amount; + bool_ cave_no_regen = FALSE; + int upkeep_factor = 0; + + dungeon_info_type *d_ptr = &d_info[dungeon_type]; + + cave_type *c_ptr; + + object_type *o_ptr; + u32b f1 = 0 , f2 = 0 , f3 = 0, f4 = 0, f5 = 0, esp = 0; + + + /* + * Every 10 game turns -- which means this section is invoked once + * in a player turn under the normal speed, and 132 times in a move + * in the reduced map mode. + */ + if (turn % 10) return; + + /* + * I don't know if this is the right thing to do because I'm totally + * ignorant (yes, I must admit that...) about the scripting part of + * the game, but since there have been complaints telling us it + * runs terribly slow in the reduced map mode... -- pelpel + * + * Note to coders: if it is desirable to make this active in the + * reduced map mode, remove the if condition surrounding the line + * and move the code inside into every 1000 game turns section. + */ + if (dun_level || (!p_ptr->wild_mode)) + { + /* Handle corruptions */ + process_world_corruptions(); + + /* Handle gods */ + process_world_gods(); + + /* Handle the player song */ + check_music(); + } + + /* Handle the timers */ + for (t_ptr = gl_timers; t_ptr != NULL; t_ptr = t_ptr->next) + { + if (!t_ptr->enabled) continue; + + t_ptr->countdown--; + if (!t_ptr->countdown) + { + t_ptr->countdown = t_ptr->delay; + assert(t_ptr->callback != NULL); + t_ptr->callback(); + } + } + + /* Handle class special actions */ + gere_class_special(); + + /* Check the fate */ + if (fate_option && (p_ptr->lev > 10)) + { + /* + * WAS: == 666 against randint(50000). + * Since CPU's don't know Judeo-Christian / Cabalistic traditions, + * and since comparisons with zero is more efficient in many + * architectures... + */ + if (rand_int(50000) == 0) gain_fate(0); + } + + /*** Is the wielded monsters still hypnotised ***/ + o_ptr = &p_ptr->inventory[INVEN_CARRY]; + + if (o_ptr->k_idx) + { + monster_race *r_ptr = &r_info[o_ptr->pval]; + + if ((randint(1000) < r_ptr->level - ((p_ptr->lev * 2) + get_skill(SKILL_SYMBIOTIC)))) + { + msg_format("%s breaks free from hypnosis!", + symbiote_name(TRUE)); + carried_make_attack_normal(o_ptr->pval); + } + } + + /*** Attempt timed autosave ***/ + if (autosave_t && autosave_freq) + { + if ((turn % ((s32b)autosave_freq * 10)) == 0) + { + is_autosave = TRUE; + msg_print("Autosaving the game..."); + do_cmd_save_game(); + is_autosave = FALSE; + } + } + + + /*** Handle the wilderness/town (sunshine) ***/ + + /* While in town/wilderness and not in the overworld mode */ + if (!dun_level && !p_ptr->wild_mode) + { + /* Hack -- Daybreak/Nighfall in town */ + if ((turn % ((10L * DAY) / 2)) == 0) + { + bool_ dawn; + + /* Check for dawn */ + dawn = ((turn % (10L * DAY)) == 0); + + /* Day breaks */ + if (dawn) + { + /* Message */ + msg_print("The sun has risen."); + + /* Hack -- Scan the town */ + for (y = 0; y < cur_hgt; y++) + { + for (x = 0; x < cur_wid; x++) + { + /* Get the cave grid */ + c_ptr = &cave[y][x]; + + /* Assume lit */ + c_ptr->info |= (CAVE_GLOW); + + /* Hack -- Memorize lit grids if allowed */ + if (view_perma_grids) c_ptr->info |= (CAVE_MARK); + + /* Hack -- Notice spot */ + note_spot(y, x); + } + } + } + + /* Night falls */ + else + { + /* Message */ + msg_print("The sun has set."); + + /* Hack -- Scan the town */ + for (y = 0; y < cur_hgt; y++) + { + for (x = 0; x < cur_wid; x++) + { + /* Get the cave grid */ + c_ptr = &cave[y][x]; + + /* Darken "boring" features */ + if (cave_plain_floor_grid(c_ptr)) + { + /* Forget the grid */ + c_ptr->info &= ~(CAVE_GLOW | CAVE_MARK); + + /* Hack -- Notice spot */ + note_spot(y, x); + } + } + } + } + + /* Update the monsters */ + p_ptr->update |= (PU_MONSTERS); + + /* Redraw map */ + p_ptr->redraw |= (PR_MAP); + + /* Window stuff */ + p_ptr->window |= (PW_OVERHEAD); + } + } + + /* Tell a day passed */ + if (((turn + (DAY_START * 10L)) % (10L * DAY)) == 0) + { + char buf[20]; + + sprintf(buf, "%s", get_day(bst(YEAR, turn) + START_YEAR)); + cmsg_format(TERM_L_GREEN, + "Today it is %s of the %s year of the third age.", + get_month_name(bst(DAY, turn), wizard, FALSE), buf); + } + + /* Set back the rewards once a day */ + if ((turn % (10L * STORE_TURNS)) == 0) + { + /* Select new bounties. */ + if (magik(20)) select_bounties(); + } + + /* Modify loan */ + if (p_ptr->loan) + { + if (p_ptr->loan_time) p_ptr->loan_time--; + + if (((turn % 5000) == 0) && !p_ptr->loan_time) + { + cmsg_print(TERM_RED, "You should pay your loan..."); + + p_ptr->loan += p_ptr->loan / 12; + + if (p_ptr->loan > PY_MAX_GOLD) p_ptr->loan = PY_MAX_GOLD; + + /* Do a nasty stuff */ + if (p_ptr->wild_mode && rand_int(2)) + { + /* Discount player items */ + int z = 0, tries = 200; + object_type *o_ptr = NULL; + + while (tries--) + { + z = rand_int(INVEN_TOTAL); + o_ptr = &p_ptr->inventory[z]; + + if (!o_ptr->k_idx) continue; + + if (o_ptr->discount >= 100) continue; + + break; + } + + if (tries) + { + o_ptr->discount += 70; + if (o_ptr->discount >= 100) o_ptr->discount = 100; + + inven_item_optimize(z); + inven_item_describe(z); + + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + } + } + + else + { + int merc = test_monster_name("Mean-looking mercenary"); + int agent = test_monster_name("Agent of the black market"); + int num = 5 + (p_ptr->lev / 3), z; + + for (z = 0; z < num; z++) + { + int yy, xx, attempts = 200, m_idx; + + /* Summon */ + while (1) + { + scatter(&yy, &xx, p_ptr->py, p_ptr->px, 6); + + /* Accept an empty grid within the boundary */ + if (in_bounds(yy, xx) && cave_floor_bold(yy, xx)) break; + + /* Max number of retries reached */ + if (--attempts == 0) break; + } + + /* All the attempts failed */ + if (attempts == 0) continue; + + /* Summon a monster */ + m_idx = place_monster_one(yy, xx, magik(80) ? merc : agent, + 0, FALSE, MSTATUS_ENEMY); + + /* Level it */ + if (m_idx) + { + monster_type *m_ptr = &m_list[m_idx]; + + m_ptr->exp = MONSTER_EXP(p_ptr->lev * 2); + monster_check_experience(m_idx, TRUE); + } + } + } + } + } + + /*** Process the monsters ***/ + + /* Check for creature generation. */ + if (!p_ptr->wild_mode && + !p_ptr->inside_arena && + !p_ptr->inside_quest && + (rand_int(d_info[(dun_level) ? dungeon_type : DUNGEON_WILDERNESS].max_m_alloc_chance) == 0)) + { + /* Make a new monster */ + if (!(dungeon_flags2 & DF2_NO_NEW_MONSTER)) + { + (void)alloc_monster(MAX_SIGHT + 5, FALSE); + } + } + + /* Hack -- Check for creature regeneration */ + if (!p_ptr->wild_mode && ((turn % 100) == 0)) regen_monsters(); + + + /*** Damage over Time ***/ + + /* Take damage from poison */ + if (p_ptr->poisoned && !p_ptr->invuln) + { + /* Take damage */ + take_hit(1, "poison"); + } + + + /* Vampires take damage from sunlight */ + if (p_ptr->sensible_lite) + { + if ((!dun_level) && (((turn / ((10L * DAY) / 2)) % 2) == 0)) + { + if (cave[p_ptr->py][p_ptr->px].info & (CAVE_GLOW)) + { + /* Take damage */ + msg_print("The sun's rays scorch your undead flesh!"); + take_hit(1, "sunlight"); + cave_no_regen = TRUE; + drop_from_wild(); + } + } + + if ((p_ptr->inventory[INVEN_LITE].tval != 0) && + (p_ptr->inventory[INVEN_LITE].sval >= SV_LITE_GALADRIEL) && + (p_ptr->inventory[INVEN_LITE].sval <= SV_STONE_LORE) && + (p_ptr->inventory[INVEN_LITE].sval != SV_LITE_UNDEATH)) + { + object_type * o_ptr = &p_ptr->inventory[INVEN_LITE]; + char o_name [80]; + char ouch [80]; + + /* Get an object description */ + object_desc(o_name, o_ptr, FALSE, 0); + + msg_format("The %s scorches your undead flesh!", o_name); + + cave_no_regen = TRUE; + + /* Get an object description */ + object_desc(o_name, o_ptr, TRUE, 0); + + sprintf(ouch, "wielding %s", o_name); + take_hit(1, ouch); + } + } + + /* Drown in deep water unless the player have levitation, water walking + water breathing, or magic breathing.*/ + if (!p_ptr->ffall && !p_ptr->walk_water && !p_ptr->magical_breath && + !p_ptr->water_breath && + (cave[p_ptr->py][p_ptr->px].feat == FEAT_DEEP_WATER)) + { + if (calc_total_weight() > ((weight_limit()) / 2)) + { + /* Take damage */ + msg_print("You are drowning!"); + take_hit(randint(p_ptr->lev), "drowning"); + cave_no_regen = TRUE; + } + } + + + /* Spectres -- take damage when moving through walls */ + + /* + * Added: ANYBODY takes damage if inside through walls + * without wraith form -- NOTE: Spectres will never be + * reduced below 0 hp by being inside a stone wall; others + * WILL BE! + */ + if (!cave_floor_bold(p_ptr->py, p_ptr->px)) + { + int feature = cave[p_ptr->py][p_ptr->px].feat; + + /* Player can walk through or fly over trees */ + if ((has_ability(AB_TREE_WALK) || p_ptr->fly) && (feature == FEAT_TREES)) + { + /* Do nothing */ + } + /* Player can climb over mountains */ + else if ((p_ptr->climb) && (f_info[feature].flags1 & FF1_CAN_CLIMB)) + { + /* Do nothing */ + } + else if (PRACE_FLAG(PR1_SEMI_WRAITH) && (!p_ptr->wraith_form) && (f_info[cave[p_ptr->py][p_ptr->px].feat].flags1 & FF1_CAN_PASS)) + { + int amt = 1 + ((p_ptr->lev) / 5); + + cave_no_regen = TRUE; + if (amt > p_ptr->chp - 1) amt = p_ptr->chp - 1; + take_hit(amt, " walls ..."); + } + } + + + /* Take damage from cuts */ + if ((p_ptr->cut) && !(p_ptr->invuln)) + { + /* Mortal wound or Deep Gash */ + if (p_ptr->cut > 200) + { + i = 3; + } + + /* Severe cut */ + else if (p_ptr->cut > 100) + { + i = 2; + } + + /* Other cuts */ + else + { + i = 1; + } + + /* Take damage */ + take_hit(i, "a fatal wound"); + } + + + /*** Check the Food, and Regenerate ***/ + + /* Digest normally */ + if (p_ptr->food < PY_FOOD_MAX) + { + /* Every 100 game turns */ + if ((turn % 100) == 0) + { + int speed_use = p_ptr->pspeed; + + /* Maximum */ + if (speed_use > 199) + { + speed_use = 199; + } + + /* Minimum */ + else if (speed_use < 0) + { + speed_use = 0; + } + + /* Basic digestion rate based on speed */ + i = extract_energy[speed_use] * 2; + + /* Regeneration takes more food */ + if (p_ptr->regenerate) i += 30; + + /* Regeneration takes more food */ + if (p_ptr->tim_regen) i += p_ptr->tim_regen_pow / 10; + + /* Invisibility consume a lot of food */ + i += p_ptr->invis / 2; + + /* Invulnerability consume a lot of food */ + if (p_ptr->invuln) i += 40; + + /* Wraith Form consume a lot of food */ + if (p_ptr->wraith_form) i += 30; + + /* Get the weapon */ + o_ptr = &p_ptr->inventory[INVEN_WIELD]; + + /* Examine the sword */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* Hitpoints multiplier consume a lot of food */ + if (o_ptr->k_idx && (f2 & (TR2_LIFE))) i += o_ptr->pval * 5; + + /* Slow digestion takes less food */ + if (p_ptr->slow_digest) i -= 10; + + /* Minimal digestion */ + if (i < 1) i = 1; + + /* Digest some food */ + (void)set_food(p_ptr->food - i); + } + } + + /* Digest quickly when gorged */ + else + { + /* Digest a lot of food */ + (void)set_food(p_ptr->food - 100); + } + + /* Starve to death (slowly) */ + if (p_ptr->food < PY_FOOD_STARVE) + { + /* Calculate damage */ + i = (PY_FOOD_STARVE - p_ptr->food) / 10; + + /* Take damage */ + if (!(p_ptr->invuln)) take_hit(i, "starvation"); + } + + /* Default regeneration */ + regen_amount = PY_REGEN_NORMAL; + + /* Getting Weak */ + if (p_ptr->food < PY_FOOD_WEAK) + { + /* Lower regeneration */ + if (p_ptr->food < PY_FOOD_STARVE) + { + regen_amount = 0; + } + else if (p_ptr->food < PY_FOOD_FAINT) + { + regen_amount = PY_REGEN_FAINT; + } + else + { + regen_amount = PY_REGEN_WEAK; + } + + /* Getting Faint */ + if (p_ptr->food < PY_FOOD_FAINT) + { + /* Faint occasionally */ + if (!p_ptr->paralyzed && (rand_int(100) < 10)) + { + /* Message */ + msg_print("You faint from the lack of food."); + disturb(1); + + /* Hack -- faint (bypass free action) */ + (void)set_paralyzed(1 + rand_int(5)); + } + } + } + + /* Are we walking the pattern? */ + if (!p_ptr->wild_mode && pattern_effect()) + { + cave_no_regen = TRUE; + } + else + { + /* Regeneration ability */ + if (p_ptr->regenerate) + { + regen_amount = regen_amount * 2; + } + } + + + /* Searching or Resting */ + if (p_ptr->searching || resting) + { + regen_amount = regen_amount * 2; + } + + if (total_friends) + { + int upkeep_divider = 20; + + if (has_ability(AB_PERFECT_CASTING)) + upkeep_divider = 15; + + if (total_friends > 1 + (p_ptr->lev / (upkeep_divider))) + { + upkeep_factor = (total_friend_levels); + + if (upkeep_factor > 100) upkeep_factor = 100; + else if (upkeep_factor < 10) upkeep_factor = 10; + } + } + + /* Regenerate the mana */ + if (p_ptr->csp < p_ptr->msp) + { + if (upkeep_factor) + { + s16b upkeep_regen = (((100 - upkeep_factor) * regen_amount) / 100); + regenmana(upkeep_regen); + } + else + { + regenmana(regen_amount); + } + } + + /* Eru piety incraese with time */ + if (((turn % 100) == 0) && (!p_ptr->did_nothing) && (!p_ptr->wild_mode)) + { + NOT_PRAY_GOD(GOD_ERU) + { + int inc = wisdom_scale(10); + + /* Increase by wisdom/4 */ + if (!inc) inc = 1; + inc_piety(GOD_ERU, inc); + } + } + /* Most gods piety decrease with time */ + if (((turn % 300) == 0) && (!p_ptr->did_nothing) && (!p_ptr->wild_mode) && (dun_level)) + { + GOD(GOD_MANWE) + { + int dec = 4 - wisdom_scale(3); + + PRAY_GOD(GOD_MANWE) + dec++; + if (PRACE_FLAG(PR1_ELF)) + dec -= wisdom_scale(2); + if (dec < 1) dec = 1; + inc_piety(GOD_MANWE, -dec); + } + GOD(GOD_MELKOR) + { + int dec = 8 - wisdom_scale(6); + + PRAY_GOD(GOD_MELKOR) + dec++; + if (PRACE_FLAG(PR1_ELF)) + dec += 5 - wisdom_scale(4); + if (dec < 1) dec = 1; + inc_piety(GOD_MELKOR, -dec); + } + PRAY_GOD(GOD_TULKAS) + { + int dec = 4 - wisdom_scale(3); + + if (dec < 1) dec = 1; + inc_piety(GOD_TULKAS, -dec); + } + } + /* Yavanna piety decrease with time */ + if (((turn % 400) == 0) && (!p_ptr->did_nothing) && (!p_ptr->wild_mode) && (dun_level)) + { + GOD(GOD_YAVANNA) + { + int dec = 5 - wisdom_scale(3); + + /* Blech what an hideous hack */ + if (!strcmp(rp_ptr->title + rp_name, "Ent")) + dec -= wisdom_scale(2); + if (dec < 1) dec = 1; + inc_piety(GOD_YAVANNA, -dec); + } + } + p_ptr->did_nothing = FALSE; + + /* Increase regen by tim regen */ + if (p_ptr->tim_regen) regen_amount += p_ptr->tim_regen_pow; + + /* Poisoned or cut yields no healing */ + if (p_ptr->poisoned) regen_amount = 0; + if (p_ptr->cut) regen_amount = 0; + + /* Special floor -- Pattern, in a wall -- yields no healing */ + if (cave_no_regen) regen_amount = 0; + + /* Being over grass allows Yavanna to regen you */ + PRAY_GOD(GOD_YAVANNA) + { + if (cave[p_ptr->py][p_ptr->px].feat == FEAT_GRASS) + { + regen_amount += 200 + wisdom_scale(800); + } + } + + /* Regenerate Hit Points if needed */ + if ((p_ptr->chp < p_ptr->mhp) && !cave_no_regen) + { + if ((cave[p_ptr->py][p_ptr->px].feat < FEAT_PATTERN_END) && + (cave[p_ptr->py][p_ptr->px].feat >= FEAT_PATTERN_START)) + { + /* Hmmm. this should never happen? */ + regenhp(regen_amount / 5); + } + else + { + regenhp(regen_amount); + } + } + + + /*** Timeout Various Things ***/ + + /* Handle temporary stat drains */ + for (i = 0; i < 6; i++) + { + if (p_ptr->stat_cnt[i] > 0) + { + p_ptr->stat_cnt[i]--; + if (p_ptr->stat_cnt[i] == 0) + { + do_res_stat(i, FALSE); + } + } + } + + /* Hack -- Hallucinating */ + if (p_ptr->image) + { + (void)set_image(p_ptr->image - 1); + } + + /* Holy Aura */ + if (p_ptr->holy) + { + (void)set_holy(p_ptr->holy - 1); + } + + /* Soul absorbtion */ + if (p_ptr->absorb_soul) + { + (void)set_absorb_soul(p_ptr->absorb_soul - 1); + } + + /* Undead loose Death Points */ + if (p_ptr->necro_extra & CLASS_UNDEAD) + { + int old_chp = p_ptr->chp; + int warning = (p_ptr->mhp * hitpoint_warn / 10); + + /* Bypass invulnerability and wraithform */ + p_ptr->chp--; + + /* Display the hitpoints */ + p_ptr->redraw |= (PR_HP); + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + + /* Dead player */ + if (p_ptr->chp < 0) + { + bool_ old_quick = quick_messages; + + /* Sound */ + sound(SOUND_DEATH); + + /* Hack -- Note death */ + if (!last_words) + { + msg_print("You die."); + msg_print(NULL); + } + else + { + char death_message[80]; + + (void)get_rnd_line("death.txt", death_message); + msg_print(death_message); + } + + /* Note cause of death */ + (void)strcpy(died_from, "being undead too long"); + + if (p_ptr->image) strcat(died_from, "(?)"); + + /* No longer a winner */ + total_winner = FALSE; + + /* Leaving */ + p_ptr->leaving = TRUE; + + /* Note death */ + death = TRUE; + + quick_messages = FALSE; + if (get_check("Make a last screenshot? ")) + { + do_cmd_html_dump(); + } + quick_messages = old_quick; + + /* Dead */ + return; + } + + /* Hitpoint warning */ + if (p_ptr->chp < warning) + { + /* Hack -- bell on first notice */ + if (alert_hitpoint && (old_chp > warning)) bell(); + + sound(SOUND_WARN); + + /* Message */ + msg_print("*** LOW DEATHPOINT WARNING! ***"); + msg_print(NULL); + } + } + + /* Walk water */ + if (p_ptr->walk_water) + { + (void)set_walk_water(p_ptr->walk_water - 1); + } + + /* True Strike */ + if (p_ptr->strike) + { + (void)set_strike(p_ptr->strike - 1); + } + + /* Meditation */ + if (p_ptr->meditation) + { + (void)set_meditation(p_ptr->meditation - 1); + } + + /* Timed project */ + if (p_ptr->tim_project) + { + (void)set_project(p_ptr->tim_project - 1, p_ptr->tim_project_gf, p_ptr->tim_project_dam, p_ptr->tim_project_rad, p_ptr->tim_project_flag); + } + + /* Timed roots */ + if (p_ptr->tim_roots) + { + (void)set_roots(p_ptr->tim_roots - 1, p_ptr->tim_roots_ac, p_ptr->tim_roots_dam); + } + + /* Timed breath */ + if (p_ptr->tim_water_breath) + { + (void)set_tim_breath(p_ptr->tim_water_breath - 1, FALSE); + } + if (p_ptr->tim_magic_breath) + { + (void)set_tim_breath(p_ptr->tim_magic_breath - 1, TRUE); + } + + /* Timed precognition */ + if (p_ptr->tim_precognition > 0) + { + set_tim_precognition(p_ptr->tim_precognition - 1); + } + + /* Timed regen */ + if (p_ptr->tim_regen) + { + (void)set_tim_regen(p_ptr->tim_regen - 1, p_ptr->tim_regen_pow); + } + + /* Timed Disrupt shield */ + if (p_ptr->disrupt_shield) + { + (void)set_disrupt_shield(p_ptr->disrupt_shield - 1); + } + + /* Timed Parasite */ + if (p_ptr->parasite) + { + (void)set_parasite(p_ptr->parasite - 1, p_ptr->parasite_r_idx); + } + + /* Timed Reflection */ + if (p_ptr->tim_reflect) + { + (void)set_tim_reflect(p_ptr->tim_reflect - 1); + } + + /* Timed Prob Travel */ + if (p_ptr->prob_travel) + { + (void)set_prob_travel(p_ptr->prob_travel - 1); + } + + /* Timed Time Resistance */ + if (p_ptr->tim_res_time) + { + (void)set_tim_res_time(p_ptr->tim_res_time - 1); + } + + /* Timed Levitation */ + if (p_ptr->tim_ffall) + { + (void)set_tim_ffall(p_ptr->tim_ffall - 1); + } + if (p_ptr->tim_fly) + { + (void)set_tim_fly(p_ptr->tim_fly - 1); + } + + /* Thunderstorm */ + if (p_ptr->tim_thunder) + { + int dam = damroll(p_ptr->tim_thunder_p1, p_ptr->tim_thunder_p2); + int i, tries = 600; + monster_type *m_ptr = NULL; + + while (tries) + { + /* Access the monster */ + m_ptr = &m_list[i = rand_range(1, m_max - 1)]; + + tries--; + + /* Ignore "dead" monsters */ + if (!m_ptr->r_idx) continue; + + /* Cant see ? cant hit */ + if (!los(p_ptr->py, p_ptr->px, m_ptr->fy, m_ptr->fx)) continue; + + /* Do not hurt friends! */ + if (is_friend(m_ptr) >= 0) continue; + break; + } + + if (tries) + { + char m_name[80]; + + monster_desc(m_name, m_ptr, 0); + msg_format("Lightning strikes %s.", m_name); + project(0, 0, m_ptr->fy, m_ptr->fx, dam / 3, GF_ELEC, + PROJECT_KILL | PROJECT_ITEM | PROJECT_HIDE); + project(0, 0, m_ptr->fy, m_ptr->fx, dam / 3, GF_LITE, + PROJECT_KILL | PROJECT_ITEM | PROJECT_HIDE); + project(0, 0, m_ptr->fy, m_ptr->fx, dam / 3, GF_SOUND, + PROJECT_KILL | PROJECT_ITEM | PROJECT_HIDE); + } + + (void)set_tim_thunder(p_ptr->tim_thunder - 1, p_ptr->tim_thunder_p1, p_ptr->tim_thunder_p2); + } + + /* Poisonned hands */ + if (p_ptr->tim_poison) + { + (void)set_poison(p_ptr->tim_poison - 1); + } + + /* Timed Fire Aura */ + if (p_ptr->tim_fire_aura) + { + (void)set_tim_fire_aura(p_ptr->tim_fire_aura - 1); + } + + /* Brightness */ + if (p_ptr->tim_lite) + { + (void)set_lite(p_ptr->tim_lite - 1); + } + + /* Blindness */ + if (p_ptr->blind) + { + (void)set_blind(p_ptr->blind - 1); + } + + /* Timed no_breeds */ + if (no_breeds) + { + (void)set_no_breeders(no_breeds - 1); + } + + /* Timed mimic */ + if (p_ptr->tim_mimic) + { + (void)set_mimic(p_ptr->tim_mimic - 1, p_ptr->mimic_form, p_ptr->mimic_level); + } + + /* Timed special move commands */ + if (p_ptr->immov_cntr) + { + p_ptr->immov_cntr--; + } + + /* Timed invisibility */ + if (p_ptr->tim_invisible) + { + (void)set_invis(p_ptr->tim_invisible - 1, p_ptr->tim_inv_pow); + } + + /* Times see-invisible */ + if (p_ptr->tim_invis) + { + (void)set_tim_invis(p_ptr->tim_invis - 1); + } + + /* Timed esp */ + if (p_ptr->tim_esp) + { + (void)set_tim_esp(p_ptr->tim_esp - 1); + } + + /* Timed infra-vision */ + if (p_ptr->tim_infra) + { + (void)set_tim_infra(p_ptr->tim_infra - 1); + } + + /* Paralysis */ + if (p_ptr->paralyzed) + { + dec_paralyzed(); + } + + /* Confusion */ + if (p_ptr->confused) + { + (void)set_confused(p_ptr->confused - 1); + } + + /* Afraid */ + if (p_ptr->afraid) + { + (void)set_afraid(p_ptr->afraid - 1); + } + + /* Fast */ + if (p_ptr->fast) + { + (void)set_fast(p_ptr->fast - 1, p_ptr->speed_factor); + } + + /* Light speed */ + if (p_ptr->lightspeed) + { + (void)set_light_speed(p_ptr->lightspeed - 1); + } + + /* Slow */ + if (p_ptr->slow) + { + (void)set_slow(p_ptr->slow - 1); + } + + /* Protection from evil */ + if (p_ptr->protevil) + { + (void)set_protevil(p_ptr->protevil - 1); + } + + /* Protection from good */ + if (p_ptr->protgood) + { + (void)set_protgood(p_ptr->protgood - 1); + } + + /* Protection from undead */ + if (p_ptr->protundead) + { + (void)set_protundead(p_ptr->protundead - 1); + } + + /* Invulnerability */ + if (p_ptr->invuln) + { + (void)set_invuln(p_ptr->invuln - 1); + } + + /* Wraith form */ + if (p_ptr->tim_wraith) + { + (void)set_shadow(p_ptr->tim_wraith - 1); + } + + /* Heroism */ + if (p_ptr->hero) + { + (void)set_hero(p_ptr->hero - 1); + } + + /* Super Heroism */ + if (p_ptr->shero) + { + (void)set_shero(p_ptr->shero - 1); + } + + /* Blessed */ + if (p_ptr->blessed) + { + (void)set_blessed(p_ptr->blessed - 1); + } + + /* Shield */ + if (p_ptr->shield) + { + (void)set_shield(p_ptr->shield - 1, p_ptr->shield_power, p_ptr->shield_opt, p_ptr->shield_power_opt, p_ptr->shield_power_opt2); + } + + /* Oppose Acid */ + if (p_ptr->oppose_acid) + { + (void)set_oppose_acid(p_ptr->oppose_acid - 1); + } + + /* Oppose Lightning */ + if (p_ptr->oppose_elec) + { + (void)set_oppose_elec(p_ptr->oppose_elec - 1); + } + + /* Oppose Fire */ + if (p_ptr->oppose_fire) + { + (void)set_oppose_fire(p_ptr->oppose_fire - 1); + } + + /* Oppose Cold */ + if (p_ptr->oppose_cold) + { + (void)set_oppose_cold(p_ptr->oppose_cold - 1); + } + + /* Oppose Poison */ + if (p_ptr->oppose_pois) + { + (void)set_oppose_pois(p_ptr->oppose_pois - 1); + } + + /* Oppose Light & Dark */ + if (p_ptr->oppose_ld) + { + (void)set_oppose_ld(p_ptr->oppose_ld - 1); + } + + /* Oppose Chaos & Confusion */ + if (p_ptr->oppose_cc) + { + (void)set_oppose_cc(p_ptr->oppose_cc - 1); + } + + /* Oppose Sound & Shards */ + if (p_ptr->oppose_ss) + { + (void)set_oppose_ss(p_ptr->oppose_ss - 1); + } + + /* Oppose Nexus */ + if (p_ptr->oppose_nex) + { + (void)set_oppose_nex(p_ptr->oppose_nex - 1); + } + + /* Mental Barrier */ + if (p_ptr->tim_mental_barrier) + { + (void)set_mental_barrier(p_ptr->tim_mental_barrier - 1); + } + + /* The rush */ + if (p_ptr->rush) + { + (void)set_rush(p_ptr->rush - 1); + } + + + /* Timed mimicry */ + if (get_skill(SKILL_MIMICRY)) + { + /* Extract the value and the flags */ + u32b value = p_ptr->mimic_extra >> 16; + + u32b att = p_ptr->mimic_extra & 0xFFFF; + + if ((att & CLASS_LEGS) || (att & CLASS_WALL) || (att & CLASS_ARMS)) + { + value--; + + if (!value) + { + if (att & CLASS_LEGS) msg_print("You lose your extra pair of legs."); + if (att & CLASS_ARMS) msg_print("You lose your extra pair of arms."); + if (att & CLASS_WALL) msg_print("You lose your affinity for walls."); + + att &= ~(CLASS_ARMS); + att &= ~(CLASS_LEGS); + att &= ~(CLASS_WALL); + + if (disturb_state) disturb(0); + } + + p_ptr->update |= (PU_BODY); + p_ptr->mimic_extra = att + (value << 16); + } + } + + + /*** Poison and Stun and Cut ***/ + + /* Poison */ + if (p_ptr->poisoned) + { + int adjust = (adj_con_fix[p_ptr->stat_ind[A_CON]] + 1); + + /* Apply some healing */ + (void)set_poisoned(p_ptr->poisoned - adjust); + } + + /* Stun */ + if (p_ptr->stun) + { + int adjust = (adj_con_fix[p_ptr->stat_ind[A_CON]] + 1); + + /* Apply some healing */ + (void)set_stun(p_ptr->stun - adjust); + } + + /* Cut */ + if (p_ptr->cut) + { + int adjust = (adj_con_fix[p_ptr->stat_ind[A_CON]] + 1); + + /* Hack -- Truly "mortal" wound */ + if (p_ptr->cut > 1000) adjust = 0; + + /* Apply some healing */ + (void)set_cut(p_ptr->cut - adjust); + } + + /* Hack - damage done by the dungeon -SC- */ + if ((dun_level != 0) && (d_ptr->d_frequency[0] != 0)) + { + int i, j, k; + + /* Apply damage to every grid in the dungeon */ + for (i = 0; i < 4; i++) + { + /* Check the frequency */ + if (d_ptr->d_frequency[i] == 0) continue; + + if (((turn % d_ptr->d_frequency[i]) == 0) && + ((d_ptr->d_side[i] != 0) || (d_ptr->d_dice[i] != 0))) + { + for (j = 0; j < cur_hgt - 1; j++) + { + for (k = 0; k < cur_wid - 1; k++) + { + int l, dam = 0; + + if (!(dungeon_flags1 & DF1_DAMAGE_FEAT)) + { + /* If the grid is empty, skip it */ + if ((cave[j][k].o_idx == 0) && + ((j != p_ptr->py) && (i != p_ptr->px))) continue; + } + + /* Let's not hurt poor monsters */ + if (cave[j][k].m_idx) continue; + + /* Roll damage */ + for (l = 0; l < d_ptr->d_dice[i]; l++) + { + dam += randint(d_ptr->d_side[i]); + } + + /* Apply damage */ + project( -100, 0, j, k, dam, d_ptr->d_type[i], + PROJECT_KILL | PROJECT_ITEM | PROJECT_HIDE); + } + } + } + } + } + + /* handle spell effects */ + if (!p_ptr->wild_mode) + { + /* + * I noticed significant performance degrade after the introduction + * of staying spell effects. I believe serious optimisation effort + * is required before another release. + * + * More important is to fix that display weirdness... + * + * It seems that the game never expects that monster deaths and + * terrain feature changes should happen here... Moving these + * to process_player() [before resting code, with "every 10 game turn" + * 'if'] may or may not fix the problem... -- pelpel to DG + */ + for (j = 0; j < cur_hgt - 1; j++) + { + for (i = 0; i < cur_wid - 1; i++) + { + int e = cave[j][i].effect; + + if (e) + { + effect_type *e_ptr = &effects[e]; + + if (e_ptr->time) + { + /* Apply damage */ + project(0, 0, j, i, e_ptr->dam, e_ptr->type, + PROJECT_KILL | PROJECT_ITEM | PROJECT_HIDE); + } + else + { + cave[j][i].effect = 0; + } + + if ((e_ptr->flags & EFF_WAVE) && !(e_ptr->flags & EFF_LAST)) + { + if (distance(e_ptr->cy, e_ptr->cx, j, i) < e_ptr->rad - 1) + cave[j][i].effect = 0; + } + else if ((e_ptr->flags & EFF_STORM) && !(e_ptr->flags & EFF_LAST)) + { + cave[j][i].effect = 0; + } + + lite_spot(j, i); + } + } + } + + /* Reduce & handle effects */ + for (i = 0; i < MAX_EFFECTS; i++) + { + /* Skip empty slots */ + if (effects[i].time == 0) continue; + + /* Reduce duration */ + effects[i].time--; + + /* Creates a "wave" effect*/ + if (effects[i].flags & EFF_WAVE) + { + effect_type *e_ptr = &effects[i]; + int x, y, z; + + e_ptr->rad++; + + /* What a frelling ugly line of ifs ... */ + if (effects[i].flags & EFF_DIR8) + for (y = e_ptr->cy - e_ptr->rad, z = 0; y <= e_ptr->cy; y++, z++) + { + for (x = e_ptr->cx - (e_ptr->rad - z); x <= e_ptr->cx + (e_ptr->rad - z); x++) + { + if (!in_bounds(y, x)) continue; + + if (los(e_ptr->cy, e_ptr->cx, y, x) && + (distance(e_ptr->cy, e_ptr->cx, y, x) == e_ptr->rad)) + cave[y][x].effect = i; + } + } + else if (effects[i].flags & EFF_DIR2) + for (y = e_ptr->cy, z = e_ptr->rad; y <= e_ptr->cy + e_ptr->rad; y++, z--) + { + for (x = e_ptr->cx - (e_ptr->rad - z); x <= e_ptr->cx + (e_ptr->rad - z); x++) + { + if (!in_bounds(y, x)) continue; + + if (los(e_ptr->cy, e_ptr->cx, y, x) && + (distance(e_ptr->cy, e_ptr->cx, y, x) == e_ptr->rad)) + cave[y][x].effect = i; + } + } + else if (effects[i].flags & EFF_DIR6) + for (x = e_ptr->cx, z = e_ptr->rad; x <= e_ptr->cx + e_ptr->rad; x++, z--) + { + for (y = e_ptr->cy - (e_ptr->rad - z); y <= e_ptr->cy + (e_ptr->rad - z); y++) + { + if (!in_bounds(y, x)) continue; + + if (los(e_ptr->cy, e_ptr->cx, y, x) && + (distance(e_ptr->cy, e_ptr->cx, y, x) == e_ptr->rad)) + cave[y][x].effect = i; + } + } + else if (effects[i].flags & EFF_DIR4) + for (x = e_ptr->cx - e_ptr->rad, z = 0; x <= e_ptr->cx; x++, z++) + { + for (y = e_ptr->cy - (e_ptr->rad - z); y <= e_ptr->cy + (e_ptr->rad - z); y++) + { + if (!in_bounds(y, x)) continue; + + if (los(e_ptr->cy, e_ptr->cx, y, x) && + (distance(e_ptr->cy, e_ptr->cx, y, x) == e_ptr->rad)) + cave[y][x].effect = i; + } + } + else if (effects[i].flags & EFF_DIR9) + for (y = e_ptr->cy - e_ptr->rad; y <= e_ptr->cy; y++) + { + for (x = e_ptr->cx; x <= e_ptr->cx + e_ptr->rad; x++) + { + if (!in_bounds(y, x)) continue; + + if (los(e_ptr->cy, e_ptr->cx, y, x) && + (distance(e_ptr->cy, e_ptr->cx, y, x) == e_ptr->rad)) + cave[y][x].effect = i; + } + } + else if (effects[i].flags & EFF_DIR1) + for (y = e_ptr->cy; y <= e_ptr->cy + e_ptr->rad; y++) + { + for (x = e_ptr->cx - e_ptr->rad; x <= e_ptr->cx; x++) + { + if (!in_bounds(y, x)) continue; + + if (los(e_ptr->cy, e_ptr->cx, y, x) && + (distance(e_ptr->cy, e_ptr->cx, y, x) == e_ptr->rad)) + cave[y][x].effect = i; + } + } + else if (effects[i].flags & EFF_DIR7) + for (y = e_ptr->cy - e_ptr->rad; y <= e_ptr->cy; y++) + { + for (x = e_ptr->cx - e_ptr->rad; x <= e_ptr->cx; x++) + { + if (!in_bounds(y, x)) continue; + + if (los(e_ptr->cy, e_ptr->cx, y, x) && + (distance(e_ptr->cy, e_ptr->cx, y, x) == e_ptr->rad)) + cave[y][x].effect = i; + } + } + else if (effects[i].flags & EFF_DIR3) + for (y = e_ptr->cy; y <= e_ptr->cy + e_ptr->rad; y++) + { + for (x = e_ptr->cx; x <= e_ptr->cx + e_ptr->rad; x++) + { + if (!in_bounds(y, x)) continue; + + if (los(e_ptr->cy, e_ptr->cx, y, x) && + (distance(e_ptr->cy, e_ptr->cx, y, x) == e_ptr->rad)) + cave[y][x].effect = i; + } + } + else + for (y = e_ptr->cy - e_ptr->rad; y <= e_ptr->cy + e_ptr->rad; y++) + { + for (x = e_ptr->cx - e_ptr->rad; x <= e_ptr->cx + e_ptr->rad; x++) + { + if (!in_bounds(y, x)) continue; + + /* This is *slow* -- pelpel */ + if (los(e_ptr->cy, e_ptr->cx, y, x) && + (distance(e_ptr->cy, e_ptr->cx, y, x) == e_ptr->rad)) + cave[y][x].effect = i; + } + } + } + /* Creates a "storm" effect*/ + else if (effects[i].flags & EFF_STORM) + { + effect_type *e_ptr = &effects[i]; + int x, y; + + e_ptr->cy = p_ptr->py; + e_ptr->cx = p_ptr->px; + for (y = e_ptr->cy - e_ptr->rad; y <= e_ptr->cy + e_ptr->rad; y++) + { + for (x = e_ptr->cx - e_ptr->rad; x <= e_ptr->cx + e_ptr->rad; x++) + { + if (!in_bounds(y, x)) continue; + + if (los(e_ptr->cy, e_ptr->cx, y, x) && + (distance(e_ptr->cy, e_ptr->cx, y, x) <= e_ptr->rad)) + { + cave[y][x].effect = i; + lite_spot(y, x); + } + } + } + } + } + + apply_effect(p_ptr->py, p_ptr->px); + } + + /* Arg cannot breath? */ + if ((dungeon_flags2 & DF2_WATER_BREATH) && (!p_ptr->water_breath)) + { + cmsg_print(TERM_L_RED, "You cannot breathe water! You suffocate!"); + take_hit(damroll(3, p_ptr->lev), "suffocating"); + } + if ((dungeon_flags2 & DF2_NO_BREATH) && (!p_ptr->magical_breath)) + { + cmsg_print(TERM_L_RED, "There is no air there! You suffocate!"); + take_hit(damroll(3, p_ptr->lev), "suffocating"); + } + + /* + * Every 1500 turns, warn about any Black Breath not gotten from + * an equipped object, and stop any resting. -LM- + * + * It's apparent that someone has halved the frequency... -- pelpel + */ + if (((turn % 3000) == 0) && p_ptr->black_breath) + { + u32b f1, f2, f3, f4, f5; + + bool_ be_silent = FALSE; + + /* check all equipment for the Black Breath flag. */ + for (i = INVEN_WIELD; i < INVEN_TOTAL; i++) + { + o_ptr = &p_ptr->inventory[i]; + + /* Skip non-objects */ + if (!o_ptr->k_idx) continue; + + /* Extract the item flags */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* No messages if object has the flag, to avoid annoyance. */ + if (f4 & (TR4_BLACK_BREATH)) be_silent = TRUE; + + } + /* If we are allowed to speak, warn and disturb. */ + + if (!be_silent) + { + cmsg_print(TERM_L_DARK, "The Black Breath saps your soul!"); + disturb(0); + } + } + + + /*** Process Light ***/ + + /* Check for light being wielded */ + o_ptr = &p_ptr->inventory[INVEN_LITE]; + + /* Burn some fuel in the current lite */ + if (o_ptr->tval == TV_LITE) + { + /* Extract the item flags */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* Hack -- Use some fuel */ + if ((f4 & TR4_FUEL_LITE) && (o_ptr->timeout > 0)) + { + /* Decrease life-span */ + o_ptr->timeout--; + + /* Hack -- notice interesting fuel steps */ + if ((o_ptr->timeout < 100) || ((o_ptr->timeout % 100) == 0)) + { + /* Window stuff */ + p_ptr->window |= (PW_EQUIP); + } + + /* Hack -- Special treatment when blind */ + if (p_ptr->blind) + { + /* Hack -- save some light for later */ + if (o_ptr->timeout == 0) o_ptr->timeout++; + } + + /* The light is now out */ + else if (o_ptr->timeout < 1) + { + disturb(0); + cmsg_print(TERM_YELLOW, "Your light has gone out!"); + } + + /* The light is getting dim */ + else if ((o_ptr->timeout < 100) && (o_ptr->timeout % 10 == 0)) + { + if (disturb_minor) disturb(0); + cmsg_print(TERM_YELLOW, "Your light is growing faint."); + } + } + } + + /* Calculate torch radius */ + p_ptr->update |= (PU_TORCH); + + + /*** Process Inventory ***/ + + /* + * Handle experience draining. In Oangband, the effect is worse, + * especially for high-level characters. As per Tolkien, hobbits + * are resistant. + */ + if (p_ptr->black_breath) + { + byte chance = 0; + int plev = p_ptr->lev; + + if (PRACE_FLAG(PR1_RESIST_BLACK_BREATH)) chance = 2; + else chance = 5; + + if ((rand_int(100) < chance) && (p_ptr->exp > 0)) + { + p_ptr->exp -= 1 + plev / 5; + p_ptr->max_exp -= 1 + plev / 5; + (void)do_dec_stat(rand_int(6), STAT_DEC_NORMAL); + check_experience(); + } + } + + /* Drain Mana */ + if (p_ptr->drain_mana && p_ptr->csp) + { + p_ptr->csp -= p_ptr->drain_mana; + if (magik(30)) p_ptr->csp -= p_ptr->drain_mana; + + if (p_ptr->csp < 0) + { + p_ptr->csp = 0; + disturb(0); + } + + /* Redraw */ + p_ptr->redraw |= (PR_MANA); + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + } + + /* Partial summons drain mana */ + if (p_ptr->maintain_sum) + { + u32b oldcsp = p_ptr->csp; + p_ptr->csp -= p_ptr->maintain_sum / 10000; + + if (p_ptr->csp < 0) + { + p_ptr->csp = 0; + disturb(0); + + p_ptr->maintain_sum = 0; + } + else + { + /* Leave behind any fractional sp */ + p_ptr->maintain_sum -= (oldcsp - p_ptr->csp) * 10000; + } + + /* Redraw */ + p_ptr->redraw |= (PR_MANA); + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + + } + + /* Drain Hitpoints */ + if (p_ptr->drain_life) + { + int drain = p_ptr->drain_life + rand_int(p_ptr->mhp / 100); + + p_ptr->chp -= (drain < p_ptr->chp ? drain : p_ptr->chp); + + if (p_ptr->chp == 0) + { + disturb(0); + } + + /* Redraw */ + p_ptr->redraw |= (PR_HP); + + /* Window stuff */ + p_ptr->window |= (PW_PLAYER); + + } + + /* Handle experience draining */ + if (p_ptr->exp_drain) + { + if ((rand_int(100) < 10) && (p_ptr->exp > 0)) + { + p_ptr->exp--; + p_ptr->max_exp--; + check_experience(); + } + } + + /* Process equipment */ + for (j = 0, i = INVEN_WIELD; i < INVEN_TOTAL; i++) + { + /* Get the object */ + o_ptr = &p_ptr->inventory[i]; + + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + + /* TY Curse */ + if ((f3 & TR3_TY_CURSE) && (rand_int(TY_CURSE_CHANCE) == 0)) + { + activate_ty_curse(); + } + + /* DG Curse */ + if ((f4 & TR4_DG_CURSE) && (rand_int(DG_CURSE_CHANCE) == 0)) + { + activate_dg_curse(); + + /* The object recurse itself ! */ + o_ptr->ident |= IDENT_CURSED; + } + + /* Auto Curse */ + if ((f3 & TR3_AUTO_CURSE) && (rand_int(AUTO_CURSE_CHANCE) == 0)) + { + /* The object recurse itself ! */ + o_ptr->ident |= IDENT_CURSED; + } + + /* + * Hack: Uncursed teleporting items (e.g. Dragon Weapons) + * can actually be useful! + */ + if ((f3 & TR3_TELEPORT) && (rand_int(100) < 1)) + { + if ((o_ptr->ident & IDENT_CURSED) && !p_ptr->anti_tele) + { + disturb(0); + + /* Teleport player */ + teleport_player(40); + } + else + { + if (p_ptr->wild_mode || + (o_ptr->note && strchr(quark_str(o_ptr->note), '.'))) + { + /* Do nothing */ + /* msg_print("Teleport aborted.") */; + } + else if (get_check("Teleport? ")) + { + disturb(0); + teleport_player(50); + } + } + } + + + /* Skip non-objects */ + if (!o_ptr->k_idx) continue; + + /* Hack: Skip wielded lights that need fuel (already handled above) */ + if ((i == INVEN_LITE) && (o_ptr->tval == TV_LITE) && (f4 & TR4_FUEL_LITE)) continue; + + /* Recharge activatable objects */ + if (o_ptr->timeout > 0) + { + /* Recharge */ + o_ptr->timeout--; + + /* Notice changes */ + if (o_ptr->timeout == 0) + { + recharged_notice(o_ptr); + j++; + } + } + + /* Recharge second spell in Mage Staffs of Spells */ + if (is_ego_p(o_ptr, EGO_MSTAFF_SPELL) && (o_ptr->xtra2 > 0)) + { + /* Recharge */ + o_ptr->xtra2--; + + /* Notice changes */ + if (o_ptr->xtra2 == 0) j++; + } + } + + /* Notice changes */ + if (j) + { + /* Window stuff */ + p_ptr->window |= (PW_EQUIP); + } + + /* Recharge rods */ + for (j = 0, i = 0; i < INVEN_TOTAL; i++) + { + o_ptr = &p_ptr->inventory[i]; + + /* Skip non-objects */ + if (!o_ptr->k_idx) continue; + + /* Examine the rod */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* Temporary items are destroyed */ + if (f5 & TR5_TEMPORARY) + { + o_ptr->timeout--; + + if (o_ptr->timeout <= 0) + { + inc_stack_size(i, -99); + + /* Combine and Reorder pack */ + p_ptr->notice |= (PN_COMBINE | PN_REORDER); + } + } + + /* Examine all charging rods or stacks of charging rods. */ + if ((o_ptr->tval == TV_ROD_MAIN) && (o_ptr->timeout < o_ptr->pval2)) + { + /* Increase the rod's mana. */ + o_ptr->timeout += (f4 & TR4_CHARGING) ? 2 : 1; + + /* Always notice */ + j++; + + /* Notice changes, provide message if object is inscribed. */ + if (o_ptr->timeout >= o_ptr->pval2) + { + o_ptr->timeout = o_ptr->pval2; + recharged_notice(o_ptr); + } + } + + /* Examine all charging random artifacts */ + if ((f5 & TR5_ACTIVATE_NO_WIELD) && (o_ptr->timeout > 0)) + { + /* Charge it */ + o_ptr->timeout--; + + /* Notice changes */ + if (o_ptr->timeout == 0) + { + j++; + recharged_notice(o_ptr); + } + } + + /* Decay objects in pack */ + if (decays(o_ptr)) + { + /* Decay it */ + if (o_ptr->pval != 0) + { + if (o_ptr->timeout > 0) + { + if (dungeon_flags1 & DF1_HOT) + { + o_ptr->pval -= 2; + } + else if ((dungeon_flags1 & DF1_COLD) && rand_int(2)) + { + if (magik(50)) o_ptr->pval--; + } + else + { + o_ptr->pval--; + } + } + + if ((o_ptr->timeout > 0) && o_ptr->timeout < o_ptr->weight) o_ptr->timeout--; + + /* Notice changes */ + if (o_ptr->pval <= 0) + { + pack_decay(i); + j++; + } + } + } + + /* Hatch eggs */ + if (o_ptr->tval == TV_EGG) + { + int mx, my; + + if (o_ptr->timeout == 0) + { + o_ptr->pval--; + + /* Notice changes */ + if (o_ptr->pval <= 0) + { + monster_type *m_ptr; + monster_race *r_ptr; + + mx = p_ptr->px; + my = p_ptr->py + 1; + get_pos_player(5, &my, &mx); + msg_print("Your egg hatches!"); + place_monster_aux(my, mx, o_ptr->pval2, FALSE, FALSE, MSTATUS_PET); + + m_ptr = &m_list[cave[my][mx].m_idx]; + r_ptr = race_inf(m_ptr); + + if ((r_ptr->flags9 & RF9_IMPRESED) && can_create_companion()) + { + msg_format("And you have given the imprint to your %s!", + r_name + r_ptr->name); + m_ptr->status = MSTATUS_COMPANION; + } + + inc_stack_size(i, -1); + + j++; + } + } + } + } + + /* Notice changes */ + if (j) + { + /* Combine pack */ + p_ptr->notice |= (PN_COMBINE); + + /* Window stuff */ + p_ptr->window |= (PW_INVEN); + } + + /*** Process Objects ***/ + + /* Process objects */ + for (i = 1; i < o_max; i++) + { + /* Access object */ + o_ptr = &o_list[i]; + + /* Skip dead objects */ + if (!o_ptr->k_idx) continue; + + /* Examine the rod */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* Temporary items are destroyed */ + if (f5 & TR5_TEMPORARY) + { + o_ptr->timeout--; + + if (o_ptr->timeout <= 0) + { + floor_item_increase(i, -99); + floor_item_optimize(i); + + /* Combine and Reorder pack */ + p_ptr->notice |= (PN_COMBINE | PN_REORDER); + } + } + + /* Recharge rods on the ground. No messages. */ + if ((o_ptr->tval == TV_ROD_MAIN) && (o_ptr->timeout < o_ptr->pval2)) + { + /* Increase the rod's mana. */ + o_ptr->timeout += (f4 & TR4_CHARGING) ? 2 : 1; + + /* Do not overflow */ + if (o_ptr->timeout >= o_ptr->pval2) + { + o_ptr->timeout = o_ptr->pval2; + } + } + + /* Decay objects on the ground*/ + if (decays(o_ptr)) + { + /* Decay it */ + if (o_ptr->pval != 0) + { + if (o_ptr->timeout > 0) + { + if (dungeon_flags1 & DF1_HOT) + { + o_ptr->pval -= 2; + } + else if ((dungeon_flags1 & DF1_COLD) && rand_int(2)) + { + if (magik(50)) o_ptr->pval--; + } + else + { + o_ptr->pval--; + } + } + + if ((o_ptr->timeout > 0) && o_ptr->timeout < o_ptr->weight) o_ptr->timeout--; + + /* Turn it into a skeleton */ + if (o_ptr->pval <= 0) + { + floor_decay(i); + } + } + } + + /* Hatch eggs */ + if (o_ptr->tval == TV_EGG) + { + int mx, my; + if (o_ptr->timeout > 0) o_ptr->pval--; + + /* Notice changes */ + if (o_ptr->pval <= 0) + { + mx = o_ptr->ix; + my = o_ptr->iy; + get_pos_player(5, &my, &mx); + msg_print("An egg hatches!"); + place_monster_one(my, mx, o_ptr->pval2, 0, FALSE, MSTATUS_ENEMY); + floor_item_increase(i, -1); + floor_item_describe(i); + floor_item_optimize(i); + } + } + } + + + /*** Involuntary Movement ***/ + + /* Delayed Word-of-Recall */ + if (p_ptr->word_recall) + { + /* Can we ? */ + if (process_hooks(HOOK_RECALL, "()", "")) + { + p_ptr->word_recall = 0; + } + + /* No recall. sorry */ + else if (dungeon_flags2 & DF2_NO_RECALL_OUT) + { + cmsg_print(TERM_L_DARK, "You cannot recall from here."); + p_ptr->word_recall = 0; + } + + /* Cannot WoR out of death fate levels */ + else if (dungeon_type == DUNGEON_DEATH) + { + cmsg_print(TERM_L_DARK, "You are fated to die here. FIGHT for your life!"); + p_ptr->word_recall = 0; + } + + /* I think the 'inside_quest' code belongs here -- pelpel */ + + /* They cannot use word of recall until reaching surface */ + else if (p_ptr->astral) + { + msg_print("As an astral being you can't recall."); + p_ptr->word_recall = 0; + } + + /* Normal WoR */ + else + { + /* + * HACK: Autosave BEFORE resetting the recall counter (rr9) + * The player is yanked up/down as soon as + * he loads the autosaved game. + */ + if (p_ptr->word_recall == 1) + { + autosave_checkpoint(); + } + + /* Make SURE that persistent levels are saved + * I don't know if this is needed, but I'm getting reports, + * so I'm adding this extra save -- Neil + */ + save_dungeon(); + + /* Count down towards recall */ + p_ptr->word_recall--; + + /* Activate the recall */ + if (p_ptr->word_recall == 0) + { + /* Disturbing! */ + disturb(0); + + /* Determine the level */ + if (p_ptr->inside_quest) + { + msg_print("The recall is cancelled by a powerful magic force!"); + } + else if (dun_level) + { + msg_print("You feel yourself yanked upwards!"); + + p_ptr->recall_dungeon = dungeon_type; + dungeon_type = DUNGEON_WILDERNESS; + dun_level = 0; + + is_recall = TRUE; + + p_ptr->inside_quest = 0; + p_ptr->leaving = TRUE; + } + else + { + msg_print("You feel yourself yanked downwards!"); + + /* New depth */ + dungeon_type = p_ptr->recall_dungeon; + dun_level = max_dlv[dungeon_type]; + if (dun_level < 1) dun_level = 1; + + /* Reset player position */ + p_ptr->oldpx = p_ptr->px; + p_ptr->oldpy = p_ptr->py; + + /* Leaving */ + is_recall = TRUE; + + p_ptr->leaving = TRUE; + p_ptr->wild_mode = FALSE; + } + + /* Sound */ + sound(SOUND_TPLEVEL); + } + } + } +} + + +/* + * Verify use of "wizard" mode + */ +static bool_ enter_wizard_mode(void) +{ + /* Ask first time, but not while loading a dead char with the -w option */ + if (!noscore && !(p_ptr->chp < 0)) + { + /* Mention effects */ + msg_print("Wizard mode is for debugging and experimenting."); + msg_print("The game will not be scored if you enter wizard mode."); + msg_print(NULL); + + /* Verify request */ + if (!get_check("Are you sure you want to enter wizard mode? ")) + { + return (FALSE); + } + + /* Mark savefile */ + noscore |= 0x0002; + } + + /* Success */ + return (TRUE); +} + + +/* + * Verify use of "debug" commands + */ +static bool_ enter_debug_mode(void) +{ + /* Ask first time */ + if (!noscore && !wizard) + { + /* Mention effects */ + msg_print("The debug commands are for debugging and experimenting."); + msg_print("The game will not be scored if you use debug commands."); + msg_print(NULL); + + /* Verify request */ + if (!get_check("Are you sure you want to use debug commands? ")) + { + return (FALSE); + } + + /* Mark savefile */ + noscore |= 0x0008; + } + + /* Success */ + return (TRUE); +} + + +/* + * Parse and execute the current command + * Give "Warning" on illegal commands. + * + * XXX XXX XXX Make some "blocks" + */ +static void process_command(void) +{ + char error_m[80]; + + /* Handle repeating the last command */ + repeat_check(); + + /* Process the appropriate hooks */ + if (process_hooks(HOOK_KEYPRESS, "(d)", command_cmd)) return; + + /* Parse the command */ + switch (command_cmd) + { + /* Ignore */ + case ESCAPE: + case ' ': + case 0: + { + break; + } + + /* Ignore return */ + case '\r': + { + break; + } + + + + /*** Wizard Commands ***/ + + /* Toggle Wizard Mode */ + case KTRL('W'): + { + if (wizard) + { + wizard = FALSE; + msg_print("Wizard mode off."); + } + else if (enter_wizard_mode()) + { + wizard = TRUE; + msg_print("Wizard mode on."); + } + + /* Update monsters */ + p_ptr->update |= (PU_MONSTERS); + + /* Redraw "title" */ + p_ptr->redraw |= (PR_TITLE); + + break; + } + + /* Special "debug" commands */ + case KTRL('A'): + { + /* Enter debug mode */ + if (enter_debug_mode()) + { + do_cmd_debug(); + } + break; + } + + + /*** Inventory Commands ***/ + + /* Wear/wield equipment */ + case 'w': + { + if (p_ptr->control) break; + if (!p_ptr->wild_mode) do_cmd_wield(); + break; + } + + /* Take off equipment */ + case 't': + { + if (p_ptr->control) break; + if (!p_ptr->wild_mode) do_cmd_takeoff(); + p_ptr->redraw |= (PR_MH); + break; + } + + /* Drop an item */ + case 'd': + { + if (do_control_drop()) break; + if (!p_ptr->wild_mode) do_cmd_drop(); + break; + } + + /* Destroy an item */ + case 'k': + { + if (p_ptr->control) break; + do_cmd_destroy(); + break; + } + + /* Equipment list */ + case 'e': + { + if (p_ptr->control) break; + do_cmd_equip(); + break; + } + + /* Inventory list */ + case 'i': + { + if (do_control_inven()) break; + do_cmd_inven(); + break; + } + + + /*** Various commands ***/ + + /* Identify an object */ + case 'I': + { + do_cmd_observe(); + break; + } + + /* Hack -- toggle windows */ + case KTRL('I'): + { + toggle_inven_equip(); + break; + } + + + /*** Standard "Movement" Commands ***/ + + /* Alter a grid */ + case '+': + { + if (p_ptr->control) break; + if (!p_ptr->wild_mode) do_cmd_alter(); + break; + } + + /* Dig a tunnel */ + case 'T': + { + if (p_ptr->control) break; + if (!p_ptr->wild_mode) do_cmd_tunnel(); + break; + } + + /* Move (usually pick up things) */ + case ';': + { + if (do_control_walk()) break; + + do_cmd_walk(always_pickup, TRUE); + + break; + } + + /* Move (usually do not pick up) */ + case '-': + { + if (do_control_walk()) break; + + do_cmd_walk(!always_pickup, TRUE); + + break; + } + + + /*** Running, Resting, Searching, Staying */ + + /* Begin Running -- Arg is Max Distance */ + case '.': + { + if (p_ptr->control || p_ptr->wild_mode) break; + do_cmd_run(); + break; + } + + /* Stay still (usually pick things up) */ + case ',': + { + if (do_control_pickup()) break; + do_cmd_stay(always_pickup); + break; + } + + /* Stay still (usually do not pick up) */ + case 'g': + { + if (p_ptr->control) break; + do_cmd_stay(!always_pickup); + break; + } + + /* Rest -- Arg is time */ + case 'R': + { + if (p_ptr->control) break; + do_cmd_rest(); + break; + } + + /* Search for traps/doors */ + case 's': + { + if (p_ptr->control) break; + do_cmd_search(); + break; + } + + /* Toggle search mode */ + case 'S': + { + if (p_ptr->control) break; + do_cmd_toggle_search(); + break; + } + + + /*** Stairs and Doors and Chests and Traps ***/ + + /* Enter store */ + case '_': + { + if (p_ptr->control) break; + if (!p_ptr->wild_mode) do_cmd_store(); + break; + } + + /* Go up staircase */ + case '<': + { + object_type *o_ptr; + u32b f1 = 0 , f2 = 0 , f3 = 0, f4 = 0, f5 = 0, esp = 0; + + + /* Check for light being wielded */ + o_ptr = &p_ptr->inventory[INVEN_LITE]; + /* Burn some fuel in the current lite */ + if (o_ptr->tval == TV_LITE) + /* Extract the item flags */ + object_flags(o_ptr, &f1, &f2, &f3, &f4, &f5, &esp); + + /* Cannot move if rooted in place */ + if (p_ptr->tim_roots) break; + + if (p_ptr->control) break; + /* Normal cases */ + if (p_ptr->wild_mode || dun_level || is_quest(dun_level)) + { + do_cmd_go_up(); + } + /* Don't let the player < when he'd just drop right back down */ + else if (p_ptr->food < PY_FOOD_ALERT) + { + msg_print("You are too hungry to travel."); + } + else if (p_ptr->sensible_lite && + (((turn / ((10L * DAY) / 2)) % 2) == 0)) + { + /* Burn vampires! burn! */ + msg_print("You can't travel during the day!"); + } + else if (p_ptr->sensible_lite && + (o_ptr->tval != 0) && + (o_ptr->sval >= SV_LITE_GALADRIEL) && + (o_ptr->sval <= SV_STONE_LORE) && + (o_ptr->sval != SV_LITE_UNDEATH)) + { + msg_print("Travel with your present light would be unsafe."); + } + else if (p_ptr->cut || p_ptr->poisoned) + { + /* I actually died this way once -- neil */ + msg_print("You are too injured to travel."); + } + else if (ambush_flag) + { + msg_print("To flee the ambush you have to reach the edge of the map."); + } + /* TODO: make the above stuff use this hook */ + else if (!process_hooks(HOOK_FORBID_TRAVEL, "()")) + { + p_ptr->oldpx = p_ptr->px; + p_ptr->oldpy = p_ptr->py; + change_wild_mode(); + + /* Update the known wilderness */ + reveal_wilderness_around_player(p_ptr->wilderness_y, + p_ptr->wilderness_x, + 0, WILDERNESS_SEE_RADIUS); + } + + break; + } + + /* Go down staircase */ + case '>': + { + /* Cannot move if rooted in place */ + if (p_ptr->tim_roots) break; + + if (p_ptr->control) break; + /* Normal cases */ + if (!p_ptr->wild_mode) + { + do_cmd_go_down(); + } + + /* Special cases */ + else + { + if ((wf_info[wild_map[p_ptr->py][p_ptr->px].feat].entrance >= 1000) || + (wild_map[p_ptr->py][p_ptr->px].entrance > 1000)) + { + p_ptr->wilderness_x = p_ptr->px; + p_ptr->wilderness_y = p_ptr->py; + p_ptr->wild_mode = !p_ptr->wild_mode; + do_cmd_go_down(); + + if (dun_level == 0) + { + p_ptr->wild_mode = !p_ptr->wild_mode; + } + else + { + p_ptr->wilderness_x = p_ptr->px; + p_ptr->wilderness_y = p_ptr->py; + change_wild_mode(); + } + } + else + { + p_ptr->wilderness_x = p_ptr->px; + p_ptr->wilderness_y = p_ptr->py; + change_wild_mode(); + } + } + + break; + } + + /* Open a door or chest */ + case 'o': + { + if (p_ptr->control) break; + if (!p_ptr->wild_mode) do_cmd_open(); + break; + } + + /* Close a door */ + case 'c': + { + if (p_ptr->control) break; + if (!p_ptr->wild_mode) do_cmd_close(); + break; + } + + /* Give an item */ + case 'y': + { + if (p_ptr->control) break; + if (!p_ptr->wild_mode) do_cmd_give(); + break; + } + + /* Chat */ + case 'Y': + { + if (p_ptr->control) break; + if (!p_ptr->wild_mode) do_cmd_chat(); + break; + } + + /* Jam a door with spikes */ + case 'j': + { + if (p_ptr->control) break; + if (!p_ptr->wild_mode) do_cmd_spike(); + break; + } + + /* Bash a door */ + case 'B': + { + if (p_ptr->control) break; + if (!p_ptr->wild_mode) do_cmd_bash(); + break; + } + + /* Disarm a trap or chest */ + case 'D': + { + if (p_ptr->control) break; + if (!p_ptr->wild_mode) do_cmd_disarm(); + break; + } + + + /*** Magic and Prayers ***/ + + /* Interact with skills */ + case 'G': + { + if (p_ptr->control) break; + do_cmd_skill(); + break; + } + + /* Interact with abilities */ + case 'N': + { + if (p_ptr->control) break; + do_cmd_ability(); + break; + } + + /* Browse a book */ + case 'b': + { + if (p_ptr->control) break; + do_cmd_browse(); + break; + } + + /* Cast a spell */ + case 'm': + { + if (do_control_magic()) break; + + /* No magic in the overworld map */ + if (p_ptr->wild_mode) break; + + /* Neither in the Arena */ + if (p_ptr->inside_arena) + { + msg_print("The arena absorbs all attempted magic!"); + + break; + } + do_cmd_activate_skill(); + squeltch_inventory(); + squeltch_grid(); + break; + } + + /* Pray a prayer */ + case 'p': + { + if (p_ptr->control || p_ptr->wild_mode) break; + do_cmd_pray(); + squeltch_inventory(); + squeltch_grid(); + break; + } + + /* Issue commands to pets */ + case 'P': + { + if (p_ptr->control) break; + if (!p_ptr->wild_mode) do_cmd_pet(); + break; + } + + /* Cut up a corpse */ + case 'h': + { + if (p_ptr->control || p_ptr->wild_mode) break; + do_cmd_cut_corpse(); + squeltch_inventory(); + squeltch_grid(); + break; + } + + /* Cure some meat */ + case 'K': + { + if (p_ptr->control) break; + do_cmd_cure_meat(); + squeltch_inventory(); + squeltch_grid(); + break; + } + + /* Steal an item form a monster */ + case 'Z': + { + if (p_ptr->control || p_ptr->wild_mode) break; + do_cmd_steal(); + squeltch_inventory(); + squeltch_grid(); + break; + } + + /*** Use various objects ***/ + + /* Inscribe an object */ + case '{': + { + if (p_ptr->control) break; + do_cmd_inscribe(); + break; + } + + /* Uninscribe an object */ + case '}': + { + if (p_ptr->control) break; + do_cmd_uninscribe(); + break; + } + + /* Activate an artifact */ + case 'A': + { + if (p_ptr->control) break; + if (p_ptr->wild_mode) break; + + if (p_ptr->inside_arena) + { + msg_print("The arena absorbs all attempted magic!"); + msg_print(NULL); + break; + } + + do_cmd_activate(); + squeltch_inventory(); + squeltch_grid(); + break; + } + + /* Eat some food */ + case 'E': + { + if (p_ptr->control) break; + do_cmd_eat_food(); + break; + } + + /* Fuel your lantern/torch */ + case 'F': + { + if (p_ptr->control) break; + do_cmd_refill(); + break; + } + + /* Fire an item */ + case 'f': + { + object_type *j_ptr; + + if (p_ptr->control) break; + if (p_ptr->wild_mode) break; + + if (p_ptr->inside_arena) + { + msg_print("You're in the arena now. This is hand-to-hand!"); + msg_print(NULL); + break; + } + + j_ptr = &p_ptr->inventory[INVEN_BOW]; + + if (process_hooks(HOOK_FIRE, "(O)", j_ptr)) + break; + + if (j_ptr->tval == TV_BOOMERANG) + { + do_cmd_boomerang(); + } + else + { + do_cmd_fire(); + } + + break; + } + + /* Throw an item */ + case 'v': + { + if (p_ptr->control) break; + if (p_ptr->wild_mode) break; + + if (p_ptr->inside_arena) + { + msg_print("You're in the arena now. This is hand-to-hand!"); + msg_print(NULL); + break; + } + + do_cmd_throw(); + break; + } + + /* Aim a wand */ + case 'a': + { + if (p_ptr->control) break; + if (p_ptr->wild_mode) break; + + if (p_ptr->inside_arena) + { + msg_print("The arena absorbs all attempted magic!"); + msg_print(NULL); + break; + } + + do_cmd_aim_wand(); + squeltch_inventory(); + squeltch_grid(); + break; + } + + /* Zap a rod */ + case 'z': + { + if (p_ptr->control) break; + if (p_ptr->wild_mode) break; + + if (p_ptr->inside_arena) + { + msg_print("The arena absorbs all attempted magic!"); + msg_print(NULL); + break; + } + + do_cmd_zap_rod(); + squeltch_inventory(); + squeltch_grid(); + break; + } + + /* Quaff a potion */ + case 'q': + { + if (p_ptr->control) break; + if (p_ptr->wild_mode) break; + + if (p_ptr->inside_arena) + { + msg_print("The arena absorbs all attempted magic!"); + msg_print(NULL); + break; + } + + do_cmd_quaff_potion(); + squeltch_inventory(); + squeltch_grid(); + break; + } + + /* Drink from a fountain -SC- */ + case 'H': + { + cave_type *c_ptr = &cave[p_ptr->py][p_ptr->px]; + + if (p_ptr->control) break; + if ((c_ptr->feat == FEAT_FOUNTAIN) || + (c_ptr->feat == FEAT_EMPTY_FOUNTAIN)) + { + do_cmd_drink_fountain(); + squeltch_inventory(); + squeltch_grid(); + } + else + { + msg_print("You see no fountain here."); + } + + break; + } + + /* Read a scroll */ + case 'r': + { + if (p_ptr->control) break; + if (p_ptr->wild_mode) break; + + if (p_ptr->inside_arena) + { + msg_print("The arena absorbs all attempted magic!"); + msg_print(NULL); + break; + } + + do_cmd_read_scroll(); + squeltch_inventory(); + squeltch_grid(); + break; + } + + /* Use a staff */ + case 'u': + { + if (p_ptr->control) break; + if (p_ptr->wild_mode) break; + + if (p_ptr->inside_arena) + { + msg_print("The arena absorbs all attempted magic!"); + msg_print(NULL); + break; + } + + do_cmd_use_staff(); + squeltch_inventory(); + squeltch_grid(); + break; + } + + /* Use racial power */ + case 'U': + { + if (p_ptr->control) break; + if (p_ptr->wild_mode) break; + + if (p_ptr->inside_arena) + { + msg_print("The arena absorbs all attempted magic!"); + msg_print(NULL); + break; + } + + do_cmd_power(); + squeltch_inventory(); + squeltch_grid(); + break; + } + + /* Sacrifice at an altar */ + case 'O': + { + if (p_ptr->control) break; + if (p_ptr->wild_mode) break; + + if (PRACE_FLAG(PR1_NO_GOD)) + { + msg_print("You cannot worship gods."); + } + else + { + do_cmd_sacrifice(); + } + + break; + } + + /*** Looking at Things (nearby or on map) ***/ + + /* Full dungeon map */ + case 'M': + { + if (!p_ptr->wild_mode) do_cmd_view_map(); + break; + } + + /* Locate player on map */ + case 'L': + { + do_cmd_locate(); + break; + } + + /* Look around */ + case 'l': + { + do_cmd_look(); + break; + } + + /* Target monster or location */ + case '*': + { + if (p_ptr->control) break; + if (!p_ptr->wild_mode) do_cmd_target(); + break; + } + + /* Engrave the floor */ + case 'x': + { + if (p_ptr->control) break; + if (p_ptr->wild_mode) break; + + /* No point in engraving if there isn't any mana on this grid. */ + /* DG - actualy there is, it doesnt break macros */ + do_cmd_sense_grid_mana(); + do_cmd_engrave(); + + break; + } + + /*** Help and Such ***/ + + /* Help */ + case '?': + { + do_cmd_help(); + break; + } + + /* Identify symbol */ + case '/': + { + do_cmd_query_symbol(); + break; + } + + /* Character description */ + case 'C': + { + do_cmd_change_name(); + break; + } + + + /*** System Commands ***/ + + /* Hack -- User interface */ + case '!': + { + (void)Term_user(0); + break; + } + + /* Single line from a pref file */ + case '"': + { + do_cmd_pref(); + break; + } + + /* Interact with macros */ + case '@': + { + do_cmd_macros(); + break; + } + + /* Interact with visuals */ + case '%': + { + do_cmd_visuals(); + break; + } + + /* Interact with colors */ + case '&': + { + do_cmd_colors(); + break; + } + + /* Interact with options */ + case '=': + { + do_cmd_options(); + break; + } + + + /*** Misc Commands ***/ + + /* Take notes */ + case ':': + { + do_cmd_note(); + break; + } + + /* Version info */ + case 'V': + { + do_cmd_version(); + break; + } + + /* Repeat level feeling */ + case KTRL('F'): + { + if (!p_ptr->wild_mode) + do_cmd_feeling(); + break; + } + + /* Show previous message */ + case KTRL('O'): + { + do_cmd_message_one(); + break; + } + + /* Show previous messages */ + case KTRL('P'): + { + do_cmd_messages(); + break; + } + + /* Show quest status -KMW- */ + case KTRL('Q'): + case CMD_QUEST: +{ + do_cmd_checkquest(); + break; + } + + /* Redraw the screen */ + case KTRL('R'): + { + do_cmd_redraw(); + break; + } + + /* Hack -- Save and don't quit */ + case KTRL('S'): + { + is_autosave = FALSE; + do_cmd_save_game(); + break; + } + + case KTRL('T'): + { + do_cmd_time(); + } + break; + + /* Save and quit */ + case KTRL('X'): + { + alive = FALSE; + + /* Leaving */ + p_ptr->leaving = TRUE; + + break; + } + + /* Quit (commit suicide) */ + case 'Q': + { + do_cmd_suicide(); + break; + } + + /* Activate cmovie */ + case '|': + { + /* Stop ? */ + if (do_movies == 1) + { + do_stop_cmovie(); + msg_print("Cmovie recording stopped."); + } + else + { + do_start_cmovie(); + } + break; + } + + /* Extended command */ + case '#': + { + do_cmd_cli(); + break; + } + + /* Check artifacts, uniques, objects */ + case '~': + { + do_cmd_knowledge(); + break; + } + + /* Commands only available as extended commands: */ + + /* Extended command help. */ + case CMD_CLI_HELP: + { + do_cmd_cli_help(); + break; + } + + /* Game time. */ + case CMD_SHOW_TIME: + { + do_cmd_time(); + break; + } + + /* Check skills. */ + case CMD_SHOW_SKILL: + { + do_cmd_skill(); + break; + } + + /* Check abilities. */ + case CMD_SHOW_ABILITY: + { + do_cmd_ability(); + break; + } + + /* Save a html screenshot. */ + case CMD_DUMP_HTML: + { + do_cmd_html_dump(); + break; + } + + /* Record a macro. */ + case '$': + case CMD_MACRO: + { + do_cmd_macro_recorder(); + break; + } + case CMD_BLUNDER: + { + if (do_control_walk()) break; + do_cmd_walk(always_pickup, FALSE); + break; + } + /* Hack -- Unknown command */ + default: + { + int insanity = (p_ptr->msane - p_ptr->csane) * 100 / p_ptr->msane; + + /* Would like to have an option disabling this -- pelpel */ + if (rand_int(100) < insanity) + { + get_rnd_line("error.txt", error_m); + sound(SOUND_ILLEGAL); + msg_print(error_m); + } + else + { + prt("Type '?' for help.", 0, 0); + } + + break; + } + } +} + + + + +/* + * Process the player + * + * Notice the annoying code to handle "pack overflow", which + * must come first just in case somebody manages to corrupt + * the savefiles by clever use of menu commands or something. + */ +void process_player(void) +{ + int i, j; + + int speed_use; + + + /*** Apply energy ***/ + + /* Obtain current speed */ + speed_use = p_ptr->pspeed; + + /* Maximum value */ + if (speed_use > 199) + { + speed_use = 199; + } + + /* Minimum value */ + else if (speed_use < 0) + { + speed_use = 0; + } + + /* Give the player some energy */ + p_ptr->energy += extract_energy[speed_use]; + + /* No turn yet */ + if (p_ptr->energy < 100) return; + + + /*** Check for interupts ***/ + + /* Complete resting */ + if (resting < 0) + { + /* Basic resting */ + if (resting == -1) + { + /* Stop resting */ + if ((p_ptr->chp == p_ptr->mhp) && (p_ptr->csp >= p_ptr->msp)) + { + disturb(0); + } + } + + /* Complete resting */ + else if (resting == -2) + { + bool_ stop = TRUE; + object_type *o_ptr; + + /* Get the carried monster */ + o_ptr = &p_ptr->inventory[INVEN_CARRY]; + + /* Stop resting */ + if ((!p_ptr->drain_life) && (p_ptr->chp != p_ptr->mhp)) stop = FALSE; + if ((!p_ptr->drain_mana) && (p_ptr->csp != p_ptr->msp)) stop = FALSE; + if (o_ptr->pval2 < o_ptr->pval3) stop = FALSE; + if (p_ptr->blind || p_ptr->confused) stop = FALSE; + if (p_ptr->poisoned || p_ptr->afraid) stop = FALSE; + if (p_ptr->stun || p_ptr->cut) stop = FALSE; + if (p_ptr->slow || p_ptr->paralyzed) stop = FALSE; + if (p_ptr->image || p_ptr->word_recall) stop = FALSE; + if (p_ptr->immov_cntr != 0) stop = FALSE; + + for (i = 0; i < 6; i++) + { + if (p_ptr->stat_cnt[i] > 0) stop = FALSE; + } + + if (stop) + { + disturb(0); + } + p_ptr->redraw |= (PR_STATE); + } + } + + /* Handle "abort" */ + if (!avoid_abort) + { + /* Check for "player abort" (semi-efficiently for resting) */ + if (running || command_rep || (resting && !(resting & 0x0F))) + { + /* Do not wait */ + inkey_scan = TRUE; + + /* Check for a key */ + if (inkey()) + { + /* Flush input */ + flush(); + + /* Disturb */ + disturb(0); + + /* Hack -- Show a Message */ + msg_print("Cancelled."); + } + } + } + + + /*** Handle actual user input ***/ + + /* Repeat until out of energy */ + while (p_ptr->energy >= 100) + { + /* Notice stuff (if needed) */ + if (p_ptr->notice) notice_stuff(); + + /* Update stuff (if needed) */ + if (p_ptr->update) update_stuff(); + + /* Redraw stuff (if needed) */ + if (p_ptr->redraw) redraw_stuff(); + + /* Redraw stuff (if needed) */ + if (p_ptr->window) window_stuff(); + + /* Hack -- mark current wilderness location as known */ + if (!p_ptr->wild_mode && dun_level == 0) + wild_map[p_ptr->wilderness_y][p_ptr->wilderness_x].known = TRUE; + + + /* Place the cursor on the player */ + move_cursor_relative(p_ptr->py, p_ptr->px); + + /* Refresh (optional) */ + if (fresh_before) Term_fresh(); + + /* Hack -- Pack Overflow */ + if (p_ptr->inventory[INVEN_PACK].k_idx) + { + int item = INVEN_PACK; + + char o_name[80]; + + object_type *o_ptr; + + /* Access the slot to be dropped */ + o_ptr = &p_ptr->inventory[item]; + + /* Disturbing */ + disturb(0); + + /* Warning */ + msg_print("Your pack overflows!"); + + /* Describe */ + object_desc(o_name, o_ptr, TRUE, 3); + + /* Message */ + msg_format("You drop %s (%c).", o_name, index_to_label(item)); + + /* Drop it (carefully) near the player */ + drop_near(o_ptr, 0, p_ptr->py, p_ptr->px); + + /* Modify, Describe, Optimize */ + inc_stack_size(item, -255); + + /* Notice stuff (if needed) */ + if (p_ptr->notice) notice_stuff(); + + /* Update stuff (if needed) */ + if (p_ptr->update) update_stuff(); + + /* Redraw stuff (if needed) */ + if (p_ptr->redraw) redraw_stuff(); + + /* Redraw stuff (if needed) */ + if (p_ptr->window) window_stuff(); + } + + + /* Assume free turn */ + energy_use = 0; + + + /* Paralyzed or Knocked Out */ + if ((p_ptr->paralyzed) || (p_ptr->stun >= 100)) + { + /* Take a turn */ + energy_use = 100; + } + + /* Resting */ + else if (resting) + { + /* Timed rest */ + if (resting > 0) + { + /* Reduce rest count */ + resting--; + + /* Redraw the state */ + p_ptr->redraw |= (PR_STATE); + } + + p_ptr->did_nothing = TRUE; + + /* Take a turn */ + energy_use = 100; + } + + /* Running */ + else if (running) + { + /* Take a step */ + run_step(0); + + /* + * Commented out because it doesn't make any sense + * to require a player holding down direction keys + * instead of using running commands when s/he follows + * Eru and do the opposite for the other deities -- pelpel + */ + /* p_ptr->did_nothing = TRUE; */ + } + + /* Repeated command */ + else if (command_rep) + { + /* Count this execution */ + command_rep--; + + /* Redraw the state */ + p_ptr->redraw |= (PR_STATE); + + /* Redraw stuff */ + redraw_stuff(); + + /* Hack -- Assume messages were seen */ + msg_flag = FALSE; + + /* Clear the top line */ + prt("", 0, 0); + + /* Process the command */ + process_command(); + + p_ptr->did_nothing = TRUE; + } + + /* Normal command */ + else + { + /* Place the cursor on the player */ + move_cursor_relative(p_ptr->py, p_ptr->px); + + /* Get a command (normal) */ + request_command(FALSE); + + /* Process the command */ + process_command(); + } + + + /*** Clean up ***/ + + /* Significant */ + if (energy_use) + { + /* Use some energy */ + p_ptr->energy -= energy_use; + + + /* Hack -- constant hallucination */ + if (p_ptr->image) p_ptr->redraw |= (PR_MAP); + + + /* Shimmer monsters if needed */ + if (!avoid_other && !use_graphics && shimmer_monsters) + { + /* Clear the flag */ + shimmer_monsters = FALSE; + + /* Shimmer multi-hued monsters */ + for (i = 1; i < m_max; i++) + { + monster_type *m_ptr; + monster_race *r_ptr; + + /* Access monster */ + m_ptr = &m_list[i]; + + /* Skip dead monsters */ + if (!m_ptr->r_idx) continue; + + /* Access the monster race */ + r_ptr = race_inf(m_ptr); + + /* Skip non-multi-hued monsters */ + if (!(r_ptr->flags1 & (RF1_ATTR_MULTI))) continue; + + /* Reset the flag */ + shimmer_monsters = TRUE; + + /* Redraw regardless */ + lite_spot(m_ptr->fy, m_ptr->fx); + } + } + + /* Shimmer objects if needed and requested */ + if (!avoid_other && !avoid_shimmer && !use_graphics && + shimmer_objects) + { + /* Clear the flag */ + shimmer_objects = FALSE; + + /* Shimmer multi-hued objects */ + for (i = 1; i < o_max; i++) + { + /* Acquire object -- for speed only base items are allowed to shimmer */ + object_type *o_ptr = &o_list[i]; + object_kind *k_ptr = &k_info[o_ptr->k_idx]; + + /* Skip dead or carried objects */ + if ((!o_ptr->k_idx) || (!o_ptr->ix)) continue; + + /* Skip non-multi-hued monsters */ + if (!(k_ptr->flags5 & (TR5_ATTR_MULTI))) continue; + + /* Reset the flag */ + shimmer_objects = TRUE; + + /* Redraw regardless */ + lite_spot(o_ptr->iy, o_ptr->ix); + } + } + + /* + * Shimmer features if needed and requested + * + * Note: this can be unbearably slow when a player chooses + * to use a REALLY big screen in levels filled with shallow + * water. I believe this also hurts a lot on multiuser systems. + * However fast modern processors are, I/O cannot be made that + * fast, and that's why shimmering has been limited to small + * number of monsters -- pelpel + */ + if (!avoid_other && !avoid_shimmer && !use_graphics && + !resting && !running) + { + for (j = panel_row_min; j <= panel_row_max; j++) + { + for (i = panel_col_min; i <= panel_col_max; i++) + { + cave_type *c_ptr = &cave[j][i]; + feature_type *f_ptr; + + /* Apply terrain feature mimics */ + if (c_ptr->mimic) + { + f_ptr = &f_info[c_ptr->mimic]; + } + else + { + f_ptr = &f_info[f_info[c_ptr->feat].mimic]; + } + + /* Skip normal features */ + if (!(f_ptr->flags1 & (FF1_ATTR_MULTI))) continue; + + /* Redraw a shimmering spot */ + lite_spot(j, i); + } + } + } + + + /* Handle monster detection */ + if (repair_monsters) + { + /* Reset the flag */ + repair_monsters = FALSE; + + /* Rotate detection flags */ + for (i = 1; i < m_max; i++) + { + monster_type *m_ptr; + + /* Access monster */ + m_ptr = &m_list[i]; + + /* Skip dead monsters */ + if (!m_ptr->r_idx) continue; + + /* Nice monsters get mean */ + if (m_ptr->mflag & (MFLAG_NICE)) + { + /* Nice monsters get mean */ + m_ptr->mflag &= ~(MFLAG_NICE); + } + + /* Handle memorized monsters */ + if (m_ptr->mflag & (MFLAG_MARK)) + { + /* Maintain detection */ + if (m_ptr->mflag & (MFLAG_SHOW)) + { + /* Forget flag */ + m_ptr->mflag &= ~(MFLAG_SHOW); + + /* Still need repairs */ + repair_monsters = TRUE; + } + + /* Remove detection */ + else + { + /* Forget flag */ + m_ptr->mflag &= ~(MFLAG_MARK); + + /* Assume invisible */ + m_ptr->ml = FALSE; + + /* Update the monster */ + update_mon(i, FALSE); + + /* Redraw regardless */ + lite_spot(m_ptr->fy, m_ptr->fx); + } + } + } + } + + /* + * Moved from dungeon() -- It'll get called whenever player + * spends energy, so that maze isn't incredibly easy for + * Sorcerors and alike any longer -- pelpel + * + * Forget everything when requested hehe I'm *NASTY* + */ + if (dun_level && (dungeon_flags1 & DF1_FORGET)) + { + wiz_dark(); + } + } + + + /* Hack -- notice death */ + if (!alive || death) break; + + /* Handle "leaving" */ + if (p_ptr->leaving) break; + } +} + + + +/* + * Interact with the current dungeon level. + * + * This function will not exit until the level is completed, + * the user dies, or the game is terminated. + */ +static void dungeon(void) +{ + /* Reset various flags */ + hack_mind = FALSE; + + /* Not leaving */ + p_ptr->leaving = FALSE; + + /* Reset the "command" vars */ + command_cmd = 0; + command_new = 0; + command_rep = 0; + command_arg = 0; + command_dir = 0; + + /* Make sure partial summoning counter is initialized. */ + p_ptr->maintain_sum = 0; + + /* Cancel the target */ + target_who = 0; + + /* Cancel the health bar */ + health_track(0); + + + /* Check visual effects */ + shimmer_monsters = TRUE; + shimmer_objects = TRUE; + repair_monsters = TRUE; + repair_objects = TRUE; + + + /* Disturb */ + disturb(1); + + /* Track maximum player level */ + if (p_ptr->max_plv < p_ptr->lev) + { + p_ptr->max_plv = p_ptr->lev; + } + + /* Track maximum dungeon level (if not in quest -KMW-) */ + if ((max_dlv[dungeon_type] < dun_level) && !p_ptr->inside_quest) + { + max_dlv[dungeon_type] = dun_level; + } + + /* No stairs down from Quest */ + if (is_quest(dun_level) && !p_ptr->astral) + { + create_down_stair = FALSE; + create_down_shaft = FALSE; + } + + /* Paranoia -- no stairs from town or wilderness */ + if (!dun_level) create_down_stair = create_up_stair = FALSE; + if (!dun_level) create_down_shaft = create_up_shaft = FALSE; + + /* Option -- no connected stairs */ + if (!dungeon_stair) create_down_stair = create_up_stair = FALSE; + if (!dungeon_stair) create_down_shaft = create_up_shaft = FALSE; + + /* no connecting stairs on special levels */ + if (!(dungeon_flags2 & DF2_NO_STAIR)) create_down_stair = create_up_stair = FALSE; + if (!(dungeon_flags2 & DF2_NO_STAIR)) create_down_shaft = create_up_shaft = FALSE; + + /* Make a stairway. */ + if ((create_up_stair || create_down_stair || + create_up_shaft || create_down_shaft) && + !get_fbranch()) + { + /* Place a stairway */ + if (cave_valid_bold(p_ptr->py, p_ptr->px)) + { + /* XXX XXX XXX */ + delete_object(p_ptr->py, p_ptr->px); + + /* Make stairs */ + if (create_down_stair) + { + cave_set_feat(p_ptr->py, p_ptr->px, (dungeon_flags1 & DF1_FLAT) ? FEAT_WAY_MORE : FEAT_MORE); + } + else if (create_down_shaft) + { + cave_set_feat(p_ptr->py, p_ptr->px, (dungeon_flags1 & DF1_FLAT) ? FEAT_WAY_MORE : FEAT_SHAFT_DOWN); + } + else if (create_up_shaft) + { + cave_set_feat(p_ptr->py, p_ptr->px, (dungeon_flags1 & DF1_FLAT) ? FEAT_WAY_LESS : FEAT_SHAFT_UP); + } + else + { + cave_set_feat(p_ptr->py, p_ptr->px, (dungeon_flags1 & DF1_FLAT) ? FEAT_WAY_LESS : FEAT_LESS); + } + } + + /* Cancel the stair request */ + create_down_stair = create_up_stair = FALSE; + create_down_shaft = create_up_shaft = FALSE; + } + + /* Hack - Assume invalid panel */ + panel_row_min = cur_hgt; + panel_row_max = 0; + panel_col_min = cur_wid; + panel_col_max = 0; + + /* Center the panel */ + verify_panel(); + + /* Flush messages */ + msg_print(NULL); + + + /* Enter "xtra" mode */ + character_xtra = TRUE; + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + + /* Window stuff */ + p_ptr->window |= (PW_MONSTER); + + /* Redraw dungeon */ + p_ptr->redraw |= (PR_WIPE | PR_BASIC | PR_EXTRA); + + /* Redraw map */ + p_ptr->redraw |= (PR_MAP); + + /* Window stuff */ + p_ptr->window |= (PW_OVERHEAD); + + /* Update stuff */ + p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS | PU_POWERS | PU_SANITY | PU_BODY); + + /* Calculate torch radius */ + p_ptr->update |= (PU_TORCH); + + /* Update stuff */ + update_stuff(); + + /* Redraw stuff */ + redraw_stuff(); + + /* Redraw stuff */ + window_stuff(); + + /* Update stuff */ + p_ptr->update |= (PU_VIEW | PU_FLOW | PU_DISTANCE | PU_MON_LITE); + + /* Update stuff */ + update_stuff(); + + /* Redraw stuff */ + redraw_stuff(); + + /* Leave "xtra" mode */ + character_xtra = FALSE; + + /* Update stuff */ + p_ptr->update |= (PU_BONUS | PU_HP | PU_MANA | PU_SPELLS | PU_POWERS | PU_BODY); + + /* Combine / Reorder the pack */ + p_ptr->notice |= (PN_COMBINE | PN_REORDER); + + /* Notice stuff */ + notice_stuff(); + + /* Update stuff */ + update_stuff(); + + /* Redraw stuff */ + redraw_stuff(); + + /* Window stuff */ + window_stuff(); + + /* Refresh */ + Term_fresh(); + + + /* Announce (or repeat) the feeling */ + if (dun_level) do_cmd_feeling(); + + + /* Hack -- notice death or departure */ + if (!alive || death) return; + + /*** Process this dungeon level ***/ + + /* Reset the monster generation level */ + monster_level = dun_level; + + /* Reset the object generation level */ + object_level = dun_level; + + hack_mind = TRUE; + + /* Mega Hack, if needed wipe all stairs */ + if (dungeon_type == DUNGEON_DEATH) + { + int i, j; + + for (i = 0; i < cur_wid; i++) + { + for (j = 0; j < cur_hgt; j++) + { + cave_type *c_ptr = &cave[j][i]; + + switch (c_ptr->feat) + { + case FEAT_MORE: + case FEAT_LESS: + case FEAT_SHAFT_UP: + case FEAT_SHAFT_DOWN: + { + cave_set_feat(j, i, FEAT_FLOOR); + break; + } + } + } + } + + /* Reset the monster generation level */ + monster_level = 127; + + /* Reset the object generation level */ + object_level = 0; + } + + /* Main loop */ + while (TRUE) + { + /* Hack -- Compact the monster list occasionally */ + if (m_cnt + 32 > max_m_idx) compact_monsters(64); + + /* Hack -- Compress the monster list occasionally */ + if (m_cnt + 32 < m_max) compact_monsters(0); + + + /* Hack -- Compact the object list occasionally */ + if (o_cnt + 32 > max_o_idx) compact_objects(64); + + /* Hack -- Compress the object list occasionally */ + if (o_cnt + 32 < o_max) compact_objects(0); + + + + /* Process the player */ + process_player(); + + /* Notice stuff */ + if (p_ptr->notice) notice_stuff(); + + /* Update stuff */ + if (p_ptr->update) update_stuff(); + + /* Redraw stuff */ + if (p_ptr->redraw) redraw_stuff(); + + /* Redraw stuff */ + if (p_ptr->window) window_stuff(); + + /* Hack -- Hilite the player */ + move_cursor_relative(p_ptr->py, p_ptr->px); + + /* Optional fresh */ + if (fresh_after) Term_fresh(); + + /* Hack -- Notice death or departure */ + if (!alive || death) break; + + + total_friends = 0; + total_friend_levels = 0; + + /* Process all of the monsters */ + process_monsters(); + + /* Notice stuff */ + if (p_ptr->notice) notice_stuff(); + + /* Update stuff */ + if (p_ptr->update) update_stuff(); + + /* Redraw stuff */ + if (p_ptr->redraw) redraw_stuff(); + + /* Redraw stuff */ + if (p_ptr->window) window_stuff(); + + /* Hack -- Hilite the player */ + move_cursor_relative(p_ptr->py, p_ptr->px); + + /* Optional fresh */ + if (fresh_after) Term_fresh(); + + /* Hack -- Notice death or departure */ + if (!alive || death) break; + + + /* Process the world */ + process_world(); + + /* Process the appropriate hooks */ + process_hooks(HOOK_END_TURN, "(d)", is_quest(dun_level)); + + /* Make it pulsate and live !!!! */ + if ((dungeon_flags1 & DF1_EVOLVE) && dun_level) + { + if (!(turn % 10)) evolve_level(TRUE); + } + + /* Notice stuff */ + if (p_ptr->notice) notice_stuff(); + + /* Update stuff */ + if (p_ptr->update) update_stuff(); + + /* Redraw stuff */ + if (p_ptr->redraw) redraw_stuff(); + + /* Window stuff */ + if (p_ptr->window) window_stuff(); + + /* Hack -- Hilite the player */ + move_cursor_relative(p_ptr->py, p_ptr->px); + + /* Optional fresh */ + if (fresh_after) Term_fresh(); + + /* Hack -- Notice death or departure */ + if (!alive || death) break; + + /* Handle "leaving" */ + if (p_ptr->leaving) break; + + /* Count game turns */ + turn++; + } + + /* Did we leave a dungeon ? */ + if ((dun_level < d_info[dungeon_type].mindepth) && !is_recall) + { + dun_level = 0; + + if (d_info[dungeon_type].ix > -1) + { + p_ptr->wilderness_x = d_info[dungeon_type].ix; + p_ptr->wilderness_y = d_info[dungeon_type].iy; + } + + dungeon_type = DUNGEON_WILDERNESS; + } + + if (dun_level > d_info[dungeon_type].maxdepth) + { + dun_level = 0; + + if (d_info[dungeon_type].ox > -1) + { + p_ptr->wilderness_x = d_info[dungeon_type].ox; + p_ptr->wilderness_y = d_info[dungeon_type].oy; + } + + dungeon_type = DUNGEON_WILDERNESS; + } + + is_recall = FALSE; +} + + + + +/* + * Load some "user pref files" + */ +static void load_all_pref_files(void) +{ + char buf[1024]; + + + /* Access the "race" pref file */ + sprintf(buf, "%s.prf", rp_ptr->title + rp_name); + + /* Process that file */ + process_pref_file(buf); + + /* Access the "class" pref file */ + sprintf(buf, "%s.prf", spp_ptr->title + c_name); + + /* Process that file */ + process_pref_file(buf); + + /* Access the "character" pref file */ + sprintf(buf, "%s.prf", player_name); + + /* Process that file */ + process_pref_file(buf); + + /* Process player specific automatizer sets */ + /* TODO: Disabled temporarily because it causes duplicate + * rules on save and subsequent game load. */ + /* sprintf(buf2, "%s.atm", player_name); */ + /* path_build(buf, sizeof(buf), ANGBAND_DIR_USER, buf2); */ + /* automatizer_load(buf); */ +} + +/* + * Actually play a game + * + * If the "new_game" parameter is true, then, after loading the + * savefile, we will commit suicide, if necessary, to allow the + * player to start a new game. + */ +void play_game(bool_ new_game) +{ + int i, tmp_dun; + + bool_ cheat_death = FALSE; + + /* Hack -- Character is "icky" */ + character_icky = TRUE; + + + /* Make sure main term is active */ + Term_activate(angband_term[0]); + + /* Initialise the resize hook XXX XXX XXX */ + angband_term[0]->resize_hook = resize_map; + + /* XXX XXX XXX hardcoded number of terms */ + for (i = 1; i < 8; i++) + { + if (angband_term[i]) + { + /* Add redraw hook */ + angband_term[i]->resize_hook = resize_window; + } + } + + + /* Hack -- turn off the cursor */ + (void)Term_set_cursor(0); + + /* Character list */ + if (!new_game && !no_begin_screen) new_game = begin_screen(); + no_begin_screen = FALSE; + + /* Attempt to load */ + if (!load_player()) + { + /* Oops */ + quit("broken savefile"); + } + + /* Nothing loaded */ + if (!character_loaded) + { + /* Make new player */ + new_game = TRUE; + + /* The dungeon is not ready */ + character_dungeon = FALSE; + } + else + { + int i; + + /* Init new skills to their defaults */ + for (i = old_max_s_idx; i < max_s_idx; i++) + { + s32b value = 0, mod = 0; + + compute_skills(&value, &mod, i); + + init_skill(value, mod, i); + } + } + + /* Process old character */ + if (!new_game) + { + /* Process the player name */ + process_player_name(FALSE); + } + + /* Init the RNG */ + if (Rand_quick) + { + u32b seed; + + /* Basic seed */ + seed = (time(NULL)); + +#ifdef SET_UID + + /* Mutate the seed on Unix machines */ + seed = ((seed >> 3) * (getpid() << 1)); + +#endif + + /* Use the complex RNG */ + Rand_quick = FALSE; + + /* Seed the "complex" RNG */ + Rand_state_init(seed); + } + + /* Extract the options */ + for (i = 0; option_info[i].o_desc; i++) + { + int os = option_info[i].o_page; + int ob = option_info[i].o_bit; + + /* Set the "default" options */ + if (option_info[i].o_var) + { + /* Set */ + if (option_flag[os] & (1L << ob)) + { + /* Set */ + (*option_info[i].o_var) = TRUE; + } + + /* Clear */ + else + { + /* Clear */ + (*option_info[i].o_var) = FALSE; + } + } + } + + /* Roll new character */ + if (new_game) + { + /* Show intro */ + modules[game_module_idx].intro(); + + /* The dungeon is not ready */ + character_dungeon = FALSE; + + /* Hack -- seed for flavors */ + seed_flavor = rand_int(0x10000000); + + /* Roll up a new character */ + player_birth(); + + /* Start in town, or not */ + if (p_ptr->astral) dun_level = 98; + else dun_level = 0; + p_ptr->inside_quest = 0; + p_ptr->inside_arena = 0; + + /* Hack -- enter the world */ + /* Mega-hack Vampires and Spectres start in the dungeon */ + if (PRACE_FLAG(PR1_UNDEAD)) + { + turn = (10L * DAY / 2) + (START_DAY * 10) + 1; + } + else + { + turn = (START_DAY * 10) + 1; + } + } + + /* Flash a message */ + prt("Please wait...", 0, 0); + + /* Flush the message */ + Term_fresh(); + + /* Be sure to not bother the player */ + calc_powers_silent = TRUE; + + /* Hack -- Enter wizard mode */ + if (arg_wizard && enter_wizard_mode()) wizard = TRUE; + + /* Flavor the objects */ + flavor_init(); + + /* Reset the visual mappings */ + reset_visuals(); + + /* Window stuff */ + p_ptr->window |= (PW_INVEN | PW_EQUIP | PW_PLAYER); + + /* Window stuff */ + p_ptr->window |= (PW_MONSTER); + + /* Window stuff */ + window_stuff(); + + /* load user file */ + process_pref_file("user.prf"); + + /* Load the "pref" files */ + load_all_pref_files(); + + /* Set or clear "rogue_like_commands" if requested */ + if (arg_force_original) rogue_like_commands = FALSE; + if (arg_force_roguelike) rogue_like_commands = TRUE; + + /* Initialize vault info */ + if (init_v_info()) quit("Cannot initialize vaults"); + + /* Initialize hooks */ + init_hooks(); + init_hooks_help(); + init_hooks_module(); + + /* React to changes */ + Term_xtra(TERM_XTRA_REACT, 0); + + /* Mega hack, prevent lots of bugs */ + if ((p_ptr->px == 0) || (p_ptr->py == 0)) + { + p_ptr->px = 1; + p_ptr->py = 1; + }; + + /* Hack - if note file exists, load it */ + if (!new_game) + { + add_note_type(NOTE_ENTER_DUNGEON); + } + + /* Generate a dungeon level if needed */ + if (!character_dungeon) generate_cave(); + + /* Ok tell the scripts that the game is about to start */ + process_hooks(HOOK_GAME_START, "()"); + process_hooks_new(HOOK_GAME_START, NULL, NULL); + + /* Character is now "complete" */ + character_generated = TRUE; + + + /* Hack -- Character is no longer "icky" */ + character_icky = FALSE; + + + /* Start game */ + alive = TRUE; + + /* Hack -- Enforce "delayed death" */ + if (p_ptr->chp < 0) death = TRUE; + + /* Process */ + while (TRUE) + { + /* Save the level */ + old_dun_level = dun_level; + p_ptr->old_wild_mode = p_ptr->wild_mode; + + /* We reached surface ? good, lets go down again !! */ + if (p_ptr->astral && !dun_level) + { + p_ptr->astral = FALSE; + cmsg_print(TERM_L_GREEN, + "Well done ! You reached the town ! " + "You can now go down again."); + } + + /* Update monster list window */ + p_ptr->window |= (PW_M_LIST); + + /* Process the level */ + dungeon(); + + /* Save the current level if in a persistent level */ + tmp_dun = dun_level; + dun_level = old_dun_level; + save_dungeon(); + dun_level = tmp_dun; + + /* A death fate affects level generation */ + for (i = 0; i < MAX_FATES; i++) + { + /* Ignore empty slots */ + if (!fates[i].fate) continue; + + /* Ignore non-applicable fates */ + if (fates[i].level != dun_level) continue; + + /* Non-serious fate fails to fire 50% of time */ + if (!fates[i].serious && (rand_int(2) == 0)) continue; + + /* Analyse fate */ + switch (fates[i].fate) + { + /* You are doomed */ + case FATE_DIE: + { + cmsg_print(TERM_L_DARK, "You were fated to die here. DIE!"); + + /* You shall perish there */ + dungeon_type = DUNGEON_DEATH; + dun_level = d_info[dungeon_type].mindepth; /* was 1 */ + + fates[i].fate = FATE_NONE; + break; + } + } + } + + /* Notice stuff */ + if (p_ptr->notice) notice_stuff(); + + /* Update stuff */ + if (p_ptr->update) update_stuff(); + + /* Redraw stuff */ + if (p_ptr->redraw) redraw_stuff(); + + /* Window stuff */ + if (p_ptr->window) window_stuff(); + + /* Cancel the target */ + target_who = 0; + + /* Cancel the health bar */ + health_track(0); + + + /* Forget the lite */ + forget_mon_lite(); + + /* Forget the view */ + forget_view(); + + /* Handle "quit and save" */ + if (!alive && !death) break; + + + /* Erase the old cave */ + wipe_o_list(); + + + /* XXX XXX XXX */ + msg_print(NULL); + + /* Accidental Death */ + if (alive && death) + { + cheat_death = FALSE; + + /* Can we die ? please let us die ! */ + if (process_hooks(HOOK_DIE, "()")) + { + cheat_death = TRUE; + } + + /* Deus ex machina */ + else if (granted_resurrection()) + { + cheat_death = TRUE; + p_ptr->grace = -200000; + cmsg_format(TERM_L_GREEN, + "The power of %s raises you back from the grave!", + deity_info[p_ptr->pgod].name); + msg_print(NULL); + } + + /* Blood of life */ + else if (p_ptr->allow_one_death > 0) + { + cheat_death = TRUE; + + /* Lose one extra life */ + p_ptr->allow_one_death--; + + cmsg_print(TERM_L_GREEN, + "You have been saved by the Blood of Life!"); + msg_print(NULL); + } + + /* Cheat death option */ + else if ((wizard || cheat_live) && !get_check("Die? ")) + { + cheat_death = TRUE; + + /* Mark social class, reset age, if needed */ + if (p_ptr->sc) p_ptr->sc = p_ptr->age = 0; + + /* Increase age */ + p_ptr->age++; + + /* Mark savefile */ + noscore |= 0x0001; + msg_print("You invoke wizard mode and cheat death."); + msg_print(NULL); + } + + if (cheat_death) + { + /* Restore the winner status */ + total_winner = has_won; + + /* One more life spent */ + p_ptr->lives++; + + /* Restore hit points */ + p_ptr->chp = p_ptr->mhp; + p_ptr->chp_frac = 0; + + /* Heal sanity */ + p_ptr->csane = p_ptr->msane; + p_ptr->csane_frac = 0; + + /* Restore spell points */ + p_ptr->csp = p_ptr->msp; + p_ptr->csp_frac = 0; + + /* Hack -- Healing */ + (void)set_blind(0); + (void)set_confused(0); + (void)set_poisoned(0); + (void)set_afraid(0); + (void)set_paralyzed(0); + (void)set_image(0); + (void)set_stun(0); + (void)set_cut(0); + + /* accounting for a new ailment. -LM- */ + p_ptr->black_breath = FALSE; + + /* Hack -- don't go to undead form */ + p_ptr->necro_extra &= ~CLASS_UNDEAD; + + /* Hack -- Prevent starvation */ + (void)set_food(PY_FOOD_MAX - 1); + + /* Hack -- cancel recall */ + if (p_ptr->word_recall) + { + /* Message */ + msg_print("A tension leaves the air around you..."); + msg_print(NULL); + + /* Hack -- Prevent recall */ + p_ptr->word_recall = 0; + } + + /* Note cause of death XXX XXX XXX */ + (void)strcpy(died_from, "Cheating death"); + + /* Do not die */ + death = FALSE; + + /* New depth -KMW- */ + /* dun_level = 0; */ + p_ptr->inside_arena = 0; + leaving_quest = 0; + p_ptr->inside_quest = 0; + + /* Leaving */ + p_ptr->leaving = TRUE; + } + } + + /* Handle "death" */ + if (death) + { + break; + } + + /* Mega hack */ + if (dun_level) p_ptr->wild_mode = FALSE; + + /* Make a new level */ + process_hooks(HOOK_NEW_LEVEL, "(d)", is_quest(dun_level)); + generate_cave(); + } + + /* Close stuff */ + close_game(); + + /* Quit */ + quit(NULL); +} + diff --git a/src/externs.h b/src/externs.h index 20f094dd..29a64267 100644 --- a/src/externs.h +++ b/src/externs.h @@ -316,7 +316,7 @@ extern term *angband_term[ANGBAND_TERM_MAX]; extern char angband_term_name[ANGBAND_TERM_MAX][80]; extern byte angband_color_table[256][4]; extern char angband_sound_name[SOUND_MAX][16]; -extern cave_type *cave[MAX_HGT]; +extern cave_type **cave; extern object_type *o_list; extern monster_type *m_list; extern monster_type *km_list; @@ -1902,8 +1902,6 @@ s16b get_random_spell(s16b random_type, int lev); /* spells6.c */ -SGLIB_DEFINE_LIST_PROTOTYPES(school_provider, compare_school_provider, next); - void schools_init(); school_type *school_at(int index); @@ -1945,7 +1943,6 @@ extern s32b rescale(s32b x, s32b max, s32b new_max); extern bool_ input_box(cptr text, int y, int x, char *buf, int max); extern void draw_box(int y, int x, int h, int w); extern void display_list(int y, int x, int h, int w, cptr title, cptr *list, int max, int begin, int sel, byte sel_color); -extern int ask_menu(cptr ask, char **items, int max); extern cptr get_player_race_name(int pr, int ps); extern cptr get_month_name(int month, bool_ full, bool_ compact); extern cptr get_day(int day); @@ -2324,7 +2321,7 @@ extern s16b get_skill_scale(int skill, u32b scale); extern void do_cmd_skill(void); extern void do_cmd_activate_skill(void); extern s16b melee_skills[MAX_MELEE]; -extern char *melee_names[MAX_MELEE]; +extern const char *melee_names[MAX_MELEE]; extern s16b get_melee_skills(void); extern s16b get_melee_skill(void); extern bool_ forbid_gloves(void); diff --git a/src/files.c b/src/files.c deleted file mode 100644 index a599af23..00000000 --- a/src/files.c +++ /dev/null @@ -1,5842 +0,0 @@ -/* File: files.c */ - -/* Purpose: code dealing with files (and death) */ - -/* - * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke - * - * This software may be copied and distributed for educational, research, and - * not for profit purposes provided that this copyright and statement are - * included in all such copies. - */ - -#include "angband.h" - -#include "hiscore.h" -#include "hooks.h" - - -/* - * Extract the first few "tokens" from a buffer - * - * This function uses "colon" and "slash" and delim arg as the delimeter characters. - * - * We never extract more than "num" tokens. The "last" token may include - * "delimeter" characters, allowing the buffer to include a "string" token. - * - * We save pointers to the tokens in "tokens", and return the number found. - * - * Hack -- Attempt to handle the 'c' character formalism - * - * Hack -- An empty buffer, or a final delimeter, yields an "empty" token. - * - * Hack -- We will always extract at least one token - */ -s16b tokenize(char *buf, s16b num, char **tokens, char delim1, char delim2) -{ - int i = 0; - - char *s = buf; - - - /* Process */ - while (i < num - 1) - { - char *t; - - /* Scan the string */ - for (t = s; *t; t++) - { - /* Found a delimiter */ - if ((*t == delim1) || (*t == delim2)) break; - - /* Handle single quotes */ - if (*t == '\'') - { - /* Advance */ - t++; - - /* Handle backslash */ - if (*t == '\\') t++; - - /* Require a character */ - if (!*t) break; - - /* Advance */ - t++; - - /* Hack -- Require a close quote */ - if (*t != '\'') *t = '\''; - } - - /* Handle back-slash */ - if (*t == '\\') t++; - } - - /* Nothing left */ - if (!*t) break; - - /* Nuke and advance */ - *t++ = '\0'; - - /* Save the token */ - tokens[i++] = s; - - /* Advance */ - s = t; - } - - /* Save the token */ - tokens[i++] = s; - - /* Number found */ - return (i); -} - - - -/* - * Parse a sub-file of the "extra info" (format shown below) - * - * Each "action" line has an "action symbol" in the first column, - * followed by a colon, followed by some command specific info, - * usually in the form of "tokens" separated by colons or slashes. - * - * Blank lines, lines starting with white space, and lines starting - * with pound signs ("#") are ignored (as comments). - * - * Note the use of "tokenize()" to allow the use of both colons and - * slashes as delimeters, while still allowing final tokens which - * may contain any characters including "delimiters". - * - * Note the use of "strtol()" to allow all "integers" to be encoded - * in decimal, hexidecimal, or octal form. - * - * Note that "monster zero" is used for the "player" attr/char, "object - * zero" will be used for the "stack" attr/char, and "feature zero" is - * used for the "nothing" attr/char. - * - * Parse another file recursively, see below for details - * %: - * - * Specify the attr/char values for "monsters" by race index - * R::: - * - * Specify the attr/char values for "objects" by kind index - * K::: - * - * Specify the attr/char values for "features" by feature index - * F::: - * - * Specify the attr/char values for "stores" by store index - * B::: - * - * Specify the attr/char values for unaware "objects" by kind tval - * U::: - * - * Specify the attr/char values for inventory "objects" by kind tval - * E::: - * - * Define a macro action, given an encoded macro action - * A: - * - * Create a normal macro, given an encoded macro trigger - * P: - * - * Create a command macro, given an encoded macro trigger - * C: - * - * Create a keyset mapping - * S::: - * - * Turn an option off, given its name - * X: - * - * Turn an option on, given its name - * Y: - * - * Specify visual information, given an index, and some data - * V::::: - * - * Specify squelch settings - * Q:: - */ -errr process_pref_file_aux(char *buf) -{ - int i, j, n1, n2; - - char *zz[16]; - - - /* Skip "empty" lines */ - if (!buf[0]) return (0); - - /* Skip "blank" lines */ - if (isspace(buf[0])) return (0); - - /* Skip comments */ - if (buf[0] == '#') return (0); - - /* Require "?:*" format */ - if (buf[1] != ':') return (1); - - - /* Process "%:" */ - if (buf[0] == '%') - { - /* Attempt to Process the given file */ - return (process_pref_file(buf + 2)); - } - - - /* Process "R::/" -- attr/char for monster races */ - if (buf[0] == 'R') - { - if (tokenize(buf + 2, 3, zz, ':', '/') == 3) - { - monster_race *r_ptr; - i = (huge)strtol(zz[0], NULL, 0); - n1 = strtol(zz[1], NULL, 0); - n2 = strtol(zz[2], NULL, 0); - if (i >= max_r_idx) return (1); - r_ptr = &r_info[i]; - if (n1) r_ptr->x_attr = n1; - if (n2) - { - r_ptr->x_char = n2; - } - return (0); - } - } - - - /* Process "G:::/" -- attr/char for overlay graphics */ - if (buf[0] == 'G') - { - /* Process "G:M::/" -- attr/char for ego monsters */ - if (buf[2] == 'M') - { - if (tokenize(buf + 4, 3, zz, ':', '/') == 3) - { - monster_ego *re_ptr; - i = (huge)strtol(zz[0], NULL, 0); - n1 = strtol(zz[1], NULL, 0); - n2 = strtol(zz[2], NULL, 0); - if (i >= max_re_idx) return (1); - re_ptr = &re_info[i]; - if (n1) re_ptr->g_attr = n1; - if (n2) - { - re_ptr->g_char = n2; - } - return (0); - } - } - - /* Process "G:P::/" -- attr/char for race modifiers */ - if (buf[2] == 'P') - { - if (tokenize(buf + 4, 3, zz, ':', '/') == 3) - { - player_race_mod *rmp_ptr; - i = (huge)strtol(zz[0], NULL, 0); - n1 = strtol(zz[1], NULL, 0); - n2 = strtol(zz[2], NULL, 0); - if (i >= max_rmp_idx) return (1); - rmp_ptr = &race_mod_info[i]; - if (n1) rmp_ptr->g_attr = n1; - if (n2) - { - rmp_ptr->g_char = n2; - } - return (0); - } - } - - /* Process "G:T::/" -- attr/char for traps */ - if (buf[2] == 'T') - { - if (tokenize(buf + 4, 3, zz, ':', '/') == 3) - { - trap_type *t_ptr; - i = (huge)strtol(zz[0], NULL, 0); - n1 = strtol(zz[1], NULL, 0); - n2 = strtol(zz[2], NULL, 0); - if (i >= max_t_idx) return (1); - t_ptr = &t_info[i]; - if (n1) t_ptr->g_attr = n1; - if (n2) - { - t_ptr->g_char = n2; - } - return (0); - } - } - } - - - /* Process "K::/" -- attr/char for object kinds */ - else if (buf[0] == 'K') - { - if (tokenize(buf + 2, 3, zz, ':', '/') == 3) - { - object_kind *k_ptr; - i = (huge)strtol(zz[0], NULL, 0); - n1 = strtol(zz[1], NULL, 0); - n2 = strtol(zz[2], NULL, 0); - if (i >= max_k_idx) return (1); - k_ptr = &k_info[i]; - if (n1) k_ptr->x_attr = n1; - if (n2) - { - k_ptr->x_char = n2; - } - return (0); - } - } - - - /* Process "F::/" -- attr/char for terrain features */ - else if (buf[0] == 'F') - { - if (tokenize(buf + 2, 3, zz, ':', '/') == 3) - { - feature_type *f_ptr; - i = (huge)strtol(zz[0], NULL, 0); - n1 = strtol(zz[1], NULL, 0); - n2 = strtol(zz[2], NULL, 0); - if (i >= max_f_idx) return (1); - f_ptr = &f_info[i]; - if (n1) f_ptr->x_attr = n1; - if (n2) - { - f_ptr->x_char = n2; - } - return (0); - } - } - - /* Process "B::/" -- attr/char for stores */ - else if (buf[0] == 'B') - { - if (tokenize(buf + 2, 3, zz, ':', '/') == 3) - { - store_info_type *st_ptr; - i = (huge)strtol(zz[0], NULL, 0); - n1 = strtol(zz[1], NULL, 0); - n2 = strtol(zz[2], NULL, 0); - if (i >= max_st_idx) return (1); - st_ptr = &st_info[i]; - if (n1) st_ptr->x_attr = n1; - if (n2) st_ptr->x_char = n2; - return (0); - } - } - - /* Process "S::/" -- attr/char for special things */ - else if (buf[0] == 'S') - { - if (tokenize(buf + 2, 3, zz, ':', '/') == 3) - { - j = (byte)strtol(zz[0], NULL, 0); - n1 = strtol(zz[1], NULL, 0); - n2 = strtol(zz[2], NULL, 0); - misc_to_attr[j] = n1; - misc_to_char[j] = n2; - return (0); - } - } - - /* Process "U::/" -- attr/char for unaware items */ - else if (buf[0] == 'U') - { - if (tokenize(buf + 2, 3, zz, ':', '/') == 3) - { - j = (huge)strtol(zz[0], NULL, 0); - n1 = strtol(zz[1], NULL, 0); - n2 = strtol(zz[2], NULL, 0); - for (i = 1; i < max_k_idx; i++) - { - object_kind *k_ptr = &k_info[i]; - if (k_ptr->tval == j) - { - if (n1) k_ptr->d_attr = n1; - if (n2) k_ptr->d_char = n2; - } - } - return (0); - } - } - - - /* Process "E::" -- attribute for inventory objects */ - else if (buf[0] == 'E') - { - if (tokenize(buf + 2, 2, zz, ':', '/') == 2) - { - j = (byte)strtol(zz[0], NULL, 0) % 128; - n1 = strtol(zz[1], NULL, 0); - if (n1) tval_to_attr[j] = n1; - return (0); - } - } - - - /* Process "A:" -- save an "action" for later */ - else if (buf[0] == 'A') - { - text_to_ascii(macro__buf, buf + 2); - return (0); - } - - /* Process "P:" -- normal macro */ - else if (buf[0] == 'P') - { - char tmp[1024]; - text_to_ascii(tmp, buf + 2); - macro_add(tmp, macro__buf); - return (0); - } - - /* Process "L::: -- extended command macro */ - else if (buf[0] == 'L') - { - switch (tokenize(buf + 2, 3, zz, ':', 0)) - { - case 3: - cli_add(zz[0], zz[1], zz[2]); - return 0; - case 2: - cli_add(zz[0], zz[1], 0); - return 0; - default: - return 1; - } - } - - /* Process "C:" -- create keymap */ - else if (buf[0] == 'C') - { - int mode; - - char tmp[1024]; - - if (tokenize(buf + 2, 2, zz, ':', '/') != 2) return (1); - - mode = strtol(zz[0], NULL, 0); - if ((mode < 0) || (mode >= KEYMAP_MODES)) return (1); - - text_to_ascii(tmp, zz[1]); - if (!tmp[0] || tmp[1]) return (1); - i = (byte)(tmp[0]); - - string_free(keymap_act[mode][i]); - - keymap_act[mode][i] = string_make(macro__buf); - - return (0); - } - - - /* Process "V:::::" -- visual info */ - else if (buf[0] == 'V') - { - if (tokenize(buf + 2, 5, zz, ':', '/') == 5) - { - i = (byte)strtol(zz[0], NULL, 0); - angband_color_table[i][0] = (byte)strtol(zz[1], NULL, 0); - angband_color_table[i][1] = (byte)strtol(zz[2], NULL, 0); - angband_color_table[i][2] = (byte)strtol(zz[3], NULL, 0); - angband_color_table[i][3] = (byte)strtol(zz[4], NULL, 0); - return (0); - } - } - /* set macro trigger names and a template */ - /* Process "T:::" */ - /* Process "T: